Api.hxx

00001 /*
00002 ** TowBowlTactics, a turn-based strategy football game.
00003 **
00004 ** Copyright (C) 2006-2010 The TBT Team.
00005 **
00006 ** This program is free software; you can redistribute it and/or
00007 ** modify it under the terms of the GNU General Public License
00008 ** as published by the Free Software Foundation; either version 2
00009 ** of the License, or (at your option) any later version.
00010 **
00011 ** The complete GNU General Public Licence Notice can be found as the
00012 ** `NOTICE' file in the root directory.
00013 **
00014 ** The TBT Team consists of people listed in the `AUTHORS' file.
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 ** Requests
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 // GS_BLOCK
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 ** Accessors, for the game
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   // FIXME: do a better implementation.
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   // FIXME: Factorize the code to common/ since SPlayer uses the same.
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 :   // quick pass
00841           distance < 8.f ? 0 :    // short pass
00842           distance < 12.f ? -1 :  // long pass
00843           -2)                     // bomb
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 }
Generated on Mon Apr 5 21:17:11 2010 for Stechec/TBT by  doxygen 1.6.3