Example #1
0
 def getOpen(self, respectivePos):
     keeper = self
     stepIncrease = 5
     maximum = -9999
     #the threshold is compared to cosTheta. so 0 means the windows has to be at least 90 degrees. 
     #1.0 is most flexible value as it's saying the angle has to be at least 0
     threshold = 0.9
     maxPoint = None
     tempmaximum = -9999
     tempmaxPoint = None
     playersToIterate = []
     for isKeeper in self.keeperArray:
         if isKeeper != self:
             playersToIterate.append(isKeeper)
     for taker in self.takerArray:
         playersToIterate.append(taker)
             
     pointsToIterate = [(self.true_pos[0],self.true_pos[1]+stepIncrease),
                         (self.true_pos[0]+stepIncrease,self.true_pos[1]),
                         (self.true_pos[0]+stepIncrease,self.true_pos[1]+stepIncrease),
                         (self.true_pos[0]-stepIncrease,self.true_pos[1]-stepIncrease),
                         (self.true_pos[0]-stepIncrease,self.true_pos[1]),
                         (self.true_pos[0],self.true_pos[1]-stepIncrease),
                         (self.true_pos[0]-stepIncrease,self.true_pos[1]+stepIncrease),
                         (self.true_pos[0]+stepIncrease,self.true_pos[1]-stepIncrease),]
         
     for point in pointsToIterate:
         if kUtil.cosTheta(point, respectivePos, self.takerArray[0].true_pos)>threshold and kUtil.cosTheta(point, respectivePos, self.takerArray[1].true_pos)>threshold:
             spar = 0
             for player in playersToIterate:
                 spar += kUtil.getDist(player.true_pos, point)
                 
             if spar>tempmaximum:
                 tempmaximum = spar
                 tempmaxPoint = point
             continue
         else:
             spar = 0
             for player in playersToIterate:
                 spar += kUtil.getDist(player.true_pos, point)
                 
             if spar>maximum:
                 maximum = spar
                 maxPoint = point
         
     if maxPoint == None:
         #print("no open position available for agent #", self.agentListIndex + 1)
         maxPoint = tempmaxPoint
             
     #return (kUtil.getVector(keeper.true_pos, maxPoint),stepIncrease)
     self.worldRef.moveAttempt(self, (kUtil.getVector(keeper.true_pos, maxPoint), self.maxPlayerSpeed))
Example #2
0
 def __lt__(self, other):
     """
     this function is simply used to allow comparision between different agents, so
     that agents can be sorted. Agents are sorted based on which agent is closest to
     the ball. So now, the simulator can call sorted(agents), and an array of all the 
     agents is returned such that the agents are sorted based on who is closest to the ball.
     
     :returns: if self is closer to the ball than the other agent
     :rType: boolean
     """
     if self.onReceiveDecision == None:
         return kUtil.getDist(self.__noisy_pos, self.noisyBallPos) < kUtil.getDist(other.get_noisy_pos(), other.noisyBallPos)
     else:
         return kUtil.getDist(self.__noisy_pos, self.onReceiveDecision[1]) < kUtil.getDist(other.get_noisy_pos(), other.onReceiveDecision[1])
Example #3
0
 def __blockPass(self, kIndex):
     """
     This function will take a keeper to block as a parameter. The keeper 
     that this taker is trying to block should NOT have the ball. 
     This function works by taking the position of the keeper with the ball, 
     and the position of the keeper to block, and making the taker run to the 
     midpoint of these 2 positions. In 3V2 keepaway, this function should be 
     implemented by the taker farther from the ball. 
     
     :param kIndex: the index of the keeper to take, sorted by distance. so kIndex = 1 means
         the keeper who is closest to the ball besides the keeper who has the ball. 
         kIndex = 2 means the 2nd closest keeper, and so on. 
     :type kIndex: integer
     
     :returns: nothing
     """
     #kIndex is ordered based on who is the closest keeper
     keeperActual = sorted(self.keeperArray)
     #use the current keeper 0 position to block pass
     midPoint = kUtil.getMidPoint(keeperActual[0].get_noisy_pos(), keeperActual[kIndex].get_noisy_pos())
     #use the predicted keeper 0 position to block pass
     #midPoint = kUtil.getMidPoint(self.onReceiveDecision[1], keeperActual[kIndex].noisy_pos)
     vector = kUtil.getVector(self.__noisy_pos, midPoint)
     minDist = min(self.maxPlayerSpeed, kUtil.getDist(self.__noisy_pos, midPoint))
     self.worldRef.moveAttempt(self, (vector, minDist))
