"""The high-score notation module. This module contains functions related to writing out the C{scores.txt} file. """ from . import Monster, g import operator, time def install_handlers(): """Activate the signal and atexit handlers. Adds L{atexit_handler} as an atexit handler and, if possible, adds signal handlers for SIGTERM and SIGHUP. """ import atexit atexit.register(atexit_handler) try: import signal except ImportError: return def signal_handler(signum, frame): g.signum = signum raise SystemExit for s in (signal.SIGTERM, signal.SIGHUP): signal.signal(s, signal_handler) def atexit_handler(): """A handler to write out data if the program exited abnormally. This function can be added as an atexit handler to ensure that scores are always written out. """ if not g.handled_death and not g.loaded: g.player.dead = True try: import signal except ImportError: g.player.last_damage = 'mysterious means' else: if g.signum == signal.SIGTERM: g.player.last_damage = 'SIGTERM' elif g.signum == signal.SIGHUP: g.player.last_damage = 'Shub-Internet' else: g.player.last_damage = 'mysterious means' writeout(True) def writeout(sig=False): """Write out the player's score, stats, and conduct to C{scores.txt}. @param sig: If True, print "caught signal" instead of what is being written out to the scores file. @type sig: L{bool} """ score = (g.player.level + 1) * (g.player.vanquished + 1) + g.player.xp score -= 50 * g.peacefuls + 100 * g.murders + 350 * g.cannibal score += g.bonus if g.do_win: if g.vegetarian == 0: score += 500 if g.vegan == 0: score += 1500 if g.food == 0: score += 3000 if g.pets_lost == 0: score += 800 if g.used_wand == 0: score += 1200 if g.used_weapon == 0: score += 5000 if g.illiterate == 0: score += 400 if g.teleported == 0: score += 300 if g.polymorphed == 0: score += 800 if g.controlled_polymorph == 0: score += 2400 out = """%8d %3d %3d %3d %3d\t%s the level %d %s \t %s%s %s %s %s%s \t %s \tHP: %d/%d, STR: %d/%d, INT: %d/%d, DEX: %d/%d, AR: %d, RG: 1/%d %s""" % ( score, g.player.vanquished, g.peacefuls, g.murders, g.cannibal, g.player.name, g.player.level, g.player.species.name, 'killed by ' if g.player.dead else '', g.player.last_damage, 'in' if g.player.dead else 'from', 'the' if g.player.here.unique else 'a', g.player.here.name, (',\n\t while helplessly %s,' % g.player.stunner) if g.player.stunned > 0 else ',', time.strftime('on %F, at %R %Z.'), g.player.hp, g.player.mhp, g.player.str, g.player.mst, g.player.int, g.player.min, g.player.dex, g.player.mdx, g.player.armor, g.player.species.regeneration, conduct() ) st = open('scores.txt', 'a') st.write(out + '\n\n\n') st.close() if sig: if g.signum is not None: print 'caught signal' return print '\n%s' % out g.handled_death = True def conduct(): """Generate a string representing the player's conducts. @returns: L{str} """ bonuses = [] if g.food == 0: bonuses.append('\t- You went without food.') elif g.vegan == 0: bonuses.append('\t- You followed a vegan diet.') elif g.vegetarian == 0: bonuses.append('\t- You followed a vegetarian diet.') if g.pets_lost == 0: bonuses.append('\t- None of your pets died.') else: bonuses.append('\t- %d of your pets died.' % g.pets_lost) pets = [mon for mon in g.monsters if not mon.dead and mon.ai == Monster.PET and mon.owner is g.player] if pets: _pets = [] pets.sort(key=operator.attrgetter('vanquished', 'xp'), reverse=True) for p in pets: if p.vanquished == 0: continue if p.name: _pets.append('\t %s the %s, with %d kill%s.' % (p.name, p.species.name, p.vanquished, 's' if p.vanquished > 1 else '')) else: _pets.append('\t %s, with %d kill%s.' % (p.species.adesc, p.vanquished, 's' if p.vanquished > 1 else '')) if _pets: bonuses.append('\t- %d of your pets survived, notably:' % len(pets)) bonuses.extend(_pets) else: bonuses.append('\t- %d of your pets survived.' % len(pets)) if g.used_wand == 0: bonuses.append('\t- You never used an electric wand.') if g.used_weapon == 0: bonuses.append('\t- You never hit with a wielded weapon.') if g.illiterate == 0: bonuses.append('\t- You were illiterate.') if g.teleported == 0: bonuses.append('\t- You never teleported.') if g.polymorphed == 0: bonuses.append('\t- You never polymorphed.') elif g.controlled_polymorph == 0: bonuses.append('\t- You never used controlled polymorph.') if g.peacefuls == 0: bonuses.append('\t- You never attacked a peaceful creature.') else: bonuses.append('\t- On %d occasion%s, you attacked a peaceful creature.' % (g.peacefuls, 's' if g.peacefuls > 1 else '')) if g.murders == 0: bonuses.append('\t- You never murdered anyone in a way a jury would believe.') else: bonuses.append('\t- You murdered %d %s%s.' % (g.murders, 'people' if g.murders > 1 else 'person', ' as a human' if g.polymorphed else '')) if g.murders > g.allow_murder: bonuses.append('\t (Convicted of %d of them.)' % (g.murders - g.allow_murder)) if g.cannibal > 0: bonuses.append('\t- You feasted on a corpse of your own species %d time%s.' % (g.cannibal, 's' if g.cannibal > 1 else '')) for s in g.special_merits: bonuses.append('\t- %s' % s) return '\n'.join(bonuses)