/* This team is taken nearly directly from the rollers team provided with Tucker Balch's asciisoccer package. The original rollers team was developed by Steve Rowe. The conversion to tclsoccer was done by Randolph M. Jones, Colby College, 1998. */ #include #define CONTROL_TIME 13 #define WINGSPAN 8 /* Standard Functions already defined as unique in interface.c (These are here for reference, you don't have to redefine them */ /* #define InitializeGame UN(InitializeGame) #define InitializePoint UN(InitializePoint) #define WonPoint UN(WonPoint) #define LostPoint UN(LostPoint) #define GameOver UN(GameOver) #define Player1 UN(Player1) #define Player2 UN(Player2) #define Player3 UN(Player3) #define Player4 UN(Player4) */ /* Team global variables */ #define cycle UN(cycle) #define haveBall UN(haveBall) #define leader UN(leader) #define plx UN(plx) #define ply UN(ply) #define roles UN(roles) #define dirs UN(dirs) /* Team functions */ #define NearObject UN(NearObject) #define Behave UN(Behave) #define Lead UN(Lead) #define NorthWing UN(NorthWing) #define SouthWing UN(SouthWing) #define Rear UN(Rear) #define Regroup UN(Regroup) typedef char *(*functionPointer)(); static int cycle, haveBall, leader, plx[4], ply[4]; static functionPointer roles[4]; static char dirs[8][10] = { "NW", "N", "NE", "E", "SE", "S", "SW", "W" }; char *Lead (); char *NorthWing (); char *SouthWing (); char *Rear (); char *Behave (int id); void InitializeGame () { cycle = -1; haveBall = 0; } void InitializePoint () { int i; leader = -1; haveBall = 0; for (i=0; i<=3; i++) { plx[i] = 0; ply[i] = 0; } roles[0] = Lead; roles[1] = NorthWing; roles[2] = SouthWing; roles[3] = Rear; } void WonPoint () {}; void LostPoint () {}; void GameOver () {}; char *NearObject (char *obj) { int i; for (i=0; i<(sizeof(dirs)/sizeof(*dirs)); i++) { if (Content(dirs[i], obj)) { return(dirs[i]); } } return(""); } char *Player1 () { return(Behave(0)); } char *Player2 () { return(Behave(1)); } char *Player3 () { return(Behave(2)); } char *Player4 () { return(Behave(3)); } void Regroup (int newLead) { int i, score, good; for (i=0; i<4; i++) { roles[i] = 0; } leader = newLead; roles[leader] = Lead; /* southernmost unassigned player is south wing */ score = -1; for (i=0; i<4; i++) { if (!roles[i]) { if (ply[i] > score) { score = ply[i]; good = i; } } } roles[good] = SouthWing; /* northernmost unassigned player is north wing */ score = 10000; for (i=0; i<4; i++) { if (!roles[i]) { if (ply[i] < score) { score = ply[i]; good = i; } } } roles[good] = NorthWing; /* easternmost unassigned player is rear */ score = -1; for (i=0; i<4; i++) { if (!roles[i]) { if (plx[i] > score) { score = plx[i]; good = i; } } } roles[good] = Rear; } char *Behave (int id) { /* Keep track of team positions */ plx[id] = MyX(); ply[id] = MyY(); cycle = (cycle + 1) % 4; if (cycle == 0) { haveBall--; } /* Whoever has the ball gets to be the leader */ if ((strlen(NearObject("BALL")) != 0) && (strcmp(BallDir(), "E")) && (strcmp(BallDir(), "NE")) && (strcmp(BallDir(), "SE")) && (strcmp(BallDir(), "N")) && (strcmp(BallDir(), "S"))) { haveBall = CONTROL_TIME; /* regroup to new leader if necessary */ if (leader != id) { Regroup(id); } } else if (haveBall <= 0) { leader = -1; } /* If there is a leader, then work as a team, otherwise everybody for themselves */ if (leader >= 0) { return (*roles[id])(); } else { return(Lead()); } } char *Lead () { int i, kickSouth; int x = MyX(); int y = MyY(); /* If lead is east of the ball and an opponent is around, get the ball out of here */ if ((strlen(NearObject("OPPONENT")) > 0) && (Content("SW","BALL") || Content("W","BALL") || Content("NW","BALL"))) { return("KICK"); } /* Try to kick away from the bulk of the players */ kickSouth = 0; for (i=0; i<4; i++) { if ((y < YSize() - 4) && (ply[i] < y)) { kickSouth++; } if ((y > 5) && (ply[i] > y)) { kickSouth--; } } /* Kick south if we "should" kick south or if we are near defending goal */ if (Content("SW","BALL")) { if ((x > 3 * XSize() / 4) || (kickSouth > 0)) { return("KICK"); } /* else try to move to kick straight west */ return("S"); } /* Similarly for north */ if (Content("NW","BALL")) { if ((x > 3 * XSize() / 4) || (kickSouth < 0)) { return("KICK"); } return("N"); } if (Content("W","BALL")) { /* If there is a strong preference to kick the ball north or south, try to move to do so */ if (kickSouth >= 3) { return("N"); } if (kickSouth <= -3) { return("S"); } /* Otherwise kick toward the goal */ return("KICK"); } if (Content("N","BALL")) { /* If an opponent can kick toward my goal, try to kick the ball away */ if (Content("W","OPPONENT") && (Content("NW","OPPONENT"))) { return("KICK"); } /* If ball is near my defending goal, really try to kick it */ if ((x > 3 * XSize() / 4) && \ (Content("W","OPPONENT") || Content("NW","OPPONENT"))) { return("KICK"); } /* If there are no opponents and I want to kick south, move to try to do so */ if ((kickSouth >= 0) && Content("NE","EMPTY")) { return("NE"); } /* else if I want to kick north, just move E so I can kick NW */ return("E"); } if (Content("NE","BALL")) { /* If an opponent can get to the ball, get between it and the ball */ if (Content("N","EMPTY") && (Content("NW","OPPONENT"))) { return("N"); } /* else get between the ball and the defending goal */ return("E"); } if (Content("E","BALL")) { /* Get into position to kick the ball, if possible */ if ((kickSouth > 0) && Content("NE","EMPTY")) { return("NE"); } if ((kickSouth < 0) && Content("SE","EMPTY")) { return("SE"); } /* else try to block any opponents */ if (Content("W","OPPONENT")) { return("W"); } /* else just move out of the way */ if (Content("N","EMPTY")) { return("N"); } return("S"); } if (Content("SE","BALL")) { /* If an opponent can get to the ball, get between it and the ball */ if (Content("S","EMPTY") && (Content("SW","OPPONENT"))) { return("S"); } /* else get between the ball and the defending goal */ return("E"); } if (Content("S","BALL")) { /* If an opponent can kick toward my goal, try to kick the ball away */ if (Content("W","OPPONENT") && (Content("SW","OPPONENT"))) { return("KICK"); } /* If ball is near my defending goal, really try to kick it */ if ((x > 3 * XSize() / 4) && \ (Content("W","OPPONENT") || Content("SW","OPPONENT"))) { return("KICK"); } /* If there are no opponents and I want to kick south, move to try to do so */ if ((kickSouth >= 0) && Content("SE","EMPTY")) { return("SE"); } /* else if I want to kick north, just move E so I can kick NW */ return("E"); } /* else just move toward the ball */ return(BallDir()); } char *NorthWing () { int x; int y; char ew = 0; char ns = 0; x = MyX(); y = MyY(); /* If near the ball, act like a leader */ if (strlen(NearObject("BALL")) > 0) { return(Lead()); } /* Try to get into position */ if (Content("N","EMPTY") && (y > ply[leader] - WINGSPAN)) { ns = 'N'; } if (Content("S","EMPTY") && (y < ply[leader] - WINGSPAN)) { ns = 'S'; } if ((x < plx[leader]) && (y == ply[leader])) { ns = 'S'; } if (Content("W","EMPTY") && (x > plx[leader] + WINGSPAN)) { ew = 'W'; } if (Content("E","EMPTY") && (x < plx[leader] + WINGSPAN)) { ew = 'E'; } if ((ew == 'E') && (ns == 'N')) { return("NE"); } if ((ew == 'E') && (ns == 'S')) { return("SE"); } if ((ew == 'W') && (ns == 'N')) { return("NW"); } if ((ew == 'W') && (ns == 'S')) { return("SW"); } if (ew == 'E') { return("E"); } if (ew == 'W') { return("W"); } if (ns == 'N') { return("N"); } if (ns == 'S') { return("S"); } return(BallDir()); } char *SouthWing () { int x; int y; char ew = 0; char ns = 0; x = MyX(); y = MyY(); /* If near the ball, act like a leader */ if (strlen(NearObject("BALL")) > 0) { return(Lead()); } /* Try to get into position */ if (Content("N","EMPTY") && (y > ply[leader] + WINGSPAN)) { ns = 'N'; } if (Content("S","EMPTY") && (y < ply[leader] + WINGSPAN)) { ns = 'S'; } if ((x < plx[leader]) && (y == ply[leader])) { ns = 'N'; } if (Content("W","EMPTY") && (x > plx[leader] + WINGSPAN)) { ew = 'W'; } if (Content("E","EMPTY") && (x < plx[leader] + WINGSPAN)) { ew = 'E'; } if ((ew == 'E') && (ns == 'N')) { return("NE"); } if ((ew == 'E') && (ns == 'S')) { return("SE"); } if ((ew == 'W') && (ns == 'N')) { return("NW"); } if ((ew == 'W') && (ns == 'S')) { return("SW"); } if (ew == 'E') { return("E"); } if (ew == 'W') { return("W"); } if (ns == 'N') { return("N"); } if (ns == 'S') { return("S"); } return(BallDir()); } char *Rear () { return(Lead()); }