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