NABS
Robocup -
Soccer Server

Basic Anatomy of Dr. Itsuki Client program

 

1.0 Usage of noda.C

client [ options ] TEAMNAME [ PLAYSTRYLE ]

options:

-h HOSTNAME
-p PORTNUMBER

PLAYSTYLE:

dango ; only chases the ball
defender ; keeps the position between the ball and theown goal
midfielder ; chases the ball if the ball is in the midfield, else surrounds in the midfield.
left_wingback ; covers the left side.
right_wingback ; covers the right side.
forward ; waits the ball in the opponent-team-side.
top ; waits the ball in front of the opponent goal.

1.0 Source Structure of noda.C

int main(int argc, char **argv){
player.mainloop() ;
player.close() ;
}

//======================================================================
//Top Facilities
//======================================================================
Boolean Player::init(int argc, char **argv)
void Player::mainloop(){
start_sensor() ;

switch(play_style)
case PS_dango:
play_as_dango() ; break ;
case PS_defender:
play_as_defender() ; break ;
case PS_midfielder:
play_as_midfielder() ; break ;
case PS_top:
play_as_forward() ; break ;
case PS_forward:
play_as_forward2() ; break ;
case PS_left_wingback:
play_as_midfielder2(PPos(-20,-15),30,20) ; break ;
case PS_right_wingback:
play_as_midfielder2(PPos(-20, 15),30,20) ; break ;
default:
exit(-1) ;
}
void Player::close()


//======================================================================
//Initializations
//======================================================================
void Player::mygetopt(int argc, char** argv)
void usage()

//======================================================================
//Sensor Process
//======================================================================
void sensor_cycle(void) P->check_message() ;
void Player::check_message()
void Player::start_sensor()
void Player::analyze_message()

//======================================================================
//Void Action
//======================================================================
void Player::voidaction()

//======================================================================
//Send Command
//======================================================================
void Player::move(PlayStyle pos)
void Player::move(Real x, Real y)
void Player::turn(Real moment)
void Player::turn_to(Real adir)
void Player::dash(Real power)
void Player::kick(Real power, Real dir)
void Player::say(Buffer msg)
void Player::change_view(ViewAngle va, ViewQuality vq)

