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 "rack.h"
00024 #include "round.h"
00025 #include "results.h"
00026 #include "board.h"
00027
00028 #include "debug.h"
00029
00030
00031
00032
00033
00034 static void BoardSearchEvalMove(const Board &iBoard,
00035 Matrix<Tile> &iTilesMx,
00036 Matrix<int> &iPointsMx,
00037 Matrix<bool> &iJokerMx,
00038 Results &iResults, Round &iWord)
00039 {
00040 int i, pts, ptscross;
00041 int l, t, fromrack;
00042 int len, row, col, wordmul;
00043
00044 fromrack = 0;
00045 pts = 0;
00046 ptscross = 0;
00047 wordmul = 1;
00048
00049 len = iWord.getWordLen();
00050
00051 row = iWord.getCoord().getRow();
00052 col = iWord.getCoord().getCol();
00053
00054 for (i = 0; i < len; i++)
00055 {
00056 if (!iTilesMx[row][col+i].isEmpty())
00057 {
00058 if (!iJokerMx[row][col+i])
00059 pts += iWord.getTile(i).getPoints();
00060 }
00061 else
00062 {
00063 if (!iWord.isJoker(i))
00064 l = iWord.getTile(i).getPoints() *
00065 iBoard.getLetterMultiplier(row, col + i);
00066 else
00067 l = 0;
00068 pts += l;
00069 wordmul *= iBoard.getWordMultiplier(row, col + i);
00070
00071 t = iPointsMx[row][col+i];
00072 if (t >= 0)
00073 ptscross += (t + l) * iBoard.getWordMultiplier(row, col + i);
00074 fromrack++;
00075 }
00076 }
00077 pts = ptscross + pts * wordmul + 50 * (fromrack == 7);
00078 iWord.setBonus(fromrack == 7);
00079 iWord.setPoints(pts);
00080
00081
00082 if (iWord.getCoord().getDir() == Coord::VERTICAL)
00083 {
00084
00085 iWord.accessCoord().swap();
00086 }
00087 iResults.add(iWord);
00088 if (iWord.getCoord().getDir() == Coord::VERTICAL)
00089 {
00090
00091 iWord.accessCoord().swap();
00092 }
00093 }
00094
00095
00096 static void ExtendRight(const Board &iBoard,
00097 const Dictionary &iDic,
00098 Matrix<Tile> &iTilesMx,
00099 Matrix<Cross> &iCrossMx,
00100 Matrix<int> &iPointsMx,
00101 Matrix<bool> &iJokerMx,
00102 Rack &iRack, Round &ioPartialWord,
00103 Results &iResults, unsigned int iNode,
00104 int iRow, int iCol, int iAnchor)
00105 {
00106 Tile l;
00107 unsigned int succ;
00108
00109 if (iTilesMx[iRow][iCol].isEmpty())
00110 {
00111 if (Dic_word(iDic, iNode) && iCol > iAnchor)
00112 BoardSearchEvalMove(iBoard, iTilesMx, iPointsMx, iJokerMx,
00113 iResults, ioPartialWord);
00114
00115 for (succ = Dic_succ(iDic, iNode); succ; succ = Dic_next(iDic, succ))
00116 {
00117 l = Tile(Dic_chr(iDic, succ));
00118 if (iCrossMx[iRow][iCol].check(l))
00119 {
00120 if (iRack.in(l))
00121 {
00122 iRack.remove(l);
00123 ioPartialWord.addRightFromRack(l, 0);
00124 ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
00125 iJokerMx, iRack, ioPartialWord, iResults,
00126 succ, iRow, iCol + 1, iAnchor);
00127 ioPartialWord.removeRightToRack(l, 0);
00128 iRack.add(l);
00129 }
00130 if (iRack.in(Tile::Joker()))
00131 {
00132 iRack.remove(Tile::Joker());
00133 ioPartialWord.addRightFromRack(l, 1);
00134 ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
00135 iJokerMx, iRack, ioPartialWord, iResults,
00136 succ, iRow, iCol + 1, iAnchor);
00137 ioPartialWord.removeRightToRack(l, 1);
00138 iRack.add(Tile::Joker());
00139 }
00140 }
00141 }
00142 }
00143 else
00144 {
00145 l = iTilesMx[iRow][iCol];
00146 for (succ = Dic_succ(iDic, iNode); succ ; succ = Dic_next(iDic, succ))
00147 {
00148 if (Tile(Dic_chr(iDic, succ)) == l)
00149 {
00150 ioPartialWord.addRightFromBoard(l);
00151 ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
00152 iJokerMx, iRack, ioPartialWord,
00153 iResults, succ, iRow, iCol + 1, iAnchor);
00154 ioPartialWord.removeRightToBoard(l);
00155 }
00156 }
00157 }
00158 }
00159
00160
00161 static void LeftPart(const Board &iBoard,
00162 const Dictionary &iDic,
00163 Matrix<Tile> &iTilesMx,
00164 Matrix<Cross> &iCrossMx,
00165 Matrix<int> &iPointsMx,
00166 Matrix<bool> &iJokerMx,
00167 Rack &iRack, Round &ioPartialWord,
00168 Results &iResults, int n, int iRow,
00169 int iAnchor, int iLimit)
00170 {
00171 Tile l;
00172 int succ;
00173
00174 ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx, iJokerMx, iRack,
00175 ioPartialWord, iResults, n, iRow, iAnchor, iAnchor);
00176
00177 if (iLimit > 0)
00178 {
00179 for (succ = Dic_succ(iDic, n); succ; succ = Dic_next(iDic, succ))
00180 {
00181 l = Tile(Dic_chr(iDic, succ));
00182 if (iRack.in(l))
00183 {
00184 iRack.remove(l);
00185 ioPartialWord.addRightFromRack(l, 0);
00186 ioPartialWord.accessCoord().setCol(ioPartialWord.getCoord().getCol() - 1);
00187 LeftPart(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
00188 iJokerMx, iRack, ioPartialWord, iResults,
00189 succ, iRow, iAnchor, iLimit - 1);
00190 ioPartialWord.accessCoord().setCol(ioPartialWord.getCoord().getCol() + 1);
00191 ioPartialWord.removeRightToRack(l, 0);
00192 iRack.add(l);
00193 }
00194 if (iRack.in(Tile::Joker()))
00195 {
00196 iRack.remove(Tile::Joker());
00197 ioPartialWord.addRightFromRack(l, 1);
00198 ioPartialWord.accessCoord().setCol(ioPartialWord.getCoord().getCol() - 1);
00199 LeftPart(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
00200 iJokerMx, iRack, ioPartialWord, iResults,
00201 succ, iRow, iAnchor, iLimit - 1);
00202 ioPartialWord.accessCoord().setCol(ioPartialWord.getCoord().getCol() + 1);
00203 ioPartialWord.removeRightToRack(l, 1);
00204 iRack.add(Tile::Joker());
00205 }
00206 }
00207 }
00208 }
00209
00210
00211 static void BoardSearchAux(const Board &iBoard,
00212 const Dictionary &iDic,
00213 Matrix<Tile> &iTilesMx,
00214 Matrix<Cross> &iCrossMx,
00215 Matrix<int> &iPointsMx,
00216 Matrix<bool> &iJokerMx,
00217 Rack &iRack, Results &iResults,
00218 Coord::Direction iDir)
00219 {
00220 int row, col, lastanchor;
00221 Round partialword;
00222 for (row = 1; row <= BOARD_DIM; row++)
00223 {
00224 partialword.init();
00225 partialword.accessCoord().setDir(iDir);
00226 partialword.accessCoord().setRow(row);
00227 lastanchor = 0;
00228 for (col = 1; col <= BOARD_DIM; col++)
00229 {
00230 if (iTilesMx[row][col].isEmpty() &&
00231 (!iTilesMx[row][col - 1].isEmpty() ||
00232 !iTilesMx[row][col + 1].isEmpty() ||
00233 !iTilesMx[row - 1][col].isEmpty() ||
00234 !iTilesMx[row + 1][col].isEmpty()))
00235 {
00236 if (!iTilesMx[row][col - 1].isEmpty())
00237 {
00238 partialword.accessCoord().setCol(lastanchor + 1);
00239 ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
00240 iJokerMx, iRack, partialword, iResults,
00241 Dic_root(iDic), row, lastanchor + 1, col);
00242 }
00243 else
00244 {
00245 partialword.accessCoord().setCol(col);
00246 LeftPart(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
00247 iJokerMx, iRack, partialword, iResults,
00248 Dic_root(iDic), row, col, col -
00249 lastanchor - 1);
00250 }
00251 lastanchor = col;
00252 }
00253 }
00254 }
00255 }
00256
00257
00258 void Board::search(const Dictionary &iDic,
00259 const Rack &iRack,
00260 Results &oResults)
00261 {
00262
00263 Rack copyRack = iRack;
00264
00265 BoardSearchAux(*this, iDic, m_tilesRow, m_crossRow,
00266 m_pointRow, m_jokerRow,
00267 copyRack, oResults, Coord::HORIZONTAL);
00268
00269 BoardSearchAux(*this, iDic, m_tilesCol, m_crossCol,
00270 m_pointCol, m_jokerCol,
00271 copyRack, oResults, Coord::VERTICAL);
00272 }
00273
00274
00275 void Board::searchFirst(const Dictionary &iDic,
00276 const Rack &iRack,
00277 Results &oResults)
00278 {
00279 int row = 8, col = 8;
00280
00281
00282 Rack copyRack = iRack;
00283
00284 Round partialword;
00285 partialword.accessCoord().setRow(row);
00286 partialword.accessCoord().setCol(col);
00287 partialword.accessCoord().setDir(Coord::HORIZONTAL);
00288 LeftPart(*this, iDic, m_tilesRow, m_crossRow,
00289 m_pointRow, m_jokerRow,
00290 copyRack, partialword, oResults, Dic_root(iDic), row, col,
00291 copyRack.nTiles() - 1);
00292 }
00293
00294
00295
00296
00297
00298
00299