class Wife(BaseGameEntity):
    def __init__(self, name='wife', wid=None, location=Location.shack):
        super().__init__()

        if wid != None:
            #override the assigned id
            self.id = wid

        self.name = name
        self.location = location
        self.cooking = False
        self.state_machine = StateMachine(self)
        self.state_machine.current_state = DoHouseWork.instance()
        self.state_machine.global_state = WifeGlobalState.instance()

    def change_location(self, new_location):
        self.location = new_location

    def update(self):
        self.state_machine.update()

    def handle_message(self, msg):
        return self.state_machine.handle_message(msg)

    def __repr__(self):
        return self.name
class Wife(BaseGameEntity):
    
    def __init__(self,name='wife',location=Location.shack):
        super().__init__()

        self.name = name
        self.location = location
        self.state_machine = StateMachine(self)
        self.state_machine.current_state = DoHouseWork.instance()
        self.state_machine.global_state = WifeGlobalState.instance()

    def change_location(self, new_location):
        self.location = new_location

    def update(self):
        self.state_machine.update()

    def __repr__(self):
        return self.name
class Miner(BaseGameEntity):
    COMFORT_LEVEL = 5
    MAX_NUGGETS = 3
    THIRST_LEVEL = 5
    TIREDNESS_THRESHOLD = 5
    
    def __init__(self,name='anonymous'):
        super().__init__()

        self.location = Location.shack
        self.gold_carried = 0
        self.money_in_bank = 0
        self.thirst = 0
        self.fatigue = 0
##        self.current_state = GoHomeAndSleepTilRested.instance()
        self.name = name
        self.state_machine = StateMachine(self)
        self.state_machine.current_state = GoHomeAndSleepTilRested.instance()

##    def change_state(self, new_state):
##        self.current_state.exit( self )
##        self.current_state = new_state
##        self.current_state.enter(self)

    def add_to_gold_carried(self, val):
        self.gold_carried += val
        self.gold_carried = max(0, self.gold_carried)

    def add_to_wealth(self, val):
        self.money_in_bank += val
        self.money_in_bank = max(0, self.money_in_bank)

    def thirsty(self):
        return self.thirst >= self.THIRST_LEVEL

    def fatigued(self):
        return self.fatigue >= self.TIREDNESS_THRESHOLD

    def pockets_full(self):
        return self.gold_carried >= self.MAX_NUGGETS

    def buy_and_drink_whiskey(self):
        self.thirst = 0
        self.money_in_bank -= 2

    def change_location(self,new_location):
        self.location = new_location

    def increase_fatigue(self):
        self.fatigue += 1

    def decrease_fatigue(self):
        self.fatigue -= 1

    def wealth(self):
        return self.money_in_bank

    def update(self):
        self.thirst += 1
        self.state_machine.update()
##        if self.current_state:
##            self.current_state.execute(self)

    def __repr__(self):
        return self.name
class Miner(BaseGameEntity):
    COMFORT_LEVEL = 5
    MAX_NUGGETS = 3
    THIRST_LEVEL = 5
    TIREDNESS_THRESHOLD = 5

    def __init__(self, name='anonymous', mid=None):
        super().__init__()

        if mid != None:
            #override the assigned id if the user passes one in
            self.id = mid

        self.name = name
        self.location = Location.saloon
        self.gold_carried = 0
        self.money_in_bank = 0
        self.thirst = 0
        self.fatigue = 0
        self.state_machine = StateMachine(self)
        self.state_machine.current_state = GoHomeAndSleepTilRested.instance()

    def change_state(self, new_state):
        self.current_state.exit(self)
        self.current_state = new_state
        self.current_state.enter(self)

    def add_to_gold_carried(self, val):
        self.gold_carried += val
        self.gold_carried = max(0, self.gold_carried)

    def add_to_wealth(self, val):
        self.money_in_bank += val
        self.money_in_bank = max(0, self.money_in_bank)

    def thirsty(self):
        return self.thirst >= self.THIRST_LEVEL

    def fatigued(self):
        return self.fatigue >= self.TIREDNESS_THRESHOLD

    def pockets_full(self):
        return self.gold_carried >= self.MAX_NUGGETS

    def buy_and_drink_whiskey(self):
        self.thirst = 0
        self.money_in_bank -= 2

    def change_location(self, new_location):
        self.location = new_location

    def increase_fatigue(self):
        self.fatigue += 1

    def decrease_fatigue(self):
        self.fatigue -= 1

    def wealth(self):
        return self.money_in_bank

    def update(self):
        self.thirst += 1
        self.state_machine.update()

    def handle_message(self, msg):
        return self.state_machine.handle_message(msg)

    def __repr__(self):
        return self.name