//======================================================================
//Visual Object Manipuration
//======================================================================
VisualObject* Player::findVisualObject(String name)
void Player::renewVisualObject(String name,
void Player::showStatus()

//======================================================================
//Check ViewInfo
//======================================================================
void Player::wait_new_vinfo()
Boolean Player::new_vinfo_p(VisualObject* obj)

//======================================================================
//Basic Actions(Turns)
//======================================================================
void Player::look_around()
void Player::look_at(String name)
void Player::look_at(VisualObject* obj)
void Player::turn_to(String name)
void Player::turn_to(VisualObject* obj)
void Player::search_obj(VisualObject* obj)

//======================================================================
//Basic Actions(Chase)
//======================================================================
void Player::chase(String name)
void Player::chase(VisualObject* obj)
void Player::go_toward(PPos tpos)

//======================================================================
//Basic Actions(Kick)
//======================================================================
Boolean Player::kickable()
void Player::shoot_to_goal()
void Player::kick_to(VisualObject* obj)
void Player::kick_immediately(VisualObject* obj)
void Player::kick_immediately(PPos tpos)

//======================================================================
//Estimate Current Position & Object Position
//======================================================================
void Player::estimate_position()
PPos Player::estimate_object_pos(VisualObject* obj)

//======================================================================
// Various Player mode in one Client
//======================================================================

//Dango Soccer
void Player::play_as_dango()

//Defender
void Player::play_as_defender()
void Player::keep_defensive_pos()
Boolean Player::teammatep(VisualObject *obj)
Boolean Player::playerp(VisualObject *obj)
Real Player::find_clear_way(Real ddir,Real dist)
Boolean Player::clearwayp(Real to_dir,Real to_dist)
VisualObject* Player::newest_fore_teammate()
void Player::clear_or_pass()

//MidFielder
Boolean Player::nearest_to_ballp()
void Player::play_as_midfielder()
void Player::shoot_or_pass()
void Player::wandering(PPos center, Real radius)

//Forward
void Player::play_as_forward()
void Player::play_as_forward2()

//MidFielder2
void Player::wandering2(PPos center, Real rx, Real ry)
void Player::play_as_midfielder2(PPos center, Real rx, Real ry)

3.0 Source code of noda.C

// -*- mode:C++ -*-
//Header:
//Title: Sample of Soccer Client Program
//File: client.C
//Author: NODA, Itsuki
//Date: 1996/05/19
//EndHeader:

//History:
// This file is created originally by NODA, Itsuki [1996/06/06]
//EndHistory:

//======================================================================
//Headers
//======================================================================
#include <String.h>
#include <iostream.h>
#include <strstream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <GetOpt.h>

#include "udpif.h"
#include "client.h"

//======================================================================
//Main
//======================================================================
int main(int argc, char **argv) {
Player player ;

if(!(player.init(argc, argv))) exit(-1) ;

player.mainloop() ;

player.close() ;
}


//======================================================================
//Top Facilities
//======================================================================
Boolean Player::init(int argc, char **argv) {
//Analyze Args
mygetopt(argc,argv) ;

sock = init_connection((char*)((const char*)serverhost),serverport) ;
if(sock.socketfd == -1) {
cerr << "Can't open socket." << endl ;
return False ;
}

ostrstream ost(send_buffer,bufsize) ;

ost << "(init " << team << ")" << endl << ends ;

if(send_message(send_buffer,sock) == -1) {
cerr << "Can't connect to the server." << endl ;
return False ;
}

//Receive Init message
Int n ;
while(!(n = receive_message(recv_buffer, bufsize, &sock))) {} ;
if(n == -1) {
cerr << "????" << endl ;
return False ;
}
Int l ;
char mode[BUFFERSIZE] ;
char sidename[NAMEMAX] ;
if(3 > sscanf(recv_buffer,"(init %[lr] %d %[^)])%n",
sidename, &unum, mode, &l)) {
cerr << "Refused by the server: " << recv_buffer << endl ;
return False ;
}

// Setup Side
side = str_to_Side(sidename) ;

// Setup Land Mark
String* LMStr = ((side == Side_L)?LandMarkStrL:LandMarkStrR) ;
for(Int i = 0 ; i < LM_max ; ++i) {
landmark[i] = findVisualObject(LMStr[i]) ;
landmark[i]->pos = LandMarkPos[i] ;
landmark[i]->fixp = True ;
}
ball = landmark[LM_ball] ;
goal = landmark[LM_goal] ;
owngoal = landmark[LM_owngoal] ;
ball->fixp = False ;

// Move to initial Position
move(play_style) ;

// Final Report
cout << "Connect with " << serverhost << " [" << serverport << "]"
<< endl ;
cout << " side: " << side << endl ;
cout << " unum: " << unum << endl ;
cout << " mode: " << mode << endl ;
cout << " play_style: " << PlayStyleStr[play_style] << endl ;

return True ;
}

void Player::mainloop() {
start_sensor() ;

switch(play_style) {
case PS_dango:
play_as_dango() ; break ;
case PS_defender:
play_as_defender() ; break ;
case PS_midfielder:
play_as_midfielder() ; break ;
case PS_top:
play_as_forward() ; break ;
case PS_forward:
play_as_forward2() ; break ;
case PS_left_wingback:
play_as_midfielder2(PPos(-20,-15),30,20) ; break ;
case PS_right_wingback:
play_as_midfielder2(PPos(-20, 15),30,20) ; break ;
default:
exit(-1) ;
}
}

void Player::close() {
close_connection(this->sock) ;
}

//======================================================================
//Initializations
//======================================================================
void Player::mygetopt(int argc, char** argv) {
GetOpt getopt(argc,argv,"h:p:") ;
Int option_char ;
while ((option_char = getopt ()) != EOF) {
switch (option_char) {
case 'h': serverhost = getopt.optarg; break;
case 'p': serverport = atoi(getopt.optarg); break;
case '?': usage() ; exit(-1) ;
}
}

for(Int i = 0, j = getopt.optind ; j < argc ; i++, j++) {
switch(i) {
case 0:
team = argv[j] ; break ;
case 1:
play_style_str = argv[j] ; break ;
default:
usage() ; exit(-1) ;
}
}

play_style = str_to_position(play_style_str) ;
if(play_style < 0) { usage() ; exit(-1) ; }
}

void usage() {
cerr <<
"Usage:\n\t\% client [options] TEAMNAME [ PLAYSTYLE ]
options:
-h HOSTNAME
-p PORTNUMBER
PLAYSTYLE:
dango
defender
midfielder
left_wingback
right_wingback
forward
top
" << ends ;

}

//======================================================================
//Sensor Process
//======================================================================
Player* P ;

void sensor_cycle(void) { P->check_message() ; }

void Player::check_message() {
clock++ ;
Int r = receive_message(recv_buffer,bufsize,&sock) ;
switch(r) {
case 0: return ;
case 1: analyze_message() ; break ;
default:
cerr << "Warning[" << __LINE__
<< "]:trouble in receive_message." << endl ;
}
}

void Player::start_sensor() {

cout << "Sensor process started!!" << endl ;

struct itimerval itv ;

itv.it_interval.tv_sec = 0 ;
itv.it_interval.tv_usec = RECV_INTERVAL_MILISEC * 1000 ;
itv.it_value.tv_sec = 0 ;
itv.it_value.tv_usec = RECV_INTERVAL_MILISEC * 1000 ;

setitimer(ITIMER_REAL, &itv, NULL) ;
P = this ;
signal(SIGALRM, (void (*)(int))sensor_cycle) ;
}

void Player::analyze_message() {
Int p,l ;

p = 0 ;
static char tmp[NAMEMAX] ;
if(1 > sscanf(&(recv_buffer[p]),"(%s %n",tmp,&l)) {
cerr << "Warning[" << __LINE__ << "]:Illegal message:"
<< recv_buffer << endl ;
return ;
}
p += l ;

Int t ;
if(!strcmp(tmp,"see")) {
if(1 > sscanf(&(recv_buffer[p]),"%d %n",&t,&l)) {
cerr << "Warning[" << __LINE__ << ": Illegal message:"
<< recv_buffer << endl ;
return ;
}
p += l ;
vtime = time = t ;

Real dist, dir ;
Int vdir ;
Int c ;

while(recv_buffer[p] != ')') {
if(1 > sscanf(&(recv_buffer[p])," ((%[^)]) %n",tmp,&l)) {
cerr << "Warning[" << __LINE__ << "]: Illegal message:"
<< &(recv_buffer[p]) << endl ;
return ;
}
p += l ;

if(3 == (c = sscanf(&(recv_buffer[p]),"%lf %lf %d)%n",
&dist,&dir,&vdir,&l))) {
} else if(2 == (c = sscanf(&(recv_buffer[p]),"%lf %lf)%n",
&dist,&dir,&l))) {
} else if(1 == (c = sscanf(&(recv_buffer[p]),"%lf)%n",
&dir,&l))) {
} else {
cerr << "Warning[" << __LINE__ << "]: Illegal message:"
<< recv_buffer << endl ;
return ;
}
p += l ;

renewVisualObject(tmp,dist,dir,vdir,c) ;
}
} else if (!strcmp(tmp,"hear")) {
Real dir ;
if(2 == sscanf(&(recv_buffer[p]),"%d %lf %n",&t,&dir,&l)) {
p += l ;
atime = time = t ;
cout << "Message:" << dir << ":"
<< &(recv_buffer[p]) << endl ;
} else if (2 == sscanf(&(recv_buffer[p]),"%d %s %n",&t,tmp,&l)) {
p += l ;
atime = time = t ;
cout << "Message:" << tmp << ":"
<< &(recv_buffer[p]) << endl ;
} else {
cerr << "Warning[" << __LINE__ << "]: Illegal message:"
<< recv_buffer << endl ;
return ;
}
} else {
cerr << "Warning[" << __LINE__ << "]: Illegal message:"
<< recv_buffer << endl ;
return ;
}
}

//======================================================================
//Void Action
//======================================================================
Int ptime = 0 ;
void Player::voidaction() {
Int i ;
turn(10) ;
spause() ;
i = time - ptime ;
if(!(0 == i)) {
showStatus() ;
ptime = time ;
}
}

//======================================================================
//Send Command
//======================================================================
PlayStyle Player::str_to_position(String PosName) {
for(Int i = 0 ; i < PS_max ; i++) {
if(PosName == PlayStyleStr[i]) {
return (PlayStyle)i ;
}
}
return (PlayStyle)-1 ;
}

void Player::move(PlayStyle pos) {
Real x,y ;

randomize() ;

x = drand(PlayStyleRange[pos][0],PlayStyleRange[pos][1]) ;
y = drand(PlayStyleRange[pos][2],PlayStyleRange[pos][3]) ;

move(x,y) ;
}

void Player::move(Real x, Real y) {

cout << "Move:(" << x << "," << y << ")" << endl ;

sprintf(send_buffer,"(move %d %d)",(Int)x,(Int)y) ;
send_message(send_buffer,sock) ;

}

void Player::turn(Real moment) {
if(moment < EPS && moment > -EPS) { return ;} ;

// cout << "Turn:" << moment << endl ;

moment = normalize_angle(moment) ;
sprintf(send_buffer,"(turn %d)",(Int)moment) ;
send_message(send_buffer,sock) ;
cdir += moment ;
cdir = (Int)normalize_angle(cdir) ;

npause() ;
}

void Player::turn_to(Real adir) {
turn(adir - cdir) ;
}

void Player::dash(Real power) {

// cout << "Dash:" << power << endl ;

sprintf(send_buffer,"(dash %d)",(Int)power) ;
send_message(send_buffer,sock) ;

npause() ;
}

void Player::kick(Real power, Real dir) {

// cout << "Kick:" << power << "," << dir << endl ;

sprintf(send_buffer,"(kick %d %d)",(Int)power, (Int)dir) ;
send_message(send_buffer,sock) ;

npause() ;
}

void Player::say(Buffer msg) {

cout << "Say:" << msg << endl ;

sprintf(send_buffer,"(say %s)",msg) ;
send_message(send_buffer,sock) ;

npause() ;
}

void Player::change_view(ViewAngle va, ViewQuality vq) {

npause() ;

cout << "ChangeView: " << va << "," << vq << endl ;

sprintf(send_buffer,"(change_view %s %s)",
(const char*)ViewAngleStr[va],(const char*)ViewQualityStr[vq]);
send_message(send_buffer,sock) ;
cva = va ;
cvq = vq ;

npause() ;
}

//======================================================================
//Visual Object Manipuration
//======================================================================
VisualObject* Player::findVisualObject(String name) {
Int i ;
for(i = 0 ; i < N_vobj ; i++) {
if(vobj[i].name == name) {
return &(vobj[i]) ;
}
}
N_vobj++ ;
vobj[i].name = name ;
vobj[i].vdir = 0 ;
vobj[i].dir = 0 ;
vobj[i].dist = 0 ;
vobj[i].time = -1 ;
vobj[i].pos.x = vobj[i].pos.y = 0.0 ;
vobj[i].fixp = False ;
return &(vobj[i]) ;
}

void Player::renewVisualObject(String name,
Real dist,
Real dir,
Int vdir,
Int type) {
VisualObject* o = findVisualObject(name) ;

o->time = time ;

switch(type) {
case 3:
o->dist = dist ;
o->dir = dir + cdir ;
o->vdir = vdir ;
break ;
case 2:
if(cvq == VQ_High) {
o->dist = dist ;
o->dir = dir + cdir;
} else {
o->dir = dist + cdir;
o->vdir = (Int)dir ;
}
break ;
case 1:
o->dir = dir + cdir;
break ;
}
}

void Player::showStatus() {
cout << "[" << time << "]--------------------------------"
<< endl;
Int i ;
for(i = 0 ; i < N_vobj ; i++) {
cout << " #" << i << ": " << vobj[i].name << "[" << vobj[i].time
<< "]:Rh("
<< vobj[i].dist << "," << vobj[i].dir << "),"
<< vobj[i].vdir
<< ", XY(" << vobj[i].pos.x << "," << vobj[i].pos.y << ")"
<<endl ;
}
}

//======================================================================
//Check ViewInfo
//======================================================================
void Player::wait_new_vinfo() {
Int tm = time ;
while(tm >= vtime) { spause() ; }
}

Boolean Player::new_vinfo_p(VisualObject* obj) {
return (Boolean)(time - obj->time < 10) ;
}


//======================================================================
//Basic Actions(Turns)
//======================================================================

void Player::look_around() {
cout << "Now, looking around." << endl ;
//change_view(VA_Wide,VQ_Low) ;
wait_new_vinfo() ;
for(Int i = 0 ; i < 4 ; i++) {
turn(80) ;
wait_new_vinfo() ;
}
}

void Player::look_at(String name) {
cout << "Now, looking at " << name << "." << endl ;
look_at(findVisualObject(name)) ;
}

void Player::look_at(VisualObject* obj) {
cout << "Now, looking at " << obj->name << "." << endl ;
//change_view(VA_Narrow,VQ_High) ;

turn_to(obj->dir) ;
Int tm = time ;
wait_new_vinfo() ;
if(obj->time <= tm) {
cout << "!!! Lose site of " << obj->name << "." << endl ;
search_obj(obj) ;
}
}

void Player::turn_to(String name) {
turn_to(findVisualObject(name)) ;
}
void Player::turn_to(VisualObject* obj) {
look_at(obj) ;
turn_to(obj->dir) ;
}

void Player::search_obj(VisualObject* obj) {
cout << "Now, searching " << obj->name << "." << endl ;
Int tm = time ;
wait_new_vinfo() ;
while(obj->time <= tm) {
turn(80) ;
wait_new_vinfo() ;
}
turn_to(obj->dir) ;
}

//======================================================================
//Basic Actions(Chase)
//======================================================================
void Player::chase(String name) {
chase(findVisualObject(name)) ;
}
void Player::chase(VisualObject* obj) {
turn_to(obj) ;

Real d = find_clear_way(0.0,obj->dist) ;
turn(d) ;

dash(obj->dist + 20.0);
_pause(3) ;
}


void Player::go_toward(PPos tpos) {
Real dx = tpos.x - pos.x, dy = tpos.y - pos.y ;
Real adir = Atan2(dy, dx) ;
turn(adir - edir) ;

Real dist = sqrt(dx * dx + dy * dy) ;

Real d = find_clear_way(0.0,dist) ;
turn(d) ;

dash(dist + 10) ;
}


//======================================================================
//Basic Actions(Kick)
//======================================================================
Boolean Player::kickable() {
return (Boolean)((ball->dist < 2.0) && new_vinfo_p(ball)) ;
}

void Player::shoot_to_goal() {
kick_to(goal) ;
}

void Player::kick_to(VisualObject* obj) {
turn_to(obj) ;
kick(obj->dist + 20.0,0.0) ;
}

void Player::kick_immediately(VisualObject* obj) {
cout << "Now, kicking the ball to " << obj->name << "." << endl ;
PPos tpos = estimate_object_pos(obj) ;
kick_immediately(tpos) ;
}

void Player::kick_immediately(PPos tpos) {
Real dx = tpos.x - pos.x, dy = tpos.y - pos.y ;
Real adir = Atan2(dy, dx) ;
Real ddir = adir - edir ;
Real dist = sqrt(dx * dx + dy * dy) ;

kick(dist + 20.0,ddir) ;
turn(ddir) ;
}

//======================================================================
//Estimate Current Position
//======================================================================
void Player::estimate_position() {
VisualObject *lm1, *lm2 ;

Boolean oldp = False ;

do {
if(landmark[LM_goal]->time > landmark[LM_owngoal]->time) {
lm1 = landmark[LM_goal] ;
lm2 = landmark[LM_owngoal] ;
} else {
lm2 = landmark[LM_goal] ;
lm1 = landmark[LM_owngoal] ;
}

for(Int i = LM_owngoal+1 ; i < LM_max ; i++) {
if(landmark[i]->time > lm1->time) {
lm2 = lm1 ;
lm1 = landmark[i] ;
} else if (landmark[i]->time > lm2->time) {
lm2 = landmark[i] ;
}
}
if (time - lm2->time > 10) {
oldp = True ;
look_around() ;
} else { oldp = False ; }
} while (oldp) ;

Real x1 = lm1->pos.x, y1 = lm1->pos.y, r1 = lm1->dist ;
Real x2 = lm2->pos.x, y2 = lm2->pos.y, r2 = lm2->dist ;
Boolean revp = (Boolean)(y1 == y2) ;
if(revp) {
Real b ;
b = x1 ; x1 = y1 ; y1 = b ;
b = x2 ; x2 = y2 ; y2 = b ;
}

Real A = (x1 * x1 - x2 * x2) + (y1 * y1 - y2 * y2)
- (r1 * r1 - r2 * r2) ;
Real B = -2 * (x1 - x2) ;
Real C = A / (2 * (y1 - y2)) ;
Real D = B / (2 * (y1 - y2)) ;
Real E = 1 + D * D ;
Real F = -x1 + C * D - D * y1 ;
Real G = x1 * x1 + C * C - 2 * C * y1 + y1 * y1 - r1 * r1 ;
Real x01 = (- F + sqrt(F * F - E * G)) / E ;
Real x02 = (- F - sqrt(F * F - E * G)) / E ;
Real y01 = C + D * x01 ;
Real y02 = C + D * x02 ;

Real theta1 = Atan2(x1 - x01, y1 - y01)
- Atan2(x2 - x01, y2 - y01) ;
// Real theta2 = Atan2(x1 - x02, y1 - y02)
// - Atan2(x2 - x02, y2 - y02) ;
theta1 = normalize_angle(theta1) ;

Real theta0 = normalize_angle(-(lm1->dir - lm2->dir)) ;


if(theta0 * theta1 > 0) {
pos.x = x01 ;
pos.y = y01 ;
} else {
pos.x = x02 ;
pos.y = y02 ;
}

if(revp) {
Real b;
b = pos.x ; pos.x = pos.y ; pos.y = b ;
}

Real tau1 = Atan2(y1 - pos.y,x1 - pos.x) ;
Real tau01 = (lm1->dir - cdir) ;
edir = normalize_angle((tau1 - tau01)) ;

}


//======================================================================
//Estimate Object Position
//======================================================================
PPos Player::estimate_object_pos(VisualObject* obj) {
if(obj->fixp) {
return obj->pos ;
} else {
obj->pos.x = pos.x +
obj->dist * Cos(edir + obj->dir - cdir) ;
obj->pos.y = pos.y +
obj->dist * Sin(edir + obj->dir - cdir) ;
return obj->pos ;
}
}


//======================================================================
//Dango Soccer
//======================================================================
void Player::play_as_dango() {
look_around() ;
while(True) {
estimate_position() ;
if(kickable()) {
shoot_to_goal() ;
} else {
chase(ball) ;
}
}
}

//======================================================================
//Defender
//======================================================================
void Player::play_as_defender() {
look_around() ;
while(True) {
estimate_position() ;
if(kickable()) {
clear_or_pass() ;
} else if(ball->dist < 10.0) {
chase(ball) ;
} else {
keep_defensive_pos() ;
}
}
}

void Player::keep_defensive_pos() {
PPos bpos = estimate_object_pos(ball) ;
PPos ogpos = estimate_object_pos(owngoal) ;
PPos tpos(0.8 * ogpos.x + 0.2 * bpos.x,
0.8 * ogpos.y + 0.2 * bpos.y) ;
go_toward(tpos) ;
lpause() ;
turn_to(ball) ;
}

Boolean Player::teammatep(VisualObject *obj) {
int p = -1 ;
char b[MINIBUFSIZE] ;
if(1 > sscanf(obj->name,"player %s%n",b,&p)) {
return False ;
}
// if(str_to_Side(b) == side) {
if(team == b) {
return True ;
} else {
return False ;
}
}

Boolean Player::playerp(VisualObject *obj) {
int p = -1 ;
sscanf(obj->name,"player%n",&p) ;
if(p > 0)
return True ;
else
return False ;
}

Real Player::find_clear_way(Real ddir,Real dist) {
Real w = 5.0 ;
while((!clearwayp(ddir,dist))&&( w < 180 )) {
ddir += drand(-w,w) ; w += 5.0 ;
}
if(ddir != 0.0) ;
// cout << "find_clear_way(" << ddir << ")[" << w << "]" << endl ;
return ddir ;
}

Boolean Player::clearwayp(Real to_dir,Real to_dist) {
for(Int i = 0 ; i < N_vobj ; i++ ) {
VisualObject* obj = &(vobj[i]) ;
if(playerp(obj)) {
if(time - obj->time < 10) {
if( to_dist > obj->dist ) {
Real d = obj->dist * Sin(to_dir + edir - obj->dir) ;
if(d < 1.0) {
return False ;
}
}
}
}
}
return True ;
}

VisualObject* Player::newest_fore_teammate() {
VisualObject* mate = (VisualObject*)NULL ;
for(Int i = 0; i < N_vobj ; i++) {
VisualObject* obj = &(vobj[i]) ;
if(teammatep(obj)) {
PPos tpos = estimate_object_pos(obj) ;
if(tpos.x > pos.x) {
if(mate == (VisualObject*)NULL) {
mate = obj ;
} else if (obj->time > mate->time) {
mate = obj ;
}
}
}
}
return mate ;
}

void Player::clear_or_pass() {
VisualObject* target = newest_fore_teammate() ;

if((target == (VisualObject*)NULL)||(time - target->time > 100)) {
if(pos.y > 0) target = landmark[LM_flag_cr] ;
else target = landmark[LM_flag_cl] ;
}

kick_immediately(target) ;
}

//======================================================================
//MidFielder
//======================================================================
Boolean Player::nearest_to_ballp() {
PPos bpos = estimate_object_pos(ball) ;
for(Int i = 0 ; i < N_vobj ; i++) {
VisualObject* obj = &(vobj[i]) ;
if(teammatep(obj)) {
if(time - obj->time < 10) {
PPos ppos = estimate_object_pos(obj) ;
Real d = bpos.distance(ppos) ;
if(d < ball->dist)
return False ;
}
}
}
return True ;
}

void Player::play_as_midfielder() {
look_around() ;
while(True) {
estimate_position() ;
PPos bpos = estimate_object_pos(ball) ;
if(kickable()) {
shoot_or_pass() ;
} else if(ball->dist < 10.0 && nearest_to_ballp()) {
chase(ball) ;
} else if(bpos.x < pos.x) {
go_toward(owngoal->pos) ;
} else if(ball->dist < 30.0 && nearest_to_ballp()) {
chase(ball) ;
} else {
wandering(PPos(0.0,0.0),30.0) ;
}
}
}

void Player::shoot_or_pass() {
if(goal->dist < 20.0) {
shoot_to_goal() ;
} else {
VisualObject* target = newest_fore_teammate() ;

if((target == (VisualObject*)NULL)||(time - target->time > 100)) {
target = goal ;
}
kick_immediately(target) ;
}
}

void Player::wandering(PPos center, Real radius) {
cout << "Now, wandering." << endl ;

// Real dx = center.x - pos.x ;
// Real dy = center.y - pos.y ;
// Real d = sqrt(dx * dx + dy * dy) ;
Real d = center.distance(pos) ;

if(d < radius) {
Real tdir = drand(-180,180) ;
turn(tdir) ;
Real pow = drand(10,20) ;
dash(pow) ;
lpause() ;
} else {
go_toward(center) ;
}
turn_to(ball) ;
}


//======================================================================
//Forward
//======================================================================
void Player::play_as_forward() {
look_around() ;
while(True) {
estimate_position() ;
PPos bpos = estimate_object_pos(ball) ;
if(kickable()) {
shoot_to_goal() ;
} else if(ball->dist < 20.0) {
chase(ball) ;
} else if(bpos.x > pos.x) {
chase(ball) ;
} else {
wandering(landmark[LM_flag_pfc]->pos,20.0) ;
}
}
}

void Player::play_as_forward2() {
look_around() ;
while(True) {
estimate_position() ;
PPos bpos = estimate_object_pos(ball) ;
if(kickable()) {
shoot_to_goal() ;
} else if(ball->dist < 30.0) {
chase(ball) ;
} else if(bpos.x > pos.x) {
chase(ball) ;
} else {
wandering(PPos(10,0),30.0) ;
}
}
}

//======================================================================
//MidFielder2
//======================================================================
void Player::wandering2(PPos center, Real rx, Real ry) {
cout << "Now, wandering." << endl ;


Real d = center.distance(pos,PPos(rx,ry)) ;

if(d < 1.0) {
Real tdir = drand(-180,180) ;
turn(tdir) ;
Real pow = drand(10,20) ;
dash(pow) ;
lpause() ;
} else {
go_toward(center) ;
}
turn_to(ball) ;
}

void Player::play_as_midfielder2(PPos center, Real rx, Real ry) {
look_around() ;
while(True) {
estimate_position() ;
PPos bpos = estimate_object_pos(ball) ;
if(kickable()) {
shoot_or_pass() ;
} else if( center.distance(pos,PPos(rx,ry)) < 1.0 ) {
if(nearest_to_ballp())
chase(ball) ;
else
wandering(bpos,10.0) ;
} else {
wandering2(center,rx,ry) ;
}
}
}


Created on 17 December 1997. Last revised on 18 December 1997