def test_trapseed_does_not_become_venus_after_10_moves_on_top_of_only_hive(): turn_num = 12345 game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(9, 5), ), ), flowers=((), ), turn_num=turn_num, game_length=sentinel.game_length) game.boards[0].inflight[sentinel.seed_1] = TrapSeed( 9, 8, 0, mock_game_params.trap_seed_lifespan) for _ in range(DEFAULT_GAME_PARAMETERS.trap_seed_lifespan + 1): game.turn([None]) assert { vid: volant for (vid, volant) in game.boards[0].inflight.items() if not isinstance(volant, Bee) } == { sentinel.seed_1: TrapSeed(9, 5, 0, -1) } assert game.boards[0].flowers == () assert game.boards[0].hives == (Hive(9, 5), )
def test_apply_venus_command_over_existing_flower(): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(9, 9), ), ), flowers=((Flower(0, 0, DEFAULT_GAME_PARAMETERS, sentinel.potency, sentinel.visits), Flower(9, 9, DEFAULT_GAME_PARAMETERS, sentinel.potency, sentinel.visits)), ), turn_num=12345, game_length=sentinel.game_length) game.boards[0].inflight[sentinel.seed_1] = TrapSeed( 0, 0, 0, DEFAULT_GAME_PARAMETERS.trap_seed_lifespan) game.apply_commands([dict(entity=sentinel.seed_1, command="flower")]) assert game.boards[0].inflight == {} assert sorted(map(str, game.boards[0].flowers)) == sorted( map(str, (VenusBeeTrap( 0, 0, DEFAULT_GAME_PARAMETERS, 1, 0, expires=12345 + DEFAULT_GAME_PARAMETERS.flower_lifespan), Flower(9, 9, DEFAULT_GAME_PARAMETERS, sentinel.potency, sentinel.visits)))) assert game.boards[0].hives == (Hive(9, 9), )
def test_trapseed_becomes_venus_after_10_moves_on_top_of_a_hive(): turn_num = 12345 game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=(( Hive(9, 5), Hive(5, 5), ), ), flowers=((), ), turn_num=turn_num, game_length=sentinel.game_length) game.boards[0].inflight[sentinel.seed_1] = TrapSeed( 9, 8, 0, mock_game_params.trap_seed_lifespan) for _ in range(DEFAULT_GAME_PARAMETERS.trap_seed_lifespan + 1): game.turn([None]) assert not [(_, volant) for (_, volant) in game.boards[0].inflight.items() if isinstance(volant, TrapSeed)] assert game.boards[0].flowers == ((VenusBeeTrap( 9, 5, DEFAULT_GAME_PARAMETERS, expires=turn_num + DEFAULT_GAME_PARAMETERS.trap_seed_lifespan + DEFAULT_GAME_PARAMETERS.flower_lifespan)), ) assert game.boards[0].hives == (Hive(5, 5), )
def test_land_bees_do_not_land_bee_not_on_hive(): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(5, 5), ), ), flowers=((), ), game_length=sentinel.game_length) assert all( board.calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor for board in game.boards) game.boards[0].inflight[sentinel.bee_1] = Bee(5, 4, 0, 10, DEFAULT_GAME_PARAMETERS, 1) landed_bees = game.land_bees() assert all( board.calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor for board in game.boards) assert sentinel.bee_1 in game.boards[0].inflight assert landed_bees == [{}] assert game.boards[0].inflight == { sentinel.bee_1: Bee(5, 4, 0, 10, DEFAULT_GAME_PARAMETERS, 1) } assert check_bee_nectar_eq_hive_nectar(landed_bees, game)
def test_land_queenbees_single_queenbee_single_board_single_hive(): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(5, 5), ), ), flowers=((), ), game_length=sentinel.game_length) assert all( board.calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor for board in game.boards) game.boards[0].inflight[sentinel.bee_1] = QueenBee( 5, 5, 0, 10, DEFAULT_GAME_PARAMETERS, 1) landed_bees = game.land_bees() for board in game.boards: assert sentinel.bee_1 not in board.inflight assert [board.calculate_score() for board in game.boards] == [ DEFAULT_GAME_PARAMETERS.hive_score_factor + DEFAULT_GAME_PARAMETERS.dead_bee_score_factor ] assert landed_bees == [{ sentinel.bee_1: QueenBee(5, 5, 0, 10, DEFAULT_GAME_PARAMETERS, 1) }] assert game.boards[0].inflight == {}
def test_land_bees_single_queenbee_single_regular_bee_single_board_single_hive( ): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(5, 5), ), ), flowers=((), ), game_length=sentinel.game_length) assert all( board.calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor for board in game.boards) queen_bee = QueenBee(5, 5, 0, 10, DEFAULT_GAME_PARAMETERS, 1) bee = Bee(5, 5, 0, 10, DEFAULT_GAME_PARAMETERS, 1) both_bees = {sentinel.bee_1: queen_bee, sentinel.bee_2: bee} game.boards[0].inflight = both_bees.copy() landed_bees = game.land_bees() for board in game.boards: assert sentinel.bee_1 not in board.inflight assert sentinel.bee_2 not in board.inflight assert [board.calculate_score() for board in game.boards] == [ DEFAULT_GAME_PARAMETERS.hive_score_factor + DEFAULT_GAME_PARAMETERS.dead_bee_score_factor + bee.nectar * DEFAULT_GAME_PARAMETERS.nectar_score_factor ] assert landed_bees == [both_bees] assert game.boards[0].inflight == {} assert check_bee_nectar_eq_hive_nectar([{sentinel.bee_2: bee}], game)
def get_child(self, cmd): """ :param cmd: :return: child node """ board = LiteBoard(game_params=self.game_params, board_width=self.board_width, board_height=self.board_height, hives=[(Hive(*i)) for i in self.hives], flowers=[Flower.from_json(i) for i in self.flowers], inflight={volant_id: volant_from_json(volant) for volant_id, volant in self.inflight.items()}, dead_bees=self.dead_bees, seeds_to_gen=self.seeds_to_gen) board.make_turn(cmd, self.turn_num) board_json = board.to_json() board_json["turnNum"] = self.turn_num + 1 board_json["scoreParams"] = self.my_score_params board_json["cmd"] = cmd return self.gen_child(board_json, self.game_params, self.game_stage, self.adjacent_to_flowers, self.adjacent_to_hives)
def test_launch_bees_single_board_single_hive_probability_zero(): params = GameParameters(launch_probability=0.0, initial_energy=10, dead_bee_score_factor=-5, hive_score_factor=100, flower_score_factor=100, nectar_score_factor=2, queen_bee_nectar_threshold=20, bee_nectar_capacity=5, bee_energy_boost_per_nectar=25, flower_seed_visit_initial_threshold=10, flower_seed_visit_subsequent_threshold=10, flower_visit_potency_ratio=10, flower_lifespan=100, flower_lifespan_visit_impact=10, trap_seed_probability=1, venus_score_factor=-50, trap_seed_lifespan=10) game = GameState(game_params=params, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(5, 5), ), ), flowers=(sentinel.flowers, ), game_length=sentinel.game_length) assert len(game.boards[0].inflight) == 0 with patch("hiveminder.game_state.rngs", {sentinel.game_id: Random(0)}): game.launch_bees(sentinel.turn_num) assert len(game.boards[0].inflight) == 0
def detail_advance(board_width, board_height, hives, flowers, inflight, turn_num, cmd): board = Board(game_params=DEFAULT_GAME_PARAMETERS, board_width=board_width, board_height=board_height, hives=[Hive(*i) for i in hives], flowers=[Flower.from_json(i) for i in flowers], neighbours={ 'N': 1, 'S': 1, 'E': 1, 'W': 1, 'NW': 1, 'SE': 1, }, inflight={ volant_id: volant_from_json(volant) for volant_id, volant in inflight.items() }, dead_bees=0) board._connect_to_neighbours([board, _OtherBoard()]) board.apply_command(cmd, turn_num) board.remove_dead_flowers(turn_num) board.move_volants() lost = set(board.send_volants()) received = set(board.receive_volants()) board.visit_flowers(Random()) landed = set(board.land_bees()) crashed = {k: set(v) for k, v in board.detect_crashes().items()} return board.hives, board.flowers, board.inflight, crashed, landed, lost, received
def test_create_hive_deletes_flower(): queen_bee = QueenBee(1, 2, 0, 10, DEFAULT_GAME_PARAMETERS, nectar=sentinel.nectar) game = GameState( game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=[[]], flowers=[[Flower(queen_bee.x, queen_bee.y, DEFAULT_GAME_PARAMETERS)]], game_length=sentinel.game_length) game.boards[0].inflight[sentinel.queenbee_1] = queen_bee game.apply_commands( [dict(entity=sentinel.queenbee_1, command="create_hive")]) assert game.boards[0].hives[0] == Hive(queen_bee.x, queen_bee.y, queen_bee.nectar) assert len(game.boards[0].inflight) == 0 assert len(game.boards[0].flowers) == 0
def test_only_queenbees_can_create_hive(): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=[[]], flowers=[[Flower(1, 2, DEFAULT_GAME_PARAMETERS)]], game_length=sentinel.game_length) queen_bee = QueenBee(4, 4, 0, 10, DEFAULT_GAME_PARAMETERS, nectar=sentinel.nectar) game.boards[0].inflight[sentinel.bee_1] = Bee(4, 5, 0, 10, DEFAULT_GAME_PARAMETERS) game.boards[0].inflight[sentinel.queenbee_1] = queen_bee game.boards[0].inflight[sentinel.seed_1] = Seed(3, 3, 0) with pytest.raises(RuntimeError): game.apply_commands( [dict(entity=sentinel.bee_1, command="create_hive")]) with pytest.raises(RuntimeError): game.apply_commands( [dict(entity=sentinel.seed_1, command="create_hive")]) game.apply_commands( [dict(entity=sentinel.queenbee_1, command="create_hive")]) assert game.boards[0].hives[0] == Hive(queen_bee.x, queen_bee.y, queen_bee.nectar) assert len(game.boards[0].inflight) == 2
def test_land_bees_two_bees_single_board_single_hive(): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(5, 5), ), ), flowers=((), ), game_length=sentinel.game_length) assert all( board.calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor for board in game.boards) game.boards[0].inflight[sentinel.bee_1] = Bee(5, 5, 0, 10, DEFAULT_GAME_PARAMETERS, 1) game.boards[0].inflight[sentinel.bee_2] = Bee(5, 5, 0, 10, DEFAULT_GAME_PARAMETERS, 2) landed_bees = game.land_bees() for board in game.boards: assert sentinel.bee_1 not in board.inflight assert sentinel.bee_2 not in board.inflight assert [board.calculate_score() for board in game.boards] == [ DEFAULT_GAME_PARAMETERS.hive_score_factor + 3 * DEFAULT_GAME_PARAMETERS.nectar_score_factor ] assert landed_bees == [{ sentinel.bee_1: Bee(5, 5, 0, 10, DEFAULT_GAME_PARAMETERS, 1), sentinel.bee_2: Bee(5, 5, 0, 10, DEFAULT_GAME_PARAMETERS, 2) }] assert check_bee_nectar_eq_hive_nectar(landed_bees, game)
def from_json(cls, json): return cls(board_width=json["boardWidth"], board_height=json["boardHeight"], hives=tuple(Hive(*hive) for hive in json["hives"]), flowers=tuple( Flower.from_json(flower) for flower in json["flowers"]), inflight={ volant_id: volant_from_json(volant) for volant_id, volant in json["inflight"].items() }, dead_bees=json["deadBees"], seeds_to_gen=json["seedsToGen"])
def test_apply_venus_command_over_existing_single_hive(): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(9, 9), ), ), flowers=((Flower(0, 0, DEFAULT_GAME_PARAMETERS), ), ), turn_num=12345, game_length=sentinel.game_length) game.boards[0].inflight[sentinel.seed_1] = TrapSeed( 9, 9, 0, DEFAULT_GAME_PARAMETERS.trap_seed_lifespan) game.apply_commands([dict(entity=sentinel.seed_1, command="flower")]) assert game.boards[0].inflight == { sentinel.seed_1: TrapSeed(9, 9, 0, DEFAULT_GAME_PARAMETERS.trap_seed_lifespan) } assert game.boards[0].flowers == (Flower(0, 0, DEFAULT_GAME_PARAMETERS), ) assert game.boards[0].hives == (Hive(9, 9), )
def test_apply_flower_command_empty_tile(): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(9, 9), ), ), flowers=((Flower(0, 0, DEFAULT_GAME_PARAMETERS), ), ), turn_num=12345, game_length=sentinel.game_length) game.boards[0].inflight[sentinel.seed_1] = Seed(4, 5, 0) game.apply_commands([dict(entity=sentinel.seed_1, command="flower")]) assert game.boards[0].inflight == {} assert game.boards[0].flowers == (Flower(0, 0, DEFAULT_GAME_PARAMETERS), Flower(4, 5, DEFAULT_GAME_PARAMETERS, expires=12645)) assert game.boards[0].hives == (Hive(9, 9), )
def apply_command_and_advance(board_width, board_height, hives, flowers, inflight, turn_num, cmd): """ You can use this function to try out a potential move and test what happens. Parameters ---------- board_width: int The number of tiles in each row of the board board_height: int The number of tiles in each column of the board hives: tuple[`Hive`+] Hives present on player's board flowers: tuple[`Flower`+] Flowers present on player's board inflight: dict [str, `Volant`] A dictionary of volant identifiers to volant turn_num: int The number of the current turn Returns ------- crashed: dict [str, set[str]] A dictionary of causes to Volant identifiers which have been removed landed: set[`str`] A set of Bee identifiers which have landed back on a hive and are no longer active on the board lost: set[`str`] A set of Volant identifiers which have moved over the boundary into a neighbouring board """ board = Board(game_params=DEFAULT_GAME_PARAMETERS, board_width=board_width, board_height=board_height, hives=[Hive(*i) for i in hives], flowers=[Flower.from_json(i) for i in flowers], neighbours={'N':1, 'S':1, 'E':1, 'W':1, 'NW':1, 'SE':1, }, inflight={volant_id: volant_from_json(volant) for volant_id, volant in inflight.items()}, dead_bees=0) board._connect_to_neighbours([board, _OtherBoard()]) board.apply_command(cmd, turn_num) board.remove_dead_flowers(turn_num) board.move_volants() lost = set(board.send_volants()) board.visit_flowers(Random()) landed = set(board.land_bees()) crashed = {k: set(v) for k, v in board.detect_crashes().items()} return crashed, landed, lost
def test_queenbees_cant_create_hive_on_top_of_existing_hive(): game = initialise_game(DEFAULT_GAME_PARAMETERS, 1, 10, 10, 1, 0, 23) board = game.boards[0] board.hives = (Hive(4, 4, 10), ) board.flowers = (Flower(1, 1, DEFAULT_GAME_PARAMETERS, expires=9999), ) # create queen bee on top of existing hive, like it has just launched board.inflight = { sentinel.queenbee_id: QueenBee(4, 4, 180, 10, DEFAULT_GAME_PARAMETERS) } # immediately create hive game.turn([{"entity": sentinel.queenbee_id, "command": "create_hive"}]) # should only be one hive (not two) assert len(board.hives) == 1 # it should be the new hive not the original (with 10 nectar) assert board.hives[0].nectar == 0 # queen bee should be gone as she has 'hived' assert sentinel.queenbee_id not in board.inflight
def test_queenbees_die_immediately_when_landing_on_hives(): game = initialise_game(DEFAULT_GAME_PARAMETERS, 1, 10, 10, 1, 0, 23) game.boards[0].hives = (Hive(4, 4, 0), ) game.boards[0].flowers = (Flower(1, 1, DEFAULT_GAME_PARAMETERS, expires=9999), ) # create queen bee that will land on hive on the next move game.boards[0].inflight = { sentinel.queenbee_id: QueenBee(4, 5, 180, 10, DEFAULT_GAME_PARAMETERS) } # with no command, queen bee should land and die game.turn([None]) # make sure the queen is gone and can't execute a hive command on top of existing hive with pytest.raises(RuntimeError) as err: game.turn([{"entity": sentinel.queenbee_id, "command": "create_hive"}]) assert "Unknown entity" in str(err.value)
def test_flowers_seeds_make_flowers_means_points(): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=1, board_width=10, board_height=10, hives=((Hive(9, 9), ), ), flowers=((), ), game_length=sentinel.game_length) assert all( board.calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor for board in game.boards) game.boards[0].inflight[sentinel.seed_1] = Seed(4, 5, 0) game.apply_commands([dict(entity=sentinel.seed_1, command="flower")]) assert all(board.calculate_score() == ( DEFAULT_GAME_PARAMETERS.hive_score_factor + DEFAULT_GAME_PARAMETERS.flower_score_factor) for board in game.boards)
def test_serialise_deserialise_game_state_to_json(nboards): params = GameParameters(launch_probability=1.0, initial_energy=10, dead_bee_score_factor=-5, hive_score_factor=100, flower_score_factor=100, nectar_score_factor=2, queen_bee_nectar_threshold=20, bee_nectar_capacity=5, bee_energy_boost_per_nectar=25, flower_seed_visit_initial_threshold=10, flower_seed_visit_subsequent_threshold=10, flower_visit_potency_ratio=10, flower_lifespan=100, flower_lifespan_visit_impact=30, trap_seed_probability=1, venus_score_factor=-50, trap_seed_lifespan=10) game = GameState( game_params=params, game_id=sentinel.game_id, boards=nboards, board_width=sentinel.board_width, board_height=sentinel.board_height, hives=[(Hive(sentinel.hive_x, sentinel.hive_y, 23 * nboards), )] * nboards, flowers=[(Flower(sentinel.fx, sentinel.fy, DEFAULT_GAME_PARAMETERS, sentinel.flower_size), )] * nboards, game_length=sentinel.game_length) # make sure there are some bees on the boards, and some of them will be queens # as the nectar in the hives should be over the queen making threshold with patch("hiveminder.game_state.rngs", {sentinel.game_id: Random(0)}): game.launch_bees(sentinel.turn_num) game_state_json = game.to_json() game_state_bounce = game.from_json(game_state_json) assert game == game_state_bounce
def test_hive_not_equal_to_other_types(): assert not (Hive(sentinel.x, sentinel.y) == sentinel.hive) assert Hive(sentinel.x, sentinel.y) != sentinel.hive
def create_hive(self, board): # add hive where queen is. destroy any existing hive. # should only happen if a newly launched queen hives immediately where she is launched board.hives = [h for h in board.hives if h.x != self.x or h.y != self.y] + [Hive(self.x, self.y, self.nectar)]
def test_the_specified_number_of_flowers_are_created(n): assert len( make_flowers(n, [Hive(3, 3)], 8, 7, Random(0), DEFAULT_GAME_PARAMETERS)) == n
def test_hives_equality(x1, y1, n1, are_equal): h1 = Hive(x1, y1, n1) h2 = Hive(sentinel.x, sentinel.y, sentinel.n) assert (h1 == h2) == are_equal assert (h1 != h2) == (not are_equal)
def test_detect_crashes(bee_types, crash_board, noncrash_board, crashing_volant_specs, noncrash_volant_specs): game = GameState(game_params=DEFAULT_GAME_PARAMETERS, game_id=sentinel.game_id, boards=2, board_width=sentinel.board_width, board_height=sentinel.board_height, hives=[[Hive(0, 0, 0)]] * 2, flowers=[[VenusBeeTrap(9, 9, DEFAULT_GAME_PARAMETERS)]] * 2, game_length=sentinel.game_length) def apply_bee_type_to_specs(bees_specs): """ Create bee instances from the specs in the test cases which are tuples if not, return the spec as is (will probably be a seed)""" def create_bee_or_seed(id, spec): if type(spec) is tuple: x, y, h, e, n = spec return bee_types[id % 10](x, y, h, e, DEFAULT_GAME_PARAMETERS, n) else: return spec return { bee_id: create_bee_or_seed(bee_id, bee) for bee_id, bee in bees_specs.items() } crashing_volants = { crash_type: apply_bee_type_to_specs(volants) for crash_type, volants in crashing_volant_specs.items() } noncrash_volants = apply_bee_type_to_specs(noncrash_volant_specs) crashing_volants_summary = { volant_id: volant for volants in crashing_volants.values() for volant_id, volant in volants.items() } crashing_bees_summary = { bee_id: bee for bee_id, bee in crashing_volants_summary.items() if isinstance(bee, Bee) } crashing_volants.setdefault("collided", {}) crashing_volants.setdefault("exhausted", {}) crashing_volants.setdefault("headon", {}) crashing_volants.setdefault("gobbled", {}) crashing_volants.setdefault("seeds", {}) for board, volants in ((crash_board, crashing_volants_summary), (noncrash_board, noncrash_volants)): for bee_id, bee_details in volants.items(): game.boards[board].inflight[bee_id] = bee_details assert all( board.calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor + DEFAULT_GAME_PARAMETERS.venus_score_factor for board in game.boards) crashes = game.detect_crashes() assert all( board.calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor + DEFAULT_GAME_PARAMETERS.venus_score_factor for i, board in enumerate(game.boards) if i != crash_board) assert (game.boards[crash_board].calculate_score() == DEFAULT_GAME_PARAMETERS.hive_score_factor + DEFAULT_GAME_PARAMETERS.venus_score_factor + DEFAULT_GAME_PARAMETERS.dead_bee_score_factor * len(crashing_bees_summary)) for board, crashed_bees in enumerate(crashes): if board == crash_board: assert crashed_bees == crashing_volants else: assert crashed_bees == dict(collided={}, headon={}, exhausted={}, gobbled={}, seeds={})
def test_can_convert_hive_to_json(): assert Hive(sentinel.x, sentinel.y, sentinel.nectar).to_json() == [ sentinel.x, sentinel.y, sentinel.nectar ]
def test_can_read_hive_from_json(): assert Hive.from_json([sentinel.x, sentinel.y, sentinel.nectar]) == Hive(sentinel.x, sentinel.y, sentinel.nectar)
def test_repr(): assert repr(Hive(1337, 2000, 23)) == "Hive(1337, 2000, 23)"
def test_str(): assert str(Hive(1337, 2000, 23)) == "Hive(1337, 2000, 23)"
def test_can_not_hash_a_hive(): h = Hive(sentinel.x, sentinel.y) with pytest.raises(TypeError) as err: hash(h) assert str(err.value) == "unhashable type: 'Hive'"