Example #4
0
 def __getOpen(self):
     """
     This function implements a hand coded procedure to go and place individual agents
     in an optimal position to receive a pass. The code for this function is 
     based heavily on "Algorithm 2 GetOpen:Hand-coded", which is the pseudo-code
     for the getOpen function used by some other researchers and was published 
     here:
     http://www.cs.utexas.edu/users/pstone/Papers/bib2html-links/LNAI09-kalyanakrishnan-1.pdf
     
     Only keeper who are not trying to go after the ball should call this method.
     The decision for who goes after the ball or gets open is deterministic. 
     
     :returns: nothing
     """
     #note: safety constant is cos(18.4) degrees
     safetyConstant = 0.94887601164449654493424118056447
     curMax = float("-inf")
     argMax = self.getOpenPoints[12] #default case
     if self.worldRef.fieldBall.trueBallDirection == (0.0, 0.0):
         predictedBallPos = self.noisyBallPos
     else:
         predictedBallPos = self.onReceiveDecision[1]
     for point in self.getOpenPoints:
         safety = max(kUtil.cosTheta(point, predictedBallPos, self.takerArray[0].get_noisy_pos()),
                      kUtil.cosTheta(point, predictedBallPos, self.takerArray[1].get_noisy_pos()))
         if (safety > safetyConstant):
             #angle is too narrow, a taker can easily steal
             continue
         
         #if you're at this point, then then point is a safe point to consider
         teamCongestion = 0.0
         oppCongestion = 0.0
         totalCongestion = 0.0
         value = 0.0
         for i in range(len(self.keeperArray)):
             if i != self.agentListIndex:
                 teamCongestion += 1.0 / (kUtil.getDist(self.keeperArray[i].get_noisy_pos(), point))
         for i in range(len(self.takerArray)):
             oppCongestion += 1.0 / (kUtil.getDist(self.takerArray[i].get_noisy_pos(), point))
         totalCongestion = teamCongestion + oppCongestion
         value = -1.0 * totalCongestion
         if (value > curMax):
             curMax = value
             argMax = point
     #At this point, just run towards argMax at max speed
     minDist = min(self.maxPlayerSpeed, kUtil.getDist(self.__noisy_pos, argMax))
     self.worldRef.moveAttempt(self, (kUtil.getVector(self.__noisy_pos, argMax), minDist) )
Example #5
0
 def calcOptimal(self, agentList, i, intersect):
     V = kUtil.getVector(self.fieldBall.trueBallPos, intersect)
     UV = kUtil.unitVector(V)
     stepVector = kUtil.scalarMultiply(self.maxBallSpeed, UV)
     #keep adding the step vector to the optimal point
     optimalPoint = self.fieldBall.trueBallPos
     maxNumSteps = int(kUtil.getDist(self.fieldBall.trueBallPos, intersect)/ self.maxBallSpeed)
     stepCount = 0
     for k in range(maxNumSteps):
         optimalPoint = kUtil.addVectorToPoint(optimalPoint, stepVector)
         stepCount += 1
         currPd = kUtil.getDist(optimalPoint,agentList[i].true_pos)
         currBd = kUtil.getDist(self.fieldBall.trueBallPos, optimalPoint)
         currPt = currPd / self.maxPlayerSpeed
         currBt = currBd / self.maxBallSpeed
         if currPt < currBt:
             #found the optimal, so return it
             return optimalPoint
     #if you get here, then no closer optimal was found, so just return the intersect
     return intersect
