- extra debug output command for board cross info

- simplified cross class
- bug fix on cross information handling during backward moves
This commit is contained in:
Antoine Fraboulet 2006-11-05 13:30:06 +00:00
parent 70041c80b3
commit 603a75a98c
6 changed files with 124 additions and 49 deletions

View file

@ -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()
{

View file

@ -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<Tile> m_tilesRow;

View file

@ -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();
}
/* Tiles that can be played */
// FIXME: create a temporary string until the dictionary uses Tile objects
// FIXME: create temporary strings 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;
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 */
node = Dic_char_lookup(iDic, Dic_root(iDic), leftTiles);
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],

View file

@ -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()); */
}
@ -239,6 +240,24 @@ static void BoardSearchAux(const Board &iBoard,
!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
}
}
}

View file

@ -17,37 +17,56 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
#include <string>
#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::clear()
void Cross::setAny()
{
m_mask = CROSS_MASK;
}
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;
}

View file

@ -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