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


Sun Mar 13 2011 Doxygen 1.7.1