Example #6
0
    def __goToBall(self):
        """
        If a keeper is calling this method, then this method will make the keeper
        run directly towards the ball if the ball is stationary. If the ball is 
        not stationary, then the simulator will use the calcReceieve methods in 
        order to calculate the optimal intersection point that the keeper can 
        run to. The keeper will then run towards that intercept point using 
        this function. The only keeper that should be running to the ball is 
        the keeper that can get to the ball the fastest. all other keepers should
        be implementing the getOpen() function. 
        
        For a taker, the taker will simply run towards the ball. The taker that is 
        closest to the ball should call this function, while the taker that is farther
        should try to block a pass with blockPass method.
        
        :returns: no return
        
        .. note::
            For keepers, this function will use information that is set when the simulator calls
            the agent method receiveDecision. Do not call __goToBall for a keeper unless that
            simulator function has been called. 

        """
        if (self.__agentType == "keeper"):
            V = kUtil.getVector(self.__noisy_pos, self.onReceiveDecision[1])
            minDist = min(self.maxPlayerSpeed, kUtil.getDist(self.__noisy_pos, self.onReceiveDecision[1]))
        else:
            #you have a taker. have him be stupider by going to the ball rather than the intersection point
            V = kUtil.getVector(self.__noisy_pos, self.noisyBallPos)
            minDist = min(self.maxPlayerSpeed, kUtil.getDist(self.__noisy_pos, self.noisyBallPos))
        
        #these 2 lines of code are for if you want keepers and takers to go to same location
        #this is the more challenging case as the taker will predict where the ball intersects
        """
        V = kUtil.getVector(self.__noisy_pos, self.onReceiveDecision[1])
        minDist = min(self.maxPlayerSpeed, kUtil.getDist(self.__noisy_pos, self.onReceiveDecision[1]))
        """
        
        self.worldRef.moveAttempt(self, (V, minDist))
def __distCenter(inputAgent, center):
    """
    calculate the distance from the given agent to the center of the field
    
    :param inputAgent: the agent you're trying to find the distance from
    :param center: a coordinate representing the center of the field
    
    :type inputAgent: agent
    :type center: tuple of floats
    
    :returns: the distance from the agent's center to the center of the field
    :rtype: float
    """
    return kUtil.getDist(inputAgent.get_noisy_pos(), center)
Example #8
0
 def agentBallIntersection(self, inputAgent):
     #print()
     agentRadius = self.agent_block_size / 2
     ballRadius = self.ball_block_size / 2
     cutoff = agentRadius+ ballRadius
     agentMidPoint = kUtil.addVectorToPoint(inputAgent.true_pos, (self.agent_block_size/2, self.agent_block_size/2))
     ballMidPoint = kUtil.addVectorToPoint(self.fieldBall.trueBallPos, (self.ball_block_size/2, self.ball_block_size/2))
     #print("agent actual:", inputAgent.true_pos, "agentMid:", agentMidPoint)
     #print("agentMid:", agentMidPoint, " ballMid:", ballMidPoint)
     distBetweenMidPoints = kUtil.getDist(agentMidPoint, ballMidPoint)
     #print("Cutoff: ", cutoff, " actual Distance: ", distBetweenMidPoints)
     if (distBetweenMidPoints <= cutoff):
         return True
     else:
         return False
