"""Global application-state data. This module is usually shadowed by an instance of L{Global} called g that is imported at the package level. """ import random, itertools, collections, weakref class Global(object): """A class for encapsulating the entire application state. There is only ever one Global object in existance, usually called C{th.g}. """ _g = None def __new__(cls): if not cls._g: cls._g = object.__new__(cls) cls._g.init() return cls._g player = None turns = 0 phase = 0 glide = None glidetrigger = True lines = 0 unpk_only = True show_pk = True loaded = 0 grid = None nodes = None seen = None deadends = None monsters = None pets_lost = 0 used_weapon = 0 used_wand = 0 food = 0 vegan = 0 vegetarian = 0 cannibal = 0 illiterate = 0 teleported = 0 murders = 0 peacefuls = 0 killed_zeius = 0 polymorphed = 0 controlled_polymorph = 0 freed_oompas = 0 handled_death = False signum = None do_win = 0 bonus = 0 random_count = 0 def insertInPlace(self, mon): """Insert a monster into the correct order in L{monsters}. """ self.dex_dict.setdefault((mon.ap, mon.dex), []).append(mon) mon.apdx_cache = mon.ap, mon.dex @property def monsters(self): for mons in self.dex_dict.itervalues(): for mon in mons: yield mon def main_loop(self): delmon, self.updatemon = set(), set() if not self.loaded: keys = [self.rng.shuffle(value) or key for key, value in self.dex_dict.iteritems()] else: keys = self.dex_dict.keys() keys.sort(reverse=True) for ap in xrange(keys[0][0], 0, -1): for apdx in keys: for mon in self.dex_dict[apdx]: if mon.hp <= 0: mon.die() if mon.dead: if mon.corpse is None: delmon.add(mon) continue if mon.ap < ap: continue if self.loaded: if mon is not self.player: continue else: self.loaded = False if mon.xap > 0: mon.xap -= 1 continue if mon is self.player: yield ap else: mon.update() if mon.apdx_cache != (mon.ap, mon.dex): self.updatemon.add(mon) for mon in delmon: try: self.dex_dict[mon.apdx_cache].remove(mon) self.updatemon.remove(mon) except (ValueError, KeyError): continue for mon in self.updatemon: self.dex_dict[mon.apdx_cache].remove(mon) self.insertInPlace(mon) mon.apdx_cache = mon.ap, mon.dex for node in self.nodes: node.update() self.turns += 1 def deadend(self): return self.deadends.pop(self.rng.randrange(len(self.deadends))) def incscore(self, score, reason): self.bonus += score self.special_merits.append(reason) def _t(self, node): if isinstance(node, int): self.glide = self.nodes[node] else: self.glide = node self.glidetrigger = False def init(self): self.nodes, self.seen, self.deadends = [], [], [] self.beacons, self.special_merits = [], [] self.regions = [] self.dex_dict = {} self.rng = random.Random() _random = self.rng.random def randomfunc(): self.random_count += 1 return _random() self.rng.random = randomfunc #choices = [self.rng.random() for x in xrange(3)] #self.rng.random = lambda: random.choice(choices) g = Global()