def is_outcome_correct_extra_action(test_document): gamestate = Gamestate.from_document(test_document["pre_gamestate"]) expected_gamestate = Gamestate.from_document(test_document["post_gamestate"]) action = Action.from_document(gamestate.all_units(), test_document["action"]) outcome = Outcome.from_document(test_document["outcome1"]) if "outcome1" in test_document else None gamestate.do_action(action, outcome) extra_action = Action.from_document(gamestate.all_units(), test_document["extra_action"]) outcome = Outcome.from_document(test_document["outcome2"]) if "outcome2" in test_document else None gamestate.do_action(extra_action, outcome) actual = gamestate.to_document() expected = expected_gamestate.to_document() return actual == expected
def select_action(self, gamestate): game = self.get_game() if not game: print("No new data on the server. By the way, our last update was from", self.last_modified) # No new data on the server return None, None, None expected_action = str(gamestate.action_count + 1) if game["action_count"] > gamestate.action_count + 1: # Several new things happened on the server # Handle this one now, but clear last_modified to make # sure we hear about the other stuff self.last_modified = datetime(1970, 1, 1) if game["action_count"] > gamestate.action_count: print("received action", document_to_string(game[expected_action])) action = Action.from_document(gamestate.all_units(), game[expected_action]) outcome = None if action.is_attack: outcome = Outcome.from_document(game[expected_action + "_outcome"]) upgrade = None if expected_action + "_options" in game: options = game[expected_action + "_options"] if "move_with_attack" in options: action.move_with_attack = bool(options["move_with_attack"]) if "upgrade" in options: upgrade = get_enum_attributes(options["upgrade"]) return action, outcome, upgrade return None, None, None
def does_action_exist(test_document): gamestate = Gamestate.from_document(test_document["gamestate"]) action = Action.from_document(gamestate.all_units(), test_document["action"]) available_actions = action_getter.get_actions(gamestate) actual = (action in available_actions) expected = test_document["result"] return give_output(actual, expected)
def is_outcome_correct(test_document): gamestate = Gamestate.from_document(test_document["pre_gamestate"]) expected_gamestate = Gamestate.from_document(test_document["post_gamestate"]) action = Action.from_document(gamestate.all_units(), test_document["action"]) outcome = Outcome.from_document(test_document["outcome"]) if "outcome" in test_document else None gamestate.set_available_actions() gamestate.do_action(action, outcome) if not gamestate.is_extra_action(): action.unit.remove(State.movement_remaining) actual = gamestate.to_document() expected = expected_gamestate.to_document() return give_output(actual, expected)
def validate_action(gamestate, action_document): gamestate.set_available_actions() available_actions = gamestate.get_actions_including_move_with_attack_none() if Position.from_string( action_document["start_at"]) not in gamestate.player_units: return invalid_action(available_actions, request.json) action = Action.from_document(gamestate.all_units(), action_document) if not action: return invalid_action(available_actions, request.json) if not action in available_actions: return invalid_action(available_actions, str(action)) return action
def is_attack_and_defence_correct(test_document): gamestate = Gamestate.from_document(test_document["gamestate"]) action = Action.from_document(gamestate.all_units(), test_document["action"]) attack = test_document["attack"] defence = test_document["defence"] gamestate.set_available_actions() action.unit = gamestate.player_units[action.start_at] gamestate.move_unit(action.start_at, action.end_at) actual_attack = battle.get_attack(action, gamestate) actual_defence = battle.get_defence(action, actual_attack, gamestate) if attack == actual_attack and defence == actual_defence: return True else: print("actual and expected attack:", actual_attack, attack) print("actual and expected defence:", actual_defence, defence) return False
def from_log_document(cls, log_document, player_intelligence=Intelligence.Human, opponent_intelligence=Intelligence.Human, player_profile=None): initial_gamestate_document = log_document["initial_gamestate"] gamestate = Gamestate.from_document(initial_gamestate_document) if "player1" in log_document: player1 = Player.from_document(log_document["player1"]) player2 = Player.from_document(log_document["player2"]) else: player1 = Player("Green", player_intelligence) player2 = Player("Red", opponent_intelligence) if player_profile: if player1.profile == player_profile: player2.intelligence = player2.ai = Intelligence.Network elif player2.profile == player_profile: player1.intelligence = player1.ai = Intelligence.Network else: print(player_profile, "is not playing this game.") print("The players are:", player1.profile, "and", player2.profile) return if "created_at" in log_document: created_at = log_document["created_at"] else: created_at = None game = cls([player1, player2], gamestate, created_at) game.gamestate = gamestate action_count = int(log_document["action_count"]) game.actions = {} game.outcomes = {} for action_number in range(1, action_count + 1): if game.is_turn_done(): game.shift_turn() game.gamestate.set_available_actions() action_document = log_document[str(action_number)] action = Action.from_document(gamestate.all_units(), action_document) game.actions[str(action_number)] = action options = None if str(action_number) + "_options" in log_document: options = log_document[str(action_number) + "_options"] game.options[str(action_number)] = options outcome = None outcome_document = None if action.has_outcome: outcome_document = log_document[str(action_number) + "_outcome"] outcome = Outcome.from_document(outcome_document) if options and "move_with_attack" in options: action.move_with_attack = bool(options["move_with_attack"]) game.outcomes[str(action_number)] = outcome_document game.do_action(action, outcome) if options and "upgrade" in options: upgrade = get_enum_attributes(options["upgrade"]) position = action.end_at if not position in game.gamestate.player_units: position = action.target_at upgraded_unit = action.unit.get_upgraded_unit_from_upgrade( upgrade) game.gamestate.player_units[position] = upgraded_unit if game.is_turn_done(): game.shift_turn() return game
def get_actions_including_pass_extra(self, positions=None): actions = filter_actions(self.available_actions, positions) if self.is_extra_action(): for position, unit in self.player_units.items(): actions.add(Action(self.player_units, position, position)) return actions
def do_action(gamestate, action, outcome): def settle_ability(): ability = action.ability level = unit.get(action.ability) if ability == Ability.bribe: target_unit.set(Effect.bribed, duration=1) gamestate.change_unit_owner(target_at) elif ability == Ability.assassinate: rolls = outcome.for_position(action.target_at) if battle.assassin_kills_target(rolls, level): gamestate.delete_unit_at(target_at) rolls = outcome.for_position(action.start_at) if battle.assassin_dies(rolls): gamestate.delete_unit_at(start_at) elif ability == Ability.poison: target_unit.set(Effect.poisoned, level=level, duration=level) elif ability == Ability.sabotage: target_unit.set(Effect.sabotaged, level=level, duration=level) elif ability == Ability.improve_weapons: target_unit.set(Effect.improved_weapons, level=level, duration=level) def prepare_extra_actions(): # If this is the extra action already, remove the option to do more extra actions if unit.has(State.extra_action): unit.remove(State.extra_action) unit.remove(State.movement_remaining) return # If the action is a move with a Hobelar, there is no reason to allow an extra action. if unit.has(Trait.swiftness) and not action.is_attack: unit.remove(State.movement_remaining) return if movement_remaining or unit.has(Trait.combat_agility): unit.set(State.extra_action) else: unit.remove(State.movement_remaining) def update_actions_remaining(): if unit.has(State.extra_action): return gamestate.decrement_actions_remaining() if action.double_cost: gamestate.decrement_actions_remaining() def apply_unit_effects(): if unit.has(Trait.attack_cooldown) and action.is_attack: unit.set(State.attack_frozen, value=3) if unit.has(Trait.attack_cooldown, 2) and action.is_attack: unit.set(State.attack_frozen, value=2) def unit_should_gain_experience(): return action.is_attack or unit.type == Type.Cavalry or action.is_ability def get_subattack_targets(): targets = [] if unit.has(Trait.triple_attack): targets = action.end_at.two_forward_tiles(attack_direction) & set( enemy_units) elif unit.has(Trait.spread_attack): targets = list(action.target_at.adjacent_tiles() & set(all_units)) elif unit.has(Trait.longsword): targets = list( action.end_at.four_forward_tiles(attack_direction) & set(enemy_units)) return targets def unit_has_subattacks(): subattack_traits = [ Trait.triple_attack, Trait.spread_attack, Trait.longsword ] return any(unit.has(trait) for trait in subattack_traits) def unit_has_extra_action_trait(): return any( unit.has(attribute) for attribute in [Trait.swiftness, Trait.combat_agility]) # Define local variables start_at = action.start_at end_at = action.end_at target_at = action.target_at unit = action.unit target_unit = action.target_unit enemy_units = gamestate.enemy_units all_units = gamestate.all_units() apply_unit_effects() update_actions_remaining() gamestate.move_unit(start_at, end_at) final_position = end_at if unit_should_gain_experience(): unit.gain_experience() if action.is_attack: attack_direction = action.attack_direction settle_attack(action, gamestate, outcome, attack_direction, False) if action.move_with_attack and action.target_at not in enemy_units: gamestate.move_unit(end_at, target_at) final_position = target_at if unit_has_subattacks(): for target in get_subattack_targets(): sub_attack = Action(all_units, start_at, end_at, target) settle_attack(sub_attack, gamestate, outcome, attack_direction, True) elif action.is_ability: settle_ability() if unit_has_extra_action_trait(): # Determine the movement points the unit can use on its extra action. movement_remaining = unit.movement - distance(start_at, final_position) # An attack requires a movement point even if it doesn't succeed. But not for Fencer. if action.is_attack and not unit.has( Trait.combat_agility) and target_at != final_position: movement_remaining -= 1 unit.set(State.movement_remaining, value=movement_remaining) prepare_extra_actions() unit.set(State.used, value=1)
def make_action(self, end_at=None, target_at=None, move_with_attack=None, ability=None): if not end_at: end_at = self.start_at return Action(self.units, self.start_at, end_at, target_at, move_with_attack, ability)
from gamestate import Gamestate from gamestate.action import Action import json import game.ai as ai_module import glob paths = glob.glob("../ai_tests/*.json") for path in paths: print path document = json.loads(open(path).read()) gamestate = Gamestate.from_document(document["gamestate"]) desired_action = Action.from_document(gamestate.all_units(), document["action"]) gamestate.set_available_actions() ai = ai_module.AI() action = ai.select_action(gamestate) if action != desired_action: print action print desired_action print