def generate_trap(b, row, column): # Here we just take a chance and put a trap here. # but we should actually explore the rest of the column for other suitable place if b.available_traps > 0: chance = int(b.max_traps_number / b.size[0] * 100) if random.randint(0, 100) >= 100 - chance: if random.choice([True, False]): trap = board_items.Wall( model=bg_color + traps_color + graphics.Blocks.QUADRANT_UPPER_LEFT_AND_LOWER_RIGHT + graphics.Blocks.QUADRANT_UPPER_RIGHT_AND_LOWER_LEFT + graphics.Style.RESET_ALL, type="trap.hfire", ) trap.fire_timer = random.uniform(1.0, 4.0) b.place_item(trap, row, column) if isinstance(b.item(row, column - 1), board_items.BoardItemVoid): trap.fdir = constants.LEFT else: trap.fdir = constants.RIGHT else: trap = board_items.Wall( model=bg_color + base.Text.red_bright( graphics.Blocks.QUADRANT_UPPER_RIGHT_AND_LOWER_LEFT_AND_LOWER_RIGHT # noqa E501 + graphics.Blocks.QUADRANT_UPPER_LEFT_AND_LOWER_LEFT_AND_LOWER_RIGHT # noqa E501 ) + graphics.Style.RESET_ALL, type="trap.vfire", ) trap.fire_timer = random.uniform(2.0, 6.0) b.place_item(trap, row, column) trap.fdir = constants.UP b.available_traps -= 1
def test_tools_function(self): b = engine.Board() g = engine.Game() g.player = constants.NO_PLAYER self.assertIsNone(g.add_board(1, b)) self.assertIsNone(g.change_level(1)) self.assertIsNone( g.add_npc(1, board_items.NPC(value=10, inventory_space=1), 1, 1)) self.assertIsNone( b.place_item(board_items.Door(value=10, inventory_space=1), 1, 2)) self.assertIsNone( b.place_item(board_items.Wall(value=10, inventory_space=1), 1, 3)) self.assertIsNone( b.place_item( board_items.GenericStructure(value=10, inventory_space=1), 1, 4)) self.assertIsNone( b.place_item( board_items.GenericActionableStructure(value=10, inventory_space=1), 1, 5, )) self.assertIsNone( b.place_item( board_items.Door(value=10, inventory_space=1, sprixel=core.Sprixel("#")), 2, 2, )) self.assertIsNone( b.place_item(board_items.Treasure(value=10, inventory_space=1), 1, 6)) with self.assertRaises(base.PglInvalidTypeException): g.neighbors("2") with self.assertRaises(base.PglInvalidTypeException): g.neighbors(2, "crash") g.object_library.append(board_items.NPC()) self.assertIsNone( g.save_board(1, "test-pygamelib.engine.Game.lvl1.json")) with self.assertRaises(base.PglInvalidTypeException): g.save_board("1", "test-pygamelib.engine.Game.lvl1.json") with self.assertRaises(base.PglInvalidTypeException): g.save_board(1, 1) with self.assertRaises(base.PglInvalidLevelException): g.save_board(11, "test-pygamelib.engine.Game.lvl1.json") self.assertIsInstance( g.load_board("test-pygamelib.engine.Game.lvl1.json", 1), engine.Board) self.assertEqual(g._string_to_constant("UP"), constants.UP) self.assertEqual(g._string_to_constant("DOWN"), constants.DOWN) self.assertEqual(g._string_to_constant("LEFT"), constants.LEFT) self.assertEqual(g._string_to_constant("RIGHT"), constants.RIGHT) self.assertEqual(g._string_to_constant("DRUP"), constants.DRUP) self.assertEqual(g._string_to_constant("DRDOWN"), constants.DRDOWN) self.assertEqual(g._string_to_constant("DLUP"), constants.DLUP) self.assertEqual(g._string_to_constant("DLDOWN"), constants.DLDOWN)
def test_serialization(self): class Bork(pgl_board_items.Wall): def __init__(self, **kwargs): super().__init__(**kwargs) b = pgl_engine.Board(ui_board_void_cell_sprixel=gfx_core.Sprixel( " ", gfx_core.Color(0, 0, 0))) b.place_item(pgl_board_items.Wall(), 2, 2) b.place_item(TestItem(), 4, 4) data = b.serialize() self.assertIsNotNone(data) self.assertIsNone(pgl_engine.Board.load(None)) bl = pgl_engine.Board.load(data) self.assertEqual(b.player_starting_position, bl.player_starting_position) self.assertEqual(b.name, bl.name) self.assertEqual(b.ui_board_void_cell, bl.ui_board_void_cell) self.assertIsInstance(b.item(2, 2), pgl_board_items.Wall) self.assertEqual(b.item(2, 2).model, bl.item(2, 2).model) data["map_data"]["(2, 2, 0)"]["object"] = "<'=bork.bork'>" with self.assertRaises(SyntaxError): pgl_engine.Board.load(data) b.place_item(Bork(), 6, 6) with self.assertRaises(SyntaxError): pgl_engine.Board.load(b.serialize())
def change_level(params): next_level_wave_obj.play() game = params[0] board = engine.Board( size=[250, 30], ui_borders="", ui_board_void_cell=bg_color + " " + graphics.Style.RESET_ALL, player_starting_position=[25, 0], DISPLAY_SIZE_WARNINGS=False, ) board.ui_border_bottom = graphics.Models.RADIOACTIVE + " " board.sprouted_count = 0 # Let's use a nice curve to increase the trap number. board.available_traps = int(10 + 10 * g.current_level * 0.2) board.max_traps_number = board.available_traps for i in range(0, board.size[0]): board.place_item( board_items.Wall( model=block_color() + " " + graphics.Style.RESET_ALL, type="platform" ), board.size[1] - 1, i, ) generate_level(game, board) game.score += 50 * game.current_level new_level = game.current_level + 1 game.add_board(new_level, board) game.change_level(new_level) game.move_player(constants.RIGHT, 3) game.player.last_y = game.player.pos[0] game.player.last_x = game.player.pos[1] g.player.max_y = g.player.pos[0] g.player.dy = gravity_speed g.obj_stack = []
def sprout(p, *args): # if p.parent is None: # return None if p is not None: o = board_items.Wall( model=bg_color + graphics.Models.DECIDUOUS_TREE + graphics.Style.RESET_ALL, type="sprouted_trees", ) o.pos = p.pos # board_items.Projectile is own by the Board by default. # Board is owned by the Game object. if p.parent is not None and p.parent.parent is not None: p.parent.sprouted_count += 1 o.age = p.parent.sprouted_count p.parent.parent.obj_stack.append(o)
def test_get_objects(self): b = pgl_engine.Board( name="test_board", size=[10, 10], player_starting_position=[0, 0], ) for i in range(1, 4): b.place_item(pgl_board_items.NPC(name=f"mover{i}", type="mover"), 0, i) for i in range(1, 4): b.place_item(pgl_board_items.Wall(name=f"static{i}", type="static"), i, 0) ret = b.get_immovables(type="static") self.assertEqual(len(ret), 3) self.assertEqual(len(ret), len(b.get_immovables())) ret = b.get_movables(type="static") self.assertEqual(len(ret), 0) ret = b.get_movables(type="mover") self.assertEqual(len(ret), 3) self.assertEqual(len(ret), len(b.get_movables()))
def make_platform(b, row, column): psize = random.randint(2, 10) plateform = [] tmp_game = engine.Game() # Only because Game needs it, we don't care. tmp_game.player = board_items.Player() tmp_game.add_board(0, b) tmp_game.change_level(0) # print( # f"[d] make_platform at {row}, {column}, psize is {psize} column will be " # f"between {column} and {column + psize + 1}" # ) get_up = 0 # for i in range(column, column + psize + 1): for i in range(column - psize - 1, column): if i >= b.size[0]: break if not isinstance(b.item(row, i), board_items.BoardItemVoid): break if i in b.visited_columns: break # Check if we have other platforms around. # If yes moving the platform up. if get_up < 3: for e in tmp_game.neighbors(2, board_items.Door(pos=[row, i])): if e.type == "ground": get_up = 3 break if get_up < 4: for e in tmp_game.neighbors(1, board_items.Door(pos=[row, i])): if e.type == "ground": get_up = 4 break m = block_color() + " " + graphics.Style.RESET_ALL plateform.append( [board_items.Wall(model=m, item_type="platform"), row, i]) for i in plateform: b.place_item(i[0], i[1] - get_up, i[2]) if random.choice([True, False]): generate_treasure(b, i[1] - get_up - 1, i[2]) else: generate_trap(b, i[1] - get_up - 1, i[2]) b.visited_columns.append(i[2])
def test_projectile_management(self): def _hit(p, t, ex): if len(ex) > 0: ex[0].stop() def _fake_hit(p, t, ex): pass def _upd(g, i, dt): pass b = engine.Board() g = engine.Game(user_update=_upd) g.player = constants.NO_PLAYER self.assertIsNone(g.add_board(1, b)) g.change_level(1) p = board_items.Projectile(hit_model="*", hit_callback=_fake_hit, callback_parameters=[g]) p.actuator = None p.step = None self.assertIsNone(g.add_projectile(1, p, 1, 1)) self.assertIsNone(g.add_projectile(1, board_items.Projectile(), 1, 100)) b.place_item(board_items.Wall(), 5, 5) b.place_item(board_items.Wall(), 1, 3) p2 = board_items.Projectile(hit_model="*", hit_callback=_fake_hit, callback_parameters=[g]) p2.set_direction(constants.LEFT) g.add_projectile(1, p2, 1, 5) g.add_projectile( 1, board_items.Projectile(hit_model="*", hit_callback=_hit, callback_parameters=[g]), 8, 1, ) g.add_projectile( 1, board_items.Projectile( hit_model="*", hit_callback=_fake_hit, callback_parameters=[g], range=3, is_aoe=True, ), 9, 1, ) self.assertIsNone( g.add_projectile(1, board_items.Projectile(hit_callback=_hit), 5, 5)) self.assertIsNone( g.add_projectile( 1, board_items.Projectile(hit_callback=_hit, is_aoe=True), 5, 5)) with self.assertRaises(base.PglInvalidTypeException): g.add_projectile(1, board_items.Projectile(), "1") with self.assertRaises(base.PglInvalidTypeException): g.add_projectile(1, board_items.Projectile(), None, "1") with self.assertRaises(base.PglInvalidTypeException): g.add_projectile(1, board_items.Projectile(), 1, "1") with self.assertRaises(base.PglInvalidTypeException): g.add_projectile(1, board_items.Projectile(), "1", 1) with self.assertRaises(base.PglInvalidTypeException): g.add_projectile(1, 1) with self.assertRaises(base.PglInvalidTypeException): g.add_projectile("1", board_items.NPC()) self.assertIsNone(g.actuate_projectiles(1)) g.mode = constants.MODE_RT g.start() self.assertIsNone(g.actuate_projectiles(1)) with self.assertRaises(base.PglInvalidLevelException): g.actuate_projectiles(99) with self.assertRaises(base.PglInvalidTypeException): g.actuate_projectiles("1") g.run()
def test_screen_buffer(self): sprites_panda = SpriteCollection.load_json_file("tests/panda.spr") b = engine.Board(size=[20, 20]) s = engine.Screen() # This is a dirty hack for CircleCI as it returns a 0x0 screen size. if s.width <= 0 or s.height <= 0: s._display_buffer = np.array( [[Sprixel(" ") for i in range(0, 50, 1)] for j in range(0, 50, 1)] ) s._screen_buffer = np.array( [[Sprixel(" ") for i in range(0, 50, 1)] for j in range(0, 50, 1)] ) # Because CircleCI return a console with no size (most probably because we are # not attached to any terminal), we need to make sure that the partial display # tests work in that environment too screen_width = 0 screen_height = 0 if s.width <= 0: screen_width = 50 else: screen_width = s.width if s.height <= 0: screen_height = 50 else: screen_height = s.height self.assertEqual(s.vcenter, int(s.height / 2)) self.assertEqual(s.hcenter, int(s.width / 2)) b.place_item(board_items.Tile(sprite=sprites_panda["panda"]), 0, 0) self.assertIsInstance(b.render_cell(1, 1), Sprixel) b.item(19, 19).model = "@" b.item(19, 19).sprixel = None self.assertIsInstance(b.render_cell(19, 19), Sprixel) self.assertEqual(b.render_cell(19, 19), Sprixel()) with self.assertRaises(base.PglOutOfBoardBoundException): b.render_cell(50, 50) self.assertIsNone(s.clear_buffers()) self.assertIsNone(s.clear_screen_buffer()) # And again after clear buffers. if s.width <= 0 or s.height <= 0: s._display_buffer = np.array( [[Sprixel(" ") for i in range(0, 50, 1)] for j in range(0, 50, 1)] ) s._screen_buffer = np.array( [[Sprixel(" ") for i in range(0, 50, 1)] for j in range(0, 50, 1)] ) self.assertTrue(s._is_dirty) self.assertTrue(functions.pgl_isinstance(s.buffer, "numpy.ndarray")) self.assertIsNone(s.update()) b = engine.Board(size=[1, 1]) b.place_item(board_items.Wall(model="##"), 0, 0) self.assertIsNone(s.place("test", 0, 0)) self.assertIsNone(s.place(b, 1, 0)) t = base.Text("test 2") self.assertIsNone(s.place(t, 2, 0)) self.assertIsNone(s.place(sprites_panda["panda"], 0, 5)) self.assertIsNone(s.place(TB(), 3, 0)) self.assertIsNone(s.place(board_items.BoardItem(model="##"), 10, 0)) self.assertIsNone( s.place( board_items.Tile( sprixels=[ [Sprixel("##"), Sprixel("##")], [Sprixel("##"), Sprixel("##")], ] ), 4, 0, ) ) with self.assertRaises(base.PglInvalidTypeException): s.place(None, 0, 0) with self.assertRaises(base.PglInvalidTypeException): s.place(1, 0, 0) s.update() t.text = "update" self.assertIsNone( s.place(sprites_panda["panda"], screen_height - 2, screen_width - 2) ) self.assertIsNone(s.place("test", 1, screen_width - 2)) s.update() self.assertIsNone(s.render()) # Should not render self.assertFalse(s.need_rendering) s.trigger_rendering() self.assertTrue(s.need_rendering) # Now testing partial display camera = board_items.Camera() camera.row = 0 camera.column = 0 b = engine.Board( size=[screen_width * 2, screen_height * 2], enable_partial_display=True, partial_display_viewport=[ int(screen_height / 2) - 1, int(screen_width / 2) - 1, ], partial_display_focus=camera, DISPLAY_SIZE_WARNINGS=False, ) for row in range(0, b.height): for col in range(0, b.width): b.place_item( board_items.Wall( sprixel=Sprixel(" ", Color(row * 4, col, int((row + col) / 2))), ), row, col, ) self.assertIsNone(s.place(b, 0, 0, 2)) s.trigger_rendering() self.assertIsNone(s.update()) b.partial_display_viewport = [ int(screen_height * 3) - 1, int(screen_width * 3) - 1, ] camera.row += 1 with self.assertRaises(IndexError): s.force_render() s.update() b.partial_display_viewport = [ int(screen_height / 2) - 1, int(screen_width / 2) - 1, ] camera.row = b.height - 1 camera.column = b.width - 1 self.assertIsNone(s.trigger_rendering()) self.assertIsNone(s.update()) camera = board_items.Tile( sprite=Sprite( sprixels=[[Sprixel("+"), Sprixel("+")], [Sprixel("+"), Sprixel("+")]] ) ) b.partial_display_focus = camera # Please never do that in real life... camera.pos = [1, 1] self.assertIsNone(s.trigger_rendering()) self.assertIsNone(s.render()) self.assertIsNone(s.update()) # This will succeed but the str type cannot benefit from deferred rendering. self.assertIsNone(s.place("test delete", 0, 0, 2)) self.assertIsNone(s.update()) self.assertIsNone(s.delete(0, 0)) self.assertIsNone(s.update())
global g g.clear_screen() nb_blocks = int((g.player.mp / g.player.max_mp) * 20) print("Mana [" + graphics.BLUE_RECT * nb_blocks + graphics.BLACK_RECT * (20 - nb_blocks) + "]") g.display_board() # manage_fireballs() b = engine.Board( ui_borders=graphics.WHITE_SQUARE, ui_board_void_cell=graphics.BLACK_SQUARE, size=[20, 20], player_starting_position=[5, 5], ) wall = board_items.Wall(model=graphics.Models.BRICK) b.place_item(wall, 1, 6) g = engine.Game() g.add_board(1, b) g.player = board_items.Player(model=graphics.Models.MAGE, name="The Maje") g.player.mp = 20 g.player.max_mp = 20 g.change_level(1) key = None black_circle = "-\U000025CF" circle_jot = "-\U0000233E" throw_fireball = False projectile = board_items.Projectile()
def test_tools_function(self): b = engine.Board() g = engine.Game() g.player = constants.NO_PLAYER self.assertIsNone(g.add_board(1, b)) self.assertIsNone(g.change_level(1)) self.assertIsNone( g.add_npc(1, board_items.NPC(value=10, inventory_space=1), 1, 1)) tmp_npc = g.get_board(1).item(1, 1) tmp_npc.actuator = actuators.PathFinder(game=g, actuated_object=tmp_npc) tmp_npc.actuator.set_destination(2, 5) tmp_npc.actuator.find_path() self.assertIsNone( b.place_item(board_items.Door(value=10, inventory_space=1), 1, 2)) self.assertIsNone( b.place_item(board_items.Wall(value=10, inventory_space=1), 1, 3)) self.assertIsNone( b.place_item( board_items.GenericStructure(value=10, inventory_space=1), 1, 4)) self.assertIsNone( b.place_item( board_items.GenericActionableStructure(value=10, inventory_space=1), 1, 5, )) self.assertIsNone( b.place_item( board_items.Door(value=10, inventory_space=1, sprixel=core.Sprixel("#")), 2, 2, )) self.assertIsNone( b.place_item(board_items.Treasure(value=10, inventory_space=1), 1, 6)) with self.assertRaises(base.PglInvalidTypeException): g.neighbors("2") with self.assertRaises(base.PglInvalidTypeException): g.neighbors(2, "crash") g.object_library.append(board_items.NPC()) self.assertIsNone( g.save_board(1, "test-pygamelib.engine.Game.lvl1.json")) with self.assertRaises(base.PglInvalidTypeException): g.save_board("1", "test-pygamelib.engine.Game.lvl1.json") with self.assertRaises(base.PglInvalidTypeException): g.save_board(1, 1) with self.assertRaises(base.PglInvalidLevelException): g.save_board(11, "test-pygamelib.engine.Game.lvl1.json") self.assertIsInstance( g.load_board("test-pygamelib.engine.Game.lvl1.json", 1), engine.Board) self.assertEqual(g._string_to_constant("UP"), constants.UP) self.assertEqual(g._string_to_constant("DOWN"), constants.DOWN) self.assertEqual(g._string_to_constant("LEFT"), constants.LEFT) self.assertEqual(g._string_to_constant("RIGHT"), constants.RIGHT) self.assertEqual(g._string_to_constant("DRUP"), constants.DRUP) self.assertEqual(g._string_to_constant("DRDOWN"), constants.DRDOWN) self.assertEqual(g._string_to_constant("DLUP"), constants.DLUP) self.assertEqual(g._string_to_constant("DLDOWN"), constants.DLDOWN) with self.assertRaises(base.PglInvalidTypeException): g.delete_level() with self.assertRaises(base.PglInvalidLevelException): g.delete_level(42) g.delete_level(1) g.delete_all_levels() self.assertIsNone(g.current_board()) bi = board_items.Door( value=10, inventory_space=0, pickable=False, overlappable=True, restorable=True, ) obj = engine.Game._ref2obj(bi.serialize()) self.assertIsInstance(obj, board_items.Door) bi = board_items.Treasure( value=10, inventory_space=0, pickable=False, overlappable=True, restorable=True, ) obj = engine.Game._ref2obj(bi.serialize()) self.assertIsInstance(obj, board_items.Treasure) bi = board_items.GenericActionableStructure( value=10, inventory_space=0, pickable=False, overlappable=True, restorable=True, ) obj = engine.Game._ref2obj(bi.serialize()) self.assertIsInstance(obj, board_items.GenericActionableStructure) bi = board_items.NPC( value=10, inventory_space=10, pickable=False, overlappable=True, restorable=True, ) bi.actuator = actuators.PathActuator(path=[constants.UP]) obj = engine.Game._ref2obj(bi.serialize()) self.assertIsInstance(obj, board_items.NPC) bi.actuator = actuators.PatrolActuator(path=[constants.UP]) obj = engine.Game._ref2obj(bi.serialize()) self.assertIsInstance(obj.actuator, actuators.PatrolActuator)
def test_screen_buffer(self): sprites_panda = SpriteCollection.load_json_file("tests/panda.spr") b = engine.Board(size=[20, 20]) s = engine.Screen(50, 50) # Because CircleCI return a console with no size (most probably because we are # not attached to any terminal), we need to make sure that the partial display # tests work in that environment too screen_width = 0 screen_height = 0 if s.width <= 0: screen_width = 50 else: screen_width = s.width if s.height <= 0: screen_height = 50 else: screen_height = s.height self.assertEqual(s.vcenter, int(s.height / 2)) self.assertEqual(s.hcenter, int(s.width / 2)) b.place_item(board_items.Tile(sprite=sprites_panda["panda"]), 0, 0) self.assertIsInstance(b.render_cell(1, 1), Sprixel) b.item(19, 19).model = "@" b.item(19, 19).sprixel = None self.assertIsInstance(b.render_cell(19, 19), Sprixel) self.assertEqual(b.render_cell(19, 19), Sprixel()) b.place_item(board_items.Door(), 19, 19) b.place_item( board_items.Door(sprixel=Sprixel( "*", Color(125, 125, 0), is_bg_transparent=False)), 19, 19, ) b.place_item( board_items.Door(sprixel=Sprixel("#", is_bg_transparent=True)), 19, 19) b.place_item( board_items.NPC(sprixel=Sprixel("$", is_bg_transparent=True)), 19, 19) self.assertEqual(b.layers(19, 19), 4) b.place_item( board_items.BoardItemVoid(sprixel=Sprixel(is_bg_transparent=True)), 19, 19) b.place_item( board_items.BoardItemVoid(sprixel=Sprixel(is_bg_transparent=True)), 19, 19) self.assertIsInstance(b.render_cell(19, 19), Sprixel) b._clean_layers(19, 19) self.assertEqual(b.layers(19, 19), 3) b._clean_layers(18, 19) self.assertEqual(b.layers(18, 19), 1) with self.assertRaises(base.PglOutOfBoardBoundException): b.render_cell(50, 50) self.assertIsNone(s.clear_buffers()) self.assertIsNone(s.clear_screen_buffer()) self.assertTrue(s._is_dirty) self.assertTrue(functions.pgl_isinstance(s.buffer, "numpy.ndarray")) self.assertIsNone(s.update()) b = engine.Board(size=[1, 1]) b.place_item(board_items.Wall(model="##"), 0, 0) self.assertIsNone(s.place("test", 0, 0)) self.assertIsNone(s.place(b, 1, 0)) self.assertIsInstance(s.get(1, 0), engine.Board) t = base.Text("test 2") self.assertIsNone(s.place(t, 2, 0)) self.assertIsNone(s.place(sprites_panda["panda"], 0, 5)) self.assertIsNone(s.place(TB(), 3, 0)) self.assertIsNone(s.place(board_items.BoardItem(model="##"), 10, 0)) self.assertIsNone( s.place( board_items.Tile(sprite=Sprite(sprixels=[ [Sprixel("##"), Sprixel("##")], [Sprixel("##"), Sprixel("##")], ])), 4, 0, )) self.assertIsNone( s.place( Sprite(sprixels=[ [Sprixel("##"), Sprixel("##")], [Sprixel("###"), Sprixel("##")], ]), 8, 0, )) s.force_render() with self.assertRaises(base.PglInvalidTypeException): s.place(None, 0, 0) with self.assertRaises(base.PglInvalidTypeException): s.place(1, 0, 0) with self.assertRaises(base.PglException): s.place(TB(), 400, 0) with self.assertRaises(base.PglException): s.place(TB(), 0, 400) s.force_update() t.text = "update" self.assertIsNone( s.place(sprites_panda["panda"], screen_height - 2, screen_width - 2)) self.assertIsNone(s.place("test", 1, screen_width - 2)) s.update() self.assertIsNone(s.render()) # Should not render self.assertFalse(s.need_rendering) s.trigger_rendering() self.assertTrue(s.need_rendering) # Now testing partial display camera = board_items.Camera() camera.row = 0 camera.column = 0 b = engine.Board( size=[screen_width * 2, screen_height * 2], enable_partial_display=True, partial_display_viewport=[ int(screen_height / 2) - 1, int(screen_width / 2) - 1, ], partial_display_focus=camera, DISPLAY_SIZE_WARNINGS=False, ) for row in range(0, b.height): for col in range(0, b.width): b.place_item( board_items.Wall(sprixel=Sprixel( " ", Color(row * 4, col, int((row + col) / 2))), ), row, col, ) self.assertIsNone(s.place(b, 0, 0, 2)) s.trigger_rendering() self.assertIsNone(s.update()) b.partial_display_viewport = [ int(screen_height / 2) - 1, int(screen_width / 2) - 1, ] camera.row = b.height - 1 camera.column = b.width - 1 self.assertIsNone(s.trigger_rendering()) self.assertIsNone(s.update()) camera = board_items.Tile( sprite=Sprite(sprixels=[[Sprixel("+"), Sprixel("+")], [Sprixel("+"), Sprixel("+")]])) b.partial_display_focus = camera # Please never do that in real life... camera.pos = [1, 1] self.assertIsNone(s.trigger_rendering()) self.assertIsNone(s.render()) self.assertIsNone(s.update()) # This will succeed but the str type cannot benefit from deferred rendering. self.assertIsNone(s.place("test delete", 0, 0, 2)) self.assertIsNone(s.update()) self.assertIsNone(s.delete(0, 0)) self.assertIsNone(s.update()) self.assertIsNone( functions.render_string_to_buffer( "hello", s._display_buffer, 0, 0, s._display_buffer.shape[0], s._display_buffer.shape[1], )) # This test has nothing to do here... but I'm lazy. self.assertEqual(5, functions.clamp(5, 0, 10)) self.assertEqual(0, functions.clamp(-5, 0, 10)) self.assertEqual(10, functions.clamp(15, 0, 10)) # This one either and it's even worst: it's going to disappear! t = base.Text("this is a text\non multiple lines") t.render_to_buffer( s._display_buffer, s._display_buffer.shape[0] - 1, s._display_buffer.shape[1] - 5, s._display_buffer.shape[0], s._display_buffer.shape[1], ) s.update() t = base.Text( "this is a text", Color(0, 0, 0), Color(255, 255, 255), font=Font("8bits"), ) t.render_to_buffer( s._display_buffer, s._display_buffer.shape[0] - 1, s._display_buffer.shape[1] - 5, s._display_buffer.shape[0], s._display_buffer.shape[1], ) s.update()
life_heart = board_items.GenericActionableStructure(model=sprite_heart, name="life_100") life_heart.set_overlappable(True) life_heart.action = add_hp life_heart.action_parameters = [game, 100] life_heart_minor = board_items.GenericActionableStructure( model=sprite_heart_minor, name="life_25") life_heart_minor.set_overlappable(True) life_heart_minor.action = add_hp life_heart_minor.action_parameters = [game, 25] game.player = p # Adding walls to level 1 lvl1.place_item(board_items.Wall(model=sprite_wall), 2, 3) lvl1.place_item(board_items.Wall(model=sprite_wall), 2, 2) lvl1.place_item(board_items.Wall(model=sprite_wall), 2, 1) lvl1.place_item(board_items.Wall(model=sprite_wall), 2, 0) lvl1.place_item(board_items.Wall(model=sprite_wall), 3, 3) lvl1.place_item(board_items.Wall(model=sprite_wall), 4, 3) lvl1.place_item(board_items.Wall(model=sprite_wall), 5, 3) lvl1.place_item(board_items.Wall(model=sprite_wall), 6, 3) lvl1.place_item(board_items.Wall(model=sprite_wall), 6, 2) lvl1.place_item(board_items.Wall(model=sprite_wall), 6, 1) lvl1.place_item(board_items.Wall(model=sprite_wall), 7, 1) lvl1.place_item(board_items.Wall(model=sprite_wall), 8, 1) lvl1.place_item(board_items.Wall(model=sprite_wall), 8, 3) lvl1.place_item(board_items.Wall(model=sprite_wall), 9, 3) lvl1.place_item(board_items.Wall(model=sprite_wall), 10, 3) lvl1.place_item(board_items.Wall(model=sprite_wall), 10, 2)
def test_pathfinder_bfs(self): npc = board_items.NPC() b = engine.Board() g = engine.Game() g.player = board_items.Player() g.add_board(1, b) g.add_npc(1, npc, 5, 5) g.change_level(1) actuators.PathFinder(actuated_object=npc) npc.actuator = actuators.PathFinder(parent=npc, game=g, circle_waypoints=False) with self.assertRaises(engine.base.PglInvalidTypeException): actuators.PathFinder( parent=npc, game=g, circle_waypoints=False, algorithm="constants.ALGO_BFS" ) npc.actuator.set_destination(2, 2) npc.actuator.find_path() self.assertTrue(len(npc.actuator.current_path()) > 0) with self.assertRaises(engine.base.PglInvalidTypeException): npc.actuator.set_destination("2", 2) npc.actuator.actuated_object = None with self.assertRaises(engine.base.PglException) as e: npc.actuator.find_path() self.assertEqual(e.error, "actuated_object is not defined") npc.actuator.actuated_object = board_items.Door() with self.assertRaises(engine.base.PglException) as e: npc.actuator.find_path() self.assertEqual(e.error, "actuated_object not a Movable object") npc.actuator.actuated_object = board_items.Door() npc.actuator.actuated_object = npc npc.actuator.destination = None with self.assertRaises(engine.base.PglException) as e: npc.actuator.find_path() self.assertEqual(e.error, "destination is not defined") b.place_item(board_items.Wall(), 2, 2) npc.actuator.set_destination(2, 2) self.assertEqual(npc.actuator.find_path(), []) # These tests are a recipe of how to NOT do things... npc.actuator.destination = (None, None) self.assertEqual(npc.actuator.next_move(), constants.NO_DIR) npc.actuator.set_destination(5, 5) npc.actuator._current_path = [] npc.actuator.next_move() npc.actuator.set_destination(2, 5) npc.actuator._current_path = [] nm = npc.actuator.next_move() self.assertEqual(nm, constants.UP) npc.actuator.add_waypoint(5, 6) npc.actuator.add_waypoint(6, 6) npc.actuator.add_waypoint(5, 4) npc.actuator.add_waypoint(4, 6) nm = None while nm != constants.NO_DIR: nm = npc.actuator.next_move() b.move(npc, nm, npc.step) with self.assertRaises(engine.base.PglInvalidTypeException): npc.actuator.add_waypoint(5, "6") with self.assertRaises(engine.base.PglInvalidTypeException): npc.actuator.add_waypoint("5", 6) npc.actuator.clear_waypoints() self.assertEqual(npc.actuator.next_waypoint(), (None, None)) npc.actuator.clear_waypoints() npc.actuator.destination = (None, None) npc.actuator.add_waypoint(10, 10) npc.actuator.add_waypoint(12, 15) self.assertEqual(npc.actuator.destination, (10, 10)) self.assertEqual(npc.actuator.next_waypoint(), (10, 10)) self.assertEqual(npc.actuator.next_waypoint(), (12, 15)) self.assertEqual(npc.actuator.next_waypoint(), (None, None)) npc.actuator.circle_waypoints = True self.assertEqual(npc.actuator.next_waypoint(), (10, 10)) with self.assertRaises(engine.base.PglInvalidTypeException): npc.actuator.remove_waypoint(10, "10") with self.assertRaises(engine.base.PglInvalidTypeException): npc.actuator.remove_waypoint("10", 10) with self.assertRaises(engine.base.PglException) as e: npc.actuator.remove_waypoint(30, 30) self.assertEqual(e.error, "invalid_waypoint") self.assertIsNone(npc.actuator.remove_waypoint(10, 10))
def generate_level(g, b): # When we get the map, the last row is full of blocks last_alt = b.size[1] - 1 gap = 0 gap_threshold = 2 b.visited_columns = [] # We keep a count of the treasures we can put on the map as well as the rate we # can put them on (in percent). There is no possibility that we will end up with # more items, but there is a small possibility that we end up with less b.treasures = { "timers": { "count": int(math.log(g.current_level + 1)), "rate": 10, "placed": 0, }, "scorers": { "count": 1 + int(math.log(g.current_level + 1)), "rate": 10, "placed": 0, }, "1UP": {"count": 1, "rate": int(math.log(g.current_level + 1)), "placed": 0}, "diamond": {"count": 1, "rate": 2, "placed": 0}, } # We go through all the column of the map. for x in range(5, b.size[0]): # print(f"[d] generate level x={x}") # We have 50% chance of putting an obstacle. if random.choice([True, False]): if gap > gap_threshold: for k in range(x - gap, x): b.clear_cell(b.size[1] - 1, k) alt = random.randint(last_alt - 2, b.size[1] - 1) last_alt = alt y = 0 for y in range(alt + 1, b.size[1] - 1): # print(f"[d] generate level y={y}") b.place_item( board_items.Wall( model=block_color() + " " + graphics.Style.RESET_ALL, type="ground", ), y, x, ) # generate_treasure(b, y - 1, x) # For the fun of it and also to break monotony we have 20% of chance # of placing a platform here (of random size). We'll put treasures on # them later. if random.randint(0, 100) >= 80: make_platform(b, last_alt - random.randint(2, 3), x) # if y < b.size[1] - 1: # generate_trap(b, alt, x) # Just to break monotony, we have 33% chance of putting a cloud # in the background if random.randint(0, 100) >= 66: b.place_item( board_items.Door( model=bg_color + "\U00002601 " + graphics.Style.RESET_ALL ), alt - 8 + random.randint(-2, 2), x, ) gap = 0 else: # If we didn't put an obstacle, we keep track of the gap we're leaving. # When the gap is spreading over a threshold, we have 50% chance of # emptying it (we make a pit) gap += 1 b.place_item( board_items.GenericActionableStructure( model=bg_color + graphics.Models.CYCLONE + graphics.Style.RESET_ALL, type="exit", action=change_level, action_parameters=[g], ), last_alt - 1, b.size[0] - 1, ) # The map is done, let's add treasures and traps. # we travel the map once again and look for openings idx = 0 while b.available_traps > 0 or idx < 10: for col in range(5, b.size[0]): if random.choice([True, False]): candidates = [] for row in range(0, b.size[1]): item = b.item(row, col) # We only put treasures and traps on the ground if ( not isinstance(item, board_items.BoardItemVoid) and item.type == "ground" ): # We want at least 2 free cells in all directions (except down) free_cells = [ (row - 1, col), (row - 2, col), (row - 1, col - 1), (row - 1, col - 2), (row - 2, col - 1), (row - 2, col - 2), (row - 1, col + 1), (row - 1, col + 2), (row - 2, col + 1), (row - 2, col + 2), ] good_candidate = True for coord in free_cells: if coord[0] >= b.size[1] or coord[1] >= b.size[0]: continue cell = b.item(coord[0], coord[1]) if not isinstance(cell, board_items.BoardItemVoid): good_candidate = False break if good_candidate: candidates.append(item) for c in candidates: generate_trap(b, c.pos[0], c.pos[1]) idx += 1 idx = 0 while True: for col in range(5, b.size[0]): if random.choice([True, False]): candidates = [] for row in range(0, b.size[1]): item = b.item(row, col) # We only put treasures and traps on the ground if ( not isinstance(item, board_items.BoardItemVoid) and item.type == "ground" ): # We want at least 2 free cells in all directions (except down) free_cells = [ (row - 1, col), (row - 2, col), (row - 1, col - 1), (row - 1, col - 2), (row - 2, col - 1), (row - 2, col - 2), (row - 1, col + 1), (row - 1, col + 2), (row - 2, col + 1), (row - 2, col + 2), ] good_candidate = True for coord in free_cells: if coord[0] >= b.size[1] or coord[1] >= b.size[0]: continue cell = b.item(coord[0], coord[1]) if not isinstance(cell, board_items.BoardItemVoid): good_candidate = False break if good_candidate: candidates.append(item) for c in candidates: generate_trap(b, c.pos[0], c.pos[1]) idx += 1 if b.treasures["scorers"]["count"] <= 0 and b.treasures["timers"]["count"] <= 0: break if idx == 10: break
def test_wall(self): bi = board_items.Wall() self.assertFalse(bi.pickable()) self.assertFalse(bi.overlappable()) self.assertFalse(bi.restorable())
# First let's create a Board that uses squares as delimiters # Borders are going to be white squares # Cells with nothing inside are going to be black squares myboard = engine.Board( name="A demo board", size=[40, 20], ui_border_left=graphics.WHITE_SQUARE, ui_border_right=graphics.WHITE_SQUARE, ui_border_top=graphics.WHITE_SQUARE, ui_border_bottom=graphics.WHITE_SQUARE, ui_board_void_cell=graphics.BLACK_SQUARE, player_starting_position=[10, 20], ) # Now let's make a couple of walls using colored squares as models green_wall = board_items.Wall(model=graphics.GREEN_SQUARE) blue_wall = board_items.Wall(model=graphics.BLUE_SQUARE) cyan_wall = board_items.Wall(model=graphics.CYAN_SQUARE) magenta_wall = board_items.Wall(model=graphics.MAGENTA_SQUARE) # Now let's place these walls on the board for k in range(1, 6, 1): myboard.place_item(green_wall, 1, k) myboard.place_item(magenta_wall, k, 6) for k in range(2, 6, 1): myboard.place_item(blue_wall, k, 1) myboard.place_item(cyan_wall, 5, k) # And just for the fun of it, let's place a yellow and cyan wall # in the middle of that "structure"