Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgPoint.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgPoint.h
00003     Definitions of points on the board.
00004 
00005     Points are defined in a way that they can be used as indices in an array,
00006     for a one-dimensional representation of a two-dimensional board with
00007     border (off-board) points between rows and columns.
00008     They are also compatible with SgMove (i.e. they use no negative integers,
00009     there is no overlap with the negative values for special moves
00010     in SgMove), so they can be used as move integers for games where a move
00011     can be described by a single point on the board.
00012     @see sgboardrepresentation
00013 */
00014 //----------------------------------------------------------------------------
00015 /** @page sgboardrepresentation Board Representation
00016 
00017     The board is represented as a one-dimensional array.
00018     Neighbors of a point can be computed with offsets <tt>WE</tt> and
00019     <tt>NS</tt>, so that the four neighbors of point <tt>p</tt> are:
00020     <pre>
00021                p + SG_NS
00022     p - SG_WE      p      p + SG_WE
00023                p - SG_NS
00024     </pre>
00025     The board is surrounded by one line of border points (if size is
00026     SG_MAX_SIZE) in all directions; also diagonally out from the corners.
00027 
00028     @section sgcoordinates Coordinates
00029 
00030     SgPointUtil::Pt, SgPointUtil::Row, and SgPointUtil::Col can be used to
00031     convert between points and coordinates. The coordinates start with 1 and
00032     the conversion is independent of the board size. <tt>Pt(1, 1)</tt>, which
00033     corresponds to A1, is the lower left corner of the board.
00034 
00035     @section sgpointnumbers Point numbers
00036 
00037     The following point numbers are valid, if the code was compiled with
00038     <code>SG_MAX_SIZE = 19</code> (which is used in the default version of
00039     SgPoint.h).
00040 
00041 <pre>
00042 19|381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
00043 18|361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
00044 17|341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
00045 16|321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
00046 15|301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
00047 14|281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
00048 13|261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
00049 12|241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
00050 11|221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
00051 10|201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
00052  9|181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
00053  8|161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
00054  7|141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
00055  6|121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
00056  5|101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
00057  4| 81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99
00058  3| 61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79
00059  2| 41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59
00060  1| 21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39
00061    [A] [B] [C] [D] [E] [F] [G] [H] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T]
00062 </pre>
00063 */
00064 //----------------------------------------------------------------------------
00065 
00066 #ifndef SG_POINT_H
00067 #define SG_POINT_H
00068 
00069 #include <climits>
00070 #include <cstdlib>
00071 #include <iosfwd>
00072 #include <string>
00073 #include "SgArray.h"
00074 #include "SgMove.h"
00075 #include "SgUtil.h"
00076 
00077 //----------------------------------------------------------------------------
00078 
00079 /** Minimum board size. */
00080 const int SG_MIN_SIZE = 2;
00081 
00082 /** Maximum board size. */
00083 const int SG_MAX_SIZE = 19;
00084 
00085 /** Point or SG_PASS. */
00086 typedef int SgPoint;
00087 
00088 /** Marker used for marking the end of points lists stored in arrays. */
00089 const SgPoint SG_ENDPOINT = 0;
00090 
00091 /** For symmetry, and for use in loops etc. */
00092 const int SG_MINPOINT = 0;
00093 
00094 /** Board plus borders. */
00095 const int SG_MAXPOINT = SG_MAX_SIZE * SG_MAX_SIZE + 3 * (SG_MAX_SIZE + 1);
00096 
00097 /** Maximum number of points on board. */
00098 const int SG_MAX_ONBOARD = SG_MAX_SIZE * SG_MAX_SIZE;
00099 
00100 /** The maximum number of moves.
00101     Limit using the largest possible board size and pass move.
00102 */
00103 const int SG_MAX_MOVES = SG_MAX_ONBOARD + 1;
00104 
00105 /** West-East  : offset of horizontal neighbors */
00106 const int SG_WE = 1;
00107 
00108 /** North-South: offset of vertical neighbors. */
00109 const int SG_NS = SG_MAX_SIZE + 1;
00110 
00111 /** Special parameter of type Point */
00112 const SgPoint SG_NULLPOINT = SG_NULLMOVE;
00113 
00114 /* Pass move.
00115    For games in which moves can be described by a SgPoint and pass is a
00116    legal move, such that legal moves can be stored in an array indexed by
00117    the move.
00118    @note SG_PASS should not be used in games that cannot use SgPoint to
00119    describe a move or in which pass is not legal, because of the potential
00120    conflict with the integer range for describing moves in those games.
00121 */
00122 const SgMove SG_PASS = SG_MAXPOINT + 1;
00123 
00124 /** Test if move is not a point.
00125     Returns true for special moves with negative values as defined in SgMove.h
00126     (e.g. SG_NULLMOVE) and for SG_PASS.
00127 */
00128 inline bool SgIsSpecialMove(SgMove m)
00129 {
00130     return m < 0 || m == SG_PASS;
00131 }
00132 
00133 /** Coordinate in range 0 to SG_MAX_SIZE. */
00134 typedef int SgGrid;
00135 
00136 #define SG_ASSERT_GRIDRANGE(c) SG_ASSERTRANGE(c, 1, SG_MAX_SIZE)
00137 
00138 #define SG_ASSERT_BOARDRANGE(p) \
00139     SG_ASSERTRANGE(p, SgPointUtil::Pt(1, 1), \
00140                    SgPointUtil::Pt(SG_MAX_SIZE, SG_MAX_SIZE))
00141 
00142 //----------------------------------------------------------------------------
00143 
00144 /** Write point.
00145     Wrapper class to allow overloading the output stream operator,
00146     because SgPoint is a typedef int.
00147 */
00148 struct SgWritePoint
00149 {
00150     SgPoint m_p;
00151 
00152     explicit SgWritePoint(SgPoint p);
00153 };
00154 
00155 /** @relatesalso SgWritePoint */
00156 std::ostream& operator<<(std::ostream& out, const SgWritePoint& writePoint);
00157 
00158 inline SgWritePoint::SgWritePoint(SgPoint p)
00159     : m_p(p)
00160 {
00161 }
00162 
00163 //----------------------------------------------------------------------------
00164 
00165 /** Read point.
00166     For overloading input stream operator for SgPoint (which is an integer).
00167     Usage:
00168     @code
00169     istream& in;
00170     SgPoint point;
00171     in >> SgReadPoint(point);
00172     if (! in)
00173        SgDebug() << "Invalid point\n";
00174     @endcode
00175 */
00176 class SgReadPoint
00177 {
00178 public:
00179     SgReadPoint(SgPoint& point);
00180 
00181     void Read(std::istream& in) const;
00182 
00183 private:
00184     SgPoint& m_point;
00185 };
00186 
00187 inline SgReadPoint::SgReadPoint(SgPoint& point)
00188     : m_point(point)
00189 {
00190 }
00191 
00192 /** @relatesalso SgReadPoint */
00193 inline std::istream& operator>>(std::istream& in,
00194                                 const SgReadPoint& readPoint)
00195 {
00196     readPoint.Read(in);
00197     return in;
00198 }
00199 
00200 //----------------------------------------------------------------------------
00201 
00202 namespace SgPointUtil {
00203 
00204 inline char Letter(int coord)
00205 {
00206     return 'A' + static_cast<char>(coord - (coord >= 9 ? 0 : 1));
00207 }
00208 
00209 std::string PointToString(SgPoint p);
00210 
00211 SgPoint Pt(int col, int row);
00212 
00213 /** Lookup table internally used by SgPointUtil::Row(). */
00214 class PointToRow
00215 {
00216 public:
00217     PointToRow()
00218     {
00219         m_row.Fill(-1);
00220         for (SgGrid row = 1; row <= SG_MAX_SIZE; ++row)
00221             for (SgGrid col = 1; col <= SG_MAX_SIZE; ++col)
00222                 m_row[Pt(col, row)] = row;
00223     }
00224 
00225     SgGrid Row(SgPoint p) const
00226     {
00227         SG_ASSERT_BOARDRANGE(p);
00228         SG_ASSERT(m_row[p] >= 0);
00229         return m_row[p];
00230     }
00231 
00232 private:
00233     SgArray<SgGrid,SG_MAXPOINT> m_row;
00234 };
00235 
00236 /** Lookup table internally used by SgPointUtil::Col(). */
00237 class PointToCol
00238 {
00239 public:
00240     PointToCol()
00241     {
00242         m_col.Fill(-1);
00243         for (SgGrid row = 1; row <= SG_MAX_SIZE; ++row)
00244             for (SgGrid col = 1; col <= SG_MAX_SIZE; ++col)
00245                 m_col[Pt(col, row)] = col;
00246     }
00247 
00248     SgGrid Col(SgPoint p) const
00249     {
00250         SG_ASSERT_BOARDRANGE(p);
00251         SG_ASSERT(m_col[p] >= 0);
00252         return m_col[p];
00253     }
00254 
00255 private:
00256     SgArray<SgGrid,SG_MAXPOINT> m_col;
00257 };
00258 
00259 /** Return column of point.
00260     The lower left corner of the coordinate grid is (1, 1).
00261 */
00262 inline SgGrid Col(SgPoint p)
00263 {
00264     static PointToCol pointToCol;
00265     return pointToCol.Col(p);
00266 }
00267 
00268 /** Return row of point.
00269     The lower left corner of the coordinate grid is (1, 1).
00270 */
00271 inline SgGrid Row(SgPoint p)
00272 {
00273     static PointToRow pointToRow;
00274     return pointToRow.Row(p);
00275 }
00276 
00277 /** Converts from (col, row) to a one-dimensional point.
00278     Only for on board points; will trigger assertion for off-board points.
00279 */
00280 inline SgPoint Pt(int col, int row)
00281 {
00282     SG_ASSERT_GRIDRANGE(col);
00283     SG_ASSERT_GRIDRANGE(row);
00284     return SG_NS * row + col;
00285 }
00286 
00287 inline bool InBoardRange(SgPoint p)
00288 {
00289     return SgUtil::InRange(p, Pt(1, 1), Pt(SG_MAX_SIZE, SG_MAX_SIZE));
00290 }
00291 
00292 /** True if the two points are adjacent to each other. */
00293 inline bool AreAdjacent(SgPoint p1, SgPoint p2)
00294 {
00295     int d = p2 - p1;
00296     return (d == SG_NS || d == SG_WE || d == -SG_NS || d == -SG_WE);
00297 }
00298 
00299 /** True if the two points are diagonally adjacent to each other. */
00300 inline bool AreDiagonal(SgPoint p1, SgPoint p2)
00301 {
00302     return (p2 == p1 - SG_NS - SG_WE || p2 == p1 - SG_NS + SG_WE
00303             || p2 == p1 + SG_NS - SG_WE || p2 == p1 + SG_NS + SG_WE);
00304 }
00305 
00306 /** Manhattan distance between two points on the board */
00307 inline int Distance(SgPoint p1, SgPoint p2)
00308 {
00309     return (std::abs(SgPointUtil::Row(p1) - SgPointUtil::Row(p2))
00310             + std::abs(SgPointUtil::Col(p1) - SgPointUtil::Col(p2)));
00311 }
00312 
00313 /** p2 is in 3x3 area around p1. */
00314 inline bool In8Neighborhood(SgPoint p1, SgPoint p2)
00315 {
00316     int d = p2 - p1;
00317     return (d == 0 || d == SG_NS || d == SG_WE || d == -SG_NS || d == -SG_WE
00318             || d == SG_NS - SG_WE || d == SG_NS + SG_WE
00319             || d == -SG_NS - SG_WE || d == -SG_NS + SG_WE);
00320 }
00321 
00322 /** Rotate/mirror point.
00323     Rotates and/or mirrors a point on a given board according to a given
00324     rotation mode.
00325     <table>
00326     <tr><th>Mode</th><th>col</th><th>row</th></tr>
00327     <tr><td>0</td><td>col</td><td>row</td></tr>
00328     <tr><td>1</td><td>size - col + 1</td><td>row</td></tr>
00329     <tr><td>2</td><td>col</td><td>size - row + 1</td></tr>
00330     <tr><td>3</td><td>row</td><td>col</td></tr>
00331     <tr><td>4</td><td>size - row + 1</td><td>col</td></tr>
00332     <tr><td>5</td><td>row</td><td>size - col + 1</td></tr>
00333     <tr><td>6</td><td>size - col + 1</td><td>size - row + 1</td></tr>
00334     <tr><td>7</td><td>size - row + 1</td><td>size - col + 1</td></tr>
00335     </table>
00336     @param rotation The rotation mode in [0..7]
00337     @param p The point to be rotated (SG_PASS is allowed and returned
00338     unmodified)
00339     @param size The board size
00340     @return The rotated mirrored point
00341 */
00342 SgPoint Rotate(int rotation, SgPoint p, int size);
00343 
00344 /** Return the inverse rotation as used in SgPointUtil::Rotate.
00345     @param rotation The rotation mode in [0..7]
00346     @return The inverse rotation mode
00347 */
00348 int InvRotation(int rotation);
00349 
00350 } // namespace SgPointUtil
00351 
00352 //----------------------------------------------------------------------------
00353 
00354 #endif // SG_POINT_H


17 Jun 2010 Doxygen 1.4.7