def setUp(self): self.engine = Engine("sqlite:///:memory:") self.graphmakers = (self.engine.new_character, ) self.tempdir = tempfile.mkdtemp(dir='.') for f in ('trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json'): if os.path.exists(f): os.rename(f, os.path.join(self.tempdir, f))
def college24_premade(clean): if not os.path.exists("college24_premade.db"): print("generating test data for query") from LiSE.examples.college import install with Engine('college24_premade.db', random_seed=69105) as eng: install(eng) for i in range(24): print(i) eng.next_turn() eng = Engine("college24_premade.db") yield eng eng.close()
def setUp(self): """Start an engine, install the sim module, and run it a while. This gives us some world-state to test upon. """ from logging import getLogger, FileHandler self.engine = Engine(":memory:") logger = getLogger('LiSE.engine') logger.setLevel('DEBUG') logger.addHandler(FileHandler('test.log')) sim.install(self.engine) for i in range(72): self.engine.next_tick() self.engine.commit()
def setUp(self): self.engine = Engine("sqlite:///:memory:") self.graphmakers = (self.engine.new_character,) self.tempdir = tempfile.mkdtemp(dir='.') for f in ( 'trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json' ): if os.path.exists(f): os.rename(f, os.path.join(self.tempdir, f))
def character_updates(request): tempdir = tempfile.mkdtemp(dir='.') for f in ('trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json'): if os.path.exists(f): os.rename(f, os.path.join(tempdir, f)) name, data, stat, nodestat, statup, nodeup, edgeup = request.param engine = Engine("sqlite:///:memory:") char = engine.new_character(name, data, **stat) update_char(char, node=nodestat) yield char, statup, nodeup, edgeup engine.close() for f in ('trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json'): if os.path.exists(f): os.remove(f) if os.path.exists(os.path.join(tempdir, f)): os.rename(os.path.join(tempdir, f), f) os.rmdir(tempdir)
def test_char_creation(name, data, stat, nodestat, statup, nodeup, edgeup): with Engine(connect_string="sqlite:///:memory:") as eng: char = eng.new_character(name, data, **stat) assert set(char.node) == set(data) es = set() for k, v in data.items(): for vv in v: es.add((k, vv)) assert set(char.edges) == es assert char.stat == stat
class CharacterTest(allegedb.tests.test_all.AllegedTest): def setUp(self): self.engine = Engine("sqlite:///:memory:") self.graphmakers = (self.engine.new_character, ) self.tempdir = tempfile.mkdtemp(dir='.') for f in ('trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json'): if os.path.exists(f): os.rename(f, os.path.join(self.tempdir, f)) def tearDown(self): self.engine.close() for f in ('trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json'): if os.path.exists(f): os.remove(f) if os.path.exists(os.path.join(self.tempdir, f)): os.rename(os.path.join(self.tempdir, f), f) os.rmdir(self.tempdir)
def test_facade_creation(name, data, stat, nodestat, statup, nodeup, edgeup): with Engine(connect_string='sqlite:///:memory:') as eng: char = eng.new_character(name, data, **stat) fac = char.facade() assert dict(fac.node) == dict(char.node) assert fac.node == char.node assert fac.edges == char.edges assert set(fac.edges) == set(char.edges) assert fac.stat == char.stat assert dict(fac.stat) == dict(char.stat)
def college24_premade(): codefiles = ('trigger.py', 'prereq.py', 'action.py', 'method.py', 'function.py', 'strings.json') tempdir = tempfile.mkdtemp(dir='.') for codefile in codefiles: if os.path.exists(codefile): os.rename(codefile, os.path.join(tempdir, codefile)) if not os.path.exists("college24_premade.db"): print("generating test data for query") from LiSE.examples.college import install with Engine('college24_premade.db', random_seed=69105) as eng: install(eng) for i in range(24): print(i) eng.next_turn() eng = Engine("college24_premade.db") yield eng eng.close() for codefile in codefiles: if os.path.exists(os.path.join(tempdir, codefile)): os.rename(os.path.join(tempdir, codefile), codefile) os.rmdir(tempdir)
def character_updates(request): tempdir = tempfile.mkdtemp(dir='.') for f in ( 'trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json' ): if os.path.exists(f): os.rename(f, os.path.join(tempdir, f)) name, data, stat, nodestat, statup, nodeup, edgeup = request.param engine = Engine("sqlite:///:memory:") char = engine.new_character(name, data, **stat) update_char(char, node=nodestat) yield char, statup, nodeup, edgeup engine.close() for f in ( 'trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json' ): if os.path.exists(f): os.remove(f) if os.path.exists(os.path.join(tempdir, f)): os.rename(os.path.join(tempdir, f), f) os.rmdir(tempdir)
class CharacterTest(allegedb.tests.test_all.AllegedTest): def setUp(self): self.engine = Engine("sqlite:///:memory:") self.graphmakers = (self.engine.new_character,) self.tempdir = tempfile.mkdtemp(dir='.') for f in ( 'trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json' ): if os.path.exists(f): os.rename(f, os.path.join(self.tempdir, f)) def tearDown(self): self.engine.close() for f in ( 'trigger.py', 'prereq.py', 'action.py', 'function.py', 'method.py', 'strings.json' ): if os.path.exists(f): os.remove(f) if os.path.exists(os.path.join(self.tempdir, f)): os.rename(os.path.join(self.tempdir, f), f) os.rmdir(self.tempdir)
if student not in student_body.stat['characters']: student_body.stat['characters'].append(student) # Students' nodes are their brain cells. # They are useless if drunk or slow, but recover from both conditions a bit every hour. for k in range(0, 100): cell = student.new_node('cell{}'.format(k), drunk=0, slow=0) # ``new_node`` is just an alias for ``new_place``; # perhaps more logical when the places don't really # represent potential locations student.stat['xp'] = 0 student.stat['drunkard'] = eng.coinflip() student.stat['lazy'] = eng.coinflip() # Apply these previously written rules to each student for rule in (drink, sloth): student.rule(rule) # Apply these previously written rules to each brain cell for rule in (learn, sober_up, catch_up): student.place.rule(rule) eng.snap_keyframe() if __name__ == "__main__": from LiSE.engine import Engine with Engine(connect_string=":memory:") as eng: install(eng) for i in range(72): eng.next_turn() print(i)
go2kobold.prereqs = ['kobold_alive'] @go2kobold.prereq def kobold_not_here(thing): return 'kobold' not in thing.location.content @dwarf.rule def wander(thing): dests = sorted(list(thing.character.place.keys())) dests.remove(thing['location']) thing.travel_to(thing.engine.choice(dests)) @wander.trigger def standing_still(thing): return thing.next_location is None if __name__ == '__main__': from LiSE.engine import Engine from os import remove try: remove('LiSEworld.db') except FileNotFoundError: pass with Engine('LiSEworld.db', random_seed=69105) as engine: inittest(engine, shrubberies=20, kobold_sprint_chance=.9) engine.commit() print('shrub_places beginning: {}'.format( engine.character['physical'].thing['kobold']['shrub_places'] ))
for student in (student0, student1): if student not in student_body.stat['characters']: student_body.stat['characters'].append(student) # Students' nodes are their brain cells. # They are useless if drunk or slow, but recover from both conditions a bit every hour. for k in range(0, 100): cell = student.new_node('cell{}'.format(k), drunk=0, slow=0) # ``new_node`` is just an alias for ``new_place``; # perhaps more logical when the places don't really # represent potential locations student.stat['xp'] = 0 student.stat['drunkard'] = eng.coinflip() student.stat['lazy'] = eng.coinflip() # Apply these previously written rules to each student for rule in (drink, sloth): student.rule(rule) # Apply these previously written rules to each brain cell for rule in (learn, sober_up, catch_up): student.place.rule(rule) if __name__ == "__main__": from LiSE.engine import Engine with Engine(":memory:") as eng: install(eng) for i in range(72): eng.next_turn() print(i)
def test_keyframe_load_init(tempdir): """Can load a keyframe at start of branch, including locations""" eng = Engine(tempdir) inittest(eng) eng.branch = 'new' eng.snap_keyframe() eng.close() eng = Engine(tempdir) assert eng._things_cache.keyframe['physical', 'kobold'][ eng.branch][eng.turn][eng.tick] assert 'kobold' in eng.character['physical'].thing assert (0, 0) in eng.character['physical'].place assert (0, 1) in eng.character['physical'].portal[0, 0] eng.close()
def mkengine(w='sqlite:///LiSEworld.db', *args, **kwargs): return Engine(worlddb=w, codedb='LiSEcode.db', *args, **kwargs)
def college24_premade(): directory = tempfile.mkdtemp('.') shutil.unpack_archive(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'college24_premade.tar.xz'), directory) with Engine(directory) as eng: yield eng shutil.rmtree(directory)
def test(): eng = Engine(":memory:") install(eng) for i in range(24): eng.next_tick()
def go2kobold(thing): thing.travel_to(thing.character.thing['kobold']['location']) go2kobold.trigger(aware) go2kobold.prereqs = ['kobold_alive'] @go2kobold.prereq def kobold_not_here(thing): return 'kobold' not in thing.location.content @dwarf.rule def wander(thing): dests = sorted(list(thing.character.place.keys())) dests.remove(thing['location']) thing.travel_to(thing.engine.choice(dests)) @wander.trigger def standing_still(thing): return thing.next_location is None if __name__ == '__main__': from LiSE.engine import Engine from os import remove with Engine(random_seed=69105, clear=True) as engine: inittest(engine, shrubberies=20, kobold_sprint_chance=.9) engine.commit() print('shrub_places beginning: {}'.format( engine.character['physical'].thing['kobold']['shrub_places']))
class SimTest(TestCase): maxDiff = None def setUp(self): """Start an engine, install the sim module, and run it a while. This gives us some world-state to test upon. """ from logging import getLogger, FileHandler self.engine = Engine(":memory:") logger = getLogger('LiSE.engine') logger.setLevel('DEBUG') logger.addHandler(FileHandler('test.log')) sim.install(self.engine) for i in range(72): self.engine.next_tick() self.engine.commit() def tearDown(self): """Close my engine.""" self.engine.close() def testRulebooksCache(self): rulebooks = defaultdict(list) for (rulebook, rule) in self.engine.rule.query.rulebooks_rules(): rulebooks[rulebook].append(rule) # Ignoring empty rulebooks because those only exist # implicitly, they don't have database records oldrulebooks = {} for (k, v) in self.engine._rulebooks_cache._data.items(): if v: oldrulebooks[k] = [rule.name for rule in v] self.assertDictEqual(oldrulebooks, rulebooks) def testCharRulebooksCaches(self): charrb = {} for (character, character_rulebook, avatar_rulebook, character_thing_rulebook, character_place_rulebook, character_node_rulebook, character_portal_rulebook ) in self.engine.query.characters_rulebooks(): charrb[character] = { 'character': character_rulebook, 'avatar': avatar_rulebook, 'character_thing': character_thing_rulebook, 'character_place': character_place_rulebook, 'character_node': character_node_rulebook, 'character_portal': character_portal_rulebook } self.assertDictEqual(charrb, self.engine._characters_rulebooks_cache._data) def testNodeRulebooksCache(self): noderb = defaultdict(dict) for (character, node, rulebook) in self.engine.query.nodes_rulebooks(): noderb[character][node] = rulebook self.assertDictEqual(noderb, self.engine._nodes_rulebooks_cache._data) def testPortalRulebooksCache(self): portrb = StructuredDefaultDict(1, dict) for (character, nodeA, nodeB, rulebook) in self.engine.query.portals_rulebooks(): portrb[character][nodeA][nodeB] = rulebook self.assertDictEqual(portrb, self.engine._portals_rulebooks_cache._data) def testAvatarnessCaches(self): user_avatarness = StructuredDefaultDict(3, WindowDict) for (character, graph, node, branch, tick, is_avatar) in self.engine.query.avatarness_dump(): user_avatarness[graph][node][character][branch][tick] = is_avatar new_user_avatarness = StructuredDefaultDict(3, WindowDict) usr = self.engine._avatarness_cache.user_order for graph in usr: for node in usr[graph]: for char in usr[graph][node]: if usr[graph][node][char]: for branch in usr[graph][node][char]: for tick, is_avatar in usr[graph][node][char][ branch].items(): new_user_avatarness[graph][node][char][branch][ tick] = is_avatar self.assertDictEqual(user_avatarness, new_user_avatarness) def testNodeRulesHandledCache(self): node_rules_handled_ticks = defaultdict( # character: lambda: defaultdict( # node: lambda: defaultdict( # rulebook: lambda: defaultdict( # rule: lambda: defaultdict( # branch: set # ticks handled ))))) new_node_rules_handled_ticks = defaultdict( # character: lambda: defaultdict( # node: lambda: defaultdict( # rulebook: lambda: defaultdict( # rule: dict)))) cache = self.engine._node_rules_handled_cache._data for char in cache: for node in cache[char]: for rulebook in cache[char][node]: for rule in cache[char][node][rulebook]: if cache[char][node][rulebook][rule]: new_node_rules_handled_ticks[ char][node][rulebook][rule] \ = cache[char][node][rulebook][rule] for character, node, rulebook, rule, branch, tick in \ self.engine.query.dump_node_rules_handled(): node_rules_handled_ticks[character][node][rulebook][rule][ branch].add(tick) self.assertDictEqual(node_rules_handled_ticks, new_node_rules_handled_ticks) def testPortalRulesHandledCache(self): portal_rules_handled_ticks = defaultdict( # character: lambda: defaultdict( # nodeA: lambda: defaultdict( # nodeB: lambda: defaultdict( # rulebook: lambda: defaultdict( # rule: lambda: defaultdict( # branch: set # ticks handled )))))) new_portal_rules_handled_ticks = defaultdict( # character: lambda: defaultdict( # nodeA: lambda: defaultdict( # nodeB: lambda: defaultdict( # rulebook: lambda: defaultdict( # rule: dict))))) cache = self.engine._portal_rules_handled_cache._data for character in cache: for nodeA in cache[character]: for nodeB in cache[character][nodeA]: for rulebook in cache[character][nodeA][nodeB]: for rule in cache[character][nodeA][nodeB][rulebook]: if cache[character][nodeA][nodeB][rulebook][rule]: new_portal_rules_handled_ticks[ character][nodeA][nodeB][rulebook][rule] \ = cache[character][nodeA][nodeB][ rulebook][rule] for (character, nodeA, nodeB, idx, rulebook, rule, branch, tick) \ in self.engine.query.dump_portal_rules_handled(): portal_rules_handled_ticks[character][nodeA][nodeB][rulebook][ rule][branch].add(tick) self.assertDictEqual(portal_rules_handled_ticks, new_portal_rules_handled_ticks) def testCharRulesHandledCaches(self): live = self.engine._character_rules_handled_cache._data for rulemap in [ 'character', 'avatar', 'character_thing', 'character_place', 'character_portal' ]: handled_ticks = StructuredDefaultDict(2, set) for character, rulebook, rule, branch, tick in getattr( self.engine.query, 'handled_{}_rules'.format(rulemap))(): handled_ticks[character][rule][branch].add(tick) old_handled_ticks = StructuredDefaultDict(2, set) for character in live: if live[character][rulemap]: for rule in live[character][rulemap]: for branch, ticks in live[character][rulemap][ rule].items(): self.assertIsInstance(ticks, set) old_handled_ticks[character][rule][branch] = ticks self.assertDictEqual(old_handled_ticks, handled_ticks, "\n{} cache differs from DB".format(rulemap)) def testThingsCache(self): things = StructuredDefaultDict(3, tuple) for (character, thing, branch, tick, loc, nextloc) in \ self.engine.query.things_dump(): things[(character, )][thing][branch][tick] = (loc, nextloc) self.assertDictEqual(things, self.engine._things_cache.keys) def testRoommateCollisions(self): """Test queries' ability to tell that all of the students that share rooms have been in the same place. """ done = set() for chara in self.engine.character.values(): if chara.name in done: continue match = re.match('dorm(\d)room(\d)student(\d)', chara.name) if not match: continue dorm, room, student = match.groups() other_student = 1 if student == 0 else 0 student = chara other_student = self.engine.character[ 'dorm{}room{}student{}'.format(dorm, room, other_student)] same_loc_ticks = list( self.engine.ticks_when( student.avatar.only.historical('location') == other_student.avatar.only.historical('location'))) self.assertTrue( same_loc_ticks, "{} and {} don't seem to share a room".format( student.name, other_student.name)) self.assertGreater( len(same_loc_ticks), 6, "{} and {} share their room for less than 6 ticks".format( student.name, other_student.name)) done.add(student.name) done.add(other_student.name) def testSoberCollisions(self): """Students that are neither lazy nor drunkards should all have been in class together at least once. """ students = [ stu for stu in self.engine.character['student_body'].stat['characters'] if not (stu.stat['drunkard'] or stu.stat['lazy']) ] assert students def sameClasstime(stu0, stu1): self.assertTrue( self.engine.ticks_when( stu0.avatar.only.historical('location') == stu1.avatar.only .historical('location') == self.engine.alias('classroom')), "{stu0} seems not to have been in the classroom " "at the same time as {stu1}.\n" "{stu0} was there at ticks {ticks0}\n" "{stu1} was there at ticks {ticks1}".format( stu0=stu0.name, stu1=stu1.name, ticks0=list( self.engine.ticks_when( stu0.avatar.only.historical('location') == self.engine.alias('classroom'))), ticks1=list( self.engine.ticks_when( stu1.avatar.only.historical('location') == self.engine.alias('classroom'))))) return stu1 reduce(sameClasstime, students) def testNoncollision(self): """Make sure students *not* from the same room never go there together""" dorm = defaultdict(lambda: defaultdict(dict)) for character in self.engine.character.values(): match = re.match('dorm(\d)room(\d)student(\d)', character.name) if not match: continue d, r, s = match.groups() dorm[d][r][s] = character for d in dorm: other_dorms = [dd for dd in dorm if dd != d] for r in dorm[d]: other_rooms = [rr for rr in dorm[d] if rr != r] for stu0 in dorm[d][r].values(): for rr in other_rooms: for stu1 in dorm[d][rr].values(): self.assertFalse( self.engine.ticks_when( stu0.avatar.only.historical('location') == stu1.avatar.only.historical('location') == self.engine.alias('dorm{}room{}'.format( d, r))), "{} seems to share a room with {}".format( stu0.name, stu1.name)) common = 'common{}'.format(d) for dd in other_dorms: for rr in dorm[dd]: for stu1 in dorm[dd][rr].values(): self.assertFalse( self.engine.ticks_when( stu0.avatar.only.historical('location') == stu1.avatar.only.historical( 'location') == self.engine.alias( common)), "{} seems to have been in the same" "common room as {}".format( stu0.name, stu1.name))