class SoccerTeam:
    def __init__(self,
                 side,
                 pitch,
                 display_model=model.initial_model,
                 entity_manager=model.initial_model.entity_manager,
                 dispatcher=model.initial_model.dispatcher):
        # self.model = model
        self.pitch = pitch
        self.view = View(display_model)
        self.view.model = self
        self.side = side
        self._entity_manager = entity_manager
        self._dispatcher = dispatcher

        if side == HOME:
            self.color = pg.Color('red')
            self.goal = self.pitch.home_goal
            self.opponent_goal = self.pitch.away_goal
            self.init_heading = Vector2(-1, 0)

        elif side == AWAY:
            self.color = pg.Color('blue')
            self.goal = self.pitch.away_goal
            self.opponent_goal = self.pitch.home_goal
            self.init_heading = Vector2(1, 0)

        else:
            raise ValueError("side must be either 'HOME' or 'AWAY' ")

        self.players = self.create_players()
        self.opponent = None

        self._controlling_player = None
        self._supporting_player = None
        self._receiving_player = None
        self.player_closest_to_ball = None

        self.dist_sq_to_ball_from_closest_player = sys.float_info.max
        self.support_spot_calculator = SupportSpotCalculator()

        self.fsm = StateMachine(self)
        self.fsm.current_state = TeamState.defending
        self.fsm.previous_state = TeamState.defending
        self.fsm.global_state = None

        #force the state enter logic to run for initial state
        # self.fsm.current_state.enter(self)

    def __call__(self):
        return self.players

    def create_players(self):
        players = []

        if self.home_team:
            regions = [
                self.pitch.pos_from_region(region)
                for region in [11, 16, 15, 4, 2]
            ]
        else:
            regions = [
                self.pitch.pos_from_region(region)
                for region in [1, 6, 8, 3, 5]
            ]

        # goal keeper
        if self.side == HOME:
            image_file = 'redshirt'
        else:
            image_file = 'blueshirt'

        print('create_players(): image_file, pitch = ', image_file, self.pitch,
              self, regions[0], self.init_heading)
        goalkeeper = GoalKeeper(image_file + '0',
                                self.pitch,
                                team=self,
                                home=regions[0],
                                heading=self.init_heading)

        print(' goalkeeper velocity = ', goalkeeper.velocity)
        players.append(goalkeeper)

        # rest of the team
        for idx, region in enumerate(regions[1:]):
            player = FieldPlayer(image_file + str(idx),
                                 self.pitch,
                                 team=self,
                                 home=region,
                                 heading=self.init_heading)

            players.append(player)

        return players

    def calculate_closest_player_to_ball(self):
        closest_so_far = sys.float_info.max
        distances = [
            p.exact_pos.distance_to(self.pitch.ball()) for p in self.players
        ]

        return min(distances)

    def draw(self, screen):
        for player in self.players:
            player.draw(screen)

        # self.view.draw(screen)

    def update(self, dt):
        #calculate this once per frame
        self.calculate_closest_player_to_ball()

        #the team state machine switches between attack/defense behavior. It
        #also handles the 'kick off' state where a team must return to their
        #kick off positions before the whistle is blown
        self.fsm.update()

        for player in self.players:
            player.update(dt)

    def return_all_field_players_home(self):
        for player in self.players:
            dispatcher.dispatch_message(Message.SEND_MSG_IMMEDIATELY, -1,
                                        player.id, Message.GO_HOME, None)

    def can_shoot(self, ball_pos, power, shot_target=Vector2()):
        pass

    def find_pass(self, passer, receiver, pass_target, power,
                  min_passing_distance):
        pass

    def get_best_pass_to_receiver(self, passer, receiver, pass_target, power):
        pass

    def is_pass_safe_from_opponent(self, phrom, target, receiver, opp,
                                   passing_force):
        pass

    def is_pass_safe_from_all_opponents(self, phrom, target, receiver,
                                        passing_force):
        pass

    def is_opponent_within_radius(self, pos, radius):
        pass

    def request_pass(self, requester):
        pass

    def determine_best_supporting_attacker(self):
        pass

    def get_support_spot(self):
        ##        return self.support_spot_calculater.get_best_spot()
        pass

    def get_player_from_id(self, player_id):
        pass

    def set_player_home_region(self, player, region):
        pass

    def determine_best_supporting_position(self):
        return self.support_spot_calculator.determine_best_supportin
        pass

    def update_targets_of_waiting_players(self):
        pass

    def all_players_at_home(self):
        return all([p.at_home for p in self.players])

    def change_state(self, nextState):
        self.fsm.change_state(nextState)

    @property
    def home_team(self):
        return self.side == HOME

    @property
    def away_team(self):
        return self.side == AWAY

    @property
    def in_control(self):
        return self.controlling_player != None

    @property
    def receiving_player(self):
        return self._receiving_player

    @receiving_player.setter
    def receiving_player(self, player):
        self._receiving_player = player

    @property
    def controlling_player(self):
        return self._controlling_player

    @controlling_player.setter
    def controlling_player(self, player):
        self._controlling_player = player

    @property
    def supporting_player(self):
        return self._supporting_player

    @supporting_player.setter
    def supporting_player(self, player):
        self._supporting_player = player
        self.opponent.lost_control()

    def __repr__(self):
        if self.color == 'red':
            return 'Red'
        else:
            return 'Blue'