Example #9
0
 def calc_receive_ball_moving(self):
     #make sure that you're only doing this if
     for i in range(len(self.keeperArray)):
         if self.keeperArray[i].inPosession == True:
             rDecision = (i, self.keeperArray[i].true_pos)
             return
     for i in range(len(self.takerArray)):
         if self.takerArray[i].inPosession == True:
             return
         
     TA = kUtil.addVectorToPoint(self.fieldBall.trueBallPos, self.fieldBall.trueBallDirection)
     TB = self.fieldBall.trueBallPos
     minTime = 99999.0
     argmin = None
     bestPerpIntersect = None
     for i in range(len(self.keeperArray)):
         TC = self.keeperArray[i].true_pos
         if (kUtil.cosTheta(TA, TB, TC)) < 0:
             #print("Keeper " , i, " can't get to ball: the cosTheta is negetive.")
             #it's impossible for this keeper to get the ball
             continue
         else:
             pd = kUtil.getPerpDist(TA, TB, TC)
             pt = pd/self.maxPlayerSpeed
             normalVector = kUtil.getNormalVector(TA, TB, TC)
             perpIntersect = kUtil.addVectorToPoint(TC, normalVector)
             bd = kUtil.getDist(TB, perpIntersect)
             bt = bd/self.maxBallSpeed
             if pt > bt:
                 #keeper wont' be able be able to get to ball in time
                 #print("player ", i+1, "can't reach ball as pt:",pt," and bt: ",bt)
                 continue
             else:
                 #keeper CAN get to ball. can it get there soonest though?
                 #save the fastest keeper
                 if (pt < minTime):
                     minTime = pt
                     argmin = i
                     bestPerpIntersect = perpIntersect
     #at this point, if a keeper can get to the ball, the fastest and it's intercept are saved
     if (argmin != None):
         rDecision = [argmin, self.calcOptimal(self.keeperArray, argmin, bestPerpIntersect)]
         for i in range(len(self.keeperArray)):
             self.keeperArray[i].receiveDecision(rDecision)
         for i in range(len(self.takerArray)):
             self.takerArray[i].receiveDecision(rDecision)
     else:
         print("no argmin found. game about to crash for sure")
Example #10
0
 def calc_receive(self):
     if(self.fieldBall.trueBallDirection == (0.0, 0.0))== False:
         self.calc_receive_ball_moving()
     else:
         mimimum = 99999.0
         argmin = None
         for i in range(len(self.keeperArray)):
             temp = kUtil.getDist(self.fieldBall.trueBallPos, self.keeperArray[i].true_pos)
             if (temp < mimimum):
                 mimimum = temp
                 argmin = i
         rDecision = [argmin, self.fieldBall.trueBallPos]
         for i in range(len(self.keeperArray)):
             self.keeperArray[i].receiveDecision(rDecision)
         for i in range(len(self.takerArray)):
             self.takerArray[i].receiveDecision(rDecision)
Example #11
0
    def __agentBallIntersection(self, inputAgent, agentType):
        """
        This private function will take an input agent, and 
        check to see if that agent intersects with the ball or not.
        If so, return true. otherwise return false.
        
        :param inputAgent: the agent that you're checking to see
            if it intersects with the ball or not. 
        :param agentType: "keeper" or "taker"
        
        :type inputAgent: agent
        :type agentType: string
        
        :returns: true if the agent intersects with the ball, false otherwise
        :rtype: boolean 
        """
        # print
        if agentType == "keeper":
            agentTruePosition = self.keeperTruePosArray[inputAgent.getSimIndex()]
        else:
            # agent must be a taker
            agentTruePosition = self.takerTruePosArray[inputAgent.getSimIndex()]

        agentRadius = self.__agent_block_size / 2
        ballRadius = self.ball_block_size / 2
        cutoff = agentRadius + ballRadius
        agentMidPoint = kUtil.addVectorToPoint(
            agentTruePosition, (self.__agent_block_size / 2, self.__agent_block_size / 2)
        )
        ballMidPoint = kUtil.addVectorToPoint(
            self.fieldBall.trueBallPos, (self.ball_block_size / 2, self.ball_block_size / 2)
        )
        # print "agent actual:", inputAgent.true_pos, "agentMid:", agentMidPoint
        # print "agentMid:", agentMidPoint, " ballMid:", ballMidPoint
        distBetweenMidPoints = kUtil.getDist(agentMidPoint, ballMidPoint)
        # print "Cutoff: ", cutoff, " actual Distance: ", distBetweenMidPoints
        if distBetweenMidPoints <= cutoff:
            return True
        else:
            return False
