Field.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 template <typename T>
00018 inline Field<T>::Field()
00019 {
00020   for (int i = 0; i < COLS * ROWS; i++)
00021     tab_[i] = NULL;
00022 }
00023 
00024 template <typename T>
00025 inline Field<T>::~Field()
00026 {
00027 }
00028 
00029 template <typename T>
00030 inline bool Field<T>::intoField(const Coordinates& coord) const
00031 {
00032   return coord.row >= 0 && coord.row < ROWS
00033     && coord.col >= 0 && coord.col < COLS;
00034 }
00035 
00036 template <typename T>
00037 inline Coordinates Field<T>::dirToCoord(enum eDirection d) const
00038 {
00039   switch(d)
00040   {
00041     case DIR_NORTHWEST: return Coordinates(-1, -1); break;
00042     case DIR_NORTH:     return Coordinates(-1,  0); break;
00043     case DIR_NORTHEAST: return Coordinates(-1, +1); break;
00044     case DIR_EAST:      return Coordinates( 0, +1); break;
00045     case DIR_SOUTHEAST: return Coordinates(+1, +1); break;
00046     case DIR_SOUTH:     return Coordinates(+1,  0); break;
00047     case DIR_SOUTHWEST: return Coordinates(+1, -1); break;
00048     case DIR_WEST:      return Coordinates( 0, -1); break;
00049     default:            return Coordinates( 0,  0); break;
00050   }
00051 }
00052 
00053 template <typename T>
00054 inline void Field<T>::setPlayer(const Coordinates& coord, T* p)
00055 {
00056   // Desynchronization between field and players for coordinates can be
00057   // _very_ critical.
00058   if (p != NULL && tab_[coord.row * COLS + coord.col] != NULL)
00059     WARN("Desynchronization bewteen field and players!");
00060       
00061   tab_[coord.row * COLS + coord.col] = p;
00062 }
00063 
00064 template <typename T>
00065 inline T* Field<T>::getPlayer(const Coordinates& coord) const
00066 {
00067     if (!intoField(coord))
00068         return NULL;
00069   return tab_[coord.row * COLS + coord.col];
00070 }
00071 
00072 template <typename T>
00073 inline int Field<T>::getNbPlayersInOppositeHalf(int team_id) const
00074 {
00075   Coordinates c;
00076   int nb_players = 0;
00077 
00078   // Check the other half of the field
00079   for (c.row = (1 - team_id) * (ROWS / 2);
00080       c.row <= (1 - team_id) * (ROWS / 2) + (ROWS / 2) - 1;
00081       c.row++)
00082     for (c.col = 0; c.col <= COLS - 1; c.col++)
00083       if (getPlayer(c) != NULL && getPlayer(c)->getTeamId() == team_id)
00084         nb_players++;
00085 
00086   return nb_players;
00087 }
00088 
00089 template <typename T>
00090 inline int Field<T>::getNbPlayersInLeftWideZone(int team_id) const
00091 {
00092   Coordinates c;
00093   int nb_players = 0;
00094 
00095   // Check the left wide zone
00096   for (c.row = team_id * ((ROWS / 2) - 1) + 1;
00097       c.row <= team_id * ((ROWS / 2) - 1) + ((ROWS / 2) - 1);
00098       c.row++)
00099     for (c.col = 0; c.col <= SIDE - 1; c.col++)
00100       if (getPlayer(c) != NULL && getPlayer(c)->getTeamId() == team_id)
00101         nb_players++;
00102   
00103   return nb_players;
00104 }
00105 
00106 template <typename T>
00107 inline int Field<T>::getNbPlayersInRightWideZone(int team_id) const
00108 {
00109   Coordinates c;
00110   int nb_players = 0;
00111 
00112   // Check the right wide zone
00113   for (c.row = team_id * ((ROWS / 2) - 1) + 1;
00114       c.row <= team_id * ((ROWS / 2) - 1) + ((ROWS / 2) - 1);
00115       c.row++)
00116     for (c.col = COLS - SIDE; c.col <= COLS - 1; c.col++)
00117       if (getPlayer(c) != NULL && getPlayer(c)->getTeamId() == team_id)
00118         nb_players++;
00119 
00120   return nb_players;
00121 }
00122 
00123 template <typename T>
00124 inline int Field<T>::getNbPlayersOnLineOfScrimmage(int team_id) const
00125 {
00126   Coordinates c;
00127   int nb_players = 0;
00128 
00129   // Check the LoS
00130   c.row = team_id + (ROWS / 2) - 1;
00131   for (c.col = SIDE; c.col <= (COLS - 1) - SIDE; c.col++)
00132     if (getPlayer(c) != NULL && getPlayer(c)->getTeamId() == team_id)
00133       nb_players++;
00134 
00135   return nb_players;
00136 }
00137 
00138 template <typename T>
00139 inline int Field<T>::getNbPlayersInEndZone(int team_id) const
00140 {
00141   Coordinates c;
00142   int nb_players = 0;
00143 
00144   // Check the end zone
00145   c.row = team_id * (ROWS - 1);
00146   for (c.col = 0; c.col <= COLS - 1; c.col++)
00147     if (getPlayer(c) != NULL && getPlayer(c)->getTeamId() == team_id)
00148       nb_players++;
00149 
00150   return nb_players;
00151 }
00152 
00153 template <typename T>
00154 inline int Field<T>::getNbPlayersInMiddle(int team_id) const
00155 {
00156   Coordinates c;
00157   int nb_players = 0;
00158 
00159   // Check the middle of the field
00160   for (c.row = team_id * (ROWS / 2) + 1;
00161       c.row <= (team_id + 1) * (ROWS / 2) - 2;
00162       c.row++)
00163     for (c.col = SIDE; c.col <= (COLS - 1) - SIDE; c.col++)
00164       if (getPlayer(c) != NULL && getPlayer(c)->getTeamId() == team_id)
00165         nb_players++;
00166 
00167   return nb_players;
00168 }
00169 
00170 template <typename T>
00171 inline int Field<T>::isPlacementValid(int team_id) const
00172 {
00173   int n, nb_players;
00174   
00175   nb_players = getNbPlayersInOppositeHalf(team_id);
00176   if (nb_players > 0)
00177     return false;
00178 
00179   n = getNbPlayersInLeftWideZone(team_id);
00180   if (n > 2)
00181     return false;
00182   nb_players += n;
00183 
00184   n = getNbPlayersInRightWideZone(team_id);
00185   if (n > 2)
00186     return false;
00187   nb_players += n;
00188 
00189   nb_players += getNbPlayersInEndZone(team_id);
00190   nb_players += getNbPlayersInMiddle(team_id);
00191 
00192   n = getNbPlayersOnLineOfScrimmage(team_id);
00193   nb_players += n;
00194 
00195   // The case where the team has less than 11 players is treated in Team
00196   return (nb_players < 12 && (n >= 3 || n == nb_players));
00197 }
00198 
00199 template <typename T>
00200 inline bool Field<T>::hasAdjacentEmptySquare(const Coordinates& coord) const
00201 {
00202   Coordinates next_square;
00203   enum eDirection dir;
00204   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00205     {
00206       next_square = coord + dirToCoord(dir);
00207       if (intoField(next_square)
00208           && getPlayer(next_square) == NULL)
00209         return true;
00210     }
00211   return false;
00212 }
00213 
00214 template <typename T>
00215 inline CoordList Field<T>::getAdjacentEmptySquares(const Coordinates& coord) const
00216 {
00217   CoordList squares;
00218   Coordinates next_square;
00219   enum eDirection dir;
00220   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00221     {
00222       next_square = coord + dirToCoord(dir);
00223       if (intoField(next_square)
00224           && getPlayer(next_square) == NULL)
00225         squares.push_back(next_square);
00226     }
00227   return squares;
00228 }
00229 
00230 template <typename T>
00231 inline bool Field<T>::hasAdjacentPlayer(const Coordinates& coord) const
00232 {
00233   enum eDirection dir;
00234   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00235     {
00236       if (getPlayer(coord + dirToCoord(dir)) != NULL)
00237         return true;
00238     }
00239   return false;
00240 }
00241 
00242 template <typename T>
00243 inline bool Field<T>::hasAdjacentPlayer(const Coordinates& coord, enum eStatus s, int team_id) const
00244 {
00245   T* player;
00246   enum eDirection dir;
00247   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00248     {
00249       player = getPlayer(coord + dirToCoord(dir));
00250       if (player != NULL
00251           && player->getStatus() == s
00252           && player->getTeamId() == team_id)
00253         return true;
00254     }
00255   return false;
00256 }
00257 
00258 template <typename T>
00259 inline std::vector<T*> Field<T>::getAdjacentPlayers(const Coordinates& coord) const
00260 {
00261   std::vector<T*> neighbours;
00262   T* player;
00263   enum eDirection dir;
00264   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00265     {
00266       player = getPlayer(coord + dirToCoord(dir));
00267       if (player != NULL)
00268         neighbours.push_back(player);
00269     }
00270   return neighbours;
00271 }
00272 
00273 template <typename T>
00274 inline std::vector<T*> Field<T>::getAdjacentPlayers(const Coordinates& coord, enum eStatus s, int team_id) const
00275 {
00276   std::vector<T*> neighbours;
00277   T* player;
00278   enum eDirection dir;
00279   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00280     {
00281       player = getPlayer(coord + dirToCoord(dir));
00282       if (player != NULL
00283           && player->getStatus() == s
00284           && player->getTeamId() == team_id)
00285         neighbours.push_back(player);
00286     }
00287   return neighbours;
00288 }
00289 
00290 template <typename T>
00291 inline int Field<T>::getNbTackleZones(int team_id, const Coordinates& coord) const
00292 {
00293   int res = 0;
00294   Coordinates c;
00295   std::vector<T*> tacklers = getAdjacentPlayers(coord, STA_STANDING, team_id);
00296   for (unsigned i = 0; i < tacklers.size(); i++)
00297     if (tacklers[i]->hasTackleZone())
00298       res++;
00299   return res;
00300 }
00301 
00302 template <typename T>
00303 inline int Field<T>::getTackleZonesMalus(int team_id, const Coordinates& coord) const
00304 {
00305   int res = 0;
00306   Coordinates c;
00307   std::vector<T*> tacklers = getAdjacentPlayers(coord, STA_STANDING, team_id);
00308   for (unsigned i = 0; i < tacklers.size(); i++)
00309     if (tacklers[i]->hasTackleZone() && !tacklers[i]->hasSkill(SK_TITCHY))
00310       res++;
00311   return res;
00312 }
00313 
00314 template <typename T>
00315 inline bool Field<T>::canAssist(const Coordinates& coord_assister, int team_id,
00316     enum eEffort effort, const Coordinates& coord_target) const
00317 {
00318   return (coord_assister.isNear(coord_target)
00319       && getPlayer(coord_assister)->getStatus() == STA_STANDING
00320       && getPlayer(coord_assister)->hasTackleZone()
00321       && ((effort == EFF_BLOCK
00322           && (getPlayer(coord_assister)->hasSkill(SK_GUARD)
00323             || (getNbTackleZones(team_id, coord_assister) ==
00324               getPlayer(coord_target)->hasTackleZone())))
00325         || (effort == EFF_FOUL
00326           && (getNbTackleZones(team_id, coord_assister) ==
00327             getPlayer(coord_target)->hasTackleZone()))));
00328 }
00329 
00330 template <typename T>
00331 inline int Field<T>::getNbAssister(const Coordinates& coord_assisted,
00332     int team_id, enum eEffort effort, const Coordinates& coord_target) const
00333 {
00334   int res = 0;
00335   Coordinates c;
00336 
00337   for (c.row = coord_target.row - 1; c.row <= coord_target.row + 1; c.row++)
00338     for (c.col = coord_target.col - 1; c.col <= coord_target.col + 1; c.col++)
00339       if (intoField(c)
00340           && getPlayer(c) != NULL
00341           && c != coord_assisted
00342           && getPlayer(c)->getTeamId() == team_id
00343           && canAssist(c, (team_id + 1) % 2, effort, coord_target))
00344         res++;
00345   return res;
00346 }
00347 template <typename T>
00348 inline int Field<T>::getNbBlockDices(const Coordinates& coord_attacker,
00349     const Coordinates& coord_target) const
00350 {
00351   T* attacker;
00352   T* target;
00353 
00354   attacker = getPlayer(coord_attacker);
00355   target = getPlayer(coord_target);
00356   if (attacker == NULL || target == NULL) {
00357     return 0;
00358   }
00359 
00360   int mod_st_atk = attacker->getSt()
00361     + ((attacker->hasSkill(SK_HORNS) && attacker->getAction() == ACT_BLITZ) ? 1 : 0)
00362     + getNbAssister(coord_attacker, attacker->getTeamId(),
00363         EFF_BLOCK, coord_target);
00364   int mod_st_df = target->getSt()
00365     + getNbAssister(coord_target, target->getTeamId(),
00366         EFF_BLOCK, coord_attacker);
00367 
00368   return (mod_st_atk < mod_st_df ? -1 : 1) *
00369     ((mod_st_atk > 2 * mod_st_df || mod_st_df > 2 * mod_st_atk) ? 3 :
00370      (mod_st_atk != mod_st_df ? 2 : 1 ));
00371 }
00372 
00373 template <typename T>
00374 inline int Field<T>::getFoulModifier(const Coordinates& coord_attacker,
00375     const Coordinates& coord_target) const
00376 {
00377   T* attacker;
00378   T* target;
00379 
00380   attacker = getPlayer(coord_attacker);
00381   target = getPlayer(coord_target);
00382   if (attacker == NULL || target == NULL) {
00383     return 0;
00384   }
00385 
00386   int atk_mod = getNbAssister(coord_attacker, attacker->getTeamId(),
00387         EFF_FOUL, coord_target);
00388   int def_mod = getNbAssister(coord_target, target->getTeamId(),
00389         EFF_FOUL, coord_attacker);
00390 
00391   return atk_mod - def_mod;
00392 }
00393 
Generated on Mon Apr 5 21:17:12 2010 for Stechec/TBT by  doxygen 1.6.3