00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "dic.h"
00022 #include "tile.h"
00023 #include "round.h"
00024 #include "bag.h"
00025 #include "rack.h"
00026 #include "results.h"
00027 #include "board.h"
00028
00029 #define oo 0
00030 #define __ 1
00031 #define T2 2
00032 #define T3 3
00033 #define W2 2
00034 #define W3 3
00035
00036
00037 const int Board::m_tileMultipliers[BOARD_REALDIM][BOARD_REALDIM] =
00038 {
00039 { oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo },
00040 { oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
00041 { oo,__,__,__,__,__,T3,__,__,__,T3,__,__,__,__,__,oo },
00042 { oo,__,__,__,__,__,__,T2,__,T2,__,__,__,__,__,__,oo },
00043 { oo,T2,__,__,__,__,__,__,T2,__,__,__,__,__,__,T2,oo },
00044 { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
00045 { oo,__,T3,__,__,__,T3,__,__,__,T3,__,__,__,T3,__,oo },
00046 { oo,__,__,T2,__,__,__,T2,__,T2,__,__,__,T2,__,__,oo },
00047 { oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
00048 { oo,__,__,T2,__,__,__,T2,__,T2,__,__,__,T2,__,__,oo },
00049 { oo,__,T3,__,__,__,T3,__,__,__,T3,__,__,__,T3,__,oo },
00050 { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
00051 { oo,T2,__,__,__,__,__,__,T2,__,__,__,__,__,__,T2,oo },
00052 { oo,__,__,__,__,__,__,T2,__,T2,__,__,__,__,__,__,oo },
00053 { oo,__,__,__,__,__,T3,__,__,__,T3,__,__,__,__,__,oo },
00054 { oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
00055 { oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo }
00056 };
00057
00058
00059 const int Board::m_wordMultipliers[BOARD_REALDIM][BOARD_REALDIM] =
00060 {
00061 { oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo },
00062 { oo,W3,__,__,__,__,__,__,W3,__,__,__,__,__,__,W3,oo },
00063 { oo,__,W2,__,__,__,__,__,__,__,__,__,__,__,W2,__,oo },
00064 { oo,__,__,W2,__,__,__,__,__,__,__,__,__,W2,__,__,oo },
00065 { oo,__,__,__,W2,__,__,__,__,__,__,__,W2,__,__,__,oo },
00066 { oo,__,__,__,__,W2,__,__,__,__,__,W2,__,__,__,__,oo },
00067 { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
00068 { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
00069 { oo,W3,__,__,__,__,__,__,W2,__,__,__,__,__,__,W3,oo },
00070 { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
00071 { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
00072 { oo,__,__,__,__,W2,__,__,__,__,__,W2,__,__,__,__,oo },
00073 { oo,__,__,__,W2,__,__,__,__,__,__,__,W2,__,__,__,oo },
00074 { oo,__,__,W2,__,__,__,__,__,__,__,__,__,W2,__,__,oo },
00075 { oo,__,W2,__,__,__,__,__,__,__,__,__,__,__,W2,__,oo },
00076 { oo,W3,__,__,__,__,__,__,W3,__,__,__,__,__,__,W3,oo },
00077 { oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo }
00078 };
00079
00080
00081 Board::Board():
00082 m_tilesRow(BOARD_REALDIM, Tile::dummy()),
00083 m_tilesCol(BOARD_REALDIM, Tile::dummy()),
00084 m_jokerRow(BOARD_REALDIM, false),
00085 m_jokerCol(BOARD_REALDIM, false),
00086 m_crossRow(BOARD_REALDIM, Cross()),
00087 m_crossCol(BOARD_REALDIM, Cross()),
00088 m_pointRow(BOARD_REALDIM, -1),
00089 m_pointCol(BOARD_REALDIM, -1),
00090 m_testsRow(BOARD_REALDIM, 0)
00091 {
00092
00093 for (int i = 0; i < BOARD_REALDIM; i++)
00094 {
00095 m_crossRow[0][i].clear();
00096 m_crossCol[0][i].clear();
00097 m_crossRow[i][0].clear();
00098 m_crossCol[i][0].clear();
00099 m_crossRow[BOARD_REALDIM - 1][i].clear();
00100 m_crossCol[BOARD_REALDIM - 1][i].clear();
00101 m_crossRow[i][BOARD_REALDIM - 1].clear();
00102 m_crossCol[i][BOARD_REALDIM - 1].clear();
00103 }
00104 }
00105
00106
00107 char Board::getChar(int iRow, int iCol) const
00108 {
00109 char letter = 0;
00110 Tile tile = getTile(iRow, iCol);
00111 if (!tile.isEmpty())
00112 {
00113 letter = tile.toChar();
00114 if (isJoker(iRow, iCol))
00115 letter = tolower(letter);
00116 }
00117 return letter;
00118 }
00119
00120 int Board::getCharAttr(int iRow, int iCol) const
00121 {
00122 int t = getTestChar(iRow, iCol);
00123 int j = isJoker(iRow, iCol);
00124 return (t << 1) | j;
00125 }
00126
00127
00128 Tile Board::getTile(int iRow, int iCol) const
00129 {
00130 return m_tilesRow[iRow][iCol];
00131 }
00132
00133
00134 bool Board::isJoker(int iRow, int iCol) const
00135 {
00136 return m_jokerRow[iRow][iCol];
00137 }
00138
00139
00140 bool Board::isVacant(int iRow, int iCol) const
00141 {
00142 if (iRow < 1 || iRow > BOARD_DIM ||
00143 iCol < 1 || iCol > BOARD_DIM)
00144 {
00145 return false;
00146 }
00147 return m_tilesRow[iRow][iCol].isEmpty();
00148 }
00149
00150
00151 void Board::addRound(const Dictionary &iDic, const Round &iRound)
00152 {
00153 Tile t;
00154 int row, col;
00155
00156 row = iRound.getCoord().getRow();
00157 col = iRound.getCoord().getCol();
00158 if (iRound.getCoord().getDir() == Coord::HORIZONTAL)
00159 {
00160 for (int i = 0; i < iRound.getWordLen(); i++)
00161 {
00162 if (m_tilesRow[row][col + i].isEmpty())
00163 {
00164 t = iRound.getTile(i);
00165 m_tilesRow[row][col + i] = t;
00166 m_jokerRow[row][col + i] = iRound.isJoker(i);
00167 m_tilesCol[col + i][row] = t;
00168 m_jokerCol[col + i][row] = iRound.isJoker(i);
00169 }
00170 }
00171 }
00172 else
00173 {
00174 for (int i = 0; i < iRound.getWordLen(); i++)
00175 {
00176 if (m_tilesRow[row + i][col].isEmpty())
00177 {
00178 t = iRound.getTile(i);
00179 m_tilesRow[row + i][col] = t;
00180 m_jokerRow[row + i][col] = iRound.isJoker(i);
00181 m_tilesCol[col][row + i] = t;
00182 m_jokerCol[col][row + i] = iRound.isJoker(i);
00183 }
00184 }
00185 }
00186 buildCross(iDic);
00187 #ifdef DEBUG
00188 checkDouble();
00189 #endif
00190 }
00191
00192
00193 void Board::removeRound(const Dictionary &iDic, const Round &iRound)
00194 {
00195 int row, col;
00196
00197 row = iRound.getCoord().getRow();
00198 col = iRound.getCoord().getCol();
00199 if (iRound.getCoord().getDir() == Coord::HORIZONTAL)
00200 {
00201 for (int i = 0; i < iRound.getWordLen(); i++)
00202 {
00203 if (iRound.isPlayedFromRack(i))
00204 {
00205 m_tilesRow[row][col + i] = Tile::dummy();
00206 m_jokerRow[row][col + i] = false;
00207 m_tilesCol[col + i][row] = Tile::dummy();
00208 m_jokerCol[col + i][row] = false;
00209 }
00210 }
00211 }
00212 else
00213 {
00214 for (int i = 0; i < iRound.getWordLen(); i++)
00215 {
00216 if (iRound.isPlayedFromRack(i))
00217 {
00218 m_tilesRow[row + i][col] = Tile::dummy();
00219 m_jokerRow[row + i][col] = false;
00220 m_tilesCol[col][row + i] = Tile::dummy();
00221 m_jokerCol[col][row + i] = false;
00222 }
00223 }
00224 }
00225 buildCross(iDic);
00226 #ifdef DEBUG
00227 checkDouble();
00228 #endif
00229 }
00230
00231
00232
00233
00234 int Board::checkRoundAux(Matrix<Tile> &iTilesMx,
00235 Matrix<Cross> &iCrossMx,
00236 Matrix<int> &iPointsMx,
00237 Matrix<bool> &iJokerMx,
00238 Round &iRound,
00239 bool firstturn)
00240 {
00241 Tile t;
00242 int row, col, i;
00243 int l, p, fromrack;
00244 int pts, ptscross, wordmul;
00245 bool isolated = true;
00246
00247 fromrack = 0;
00248 pts = 0;
00249 ptscross = 0;
00250 wordmul = 1;
00251 row = iRound.getCoord().getRow();
00252 col = iRound.getCoord().getCol();
00253
00254
00255 if (!iTilesMx[row][col - 1].isEmpty() ||
00256 !iTilesMx[row][col + iRound.getWordLen()].isEmpty())
00257 {
00258 return 1;
00259 }
00260
00261 for (i = 0; i < iRound.getWordLen(); i++)
00262 {
00263 t = iRound.getTile(i);
00264 if (!iTilesMx[row][col + i].isEmpty())
00265 {
00266
00267 if (iTilesMx[row][col + i] != t)
00268 return 2;
00269
00270 isolated = false;
00271 iRound.setFromBoard(i);
00272
00273 if (!iJokerMx[row][col + i])
00274 pts += t.getPoints();
00275 }
00276 else
00277 {
00278
00279 if (iCrossMx[row][col + i].check(t))
00280 {
00281
00282 if (!iCrossMx[row][col + i].isAny())
00283 isolated = false;
00284
00285 if (!iRound.isJoker(i))
00286 l = t.getPoints() * m_tileMultipliers[row][col + i];
00287 else
00288 l = 0;
00289 pts += l;
00290 wordmul *= m_wordMultipliers[row][col + i];
00291
00292 p = iPointsMx[row][col + i];
00293 if (p >= 0)
00294 {
00295 ptscross += (p + l) * m_wordMultipliers[row][col + i];
00296 }
00297 fromrack++;
00298 iRound.setFromRack(i);
00299 }
00300 else
00301 {
00302
00303 return 3;
00304 }
00305 }
00306 }
00307
00308
00309 if (fromrack == 0)
00310 return 4;
00311
00312
00313
00314 if (isolated && !firstturn)
00315 return 5;
00316
00317 if (firstturn && iRound.getCoord().getDir() == Coord::VERTICAL)
00318 return 6;
00319
00320 if (firstturn
00321 && (row != 8 || col > 8 || col + iRound.getWordLen() <= 8))
00322 {
00323 return 7;
00324 }
00325
00326
00327 pts = ptscross + pts * wordmul + 50 * (fromrack == 7);
00328 iRound.setPoints(pts);
00329 iRound.setBonus(fromrack == 7);
00330
00331 return 0;
00332 }
00333
00334
00335 int Board::checkRound(Round &iRound, bool firstturn)
00336 {
00337 if (iRound.getCoord().getDir() == Coord::HORIZONTAL)
00338 {
00339 return checkRoundAux(m_tilesRow, m_crossRow,
00340 m_pointRow, m_jokerRow,
00341 iRound, firstturn);
00342 }
00343 else
00344 {
00345
00346
00347 iRound.accessCoord().swap();
00348
00349 int res = checkRoundAux(m_tilesCol, m_crossCol,
00350 m_pointCol, m_jokerCol,
00351 iRound, firstturn);
00352
00353
00354 iRound.accessCoord().swap();
00355
00356 return res;
00357 }
00358 }
00359
00360
00361 void Board::testRound(const Round &iRound)
00362 {
00363 Tile t;
00364 int row, col;
00365
00366 row = iRound.getCoord().getRow();
00367 col = iRound.getCoord().getCol();
00368 if (iRound.getCoord().getDir() == Coord::HORIZONTAL)
00369 {
00370 for (int i = 0; i < iRound.getWordLen(); i++)
00371 {
00372 if (m_tilesRow[row][col + i].isEmpty())
00373 {
00374 t = iRound.getTile(i);
00375 m_tilesRow[row][col + i] = t;
00376 m_jokerRow[row][col + i] = iRound.isJoker(i);
00377 m_testsRow[row][col + i] = 1;
00378
00379 m_tilesCol[col + i][row] = t;
00380 m_jokerCol[col + i][row] = iRound.isJoker(i);
00381 }
00382 }
00383 }
00384 else
00385 {
00386 for (int i = 0; i < iRound.getWordLen(); i++)
00387 {
00388 if (m_tilesRow[row + i][col].isEmpty())
00389 {
00390 t = iRound.getTile(i);
00391 m_tilesRow[row + i][col] = t;
00392 m_jokerRow[row + i][col] = iRound.isJoker(i);
00393 m_testsRow[row + i][col] = 1;
00394
00395 m_tilesCol[col][row + i] = t;
00396 m_jokerCol[col][row + i] = iRound.isJoker(i);
00397 }
00398 }
00399 }
00400 }
00401
00402
00403 void Board::removeTestRound()
00404 {
00405 for (int row = 1; row <= BOARD_DIM; row++)
00406 {
00407 for (int col = 1; col <= BOARD_DIM; col++)
00408 {
00409 if (m_testsRow[row][col])
00410 {
00411 m_tilesRow[row][col] = Tile::dummy();
00412 m_testsRow[row][col] = 0;
00413 m_jokerRow[row][col] = false;
00414
00415 m_tilesCol[col][row] = Tile::dummy();
00416 m_jokerCol[col][row] = false;
00417 }
00418 }
00419 }
00420 }
00421
00422
00423 char Board::getTestChar(int iRow, int iCol) const
00424 {
00425 return m_testsRow[iRow][iCol];
00426 }
00427
00428
00429 int Board::getWordMultiplier(int iRow, int iCol) const
00430 {
00431 if (iRow < BOARD_MIN || iRow > BOARD_MAX ||
00432 iCol < BOARD_MIN || iCol > BOARD_MAX)
00433 return 0;
00434 return m_wordMultipliers[iRow][iCol];
00435 }
00436
00437
00438 int Board::getLetterMultiplier(int iRow, int iCol) const
00439 {
00440 if (iRow < BOARD_MIN || iRow > BOARD_MAX ||
00441 iCol < BOARD_MIN || iCol > BOARD_MAX)
00442 return 0;
00443 return m_tileMultipliers[iRow][iCol];
00444 }
00445
00446
00447 #ifdef DEBUG
00448 void Board::checkDouble()
00449 {
00450 for (int row = BOARD_MIN; row <= BOARD_MAX; row++)
00451 {
00452 for (int col = BOARD_MIN; col <= BOARD_MAX; col++)
00453 {
00454 if (m_tilesRow[row][col] != m_tilesCol[col][row])
00455 printf("tiles diff %d %d\n", row, col);
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 if (m_jokerRow[row][col] != m_jokerCol[col][row])
00470 printf("joker diff %d %d\n", row, col);
00471 }
00472 }
00473 }
00474 #endif
00475
00476
00477
00478
00479
00480
00481