Example #12
0
 def test_getStateVars2(self):
     simulatedError = 0.01
     simWidth = 550.0
     simHeight = 357.0
     ballPos = (1/3 * simWidth,1/6 * simHeight)
     c = (simWidth /2.0,simHeight/2.0)
     a1 = agent.agent((1/3 * simWidth,1/6 * simHeight),simulatedError,"Keeper",ballPos)
     a2 = agent.agent((2/3 * simWidth,1/7 * simHeight),simulatedError,"Keeper",ballPos)
     a3 = agent.agent((2/5 * simWidth,6/7 * simHeight),simulatedError,"Keeper",ballPos)
     keepers = [a1,a2,a3]
     t1 = agent.agent((1/2 * simWidth,5/12 * simHeight),simulatedError,"Taker",ballPos)
     t2 = agent.agent((2/5 * simWidth,7/12 * simHeight),simulatedError,"Taker",ballPos)
     takers = [t1,t2]
     testOut = getStateVarsKeepers(keepers, takers, c)
     actualOut = [kUtil.getDist((550/3, 59.5), c),
                  kUtil.getDist((550/3 * 2, 51), c),
                  kUtil.getDist((220, 306), c),
                  kUtil.getDist((275, 148.75), c),
                  kUtil.getDist((220, 208.25), c),
                  kUtil.getDist((550/3,59.5), (550/3*2, 51)),
                  kUtil.getDist((550/3,59.5), (220,306)),
                  kUtil.getDist((550/3,59.5), (275, 148.75)),
                  kUtil.getDist((550/3,59.5), (220, 208.25)),
                  min( kUtil.getDist((550/3*2,51), (220, 208.25)), kUtil.getDist((550/3*2,51), (275, 148.75)) ),
                  min( kUtil.getDist((220,306), (220, 208.25)), kUtil.getDist((220,306), (275, 148.75)) ),
                  max(kUtil.cosTheta((550/3*2, 51), (550/3,59.5), (275,148.75)), 
                      kUtil.cosTheta((550/3*2, 51), (550/3,59.5), (220,208.25))),
                  max(kUtil.cosTheta((220,306), (550/3,59.5), (275,148.75)), 
                      kUtil.cosTheta((220,306), (550/3,59.5), (220,208.25))),
                  ]
     for i in range(len(testOut)):
         self.assertAlmostEqual(testOut[i], actualOut[i], 1,"Failed on index: %d" % i)
Example #13
0
def __distAgent(agent1, agent2):
    # return kUtil.getDist(agent1.get_noisy_pos(), agent2.true_pos)
    return kUtil.getDist(agent1.get_noisy_pos(), agent2.get_noisy_pos())
Example #14
0
def distCenter(inputAgent, center):
    return kUtil.getDist(inputAgent.noisy_pos, center)
Example #15
0
 def __lt__(self, other):
     return kUtil.getDist(self.noisy_pos, self.noisyBallPos) < kUtil.getDist(other.noisy_pos, other.noisyBallPos)
