00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Ball.hh"
00018 #include "Dice.hh"
00019
00020 #define CHECK_TEAM \
00021 { \
00022 if (selected_team_ == NULL) \
00023 return BAD_TEAM; \
00024 }
00025
00026 #define CHECK_PLAYER \
00027 { \
00028 if (selected_player_ == NULL) \
00029 return BAD_PLAYER; \
00030 }
00031
00032 #define CHECK_COORD(X, Y) \
00033 { \
00034 if (X < 0 || X >= COLS || Y < 0 || Y >= ROWS) \
00035 return BAD_ARGUMENT; \
00036 }
00037
00038
00039
00040 inline Api::Api(CRules* rules)
00041 : BaseApi<CRules>(rules),
00042 selected_team_(NULL),
00043 selected_player_(NULL),
00044 skilled_player_(NULL),
00045 player_path_(NULL)
00046 {
00047 for (int i = 0; i < ACT_LAST; i++)
00048 possible_actions_[i] = false;
00049 for (int i = 0; i < EFF_LAST; i++)
00050 possible_efforts_[i] = false;
00051 }
00052
00053 inline Api::~Api()
00054 {
00055 }
00056
00057
00058
00059
00060
00061 inline int Api::doEndTurn()
00062 {
00063 assert(rules_->getState() != GS_WAIT);
00064 rules_->countRequestSending();
00065 rules_->sendPacket(MsgEndTurn());
00066 return SUCCESS;
00067 }
00068
00069 inline int Api::doCalmDown()
00070 {
00071 assert(rules_->getState() != GS_WAIT);
00072 if (rules_->getState() != GS_TOUCHDOOOWN)
00073 {
00074 LOG2("You do not have to stop fidgeting. (%1)", gameStateString());
00075 return INVALID_REQUEST;
00076 }
00077
00078 rules_->countQueryProcessed();
00079 rules_->sendPacket(MsgTouchdooown());
00080 return SUCCESS;
00081 }
00082
00083 inline int Api::doCelebrate()
00084 {
00085 assert(rules_->getState() != GS_WAIT);
00086 if (rules_->getState() != GS_CELEBRATE)
00087 {
00088 LOG2("There is nothing to celebrate. (%1)", gameStateString());
00089 return INVALID_REQUEST;
00090 }
00091
00092 rules_->countQueryProcessed();
00093 rules_->sendPacket(MsgEndGame());
00094 return SUCCESS;
00095 }
00096
00097 inline int Api::doMoveTurnMarker()
00098 {
00099 assert(rules_->getState() != GS_WAIT);
00100 rules_->sendPacket(MsgMoveTurnMarker());
00101 return SUCCESS;
00102 }
00103
00104 inline int Api::doAskIllegalProcedure()
00105 {
00106 assert(rules_->getState() != GS_WAIT);
00107 rules_->sendPacket(MsgIllegalProc());
00108 return SUCCESS;
00109 }
00110
00111 inline int Api::doChooseKickoff(bool kickoff)
00112 {
00113 assert(rules_->getState() != GS_WAIT);
00114 if (rules_->getState() != GS_DRAWKICKER)
00115 {
00116 LOG2("You do not have the choice of who will kick off. (%1)", gameStateString());
00117 return INVALID_REQUEST;
00118 }
00119
00120 MsgDrawKicker pkt;
00121 pkt.kickoff = (kickoff ? 1 : 0);
00122 rules_->countQueryProcessed();
00123 rules_->sendPacket(pkt);
00124 return SUCCESS;
00125 }
00126
00127 inline int Api::doPlacePlayer(const Coordinates& coord)
00128 {
00129 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00130 CHECK_TEAM;
00131 CHECK_PLAYER;
00132
00133 if (rules_->getState() != GS_INITKICKOFF)
00134 {
00135 LOG2("It's not the right moment to place player #%1 on the field. (%2)",
00136 selected_player_->getId(), gameStateString());
00137 return INVALID_REQUEST;
00138 }
00139
00140 MsgPlayerCoord pkt;
00141 pkt.player_id = selected_player_->getId();
00142 pkt.col = coord.col;
00143 pkt.row = coord.row;
00144 rules_->sendPacket(pkt);
00145
00146 return SUCCESS;
00147 }
00148
00149 inline int Api::doPlaceTeam(int formation_id)
00150 {
00151 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00152
00153 if (rules_->getState() != GS_INITKICKOFF)
00154 {
00155 LOG2("It's not the right moment to place our team on the field. (%1)", gameStateString());
00156 return INVALID_REQUEST;
00157 }
00158 if (formation_id < 1 || 4 < formation_id)
00159 {
00160 LOG2("`%1' is not a valid formation identifier.", formation_id);
00161 return INVALID_REQUEST;
00162 }
00163
00164 MsgPlayerCoord pkt;
00165 for (int player_id = 1; player_id <= MAX_PLAYER; player_id++)
00166 if (rules_->our_team_->getPlayer(player_id) != NULL
00167 && rules_->our_team_->getPlayer(player_id)->getStatus() == STA_STANDING)
00168 {
00169 pkt.player_id = player_id;
00170 pkt.col = -1;
00171 pkt.row = -1;
00172 rules_->sendPacket(pkt);
00173 }
00174 rules_->our_team_->placeTeam(formation_id);
00175 return SUCCESS;
00176 }
00177
00178 inline int Api::doEndPlacement()
00179 {
00180 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00181
00182 if (rules_->getState() != GS_INITKICKOFF)
00183 {
00184 LOG2("It's not the right moment to end team placement. (%1)", gameStateString());
00185 return INVALID_REQUEST;
00186 }
00187
00188 MsgInitKickoff pkt;
00189 pkt.place_team = 1;
00190 rules_->countQueryProcessed();
00191 rules_->sendPacket(pkt);
00192
00193 return SUCCESS;
00194 }
00195
00196 inline int Api::doPlaceBall(const Coordinates& coord)
00197 {
00198 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00199
00200 if (rules_->getState() != GS_KICKOFF)
00201 {
00202 LOG2("This is not the right moment to kick the ball. (%1)", gameStateString());
00203 return INVALID_REQUEST;
00204 }
00205
00206 if (!rules_->match_->getField()->intoField(coord))
00207 {
00208 LOG2("Kick-off rejected. Ball is not into the field: %1.", coord);
00209 return INVALID_REQUEST;
00210 }
00211 if ((rules_->getCoachId() == 0 && coord.row < 13)
00212 || (rules_->getCoachId() == 1 && coord.row > 12))
00213 {
00214 LOG2("Kick-off rejected. Ball is in your part of the field: %1.", coord);
00215 return INVALID_REQUEST;
00216 }
00217 MsgBallCoord pkt;
00218 pkt.row = coord.row;
00219 pkt.col = coord.col;
00220 rules_->countQueryProcessed();
00221 rules_->sendPacket(pkt);
00222
00223 return SUCCESS;
00224 }
00225
00226 inline int Api::doGiveBall(int player_id)
00227 {
00228 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00229
00230 if (rules_->getState() != GS_TOUCHBACK)
00231 {
00232 LOG2("There is no touchback. (%1)", gameStateString());
00233 return INVALID_REQUEST;
00234 }
00235
00236 const CPlayer* player = getPlayer(player_id);
00237 if (player == NULL)
00238 {
00239 LOG2("Player `%1' does not exist.", player_id);
00240 return BAD_PLAYER;
00241 }
00242
00243 if (player->getStatus() != STA_STANDING)
00244 {
00245 LOG2("Player `%1' can't carry the ball. (%2)", player_id, player->getStatus());
00246 return INVALID_REQUEST;
00247 }
00248 MsgBallOwner pkt;
00249 pkt.player_id = player_id;
00250 rules_->countQueryProcessed();
00251 rules_->sendPacket(pkt);
00252 return SUCCESS;
00253 }
00254
00255 inline int Api::doReroll(bool reroll)
00256 {
00257 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00258 if (rules_->getState() != GS_REROLL && rules_->getState() != GS_BLOCK)
00259 {
00260 LOG2("Cannot do reroll nor accept (no dice to reroll). (%1)", gameStateString());
00261 return INVALID_REQUEST;
00262 }
00263 if (reroll && !rules_->our_team_->canUseReroll())
00264 {
00265 LOG2("Cannot use reroll (no one left or already use one this turn).");
00266 return INVALID_REQUEST;
00267 }
00268
00269 MsgReroll msg(rules_->getCoachId());
00270 msg.reroll = reroll;
00271 rules_->countQueryProcessed();
00272 rules_->sendPacket(msg);
00273 return SUCCESS;
00274 }
00275
00276 inline int Api::doUseSkill(enum eSkill skill, bool useIt)
00277 {
00278 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00279
00280 if (skilled_player_ == NULL)
00281 return BAD_PLAYER;
00282 if (!skilled_player_->hasSkill(skill))
00283 {
00284 LOG2("Player %1 of team %2 doesn't have the skill %3.", skilled_player_->getId(),
00285 skilled_player_->getTeamId(), Player::stringify(skill));
00286 return INVALID_REQUEST;
00287 }
00288 if (rules_->getState() != GS_REROLL && rules_->getState() != GS_SKILL)
00289 {
00290 LOG2("Cannot use the skill %1 or not now.", Player::stringify(skill));
00291 return INVALID_REQUEST;
00292 }
00293 if (rules_->getState() == GS_REROLL && !useIt)
00294 {
00295 LOG2("Use Api::doReroll(false) in order to accept a roll result.");
00296 return INVALID_REQUEST;
00297 }
00298
00299 MsgSkill msg(rules_->getCoachId());
00300 msg.player_id = skilled_player_->getId();
00301 msg.skill = skill;
00302 msg.choice = (useIt ? 1 : 0 );
00303 rules_->countQueryProcessed();
00304 rules_->sendPacket(msg);
00305 return SUCCESS;
00306 }
00307
00308 inline int Api::doBeginAction(enum eAction action)
00309 {
00310 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00311 CHECK_TEAM;
00312 CHECK_PLAYER;
00313
00314 if (action == ACT_UNASSIGNED)
00315 {
00316 LOG2("Cannot begin an unassigned action for player #%1.",
00317 selected_player_->getId());
00318 return INVALID_REQUEST;
00319 }
00320 return rules_->our_team_->beginAction(selected_player_, action);
00321 }
00322
00323 inline int Api::doEndAction()
00324 {
00325 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00326 return rules_->our_team_->endAction();
00327 }
00328
00329 inline int Api::doChooseBlockDice(int n)
00330 {
00331 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00332 if (rules_->getState() != GS_BLOCK && rules_->getState() != GS_REROLL)
00333 {
00334 LOG2("You do not have the choice of which block dice to apply.");
00335 return INVALID_REQUEST;
00336 }
00337 if (rules_->getState() == GS_REROLL)
00338 {
00339 rules_->sq_->storeBlockDiceChoice(n);
00340 MsgReroll msgr;
00341 msgr.reroll = false;
00342 rules_->countQueryProcessed();
00343 rules_->sendPacket(msgr);
00344 }
00345 else
00346 {
00347 MsgBlockDice msg(rules_->getCoachId());
00348 msg.dice = n;
00349 rules_->countQueryProcessed();
00350 rules_->sendPacket(msg);
00351 }
00352 return SUCCESS;
00353 }
00354
00355 inline int Api::doBlockPush(int n)
00356 {
00357 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00358 if (rules_->getState() != GS_PUSH)
00359 {
00360 LOG2("You do not have the choice of which square to push in.");
00361 return INVALID_REQUEST;
00362 }
00363 MsgBlockPush msg(rules_->getCoachId());
00364 msg.chosen_square = n;
00365 rules_->countQueryProcessed();
00366 rules_->sendPacket(msg);
00367 return SUCCESS;
00368 }
00369
00370 inline int Api::doFollow(bool follow)
00371 {
00372 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00373 if (rules_->getState() != GS_FOLLOW)
00374 {
00375 LOG2("You do not have the choice to follow or not.");
00376 return INVALID_REQUEST;
00377 }
00378 MsgFollow msg(rules_->getCoachId());
00379 msg.follow = follow;
00380 rules_->countQueryProcessed();
00381 rules_->sendPacket(msg);
00382 return SUCCESS;
00383 }
00384
00385 inline int Api::doEffort(enum eEffort effort, const Coordinates& to)
00386 {
00387 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00388 CHECK_TEAM;
00389 CHECK_PLAYER;
00390
00391 switch(effort)
00392 {
00393 case EFF_STANDUP:
00394 return selected_player_->standUp();
00395 break;
00396 case EFF_MOVE:
00397 return selected_player_->move(to);
00398 break;
00399 case EFF_BLOCK:
00400 {
00401 CPlayer* opponent = rules_->getMatch()->getField()->getPlayer(to);
00402 return selected_player_->block(opponent);
00403 }
00404 break;
00405 case EFF_FOUL:
00406 {
00407 CPlayer* opponent = rules_->getMatch()->getField()->getPlayer(to);
00408 return selected_player_->foul(opponent);
00409 }
00410 break;
00411 case EFF_HANDOFF:
00412 {
00413 CPlayer* target = rules_->getMatch()->getField()->getPlayer(to);
00414 return selected_player_->handoff(target);
00415 }
00416 break;
00417 case EFF_THROW:
00418 return selected_player_->pass(to);
00419 break;
00420 default:
00421 LOG2("Cannot perform unknown effort %1 for player #%2.",
00422 effort, selected_player_->getId());
00423 return INVALID_REQUEST;
00424 break;
00425 }
00426 }
00427
00428 inline int Api::doStandUpPlayer()
00429 {
00430 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00431 CHECK_TEAM;
00432 CHECK_PLAYER;
00433
00434 return selected_player_->standUp();
00435 }
00436
00437 inline int Api::doMovePlayer(const Coordinates& to)
00438 {
00439 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00440 CHECK_TEAM;
00441 CHECK_PLAYER;
00442
00443 return selected_player_->move(to);
00444 }
00445
00446 inline int Api::doBlockPlayer(int def_p)
00447 {
00448 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00449 CHECK_TEAM;
00450 CHECK_PLAYER;
00451
00452 CPlayer* opponent = rules_->other_team_->getPlayer(def_p);
00453 return selected_player_->block(opponent);
00454 }
00455
00456 inline int Api::doPassPlayer(const Coordinates& to)
00457 {
00458 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00459 CHECK_TEAM;
00460 CHECK_PLAYER;
00461
00462 return selected_player_->pass(to);
00463 }
00464
00465 inline int Api::sendChatMessage(const std::string& msg)
00466 {
00467 if (rules_->getState() == GS_WAIT)
00468 return BAD_ARGUMENT;
00469
00470 MsgChat pkt;
00471 stringToPacket(pkt.msg, msg, sizeof(pkt.msg));
00472 rules_->sendPacket(pkt);
00473 return SUCCESS;
00474 }
00475
00476 inline int Api::sendDebugRequest()
00477 {
00478 if (rules_->getState() == GS_WAIT)
00479 return BAD_ARGUMENT;
00480
00481 Log::getDefaultInst()->getStream() << *rules_ << std::flush;
00482
00483 rules_->sendPacket(MsgDebug());
00484 return SUCCESS;
00485 }
00486
00487 inline int Api::doCheatDice(int roll)
00488 {
00489 if (rules_->getState() == GS_WAIT)
00490 return BAD_ARGUMENT;
00491
00492 MsgCheatDice pkt;
00493 pkt.next_result = roll;
00494 rules_->sendPacket(pkt);
00495 return SUCCESS;
00496 }
00497
00498
00499
00500
00501
00502
00503 inline int Api::turn() const
00504 {
00505 return rules_->match_->getTurn();
00506 }
00507
00508 inline int Api::half() const
00509 {
00510 return rules_->match_->getHalf();
00511 }
00512
00513 inline int Api::getActiveTeamId() const
00514 {
00515 return rules_->match_->getActiveTeamId();
00516 }
00517
00518 inline int Api::myTeamId() const
00519 {
00520 return rules_->getCoachId();
00521 }
00522
00523 inline Coordinates Api::ball() const
00524 {
00525 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00526 return rules_->match_->getBall()->getCoordinates();
00527 }
00528
00529 inline const CPlayer* Api::getBallOwner() const
00530 {
00531 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00532 return rules_->match_->getBall()->getOwner();
00533 }
00534
00535 inline int Api::teamId(const Coordinates& coord)
00536 {
00537 CHECK_COORD(coord.col, coord.row);
00538 CPlayer* p = rules_->match_->getField()->getPlayer(coord);
00539 if (p != NULL)
00540 return p->getTeamId();
00541 return -1;
00542 }
00543
00544 inline int Api::playerId(const Coordinates& coord)
00545 {
00546 CHECK_COORD(coord.col, coord.row);
00547 CPlayer* p = rules_->match_->getField()->getPlayer(coord);
00548 if (p != NULL)
00549 return p->getId();
00550 return -1;
00551 }
00552
00553 inline int Api::selectTeam(int team_id)
00554 {
00555 if (rules_->getState() == GS_WAIT ||
00556 (team_id != 0 && team_id != 1))
00557 return BAD_ARGUMENT;
00558
00559 selected_team_ = NULL;
00560 selected_player_ = NULL;
00561
00562 if (team_id != 0 && team_id != 1)
00563 return BAD_ARGUMENT;
00564
00565 selected_team_ = rules_->match_->getTeam(team_id);
00566 return SUCCESS;
00567 }
00568
00569 inline int Api::selectPlayer(int player_id)
00570 {
00571 CHECK_TEAM;
00572 selected_player_ = selected_team_->getPlayer(player_id);
00573 return selected_player_ == NULL ? BAD_PLAYER : SUCCESS;
00574 }
00575
00576 inline int Api::selectSkilledPlayer(int player_id)
00577 {
00578 skilled_player_ = rules_->our_team_->getPlayer(player_id);
00579 return skilled_player_ == NULL ? BAD_PLAYER : SUCCESS;
00580 }
00581
00582 inline int Api::actionPossibleNumber()
00583 {
00584 CHECK_TEAM;
00585 CHECK_PLAYER;
00586
00587 if (selected_player_->hasPlayed())
00588 return 0;
00589 if (selected_player_->getAction() != ACT_UNASSIGNED)
00590 return 0;
00591 if (selected_player_->getStatus() != STA_STANDING
00592 && selected_player_->getStatus() != STA_PRONE)
00593 return 0;
00594
00595 int number = ACT_LAST;
00596 for (int i = 0; i < ACT_LAST; i++)
00597 possible_actions_[i] = true;
00598
00599 if (selected_player_->getStatus() == STA_PRONE ||
00600 !(rules_->match_->getField()->hasAdjacentPlayer(
00601 selected_player_->getCoordinates(),
00602 STA_STANDING,
00603 rules_->other_team_->getTeamId())))
00604 {
00605 number --;
00606 possible_actions_[ACT_BLOCK - 1] = false;
00607 }
00608 for (int i = 0; i < ACT_LAST; i++)
00609 {
00610 if (selected_team_->hasDoneAction(static_cast<enum eAction>(i + 1)) &&
00611 ((i + 1) == ACT_BLITZ ||
00612 (i + 1) == ACT_FOUL ||
00613 (i + 1) == ACT_PASS ||
00614 (i + 1) == ACT_TRANSMIT))
00615 {
00616 number --;
00617 possible_actions_[i] = false;
00618 }
00619 }
00620 return number;
00621 }
00622
00623 inline int Api::actionPossible(int index) const
00624 {
00625 if (index < 0 || ACT_LAST <= index)
00626 return BAD_ARGUMENT;
00627
00628 int action = ACT_UNASSIGNED;
00629 while (index >= 0)
00630 {
00631 action ++;
00632 if (action > ACT_LAST)
00633 return BAD_ARGUMENT;
00634 else if (possible_actions_[action - 1])
00635 index --;
00636 }
00637 return action;
00638 }
00639
00640 inline int Api::effortPossibleNumber()
00641 {
00642 CHECK_TEAM;
00643 CHECK_PLAYER;
00644
00645 if (selected_player_->hasPlayed())
00646 return 0;
00647 if (selected_player_->getAction() == ACT_UNASSIGNED)
00648 return 0;
00649 if (selected_player_->getStatus() != STA_STANDING
00650 && selected_player_->getStatus() != STA_PRONE)
00651 return 0;
00652
00653 int number = 0;
00654 for (int i = 0; i < EFF_LAST; i++)
00655 possible_efforts_[i] = false;
00656
00657 if (selected_player_->getStatus() == STA_PRONE)
00658 {
00659 if (selected_player_->getAction() != ACT_BLOCK
00660 && selected_player_->getMaRemain() > 0)
00661 {
00662 number ++;
00663 possible_efforts_[EFF_STANDUP - 1] = true;
00664 }
00665 return number;
00666 }
00667
00668 if (selected_player_->getAction() != ACT_BLOCK
00669 && selected_player_->getMaRemain() > 0
00670 && rules_->match_->getField()->hasAdjacentEmptySquare(selected_player_->getCoordinates()))
00671 {
00672 number ++;
00673 possible_efforts_[EFF_MOVE - 1] = true;
00674 }
00675 if ((selected_player_->getAction() == ACT_BLOCK
00676 || selected_player_->getAction() == ACT_BLITZ)
00677 && !(selected_player_->hasBlocked())
00678 && selected_player_->getMaRemain() > 0
00679 && rules_->match_->getField()->hasAdjacentPlayer(
00680 selected_player_->getCoordinates(),
00681 STA_STANDING,
00682 rules_->other_team_->getTeamId()))
00683 {
00684 number ++;
00685 possible_efforts_[EFF_BLOCK - 1] = true;
00686 }
00687 if (selected_player_->getAction() == ACT_FOUL
00688 && (!selected_player_->hasPlayed())
00689 && (rules_->match_->getField()->hasAdjacentPlayer(
00690 selected_player_->getCoordinates(), STA_PRONE,
00691 rules_->other_team_->getTeamId()) ||
00692 rules_->match_->getField()->hasAdjacentPlayer(
00693 selected_player_->getCoordinates(), STA_STUNNED,
00694 rules_->other_team_->getTeamId())))
00695 {
00696 number ++;
00697 possible_efforts_[EFF_FOUL - 1] = true;
00698 }
00699 if (selected_player_->getAction() == ACT_TRANSMIT
00700 && selected_player_ == rules_->match_->getBall()->getOwner()
00701 && (rules_->match_->getField()->hasAdjacentPlayer(
00702 selected_player_->getCoordinates(), STA_STANDING,
00703 rules_->our_team_->getTeamId()) ||
00704 rules_->match_->getField()->hasAdjacentPlayer(
00705 selected_player_->getCoordinates(), STA_STANDING,
00706 rules_->other_team_->getTeamId())))
00707 {
00708 number ++;
00709 possible_efforts_[EFF_HANDOFF - 1] = true;
00710 }
00711 if (selected_player_->getAction() == ACT_PASS
00712 && selected_player_ == rules_->match_->getBall()->getOwner())
00713 {
00714 number ++;
00715 possible_efforts_[EFF_THROW - 1] = true;
00716 }
00717 return number;
00718 }
00719
00720 inline int Api::effortPossible(int index) const
00721 {
00722 if (index < 0 || EFF_LAST <= index)
00723 return BAD_ARGUMENT;
00724
00725 int effort = EFF_UNASSIGNED;
00726 while (index >= 0)
00727 {
00728 effort ++;
00729 if (effort > EFF_LAST)
00730 return BAD_ARGUMENT;
00731 else if (possible_efforts_[effort - 1])
00732 index --;
00733 }
00734 return effort;
00735 }
00736
00737 inline int Api::isEffortPossible(int effort) const
00738 {
00739 if (effort <= EFF_UNASSIGNED || EFF_LAST < effort)
00740 return BAD_ARGUMENT;
00741
00742 return (possible_efforts_[effort - 1]) ? 1 : 0;
00743 }
00744
00745 inline int Api::moveLength(const Coordinates& to)
00746 {
00747 CHECK_TEAM;
00748 CHECK_PLAYER;
00749 CHECK_COORD(to.col, to.row);
00750
00751 player_path_ = &rules_->match_->getField()->getPath(selected_player_->getCoordinates(),
00752 to,
00753 selected_player_);
00754 return player_path_->size();
00755 }
00756
00757 inline int Api::moveDifficulty(int step)
00758 {
00759 if (player_path_ == NULL || step < 0 || step >= (int)player_path_->size())
00760 return BAD_ARGUMENT;
00761
00762 Coordinates from_coord = (step == 0)
00763 ? selected_player_->getCoordinates()
00764 : ((*player_path_)[step - 1]);
00765 int nbTZFrom = rules_->match_->getField()->getNbTackleZones(
00766 1 - selected_team_->getTeamId(), from_coord);
00767 if (nbTZFrom == 0)
00768 return 0;
00769
00770 Coordinates dest_coord = (*player_path_)[step];
00771 int tzDestMalus;
00772 if (selected_player_->hasSkill(SK_STUNTY))
00773 tzDestMalus = 0;
00774 else
00775 tzDestMalus = rules_->match_->getField()->getTackleZonesMalus(
00776 1 - selected_team_->getTeamId(), dest_coord);
00777 return (7 - std::min(selected_player_->getAg(), 6)) + tzDestMalus - 1;
00778 }
00779
00780 inline Coordinates Api::movePath(int step)
00781 {
00782 if (player_path_ == NULL || step < 0 || step >= (int)player_path_->size())
00783 return Coordinates(-1, -1);
00784
00785 return (*player_path_)[step];
00786 }
00787
00788 inline int Api::movePossible(const Coordinates& to)
00789 {
00790 CHECK_TEAM;
00791 CHECK_PLAYER;
00792 CHECK_COORD(to.col, to.row);
00793
00794
00795 return rules_->match_->getField()->getPath(selected_player_->getCoordinates(),
00796 to,
00797 selected_player_).empty() ? 0 : 1;
00798 }
00799
00800 inline int Api::blockDicesNumber(const Coordinates& to) const
00801 {
00802 CHECK_TEAM;
00803 CHECK_PLAYER;
00804 CHECK_COORD(to.col, to.row);
00805
00806 if (!to.isNear(selected_player_->getCoordinates()))
00807 return INVALID_REQUEST;
00808
00809 CPlayer* p = rules_->match_->getField()->getPlayer(to);
00810 if (p == NULL || p->getStatus() != STA_STANDING
00811 || p->getTeamId() == selected_player_->getTeamId())
00812 return INVALID_REQUEST;
00813
00814 int dices = rules_->match_->getField()->getNbBlockDices(selected_player_->getCoordinates(), to);
00815 if (dices == 0) { ERR("target undefined or synchronisation error between field and players"); }
00816
00817 return blockDicesNumberPadding() + dices;
00818 }
00819
00820 inline int Api::blockDicesNumberPadding() const
00821 {
00822 return 4;
00823 }
00824
00825 inline int Api::throwDifficulty(const Coordinates& to) const
00826 {
00827 CHECK_TEAM;
00828 CHECK_PLAYER;
00829 CHECK_COORD(to.col, to.row);
00830
00831
00832 float distance = to.distance(rules_->match_->getBall()->getCoordinates());
00833 if (selected_player_ != rules_->match_->getBall()->getOwner()
00834 || distance == 0.f || distance >= 16.f)
00835 {
00836 return INVALID_REQUEST;
00837 }
00838 return 7 - std::min(5, std::max(1,
00839 selected_player_->getAg()
00840 + (distance < 4.f ? 1 :
00841 distance < 8.f ? 0 :
00842 distance < 12.f ? -1 :
00843 -2)
00844 - rules_->match_->getField()->getNbTackleZones(
00845 1 - selected_team_->getTeamId(),
00846 selected_player_->getCoordinates())
00847 + (selected_player_->hasSkill(SK_STRONGARM) && distance >= 4.f ? 1 : 0)
00848 - (selected_player_->hasSkill(SK_STUNTY) ? 1 : 0)));
00849 }
00850
00851 inline int Api::remainingTime() const
00852 {
00853 assert(rules_->getState() != GS_WAIT);
00854 int ta = rules_->match_->getTimer().getAllowedTime();
00855 int tr = rules_->match_->getTimer().getTimeRemaining();
00856 return (tr < 0 || tr > ta) ? 0 : tr;
00857 }
00858
00859 inline int Api::isTimerPaused() const
00860 {
00861 return rules_->match_->getTimer().isPaused() ? 1 : 0;
00862 }
00863
00864 inline const char* Api::gameStateString() const
00865 {
00866 return Match<CPlayer>::stringifyGameState(rules_->getState());
00867 }
00868
00869 inline int Api::canMakeRequest() const
00870 {
00871 return ((rules_->nb_requests_sent_ == 0) ? 1 : 0);
00872 }
00873
00874 inline int Api::mustMakeChoice() const
00875 {
00876 return ((rules_->nb_server_queries_ > 0) ? 1 : 0);
00877 }
00878
00879 inline const CTeam* Api::getTeam() const
00880 {
00881 return selected_team_;
00882 }
00883
00884 inline const CPlayer* Api::getPlayer() const
00885 {
00886 return selected_player_;
00887 }
00888
00889 inline const CPlayer* Api::getPlayer(int player_id)
00890 {
00891 if (selected_team_ == NULL)
00892 return NULL;
00893 return selected_team_->getPlayer(player_id);
00894 }
00895
00896 inline const CPlayer* Api::getPlayer(const Coordinates& coord)
00897 {
00898 return rules_->match_->getField()->getPlayer(coord);
00899 }
00900
00901 inline const CPlayer* Api::getActivePlayer() const
00902 {
00903 CTeam* t;
00904 if (rules_->match_->getActiveTeamId() == rules_->getCoachId())
00905 t = rules_->our_team_;
00906 else if (rules_->match_->getActiveTeamId() == ((rules_->getCoachId() + 1) % 2))
00907 t = rules_->other_team_;
00908 else
00909 return NULL;
00910 return t->getPlayer(t->getActivePlayerId());
00911 }
00912
00913 inline const Weather* Api::getWeather() const
00914 {
00915 assert(rules_->getState() != GS_WAIT && rules_->getState() != GS_INITGAME);
00916 return rules_->match_->getWeather();
00917 }