Esempio n. 6
0
class BasePlayer(MovingEntity):
    # max_speed_with_ball = None
    # receiving_range = None

    # @classmethod
    # def initialize_class_parameters(cls,**kwargs):
    #       cls.max_speed_with_ball = kwargs['max_speed_with_ball']
    #       cls.receiving_range = kwargs['receiving_range']

    def __init__(self,
                 image,
                 pitch,
                 team,
                 home,
                 heading,
                 model=model.initial_model,
                 **kwargs):
        super().__init__('redshirt0')  #image,  **kwargs)

        self.max_turn_rate = model.player_max_turn_rate
        self.max_force = model.player_max_force
        self.max_speed = model.player_max_speed

        #register with the entity_manager
        model.entity_manager.register(self)

        self.home = Vector2(home)
        self.pos = Vector2(home)
        self.mass = model.player_mass
        # self.velocity = Vector2()
        # self.heading = Vector2(heading)
        _, self.angle = Vector2(heading).as_polar()

        print('...creating player{}: @ position {}, angle {}'.format(
            self.id, self.pos, self.angle))

        # in case the velocity is zero
        if self.speed < 0.00001:
            self.angle = 0.0
            # self.set_orientation(Vector2(heading))

        self.model = model
        self.max_speed_with_ball = model.player_max_speed_with_ball
        self.receiving_range = model.ball_within_receiving_range
        self.role = None
        self.pitch = pitch
        self.team = team

        self.steering = SteeringBehaviors(self)
        self.steering.separation_on()

        self.state = PState.wait
        self.fsm = StateMachine(self)
        self.fsm.current_state = self.state
        self.fsm.previous_state = self.state
        self.fsm.global_state = PState.global_player
        self.fsm.current_state.enter(self)

        # TODO: implement and test regulator
        # self.kick_limiter = Regulator(self.model.player_kick_frequency)

    def update(self, dt):
        self.fsm.update()
        self.steering.calculate()

        #apply braking if there is no steering force but there is velocity
        if self.steering.steering_force.length() < 0.0001 and (
                self.velocity.length_squared() > 0.001):
            braking_rate = 0.8
            self.velocity *= braking_rate

        # first calculate the speed change due to the force

        #FORWARD COMPONENT CALC
        # get the components now because updating the angle and
        # velocity will change the computations
        forward_component = self.steering.forward_component()
        side_component = self.steering.side_component()

        # first calculate the velocity change due to turning

        dAngle = (side_component * self.max_turn_rate)
        # this will adjust the heading...
        self.angle -= dAngle

        speed = abs(forward_component) * self.max_speed
        self.velocity = (speed / self.mass) * self.heading

        #FORWARD COMPONENT CALC
        # accel = self.heading *  forward_component/ self.mass
        # self.velocity += accel

        # self.exact_pos += self.velocity

        # self.exact_pos +=  speed * self.heading #self.velocity
        self.exact_pos = self.exact_pos + self.velocity

        # if debug_output:
        #       print('   prevPos = {}  position={}'.format(self.prev_pos, self.exact_pos))
        #       print('---END UPDATE\n\n')

    def draw(self, screen):
        super().draw()

        #
        # Show Rendering Aids - Steering_Force
        #

        #DEBUG
        screen.draw.circle(self.home, 10, (255, 0, 0))
        # if self.at_home():

        #print ID
        screen.draw.text(str(self.id), self.exact_pos + Vector2(0, -20))

        if self.model.show_steering_force:
            screen.draw.line(
                self.exact_pos,
                self.exact_pos + self.model.steering_force_display_length *
                self.steering.steering_force, (200, 0, 0))

        if self.model.show_player_states:
            states = ""
            if self.steering.is_seek_on():
                states += "S"
            if self.steering.is_arrive_on():
                states += "A"
            if self.steering.is_separation_on():
                states += "Sp"
            if self.steering.is_pursuit_on():
                states += "P"
            if self.steering.is_interpose_on():
                states += "I"

            if len(states) > 0:
                offset = self.exact_pos + (self.heading * 5) + Vector2(0, 5)
                screen.draw.text(states, offset)

        if self.model.show_heading:
            screen.draw.line(self.exact_pos,
                             self.exact_pos + 50 * self.heading, (0, 255, 0))
            screen.draw.line(self.exact_pos, self.exact_pos + 50 * self.side,
                             (0, 0, 255))

    def ball_within_receiving_range(self):
        return self.exact_pos.distance_to(self.ball()) < self.receiving_range

    def track_ball(self):
        return self.rotate_heading_to_face_position(self.ball())

    def is_controlling_player(self):
        return False

    def at_home(self):
        return self.at_target(self.home)
        # return self.exact_pos.distance_to(self.home) < 0.001

    def at_target(self, target):
        if self.id == 1:
            print('[FieldPlayer.at_target] pos: {}, target: {}, dist: {} '.
                  format(self.exact_pos, target,
                         self.exact_pos.distance_to(Vector2(target))))
            print('    vel= {}, speed= '.format(self.velocity, self.speed))
        return self.exact_pos.distance_to(Vector2(target)) < 1.0

    def arrive_on(self):
        self.steering.on(BehaviorType.ARRIVE)

    def arrive_off(self):
        self.steering.off(BehaviorType.ARRIVE)

    @property
    def tagged(self):
        return self.steering.tagged

    @property
    def ball(self):
        return self.pitch.ball

    def __repr__(self):
        if 'GoalKeeper' in str(type(self)):
            position = '*'
        else:
            position = ''
        return '{{[player{}{}] {}}}'.format(self.id, position, self.exact_pos)