Пример #1
0
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)
Пример #3
0
    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
Пример #5
0
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
Пример #7
0
    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
Пример #9
0
    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()
Пример #10
0
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),
Пример #12
0
        # 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.
Пример #13
0
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.))
Пример #14
0
        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):
Пример #15
0
    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:
Пример #16
0
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))
Пример #17
0
        '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)
Пример #18
0
 # 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(
Пример #19
0
 def __init__(self):
     self.current_state = WorldState.generate_random_state()
Пример #20
0
        """
        # 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: