New BoardLayout class to wrap the board layout (size and special squares).

Until now there is no user-visible change, but it should make it much
easier to add custom layouts.
This commit is contained in:
Olivier Teulière 2012-12-26 14:14:44 +01:00
parent c138947138
commit 5441007db1
11 changed files with 328 additions and 137 deletions

View file

@ -41,6 +41,7 @@ libgame_a_SOURCES= \
ai_player.h \ ai_player.h \
ai_percent.cpp ai_percent.h \ ai_percent.cpp ai_percent.h \
game_params.h \ game_params.h \
board_layout.cpp board_layout.h \
board.cpp board.h \ board.cpp board.h \
board_cross.cpp \ board_cross.cpp \
matrix.h \ matrix.h \

View file

@ -27,6 +27,7 @@
#include "board.h" #include "board.h"
#include "board_search.h" #include "board_search.h"
#include "game_params.h" #include "game_params.h"
#include "board_layout.h"
#include "tile.h" #include "tile.h"
#include "round.h" #include "round.h"
#include "rack.h" #include "rack.h"
@ -34,63 +35,14 @@
#include "encoding.h" #include "encoding.h"
#include "debug.h" #include "debug.h"
#define oo 0 #define BOARD_REALDIM (BOARD_DIM + 2)
#define __ 1
#define T2 2
#define T3 3
#define W2 2
#define W3 3
INIT_LOGGER(game, Board); INIT_LOGGER(game, Board);
const int Board::m_tileMultipliers[BOARD_REALDIM][BOARD_REALDIM] =
{
{ oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo },
{ oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
{ oo,__,__,__,__,__,T3,__,__,__,T3,__,__,__,__,__,oo },
{ oo,__,__,__,__,__,__,T2,__,T2,__,__,__,__,__,__,oo },
{ oo,T2,__,__,__,__,__,__,T2,__,__,__,__,__,__,T2,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,__,T3,__,__,__,T3,__,__,__,T3,__,__,__,T3,__,oo },
{ oo,__,__,T2,__,__,__,T2,__,T2,__,__,__,T2,__,__,oo },
{ oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
{ oo,__,__,T2,__,__,__,T2,__,T2,__,__,__,T2,__,__,oo },
{ oo,__,T3,__,__,__,T3,__,__,__,T3,__,__,__,T3,__,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,T2,__,__,__,__,__,__,T2,__,__,__,__,__,__,T2,oo },
{ oo,__,__,__,__,__,__,T2,__,T2,__,__,__,__,__,__,oo },
{ oo,__,__,__,__,__,T3,__,__,__,T3,__,__,__,__,__,oo },
{ oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
{ oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo }
};
const int Board::m_wordMultipliers[BOARD_REALDIM][BOARD_REALDIM] =
{
{ oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo },
{ oo,W3,__,__,__,__,__,__,W3,__,__,__,__,__,__,W3,oo },
{ oo,__,W2,__,__,__,__,__,__,__,__,__,__,__,W2,__,oo },
{ oo,__,__,W2,__,__,__,__,__,__,__,__,__,W2,__,__,oo },
{ oo,__,__,__,W2,__,__,__,__,__,__,__,W2,__,__,__,oo },
{ oo,__,__,__,__,W2,__,__,__,__,__,W2,__,__,__,__,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,W3,__,__,__,__,__,__,W2,__,__,__,__,__,__,W3,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,__,__,__,__,W2,__,__,__,__,__,W2,__,__,__,__,oo },
{ oo,__,__,__,W2,__,__,__,__,__,__,__,W2,__,__,__,oo },
{ oo,__,__,W2,__,__,__,__,__,__,__,__,__,W2,__,__,oo },
{ oo,__,W2,__,__,__,__,__,__,__,__,__,__,__,W2,__,oo },
{ oo,W3,__,__,__,__,__,__,W3,__,__,__,__,__,__,W3,oo },
{ oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo }
};
Board::Board(const GameParams &iParams): Board::Board(const GameParams &iParams):
m_params(iParams), m_params(iParams), m_layout(iParams.getBoardLayout()),
m_tilesRow(BOARD_REALDIM, Tile()), m_tilesRow(BOARD_REALDIM, Tile()),
m_tilesCol(BOARD_REALDIM, Tile()), m_tilesCol(BOARD_REALDIM, Tile()),
m_jokerRow(BOARD_REALDIM, false), m_jokerRow(BOARD_REALDIM, false),
@ -142,8 +94,9 @@ bool Board::isJoker(int iRow, int iCol) const
bool Board::isVacant(int iRow, int iCol) const bool Board::isVacant(int iRow, int iCol) const
{ {
ASSERT(iRow >= BOARD_MIN && iRow <= BOARD_MAX && ASSERT(iRow >= 1 && (unsigned)iRow <= m_layout.getRowCount() &&
iCol >= BOARD_MIN && iCol <= BOARD_MAX, "Invalid coordinates"); iCol >= 1 && (unsigned)iCol <= m_layout.getColCount(),
"Invalid coordinates");
return m_tilesRow[iRow][iCol].isEmpty(); return m_tilesRow[iRow][iCol].isEmpty();
} }
@ -154,7 +107,7 @@ void Board::addRound(const Dictionary &iDic, const Round &iRound)
int col = iRound.getCoord().getCol(); int col = iRound.getCoord().getCol();
if (iRound.getCoord().getDir() == Coord::HORIZONTAL) if (iRound.getCoord().getDir() == Coord::HORIZONTAL)
{ {
for (unsigned int i = 0; i < iRound.getWordLen(); i++) for (unsigned i = 0; i < iRound.getWordLen(); i++)
{ {
const Tile &t = iRound.getTile(i); const Tile &t = iRound.getTile(i);
if (isVacant(row, col + i)) if (isVacant(row, col + i))
@ -282,7 +235,7 @@ int Board::checkRoundAux(const Matrix<Tile> &iTilesMx,
int col = iRound.getCoord().getCol(); int col = iRound.getCoord().getCol();
// Is the word going out of the board? // Is the word going out of the board?
if (col + iRound.getWordLen() > BOARD_MAX + 1) if (col + iRound.getWordLen() >= BOARD_REALDIM)
return 8; return 8;
// Is the word an extension of another word? // Is the word an extension of another word?
@ -323,16 +276,17 @@ int Board::checkRoundAux(const Matrix<Tile> &iTilesMx,
int l; int l;
if (!iRound.isJoker(i)) if (!iRound.isJoker(i))
l = t.getPoints() * m_tileMultipliers[row][col + i]; l = t.getPoints() * getLayout().getLetterMultiplier(row, col + i);
else else
l = 0; l = 0;
pts += l; pts += l;
wordmul *= m_wordMultipliers[row][col + i]; int wm = getLayout().getWordMultiplier(row, col + i);
wordmul *= wm;
int p = iPointsMx[row][col + i]; int p = iPointsMx[row][col + i];
if (p >= 0) if (p >= 0)
{ {
ptscross += (p + l) * m_wordMultipliers[row][col + i]; ptscross += (p + l) * wm;
} }
++fromrack; ++fromrack;
iRound.setFromRack(i); iRound.setFromRack(i);
@ -466,24 +420,6 @@ const Tile& Board::getTestTile(int iRow, int iCol) const
} }
int Board::GetWordMultiplier(int iRow, int iCol)
{
if (iRow < BOARD_MIN || iRow > BOARD_MAX ||
iCol < BOARD_MIN || iCol > BOARD_MAX)
return 0;
return m_wordMultipliers[iRow][iCol];
}
int Board::GetLetterMultiplier(int iRow, int iCol)
{
if (iRow < BOARD_MIN || iRow > BOARD_MAX ||
iCol < BOARD_MIN || iCol > BOARD_MAX)
return 0;
return m_tileMultipliers[iRow][iCol];
}
// #define CELL_STRING_FORMAT "[%c:%s:%2d]" // #define CELL_STRING_FORMAT "[%c:%s:%2d]"
#define CELL_STRING_FORMAT "[%s:%2d]" #define CELL_STRING_FORMAT "[%s:%2d]"
@ -511,9 +447,11 @@ string Board::getCellContent_col(int row, int col) const
#ifdef DEBUG #ifdef DEBUG
void Board::checkDouble() void Board::checkDouble()
{ {
for (int row = BOARD_MIN; row <= BOARD_MAX; row++) const unsigned nbRows = m_layout.getRowCount();
const unsigned nbCols = m_layout.getColCount();
for (unsigned row = 1; row <= nbRows; row++)
{ {
for (int col = BOARD_MIN; col <= BOARD_MAX; col++) for (unsigned col = 1; col <= nbCols; col++)
{ {
ASSERT(m_tilesRow[row][col] == m_tilesCol[col][row], ASSERT(m_tilesRow[row][col] == m_tilesCol[col][row],
"Tiles inconsistency at " << row << "x" << col); "Tiles inconsistency at " << row << "x" << col);

View file

@ -30,6 +30,7 @@
#include "logging.h" #include "logging.h"
class GameParams; class GameParams;
class BoardLayout;
class Dictionary; class Dictionary;
class Rack; class Rack;
class Round; class Round;
@ -40,7 +41,6 @@ using namespace std;
#define BOARD_MIN 1 #define BOARD_MIN 1
#define BOARD_MAX 15 #define BOARD_MAX 15
#define BOARD_DIM 15 #define BOARD_DIM 15
#define BOARD_REALDIM (BOARD_DIM + 2)
/** /**
@ -55,6 +55,8 @@ class Board
public: public:
Board(const GameParams &iParams); Board(const GameParams &iParams);
const BoardLayout & getLayout() const { return m_layout; }
bool isJoker(int iRow, int iCol) const; bool isJoker(int iRow, int iCol) const;
bool isVacant(int iRow, int iCol) const; bool isVacant(int iRow, int iCol) const;
@ -76,12 +78,6 @@ public:
void search(const Dictionary &iDic, const Rack &iRack, Results &oResults) const; void search(const Dictionary &iDic, const Rack &iRack, Results &oResults) const;
void searchFirst(const Dictionary &iDic, const Rack &iRack, Results &oResults) const; void searchFirst(const Dictionary &iDic, const Rack &iRack, Results &oResults) const;
/**
*
*/
static int GetWordMultiplier(int iRow, int iCol);
static int GetLetterMultiplier(int iRow, int iCol);
/** /**
* *
*/ */
@ -92,6 +88,8 @@ private:
const GameParams &m_params; const GameParams &m_params;
const BoardLayout &m_layout;
Matrix<Tile> m_tilesRow; Matrix<Tile> m_tilesRow;
Matrix<Tile> m_tilesCol; Matrix<Tile> m_tilesCol;
@ -109,9 +107,6 @@ private:
/// Flag indicating if the board is empty or if it has letters /// Flag indicating if the board is empty or if it has letters
bool m_isEmpty; bool m_isEmpty;
static const int m_tileMultipliers[BOARD_REALDIM][BOARD_REALDIM];
static const int m_wordMultipliers[BOARD_REALDIM][BOARD_REALDIM];
/** /**
* board_cross.c * board_cross.c
*/ */

158
game/board_layout.cpp Normal file
View file

@ -0,0 +1,158 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2012 Olivier Teulière
* Authors: Olivier Teulière <ipkiss @@ gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
#include "board_layout.h"
#include "dic.h"
#include "debug.h"
#define oo 0
#define __ 1
#define T2 2
#define T3 3
#define W2 2
#define W3 3
#define BOARD_DIM 15
#define BOARD_REALDIM (BOARD_DIM + 2)
INIT_LOGGER(game, BoardLayout);
static const int DefaultTileMultipliers[BOARD_REALDIM][BOARD_REALDIM] =
{
{ oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo },
{ oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
{ oo,__,__,__,__,__,T3,__,__,__,T3,__,__,__,__,__,oo },
{ oo,__,__,__,__,__,__,T2,__,T2,__,__,__,__,__,__,oo },
{ oo,T2,__,__,__,__,__,__,T2,__,__,__,__,__,__,T2,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,__,T3,__,__,__,T3,__,__,__,T3,__,__,__,T3,__,oo },
{ oo,__,__,T2,__,__,__,T2,__,T2,__,__,__,T2,__,__,oo },
{ oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
{ oo,__,__,T2,__,__,__,T2,__,T2,__,__,__,T2,__,__,oo },
{ oo,__,T3,__,__,__,T3,__,__,__,T3,__,__,__,T3,__,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,T2,__,__,__,__,__,__,T2,__,__,__,__,__,__,T2,oo },
{ oo,__,__,__,__,__,__,T2,__,T2,__,__,__,__,__,__,oo },
{ oo,__,__,__,__,__,T3,__,__,__,T3,__,__,__,__,__,oo },
{ oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
{ oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo }
};
static const int DefaultWordMultipliers[BOARD_REALDIM][BOARD_REALDIM] =
{
{ oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo },
{ oo,W3,__,__,__,__,__,__,W3,__,__,__,__,__,__,W3,oo },
{ oo,__,W2,__,__,__,__,__,__,__,__,__,__,__,W2,__,oo },
{ oo,__,__,W2,__,__,__,__,__,__,__,__,__,W2,__,__,oo },
{ oo,__,__,__,W2,__,__,__,__,__,__,__,W2,__,__,__,oo },
{ oo,__,__,__,__,W2,__,__,__,__,__,W2,__,__,__,__,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,W3,__,__,__,__,__,__,W2,__,__,__,__,__,__,W3,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
{ oo,__,__,__,__,W2,__,__,__,__,__,W2,__,__,__,__,oo },
{ oo,__,__,__,W2,__,__,__,__,__,__,__,W2,__,__,__,oo },
{ oo,__,__,W2,__,__,__,__,__,__,__,__,__,W2,__,__,oo },
{ oo,__,W2,__,__,__,__,__,__,__,__,__,__,__,W2,__,oo },
{ oo,W3,__,__,__,__,__,__,W3,__,__,__,__,__,__,W3,oo },
{ oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo }
};
// Initialize the static member
BoardLayout BoardLayout::m_defaultLayout;
BoardLayout::BoardLayout()
{
setDefaultLayout();
}
unsigned BoardLayout::getRowCount() const
{
ASSERT(m_wordMultipliers.size() > 2 && m_tileMultipliers.size() > 2,
"Invalid board size");
return m_wordMultipliers.size() - 2;
}
unsigned BoardLayout::getColCount() const
{
ASSERT(m_wordMultipliers.size() > 2 && m_tileMultipliers.size() > 2,
"Invalid board size");
return m_wordMultipliers[0].size() - 2;
}
int BoardLayout::getWordMultiplier(unsigned iRow, unsigned iCol) const
{
if (!isValidCoord(iRow, iCol))
return 0;
return m_wordMultipliers[iRow][iCol];
}
int BoardLayout::getLetterMultiplier(unsigned iRow, unsigned iCol) const
{
if (!isValidCoord(iRow, iCol))
return 0;
return m_tileMultipliers[iRow][iCol];
}
bool BoardLayout::isValidCoord(unsigned iRow, unsigned iCol) const
{
return (iRow >= 1 && iRow <= getRowCount() &&
iCol >= 1 && iCol <= getColCount());
}
static void InitMatrixFromArray(Matrix<int> &oMatrix, const int iArray[BOARD_REALDIM][BOARD_REALDIM])
{
oMatrix.resize(BOARD_REALDIM, BOARD_REALDIM, 0);
for (unsigned i = 0; i < BOARD_REALDIM; ++i)
{
for (unsigned j = 0; j < BOARD_REALDIM; ++j)
{
oMatrix[i][j] = iArray[i][j];
}
}
}
void BoardLayout::setDefaultLayout()
{
InitMatrixFromArray(m_wordMultipliers, DefaultWordMultipliers);
InitMatrixFromArray(m_tileMultipliers, DefaultTileMultipliers);
}
const BoardLayout & BoardLayout::GetDefault()
{
return m_defaultLayout;
}

58
game/board_layout.h Normal file
View file

@ -0,0 +1,58 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2012 Olivier Teulière
* Authors: Olivier Teulière <ipkiss @@ gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
#ifndef BOARD_LAYOUT_H_
#define BOARD_LAYOUT_H_
#include "matrix.h"
#include "logging.h"
/**
* Board layout (size and special squares)
*/
class BoardLayout
{
DEFINE_LOGGER();
public:
BoardLayout();
unsigned getRowCount() const;
unsigned getColCount() const;
int getWordMultiplier(unsigned iRow, unsigned iCol) const;
int getLetterMultiplier(unsigned iRow, unsigned iCol) const;
static const BoardLayout & GetDefault();
private:
static BoardLayout m_defaultLayout;
Matrix<int> m_wordMultipliers;
Matrix<int> m_tileMultipliers;
bool isValidCoord(unsigned iRow, unsigned iCol) const;
void setDefaultLayout();
};
#endif

View file

@ -246,6 +246,7 @@ void BoardSearch::evalMove(Results &oResults, Round &iWord) const
int row = iWord.getCoord().getRow(); int row = iWord.getCoord().getRow();
int col = iWord.getCoord().getCol(); int col = iWord.getCoord().getCol();
const BoardLayout & boardLayout = m_params.getBoardLayout();
for (unsigned int i = 0; i < len; i++) for (unsigned int i = 0; i < len; i++)
{ {
if (!m_tilesMx[row][col+i].isEmpty()) if (!m_tilesMx[row][col+i].isEmpty())
@ -258,15 +259,16 @@ void BoardSearch::evalMove(Results &oResults, Round &iWord) const
int l; int l;
if (!iWord.isJoker(i)) if (!iWord.isJoker(i))
l = iWord.getTile(i).getPoints() * l = iWord.getTile(i).getPoints() *
Board::GetLetterMultiplier(row, col + i); boardLayout.getLetterMultiplier(row, col + i);
else else
l = 0; l = 0;
pts += l; pts += l;
wordmul *= Board::GetWordMultiplier(row, col + i); int wm = boardLayout.getWordMultiplier(row, col + i);
wordmul *= wm;
int t = m_pointsMx[row][col+i]; int t = m_pointsMx[row][col+i];
if (t >= 0) if (t >= 0)
ptscross += (t + l) * Board::GetWordMultiplier(row, col + i); ptscross += (t + l) * wm;
fromrack++; fromrack++;
} }
} }

View file

@ -22,6 +22,7 @@
#define GAME_PARAMS_H_ #define GAME_PARAMS_H_
#include "game_exception.h" #include "game_exception.h"
#include "board_layout.h"
class Dictionary; class Dictionary;
@ -82,6 +83,8 @@ class GameParams
m_rackSize = 8; m_rackSize = 8;
} }
void setBoardLayout(const BoardLayout &iLayout) { m_boardLayout = iLayout; }
// Getters // Getters
const Dictionary & getDic() const { return m_dic; } const Dictionary & getDic() const { return m_dic; }
GameMode getMode() const { return m_mode; } GameMode getMode() const { return m_mode; }
@ -90,7 +93,10 @@ class GameParams
int getLettersToPlay() const { return m_lettersToPlay; } int getLettersToPlay() const { return m_lettersToPlay; }
int getBonusPoints() const { return m_bonusPoints; } int getBonusPoints() const { return m_bonusPoints; }
const BoardLayout & getBoardLayout() const { return m_boardLayout; }
private: private:
BoardLayout m_boardLayout;
const Dictionary &m_dic; const Dictionary &m_dic;
GameMode m_mode; GameMode m_mode;
unsigned int m_variants; unsigned int m_variants;

View file

@ -31,16 +31,32 @@ template <class T>
class Matrix: public vector<vector<T> > class Matrix: public vector<vector<T> >
{ {
public: public:
// Construct a matrix with an initial value /// Construct a matrix with an initial value
Matrix(int iSize1, int iSize2, const T &iValue) Matrix(int iSize1, int iSize2, const T &iValue)
{
resize(iSize1, iSize2, iValue);
}
/// Construct a square matrix with an initial value
Matrix(int iSize, const T &iValue)
{
resize(iSize, iSize, iValue);
}
Matrix()
{
}
/**
* Resize the matrix to iSize1 rows and iSize2 cols.
* The contents may be erased.
*/
void resize(int iSize1, int iSize2, const T &iValue)
{ {
this->resize(iSize1, vector<T>(iSize2, iValue)); this->resize(iSize1, vector<T>(iSize2, iValue));
} }
// Construct a square matrix with an initial value
Matrix(int iSize, const T &iValue) using::vector<vector<T> >::resize;
{
this->resize(iSize, vector<T>(iSize, iValue));
}
}; };
#endif #endif

View file

@ -28,6 +28,7 @@
#include "qtcommon.h" #include "qtcommon.h"
#include "public_game.h" #include "public_game.h"
#include "tile.h" #include "tile.h"
#include "board_layout.h"
#include "board.h" #include "board.h"
#include "play_model.h" #include "play_model.h"
#include "move.h" #include "move.h"
@ -41,9 +42,14 @@ INIT_LOGGER(qt, BoardWidget);
BoardWidget::BoardWidget(PlayModel &iPlayModel, QWidget *parent) BoardWidget::BoardWidget(PlayModel &iPlayModel, QWidget *parent)
: QFrame(parent), m_game(NULL), : QFrame(parent), m_game(NULL),
m_playModel(iPlayModel), m_showTemporarySigns(true), m_playModel(iPlayModel), m_showTemporarySigns(true),
m_showOnlyLastTurn(false), m_showOnlyLastTurn(false)
m_widgetsMatrix(BOARD_MAX + 1, BOARD_MAX + 1, 0)
{ {
const BoardLayout & boardLayout = BoardLayout::GetDefault();
const unsigned nbRows = boardLayout.getRowCount();
const unsigned nbCols = boardLayout.getColCount();
m_widgetsMatrix.resize(nbRows + 1, nbCols + 1, 0);
// Try to have a black background... FIXME: not working well! // Try to have a black background... FIXME: not working well!
QPalette pal = palette(); QPalette pal = palette();
for (int i = 0; i <= 19; ++i) for (int i = 0; i <= 19; ++i)
@ -52,37 +58,39 @@ BoardWidget::BoardWidget(PlayModel &iPlayModel, QWidget *parent)
setForegroundRole(QPalette::Window); setForegroundRole(QPalette::Window);
setBackgroundRole(QPalette::Window); setBackgroundRole(QPalette::Window);
TileLayout *layout = new TileLayout(BOARD_MAX + 1, BOARD_MAX + 1); TileLayout *layout = new TileLayout(nbRows + 1, nbCols + 1);
layout->setSpacing(1); layout->setSpacing(1);
layout->setAlignment(Qt::AlignHCenter); layout->setAlignment(Qt::AlignHCenter);
// Line full of coordinates // Line full of coordinates
TileWidget *cornerTile = new TileWidget; TileWidget *cornerTile = new TileWidget;
cornerTile->setCoordText(""); cornerTile->setCoordText("");
layout->addWidget(cornerTile); layout->addWidget(cornerTile);
for (unsigned int col = BOARD_MIN; col <= BOARD_MAX; ++col) for (unsigned int col = 1; col <= nbCols; ++col)
{ {
TileWidget *coordTile = new TileWidget; TileWidget *coordTile = new TileWidget;
coordTile->setCoordText(QString("%1").arg(col)); coordTile->setCoordText(QString("%1").arg(col));
layout->addWidget(coordTile); layout->addWidget(coordTile);
} }
// Rest of the board // Rest of the board
for (unsigned int row = BOARD_MIN; row <= BOARD_MAX; ++row) for (unsigned int row = 1; row <= nbRows; ++row)
{ {
// Add the coordinate // Add the coordinate
TileWidget *coordTile = new TileWidget; TileWidget *coordTile = new TileWidget;
coordTile->setCoordText(QString(QChar('A' + row - BOARD_MIN))); coordTile->setCoordText(QString(QChar('A' + row - 1)));
layout->addWidget(coordTile); layout->addWidget(coordTile);
// Add the squares // Add the squares
for (unsigned int col = BOARD_MIN; col <= BOARD_MAX; ++col) for (unsigned int col = 1; col <= nbCols; ++col)
{ {
TileWidget::Multiplier mult = TileWidget::NONE; TileWidget::Multiplier mult = TileWidget::NONE;
if (Board::GetWordMultiplier(row, col) == 3) if (boardLayout.getWordMultiplier(row, col) == 3)
mult = TileWidget::WORD_TRIPLE; mult = TileWidget::WORD_TRIPLE;
else if (Board::GetWordMultiplier(row, col) == 2) else if (boardLayout.getWordMultiplier(row, col) == 2)
mult = TileWidget::WORD_DOUBLE; mult = TileWidget::WORD_DOUBLE;
else if (Board::GetLetterMultiplier(row, col) == 3) else if (boardLayout.getLetterMultiplier(row, col) == 3)
mult = TileWidget::LETTER_TRIPLE; mult = TileWidget::LETTER_TRIPLE;
else if (Board::GetLetterMultiplier(row, col) == 2) else if (boardLayout.getLetterMultiplier(row, col) == 2)
mult = TileWidget::LETTER_DOUBLE; mult = TileWidget::LETTER_DOUBLE;
TileWidget *t = new TileWidget(this, mult, row, col); TileWidget *t = new TileWidget(this, mult, row, col);
m_widgetsMatrix[row][col] = t; m_widgetsMatrix[row][col] = t;
@ -159,9 +167,11 @@ void BoardWidget::refresh()
// Note: the TileWidget class will redraw the tile only if something // Note: the TileWidget class will redraw the tile only if something
// has changed, to avoid useless repainting. // has changed, to avoid useless repainting.
const Board &board = m_game->getBoard(); const Board &board = m_game->getBoard();
for (unsigned int row = BOARD_MIN; row <= BOARD_MAX; ++row) const unsigned nbRows = board.getLayout().getRowCount();
const unsigned nbCols = board.getLayout().getColCount();
for (unsigned row = 1; row <= nbRows; ++row)
{ {
for (unsigned int col = BOARD_MIN; col <= BOARD_MAX; ++col) for (unsigned col = 1; col <= nbCols; ++col)
{ {
if (board.isTestChar(row, col) && m_showTemporarySigns) if (board.isTestChar(row, col) && m_showTemporarySigns)
{ {
@ -191,9 +201,9 @@ void BoardWidget::refresh()
else else
{ {
// Clear the board // Clear the board
for (unsigned int row = BOARD_MIN; row <= BOARD_MAX; ++row) for (unsigned row = 1; row < m_widgetsMatrix.size(); ++row)
{ {
for (unsigned int col = BOARD_MIN; col <= BOARD_MAX; ++col) for (unsigned col = 1; col < m_widgetsMatrix[1].size(); ++col)
{ {
m_widgetsMatrix[row][col]->tileChanged(TileWidget::BOARD_EMPTY); m_widgetsMatrix[row][col]->tileChanged(TileWidget::BOARD_EMPTY);
} }
@ -222,7 +232,7 @@ void BoardWidget::paintEvent(QPaintEvent *)
QLine vLine(0, 0, 0, rect.height() + 1); QLine vLine(0, 0, 0, rect.height() + 1);
hLine.translate(rect.left() - 1, rect.top() - 1); hLine.translate(rect.left() - 1, rect.top() - 1);
vLine.translate(rect.left() - 1, rect.top() - 1); vLine.translate(rect.left() - 1, rect.top() - 1);
for (int i = 0; i <= BOARD_MAX; ++i) for (unsigned i = 0; i < m_widgetsMatrix.size(); ++i)
{ {
painter.drawLine(hLine); painter.drawLine(hLine);
painter.drawLine(vLine); painter.drawLine(vLine);

View file

@ -25,12 +25,13 @@
#include <string> #include <string>
#include <stdlib.h> #include <stdlib.h>
#include <dic.h>
#include "game_io.h" #include "game_io.h"
#include "game_params.h" #include "game_params.h"
#include "dic.h"
#include "public_game.h" #include "public_game.h"
#include "bag.h" #include "bag.h"
#include "board.h" #include "board.h"
#include "board_layout.h"
#include "results.h" #include "results.h"
#include "player.h" #include "player.h"
#include "encoding.h" #include "encoding.h"
@ -50,16 +51,17 @@ INIT_LOGGER(utils, GameIO);
void GameIO::printBoard(ostream &out, const PublicGame &iGame) void GameIO::printBoard(ostream &out, const PublicGame &iGame)
{ {
int row, col; int nbRows = iGame.getBoard().getLayout().getRowCount();
int nbCols = iGame.getBoard().getLayout().getColCount();
out << " "; out << " ";
for (col = BOARD_MIN; col <= BOARD_MAX; col++) for (int col = 1; col <= nbCols; ++col)
out << setw(3) << col - BOARD_MIN + 1; out << setw(3) << col;
out << endl; out << endl;
for (row = BOARD_MIN; row <= BOARD_MAX; row++) for (int row = 1; row <= nbRows; ++row)
{ {
out << " " << (char)(row - BOARD_MIN + 'A') << " "; out << " " << (char)(row + 'A' - 1) << " ";
for (col = BOARD_MIN; col <= BOARD_MAX; col++) for (int col = 1; col <= nbCols; ++col)
{ {
if (iGame.getBoard().isVacant(row, col)) if (iGame.getBoard().isVacant(row, col))
out << " - "; out << " - ";
@ -74,23 +76,24 @@ void GameIO::printBoard(ostream &out, const PublicGame &iGame)
/* this mode is used for regression tests */ /* this mode is used for regression tests */
void GameIO::printBoardDebug(ostream &out, const PublicGame &iGame) void GameIO::printBoardDebug(ostream &out, const PublicGame &iGame)
{ {
int row, col; int nbRows = iGame.getBoard().getLayout().getRowCount();
int nbCols = iGame.getBoard().getLayout().getColCount();
/* first printf row cell contents */ /* first printf row cell contents */
for (row = BOARD_MIN; row <= BOARD_MAX; row++) for (int row = 1; row <= nbRows; ++row)
{ {
out << " " << (char)(row - BOARD_MIN + 'A') << "r "; out << " " << (char)(row + 'A' - 1) << "r ";
for (col = BOARD_MIN; col <= BOARD_MAX; col++) for (int col = 1; col <= nbCols; ++col)
{ {
out << iGame.getBoard().getCellContent_row(row, col); out << iGame.getBoard().getCellContent_row(row, col);
} }
out << endl; out << endl;
} }
out << " -" << endl; out << " -" << endl;
for (row = BOARD_MIN; row <= BOARD_MAX; row++) for (int row = 1; row <= nbRows; ++row)
{ {
out << " " << (char)(row - BOARD_MIN + 'A') << "c "; out << " " << (char)(row + 'A' - 1) << "c ";
for (col = BOARD_MIN; col <= BOARD_MAX; col++) for (int col = 1; col <= nbCols; ++col)
{ {
out << iGame.getBoard().getCellContent_col(row, col); out << iGame.getBoard().getCellContent_col(row, col);
} }
@ -101,24 +104,26 @@ void GameIO::printBoardDebug(ostream &out, const PublicGame &iGame)
void GameIO::printBoardMultipliers(ostream &out, const PublicGame &iGame) void GameIO::printBoardMultipliers(ostream &out, const PublicGame &iGame)
{ {
int row, col; int nbRows = iGame.getBoard().getLayout().getRowCount();
int nbCols = iGame.getBoard().getLayout().getColCount();
out << " "; out << " ";
for (col = BOARD_MIN; col <= BOARD_MAX; col++) for (int col = 1; col <= nbCols; ++col)
out << setw(3) << col - BOARD_MIN + 1; out << setw(3) << col;
out << endl; out << endl;
for (row = BOARD_MIN; row <= BOARD_MAX; row++) const BoardLayout & boardLayout = iGame.getBoard().getLayout();
for (int row = 1; row <= nbRows; ++row)
{ {
out << " " << (char)(row - BOARD_MIN + 'A') << " "; out << " " << (char)(row + 'A' - 1) << " ";
for (col = BOARD_MIN; col <= BOARD_MAX; col++) for (int col = 1; col <= nbCols; ++col)
{ {
if (!iGame.getBoard().isVacant(row, col)) if (!iGame.getBoard().isVacant(row, col))
out << padAndConvert(iGame.getBoard().getDisplayStr(row, col), 3); out << padAndConvert(iGame.getBoard().getDisplayStr(row, col), 3);
else else
{ {
int wm = iGame.getBoard().GetWordMultiplier(row, col); int wm = boardLayout.getWordMultiplier(row, col);
int tm = iGame.getBoard().GetLetterMultiplier(row, col); int tm = boardLayout.getLetterMultiplier(row, col);
if (wm > 1) if (wm > 1)
out << " " << ((wm == 3) ? '@' : '#'); out << " " << ((wm == 3) ? '@' : '#');

View file

@ -42,6 +42,7 @@
#include "game_factory.h" #include "game_factory.h"
#include "game_params.h" #include "game_params.h"
#include "board.h" #include "board.h"
#include "board_layout.h"
#include "bag.h" #include "bag.h"
#include "public_game.h" #include "public_game.h"
#include "results.h" #include "results.h"
@ -232,13 +233,14 @@ void CursesIntf::drawBoard(WINDOW *win, int y, int x) const
} }
// The board itself // The board itself
const BoardLayout & boardLayout = m_game->getBoard().getLayout();
for (int row = 1; row < 16; row++) for (int row = 1; row < 16; row++)
{ {
for (int col = 1; col < 16; col++) for (int col = 1; col < 16; col++)
{ {
// Handle colors // Handle colors
int wm = m_game->getBoard().GetWordMultiplier(row, col); int wm = boardLayout.getWordMultiplier(row, col);
int lm = m_game->getBoard().GetLetterMultiplier(row, col); int lm = boardLayout.getLetterMultiplier(row, col);
if (wm == 3) if (wm == 3)
wattron(win, COLOR_PAIR(COLOR_RED)); wattron(win, COLOR_PAIR(COLOR_RED));
else if (wm == 2) else if (wm == 2)