def test09_ArrayGet(self): mv1 = MapVector([('door', 0), ('hwal', 1)]) mv2 = MapVector([('hall', 0), ('room', 1)]) ma1 = MapArray([mv1, mv2], (5, 5)) print('\n' + str(ma1)) # row getters mv3 = ma1[1] st3 = "#.#.#" self.assertEqual(str(mv3), "#.#.#", "get single row element") self.assertTrue(isinstance(mv3, MapVector), "single int parameter is MapVector") li1 = ma1[1:5] self.assertTrue( type(li1) == list, "single-dimension slice is standard list") mv4 = li1[1] st4 = "+-+-+" self.assertTrue(isinstance(mv4, MapVector), "element of list is MapVector") self.assertEqual(str(mv4), st4, "get element from slice of rows") ms1 = ma1[1, 1] self.assertTrue(isinstance(ms1, MapSquare), "[int,int] returns single MapSquare") self.assertEqual(str(ms1), ".", "[int,int] correct element") # changed MapArray get result types #mv5 = ma1[1][1:3] #mv6 = ma1[1:3,1] # self.assertTrue(isinstance(mv6, MapVector), "[range,y] returns MapVector") #self.assertEqual(str(mv5),str(mv6), "[range, y] returns the right MapVector") # get single square mc = ('hall', 0) self.assertEqual(ma1[2, 1], mc, "get correct single MapSquare from [int,int]") # column slice tests ma2a = ma1[1, 1:2] self.assertEqual((1, 1), (ma2a.w, ma2a.h), "1x1 column slice") ma2 = ma1[1, 1:3] self.assertEqual((1, 2), (ma2.w, ma2.h), "1x2 column slice") st2 = ".\n-" st2b = "MapArray([MapVector([MapSquare('room', 1)]), MapVector([MapSquare('hwal', 1)])])" self.assertEqual(ma2.__repr__(), st2b, "get range on single column __repr__") self.assertEqual(len(ma2), 2) self.assertEqual(type(ma2[1]), MapVector, "2 MapVector rows") self.assertEqual(str(ma2), st2, "get range on single column") ma3 = MapArray(ma1, (2, 3)) ma4 = ma1[2:4, 2:6] self.assertEqual(str(ma3), str(ma4), "slices in multiple dimensions") ma5 = ma1[3:5, 4:5] st5 = "-+" self.assertTrue(isinstance(ma5, MapArray), "1 row slice is still MapArray") self.assertEqual(str(ma5), st5, "correct 1 row slice")
def __init__(self, params): self.params = params self.log_messages = [] self.roll_log = [] self.loaded_dice = [] self.process_params() self.maparray = MapArray(("void", 0), (self.w, self.h)) self.descriptions = [{}] self.engine = self.the_engine()
def hall_test(w, h): ma = MapArray(('void', 0), (w, h)) rlist = [{}] features = set({'type': 'passage', 'x': 1, 'y': h // 2, 'd': 'e'}) while len(features) > 0: add_feature(ma, rlist, features) return ma, rlist
def room(w, h, rnum): mp = MapArray(('room', rnum), (w, h)) mp[0:w:w - 1, 1:h - 1] = ('vwal', rnum) mp[1:w - 1, 0:h:h - 1] = ('hwal', rnum) mp[0:w:w - 1, 0] = ('tcor', rnum) mp[0:w:w - 1, h - 1] = ('bcor', rnum) return mp
def maparray_tests(): m = MapArray(('void', 0), (10, 10)) assert ('void', 0) == m[0, 0] assert ('void', 0) == m[5, 5] m[4, 4] = ('hall', 0) assert ('hall', 0) == m[4, 4] x = len(m[0:4, 1:2].squares()) assert x == 4
def test10_ArraySet(self): mvs = [] mvs.append(MapVector([('void', 0), ('hall', 0)], 8)) mvs.append(MapVector([('room', 0), ('sdor', 0)], 8)) mvs.append(MapVector([('vwal', 0), ('hwal', 0)], 8)) mvs.append(MapVector([('sdwn', 0), ('stup', 0)], 8)) ma1 = MapArray(mvs) print("\n" + str(ma1)) st1 = "\n".join([str(mv) for mv in mvs]) self.assertEqual(str(ma1), st1) ma1[2] = mvs[3] mvs2 = [mvs[0], mvs[1], mvs[3], mvs[3]] st2 = "\n".join([str(mv) for mv in mvs2]) self.assertEqual(str(ma1), st2, "replace single row") ma1[2] = ('door', 0) mvd = MapVector(('door', 0), 8) mvs3 = [mvs[0], mvs[1], mvd, mvs[3]] st3 = "\n".join([str(mv) for mv in mvs3]) self.assertEqual(str(ma1), st3, "replace row with single square") ma1[0:5:2] = mvs[2] mvs4 = [mvs[2], mvs[1], mvs[2], mvs[3]] st4 = "\n".join([str(mv) for mv in mvs4]) self.assertEqual(str(ma1), st4, "replace slice with single row") ma1 = MapArray(mvs) ma1[1:3] = mvs mvs5 = [mvs[0], mvs[0], mvs[1], mvs[3]] st5 = "\n".join([str(mv) for mv in mvs5]) self.assertEqual(str(ma1), st5, "replace slice with larger list") # set 2d ma1 = MapArray(mvs) ma1[0, 0] = ('door', 1) st6 = "+#\n.*" self.assertEqual(str(ma1[0:2, 0:2]), st6, "set single square") ma1[1:4, 1] = ('door', 1) st7 = ".+++.*.*" self.assertEqual(str(ma1[1]), st7) ma2 = MapArray(('room', 0), (4, 4)) st8 = "...." st9 = ".++." st10 = "\n".join([st8, st9, st9, st8]) ma2[1:3, 1:3] = ('door', 1) self.assertEqual(str(ma2), st10) ma1[1:7, 1:3] = ma2 print(ma1)
def gen_map(w, h, typ="default"): maparray = MapArray(('void', 0), (w, h)) x = maparray.w // 2 y = 0 mapset = set() add_hall(maparray, ('hall', 's', x, y), mapset) while len(mapset) > 0: pop_section(maparray, mapset) return (maparray, [{}])
def big_room(w, h): ma = MapArray(('void', 0), (w, h)) rlist = [{}] x = 3 y = 3 rw = w - 6 rh = h - 6 ma[x:x + rw, y:y + rh] = room(rw, rh, 1) rlist.append({"description": "BIG ROOM DADDY-O"}) return ma, rlist
def test03_VecConstruct(self): mv1 = MapVector([MapSquare('door', 0)]) st1 = "MapVector([MapSquare('door', 0)])" self.assertEqual(mv1.__repr__(), st1) self.assertEqual(str(mv1), "+") mv2 = MapVector(('door', 0)) self.assertEqual(mv2.__repr__(), st1) self.assertEqual(str(mv1), "+") mv3 = MapVector( [MapSquare('vwal', 1), MapSquare('room', 2), MapSquare('vwal', 3)]) st2 = "MapVector([MapSquare('vwal', 1), MapSquare('room', 2), MapSquare('vwal', 3)])" self.assertEqual(mv3.__repr__(), st2, "MapVector constructor from list of MapSquares") self.assertEqual( str(mv3), "|.|", "MapVector constructor from list of MapSquares - str") mv4 = MapVector([('vwal', 1), ('room', 2), ('vwal', 3)]) self.assertEqual(mv4.__repr__(), st2, "MapVector constructor from list of tuples") self.assertEqual(str(mv4), "|.|", "MapVector constructor from list of tuples - str") mv6 = MapVector([MapSquare('hall', 0) for _ in range(3)]) st3 = "MapVector([MapSquare('hall', 0), MapSquare('hall', 0), MapSquare('hall', 0)])" self.assertEqual(mv6.__repr__(), st3, "MapVector constructor with list comprehension") self.assertEqual( str(mv6), "###", "MapVector constructor with list comperhension - str)") mv5 = MapVector(mv4) self.assertEqual(mv5.__repr__(), st2, "Nested MapVector constructor is copies value") self.assertNotEqual( id(mv4), id(mv5), "Nested MapVector constructor does not copy pointer") l1 = [("room", 3), ("room", 4), ("room", 5)] mv7 = MapVector(l1) mv8 = MapVector(l1) self.assertNotEqual( id(mv7), id(mv8), "MapVector constructor from same list does not duplicate pointer") s1 = MapSquare("void", 0) mv9 = MapVector(s1) mv10 = MapVector(s1) self.assertNotEqual( id(mv9), id(mv10), "MapVector constructor from same MapSquare does not duplicate pointer" ) ma = MapArray([mv4, mv6]) mv11 = MapVector(ma) self.assertEqual(str(mv11), "|.|")
def gen_splash(w, h): ma = MapArray(('void', 0), (w, h)) topW = ma.w // 4 * 2 botW = ma.w // 7 topH = ma.h // 9 botH = ma.h // 9 * 5 topX = ma.w // 4 botX = ma.w // 7 * 3 dorX = ma.w // 2 - 1 topY = ma.h // 9 * 2 botY = ma.h // 9 * 3 - 1 topR = room(topW, topH, 1) botR = room(botW, botH, 1) ma[topX:topX + topW, topY:topY + topH] = topR ma[botX:botX + botW, botY:botY + botH] = botR ma[dorX, botY] = ('door', 1) rlist = [{}] rlist.append({ "description": """<h2>Tarterus</h2> <p>© Carter Adams 2018</p>""" }) return ma, rlist
def dispatch_command(self, command): if command is None: pass elif command[0] == 'step': self.dispatch(self.pending.pop()) return len(self.pending) elif command[0] == 'add': self.pending.add(command[1]) return len(self.pending) elif command[0] == 'insert': self.pending.insert(command[1], command[2]) return len(self.pending) elif command[0] == 'execute': self.dispatch(self.pending.ipop(command[1]), None) return len(self.pending) elif command[0] == 'step_with_command': self.dispatch(self.pending.pop(), command[1]) return len(self.pending) elif command[0] == 'execute_with_command': self.dispatch(self.pending.ipop(command[1]), command[2]) return len(self.pending) elif command[0] == 'remove': self.pending.ipop(command[1]) return len(self.pending) elif command[0] == 'replace': self.pending[command[1]] = command[2] return len(self.pending) # Clears everything but the log elif command[0] == 'clear': self.log("\n\n:: CLEARING ENGINE") self.maparray = MapArray(('void', 0), (self.w, self.h)) self.descriptions = [] self.pending.clear() self.pending = PendingList(self.params.get("pop_mode", "random")) return None elif command[0] == 'set_params': self.params = command[1] self.process_params() return None elif command[0] == 'get' and len(command) == 1: return { "maparray": self.maparray, "descriptions": self.descriptions, "pending": self.pending } elif command[0] == 'in': return command[1] in self.pending.items elif command[0] == 'load_dice': self.loaded_dice = command[1] return None elif command[0] == 'roll': try: return self.roll(command[1]) except IndexError: return self.roll([20]) elif command[0] == 'log': self.log(command[1]) return None elif command[0] == 'get_log': return "\n".join(str(message) for message in self.get_log()) # this will render the map pretty well non-functional as a map, should # move this into MapArray logic if it is kept at all, but it's a hack # for testing elif command[0] == 'place_grid': for x in range(1, self.w, 5): for y in range(1, self.w, 5): if self.maparray[x, y][0] == "void": self.maparray[x, y] = ("grid", 0)
class Engine(): def __init__(self, params): self.params = params self.log_messages = [] self.roll_log = [] self.loaded_dice = [] self.process_params() self.maparray = MapArray(("void", 0), (self.w, self.h)) self.descriptions = [{}] self.engine = self.the_engine() def generate_description(self, t): n = t[1] if n == -1: n = len(self.descriptions) if n >= len(self.descriptions): for _ in range(len(self.descriptions), n+1): self.descriptions.append({'num': n}) return (t[0], n) def describe(self, n, content): old_content = self.descriptions[n] self.descriptions[n] = {**old_content, **content} def process_params(self): self.w = self.params['w'] self.h = self.params['h'] self.pending = PendingList(self.params.get("pop_mode", "random")) self.immediate_list = PendingList("stack") script_file = self.params.get("script_file", None) if script_file is not None: script_data = json.load(open(script_file)) self.loaded_dice = script_data["roll"] self.pending.scripted_ipop = script_data["ipop"] if self.params.get("log", True) is True: self.log = self.yes_log self.log2 = self.no_log elif self.params.get("log", True) is 2: self.log = self.yes_log self.log2 = self.yes_log else: self.log = self.no_log self.log2 = self.no_log self.dont_terminate = self.params.get("dont_terminate", False) # does not do anything yet self.max_steps = self.params.get("max_steps", -1) self.log("::Parameters Loaded\n\t{}".format(self.params)) self.extra_branch = self.params.get("extra_branch", False) # Coroutine generator. At each step returns the length of pending. # .__next__() will iterate the generation by popping an element from # pending and dispatching it. .send(command) will dispatch the command def the_engine(self): ret = len(self.pending) while True: command = yield ret # PEP 342 if command is None and len(self.pending) > 0: self.log(":: Step()") self.dispatch(self.pending.pop(), {}) ret = len(self.pending) elif command is None and self.dont_terminate is False: self.log(":: No Action") return elif command is not None: self.log(":: Command:\n\t{}".format(command)) ret = self.dispatch_command(command) # Default log function, does nothing def no_log(self, message): pass def yes_log(self, message): self.log_messages.append(message) def get_log(self): return "\n".join(str(m) for m in self.log_messages) def print_log(self, message): print(message) # Generate the map by looping through the engine with no commands. Does not # respect dont_terminate. Should never create an infinite loop. def gen_map(self): the_engine = self.the_engine() next(the_engine) for ndispatches in the_engine: if ndispatches == 0: break # def gen_map_with_status(self, filename): # the_engine = self.the_engine() # next(the_engine) # for ndispatches in the_engine: # if randint(1, 10) == 10: # with open(filename, 'w') as f: # f.write(str(len(self.descriptions))) # if ndispatches == 0: # break # with open(filename, 'w') as f: # f.write("done") # def gen_map_files(self, mapfile, jsonfile, statusfile): the_engine = self.the_engine() next(the_engine) for ndispatches in the_engine: if randint(1, 20) == 20: with open(statusfile, 'w') as f: f.write(str(len(self.descriptions))) if ndispatches == 0: break with open(statusfile, "w") as f: f.write("populating rooms") self.process_descriptions() with open(mapfile, "wb") as f: f.write(self.maparray.bytes()) with open(jsonfile, "w") as f: json.dump({ "w": self.w, "h": self.h, "descriptions": self.descriptions }, f) with open(statusfile, "w") as f: f.write("done") # iterate map generation one step with no command def step(self): return next(self.engine) # send a command to the engine def send(self, command): return self.engine.send(command) def add(self, element): self.log(":: Add\n\t{}".format(element)) self.pending.add(element) def write_choice_log(self, filename): with open(filename, "w") as f: log_output = { "roll": self.roll_log, "ipop": self.pending.ipop_log } json.dump(log_output, f) # Create a list of die roll results from a vector of the numbers of sides # of each die. All random number generation in the map generation process # is handled by this method and in the random pop method of PendingList # forced_rolls will force rolls # if no forced rolls, check loaded_dice (set with a command or a script # file) def roll(self, dice, forced_rolls=[]): ret = [] for i, nsides in enumerate(dice): try: ret.append(forced_rolls[i]) except IndexError: try: ret.append(self.loaded_dice[0]) self.loaded_dice = self.loaded_dice[1:] except IndexError: ret.append(randint(1, nsides)) self.log("::Dice rolled\n\t{}".format(ret)) # log dice rolled, to be output to a script json for roll in ret: self.roll_log.append(roll) return ret # TODO: send die rolls from a command to the immediate list # Dispatch an element from the immediate_list, which is a stack. def dispatch_immediate(self, command={}): if len(self.immediate_list) > 0: element = self.immediate_list.pop() return self.dispatch(element, command) else: return False # Add an element to the immediate list def immediate_add(self, element): self.log(":: immediate_add\n\t{}".format(element)) self.immediate_list.add(element) # dispatch an element def dispatch(self, element, command={}): if element[0] == 'describe': pass if element[0] == 'door': dice = self.roll(door_dice, command.get("dice", [])) self.log("::dispatch_door\n\t{} {}".format(element, dice)) return dispatch_door(self, element, dice) if element[0] == 'hall': dice = self.roll(passage_dice, command.get("dice", [])) self.log("::dispatch_passage\n\t{} {}".format(element, dice)) return dispatch_passage(self, element, dice) if element[0] == 'start': dice = self.roll(start_dice, command.get("dice", [])) self.log("::dispatch_start\n\t{} {}".format(element, dice)) return dispatch_start(self, element, dice) if element[0] == 'room': dice = self.roll(room_dice, command.get("dice", [])) self.log("::dispatch_room\n\t{} {}".format(element, dice)) return dispatch_room(self, element, dice) if element[0] == 'exit': dice = self.roll(exit_dice, command.get("dice", [])) self.log("::dispatch_exit\n\t{} {}".format(element, dice)) return dispatch_exit(self, element, dice) def __str__(self): if len(self.roll_log) > 2: last_roll = self.roll_log[-3:] else: last_roll = self.roll_log return """Engine: maparray: {} descriptions: {} last roll: {} pending elements: {}""".format(self.maparray, self.descriptions, last_roll, self.pending) def process_descriptions(self): for d in self.descriptions: if 'type' in d: if d['type'] == 'chamber': try: d['description'] = describe_chamber(self, d) except Exception as e: d['description'] = "Oops, the room chamber contains\ {}.\nRoll for initiative to fight the bug. {}".format(e, self.roll_log[-20:]) elif d['type'] == 'passage': try: d['description'] = describe_passage(self, d) except Exception as e: d['description'] = "Oops, the passage contains\ {}.\nRoll for initiative to fight the bug.".format(e) elif d['type'] == 'door': try: d['description'] = describe_door(self, d) except Exception as e: d['description'] = "Oops, the door contains\ {}.\nRoll for initiative to fight the bug.".format(e) # COMMANDS # ['step'] pop an element & dispatch # ['add', element] add an element to the list # ['insert', index, element] insert element at position in list # ['execute', index] pop specific element & dispatch # ['dispatch_with_command', command] pop specific element & dispatch w/ # a command parameter # ['step_with_command', index, command] pop an element & dispatch w/ a # command parameter # ['remove', index] remove an element from a location # ['replace', index, command] replace the element at a location # ['clear'] clear maparray, descriptions, and # parameters # ['set_params'] reset the parameters from initiation # ['get'] get {maparray, pending, descriptions # ['in', element] boolean, if an element is in the # pending list # ['load_dice', dice] add list of forced die rolls # ['roll', sides] # ['log', message] # ['get_log'] # ['place_grid'] def dispatch_command(self, command): if command is None: pass elif command[0] == 'step': self.dispatch(self.pending.pop()) return len(self.pending) elif command[0] == 'add': self.pending.add(command[1]) return len(self.pending) elif command[0] == 'insert': self.pending.insert(command[1], command[2]) return len(self.pending) elif command[0] == 'execute': self.dispatch(self.pending.ipop(command[1]), None) return len(self.pending) elif command[0] == 'step_with_command': self.dispatch(self.pending.pop(), command[1]) return len(self.pending) elif command[0] == 'execute_with_command': self.dispatch(self.pending.ipop(command[1]), command[2]) return len(self.pending) elif command[0] == 'remove': self.pending.ipop(command[1]) return len(self.pending) elif command[0] == 'replace': self.pending[command[1]] = command[2] return len(self.pending) # Clears everything but the log elif command[0] == 'clear': self.log("\n\n:: CLEARING ENGINE") self.maparray = MapArray(('void', 0), (self.w, self.h)) self.descriptions = [] self.pending.clear() self.pending = PendingList(self.params.get("pop_mode", "random")) return None elif command[0] == 'set_params': self.params = command[1] self.process_params() return None elif command[0] == 'get' and len(command) == 1: return { "maparray": self.maparray, "descriptions": self.descriptions, "pending": self.pending } elif command[0] == 'in': return command[1] in self.pending.items elif command[0] == 'load_dice': self.loaded_dice = command[1] return None elif command[0] == 'roll': try: return self.roll(command[1]) except IndexError: return self.roll([20]) elif command[0] == 'log': self.log(command[1]) return None elif command[0] == 'get_log': return "\n".join(str(message) for message in self.get_log()) # this will render the map pretty well non-functional as a map, should # move this into MapArray logic if it is kept at all, but it's a hack # for testing elif command[0] == 'place_grid': for x in range(1, self.w, 5): for y in range(1, self.w, 5): if self.maparray[x, y][0] == "void": self.maparray[x, y] = ("grid", 0)
def start_table_1(engine, origin, dice): layout = MapArray(('void', 0), (10, 10)) layout[4:6, 0:2] = ('hall', 1) layout[8:10, 4:6] = ('hall', 2) layout[4:6, 8:10] = ('hall', 3) layout[0:2, 4:6] = ('hall', 4) layout[2, 3] = ('vwal', 5) layout[2, 6] = ('vwal', 5) layout[7, 3] = ('vwal', 5) layout[7, 6] = ('vwal', 5) layout[3, 2] = ('hwal', 5) layout[6, 2] = ('hwal', 5) layout[3, 7] = ('hwal', 5) layout[6, 7] = ('hwal', 5) layout[2, 2] = ('tcor', 5) layout[7, 2] = ('tcor', 5) layout[2, 7] = ('bcor', 5) layout[7, 7] = ('bcor', 5) layout[2, 4:6] = ('open', 5) layout[4:6, 2] = ('open', 5) layout[7, 4:6] = ('open', 5) layout[4:6, 7] = ('open', 5) layout[3:7, 3:7] = ('room', 5) layout[5, 5] = ('stup', 5) w = 10 h = 10 if origin not in ['n', 'e', 's', 'w', 'm']: origin = 'm' if origin == 'n': x = engine.maparray.w // 2 - w // 2 y = 0 elif origin == 'e': x = engine.maparray.w - w y = engine.maparray.h // 2 - h // 2 elif origin == 's': x = engine.maparray.w // 2 - w // 2 y = engine.maparray.h - h elif origin == 'w': x = 0 y = engine.maparray.h // 2 - h // 2 elif origin == 'm': x = engine.maparray.w // 2 - w // 2 y = engine.maparray.h // 2 - h // 2 engine.generate_description(('hall', 1)) engine.describe(1, {'type': 'passage', 'w': 10}) engine.generate_description(('hall', 2)) engine.describe(2, {'type': 'passage', 'w': 10}) engine.generate_description(('hall', 3)) engine.describe(3, {'type': 'passage', 'w': 10}) engine.generate_description(('hall', 4)) engine.describe(4, {'type': 'passage', 'w': 10}) engine.generate_description(('hall', 5)) engine.describe(5, {'type': 'chamber', 'w': 20, 'h': 20}) if origin != 'n': engine.add(['hall', 'passage', x + 4, y - 1, 'n', 2, ('hall', 1)]) if origin != 'e': engine.add(['hall', 'passage', x + 10, y + 4, 'e', 2, ('hall', 2)]) if origin != 's': engine.add(['hall', 'passage', x + 4, y + 10, 's', 2, ('hall', 3)]) if origin != 'w': engine.add(['hall', 'passage', x - 1, y + 4, 'w', 2, ('hall', 4)]) engine.maparray[x:x + w, y:y + h] = layout return (True, )
def test08_MapArrayConstructor(self): ma1 = MapArray(('hall', 10)) st1 = "MapArray([MapVector([MapSquare('hall', 10)])])" self.assertEqual(ma1.__repr__(), st1, "constructor with single MapSquare") ma1 = MapArray(('hall', 10), 1) self.assertEqual( ma1.__repr__(), st1, "single-square constructor with 1 dimensional size parameter") ma1 = MapArray(('hall', 10), (1, 1)) self.assertEqual( ma1.__repr__(), st1, "single-square constructor with 2 dimensional size parameter") st2 = "##" st2b = "MapArray([MapVector([MapSquare('hall', 0), MapSquare('hall', 0)])])" ma2 = MapArray(('hall', 0), (2, 1)) self.assertEqual(ma2.__repr__(), st2b, "(2,1) __repr__ test") self.assertEqual(str(ma2), st2, "(2,1) size constructor") st3 = "#\n#" st3b = "MapArray([MapVector([MapSquare('hall', 0)]), MapVector([MapSquare('hall', 0)])])" ma3 = MapArray(('hall', 0), (1, 2)) self.assertEqual(str(ma3), st3, "(1,2) size constructor") self.assertEqual(ma3.__repr__(), st3b, "(1,2) __repr__ test") mv1 = MapVector(('room', 2), 3) ma4 = MapArray(mv1) self.assertEqual(str(mv1), str(ma4), "Constructor with single MapVector") ma4 = MapArray([('room', 2) for i in range(3)]) self.assertEqual(str(mv1), str(ma4), "Constructor with 1d list") ma5 = MapArray(mv1, (2, 1)) st5 = ".." self.assertEqual(str(ma5), st5, "Constructor restricts x dimension") mv2 = MapVector([('hall', 1), ('door', 1)]) ma6 = MapArray(mv2, (5, 1)) st6 = "#+#+#" self.assertEqual(str(ma6), st6, "Constructor expands x dimension") ma7 = MapArray(mv2, 2) st7 = "#+\n#+" self.assertEqual(str(ma7), st7, "Constructor expands y dimension, single parameter") ma1b = MapArray(ma1) ma7b = MapArray(ma7) self.assertEqual(ma1.__repr__(), ma1b.__repr__(), "Constructor as identity on MapArray 1x1") self.assertEqual(ma7.__repr__(), ma7b.__repr__(), "Constructor as identity on MapArray 2x2") id1 = id(ma7) id2 = id(ma7b) self.assertNotEqual(id1, id2, "Constructor copies value not reference") mv3 = MapVector([('hwal', 0), ('door', 1)]) mv4 = MapVector(mv3, 3)[1:] ma8 = MapArray([mv3, mv4]) st8 = "-+\n+-" self.assertEqual(str(ma8), st8, "Constructor with list of MapVectors") mv5 = MapVector(mv4, 10) ma8 = MapArray([mv3, mv5]) self.assertEqual( str(ma8), st8, "Constructor with list of irregular MapVectors (keep dimension of top row)" ) ma9 = MapArray(ma8, (3, 3)) st9 = "-+-\n+-+\n-+-" self.assertEqual(str(ma9), st9, "Constructor expands Maparray (2x2) -> (3x3)") ma10 = MapArray(ma9, (5, 1)) st10 = "-+--+" self.assertEqual( str(ma10), st10, "Constructor expands in one dimension and contracts in another (3x3) -> (5,1)" )
def room_tests(): print("room.py") e = Engine({"w": 80, "h": 40, "pop_mode": "queue"}) e.step() # test draw_room m = MapArray(('void', 0), (10, 10)) m[5, 5] = ('vwal', 1) print("draw_room") _ = room.draw_room(m, 1, 1, 8, 8, ('room', 1)) assert _ is True assert m[1, 5] == m[8, 7] == ('vwal', 1) assert m[1, 1] == m[8, 1] == ('tcor', 1) assert m[8, 8] == m[1, 8] == ('bcor', 1) assert m[5, 1] == m[2, 8] == ('hwal', 1) assert m[2, 2] == m[7, 7] == ('room', 1) # attempt to draw room with blocking tile in the way m = MapArray(('void', 0), (10, 10)) m[5, 5] = ('hall', 1) _ = room.draw_room(m, 0, 0, 10, 10, 1) assert _ is False # draw room from dispatch room.dispatch_room(e, ["room", "draw", 1, 1, "e", (8, 8), ("room", 1)], [1, 5, 6]) m = e.maparray assert m[1, 5] == m[8, 7] == ('vwal', 1) assert m[1, 1] == m[8, 1] == ('tcor', 1) assert m[8, 8] == m[1, 8] == ('bcor', 1) assert m[5, 1] == m[2, 8] == ('hwal', 1) assert m[2, 2] == m[7, 7] == ('room', 1) # test find_loc print("find_loc") m = MapArray(('void', 0), (40, 40)) x, y = room.find_loc(m, 20, 1, 20, 10, "s", 1, [6, 5]) assert (x, y) == (10, 1), str((x, y)) x, y = room.find_loc(m, 20, 10, 20, 10, "n", 1, [6, 5]) assert (x, y) == (10, 1), str((x, y)) m[11, 2] = ('hall', 1) x, y = room.find_loc(m, 20, 1, 20, 10, "s", 1, [6, 5]) assert (x, y) == (19, 1), str((x, y)) m[35, 2] = ('room', 2) x, y = room.find_loc(m, 20, 1, 20, 10, "s", 1, [6, 5]) assert (x, y) == (15, 1), str((x, y)) m = MapArray(('void', 0), (40, 40)) m[4, 4] = ("room", 1) m[6, 11] = ("hall", 2) x, y = room.find_loc(m, 1, 8, 6, 6, "e", 1, [10, 4]) assert (x, y) == (1, 5), str((x, y)) m = MapArray(('void', 0), (40, 40)) x, y = room.find_loc(m, 1, 10, 6, 6, "e", 1, [6, 5]) assert (x, y) == (1, 7), str((x, y)) x, y = room.find_loc(m, 10, 1, 6, 6, "s", 4, [6, 5]) assert (x, y) == (9, 1), str((x, y)) m = MapArray(('void', 0), (50, 50)) # 6 + 5 = 11 - 11 = 0 + (8-2)//2 = 3 # 30, 20 move north by (3-1) = 18 x, y = room.find_loc(m, 30, 20, 8, 8, "w", 1, [6, 5]) assert (x, y) == (23, 16), str((x, y)) x, y = room.find_loc(m, 30, 20, 8, 8, "w", 4, [6, 5]) assert (x, y) == (23, 19), str((x, y)) # room tables e = Engine({ "w": 80, "h": 40, "pop_mode": "queue", "log": True, "dont_terminate": True }) e.step() e.add(['room', 'door', 10, 10, "n", 1, ('room', 1)]) e.add(['room', 'passage', 30, 10, "s", 2, ('room', 1)]) e.add(['hall', 'start', 50, 38, "n", 4, ('hall', 2)]) e.add(['hall', 'start', 70, 1, "s", 4, ('hall', 2)]) e.send([ 'load_dice', [ 13, 6, 5, 13, 7, 2, 11, 1, 1, 1, 1, 1, 15, 1, 1, 13, 7, 2, 6, 1, 1, 15, 1, 1, 15, 1, 1, 8, 5, 7 ] ]) e.gen_map() print("\n".join(str(m) for m in e.log_messages)) # print(e) e = Engine({ "w": 80, "h": 40, "pop_mode": "queue", "log": True, "dont_terminate": True }) e.step() e.add(['hall', 'start', 20, 1, 's', 4, ('hall', 1)]) e.send([ 'load_dice', [7, 2, 10, 8, 7, 9, 15, 2, 2, 19, 11, 9, 1, 8, 7, 14, 2, 2, 11, 2, 3] ]) e.gen_map()
def getlevel(self): w = self.file_obj['w'] h = self.file_obj['h'] bts = self.file_obj['mapbytes'] return MapArray(bts, (w, h))