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'
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)