mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2025-01-30 20:34:27 +01:00
- 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:
parent
70041c80b3
commit
603a75a98c
6 changed files with 124 additions and 49 deletions
|
@ -94,14 +94,14 @@ Board::Board():
|
||||||
// No cross check allowed around the board
|
// No cross check allowed around the board
|
||||||
for (int i = 0; i < BOARD_REALDIM; i++)
|
for (int i = 0; i < BOARD_REALDIM; i++)
|
||||||
{
|
{
|
||||||
m_crossRow[0][i].clear();
|
m_crossRow[0][i].setNone();
|
||||||
m_crossCol[0][i].clear();
|
m_crossCol[0][i].setNone();
|
||||||
m_crossRow[i][0].clear();
|
m_crossRow[i][0].setNone();
|
||||||
m_crossCol[i][0].clear();
|
m_crossCol[i][0].setNone();
|
||||||
m_crossRow[BOARD_REALDIM - 1][i].clear();
|
m_crossRow[BOARD_REALDIM - 1][i].setNone();
|
||||||
m_crossCol[BOARD_REALDIM - 1][i].clear();
|
m_crossCol[BOARD_REALDIM - 1][i].setNone();
|
||||||
m_crossRow[i][BOARD_REALDIM - 1].clear();
|
m_crossRow[i][BOARD_REALDIM - 1].setNone();
|
||||||
m_crossCol[i][BOARD_REALDIM - 1].clear();
|
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_tilesRow[row][col + i] = Tile::dummy();
|
||||||
m_jokerRow[row][col + i] = false;
|
m_jokerRow[row][col + i] = false;
|
||||||
|
m_crossRow[row][col + i].setAny();
|
||||||
m_tilesCol[col + i][row] = Tile::dummy();
|
m_tilesCol[col + i][row] = Tile::dummy();
|
||||||
m_jokerCol[col + i][row] = false;
|
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_tilesRow[row + i][col] = Tile::dummy();
|
||||||
m_jokerRow[row + i][col] = false;
|
m_jokerRow[row + i][col] = false;
|
||||||
|
m_crossRow[row + i][col].setAny();
|
||||||
m_tilesCol[col][row + i] = Tile::dummy();
|
m_tilesCol[col][row + i] = Tile::dummy();
|
||||||
m_jokerCol[col][row + i] = false;
|
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
|
#ifdef DEBUG
|
||||||
void Board::checkDouble()
|
void Board::checkDouble()
|
||||||
{
|
{
|
||||||
|
|
|
@ -88,7 +88,7 @@ public:
|
||||||
|
|
||||||
void addRound(const Dictionary &iDic, const Round &iRound);
|
void addRound(const Dictionary &iDic, const Round &iRound);
|
||||||
void removeRound(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 getWordMultiplier(int iRow, int iCol) const;
|
||||||
int getLetterMultiplier(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:
|
private:
|
||||||
|
|
||||||
Matrix<Tile> m_tilesRow;
|
Matrix<Tile> m_tilesRow;
|
||||||
|
|
|
@ -37,38 +37,40 @@ static void Board_checkout_tile(const Dictionary &iDic,
|
||||||
int& oPoints,
|
int& oPoints,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
|
int i,left;
|
||||||
unsigned int node, succ;
|
unsigned int node, succ;
|
||||||
int j;
|
|
||||||
|
|
||||||
oPoints = 0;
|
oPoints = 0;
|
||||||
|
|
||||||
/* Points on the left part */
|
/* Points on the left part */
|
||||||
int i = index;
|
left = index;
|
||||||
while (!iTiles[i - 1].isEmpty())
|
while (!iTiles[left - 1].isEmpty())
|
||||||
{
|
{
|
||||||
i--;
|
left--;
|
||||||
if (!iJoker[i])
|
if (!iJoker[left])
|
||||||
oPoints += iTiles[i].getPoints();
|
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 */
|
/* 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);
|
node = Dic_char_lookup(iDic, Dic_root(iDic), leftTiles);
|
||||||
if (node == 0)
|
if (node == 0)
|
||||||
{
|
{
|
||||||
oCross.clear();
|
oCross.setNone();
|
||||||
return;
|
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))
|
for (succ = Dic_succ(iDic, node); succ; succ = Dic_next(iDic, succ))
|
||||||
{
|
{
|
||||||
if (Dic_word(iDic, Dic_char_lookup(iDic, succ, rightTiles)))
|
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;
|
iPointMx[j][i] = -1;
|
||||||
if (!iTilesMx[i][j].isEmpty())
|
if (!iTilesMx[i][j].isEmpty())
|
||||||
{
|
{
|
||||||
iCrossMx[j][i].clear();
|
iCrossMx[j][i].setNone();
|
||||||
}
|
}
|
||||||
else if (!iTilesMx[i][j - 1].isEmpty() ||
|
else if (!iTilesMx[i][j - 1].isEmpty() ||
|
||||||
!iTilesMx[i][j + 1].isEmpty())
|
!iTilesMx[i][j + 1].isEmpty())
|
||||||
{
|
{
|
||||||
iCrossMx[j][i].clear();
|
iCrossMx[j][i].setNone();
|
||||||
Board_checkout_tile(iDic,
|
Board_checkout_tile(iDic,
|
||||||
iTilesMx[i],
|
iTilesMx[i],
|
||||||
iJokerMx[i],
|
iJokerMx[i],
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "round.h"
|
#include "round.h"
|
||||||
#include "results.h"
|
#include "results.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
#include "encoding.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -78,7 +78,6 @@ static void BoardSearchEvalMove(const Board &iBoard,
|
||||||
iWord.setBonus(fromrack == 7);
|
iWord.setBonus(fromrack == 7);
|
||||||
iWord.setPoints(pts);
|
iWord.setPoints(pts);
|
||||||
|
|
||||||
// XXX: ugly!
|
|
||||||
if (iWord.getCoord().getDir() == Coord::VERTICAL)
|
if (iWord.getCoord().getDir() == Coord::VERTICAL)
|
||||||
{
|
{
|
||||||
// Exchange the coordinates temporarily
|
// Exchange the coordinates temporarily
|
||||||
|
@ -90,6 +89,8 @@ static void BoardSearchEvalMove(const Board &iBoard,
|
||||||
// Restore the coordinates
|
// Restore the coordinates
|
||||||
iWord.accessCoord().swap();
|
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() ||
|
||||||
!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
|
// Optimization compared to the original Appel & Jacobson
|
||||||
// algorithm: skip Leftpart if none of the tiles of the rack
|
// algorithm: skip Leftpart if none of the tiles of the rack
|
||||||
// matches the cross mask for the current anchor
|
// matches the cross mask for the current anchor
|
||||||
|
@ -270,6 +289,7 @@ static void BoardSearchAux(const Board &iBoard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastanchor = col;
|
lastanchor = col;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,37 +17,56 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include "cross.h"
|
#include "cross.h"
|
||||||
|
|
||||||
|
#define CROSS_MASK 0xFFFFFFFF
|
||||||
|
|
||||||
Cross::Cross()
|
Cross::Cross()
|
||||||
{
|
{
|
||||||
// The default behaviour is to match everything
|
// The default behaviour is to match everything
|
||||||
m_any = true;
|
setAny();
|
||||||
m_mask = 0xFFFFFFFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Cross::setAny()
|
||||||
void Cross::clear()
|
{
|
||||||
|
m_mask = CROSS_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Cross::isAny() const
|
||||||
|
{
|
||||||
|
return m_mask == CROSS_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cross::setNone()
|
||||||
{
|
{
|
||||||
m_any = false;
|
|
||||||
m_mask = 0;
|
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
|
bool Cross::check(const Tile& iTile) const
|
||||||
{
|
{
|
||||||
if (m_any || (iTile.isJoker() && m_mask != 0))
|
return (iTile.isJoker() && m_mask != 0) || (m_mask & (1 << iTile.toCode()));
|
||||||
return true;
|
|
||||||
return m_mask & (1 << iTile.toCode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Cross::insert(const Tile& iTile)
|
||||||
|
{
|
||||||
|
m_mask |= (1 << iTile.toCode());
|
||||||
|
}
|
||||||
|
|
||||||
bool Cross::operator==(const Cross &iOther) const
|
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;
|
return m_mask == iOther.m_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
game/cross.h
15
game/cross.h
|
@ -36,23 +36,24 @@ public:
|
||||||
Cross();
|
Cross();
|
||||||
virtual ~Cross() {}
|
virtual ~Cross() {}
|
||||||
|
|
||||||
void setAny() { m_any = true; }
|
void setAny();
|
||||||
bool isAny() const { return m_any; }
|
void setNone();
|
||||||
|
|
||||||
|
bool isAny() const;
|
||||||
|
bool isNone() const;
|
||||||
|
|
||||||
bool check(const Tile& iTile) const;
|
bool check(const Tile& iTile) const;
|
||||||
|
|
||||||
bool operator==(const Cross &iOther) const;
|
bool operator==(const Cross &iOther) const;
|
||||||
bool operator!=(const Cross &iOther) const { return !(*this == iOther); }
|
bool operator!=(const Cross &iOther) const { return !(*this == iOther); }
|
||||||
|
|
||||||
// Standard set methods (almost)
|
// Standard set methods (almost)
|
||||||
void insert(const Tile& iTile) { m_mask |= (1 << iTile.toCode()); }
|
void insert(const Tile& iTile);
|
||||||
void clear();
|
|
||||||
|
|
||||||
|
string getHexContent() const;
|
||||||
private:
|
private:
|
||||||
/// Mask indicating which tiles are accepted for the cross check
|
/// Mask indicating which tiles are accepted for the cross check
|
||||||
unsigned int m_mask;
|
unsigned int m_mask;
|
||||||
|
|
||||||
/// When this value is true, any letter matches the cross check
|
|
||||||
bool m_any;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue