From 603a75a98c9e8398f7fce6437b2d063c14218227 Mon Sep 17 00:00:00 2001 From: Antoine Fraboulet Date: Sun, 5 Nov 2006 13:30:06 +0000 Subject: [PATCH] - extra debug output command for board cross info - simplified cross class - bug fix on cross information handling during backward moves --- game/board.cpp | 43 +++++++++++++++++++++++++++++++++++-------- game/board.h | 8 +++++++- game/board_cross.cpp | 42 ++++++++++++++++++++++-------------------- game/board_search.cpp | 26 +++++++++++++++++++++++--- game/cross.cpp | 39 +++++++++++++++++++++++++++++---------- game/cross.h | 15 ++++++++------- 6 files changed, 124 insertions(+), 49 deletions(-) diff --git a/game/board.cpp b/game/board.cpp index 3e13279..91f415b 100644 --- a/game/board.cpp +++ b/game/board.cpp @@ -94,14 +94,14 @@ Board::Board(): // No cross check allowed around the board for (int i = 0; i < BOARD_REALDIM; i++) { - m_crossRow[0][i].clear(); - m_crossCol[0][i].clear(); - m_crossRow[i][0].clear(); - m_crossCol[i][0].clear(); - m_crossRow[BOARD_REALDIM - 1][i].clear(); - m_crossCol[BOARD_REALDIM - 1][i].clear(); - m_crossRow[i][BOARD_REALDIM - 1].clear(); - m_crossCol[i][BOARD_REALDIM - 1].clear(); + m_crossRow[0][i].setNone(); + m_crossCol[0][i].setNone(); + m_crossRow[i][0].setNone(); + m_crossCol[i][0].setNone(); + m_crossRow[BOARD_REALDIM - 1][i].setNone(); + m_crossCol[BOARD_REALDIM - 1][i].setNone(); + m_crossRow[i][BOARD_REALDIM - 1].setNone(); + m_crossCol[i][BOARD_REALDIM - 1].setNone(); } } @@ -206,8 +206,10 @@ void Board::removeRound(const Dictionary &iDic, const Round &iRound) { m_tilesRow[row][col + i] = Tile::dummy(); m_jokerRow[row][col + i] = false; + m_crossRow[row][col + i].setAny(); m_tilesCol[col + i][row] = Tile::dummy(); m_jokerCol[col + i][row] = false; + m_crossCol[col + i][row].setAny(); } } } @@ -219,8 +221,10 @@ void Board::removeRound(const Dictionary &iDic, const Round &iRound) { m_tilesRow[row + i][col] = Tile::dummy(); m_jokerRow[row + i][col] = false; + m_crossRow[row + i][col].setAny(); m_tilesCol[col][row + i] = Tile::dummy(); m_jokerCol[col][row + i] = false; + m_crossCol[col][row + i].setAny(); } } } @@ -461,6 +465,29 @@ int Board::getLetterMultiplier(int iRow, int iCol) const } +#define CELL_STRING_FORMAT "[%s:%2d]" + +string Board::getCellContent_row(int row, int col) const +{ + char buff[1024]; /* [ joker, mask, point, tiles ] */ + sprintf(buff,CELL_STRING_FORMAT, + // m_jokerRow[row][col] ? 'j':'.', + m_crossRow[row][col].getHexContent().c_str(), + m_pointRow[row][col]); + return string(buff); +} + +string Board::getCellContent_col(int row, int col) const +{ + char buff[1024]; + sprintf(buff,CELL_STRING_FORMAT, + // m_jokerCol[col][row] ? 'j':'.', + m_crossCol[col][row].getHexContent().c_str(), + m_pointCol[col][row]); + return string(buff); +} + + #ifdef DEBUG void Board::checkDouble() { diff --git a/game/board.h b/game/board.h index f8589de..004b46d 100644 --- a/game/board.h +++ b/game/board.h @@ -88,7 +88,7 @@ public: void addRound(const Dictionary &iDic, const Round &iRound); void removeRound(const Dictionary &iDic, const Round &iRound); - int checkRound(Round &iRound, bool iFirstTurn); + int checkRound(Round &iRound, bool iFirstTurn); /** * @@ -114,6 +114,12 @@ public: int getWordMultiplier(int iRow, int iCol) const; int getLetterMultiplier(int iRow, int iCol) const; + /** + * + */ + string getCellContent_row(int row, int col) const; + string getCellContent_col(int row, int col) const; + private: Matrix m_tilesRow; diff --git a/game/board_cross.cpp b/game/board_cross.cpp index 7a163c0..4f285d1 100644 --- a/game/board_cross.cpp +++ b/game/board_cross.cpp @@ -37,38 +37,40 @@ static void Board_checkout_tile(const Dictionary &iDic, int& oPoints, int index) { + int i,left; unsigned int node, succ; - int j; oPoints = 0; /* Points on the left part */ - int i = index; - while (!iTiles[i - 1].isEmpty()) + left = index; + while (!iTiles[left - 1].isEmpty()) { - i--; - if (!iJoker[i]) - oPoints += iTiles[i].getPoints(); + left--; + if (!iJoker[left]) + oPoints += iTiles[left].getPoints(); } + // FIXME: create temporary strings until the dictionary uses Tile objects + char leftTiles [BOARD_DIM + 1]; + char rightTiles[BOARD_DIM + 1]; + + for (i = left; i < index; i++) + leftTiles[i - left] = toupper(iTiles[i].toChar()); + leftTiles[index - left] = 0; + + for (i = index + 1; !iTiles[i].isEmpty(); i++) + rightTiles[i - index - 1] = toupper(iTiles[i].toChar()); + rightTiles[i - index - 1] = 0; + /* Tiles that can be played */ - // FIXME: create a temporary string until the dictionary uses Tile objects - char leftTiles[BOARD_DIM + 1]; - for (j = i; j < index; j++) - leftTiles[j - i] = toupper(iTiles[j].toChar()); - leftTiles[index - i] = 0; node = Dic_char_lookup(iDic, Dic_root(iDic), leftTiles); - if (node == 0) + if (node == 0) { - oCross.clear(); + oCross.setNone(); return; } - // FIXME: same thing for the right part - char rightTiles[BOARD_DIM + 1]; - for (j = index + 1; !iTiles[j].isEmpty(); j++) - rightTiles[j - index - 1] = toupper(iTiles[j].toChar()); - rightTiles[j - index - 1] = 0; for (succ = Dic_succ(iDic, node); succ; succ = Dic_next(iDic, succ)) { if (Dic_word(iDic, Dic_char_lookup(iDic, succ, rightTiles))) @@ -101,12 +103,12 @@ static void Board_check(const Dictionary &iDic, iPointMx[j][i] = -1; if (!iTilesMx[i][j].isEmpty()) { - iCrossMx[j][i].clear(); + iCrossMx[j][i].setNone(); } else if (!iTilesMx[i][j - 1].isEmpty() || !iTilesMx[i][j + 1].isEmpty()) { - iCrossMx[j][i].clear(); + iCrossMx[j][i].setNone(); Board_checkout_tile(iDic, iTilesMx[i], iJokerMx[i], diff --git a/game/board_search.cpp b/game/board_search.cpp index 8f889fa..5790e40 100644 --- a/game/board_search.cpp +++ b/game/board_search.cpp @@ -24,7 +24,7 @@ #include "round.h" #include "results.h" #include "board.h" - +#include "encoding.h" #include "debug.h" /* @@ -78,7 +78,6 @@ static void BoardSearchEvalMove(const Board &iBoard, iWord.setBonus(fromrack == 7); iWord.setPoints(pts); - // XXX: ugly! if (iWord.getCoord().getDir() == Coord::VERTICAL) { // Exchange the coordinates temporarily @@ -90,6 +89,8 @@ static void BoardSearchEvalMove(const Board &iBoard, // Restore the coordinates iWord.accessCoord().swap(); } + + /* fprintf(stdout,"eval: %s\n",convertToMb(iWord.toString()).c_str()); */ } @@ -236,9 +237,27 @@ static void BoardSearchAux(const Board &iBoard, if (iTilesMx[row][col].isEmpty() && (!iTilesMx[row][col - 1].isEmpty() || !iTilesMx[row][col + 1].isEmpty() || - !iTilesMx[row - 1][col].isEmpty() || + !iTilesMx[row - 1][col].isEmpty() || !iTilesMx[row + 1][col].isEmpty())) { +#if defined(DONT_USE_SEARCH_OPTIMIZATION) + if (!iTilesMx[row][col - 1].isEmpty()) + { + partialword.accessCoord().setCol(lastanchor + 1); + ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx, + iJokerMx, iRack, partialword, iResults, + Dic_root(iDic), row, lastanchor + 1, col); + } + else + { + partialword.accessCoord().setCol(col); + LeftPart(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx, + iJokerMx, iRack, partialword, iResults, + Dic_root(iDic), row, col, col - + lastanchor - 1); + } + lastanchor = col; +#else // Optimization compared to the original Appel & Jacobson // algorithm: skip Leftpart if none of the tiles of the rack // matches the cross mask for the current anchor @@ -270,6 +289,7 @@ static void BoardSearchAux(const Board &iBoard, } } lastanchor = col; +#endif } } } diff --git a/game/cross.cpp b/game/cross.cpp index cebce18..32cb938 100644 --- a/game/cross.cpp +++ b/game/cross.cpp @@ -17,37 +17,56 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *****************************************************************************/ +#include #include "cross.h" +#define CROSS_MASK 0xFFFFFFFF Cross::Cross() { // The default behaviour is to match everything - m_any = true; - m_mask = 0xFFFFFFFF; + setAny(); } +void Cross::setAny() +{ + m_mask = CROSS_MASK; +} -void Cross::clear() +bool Cross::isAny() const +{ + return m_mask == CROSS_MASK; +} + +void Cross::setNone() { - m_any = false; m_mask = 0; } +string Cross::getHexContent() const +{ + char buff[10]; + sprintf(buff,"%08x",m_mask); + string s(buff); + return s; +} bool Cross::check(const Tile& iTile) const { - if (m_any || (iTile.isJoker() && m_mask != 0)) - return true; - return m_mask & (1 << iTile.toCode()); + return (iTile.isJoker() && m_mask != 0) || (m_mask & (1 << iTile.toCode())); } +void Cross::insert(const Tile& iTile) +{ + m_mask |= (1 << iTile.toCode()); +} bool Cross::operator==(const Cross &iOther) const { - if (isAny() || iOther.isAny()) - return isAny() && iOther.isAny(); - + /* + * if (isAny() || iOther.isAny()) + * return isAny() && iOther.isAny(); + */ return m_mask == iOther.m_mask; } diff --git a/game/cross.h b/game/cross.h index 18c7485..9a0beb2 100644 --- a/game/cross.h +++ b/game/cross.h @@ -36,23 +36,24 @@ public: Cross(); virtual ~Cross() {} - void setAny() { m_any = true; } - bool isAny() const { return m_any; } + void setAny(); + void setNone(); + + bool isAny() const; + bool isNone() const; + bool check(const Tile& iTile) const; bool operator==(const Cross &iOther) const; bool operator!=(const Cross &iOther) const { return !(*this == iOther); } // Standard set methods (almost) - void insert(const Tile& iTile) { m_mask |= (1 << iTile.toCode()); } - void clear(); + void insert(const Tile& iTile); + string getHexContent() const; private: /// Mask indicating which tiles are accepted for the cross check unsigned int m_mask; - - /// When this value is true, any letter matches the cross check - bool m_any; }; #endif