00001 //---------------------------------------------------------------------------- 00002 /** @file HexPoint.hpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef HEXPOINT_HPP 00007 #define HEXPOINT_HPP 00008 00009 #include <map> 00010 #include <string> 00011 #include <vector> 00012 #include <utility> 00013 00014 #include "Benzene.hpp" 00015 #include "Bitset.hpp" 00016 #include "HexAssert.hpp" 00017 #include "HexColor.hpp" 00018 00019 _BEGIN_BENZENE_NAMESPACE_ 00020 00021 //---------------------------------------------------------------------------- 00022 00023 /** @page hexpoints HexPoints 00024 00025 There are three types of HexPoints: special, edges, and interior. 00026 Special points encode special moves that do not correspond to a 00027 physical location on a hex board. These are: INVALID_POINT, 00028 RESIGN, and SWAP_PIECES. Edge points (NORTH, SOUTH, EAST, WEST) 00029 denote the edges of the board. Internal points are the interior 00030 points of the board, the number of which is controlled by the 00031 constants MAX_WIDTH and MAX_HEIGHT. 00032 00033 HexPoints are laid out in memory as follows: 00034 00035 @verbatim 00036 00037 0 INVALID_POINT 00038 1 RESIGN 00039 2 SWAP_PIECES 00040 3 NORTH 00041 4 EAST 00042 5 SOUTH 00043 6 WEST 00044 7 1st interior point 00045 8 2nd interior point 00046 ... 00047 ... 00048 ... FIRST_INVALID 00049 @endverbatim 00050 00051 It is assumed that the special points (i.e. SWAP_PIECES and 00052 RESIGN) come immediately before the edge points (i.e. NORTH to 00053 WEST) which come immediately before the interior points. 00054 00055 The interior points are laid out as follows. The first MAX_WIDTH 00056 interior points get the name 'a1, b1, c1, ... , L1', where L is 00057 letter MAX_WIDTH-1 letters after 'a'. The next MAX_WIDTH points 00058 get a '2' suffix, then a '3' suffix, and so on, until MAX_HEIGHT 00059 is reached. 00060 00061 This encoding allows an 11x11 hex board to fit into 128 bits if 00062 MAX_WIDTH = 11 and MAX_HEIGHT = 11. 00063 */ 00064 00065 //---------------------------------------------------------------------------- 00066 00067 /** @name Maximum dimensions. 00068 00069 If you are going to change either of these constants, make sure to 00070 synchronize the printed names in HexPointData with the enumerated 00071 interior cell constants below. 00072 */ 00073 // @{ 00074 00075 #if defined(SUPPORT_19x19) 00076 00077 /** The maximum width of a valid ConstBoard. */ 00078 static const int MAX_WIDTH = 19; 00079 00080 /** The maximum height of a valid ConstBoard. */ 00081 static const int MAX_HEIGHT = 19; 00082 00083 #elif defined(SUPPORT_14x14) 00084 00085 /** The maximum width of a valid ConstBoard. */ 00086 static const int MAX_WIDTH = 14; 00087 00088 /** The maximum height of a valid ConstBoard. */ 00089 static const int MAX_HEIGHT = 14; 00090 00091 #elif defined(SUPPORT_13x13) 00092 00093 /** The maximum width of a valid ConstBoard. */ 00094 static const int MAX_WIDTH = 13; 00095 00096 /** The maximum height of a valid ConstBoard. */ 00097 static const int MAX_HEIGHT = 13; 00098 00099 #else 00100 00101 /** The maximum width of a valid ConstBoard. */ 00102 static const int MAX_WIDTH = 11; 00103 00104 /** The maximum height of a valid ConstBoard. */ 00105 static const int MAX_HEIGHT = 11; 00106 00107 #endif 00108 00109 // @} 00110 00111 //---------------------------------------------------------------------------- 00112 00113 #if defined(SUPPORT_19x19) 00114 00115 #include "HexPoints19x19.hpp" 00116 00117 #elif defined(SUPPORT_14x14) 00118 00119 #include "HexPoints14x14.hpp" 00120 00121 #elif defined(SUPPORT_13x13) 00122 00123 #include "HexPoints13x13.hpp" 00124 00125 #else 00126 00127 #include "HexPoints11x11.hpp" 00128 00129 #endif 00130 00131 /** The value of the first special HexPoint. */ 00132 static const HexPoint FIRST_SPECIAL = RESIGN; 00133 00134 /** The value of the first edge HexPoint. */ 00135 static const HexPoint FIRST_EDGE = NORTH; 00136 00137 /** The value of the first interior cell; this should always be A1. */ 00138 static const HexPoint FIRST_CELL = HEX_CELL_A1; 00139 00140 //--------------------------------------------------------------------------- 00141 00142 /** A map of points to points. */ 00143 typedef std::map<HexPoint, HexPoint> PointToPoint; 00144 00145 /** Pair of HexPoints. */ 00146 typedef std::pair<HexPoint, HexPoint> HexPointPair; 00147 00148 /** Set of HexPoints. */ 00149 typedef std::set<HexPoint> HexPointSet; 00150 00151 /** Map of HexPoints to bitsets. */ 00152 typedef std::map<HexPoint, bitset_t> PointToBitset; 00153 00154 /** A sequence of HexPoints. */ 00155 typedef std::vector<HexPoint> PointSequence; 00156 00157 //--------------------------------------------------------------------------- 00158 00159 /** 00160 Delta arrays. 00161 00162 On a hex board, we can travel only in the following six directions: 00163 EAST, NORTH_EAST, NORTH, WEST, SOUTH_WEST, SOUTH. 00164 00165 @verbatim 00166 | / 00167 |/ 00168 --- o --- 00169 /| 00170 / | 00171 @endverbatim 00172 */ 00173 enum HexDirection 00174 { 00175 DIR_EAST=0, 00176 DIR_NORTH_EAST, 00177 DIR_NORTH, 00178 DIR_WEST, 00179 DIR_SOUTH_WEST, 00180 DIR_SOUTH, 00181 NUM_DIRECTIONS 00182 }; 00183 00184 //---------------------------------------------------------------------------- 00185 00186 /** Utilities on HexPoints: converting to/from strings, testing for edges, 00187 converting to/from x/y coordinates, etc. */ 00188 namespace HexPointUtil 00189 { 00190 /** Converts a HexPoint to a string. */ 00191 std::string ToString(HexPoint p); 00192 00193 /** Converts a pair of HexPoints to a string. */ 00194 std::string ToString(const HexPointPair& p); 00195 00196 /** Returns a space separated output of points in lst. */ 00197 std::string ToString(const PointSequence& lst); 00198 00199 /** Returns a string representation of the bitset's set bits. */ 00200 std::string ToString(const bitset_t& b); 00201 00202 /** Returns the HexPoint with the given name; INVALID_POINT otherwise. */ 00203 HexPoint FromString(const std::string& name); 00204 00205 /** Reads a PointSequence from a string of space separated 00206 points. */ 00207 void FromString(const std::string& str, PointSequence& pts); 00208 00209 /** Returns true if this point is a swap move. */ 00210 bool isSwap(HexPoint c); 00211 00212 /** Returns true if this point is an edge point. */ 00213 bool isEdge(HexPoint c); 00214 00215 /** Returns true if this point is an interior cell. */ 00216 bool isInteriorCell(HexPoint c); 00217 00218 /** Returns the edge opposite the given edge. */ 00219 HexPoint oppositeEdge(HexPoint edge); 00220 00221 /** Returns the edge to the left of the given edge. */ 00222 HexPoint leftEdge(HexPoint edge); 00223 00224 /** Returns the edge to the right of the given edge. */ 00225 HexPoint rightEdge(HexPoint edge); 00226 00227 /** Returns a color's first edge. NORTH for VERTICAL_COLOR 00228 and EAST for !VERTICAL_COLOR. */ 00229 HexPoint colorEdge1(HexColor color); 00230 00231 /** Returns a color's second edge. SOUTH for VERTICAL_COLOR 00232 and WEST for !VERTICAL_COLOR. */ 00233 HexPoint colorEdge2(HexColor color); 00234 00235 /** Returns true if cell is one of color's edges. */ 00236 bool isColorEdge(HexPoint cell, HexColor color); 00237 00238 /** Converts cell into its x and y components, where 00239 @code 00240 x = (cell-FIRST_CELL) % MAX_WIDTH; 00241 y = (cell-FIRST_CELL) / MAX_WIDTH; 00242 @endcode 00243 00244 Does not handle cases where cell is an edge. 00245 ConstBoard has a method for that. 00246 */ 00247 void pointToCoords(HexPoint cell, int& x, int& y); 00248 00249 /** Returns the HexPoint corresponding to the given x and y coords. 00250 @code 00251 point = FIRST_CELL + (y*MAX_WIDTH) + x; 00252 @endcode 00253 */ 00254 HexPoint coordsToPoint(int x, int y); 00255 00256 /** Returns the change in the x-coordinate when travelling in the 00257 given direction. */ 00258 int DeltaX(int dir); 00259 00260 /** Returns the change in the y-coordinate when travelling in the 00261 given direction. */ 00262 int DeltaY(int dir); 00263 00264 } // namespace 00265 00266 //---------------------------------------------------------------------------- 00267 00268 inline bool HexPointUtil::isSwap(HexPoint c) 00269 { 00270 return (c==SWAP_PIECES); 00271 } 00272 00273 inline bool HexPointUtil::isEdge(HexPoint c) 00274 { 00275 return (c==NORTH || c==SOUTH || c==EAST || c==WEST); 00276 } 00277 00278 inline bool HexPointUtil::isInteriorCell(HexPoint c) 00279 { 00280 return (FIRST_CELL <= c && c < FIRST_INVALID); 00281 } 00282 00283 inline HexPoint HexPointUtil::oppositeEdge(HexPoint edge) 00284 { 00285 HexAssert(isEdge(edge)); 00286 if (edge == NORTH) return SOUTH; 00287 if (edge == SOUTH) return NORTH; 00288 if (edge == EAST) return WEST; 00289 HexAssert(edge == WEST); 00290 return EAST; 00291 } 00292 00293 inline HexPoint HexPointUtil::leftEdge(HexPoint edge) 00294 { 00295 HexAssert(isEdge(edge)); 00296 if (edge == NORTH) return EAST; 00297 if (edge == SOUTH) return WEST; 00298 if (edge == EAST) return SOUTH; 00299 HexAssert(edge == WEST); 00300 return NORTH; 00301 } 00302 00303 inline HexPoint HexPointUtil::rightEdge(HexPoint edge) 00304 { 00305 HexAssert(isEdge(edge)); 00306 if (edge == NORTH) return WEST; 00307 if (edge == SOUTH) return EAST; 00308 if (edge == EAST) return NORTH; 00309 HexAssert(edge == WEST); 00310 return SOUTH; 00311 } 00312 00313 inline HexPoint HexPointUtil::colorEdge1(HexColor color) 00314 { 00315 HexAssert(HexColorUtil::isBlackWhite(color)); 00316 return (color == VERTICAL_COLOR) ? NORTH : EAST; 00317 } 00318 00319 inline HexPoint HexPointUtil::colorEdge2(HexColor color) 00320 { 00321 HexAssert(HexColorUtil::isBlackWhite(color)); 00322 return (color == VERTICAL_COLOR) ? SOUTH : WEST; 00323 } 00324 00325 inline bool HexPointUtil::isColorEdge(HexPoint cell, HexColor color) 00326 { 00327 HexAssert(HexColorUtil::isBlackWhite(color)); 00328 return (cell == colorEdge1(color) || cell == colorEdge2(color)); 00329 } 00330 00331 inline void HexPointUtil::pointToCoords(HexPoint cell, int& x, int& y) 00332 { 00333 HexAssert(FIRST_CELL <= cell && cell < FIRST_INVALID); 00334 x = (cell-FIRST_CELL) % MAX_WIDTH; 00335 y = (cell-FIRST_CELL) / MAX_WIDTH; 00336 } 00337 00338 inline HexPoint HexPointUtil::coordsToPoint(int x, int y) 00339 { 00340 HexAssert(0 <= x && x < MAX_WIDTH); 00341 HexAssert(0 <= y && y < MAX_HEIGHT); 00342 return static_cast<HexPoint>(FIRST_CELL + (y*MAX_WIDTH) + x); 00343 } 00344 00345 inline int HexPointUtil::DeltaX(int dir) 00346 { 00347 HexAssert(DIR_EAST <= dir && dir < NUM_DIRECTIONS); 00348 static const int dx[] = {1, 1, 0, -1, -1, 0}; 00349 return dx[dir]; 00350 } 00351 00352 inline int HexPointUtil::DeltaY(int dir) 00353 { 00354 HexAssert(DIR_EAST <= dir && dir < NUM_DIRECTIONS); 00355 static const int dy[] = {0, -1, -1, 0, 1, 1}; 00356 return dy[dir]; 00357 } 00358 00359 //---------------------------------------------------------------------------- 00360 00361 /** Extends standard output operator to handle HexPoints. */ 00362 inline std::ostream& operator<<(std::ostream& os, HexPoint p) 00363 { 00364 return os << HexPointUtil::ToString(p); 00365 } 00366 00367 //---------------------------------------------------------------------------- 00368 00369 _END_BENZENE_NAMESPACE_ 00370 00371 #endif // HEXPOINT_HPP