def make_encoding(ship_a, ship_b, attack_range, agent): """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 = [] # Reset ship b for each trial world_state = WorldState() world_state.addShip(ship_a, 0) world_state.addShip(ship_b, 1) pool_colors, pool_faces = ship_a.roll("front", attack_range) attack = AttackState(attack_range=attack_range, attacker=ship_a, attacking_hull="front", defender=ship_b, defending_hull="front", pool_colors=pool_colors, pool_faces=pool_faces) world_state.updateAttack(attack) # The defense token and die locations have been reordered in the encoding, put them back to # their original ordering here. encoding = Encodings.encodeAttackState(world_state) return encoding, world_state
def __init__(self, gui): super().__init__() # In order to get to the slider values self.gui = gui self.title = "Robot and Walls" # Window size self.top = 15 self.left = 15 self.width = 700 self.height = 700 # State/action text self.sensor_text = "No sensor" self.action_text = "No action" # The world state self.world_state = WorldState() # For querying door self.door_sensor = DoorSensor() # For moving robot self.robot_state = RobotState() # For robot state estimation self.state_estimation = RobotStateEstimation() # Height of prob self.draw_height = 0.6 # Set geometry self.initUI()
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 __init__(self, agents, totalIter=100): self.agents = agents self.numAgents = len(agents) self.currAgentInd = 0 # 0 is Gov, 1 is COVID self.iterNum = 0 self.totalIter = totalIter self.gameOver = False self.state = WorldState(None, self.numAgents, totalIter)
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 __init__(self, gui_world): super().__init__() # In order to get to the slider values self.gui = gui_world self.title = "Robot and Walls" # Window size self.top = 15 self.left = 15 self.width = 700 self.height = 700 # State/action text self.sensor_text = "No sensor" self.action_text = "No action" self.move_text = "No move" self.loc_text = "No location" # The world state self.world_state = WorldState() # For querying door self.door_sensor = DoorSensor() # For moving robot self.robot_state = RobotState() # For robot state estimation self.state_estimation = RobotStateEstimation() # For keeping sampled error self.last_wall_sensor_noise = 0 self.last_move_noise = 0 # Height of prob self.draw_height = 0.6 # Set geometry self.text = "None" self.init_ui()
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
def test_defense_tokens_model(spend_defense_tokens_model): """Test basic network learning loop. Test lifetime predictions during the spend defense tokens phase. """ network, errors, eval_errors = spend_defense_tokens_model network.eval() phase_name = "attack - spend defense tokens" world_size = Encodings.calculateWorldStateSize() action_size = Encodings.calculateActionSize(phase_name) attack_size = Encodings.calculateAttackSize() input_size = world_size + action_size + attack_size target_device = torch.device("cuda" if torch.cuda.is_available() else "cpu") batch_size = 32 batch = torch.Tensor(batch_size, input_size).to(target_device) print("Eval errors for B were {}".format(eval_errors)) #print("First and last errors in b are {} and {}".format(eval_errors[0], eval_errors[-1])) assert eval_errors[0] > eval_errors[-1] # Let's examine predictions for different dice pools and spent defense tokens. # Go through the following scenarios: # 1.1 An attack with more than enough damage to destroy the ship # 1.2 The same attack but a brace that would prevent destruction # 1.3 The same attack but a redirect that would prevent destruction # Result: 1.1 should have lower lifetime than 1.2 and 1.3 # 2.1 An attack that can barely destroy the ship # 2.2 An attack that barely will not destroy the ship # Result: 2.1 should have lower lifetime than 2.2. # Ideally 1.1 and 2.1 would predict the current round. world_state = WorldState() world_state.round = 1 ship_a = Ship(name="Ship A", template=ship_templates["All Defense Tokens"], upgrades=[], player_number=1) ship_b = Ship(name="Ship B", template=ship_templates["All Defense Tokens"], upgrades=[], player_number=2) world_state.addShip(ship_a, 0) world_state.addShip(ship_b, 1) pool_colors, pool_faces = ['black'] * 4, ['hit_crit'] * 4 world_state.setPhase("ship phase", phase_name) # Set the front hull zone to 2 shields ship_b.get_range('shields')[ArmadaTypes.hull_zones.index('front')] = 2 # Set the hull to 3 (by assigning damage to reduce the remaining hull to 3) ship_b.set('damage', ship_b.get('hull') - 3) attack = AttackState('short', ship_a, 'left', ship_b, 'front', pool_colors, pool_faces) world_state.updateAttack(attack) action_encoding = torch.cat((Encodings.encodeWorldState(world_state), Encodings.encodeAction(world_state.sub_phase, None))) state_encoding = Encodings.encodeAttackState(world_state) batch[0] = torch.cat( (action_encoding.to(target_device), state_encoding.to(target_device))) action = [("brace", (ArmadaTypes.green, None))] action_encoding = torch.cat((Encodings.encodeWorldState(world_state), Encodings.encodeAction(world_state.sub_phase, action))) state_encoding = Encodings.encodeAttackState(world_state) batch[1] = torch.cat( (action_encoding.to(target_device), state_encoding.to(target_device))) world_state = WorldState() world_state.round = 1 ship_a = Ship(name="Ship A", template=ship_templates["All Defense Tokens"], upgrades=[], player_number=1) ship_b = Ship(name="Ship B", template=ship_templates["All Defense Tokens"], upgrades=[], player_number=2) world_state.addShip(ship_a, 0) world_state.addShip(ship_b, 1) pool_colors, pool_faces = ['black'] * 4, ['hit_crit'] * 2 + ['hit'] * 2 world_state.setPhase("ship phase", phase_name) # Set the front hull zone to 2 shields ship_b.get_range('shields')[ArmadaTypes.hull_zones.index('front')] = 2 # Set the hull to 3 (by assigning damage to reduce the remaining hull to 3) ship_b.set('damage', ship_b.get('hull') - 3) attack = AttackState('short', ship_a, 'left', ship_b, 'front', pool_colors, pool_faces) world_state.updateAttack(attack) action = [("redirect", (ArmadaTypes.green, [('left', 4)]))] action_encoding = torch.cat((Encodings.encodeWorldState(world_state), Encodings.encodeAction(world_state.sub_phase, action))) state_encoding = Encodings.encodeAttackState(world_state) batch[2] = torch.cat( (action_encoding.to(target_device), state_encoding.to(target_device))) round_status = network(batch[:3]) print("super cool estimated rounds of destructions are {}".format(round_status[:3])) # Using no defense token results in destruction, the final round should be less assert(round_status[0].item() < round_status[1].item()) assert(round_status[0].item() < round_status[2].item())
def test_resolve_attack_effects_model(resolve_attack_effects_model): """Test basic network learning loop. Test lifetime predictions during the resolve attack effects phase. """ network, errors, eval_errors = resolve_attack_effects_model network.eval() phase_name = "attack - resolve attack effects" world_size = Encodings.calculateWorldStateSize() action_size = Encodings.calculateActionSize(phase_name) attack_size = Encodings.calculateAttackSize() input_size = world_size + action_size + attack_size # First verify that errors decreased during training. # print("Errors for A were {}".format(errors)) print("Eval errors for A were {}".format(eval_errors)) assert eval_errors[0] > eval_errors[-1] # Let's examine predictions for different ranges and hull zones. target_device = torch.device("cuda" if torch.cuda.is_available() else "cpu") batch_size = 4 batch = torch.Tensor(batch_size, input_size).to(target_device) # Let's examine predictions for different dice pools and spent defense tokens. # Go through the following scenarios: # 1.1 An attack upon a ship with only 1 hull remaining # 1.2 The same dice pool but on a ship with full hull # 1.3 A dice pool with only blank dice # 1.4 A dice pool with only blanks when attacking at long range. # Create a state from resolve attack effects and an empty action. world_state = WorldState() world_state.round = 1 ship_a = Ship(name="Ship A", template=ship_templates["All Defense Tokens"], upgrades=[], player_number=1) ship_b = Ship(name="Ship B", template=ship_templates["All Defense Tokens"], upgrades=[], player_number=2) world_state.addShip(ship_a, 0) world_state.addShip(ship_b, 1) pool_colors, pool_faces = ['black'] * 4, ['hit_crit'] * 4 world_state.setPhase("ship phase", "attack - resolve attack effects") ship_b.set('damage', ship_b.get('hull') - 1) attack = AttackState('short', ship_a, 'left', ship_b, 'front', pool_colors, pool_faces) world_state.updateAttack(attack) action_encoding = torch.cat((Encodings.encodeWorldState(world_state), Encodings.encodeAction(world_state.sub_phase, None))) state_encoding = Encodings.encodeAttackState(world_state) batch[0] = torch.cat( (action_encoding.to(target_device), state_encoding.to(target_device))) # Same dice pool but the defender has full hull ship_b.set('damage', 0) attack = AttackState('short', ship_a, 'left', ship_b, 'front', pool_colors, pool_faces) world_state.updateAttack(attack) action_encoding = torch.cat((Encodings.encodeWorldState(world_state), Encodings.encodeAction(world_state.sub_phase, None))) state_encoding = Encodings.encodeAttackState(world_state) batch[1] = torch.cat( (action_encoding.to(target_device), state_encoding.to(target_device))) # Full hull and all blanks pool_colors, pool_faces = ['black'] * 4, ['blank'] * 4 world_state.setPhase("ship phase", "attack - resolve attack effects") attack = AttackState('short', ship_a, 'left', ship_b, 'front', pool_colors, pool_faces) world_state.updateAttack(attack) state_encoding = Encodings.encodeAttackState(world_state) batch[2] = torch.cat( (action_encoding.to(target_device), state_encoding.to(target_device))) # Full hull, all blanks, firing at red range pool_colors, pool_faces = ['red'] * 2, ['blank'] * 2 world_state.setPhase("ship phase", "attack - resolve attack effects") attack = AttackState('long', ship_a, 'left', ship_b, 'front', pool_colors, pool_faces) world_state.updateAttack(attack) state_encoding = Encodings.encodeAttackState(world_state) batch[3] = torch.cat( (action_encoding.to(target_device), state_encoding.to(target_device))) lifetime_out = network(batch) print("super cool attack effects round estimates are {}".format(lifetime_out)) # The lifetimes should go up sequentially with the above scenarios. # However if the ship won't be destroyed the NN can't make an accurate relative number so be # lenient once lifetimes go above round 6. The first scenario should result in destruction # however. assert(lifetime_out[0].item() < 6) for i in range(batch.size(0) - 1): assert(lifetime_out[i].item() < lifetime_out[i+1].item() or (lifetime_out[i].item() > 6. and lifetime_out[i+1].item() > 6.))
# end homework 3 : Problem 2 return self.mean, self.standard_deviation # Sensor reading, distance to wall (Kalman filtering) def update_gauss_sensor_reading(self, ws, dist_reading): """ Update state estimation based on sensor reading :param ws - for standard deviation of wall sensor :param dist_reading - distance reading returned""" # begin homework 3 : Problem 1 # end homework 3 : Problem 1 return self.mean, self.standard_deviation if __name__ == '__main__': ws_global = WorldState() ds_global = DoorSensor() rse_global = RobotStateEstimation() # Check out these cases # We have two possibilities - either in front of door, or not - cross two sensor readings # saw door versus not saw door uniform_prob = rse_global.probabilities[0] # begin homework 2 problem 4 # Four cases - based on default door probabilities of # DoorSensor.prob_see_door_if_door = 0.8 # DoorSensor.prob_see_door_if_no_door = 0.2 # and 10 probability divisions. Three doors visible.
def move_gauss(self, amount): """ Move by the amount given (may be positive or negative) with noise added :param amount - amount to move (negative is left, positive right) :returns The amount actually moved """ # begin homework 3 : problem 2 # Sample the noise distribution - note zero mean # Move amount plus noise sampled from noise distribution # end homework 3 : problem 2 # Actually move (don't run off of end) return self._move_(amount) if __name__ == '__main__': ws = WorldState() rs = RobotState() # Move far enough to the left and you should stop moving print("Checking _Move_ function") check_step_size = 0.1 for i in range(0, 20): rs.move_left(check_step_size) if rs.robot_loc < 0 or rs.robot_loc > 1: raise ValueError("Robot went off end of left wall") # Repeat for right for i in range(0, 20): rs.move_right(check_step_size) if rs.robot_loc < 0 or rs.robot_loc > 1:
'Please introduce the operation you would like to calculate: ') code.append(user_input) def ask_user_again(): second_user_input = input( ' Would you like to introduce a new operation? yes/no: ') if second_user_input == 'yes': ask_user() third_user_input = input( ' Would you like to introduce a new operation? yes/no: ') if third_user_input == 'yes': ask_user() ask_user() ask_user_again() setup_scanner = Scanner(RegexRules.list_regex_rules, code) setup_parser = Parser(setup_scanner) parsed_string = setup_parser.parse() world_state = WorldState() setup_analyzer = Analyzer(parsed_string) analyzed_string = setup_analyzer.analyze(world_state) setup_interpreter = Interpreter(analyzed_string) interpreted_tree = setup_interpreter.interpret(world_state)