4.10 Basic Decision Tree
The basis of any AI can be reduced down to the humble if statement. Now a decision tree is just a collection of nested if’s each letting us know one piece of information.
For this tutorial we are going to utilise a few of the already implemented functions to build up a decision with increasingly intelligent behaviour. We have already got something that checks to see which agent is closest to the ball on our team, so lets build on that
So we have the following :
if(isClosestTeam(_playerNumber,TeamDistToBall)){
worldModel->getRVSender()->drawCircle("Im at Pos",_myPos.getX(), _myPos.getY(),0.2,1,0,0); //RED
return kickBall(KICK_FORWARD, VecPosition(HALF_FIELD_X, 0, 0)); // Basic kick
}
else{
worldModel->getRVSender()->drawCircle("Im at Pos",_myPos.getX(), _myPos.getY(),0.2,0,1,0); //GREEN
return(SKILL_STAND);
}
Now lets add alil more complexity, lets say if we arent close enough to the goal then we should pass to the closest teammate. To do this we need another if statement which checks if we are in shooting range and returns true if that is the case. For example :
if(isShootingRange(_myPos, 8)){
worldModel->getRVSender()->drawCircle("Im at Pos",_myPos.getX(), _myPos.getY(),0.2,1,0.5,0); //ORANGE
return kickBall(KICK_FORWARD, VecPosition(HALF_FIELD_X, 0, 0)); // Basic kick
}
However, we need the else part to handle when this is not true. In this case we need to find the closest team mate and thankfully we have a function for that VecPosition NaoBehavior::getClosestTeammatePos(int _playerNumber,vector<pair<double,int > > TeamDistToBall)
So now we can add the following inside the else
else{
VecPosition teammate = getClosestTeammatePos( _playerNumber,TeamDistToBall);
return kickBall(KICK_FORWARD, teammate); // Basic kick
}
Well that handles the case if our initial if was true but it is not very good if the other agents just stand still, so we need to handle that case in a more intelligent fashion. Here we could do something like separate our behaviour into “forwards” and “defenders” based on playernumber. For example the defenders should be between the ball and our goal, while the forwards should be between the ball and the opponents goal. Naively this can be achieved by calculated the Vecposition Midpoint between the ball and the goal as follows:
if(_playerNumber == 4 || _playerNumber == 5){
VecPosition target = ball.Midpoint(VecPosition(HALF_FIELD_X, 0, 0));
worldModel->getRVSender()->drawCircle("Im at Pos",_myPos.getX(), _myPos.getY(),0.2,0,1,0); //GREEN
return SmartGoToTarget(target, 1);
}
else{
VecPosition target = ball.Midpoint(VecPosition(-HALF_FIELD_X, 0, 0));
return SmartGoToTarget(target, 1);
}