def a_vs_b(ship_a, ship_b, trials, attack_range): """This function calculates the average time to destruction when a shoots at b. Args: ship_a ((Ship, str)): Attacker and hull zone tuple. ship_b ((Ship, str)): Defender and hull zone tuple. trials (int): Number of trials in average calculation. range (str): Attack range. """ roll_counts = [] agent = SimpleAgent() for trial in range(trials): # Reset ship b for each trial ship_b.reset() world_state = WorldState() world_state.addShip(ship_a, 0) world_state.addShip(ship_b, 1) num_rolls = 0 while ship_b.damage_cards() < ship_b.hull(): num_rolls += 1 # Handle the attack and receive the updated world state world_state = handleAttack(world_state=world_state, attacker=(ship_a, "front"), defender=(ship_b, "front"), attack_range=attack_range, offensive_agent=agent, defensive_agent=agent) roll_counts.append(num_rolls) np_counts = numpy.array(roll_counts) return np_counts.mean()
def a_vs_b(ship_a, ship_b, agent_a, agent_b, ship_a_hull, trials, attack_range): """This function runs multiple trials of ship_a firing upon ship_b. Args: ship_a ((Ship, str)): Attacker and hull zone tuple. ship_b ((Ship, str)): Defender and hull zone tuple. agent_a (BaseAgent): Agent to control the actions of ship a. agent_b (BaseAgent): Agent to control the actions of ship b. ship_a_hull (str) : Attacking hull zone. trials (int): Number of trials in average calculation. range (str): Attack range. Returns: List[(str, world_state or attack effect tuple)] """ state_log = [] failures = 0 for _ in range(trials): # Reset ship b for each trial ship_b.reset() world_state = WorldState() world_state.addShip(ship_a, 0) world_state.addShip(ship_b, 1) # Begin at round 1 world_state.round = 1 # Don't attempt forever in the case of some catastrophic reoccurring error. attempts = 0 while ship_b.damage_cards() < ship_b.hull( ) and world_state.round <= ArmadaPhases.max_rounds: attempts += 1 # Handle the attack and receive the updated world state #try: world_state = handleAttack(world_state=world_state, attacker=(ship_a, ship_a_hull), defender=(ship_b, "front"), attack_range=attack_range, offensive_agent=agent_a, defensive_agent=agent_b, state_log=state_log) # Record the final state with the incremented round number. world_state.setPhase("status phase", "increment round number") world_state.round += 1 state_log.append(('state', world_state.clone())) #except RuntimeError as err: # # This is fine, the random agent will do illegal things plenty of times # pass if 250 == attempts: raise RuntimeError("Too many failures for ship firing simulation.") return state_log
def a_vs_b(ship_a, ship_b, trials, attack_range): """This uses a random agent to choose actions during attacks from ship_a to ship_b. Args: ship_a ((Ship, str)): Attacker and hull zone tuple. ship_b ((Ship, str)): Defender and hull zone tuple. trials (int): Number of trials in average calculation. range (str): Attack range. Returns: state_log (List[List[("state" or "action", (WorldState or action tuple))]]) """ agent = RandomAgent() state_log = [] for trial in range(trials): # Reset ship b for each trial ship_b.reset() world_state = WorldState() world_state.addShip(ship_a, 0) world_state.addShip(ship_b, 1) num_rolls = 0 while ship_b.damage_cards() < ship_b.hull(): num_rolls += 1 # Handle the attack and receive the updated world state try: world_state = handleAttack(world_state=world_state, attacker=(ship_a, "front"), defender=(ship_b, "front"), attack_range=attack_range, offensive_agent=agent, defensive_agent=agent, state_log=state_log) except RuntimeError: # This is fine, the random agent will do illegal things plenty of times pass return state_log
world_state = WorldState() world_state.addShip(attacker, 0) world_state.addShip(defender, 1) num_rolls = 0 # This will hold lists of the state action pairs for each roll state_actions = [] while 0 < defender.hull(): num_rolls += 1 # Handle the attack and receive the updated world state # In this initial version of the code the prediction agent won't actually take any # actions but we need it to log the (attack_state, action) pairs prediction_agent.rememberStateActions() # TOOD FIXME HERE For random training sometimes the agents should be random agents. world_state = handleAttack(world_state=world_state, attacker=(attacker, attack_hull), defender=(defender, defend_hull), attack_range=attack_range, offensive_agent=prediction_agent, defensive_agent=prediction_agent) world_state.round += 1 # Get the (state, action) pairs back state_action_pairs = prediction_agent.returnStateActions() state_actions.append(state_action_pairs) if args.novelty: logging.info("\t roll {}, estimate {}, novelty {}".format( num_rolls, state_action_pairs[0][2][-2], state_action_pairs[0][3])) else: logging.info("\t roll {}, estimate {}".format( num_rolls, state_action_pairs[0][2][-2])) # Pair the lifetimes with the (state, action) pairs and push them into the examples list for roll_idx, state_action_pairs in enumerate(state_actions):
logging.info("Trial number {}".format(trial)) # Reset ship b for each trial ship_2 = ship.Ship(name=ship_name_2, template=ship_templates[ship_name_2], upgrades=[], player_number=2) world_state = WorldState() world_state.addShip(ship_1, 0) world_state.addShip(ship_2, 1) num_rolls = 0 while 0 < ship_2.hull(): num_rolls += 1 # Handle the attack and receive the updated world state world_state = handleAttack(world_state=world_state, attacker=(ship_1, "front"), defender=(ship_2, "front"), attack_range=attack_range, offensive_agent=agent, defensive_agent=agent) roll_counts.append(num_rolls) np_counts = numpy.array(roll_counts) print( "Ship {} destroys {} in {} average rolls, stddev = {}, at range {}." .format(ship_name_1, ship_name_2, np_counts.mean(), np_counts.var()**0.5, attack_range)) logging.info( "Ship {} destroys {} in {} average rolls, stddev = {}, at range {}.\n" .format(ship_name_1, ship_name_2, np_counts.mean(), np_counts.var()**0.5, attack_range)) # TODO(take defense tokens into account) # Make a base player class that allows you to bind a function for this stuff # TODO(take accuracy into account)