Files
commandergenius/project/jni/application/gav/gav-0.9.0/PlayerAI.cpp
2010-11-12 13:32:08 +02:00

245 lines
7.3 KiB
C++

/* -*- C++ -*- */
/*
GAV - Gpl Arcade Volleyball
Copyright (C) 2002
GAV team (http://sourceforge.net/projects/gav/)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "PlayerAI.h"
#include "Ball.h"
#define JUMP_LIMIT ( (int) (configuration.SCREEN_HEIGHT / 1.82) )
#define JUMPING_TIME ( 150 )
#define NEWPL_SIDE (-1)
triple_t PlayerAI::planAction() {
int jmp = 0;
//int i;
int side = (team())->side();
int nplrs = (team())->nplayers();
int px, bx, fs, mp, bsx, net, wall, xt, xs; /* Normalized values */
int mypos, minslot, maxslot;
float slotsize;
int move, pw;
triple_t ret;
int ttime;
net = fs = abs(maxX() - minX());
wall = 0;
mp = fs/2;
/* Normalize player x position, ball x position and ball x speed:
Reasoning as it plays on the left, net=fs, wall=0 */
px = (side>0)?(maxX()-x()-width()/2):
(x()+width()/2-minX());
pw = width();
bx = (side>0)?(maxX()-(_b->radius()+_b->x())):
(_b->radius()+_b->x()-minX());
bsx = -side*_b->spdx();
xs = bx;
/* if ( (_y > _highestpoint) ){
printf("_y: %d, hp: %d\n",_y, _highestpoint);
_highestpoint = _y;
}*/
if ( !_b->gravity() ) {
xt = (side>0)?(maxX()-(_b->radius()/2+_b->x())):
(_b->radius()/2+_b->x()-minX());
} else {
//xt = bx; /* The old one
int exp_y = _b->y();
int exp_x = _b->x();
int sx = _b->spdx();
int sy = _b->spdy();
// printf("I(%d,%d) -> (%d,%d)\n",exp_x,exp_y,sx,sy);
ttime=0;
while (exp_y < 240) {
int passed=20;
int px = exp_x;
int py = exp_y;
ttime += passed;
exp_x += (int)(sx * ((float) passed/1000.0));
exp_y -= (int)(sy * ((float) passed/1000.0));
sy = (int)(sy-((float) passed*_b->gravity()/1000.0));
if ( exp_y < configuration.CEILING ) {
exp_y = configuration.CEILING;
sy = - (int ) (sy*ELASTIC_SMOOTH);
}
if ( exp_x < configuration.LEFT_WALL ) {
exp_x = configuration.LEFT_WALL;
sx = - (int ) (sx*ELASTIC_SMOOTH);
}
if ( exp_x > configuration.RIGHT_WALL - (_b->radius()*2) ) {
exp_x = configuration.RIGHT_WALL - (_b->radius()*2);
sx = - (int ) (sx*ELASTIC_SMOOTH);
}
int minx = (exp_x < px)?exp_x:px;
if ( (minx > (configuration.NET_X-_b->radius()*2)) &&
( minx < configuration.NET_X ) ) {
/* The ball crossed the net region */
if ( ( exp_y > configuration.NET_Y ) ||
( py > configuration.NET_Y ) ) {
/* Probably the ball will hit the net,
consider a full collision */
exp_x = (minx == exp_x)?configuration.NET_X-_b->radius()*2:configuration.NET_X;
sx = - (int ) (sx*ELASTIC_SMOOTH);
if (!sx) sx = side*20;/*SMALL_SPD_X*/
}
}
// printf("+(%d,%d) -> (%d,%d)\n", exp_x, exp_y, sx, sy);
}
xt = exp_x+_b->radius();
xt = (side>0)?(maxX()-xt):(xt-minX());
// printf("Expected X: %d (bsx: %d, bsy: %d, bx: %d, by: %d (radius: %d, rw:%d, hp: %d)\n",xt, _b->spdx(), _b->spdy(), _b->x(), _b->y(), _b->radius(), RIGHT_WALL(2*_b->radius()),_highestpoint);
// printf("HP: %d\n"u, _highestpoint);
}
//Expected X: 80061 (bsx: -624, bsy: 679, bx: 455, by: 241 (radius: 25)
slotsize = net/nplrs;
if (nplrs > 1) {
std::vector<Player *> plv = (team())->players();
/* Look for my id */
std::vector<Player *>::iterator it;
int myidx = orderInField(), i;
/* If nobody set the Order In Field I will do for all the team */
if (orderInField() < 0) {
for ( it = plv.begin(), i=0;
it != plv.end();
it++,i++ )
(*it)->setOIF(i);
myidx = orderInField();
}
mypos = (int)(slotsize*(myidx+0.5));
Player *closerp;
int minxsearching = net, minopx, opx, closer;
for ( it = plv.begin();
it != plv.end();
it++ ) {
opx = (side>0)?((*it)->maxX()-(*it)->x()-(*it)->width()/2):
((*it)->x()+(*it)->width()/2-(*it)->minX());
if ( ( (*it)->id() != id() ) &&
( abs(opx-mypos) < minxsearching ) ){
closer=(*it)->id();
closerp=(*it);
minxsearching=abs(opx-mypos);
minopx=opx;
}
}
/* Someone is inside my slot over the 15% the slot size */
if (minxsearching < (slotsize*0.35)) {
myidx = closerp->orderInField();
closerp->setOIF(orderInField());
setOIF(myidx);
}
mypos = (int )(slotsize*(myidx+0.5));
minslot = (int )(slotsize*myidx);
maxslot = (int )(slotsize*(myidx+1));
} else {
minslot = wall;
mypos = mp-50; // behind the middle point
maxslot = net;
}
/* My rest position has been chosen, and the slot determined */
// int hd = 3*_b->radius()/4;
int hd = (_b->radius()+width())/2;
int minhd = 0;
if ( !_b->gravity() ) {
if (hd/2 >= 12)
minhd = rand()%(hd/2-10)+10;
hd = rand()%(hd-minhd)+minhd+1;
}
/* When I consider closer, is the closer to the falling point */
/* I care whether I'm the closer only when it's "service time" */
int closest = 1;
if ( !_b->gravity() ) {
int opx;
std::vector<Player *> plv = (team())->players();
/* Look for my id */
std::vector<Player *>::iterator it;
for ( it = plv.begin();
it != plv.end();
it++ ) {
opx = (side>0)?((*it)->maxX()-(*it)->x()-(*it)->width()/2):
((*it)->x()+(*it)->width()/2-(*it)->minX());
if ( abs(px-xt) > abs(opx-xt) )
closest = 0;
}
}
// printf("%d\n", _b->spdy());
// if (abs(bsx) < 160) hd += 7;
if ( _b->gravity() ) {
if ( ( (abs(px - bx)) <= hd ) && // is the ball close?
//(abs(_b->spdy()) > 10) && // is the ball going down too slow?
//( abs(px-bx) > 5 ) && // am I to close to the ball center?
// Can I reach the ball jumping, or am I missing the ball?
(_b->y() > ((_b->spdy() > 20)?JUMP_LIMIT:(JUMP_LIMIT+20)))
) {
jmp = 1;
}
} else { // I serve only forward
jmp = ( (minhd < (bx - px) && ((bx - px) <= hd) ) );
}
// printf("hd: %d - %d (%d - %d)\n",hd, abs(bx-px), _b->spdy(), _b->y());
// if I'm the closest player I serve (when it's "service time").
// if the ball is (too) outside my slot I do not go for it.
double concern = (nplrs>1)?(slotsize*1.05):slotsize;
if ( (abs(xt-mypos) < concern) && closest) {
if ( _b->gravity() ) {
move = xt-hd-px;
} else { // I serve only forward
move = bx-hd-px;
}
if ( ( ttime < JUMPING_TIME ) ){
jmp = 1;
move = (bx-px);
}
} else {
move = mypos-px;
}
move=-side*(move);
ret.left = ret.right = ret.jump = 0;
if ( abs(move) > 2) {
if ( move < 0 )
ret.left = 1;
if ( move > 0 )
ret.right = 1;
}
if ( jmp )
ret.jump = 1;
return ret;
}