mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2025-01-18 10:26:15 +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
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -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<Tile> m_tilesRow;
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::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;
|
||||
}
|
||||
|
||||
|
|
15
game/cross.h
15
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
|
||||
|
|
Loading…
Reference in a new issue