Example #16
0
def calc_receive(worldRef, inputDirection = None):
    """
    This function is the only public function of this module. It will go and 
    calculate the receive decision, which is a tuple that simply contains the 
    index of the keeper that should run towards the ball, and the coordinate 
    that the keeper should run to. If the ball is stationary, the coordinate
    the selected keeper should run to is simply the coordinates of the ball. 
    If the ball is moving, then calc_receieve will find an intersection point
    along the balls projected path that the selected keeper can run to. 
    The intercept point is selected such that the 
    selected keeper will run a short distance, be far away from the takers, 
    and also be far away from out of bounds.  
    
    .. note::
        Only the simulator class should call the calc_receive method. This method
        will therefore return the noise-free interception point. The simulator
        must then add random noise to the noise-free interception point before
        passing the receive decision to a keeper. A different amount of noise value
        be added for each keeper. 
    
    :param worldRef: a reference to the simulator class which is calling this function
    :param inputDirection: the current direction the ball is moving. This parameter must 
        be specified if the ball is moving. If the ball is not moving, then leave this 
        parameter blank. 
        
    :type worldRef: keepAway
    :type inputDirection: tuple of floats
    
    :returns: tuple, where first element is the index of the keeper picked to run towards
        the ball. The simulator will use this index to look up the index of the keeper 
        in its self.keeperArray. The 2nd element is the intersection coordinate
    :rtype: tuple where first element is integer, second element is tuple. 2nd element
        tuple contains integers

    """
    #keep track of which keeper is currently the possessing keeper.
    #this way, you don't try to pass to yourself.
    posessingKeeperIndex = None
    for keeper in worldRef.keeperArray:
        if keeper.inPosession == True:
            posessingKeeperIndex = keeper.agentListIndex
            break
        
    #you're either calculating a hypothetical pass, or the actual pass
    """
    if inputDirection == None:
        print("calc recieve for ball. ")
        if(worldRef.fieldBall.trueBallDirection == (0.0, 0.0)):
            print("ball is stationary") 
        else:
            print("ball is moving") 
        inputDirection = worldRef.fieldBall.trueBallDirection
    """
    if inputDirection == None:
        inputDirection = worldRef.fieldBall.trueBallDirection
    
    
    if(inputDirection == (0.0, 0.0))== False:
        rDecision = __calc_receive_ball_moving(worldRef, inputDirection, posessingKeeperIndex)
    else:
        mimimum = 99999.0
        argmin = None
        for i in range(len(worldRef.keeperArray)):
            temp = kUtil.getDist(worldRef.fieldBall.trueBallPos, worldRef.keeperTruePosArray[i])
            if (temp < mimimum and i != posessingKeeperIndex):
                mimimum = temp
                argmin = i
        rDecision = [argmin, worldRef.fieldBall.trueBallPos]
    return rDecision
Example #17
0
def __calcOptimal(worldRef, agentList, i, intersect):
    """
    This function is a private function meant to assist another private function called
    __calc_receive_ball_moving. 
    
    once __calc_receive_ball_moving has calculated the intersection point, there's 
    one last step: to make sure that the intersection point isn't too close to 
    the out of bounds area. If the intersection point too close to out of bounds, 
    then return an intersection point along the path that the ball is traveling, but
    is just still safely away from the out of bounds areas. 
    
    
    .. note::
        This is a private function that the user shouldn't worry about calling.
        Only the calc_receive function should be called.  
    
    :param worldRef: a reference to the simulator class which is calling this function
    :param agentList: a list provided by the simulator of all agents
    :param i: the index of the agent running to the ball for the list agentList
    :param intersect: the intersection point that has been calculated, and might be too
        close to out of bounds

        
    :type worldRef: keepAway class
    :type agentList: a list where each element is an agent class
    :type i: integer
    :type intersect: a tuple of floats
    
    :returns: the intersection coordinate which is safely within bounds, or the original
        intersection point if no such point is found
    :rtype: tuple of floats

    """
    #if the intersect is in bounds, just go to it. no calculations needed
    if __isPointOutOfPlayRegion(worldRef, intersect, agentList, i) == False:
        #print("point in bounds, return intersect") 
        return intersect
        
    #V = vector from agent's perpendicular intercept to the ball
    V = kUtil.getVector(intersect, worldRef.fieldBall.trueBallPos)
    #turn V into a unit vector and multipy it by the speed of the ball to get velocity vector
    UV = kUtil.unitVector(V)
    stepVector = kUtil.scalarMultiply(worldRef.maxBallSpeed, UV)
        
    #the optimal point is intialized to the intersect, and 
    #the intersect is currently out of bounds.
    #keep adding the step vector to the optimal point until
    #the intersect is no longer out of bounds
    optimalPoint = intersect
    maxNumSteps = int(kUtil.getDist(worldRef.fieldBall.trueBallPos, intersect)/ worldRef.maxBallSpeed)
    stepCount = 0
    #if you can't get to the ball in maxNumSteps, then it's hopeless. simply
    #return the intersection point. Your agent will fail and the ball will
    #go out of bounds, but there's nothing that can be done
    for k in range(maxNumSteps):
        optimalPoint = kUtil.addVectorToPoint(optimalPoint, stepVector)
        stepCount += 1
        if __isPointOutOfPlayRegion(worldRef, optimalPoint, agentList, i) == False:
            #print("Optimal found, returning optimal point:", optimalPoint) 
            return optimalPoint
    #if you get here, then no closer optimal was found
    #print("no optimal found, returning intersect", intersect) 
    return intersect
