00001 //---------------------------------------------------------------------------- 00002 /** @file SgBoardConst.h 00003 Constant data for a given board size. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef SG_BOARDCONST_H 00007 #define SG_BOARDCONST_H 00008 00009 #include <boost/shared_ptr.hpp> 00010 #include "SgArray.h" 00011 #include "SgNbIterator.h" 00012 #include "SgPoint.h" 00013 #include "SgPointArray.h" 00014 #include "SgPointIterator.h" 00015 #include "SgPointSet.h" 00016 00017 //---------------------------------------------------------------------------- 00018 00019 /** Constant data for a given board size for games with square boards. 00020 All boards created with the same board size share the same 00021 data to reduce memory consumption and increase cache hits. */ 00022 class SgBoardConst 00023 { 00024 public: 00025 SgBoardConst(SgGrid size); 00026 00027 /** Change the information for this object to another size. 00028 Does nothing if 'newSize' is the same. */ 00029 void ChangeSize(SgGrid newSize); 00030 00031 /** Get board size. */ 00032 SgGrid Size() const; 00033 00034 /** Distance from the nearest border point. 00035 Points on the edge of the board have distance 1; 00036 border (off-board) points have distance 0. */ 00037 SgGrid Line(SgPoint p) const; 00038 00039 /** The distance to the second-closest border point. 00040 Points on the edge of the board have distance 1; 00041 border (off-board) points have distance 0. */ 00042 SgGrid Pos(SgPoint p) const; 00043 00044 /** Offset for neighboring point away from edge of board. 00045 @todo: the following seems weird, remove? 00046 Can also be a diagonal neighbor if no direct up-neighbor exists. 00047 If no up-neighbor exists at all, returns offset of 0. */ 00048 int Up(SgPoint p) const; 00049 00050 /** Offset for neighbor to the left, when looking in Up() direction */ 00051 int Left(SgPoint p) const; 00052 00053 /** */ 00054 int Right(SgPoint p) const; 00055 00056 /** @todo */ 00057 int Side(SgPoint p, int i) const; 00058 00059 /** Set of points in corners of the board. 00060 On 12x12 boards and larger, this includes 5x5 area from corner 00061 except the 5,5 point itself (the classical opening moves and below). 00062 See SgBoardConst::BoardConstImpl::BoardConstImpl for details. 00063 On smaller boards, includes the 4x4 area except the 4,4 point itself. */ 00064 const SgPointSet& Corners() const; 00065 00066 /** Set of points on edge but not in corners of the board. 00067 On 12x12 boards and larger, this includes points on lines 1-4. 00068 On smaller boards, lines 1 to 3. */ 00069 const SgPointSet& Edges() const; 00070 00071 /** All points on board not in Corners() or Edges() */ 00072 const SgPointSet& Centers() const; 00073 00074 /** Points for standard side extensions on lines 2 to 4. */ 00075 const SgPointSet& SideExtensions() const; 00076 00077 /** Set of all points on given line. */ 00078 const SgPointSet& LineSet(SgGrid line) const; 00079 00080 /** Upper left corner of the board. 00081 Using FirstBoardPoint and LastBoardPoint the board points can be 00082 traversed with a for-loop. This avoids the border points before and 00083 after the board, but not the ones to the side of the board; 00084 one must still check for border fields within the loop. */ 00085 int FirstBoardPoint() const; 00086 00087 /** See FirstBoardPoint */ 00088 int LastBoardPoint() const; 00089 00090 /** List of on-board neighbor points terminated by SG_ENDPOINT. 00091 Points are sorted from low to high. */ 00092 const SgPoint* NeighborIterAddress(SgPoint p) const; 00093 00094 const SgPoint* BoardIterAddress() const; 00095 00096 const SgPoint* BoardIterEnd() const; 00097 00098 const SgPoint* LineIterAddress(SgGrid line) const; 00099 00100 const SgPoint* CornerIterAddress() const; 00101 00102 private: 00103 struct BoardConstImpl 00104 { 00105 BoardConstImpl(SgGrid size); 00106 00107 /** Size */ 00108 SgGrid m_size; 00109 00110 int m_firstBoardPoint; 00111 00112 int m_lastBoardPoint; 00113 00114 SgPointArray<SgGrid> m_gridToLine; 00115 00116 SgPointArray<SgGrid> m_gridToPos; 00117 00118 /** See SgBoardConst::Neighbors() */ 00119 SgPoint m_neighbors[SG_MAXPOINT][5]; 00120 00121 SgPointArray<int> m_up; 00122 00123 SgPointSet m_corners; 00124 00125 SgPointSet m_edges; 00126 00127 SgPointSet m_centers; 00128 00129 SgPointSet m_sideExtensions; 00130 00131 SgPoint m_cornerIter[4 + 1]; 00132 00133 SgPointSet m_line[(SG_MAX_SIZE / 2) + 1]; 00134 00135 SgPoint* m_lineIterAddress[(SG_MAX_SIZE / 2) + 1]; 00136 00137 SgPoint m_boardIter[SG_MAX_ONBOARD + 1]; 00138 00139 SgPoint* m_boardIterEnd; 00140 00141 SgPoint m_lineIter[SG_MAX_SIZE * SG_MAX_SIZE + (SG_MAX_SIZE / 2) + 1]; 00142 00143 int m_side[2][2 * (SG_NS + SG_WE) + 1]; 00144 }; 00145 00146 typedef SgArray<boost::shared_ptr<BoardConstImpl>,SG_MAX_SIZE + 1> 00147 BoardConstImplArray; 00148 00149 boost::shared_ptr<BoardConstImpl> m_const; 00150 00151 void Create(SgGrid size); 00152 00153 static BoardConstImplArray s_const; 00154 }; 00155 00156 inline SgGrid SgBoardConst::Size() const 00157 { 00158 return m_const->m_size; 00159 } 00160 00161 inline SgGrid SgBoardConst::Line(SgPoint p) const 00162 { 00163 return m_const->m_gridToLine[p]; 00164 } 00165 00166 inline const SgPoint* SgBoardConst::NeighborIterAddress(SgPoint p) const 00167 { 00168 return m_const->m_neighbors[p]; 00169 } 00170 00171 inline SgGrid SgBoardConst::Pos(SgPoint p) const 00172 { 00173 return m_const->m_gridToPos[p]; 00174 } 00175 00176 inline int SgBoardConst::Up(SgPoint p) const 00177 { 00178 return m_const->m_up[p]; 00179 } 00180 00181 inline int SgBoardConst::Left(SgPoint p) const 00182 { 00183 return m_const->m_side[0][m_const->m_up[p] + (SG_NS + SG_WE)]; 00184 } 00185 00186 inline int SgBoardConst::Right(SgPoint p) const 00187 { 00188 return m_const->m_side[1][m_const->m_up[p] + (SG_NS + SG_WE)]; 00189 } 00190 00191 inline int SgBoardConst::Side(SgPoint p, int i) const 00192 { 00193 return m_const->m_side[i][m_const->m_up[p] + (SG_NS + SG_WE)]; 00194 } 00195 00196 inline const SgPointSet& SgBoardConst::Corners() const 00197 { 00198 return m_const->m_corners; 00199 } 00200 00201 inline const SgPointSet& SgBoardConst::Edges() const 00202 { 00203 return m_const->m_edges; 00204 } 00205 00206 inline const SgPointSet& SgBoardConst::Centers() const 00207 { 00208 return m_const->m_centers; 00209 } 00210 00211 inline const SgPointSet& SgBoardConst::SideExtensions() const 00212 { 00213 return m_const->m_sideExtensions; 00214 } 00215 00216 inline const SgPointSet& SgBoardConst::LineSet(SgGrid line) const 00217 { 00218 return m_const->m_line[line - 1]; 00219 } 00220 00221 inline int SgBoardConst::FirstBoardPoint() const 00222 { 00223 return m_const->m_firstBoardPoint; 00224 } 00225 00226 inline int SgBoardConst::LastBoardPoint() const 00227 { 00228 return m_const->m_lastBoardPoint; 00229 } 00230 00231 inline const SgPoint* SgBoardConst::BoardIterAddress() const 00232 { 00233 return m_const->m_boardIter; 00234 } 00235 00236 inline const SgPoint* SgBoardConst::BoardIterEnd() const 00237 { 00238 return m_const->m_boardIterEnd; 00239 } 00240 00241 inline const SgPoint* SgBoardConst::LineIterAddress(SgGrid line) const 00242 { 00243 return m_const->m_lineIterAddress[line - 1]; 00244 } 00245 00246 inline const SgPoint* SgBoardConst::CornerIterAddress() const 00247 { 00248 return m_const->m_cornerIter; 00249 } 00250 00251 //---------------------------------------------------------------------------- 00252 00253 /** Iterate through all points on a specific line on the given board. 00254 e.g. all points on the third line. */ 00255 class SgLineIterator 00256 : public SgPointIterator 00257 { 00258 public: 00259 SgLineIterator(const SgBoardConst& boardConst, SgGrid line) 00260 : SgPointIterator(boardConst.LineIterAddress(line)) 00261 { } 00262 }; 00263 00264 //---------------------------------------------------------------------------- 00265 00266 /** Iterate through all four corner point of the given board. */ 00267 class SgCornerIterator 00268 : public SgPointIterator 00269 { 00270 public: 00271 SgCornerIterator(const SgBoardConst& boardConst) 00272 : SgPointIterator(boardConst.CornerIterAddress()) 00273 { } 00274 }; 00275 00276 //---------------------------------------------------------------------------- 00277 00278 /** Iterate through the two directions along the sides for the given point. 00279 Returns the offset to the left (clockwise) first, then to the right. */ 00280 class SgSideIterator 00281 { 00282 public: 00283 SgSideIterator(const SgBoardConst& boardConst, SgPoint p) 00284 : m_boardConst(boardConst), 00285 m_p(p), 00286 m_index(0) 00287 { 00288 SG_ASSERT(m_boardConst.Side(m_p, 0) != 0); 00289 } 00290 00291 /** Advance the state of the iteration to the next element. */ 00292 void operator++() 00293 { 00294 ++m_index; 00295 } 00296 00297 /** Return the value of the current element. */ 00298 int operator*() const 00299 { 00300 return m_boardConst.Side(m_p, m_index); 00301 } 00302 00303 /** Return true if iteration is valid, otherwise false. */ 00304 operator bool() const 00305 { 00306 return m_index <= 1; 00307 } 00308 00309 private: 00310 const SgBoardConst& m_boardConst; 00311 00312 SgPoint m_p; 00313 00314 int m_index; 00315 00316 /** Not implemented. */ 00317 SgSideIterator(const SgSideIterator&); 00318 00319 /** Not implemented. */ 00320 SgSideIterator& operator=(const SgSideIterator&); 00321 }; 00322 00323 //---------------------------------------------------------------------------- 00324 00325 /** Iterate over all on-board neighbor points. 00326 The points are iterated in sorted order (from low to high). */ 00327 class SgNbIterator 00328 : public SgPointIterator 00329 { 00330 public: 00331 SgNbIterator(const SgBoardConst& boardConst, SgPoint p); 00332 }; 00333 00334 inline SgNbIterator::SgNbIterator(const SgBoardConst& boardConst, SgPoint p) 00335 : SgPointIterator(boardConst.NeighborIterAddress(p)) 00336 { 00337 } 00338 00339 //---------------------------------------------------------------------------- 00340 00341 #endif // SG_BOARDCONST_H