Field.hxx

00001 /*
00002 ** TowBowlTactics, an adaptation of the tabletop game Blood Bowl.
00003 ** 
00004 ** Copyright (C) 2006, 2007 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 Position& pos) const
00031 {
00032   return pos.row >= 0 && pos.row < ROWS
00033     && pos.col >= 0 && pos.col < COLS;
00034 }
00035 
00036 template <typename T>
00037 inline Position Field<T>::dirToPos(enum eDirection d) const
00038 {
00039   switch(d)
00040   {
00041     case DIR_NORTHWEST: return Position(-1, -1); break;
00042     case DIR_NORTH:     return Position(-1,  0); break;
00043     case DIR_NORTHEAST: return Position(-1, +1); break;
00044     case DIR_EAST:      return Position( 0, +1); break;
00045     case DIR_SOUTHEAST: return Position(+1, +1); break;
00046     case DIR_SOUTH:     return Position(+1,  0); break;
00047     case DIR_SOUTHWEST: return Position(+1, -1); break;
00048     case DIR_WEST:      return Position( 0, -1); break;
00049     default:            return Position( 0,  0); break;
00050   }
00051 }
00052 
00053 template <typename T>
00054 inline void Field<T>::setPlayer(const Position& pos, T* p)
00055 {
00056   // Desynchronization between field and players for position can be
00057   // _very_ critical.
00058   if (p != NULL && tab_[pos.row * COLS + pos.col] != NULL)
00059     WARN("Desynchronization bewteen field and players!");
00060       
00061   tab_[pos.row * COLS + pos.col] = p;
00062 }
00063 
00064 template <typename T>
00065 inline T* Field<T>::getPlayer(const Position& pos) const
00066 {
00067     if (!intoField(pos))
00068         return NULL;
00069   return tab_[pos.row * COLS + pos.col];
00070 }
00071 
00072 template <typename T>
00073 inline int Field<T>::isPlacementValid(int team_id) const
00074 {
00075   Position p;
00076 
00077   // Check the other half of the field
00078   for (p.row = (1 - team_id) * (ROWS / 2); p.row <= (1 - team_id) * (ROWS / 2) + (ROWS / 2) - 1; p.row++)
00079     for (p.col = 0; p.col <= COLS - 1; p.col++)
00080       if (getPlayer(p) != NULL
00081       && getPlayer(p)->getTeamId() == team_id)
00082         return false;
00083 
00084   int nb_player = 0;
00085   int nb_player_wide = 0;
00086   // Check the left wide zone
00087   for (p.row = team_id * ((ROWS / 2) - 1) + 1; p.row <= team_id * ((ROWS / 2) - 1) + ((ROWS / 2) - 1); p.row++)
00088     for (p.col = 0; p.col <= SIDE - 1; p.col++)
00089       if (getPlayer(p) != NULL 
00090       && getPlayer(p)->getTeamId() == team_id)
00091     {
00092       nb_player_wide++;
00093       nb_player++;
00094     }
00095   if (nb_player_wide > 2)
00096     return false;
00097     
00098   nb_player_wide = 0;
00099   // Check the right wide zone
00100   for (p.row = team_id * ((ROWS / 2) - 1) + 1; p.row <= team_id * ((ROWS / 2) - 1) + ((ROWS / 2) - 1); p.row++)
00101     for (p.col = COLS - SIDE; p.col <= COLS - 1; p.col++)
00102       if (getPlayer(p) != NULL 
00103       && getPlayer(p)->getTeamId() == team_id)
00104     {
00105       nb_player_wide++;
00106       nb_player++;
00107     }
00108   if (nb_player_wide > 2)
00109     return false;
00110     
00111   int nb_player_LoS = 0;
00112   // Check the LoS
00113   p.row = team_id + (ROWS / 2) - 1;
00114   for (p.col = SIDE; p.col <= (COLS - 1) - SIDE; p.col++)
00115     if (getPlayer(p) != NULL 
00116     && getPlayer(p)->getTeamId() == team_id)
00117       {
00118     nb_player_LoS++;
00119     nb_player++;
00120       }
00121 
00122   // Check the end zone
00123   p.row = team_id * (ROWS - 1);
00124   for (p.col = 0; p.col <= COLS - 1; p.col++)
00125     if (getPlayer(p) != NULL 
00126     && getPlayer(p)->getTeamId() == team_id)
00127       {
00128     nb_player++;
00129       }
00130     
00131   // Check the middle of the field
00132   for (p.row = team_id * (ROWS / 2) + 1; p.row <= (team_id + 1) * (ROWS / 2) - 2; p.row++)
00133     for (p.col = SIDE; p.col <= (COLS - 1) - SIDE; p.col++)
00134       if (getPlayer(p) != NULL 
00135       && getPlayer(p)->getTeamId() == team_id)
00136     {
00137       nb_player++;
00138     }
00139     
00140   // The case where the team has less than 11 players is treated in Team
00141   return (nb_player < 12 && (nb_player_LoS >= 3 || nb_player_LoS == nb_player));
00142 }
00143 
00144 template <typename T>
00145 inline bool Field<T>::hasAdjacentEmptySquare(const Position& pos) const
00146 {
00147   Position next_square;
00148   enum eDirection dir;
00149   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00150     {
00151       next_square = pos + dirToPos(dir);
00152       if (intoField(next_square)
00153           && getPlayer(next_square) == NULL)
00154         return true;
00155     }
00156   return false;
00157 }
00158 
00159 template <typename T>
00160 inline PosList Field<T>::getAdjacentEmptySquares(const Position& pos) const
00161 {
00162   PosList squares;
00163   Position next_square;
00164   enum eDirection dir;
00165   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00166     {
00167       next_square = pos + dirToPos(dir);
00168       if (intoField(next_square)
00169           && getPlayer(next_square) == NULL)
00170         squares.push_back(next_square);
00171     }
00172   return squares;
00173 }
00174 
00175 template <typename T>
00176 inline bool Field<T>::hasAdjacentPlayer(const Position& pos) const
00177 {
00178   enum eDirection dir;
00179   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00180     {
00181       if (getPlayer(pos + dirToPos(dir)) != NULL)
00182         return true;
00183     }
00184   return false;
00185 }
00186 
00187 template <typename T>
00188 inline bool Field<T>::hasAdjacentPlayer(const Position& pos, enum eStatus s, int team_id) const
00189 {
00190   T* player;
00191   enum eDirection dir;
00192   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00193     {
00194       player = getPlayer(pos + dirToPos(dir));
00195       if (player != NULL
00196           && player->getStatus() == s
00197           && player->getTeamId() == team_id)
00198         return true;
00199     }
00200   return false;
00201 }
00202 
00203 template <typename T>
00204 inline std::vector<T*> Field<T>::getAdjacentPlayers(const Position& pos) const
00205 {
00206   std::vector<T*> neighbours;
00207   T* player;
00208   enum eDirection dir;
00209   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00210     {
00211       player = getPlayer(pos + dirToPos(dir));
00212       if (player != NULL)
00213         neighbours.push_back(player);
00214     }
00215   return neighbours;
00216 }
00217 
00218 template <typename T>
00219 inline std::vector<T*> Field<T>::getAdjacentPlayers(const Position& pos, enum eStatus s, int team_id) const
00220 {
00221   std::vector<T*> neighbours;
00222   T* player;
00223   enum eDirection dir;
00224   for (dir = DIR_LAST; dir > DIR_UNASSIGNED; dir = static_cast<enum eDirection>(dir - 1))
00225     {
00226       player = getPlayer(pos + dirToPos(dir));
00227       if (player != NULL
00228           && player->getStatus() == s
00229           && player->getTeamId() == team_id)
00230         neighbours.push_back(player);
00231     }
00232   return neighbours;
00233 }
00234 
00235 template <typename T>
00236 inline int Field<T>::getNbTackleZones(int team_id, const Position& pos) const
00237 {
00238   int res = 0;
00239   Position p;
00240 
00241   for (p.row = pos.row - 1; p.row <= pos.row + 1; p.row++)
00242     for (p.col = pos.col - 1; p.col <= pos.col + 1; p.col++)
00243       if (intoField(p)
00244           && getPlayer(p) != NULL
00245           && getPlayer(p)->getTeamId() == team_id
00246       && getPlayer(p)->getStatus() == STA_STANDING)
00247         res++;
00248   return res;
00249 }

Generated on Sat Jun 23 16:07:23 2007 for Stechec/TBT by  doxygen 1.4.7