Ejemplo n.º 1
0
 def resolve(self):
     """
     Return combined result of all steering behaviours.
     """
     acc=Vector(0,0)
     #if type(self.player.state) == Player.RxAttack:
     #    pdb.set_trace()
     if self._avoid_defenders_on:
         acc += self.avoid_defenders() * self.w_avoid_defenders
     if self._seek_on:
         acc += self.seek() * self.w_seek
     if self._seek_end_zone_on:
         acc += self.seek_end_zone() * self.w_seek_end_zone
     if self._avoid_walls_on:
         acc += self.avoid_walls() * self.w_avoid_walls
     if self._pursue_on:
         acc += self.pursue() * self.w_pursue
     if self._block_on:
         acc += self.block() * self.w_block
     if self._avoid_friends_on:
         acc += self.avoid_friends() * self.w_avoid_friends
     if self._zone_defend_on:
         acc += self.zone_defend() * self.w_zone_defend
     if self._guard_on:
         acc += self.guard() * self.w_guard
     if self._stay_in_range_on:
         acc += self.stay_in_range() * self.w_stay_in_range
     if self._avoid_end_zone_on:
         acc += self.avoid_end_zone() * self.w_avoid_end_zone
     if self._arrive_at_speed_on:
         acc += self.arrive_at_speed() * self.w_arrive_at_speed
     return acc.truncate(self.player.top_acc)
Ejemplo n.º 2
0
class Player(Entity.Entity):
    """
    Player base class. Implements a general all-rounder position.
    """
    def __init__(self,message_handler,role,pitch,xstart,ystart,top_speed=10.,acc=10.,strength=5.,throw_power=30.,\
                 stamina=100.,tough=100.,block_skill=5.,catch_skill=70.,mass=1.):
        super(Player,self).__init__(message_handler)
        self.team=None
        self.role=role
        self.pitch=pitch
        self.size=1.
        self.xstart=xstart
        self.ystart=ystart
        self.top_speed=top_speed
        self.top_acc=acc
        self.stamina=stamina
        self.tough=tough
        self.strength=strength
        self.throw_power=throw_power
        self.block_skill=block_skill
        self.catch_skill=catch_skill
        self.mass=mass
        # Experimental linear drag locomotion model
        self.drag = self.top_acc/self.top_speed
        # Damage and exhaustion counters
        self.puff = self.stamina
        self._health = self.tough 
        self._state = None
        self._move_state = None

    def setup(self):
        """
        Call to reset to neutral state at starting position.
        """
        self.pos = Vector(self.xstart,self.ystart)
        self.vel = Vector(0.,0.)
        self.acc = Vector(0.,0.)
        self.standing=True
        self._prone=-1.
        # Are we trying to catch the ball?
        self.want_to_catch=True
        self._state=None
        self._move_state=None

    @property
    def move_state(self):
        return self._move_state
    
    @move_state.setter
    def move_state(self,new_state):
        try:
            self._move_state.exit()
        except:
            pass
        finally:
            self._move_state=new_state        
            self._move_state.enter()

    @property
    def prone(self):
        return self._prone
    
    @prone.setter
    def prone(self,value):
        if value < 0.:
            self.standing = True
        else:
            self.standing = False
            if self.has_ball:
                self.drop_ball()
            if self.in_contact:
                self.pitch.remove_all_contact(self)
        self._prone=value
    
    @property
    def health(self):
        return self._health

    @health.setter
    def health(self,value):
        if value < 0.:
            msg = (self.team,self,'tap_out')
            self.message_handler.add(msg)

    def get_message(self,msg):
        """
        Only messages content looked at for the moment.
        """

        if msg.subject == "ball_flying":
            self.state = self.role['ball_flying'](self)
        elif msg.subject == "ball_loose":
            self.state = self.role['ball_loose'](self)
        elif msg.subject == "ball_held":
            if self.has_ball:
                self.state = self.role['ball_carrier'](self)
            elif self.team_in_possession:
                self.state = self.role['attack'](self)
            else:
                self.state = self.role['defence'](self)
        elif msg.subject == "setup":
            self.setup()
        else:
            if not self.state.get_message(msg):
                if not self.move_state.get_message(msg):
                    print("Uncaught message " + msg.subject)    
    
    @property
    def attack_end_zone_x(self):
        return self.team.attack_end_zone_x
    
    @property
    def defend_end_zone_x(self):
        return self.team.defend_end_zone_x

    @property
    def dist_to_attack_end_zone(self):
        return (self.attack_end_zone_x - self.x)*self.team.direction

    @property
    def dist_to_defend_end_zone(self):
        return (self.x - self.defend_end_zone_x)*self.team.direction

    @property
    def opposite_team(self):
        return self.team.opposite_team

    @property
    def direction(self):
        return self.team.direction    

    @property
    def has_ball(self):
        return self.pitch.ball.carrier == self

    @property
    def in_contact(self):
        return self in self.pitch.contacts.keys()

    @property
    def team_name(self):
        if self.team.direction > 0:
            return('home')
        else:
            return('away')

    @property
    def team_in_possession(self):
        return self.team.in_possession

    def x_from_defend_end_zone(self,x):
        if self.team.direction > 0:
            return x
        else:
            return self.pitch.xsize-x  

    def move(self):

        # NOTE: Ignores mass! (assumes m=1 I guess)
        # Don't move if we are prone
        if not self.standing:
            # Prone players might still be moving, but they rapidly deccelerate!
            # Magic numbers
            prone_acc = 20.
            prone_top_speed = 5.
            desired_acc = self.vel.norm() * prone_acc * self.pitch.dt * -1.
            if self.vel.mag() < desired_acc.mag():
                self.vel=Vector(0,0)
            else:
                self.vel += desired_acc
                self.vel = self.vel.truncate(prone_top_speed)
                self.pos += self.vel * self.pitch.dt
            return
        elif self.in_contact:
            # Push resolved seperately
            return
        acc = self.current_acc()
        # Check current puff reduced acc
        # NOTE HACK: Current states consider current vel in providing desired acc
        # We undo this so that they return the actual desired velocity
        state_vel = self.move_state.execute()
        desired_vel = state_vel + self.vel 
        drag_limited_acc = acc * (1. - desired_vel.angle_factor(self.vel) * self.vel.mag() / self.top_speed)
        desired_acc = (desired_vel - self.vel).truncate(drag_limited_acc)
        self.vel += desired_acc * self.pitch.dt
        self.vel = self.vel.truncate(self.top_speed)
        self.pos += self.vel * self.pitch.dt
        # It costs puff to move
        self.puff -= desired_acc.mag() * self.pitch.dt * self.pitch.puff_fac

    def push(self):
        if not self.in_contact: return
        # NOTE: Pushing forwards always, but we don't always want to do that. Need to have hook
        # into state and define in states the push directions ( a parrallel steering behaviours).
        
    def current_acc(self):
        " Current puff reduced max accel."
        cut_in=0.5
        ability_floor=0.5
        #NOTE: Turned off for now to allow easier state debugging
        return self.top_acc
        # Reduce ability linearily after cut in, down to floor
        ratio = self.puff/self.stamina
        if ratio < cut_in:
            fac = ratio*(1.-ability_floor)/cut_in + ability_floor
        else:
            fac = 1.
        return fac*self.top_acc

    def standup(self):
        """
        Check if player is prone and if so whether they can stand yet.
        """
        # Done via property now (but is it working?)
        #if self.prone > 0.:
        self.prone -= self.pitch.dt
        #    if self.prone <= 0.:
        #        self.standing=True
    
    def drop_ball(self):
        self.send(self.pitch.ball,'ball_loose')