def do_action(game, coin, action, data): if action == PASS: if game.should_wait and game.should_wait['unit'] == units.ROYAL_GUARD: game.board.kill(units.ROYAL_GUARD, game.board.coins_on[units.ROYAL_GUARD]) return True if action == INITIATIVE: return game.take_initiative() if action == RECRUIT: zones = game.zones[game.active_player] return zones['recruit'].move(zones['faceup'], coin=data) if action == DEPLOY: return game.board.deploy(coin, data) if action == BOLSTER: return game.board.bolster(coin, data) if action == MOVE: return game.board.move(coin, data) if action == ATTACK: game.board.attack(coin, data) if coin == units.SWORDSMAN: game.waiton = units.SWORDSMAN return False if action == CONTROL: return game.board.control(data) if action == TACTIC: if coin == units.LIGHT_CAVALRY: return game.board.move(coin, data) if coin in [units.ARCHER, units.CROSSBOWMAN]: return game.board.attack(coin, data, ranged=True) if coin == units.ENSIGN: unit = list(data.keys())[0] return game.board.move(unit, data[unit]) if coin == units.MARSHALL: unit = list(data.keys())[0] return game.board.attack(unit, data[unit]) if coin == units.ROYAL_TOKEN: return game.board.move(units.ROYAL_GUARD, data) if coin in [units.LANCER, units.HEAVY_CAVALRY]: move_to = list(data.keys())[0] move_to_hex = Hex([int(i) for i in move_to.split(",")]) game.board.move(coin, move_to_hex) return game.board.attack(coin, data[move_to]) if action == SAVE: zones = game.zones[game.active_player] return zones['recruit'].remove(units.ROYAL_GUARD)
def test_within_n(): assert len(Hex((0, 0, 0)).hexes_within_n(2)) == 18 assert len(Hex((0, 0, 0)).hexes_within_n(1)) == 6 assert Hex((2, -3, 1)) not in Hex((0, -2, 2)).hexes_within_n(1) assert Hex((2, -3, 1)) in Hex((0, -2, 2)).hexes_within_n(2) assert len(Hex((0, 0, 0)).hexes_within_n(2, at_least=2)) == 12
def _get_tactic(game, coins): name, pos = coins.popitem() if name == units.LIGHT_CAVALRY: first_moves = [hex for hex in game.board.get_adjacent(pos) if not game.board.what_is_on(hex)] moves = [] for move in first_moves: moves = moves + [_hex for _hex in game.board.get_adjacent(move) if not game.board.what_is_on(_hex)] return list(set(moves)) or False if name == units.HEAVY_CAVALRY: first_moves = [hex for hex in game.board.get_adjacent(pos) if not game.board.what_is_on(hex)] targets = {} for move in first_moves: enemies = [] for _hex in game.board.get_adjacent(move): target_unit = game.board.what_is_on(_hex) if target_unit and target_unit[1]['owner'] != game.active_player: enemies.append(target_unit[1]['space']) if enemies: targets[str(move)] = enemies return targets or False if name == units.ARCHER: targets = [] for target_space in Hex(pos).hexes_within_n(2, at_least=2): target_unit = game.board.what_is_on(target_space) if target_unit and target_unit[1]['owner'] != game.active_player: targets.append(target_space) return list(set(targets)) or False if name == units.ROYAL_TOKEN: guard = game.board.coins_on.get(units.ROYAL_GUARD) if not guard or guard['owner'] != game.active_player: return False return _get_moves(game, {units.ROYAL_GUARD: guard['space']})[units.ROYAL_GUARD] if name == units.CROSSBOWMAN: targets = [] my_spot = Hex(pos) for d, h in HEX_DIRECTIONS.items(): next_space = my_spot.add(h) if not next_space or game.board.what_is_on(next_space): continue next_space = my_spot.add(h) if not next_space: continue next_next_space = next_space.add(h) if not next_next_space: continue target_unit = game.board.what_is_on(game.board.what_is_on(next_next_space)) if target_unit: if target_unit[1]['owner'] != game.active_player: targets[next_space] = next_next_space if name == units.LANCER: targets = {} my_spot = Hex(pos) for d, h in HEX_DIRECTIONS.items(): next_space = my_spot.add(h) if not next_space or game.board.what_is_on(next_space): continue next_space = my_spot.add(h) if not next_space: continue next_next_space = next_space.add(h) if not next_next_space: continue target_unit = game.board.what_is_on(game.board.what_is_on(next_next_space)) if target_unit: if target_unit[1]['owner'] != game.active_player: targets[str(next_space)] = next_next_space else: next_space = my_spot.add(h) if not next_space: continue next_next_space = next_space.add(h) if not next_next_space: continue target_unit = game.board.what_is_on(game.board.what_is_on(next_next_space)) if target_unit and target_unit[1]['owner'] != game.active_player: targets[str(next_space)] = next_next_space return targets or False if name == units.MARSHALL: targets = {} for target_space in Hex(pos).hexes_within_n(2): target_unit = game.board.what_is_on(target_space) if target_unit and target_unit[1]['owner'] == game.active_player: attacks = _get_attacks(game, {target_unit[0]: target_unit[1]['space']}) if attacks: targets[target_unit[0]] = attacks[target_unit[0]] return targets or False if name == units.ENSIGN: targets = {} for target_space in Hex(pos).hexes_within_n(2): target_unit = game.board.what_is_on(target_space) if target_unit and target_unit[1]['owner'] == game.active_player: possible_moves = _get_moves(game, {target_unit[0]: target_unit[1]['space']}) if not possible_moves: continue moves = [m for m in possible_moves[target_unit[0]] if Hex(pos).distance(Hex(m)) <= 2] if moves: targets[target_unit[0]] = moves return targets or False return False
def get_adjacent(self, coordinates): return Hex(coordinates).hexes_within_n(1)
def test_get_distance(): assert Hex((0, 0, 0)).distance(Hex((0, -1, 1))) == 1 assert Hex((0, 0, 0)).distance(Hex((-1, -1, 2))) == 2 assert Hex((2, 0, -2)).distance(Hex((3, -3, 0))) == 3
def test_get_neighbor(): assert Hex((0, 0, 0)).neighbor('n') == Hex((0, -1, 1)) assert Hex((0, -1, 1)).neighbor('nw') == Hex((-1, -1, 2)) assert Hex((0, -3, 3)).neighbor('n') is None