Example #18
0
def __calc_receive_ball_moving(worldRef, inputDirection, possessingKeeperIndex):
    """
    This function is a private function meant to assist calc_receive. This function 
    will go and calculate the receive decision for the special case where the 
    ball is moving. The receive decision is a tuple that simply contains the 
    index of the keeper that should run towards the ball, and the coordinate 
    that the keeper should run to. 
    If the ball is moving, then calc_receieve will find an intersection point
    along the balls projected path that the selected keeper can run to. 
    The intercept point is selected such that the 
    selected keeper will run a short distance, be far away from the takers, 
    and also be far away from out of bounds.  
    
    .. note::
        This is a private function that the user shouldn't worry about calling.
        Only the calc_receieve function of this method will use this function.
        And only the simulator class should call the calc_receive function. 
    
    :param worldRef: a reference to the simulator class which is calling this function
    :param inputDirection: the current direction the ball is moving.
    :param possessingKeeperIndex: the index of the keeper who currently has possession
        
    :type worldRef: keepAway
    :type inputDirection: tuple of floats
    :type possessingKeeperIndex: integer
    
    :returns: tuple, where first element is the index of the keeper picked to run towards
        the ball. The simulator will use this index to look up the index of the keeper 
        in its self.keeperArray. The 2nd element is the intersection coordinate
    :rtype: tuple where first element is integer, second element is tuple. 2nd element
        tuple contains integers

    """
    #TA is a point that the ball is heading to in the next time step      
    TA = kUtil.addVectorToPoint(worldRef.fieldBall.trueBallPos, inputDirection)
    #TB is the current ball position, and for angle calculations, it will be the vertex
    TB = worldRef.fieldBall.trueBallPos
    minTime = float("inf")
    argmin = None
    bestPerpIntersect = None
    #the purpose of this for loop is to find which keeper should go to the ball. 
    for i in range(len(worldRef.keeperArray)):
        #TC is the position of the keeper who's figuring out if he should goToBall(), or getOpen()
        TC = worldRef.keeperTruePosArray[i]
        if (kUtil.cosTheta(TA, TB, TC)) < 0:
            #print "Keeper " , i, " can't get to ball: the cosTheta is negetive."
            #it's impossible for this keeper to get the ball
            continue 
        else:
            pd = kUtil.getPerpDist(TA, TB, TC)
            pt = pd/worldRef.maxPlayerSpeed
            normalVector = kUtil.getNormalVector(TA, TB, TC)
            perpIntersect = kUtil.addVectorToPoint(TC, normalVector)
            bd = kUtil.getDist(TB, perpIntersect)
            bt = bd/worldRef.maxBallSpeed
            if pt > bt:
                #keeper wont' be able be able to get to ball in time
                #print "player ", i+1, "can't reach ball as pt:",pt," and bt: ",bt 
                continue
            else:
                #keeper CAN get to ball. can it get there soonest though?
                #save the fastest keeper
                if (pt < minTime and i !=  possessingKeeperIndex):
                    minTime = pt
                    argmin = i
                    bestPerpIntersect = perpIntersect
    #at this point, if a keeper can get to the ball, 
    #the fastest and it's intercept are saved
    if (argmin != None):
        rDecision = [argmin, __calcOptimal(worldRef, worldRef.keeperArray, argmin, bestPerpIntersect)]
        return rDecision
    else:
		rDecision = [1 , worldRef.get_field_center()]
		#print("no argmin found. game about to end for sure.")
		return rDecision
Example #19
0
def distAgent(agent1, agent2):
    return kUtil.getDist(agent1.noisy_pos, agent2.true_pos)