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


Sun Mar 13 2011 Doxygen 1.7.1