00001
00002
00003
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
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
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
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
00100
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
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
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
00130 *m_boardIterEnd = SG_ENDPOINT;
00131
00132
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
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
00159
00160
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
00207 SgGrid oldSize = m_const->m_size;
00208 if (newSize != oldSize)
00209 Create(newSize);
00210 }
00211
00212
00213