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 __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()
class World: 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 printStats( self ): pass def run(self, verbose=False): """ Main control loop for game play. """ while not self.gameOver: agent = self.agents[self.currAgentInd] # For Govt, this returns list of tuples (ACTION, LIST_INDEX) # For COVID, this returns list of 2 items [INFECT, IDLE] #legalActions = self.state.getLegalActions(self.currAgentInd) # Solicit actiion #action = agent.getAction(self.state.deepCopy(), legalActions) #action = agent.getAction(self.state.deepCopy()) action = agent.getAction(self.state) # Update state self.state = self.state.generateSuccessor(self.currAgentInd, action) # Print stats if self.currAgentInd == 0: print('----------------------------------------------------------') print('Round: {}'.format(self.iterNum)) print('Num People Infected: {} / {}'.format(self.state.data.numCovidCases(), self.state.data.population)) print('Num States Infected: {} / {}'.format(self.state.data.numGridsInfected(), len(self.state.data.grids))) print('Lockdown Stats: {} / {}'.format(self.state.data.numLockdowns(), len(self.state.data.grids))) print('Value: {}'.format(self.state.data.score)) if verbose: # Print any additional information self.printStats() # Switch players self.currAgentInd = (self.currAgentInd + 1) % self.numAgents self.iterNum += 1 if not self.currAgentInd else 0 # Game over if reach max iter or everyone has COVID if self.iterNum >= self.totalIter or self.state.data.allInfected(): self.gameOver = True
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 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, model=None): if not model: # For testing. self.actors = {} self.current_turn = 0 self.world = WorldState(current_turn=self.current_turn) else: self.uuid = str(model.uuid) self.current_turn = model.current_turn self.actors = {} if model.seed: seed = json.loads(model.seed) if model.cells: seed['cells'] = json.loads(model.cells) else: seed['cells'] = {} self.world = WorldState(json_dump=seed, current_turn=self.current_turn) else: self.world = WorldState(current_turn=self.current_turn) for a in model.actors.all(): self.add_actor(Actor(model=a)) self.smell_matrix = defaultdict(list)
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 __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 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())
attacker = ship.Ship(name=attacker_name, template=ship_templates[attacker_name], upgrades=[], player_number=1) defender = ship.Ship(name=defender_name, template=ship_templates[defender_name], upgrades=[], player_number=2) # Make sure we are actually rolling dice colors, _ = attacker.roll(attack_hull, attack_range) if 0 < len(colors): logging.info("{} vs {} at range {}".format(attacker_name, defender_name, attack_range)) 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),
# 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 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.))
n_prob = 1 - prob print(prob) print(n_prob) # end homework 2 : problem 1 return True # set the probabilities based on the gui def set_probabilities(self, in_prob_see_door_if_door, in_prob_see_door_if_not_door): self.prob_see_door_if_door = in_prob_see_door_if_door self.prob_see_door_if_no_door = in_prob_see_door_if_not_door if __name__ == '__main__': ws_global = WorldState() ds_global = DoorSensor() rs_global = RobotState() # Robot should be at 0.5, no door at 0.5, so this should be false print("Testing probabilities for robot NOT in front of door") rs_global.robot_loc = ws_global.place_robot_not_in_front_of_door() if ds_global.is_in_front_of_door(ws_global, rs_global): raise ValueError("The robot should NOT be in front of a door") # Check that we get our probabilites back (mostly) count_returned_true = 0 for i in range(0, 1000): if ds_global.sensor_reading(ws_global, rs_global):
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:
class GameInstance(CoordParseMixin): """Container for world and actors in world. GameInstance is responsible for tracking the world and the actors within it. It has functions to simplify interacting with the world and actors in it. It also provides functions that actors can call for information about the world, in order to aid in their decision making. Most functions that have a signature of the form fn(x,y) can accept a number of different arguments. The goal is to have as open an api as possible, given """ def __init__(self, model=None): if not model: # For testing. self.actors = {} self.current_turn = 0 self.world = WorldState(current_turn=self.current_turn) else: self.uuid = str(model.uuid) self.current_turn = model.current_turn self.actors = {} if model.seed: seed = json.loads(model.seed) if model.cells: seed['cells'] = json.loads(model.cells) else: seed['cells'] = {} self.world = WorldState(json_dump=seed, current_turn=self.current_turn) else: self.world = WorldState(current_turn=self.current_turn) for a in model.actors.all(): self.add_actor(Actor(model=a)) self.smell_matrix = defaultdict(list) def __getitem__(self, key): return self.world[key] def __setitem__(self, key, item): self.world[key] = item @property def is_night(self): return (self.current_turn / 12) % 2 == 0 def set_turn(self, num): self.current_turn = num self.world.current_turn = num def add_actor(self, a, xy=None): """Add an Actor to the GameInstance. :param a: Actor object to be added. :param xy: x,y coord OR a WorldInhabitant (such as a Cell) """ atest = self.actors.get(a.uuid) if atest: tmp = "{} already in GameInstance." raise ValueError(tmp.format(atest)) if xy: x, y = self.coord_parse(xy) else: x, y = self.coord_parse(a) # Insert actor at nearby location if spot is full. atest = self.get_actor((x, y)) if atest: for x1, y1 in self.circle_at((x, y), 4): atest = self.get_actor((x1, y1)) if not atest: self.actors[a.uuid] = a a._coords = (x1, y1) a.gameInstance = self self.world.add_inhabitant(a) warn = "Warning, actor already at ({},{}): '{}' inserted at ({},{})." print(warn.format(x, y, a.name, x1, y1)) break else: self.actors[a.uuid] = a a._coords = (x, y) a.gameInstance = self self.world.add_inhabitant(a) def remove_actor(self, act_uuid): """Remove an actor from the GameInstance. Fail silently. :param xy_or_WI: x,y coord OR a WorldInhabitant object. """ actr = self.get_actor(act_uuid) if not actr: return del self.actors[actr.uuid] self.world.remove_inhabitant(actr) actr._coords = (-1, -1) return def get_actor(self, xy_or_UUID): """Get actor by _coords, UUID, or WorldInhabitant. :param xy_or_UUID: x,y coord OR UUID of actor, or WorldInhabitant :return: Actor that fits description, or None """ try: uuid.UUID(xy_or_UUID) is_uuid = True except Exception as e: is_uuid = False if is_uuid: return self.actors.get(xy_or_UUID) else: print(xy_or_UUID) x, y = self.coord_parse(xy_or_UUID) content = self[x][y] if len(content) > 1: for z in content: if isinstance(z, Actor): return z return None def check_actor(self, xy): """ Check to see if actor is currently in location specified by param. :param xy: x,y coord of gameInstance :return Boolean if Actor is at xy location or False if not """ x, y = self.coord_parse(xy) content = self[x][y] if len(content) > 1: for z in content: if isinstance(z, Actor): return True return False def move_actor(self, actor_or_UUID_or_coords, xy_or_WI): """Move an actor to a location. :param actor_or_UUID_or_coords: Exactly what it says. :param xy_or_WI: Coords or a WorldInhabitant (cell) :return: None. """ if isinstance(actor_or_UUID_or_coords, Actor): actor = actor_or_UUID_or_coords else: actor = self.get_actor(actor_or_UUID_or_coords) x,y = self.coord_parse(xy_or_WI) self.world.remove_inhabitant(actor) actor._coords = (x,y) self.world.add_inhabitant(actor) def has_attr(self, world_inhab, attr): """Determine if the wold_inhab has an attribute. :param world_inhab: A WorldInhabitant. :param attr: A property defined in globals.ATTRIBUTES :return: bool """ if attr == "FOOD": return world_inhab.is_food if attr == "DEADLY": return world_inhab.is_deadly if attr == "ACTOR": return world_inhab.is_actor if attr == "WATER": return world_inhab.is_water if attr == "GRASS": return world_inhab.is_grass if attr == "ROCK": return world_inhab.is_rock if attr == "PLANT": return world_inhab.is_plant else: return False def find_nearest(self, xy_or_WI, attr): """Find and return nearest coords of world where something with attr is. :param xy_or_UUID: x,y tuple OR a WorldInhabitant :param attr: A property defined in globals.ATTRIBUTES :return: Coordinate tuple of nearest cell with something having that attribute. Returns original coords if not found. """ vision_radius = 2 if self.is_night else 4 scan_area = self.circle_at(xy_or_WI, vision_radius) for x, y in scan_area: coord_contents = self.world[x][y] for content in coord_contents: if self.has_attr(content, attr): return x, y return self.coord_parse(xy_or_WI) def actor_turn_effects(self, actor_turn): """ Receive a turn and determine if it has any reprocussions. :param actor_turn: the delta that the actor wants to execute :return: delta of any direct changes that have occured. """ effects = [] if not actor_turn: return [] if not isinstance(actor_turn, list): actor_turn = [actor_turn] # Calculate side effects of the actor's turn. for delta in actor_turn: actor = self.get_actor(delta['actorID']) if delta['varTarget'] == "_coords": new_x = delta["to"][0] new_y = delta["to"][1] coord_contents = self.world.get_cell((new_x, new_y)) if self.has_attr(coord_contents, "WATER"): effects.append({ "type": "actorDelta", "coords": {'x': new_x, 'y': new_y}, "actorID": actor.uuid, "varTarget": "health", "from": actor.health, "to": 0, "message": actor.name + " has drowned!" }) if self.has_attr(coord_contents, "DEADLY"): effects.append({ "type": "actorDelta", "coords": {'x': new_x, 'y': new_y}, "actorID": actor.uuid, "varTarget": "health", "from": actor.health, "to": actor.health-50 }) # Check if actor is alive if delta['varTarget'] == 'health': if delta['to'] <= 0: effects.append({ "type": "actorDelta", "coords": {'x': delta["coords"]['x'], 'y': delta["coords"]['y']}, "actorID": actor.uuid, "varTarget": "is_alive", "from": True, "to": False, "message:": actor.name + " has died!" }) if delta['varTarget'] == 'hunger': if delta['to'] == False: effects.append({ "type": "actorDelta", "coords": {'x': self.x, 'y': self.y}, "actorID": self.uuid, "varTarget": "has_food", "from": True, "to": False }) # Calculate any side effects of the side effects. old_effects = effects while old_effects: new_effects = self.actor_turn_effects(old_effects) old_effects = new_effects effects.extend(old_effects) return effects def global_turn_effects(self): """Calculate the effects of this turn not necessarily related to actor action.""" effects = [] for u, actr in self.actors.items(): if not actr.is_alive: continue if actr.sleep <= 1 and not actr.is_sleeping: sleep_action = actr.sleep_action() sleep_action['message'] = actr.name + " is exhauseted and fell asleep!" effects.append(sleep_action) if actr.sleep >= 100 and actr.is_sleeping: wake_action = actr.wake_action() wake_action['message'] = actr.name + " is fully rested and has woken up!" effects.append(wake_action) if actr.hunger <= 1: effects.append({ "type": "actorDelta", "coords": {'x': actr.x, 'y': actr.y}, "actorID": actr.uuid, "varTarget": "health", "from": actr.health, "to": actr.health-5, "message": actr.name + " is starving!" }) return effects def do_turn(self, up_to=0): """High level function for returning a list of turns in this game.""" all_turns = [] while self.current_turn < up_to: this_turn = {'number': self.current_turn, 'deltas': [], } self.current_turn += 1 this_turn['diff'] = self.world.apply_updates() #Returns diff each call. They should be stored though. self.compute_smells() for uuid, actor in self.actors.items(): turn_res = [] aturn = actor.do_turn() if aturn: turn_res.append(aturn) effects = self.actor_turn_effects(turn_res) if effects: turn_res.extend(effects) if turn_res: self.apply_deltas(turn_res) this_turn['deltas'].extend(turn_res) global_effects = self.global_turn_effects() self.apply_deltas(global_effects) this_turn['deltas'].extend(global_effects) all_turns.append(this_turn) return all_turns def apply_deltas(self, delta_list, reverse=False): """Apply the deltas produced during turns.""" for delta in delta_list: if reverse: val = delta['from'] else: val = delta['to'] actr = self.get_actor(delta['actorID']) if delta['varTarget'] == '_coords': self.move_actor(actr, val) if delta['varTarget'] == 'health': actr.health = val if delta['varTarget'] == 'is_sleeping': actr.is_sleeping = val if delta['varTarget'] == 'has_rock': if (delta['to'] == True): actr.has_rock = val elif (delta['to'] == False): actr.has_rock = val if delta['varTarget'] == 'has_food': if (delta['to'] == False): actr.has_food = val if (delta['to'] == True): actr.has_food = val if reverse: for act in self.actors.values(): act._turn_stat_change(reverse=True) def to_dict(self, withseed=True): d = self.world.to_dict(withseed=withseed) d['current_turn'] = self.current_turn return d def _coord_neighbors(self, xy): x, y = xy return (x-1, y), (x+1, y), (x,y-1), (x, y+1) def compute_smells(self): self.smell_matrix = defaultdict(list) for act in self.actors.values(): self._bfs_smell_spread(act) def _bfs_smell_spread(self, world_inhabitant): smell_code = world_inhabitant.smell_code x, y = world_inhabitant._coords z = self.world.get_cell((x, y)).elevation q = deque() visited = set() neighbors = world_inhabitant.neighbors q.extendleft(neighbors) visited.add(world_inhabitant._coords) visited = visited.union(neighbors) # BFS to populate smell matrix for the turn. while q: # get first coord x1, y1 = q.pop() z1 = self.world.get_cell((x1,y1)).elevation x2,y2,z2 = x1-x, y1-y, z1-z intensity = math.exp(-(x2**2 + y2**2 + z2**2)/SMELL_SPREAD) if intensity > .3: # get its unvisited neighbors and put them in their place. neighbors = set(self._coord_neighbors((x1, y1))) neighbors = neighbors.difference(visited) q.extendleft(neighbors) visited = visited.union(neighbors) self.smell_matrix[(x1, y1)].append((smell_code, intensity))
'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)
# Make sure we are actually rolling dice a_colors, a_roll = ship_1.roll("front", attack_range) if 0 < len(a_colors): roll_counts = [] print("{} vs {} at range {}".format(ship_name_1, ship_name_2, attack_range)) logging.info("{} vs {} at range {}".format( ship_name_1, ship_name_2, attack_range)) for trial in range(250): 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(
def __init__(self): self.current_state = WorldState.generate_random_state()
""" # begin homework 2 : problem 1 # Flip the coin... # Determine percentage in front of door # end homework 2 : problem 1 return True # set the probabilities based on the gui def set_probabilities(self, in_prob_see_door_if_door, in_prob_see_door_if_not_door): self.prob_see_door_if_door = in_prob_see_door_if_door self.prob_see_door_if_no_door = in_prob_see_door_if_not_door if __name__ == '__main__': ws = WorldState() ds = DoorSensor() rs = RobotState() # Robot should be at 0.5, no door at 0.5, so this should be false print("Testing probabilities for robot NOT in front of door") rs.robot_loc = ws.place_robot_NOT_in_front_of_door() if ds.is_in_front_of_door(ws, rs): raise ValueError("The robot should NOT be in front of a door") # Check that we get our probabilites back (mostly) count_returned_true = 0 for i in range(0, 1000): if ds.sensor_reading(ws, rs) == True: