Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgBoardConst.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgBoardConst.cpp
00003     See SgBoardConst.h
00004 */
00005 //----------------------------------------------------------------------------
00006 
00007 #include "SgSystem.h"
00008 #include "SgBoardConst.h"
00009 
00010 #include <algorithm>
00011 #include "SgInit.h"
00012 #include "SgStack.h"
00013 
00014 using namespace std;
00015 using SgPointUtil::Pt;
00016 
00017 //----------------------------------------------------------------------------
00018 
00019 SgBoardConst::BoardConstImpl::BoardConstImpl(SgGrid size)
00020     : m_size(size),
00021       m_firstBoardPoint(Pt(1, 1)),
00022       m_lastBoardPoint(Pt(size, size))
00023 {
00024     m_gridToLine.Fill(0);
00025     m_gridToPos.Fill(0);
00026     m_up.Fill(0);
00027     for (SgGrid line = 0; line <= SG_MAX_SIZE / 2; ++line)
00028         m_line[line].Clear();
00029 
00030     // Set up values for points on the board.
00031     m_boardIterEnd = m_boardIter;
00032     SgGrid halfSize = (m_size + 1) / 2;
00033     for (SgGrid row = 1; row <= m_size; ++row)
00034     {
00035         for (SgGrid col = 1; col <= m_size; ++col)
00036         {
00037             SgPoint p = Pt(col, row);
00038             SgGrid lineRow = row > halfSize ? m_size + 1 - row : row;
00039             SgGrid lineCol = col > halfSize ? m_size + 1 - col : col;
00040             SgGrid line = min(lineRow, lineCol);
00041             SgGrid pos = max(lineRow, lineCol);
00042             m_gridToLine[p] = line;
00043             m_gridToPos[p] = pos;
00044             m_line[line - 1].Include(p);
00045             const int MAX_EDGE = m_size > 11 ? 4 : 3;
00046             if (line <= MAX_EDGE)
00047             {
00048                 if (pos <= MAX_EDGE + 1)
00049                     m_corners.Include(p);
00050                 else
00051                     m_edges.Include(p);
00052             }
00053             else
00054                 m_centers.Include(p);
00055             int nuNb = 0;
00056             if (row > 1)
00057                 m_neighbors[p][nuNb++] = Pt(col, row - 1);
00058             if (col > 1)
00059                 m_neighbors[p][nuNb++] = Pt(col - 1, row);
00060             if (col < m_size)
00061                 m_neighbors[p][nuNb++] = Pt(col + 1, row);
00062             if (row < m_size)
00063                 m_neighbors[p][nuNb++] = Pt(col, row + 1);
00064             m_neighbors[p][nuNb] = SG_ENDPOINT;
00065             *(m_boardIterEnd++) = p;
00066         }
00067     }
00068 
00069     // Set up direction to point on line above.
00070     for (SgPoint p = 0; p < SG_MAXPOINT; ++p)
00071     {
00072         if (m_gridToLine[p] != 0)
00073         {
00074             SgGrid line = m_gridToLine[p];
00075             if (m_gridToLine[p - SG_NS] == line + 1)
00076                 m_up[p] = -SG_NS;
00077             if (m_gridToLine[p - SG_WE] == line + 1)
00078                 m_up[p] = -SG_WE;
00079             if (m_gridToLine[p + SG_WE] == line + 1)
00080                 m_up[p] = SG_WE;
00081             if (m_gridToLine[p + SG_NS] == line + 1)
00082                 m_up[p] = SG_NS;
00083 
00084             // If no line above vertically or horizontally, try diagonally.
00085             if (m_up[p] == 0)
00086             {
00087                 if (m_gridToLine[p - SG_NS - SG_WE] == line + 1)
00088                     m_up[p] = -SG_NS - SG_WE;
00089                 if (m_gridToLine[p - SG_NS + SG_WE] == line + 1)
00090                     m_up[p] = -SG_NS + SG_WE;
00091                 if (m_gridToLine[p + SG_NS - SG_WE] == line + 1)
00092                     m_up[p] = SG_NS - SG_WE;
00093                 if (m_gridToLine[p + SG_NS + SG_WE] == line + 1)
00094                     m_up[p] = SG_NS + SG_WE;
00095             }
00096         }
00097     }
00098 
00099     // Set up direction to the sides, based on Up. Always list clockwise
00100     // direction first.
00101     {
00102         for (int i = 0; i <= 2 * (SG_NS + SG_WE); ++i)
00103         {
00104             m_side[0][i] = 0;
00105             m_side[1][i] = 0;
00106         }
00107 
00108         // When Up is towards center, sides are orthogonal to Up.
00109         m_side[0][-SG_NS + (SG_NS + SG_WE)] = -SG_WE;
00110         m_side[1][-SG_NS + (SG_NS + SG_WE)] = +SG_WE;
00111         m_side[0][-SG_WE + (SG_NS + SG_WE)] = +SG_NS;
00112         m_side[1][-SG_WE + (SG_NS + SG_WE)] = -SG_NS;
00113         m_side[0][+SG_WE + (SG_NS + SG_WE)] = -SG_NS;
00114         m_side[1][+SG_WE + (SG_NS + SG_WE)] = +SG_NS;
00115         m_side[0][+SG_NS + (SG_NS + SG_WE)] = +SG_WE;
00116         m_side[1][+SG_NS + (SG_NS + SG_WE)] = -SG_WE;
00117 
00118         // When Up is diagonal, sides are along different sides of board.
00119         m_side[0][-SG_NS - SG_WE + (SG_NS + SG_WE)] = -SG_WE;
00120         m_side[1][-SG_NS - SG_WE + (SG_NS + SG_WE)] = -SG_NS;
00121         m_side[0][-SG_NS + SG_WE + (SG_NS + SG_WE)] = -SG_NS;
00122         m_side[1][-SG_NS + SG_WE + (SG_NS + SG_WE)] = +SG_WE;
00123         m_side[0][+SG_NS - SG_WE + (SG_NS + SG_WE)] = +SG_NS;
00124         m_side[1][+SG_NS - SG_WE + (SG_NS + SG_WE)] = -SG_WE;
00125         m_side[0][+SG_NS + SG_WE + (SG_NS + SG_WE)] = +SG_WE;
00126         m_side[1][+SG_NS + SG_WE + (SG_NS + SG_WE)] = +SG_NS;
00127     }
00128 
00129     // Terminate board iterator.
00130     *m_boardIterEnd = SG_ENDPOINT;
00131 
00132     // Set up line iterators.
00133     {
00134         int lineIndex = 0;
00135         for (SgGrid line = 1; line <= (SG_MAX_SIZE / 2) + 1; ++line)
00136         {
00137             m_lineIterAddress[line-1] = &m_lineIter[lineIndex];
00138             for (SgPoint p = m_firstBoardPoint; p <= m_lastBoardPoint; ++p)
00139             {
00140                 if (m_gridToLine[p] == line)
00141                     m_lineIter[lineIndex++] = p;
00142             }
00143             m_lineIter[lineIndex++] = SG_ENDPOINT;
00144             SG_ASSERT(lineIndex
00145                       <= SG_MAX_SIZE * SG_MAX_SIZE + (SG_MAX_SIZE / 2) + 1);
00146         }
00147         SG_ASSERT(lineIndex == m_size * m_size + (SG_MAX_SIZE / 2) + 1);
00148     }
00149 
00150     // Set up corner iterator.
00151     m_cornerIter[0] = Pt(1, 1);
00152     m_cornerIter[1] = Pt(m_size, 1);
00153     m_cornerIter[2] = Pt(1, m_size);
00154     m_cornerIter[3] = Pt(m_size, m_size);
00155     m_cornerIter[4] = SG_ENDPOINT;
00156 
00157     m_sideExtensions = m_line[2 - 1] | m_line[3 - 1] | m_line[4 - 1];
00158     // LineSet(line)  == m_line[line-1], see .h
00159     // exclude diagonals, so that different sides from corner are in different
00160     // sets.
00161     m_sideExtensions.Exclude(Pt(2, 2));
00162     m_sideExtensions.Exclude(Pt(2, m_size + 1 - 2));
00163     m_sideExtensions.Exclude(Pt(m_size + 1 - 2, 2));
00164     m_sideExtensions.Exclude(Pt(m_size + 1 - 2, m_size + 1 - 2));
00165     if (m_size > 2)
00166     {
00167         m_sideExtensions.Exclude(Pt(3, 3));
00168         m_sideExtensions.Exclude(Pt(3, m_size + 1 - 3));
00169         m_sideExtensions.Exclude(Pt(m_size + 1 - 3, 3));
00170         m_sideExtensions.Exclude(Pt(m_size + 1 - 3, m_size + 1 - 3));
00171         if (m_size > 3)
00172         {
00173             m_sideExtensions.Exclude(Pt(4, 4));
00174             m_sideExtensions.Exclude(Pt(4, m_size + 1 - 4));
00175             m_sideExtensions.Exclude(Pt(m_size + 1 - 4, 4));
00176             m_sideExtensions.Exclude(Pt(m_size + 1 - 4, m_size + 1 - 4));
00177         }
00178     }
00179 }
00180 
00181 //----------------------------------------------------------------------------
00182 
00183 SgBoardConst::BoardConstImplArray SgBoardConst::s_const;
00184 
00185 void SgBoardConst::Create(SgGrid size)
00186 {
00187     SG_ASSERT_GRIDRANGE(size);
00188     if (! s_const[size])
00189         s_const[size] =
00190             boost::shared_ptr<BoardConstImpl>(new BoardConstImpl(size));
00191     m_const = s_const[size];
00192     SG_ASSERT(m_const);
00193 }
00194 
00195 SgBoardConst::SgBoardConst(SgGrid size)
00196 {
00197     SG_ASSERT_GRIDRANGE(size);
00198     SgInitCheck();
00199     Create(size);
00200 }
00201 
00202 void SgBoardConst::ChangeSize(SgGrid newSize)
00203 {
00204     SG_ASSERT_GRIDRANGE(newSize);
00205     SG_ASSERT(m_const);
00206     // Don't do anything if called with same size.
00207     SgGrid oldSize = m_const->m_size;
00208     if (newSize != oldSize)
00209         Create(newSize);
00210 }
00211 
00212 //----------------------------------------------------------------------------
00213 


17 Jun 2010 Doxygen 1.4.7