00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Dice.hh"
00018
00019 #define CHECK_TEAM \
00020 { \
00021 if (selected_team_ == NULL) \
00022 return BAD_TEAM; \
00023 }
00024
00025 #define CHECK_PLAYER \
00026 { \
00027 if (selected_player_ == NULL) \
00028 return BAD_PLAYER; \
00029 }
00030
00031 #define CHECK_POS(X, Y) \
00032 { \
00033 if (X < 0 || X >= COLS || Y < 0 || Y >= ROWS) \
00034 return BAD_ARGUMENT; \
00035 }
00036
00037
00038
00039 inline Api::Api(CRules* rules)
00040 : BaseApi<CRules>(rules),
00041 selected_team_(NULL),
00042 selected_player_(NULL),
00043 skilled_player_(NULL)
00044 {
00045 for (int i = 0; i < DCL_LAST; i++)
00046 possible_declarations_[i] = false;
00047 for (int i = 0; i < ACT_LAST; i++)
00048 possible_actions_[i] = false;
00049 }
00050
00051 inline Api::~Api()
00052 {
00053 }
00054
00055
00056
00057
00058
00059 inline void Api::doEndTurn()
00060 {
00061 rules_->sendPacket(MsgEndTurn());
00062 }
00063
00064 inline void Api::doMoveTurnMarker()
00065 {
00066 rules_->sendPacket(MsgMoveTurnMarker());
00067 }
00068
00069 inline void Api::doAskIllegalProcedure()
00070 {
00071 rules_->sendPacket(MsgIllegalProc());
00072 }
00073
00074 inline int Api::doChooseKickoff(bool kickoff)
00075 {
00076 assert(rules_->getState() != GS_WAIT);
00077 if (rules_->getState() != GS_DRAWKICKER)
00078 {
00079 LOG2("You do not have the choice of who will kick off. (%1)", gameStateString());
00080 return INVALID_ACTION;
00081 }
00082
00083 MsgDrawKicker pkt;
00084 pkt.kickoff = (kickoff ? 1 : 0);
00085 rules_->sendPacket(pkt);
00086 return SUCCESS;
00087 }
00088
00089 inline int Api::doPlacePlayer(const Point& pos)
00090 {
00091 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00092 CHECK_TEAM;
00093 CHECK_PLAYER;
00094
00095 if (rules_->getState() != GS_INITKICKOFF)
00096 {
00097 LOG2("It's not the right moment to place player #%1 on the field. (%2)",
00098 selected_player_->getId(), gameStateString());
00099 return INVALID_ACTION;
00100 }
00101
00102 Position player_pos(pos);
00103 MsgPlayerPos pkt;
00104 pkt.player_id = selected_player_->getId();
00105 pkt.col = player_pos.col;
00106 pkt.row = player_pos.row;
00107 rules_->sendPacket(pkt);
00108
00109 return SUCCESS;
00110 }
00111
00112 inline int Api::doEndPlacement()
00113 {
00114 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00115
00116 if (rules_->getState() != GS_INITKICKOFF)
00117 {
00118 LOG2("It's not the right moment to end team placement. (%1)", gameStateString());
00119 return INVALID_ACTION;
00120 }
00121
00122 MsgInitKickoff pkt;
00123 pkt.place_team = 1;
00124 rules_->sendPacket(pkt);
00125
00126 return SUCCESS;
00127 }
00128
00129 inline int Api::doPlaceBall(const Point& pos)
00130 {
00131 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00132
00133 if (rules_->getState() != GS_KICKOFF)
00134 {
00135 LOG2("This is not the right moment to kick the ball. (%1)", gameStateString());
00136 return INVALID_ACTION;
00137 }
00138
00139 Position bpos(pos);
00140 if (!rules_->field_->intoField(bpos))
00141 {
00142 LOG2("Kick-off rejected. Ball is not into the field: %1.", pos);
00143 return INVALID_ACTION;
00144 }
00145 if ((rules_->getCoachId() == 0 && bpos.row < 13)
00146 || (rules_->getCoachId() == 1 && bpos.row > 12))
00147 {
00148 LOG2("Kick-off rejected. Ball is in your part of the field: %1.", pos);
00149 return INVALID_ACTION;
00150 }
00151 MsgBallPos pkt;
00152 pkt.row = bpos.row;
00153 pkt.col = bpos.col;
00154 rules_->sendPacket(pkt);
00155
00156 return SUCCESS;
00157 }
00158
00159 inline int Api::doGiveBall(int player_id)
00160 {
00161 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00162
00163 if (rules_->getState() != GS_TOUCHBACK)
00164 {
00165 LOG2("There is no touchback. (%1)", gameStateString());
00166 return INVALID_ACTION;
00167 }
00168
00169 const CPlayer* player = getPlayer(player_id);
00170 if (player == NULL)
00171 {
00172 LOG2("Player `%1' does not exist.", player_id);
00173 return BAD_PLAYER;
00174 }
00175
00176 if (player->getStatus() != STA_STANDING)
00177 {
00178 LOG2("Player `%1' can't carry the ball. (%2)", player_id, player->getStatus());
00179 return INVALID_ACTION;
00180 }
00181 MsgGiveBall pkt;
00182 pkt.player_id = player_id;
00183 rules_->sendPacket(pkt);
00184 return SUCCESS;
00185 }
00186
00187 inline int Api::doReroll(bool reroll)
00188 {
00189 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00190 if (rules_->getState() != GS_REROLL && rules_->getState() != GS_BLOCK)
00191 {
00192 LOG2("Cannot do reroll nor accept (no dice to reroll). (%1)", gameStateString());
00193 return INVALID_ACTION;
00194 }
00195 if (reroll && !selected_team_->canUseReroll())
00196 {
00197 LOG2("Cannot use reroll (no one left or already use one this turn).");
00198 return INVALID_ACTION;
00199 }
00200
00201 MsgReroll msg(rules_->our_team_->getTeamId());
00202 msg.reroll = reroll;
00203 rules_->sendPacket(msg);
00204 return SUCCESS;
00205 }
00206
00207 inline int Api::doUseSkill(enum eSkill skill, bool useIt)
00208 {
00209 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00210
00211 if (skilled_player_ == NULL)
00212 return BAD_PLAYER;
00213 if (!skilled_player_->hasSkill(skill))
00214 {
00215 LOG2("Player %1 of team %2 doesn't have the skill %3.", skilled_player_->getId(),
00216 skilled_player_->getTeamId(), Player::stringify(skill));
00217 return INVALID_ACTION;
00218 }
00219 if (rules_->getState() != GS_REROLL && rules_->getState() != GS_SKILL)
00220 {
00221 LOG2("Cannot use the skill %1 or not now.", Player::stringify(skill));
00222 return INVALID_ACTION;
00223 }
00224 if (rules_->getState() == GS_REROLL && !useIt)
00225 {
00226 LOG2("Use Api::doReroll(false) in order to accept a roll result.");
00227 return INVALID_ACTION;
00228 }
00229
00230 MsgSkill msg(rules_->our_team_->getTeamId());
00231 msg.player_id = skilled_player_->getId();
00232 msg.skill = skill;
00233 msg.choice = (useIt ? 1 : 0 );
00234 rules_->sendPacket(msg);
00235 return SUCCESS;
00236 }
00237
00238 inline int Api::doDeclare(enum eDeclaredAction action)
00239 {
00240 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00241 CHECK_TEAM;
00242 CHECK_PLAYER;
00243
00244 if (action == DCL_UNASSIGNED)
00245 {
00246 LOG2("You can't declare an empty action for player #%1.", selected_player_->getId());
00247 return INVALID_ACTION;
00248 }
00249 return rules_->our_team_->declareAction(selected_player_, action);
00250 }
00251
00252 inline int Api::doChooseBlockDice(int n)
00253 {
00254 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00255 if (rules_->getState() != GS_BLOCK && rules_->getState() != GS_REROLL)
00256 {
00257 LOG2("You do not have the choice of which block dice to apply.");
00258 return INVALID_ACTION;
00259 }
00260 if (rules_->getState() == GS_REROLL)
00261 {
00262 MsgReroll msgr;
00263 msgr.reroll = false;
00264 rules_->sendPacket(msgr);
00265 }
00266 MsgBlockDice msg(rules_->our_team_->getTeamId());
00267 msg.dice = n;
00268 rules_->sendPacket(msg);
00269 return SUCCESS;
00270 }
00271
00272 inline int Api::doBlockPush(int n)
00273 {
00274 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00275 if (rules_->getState() != GS_PUSH)
00276 {
00277 LOG2("You do not have the choice of which square to push in.");
00278 return INVALID_ACTION;
00279 }
00280 MsgBlockPush msg(rules_->our_team_->getTeamId());
00281 msg.square_chosen = n;
00282 rules_->sendPacket(msg);
00283 return SUCCESS;
00284 }
00285
00286 inline int Api::doFollow(bool follow)
00287 {
00288 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00289 if (rules_->getState() != GS_FOLLOW)
00290 {
00291 LOG2("You do not have the choice to follow or not.");
00292 return INVALID_ACTION;
00293 }
00294 MsgFollow msg(rules_->our_team_->getTeamId());
00295 msg.follow = follow;
00296 rules_->sendPacket(msg);
00297 return SUCCESS;
00298 }
00299
00300 inline int Api::doStandUpPlayer()
00301 {
00302 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00303 CHECK_TEAM;
00304 CHECK_PLAYER;
00305
00306 return selected_player_->standUp();
00307 }
00308
00309 inline int Api::doMovePlayer(const Point& to)
00310 {
00311 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00312 CHECK_TEAM;
00313 CHECK_PLAYER;
00314
00315 return selected_player_->move(to);
00316 }
00317
00318 inline int Api::doBlockPlayer(int def_p)
00319 {
00320 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00321 CHECK_TEAM;
00322 CHECK_PLAYER;
00323
00324 CPlayer* opponent = rules_->other_team_->getPlayer(def_p);
00325 return selected_player_->block(opponent);
00326 }
00327
00328 inline int Api::doPassPlayer(const Point& to)
00329 {
00330 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00331 CHECK_TEAM;
00332 CHECK_PLAYER;
00333
00334 return selected_player_->pass(to);
00335 }
00336
00337 inline void Api::sendChatMessage(const std::string& msg)
00338 {
00339 if (rules_->getState() == GS_WAIT)
00340 return;
00341
00342 MsgChat pkt;
00343 stringToPacket(pkt.msg, msg, sizeof(pkt.msg));
00344 rules_->sendPacket(pkt);
00345 }
00346
00347 inline void Api::doCheatDice(int roll)
00348 {
00349 MsgCheatDice pkt;
00350 pkt.next_result = roll;
00351 rules_->sendPacket(pkt);
00352 }
00353
00354
00355
00356
00357
00358
00359 inline int Api::turn() const
00360 {
00361 return rules_->cur_turn_;
00362 }
00363
00364 inline int Api::half() const
00365 {
00366 return rules_->cur_half_;
00367 }
00368
00369 inline int Api::myTeamId() const
00370 {
00371 return rules_->getCoachId();
00372 }
00373
00374 inline Point Api::ball() const
00375 {
00376 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00377 return rules_->ball_->getPosition();
00378 }
00379
00380 inline const CPlayer* Api::getBallOwner() const
00381 {
00382 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00383 return rules_->ball_->getOwner();
00384 }
00385
00386 inline int Api::teamId(const Point& pos)
00387 {
00388 CHECK_POS(pos.x, pos.y);
00389 CPlayer* p = rules_->field_->getPlayer(pos);
00390 if (p != NULL)
00391 return p->getTeamId();
00392 return -1;
00393 }
00394
00395 inline int Api::playerId(const Point& pos)
00396 {
00397 CHECK_POS(pos.x, pos.y);
00398 CPlayer* p = rules_->field_->getPlayer(pos);
00399 if (p != NULL)
00400 return p->getId();
00401 return -1;
00402 }
00403
00404 inline void Api::selectTeam(int team_id)
00405 {
00406 selected_team_ = NULL;
00407 selected_player_ = NULL;
00408
00409 if (rules_->getState() == GS_WAIT)
00410 return;
00411 if (team_id == US || (team_id <= 1 && team_id == rules_->getCoachId()))
00412 selected_team_ = rules_->our_team_;
00413 if (team_id == THEM || ((team_id == 0 || team_id == 1) && team_id != rules_->getCoachId()))
00414 selected_team_ = rules_->other_team_;
00415 }
00416
00417 inline int Api::selectPlayer(int player_id)
00418 {
00419 CHECK_TEAM;
00420 selected_player_ = selected_team_->getPlayer(player_id);
00421 return selected_player_ == NULL ? BAD_PLAYER : SUCCESS;
00422 }
00423
00424 inline int Api::selectSkilledPlayer(int player_id)
00425 {
00426 skilled_player_ = rules_->our_team_->getPlayer(player_id);
00427 return skilled_player_ == NULL ? BAD_PLAYER : SUCCESS;
00428 }
00429
00430 inline int Api::declarationPossibleNumber()
00431 {
00432 CHECK_TEAM;
00433 CHECK_PLAYER;
00434
00435 if (selected_player_->hasPlayed())
00436 return 0;
00437 if (selected_player_->getAction() != DCL_UNASSIGNED)
00438 return 0;
00439 if (selected_player_->getStatus() != STA_STANDING
00440 && selected_player_->getStatus() != STA_PRONE)
00441 return 0;
00442
00443 int number = DCL_LAST;
00444 for (int i = 0; i < DCL_LAST; i++)
00445 possible_declarations_[i] = true;
00446
00447 if (selected_player_->getStatus() == STA_PRONE ||
00448 !(rules_->getField()->hasAdjacentPlayer(
00449 selected_player_->getPosition(),
00450 STA_STANDING,
00451 rules_->other_team_->getTeamId())))
00452 {
00453 number --;
00454 possible_declarations_[DCL_BLOCK] = false;
00455 }
00456 if (selected_team_->hasDoneBlitz())
00457 {
00458 number --;
00459 possible_declarations_[DCL_BLITZ] = false;
00460 }
00461 if (selected_team_->hasDonePass())
00462 {
00463 number --;
00464 possible_declarations_[DCL_PASS] = false;
00465 }
00466 return number;
00467 }
00468
00469 inline int Api::declarationPossible(int index) const
00470 {
00471 if (index < 0 || DCL_LAST <= index)
00472 return BAD_ARGUMENT;
00473
00474 int declared_action = DCL_UNASSIGNED;
00475 while (index >= 0)
00476 {
00477 declared_action ++;
00478 if (declared_action >= DCL_LAST)
00479 return BAD_ARGUMENT;
00480 else if (possible_declarations_[declared_action])
00481 index --;
00482 }
00483 return declared_action;
00484 }
00485
00486 inline int Api::actionPossibleNumber()
00487 {
00488 CHECK_TEAM;
00489 CHECK_PLAYER;
00490
00491 if (selected_player_->hasPlayed())
00492 return 0;
00493 if (selected_player_->getAction() != DCL_UNASSIGNED)
00494 return 0;
00495 if (selected_player_->getStatus() != STA_STANDING
00496 && selected_player_->getStatus() != STA_PRONE)
00497 return 0;
00498
00499 int number = 0;
00500 for (int i = 0; i < ACT_LAST; i++)
00501 possible_actions_[i] = false;
00502
00503 if (selected_player_->getStatus() == STA_PRONE)
00504 {
00505 if (selected_player_->getAction() != DCL_BLOCK)
00506 {
00507 number ++;
00508 possible_actions_[ACT_STANDUP] = true;
00509 }
00510 return number;
00511 }
00512
00513 if (selected_player_->getAction() != DCL_BLOCK
00514 && rules_->getField()->hasAdjacentEmptySquare(selected_player_->getPosition()))
00515 {
00516 number ++;
00517 possible_actions_[ACT_MOVE] = true;
00518 }
00519 if ((selected_player_->getAction() == DCL_BLOCK
00520 || selected_player_->getAction() == DCL_BLITZ)
00521 && rules_->getField()->hasAdjacentPlayer(
00522 selected_player_->getPosition(),
00523 STA_STANDING,
00524 rules_->other_team_->getTeamId())
00525 && !(selected_player_->hasBlocked()))
00526 {
00527 number ++;
00528 possible_actions_[ACT_BLOCK] = true;
00529 }
00530 if (selected_player_->getAction() == DCL_PASS
00531 && selected_player_ == rules_->ball_->getOwner()
00532 )
00533 {
00534 number ++;
00535 possible_actions_[ACT_THROW] = true;
00536 }
00537 return number;
00538 }
00539
00540 inline int Api::actionPossible(int index) const
00541 {
00542 if (index < 0 || ACT_LAST <= index)
00543 return BAD_ARGUMENT;
00544
00545 int action = -1;
00546 while (index >= 0)
00547 {
00548 action ++;
00549 if (action >= ACT_LAST)
00550 return BAD_ARGUMENT;
00551 else if (possible_actions_[action])
00552 index --;
00553 }
00554 return action;
00555 }
00556
00557 inline int Api::moveLength(const Point& to)
00558 {
00559 CHECK_TEAM;
00560 CHECK_PLAYER;
00561 CHECK_POS(to.x, to.y);
00562
00563 player_path_ = &rules_->field_->getPath(selected_player_->getPosition(),
00564 to,
00565 selected_player_);
00566 return player_path_->size();
00567 }
00568
00569 inline int Api::moveDifficulty(int step)
00570 {
00571 if (player_path_ == NULL || step < 0 || step >= (int)player_path_->size())
00572 return BAD_ARGUMENT;
00573
00574 Position step_pos((*player_path_)[step]);
00575 int nbt = rules_->field_->getNbTackleZones(selected_team_->getTeamId(), step_pos);
00576 if (nbt == 0)
00577 return 0;
00578 return (7 - std::min(selected_player_->getAg(), 6)) + nbt - 1;
00579 }
00580
00581 inline Point Api::movePath(int step)
00582 {
00583 if (player_path_ == NULL || step < 0 || step >= (int)player_path_->size())
00584 return Point(-1, -1);
00585
00586 return (*player_path_)[step];
00587 }
00588
00589 inline int Api::movePossible(const Point& to)
00590 {
00591 CHECK_TEAM;
00592 CHECK_PLAYER;
00593 CHECK_POS(to.x, to.y);
00594
00595
00596 return rules_->field_->getPath(selected_player_->getPosition(),
00597 to,
00598 selected_player_).empty() ? 0 : 1;
00599 }
00600
00601 inline int Api::remainingTime() const
00602 {
00603 int state = rules_->getState();
00604 int tr;
00605
00606 if (state != GS_COACH1 && state != GS_COACH2)
00607 return -1;
00608 tr = rules_->timer_.getTimeRemaining();
00609 return tr < 0 ? 0 : tr;
00610 }
00611
00612
00613 inline const char* Api::gameStateString() const
00614 {
00615 switch (rules_->getState())
00616 {
00617 case GS_INITGAME:
00618 return "GS_INITGAME";
00619 case GS_INITHALF:
00620 return "GS_INITHALF";
00621 case GS_DRAWKICKER:
00622 return "GS_DRAWKICKER";
00623 case GS_INITKICKOFF:
00624 return "GS_INITKICKOFF";
00625 case GS_KICKOFF:
00626 return "GS_KICKOFF";
00627 case GS_COACH1:
00628 return "GS_COACH1";
00629 case GS_COACH2:
00630 return "GS_COACH2";
00631 case GS_TOUCHBACK:
00632 return "GS_TOUCHBACK";
00633 case GS_REROLL:
00634 return "GS_REROLL";
00635 case GS_BLOCK:
00636 return "GS_BLOCK";
00637 case GS_PUSH:
00638 return "GS_PUSH";
00639 case GS_FOLLOW:
00640 return "GS_FOLLOW";
00641 case GS_SKILL:
00642 return "GS_SKILL";
00643 }
00644 return BaseApi<CRules>::getStateString();
00645 }
00646
00647 inline const CTeam* Api::getTeam() const
00648 {
00649 return selected_team_;
00650 }
00651
00652 inline const CPlayer* Api::getPlayer() const
00653 {
00654 return selected_player_;
00655 }
00656
00657 inline const CPlayer* Api::getPlayer(int player_id)
00658 {
00659 if (selected_team_ == NULL)
00660 return NULL;
00661 return selected_team_->getPlayer(player_id);
00662 }
00663
00664 inline const CPlayer* Api::getPlayer(const Point& pos)
00665 {
00666 return rules_->field_->getPlayer(pos);
00667 }
00668
00669 inline const Weather* Api::getWeather() const
00670 {
00671 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00672 return rules_->weather_;
00673 }