Backport of the 'multibyte' branch on HEAD.

This commit is contained in:
Olivier Teulière 2006-01-22 12:23:52 +00:00
parent 2799f5191e
commit 77be2e9219
51 changed files with 1246 additions and 803 deletions

16
TODO
View file

@ -3,15 +3,7 @@
* TODO Current version
* ====================
- The dictionary must use codes for performance reasons,
the board must also be made to use codes instead of tiles.
Using class Tiles during search results in a HUGE
performance penalty. Class cross is a performance killer.
Will return back to using code bitmaps in board for cross
search. Files cross.h and cross.cpp are to be removed or
replaced by a 64 bits code bitmap.
- Correct game save/load functions : Advanced format
- Correct game save/load functions : Advanced format
file saving for freegames and duplicate need a serious
rewrite. We need to specifie a file format that can handle
all the information contained in a multiplayer game.
@ -19,14 +11,14 @@
- Add "joker" type games in wxwin version of Eliot, Freegame
and Duplicate will follow
- full French i18n interface and error messages for wxwin.
- full French i18n interface and error messages for wxwin.
* ==================
* Next Eliot version
* ==================
- new dictionnary format that includes tiles
- new dictionnary format that includes tiles
- number
- points
- printable equivalent
@ -45,6 +37,8 @@
- network support
- add timers
- implement the dictionary as a GADDAG:
http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol24/issue2/spe880.pdf
%%% Local Variables:

View file

@ -86,10 +86,10 @@ dnl Check for wxWidgets
AC_ARG_ENABLE([wxwidgets],AC_HELP_STRING([--enable-wxwidgets],[wxWidgets interface support (default disabled)]))
if test "${enable_wxwidgets}" = "yes"
then
AM_PATH_WXCONFIG(2.6.0, wxWin=1)
AM_PATH_WXCONFIG(2.6.0, [wxWin=1], [wxWin=0], [], [--unicode])
if test "${wxWin}" != 1; then
AC_MSG_ERROR([
wxWidgets must be installed on your system
wxWidgets (unicode build) must be installed on your system
but wx-config script couldn't be found.
Please check that wx-config is in path, the directory

View file

@ -1,5 +1,10 @@
.deps
Makefile
Makefile.in
scanner.h
er.c
libdic_a-er.c
libdic_a-er.h
compdic
listdic
regexp

View file

@ -111,14 +111,14 @@ void
print_header_info(Dict_header *header)
{
printf("============================\n");
printf("keyword length %d bytes\n",(int)strlen(_COMPIL_KEYWORD_));
printf("keyword size %d bytes\n",sizeof(_COMPIL_KEYWORD_));
printf("header size %d bytes\n",sizeof(Dict_header));
printf("keyword length %lu bytes\n", strlen(_COMPIL_KEYWORD_));
printf("keyword size %lu bytes\n", sizeof(_COMPIL_KEYWORD_));
printf("header size %lu bytes\n", sizeof(Dict_header));
printf("\n");
printf("%d words\n",header->nwords);
printf("\n");
printf("root : %7d (edge)\n",header->root);
printf("root : %7d (byte)\n",header->root * sizeof(Dawg_edge));
printf("root : %7lu (byte)\n",header->root * sizeof(Dawg_edge));
printf("\n");
printf("nodes : %d+%d\n",header->nodesused, header->nodessaved);
printf("edges : %d+%d\n",header->edgesused, header->edgessaved);

View file

@ -27,6 +27,7 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "dic_internals.h"
#include "dic.h"
@ -70,18 +71,35 @@ Dic_seek_edgeptr(const Dictionary dic, const char* s, Dawg_edge *eptr)
/**
* Dic_search_word : direct application of Dic_seek_edgeptr
* Dic_search_word_inner : direct application of Dic_seek_edgeptr
* @param dic : dictionary
* @param word : word to lookup
* @result 0 not a valid word, 1 ok
*/
int
Dic_search_word(const Dictionary dic, const char* word)
static int Dic_search_word_inner(const Dictionary dic, const char* word)
{
Dawg_edge *e;
e = Dic_seek_edgeptr(dic,word,dic->dawg + dic->root);
return e->term;
Dawg_edge *e;
e = Dic_seek_edgeptr(dic, word, dic->dawg + dic->root);
return e->term;
}
/**
* Wrapper around Dic_search_word_inner, until we have multibyte support in
* the dictionary
*/
int Dic_search_word(const Dictionary dic, const wchar_t* word)
{
int res;
char *tmp_word = malloc(wcslen(word) + 1);
sprintf(tmp_word, "%ls", word);
// Do the actual work
res = Dic_search_word_inner(dic, tmp_word);
// Release memory
free(tmp_word);
return res;
}
@ -159,10 +177,10 @@ Dic_search_word_by_len(struct params_7plus1_t *params, int i, Dawg_edge *edgeptr
} while (! (*edgeptr++).last);
}
void
Dic_search_7pl1(const Dictionary dic, const char* rack,
char buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX],
int joker)
static void
Dic_search_7pl1_inner(const Dictionary dic, const char* rack,
char buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX],
int joker)
{
int i,j,wordlen;
const char* r = rack;
@ -235,12 +253,41 @@ Dic_search_7pl1(const Dictionary dic, const char* rack,
}
}
/**
* Wrapper around Dic_search_7pl1_inner, until we have multibyte support in
* the dictionary
*/
void
Dic_search_7pl1(const Dictionary dic, const wchar_t* rack,
wchar_t buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX],
int joker)
{
int i, j, k;
char tmp_buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX];
char *tmp_rack = malloc(wcslen(rack) + 1);
sprintf(tmp_rack, "%ls", rack);
// Do the actual work
Dic_search_7pl1_inner(dic, tmp_rack, tmp_buff, joker);
for (i = 0; i < DIC_LETTERS; i++)
{
for (j = 0; j < RES_7PL1_MAX; j++)
{
for (k = 0; k < DIC_WORD_MAX; k++)
{
buff[i][j][k] = tmp_buff[i][j][k];
}
}
}
}
/****************************************/
/****************************************/
void
Dic_search_Racc(const Dictionary dic, const char* word,
char wordlist[RES_RACC_MAX][DIC_WORD_MAX])
static void
Dic_search_Racc_inner(const Dictionary dic, const char* word,
char wordlist[RES_RACC_MAX][DIC_WORD_MAX])
{
/* search_racc will try to add a letter in front and at the end of a word */
@ -260,7 +307,7 @@ Dic_search_Racc(const Dictionary dic, const char* word,
for(i='a'; i <= 'z'; i++)
{
wordtst[0] = i;
if (Dic_search_word(dic,wordtst) && wordlistlen < RES_RACC_MAX)
if (Dic_search_word_inner(dic,wordtst) && wordlistlen < RES_RACC_MAX)
strcpy(wordlist[wordlistlen++],wordtst);
}
@ -288,13 +335,37 @@ Dic_search_Racc(const Dictionary dic, const char* word,
}
}
/****************************************/
/****************************************/
/**
* Wrapper around Dic_search_Racc_inner, until we have multibyte support in
* the dictionary
*/
void
Dic_search_Benj(const Dictionary dic, const char* word,
char wordlist[RES_BENJ_MAX][DIC_WORD_MAX])
Dic_search_Racc(const Dictionary dic, const wchar_t* word,
wchar_t wordlist[RES_RACC_MAX][DIC_WORD_MAX])
{
int i, j;
char tmp_buff[RES_RACC_MAX][DIC_WORD_MAX];
char *tmp_word = malloc(wcslen(word) + 1);
sprintf(tmp_word, "%ls", word);
// Do the actual work
Dic_search_Racc_inner(dic, tmp_word, tmp_buff);
for (i = 0; i < RES_RACC_MAX; i++)
{
for (j = 0; j < DIC_WORD_MAX; j++)
{
wordlist[i][j] = tmp_buff[i][j];
}
}
}
/****************************************/
/****************************************/
static void
Dic_search_Benj_inner(const Dictionary dic, const char* word,
char wordlist[RES_BENJ_MAX][DIC_WORD_MAX])
{
int i,wordlistlen;
char wordtst[DIC_WORD_MAX];
@ -326,6 +397,30 @@ Dic_search_Benj(const Dictionary dic, const char* word,
} while (!(*edge0++).last);
}
/**
* Wrapper around Dic_search_Benj_inner, until we have multibyte support in
* the dictionary
*/
void
Dic_search_Benj(const Dictionary dic, const wchar_t* word,
wchar_t wordlist[RES_BENJ_MAX][DIC_WORD_MAX])
{
int i, j;
char tmp_buff[RES_BENJ_MAX][DIC_WORD_MAX];
char *tmp_word = malloc(wcslen(word) + 1);
sprintf(tmp_word, "%ls", word);
// Do the actual work
Dic_search_Benj_inner(dic, tmp_word, tmp_buff);
for (i = 0; i < RES_BENJ_MAX; i++)
{
for (j = 0; j < DIC_WORD_MAX; j++)
{
wordlist[i][j] = tmp_buff[i][j];
}
}
}
/****************************************/
/****************************************/
@ -341,8 +436,8 @@ struct params_cross_t {
void
Dic_search_cross_rec(struct params_cross_t *params,
char wordlist[RES_CROS_MAX][DIC_WORD_MAX],
Dawg_edge *edgeptr)
char wordlist[RES_CROS_MAX][DIC_WORD_MAX],
Dawg_edge *edgeptr)
{
Dawg_edge *current = params->dic->dawg + edgeptr->ptr;
@ -380,10 +475,9 @@ Dic_search_cross_rec(struct params_cross_t *params,
}
void
Dic_search_Cros(const Dictionary dic, const char* mask,
char wordlist[RES_CROS_MAX][DIC_WORD_MAX])
static void
Dic_search_Cros_inner(const Dictionary dic, const char* mask,
char wordlist[RES_CROS_MAX][DIC_WORD_MAX])
{
int i;
struct params_cross_t params;
@ -410,6 +504,31 @@ Dic_search_Cros(const Dictionary dic, const char* mask,
Dic_search_cross_rec(&params, wordlist, dic->dawg + dic->root);
}
/**
* Wrapper around Dic_search_Cros_inner, until we have multibyte support in
* the dictionary
*/
void
Dic_search_Cros(const Dictionary dic, const wchar_t* mask,
wchar_t wordlist[RES_CROS_MAX][DIC_WORD_MAX])
{
int i, j;
char tmp_buff[RES_CROS_MAX][DIC_WORD_MAX];
char *tmp_mask = malloc(wcslen(mask) + 1);
sprintf(tmp_mask, "%ls", mask);
// Do the actual work
Dic_search_Cros_inner(dic, tmp_mask, tmp_buff);
for (i = 0; i < RES_CROS_MAX; i++)
{
for (j = 0; j < DIC_WORD_MAX; j++)
{
wordlist[i][j] = tmp_buff[i][j];
}
}
}
/****************************************/
/****************************************/
@ -466,13 +585,13 @@ Dic_search_regexp_rec(struct params_regexp_t *params,
* function prototype for parser generated by bison
*/
int regexpparse(yyscan_t scanner, NODE** root,
struct search_RegE_list_t *list,
struct regexp_error_report_t *err);
struct search_RegE_list_t *list,
struct regexp_error_report_t *err);
void
Dic_search_RegE(const Dictionary dic, const char* re,
char wordlist[RES_REGE_MAX][DIC_WORD_MAX],
struct search_RegE_list_t *list)
Dic_search_RegE_inner(const Dictionary dic, const char* re,
char wordlist[RES_REGE_MAX][DIC_WORD_MAX],
struct search_RegE_list_t *list)
{
int i,p,n,value;
int ptl[REGEXP_MAX+1];
@ -548,6 +667,31 @@ Dic_search_RegE(const Dictionary dic, const char* re,
regexp_delete_tree(root);
}
/**
* Wrapper around Dic_search_RegE_inner, until we have multibyte support in
* the dictionary
*/
void
Dic_search_RegE(const Dictionary dic, const wchar_t* re,
wchar_t wordlist[RES_REGE_MAX][DIC_WORD_MAX],
struct search_RegE_list_t *list)
{
int i, j;
char tmp_buff[RES_REGE_MAX][DIC_WORD_MAX];
char *tmp_re = malloc(wcslen(re) + 1);
sprintf(tmp_re, "%ls", re);
// Do the actual work
Dic_search_RegE_inner(dic, tmp_re, tmp_buff, list);
for (i = 0; i < RES_REGE_MAX; i++)
{
for (j = 0; j < DIC_WORD_MAX; j++)
{
wordlist[i][j] = tmp_buff[i][j];
}
}
}
/****************************************/
/****************************************/

View file

@ -62,7 +62,8 @@ extern "C"
* @param path : lookup word
* @return 1 present, 0 error
*/
int Dic_search_word(Dictionary dic, const char* path);
int Dic_search_word(Dictionary dic,
const wchar_t* path);
/**
* Search for all feasible word with "rack" plus one letter
@ -70,7 +71,10 @@ int Dic_search_word(Dictionary dic, const char* path);
* @param rack : letters
* @param wordlist : results
*/
void Dic_search_7pl1(Dictionary dic, const char* rack, char wordlist[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX], int joker);
void Dic_search_7pl1(Dictionary dic,
const wchar_t* rack,
wchar_t wordlist[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX],
int joker);
/**
* Search for all feasible word adding a letter in front or at the end
@ -78,7 +82,9 @@ void Dic_search_7pl1(Dictionary dic, const char* rack, char wordlist[DIC_LETTERS
* @param word : word
* @param wordlist : results
*/
void Dic_search_Racc(Dictionary dic, const char* word, char wordlist[RES_RACC_MAX][DIC_WORD_MAX]);
void Dic_search_Racc(Dictionary dic,
const wchar_t* word,
wchar_t wordlist[RES_RACC_MAX][DIC_WORD_MAX]);
/**
* Search for benjamins
@ -86,7 +92,9 @@ void Dic_search_Racc(Dictionary dic, const char* word, char wordlist[RES_RACC_MA
* @param rack : letters
* @param wordlist : results
*/
void Dic_search_Benj(Dictionary dic, const char* word, char wordlist[RES_BENJ_MAX][DIC_WORD_MAX]);
void Dic_search_Benj(Dictionary dic,
const wchar_t* word,
wchar_t wordlist[RES_BENJ_MAX][DIC_WORD_MAX]);
/**
* Search for crosswords
@ -94,7 +102,9 @@ void Dic_search_Benj(Dictionary dic, const char* word, char wordlist[RES_BENJ_MA
* @param rack : letters
* @param wordlist : results
*/
void Dic_search_Cros(Dictionary dic, const char* mask, char wordlist[RES_CROS_MAX][DIC_WORD_MAX]);
void Dic_search_Cros(Dictionary dic,
const wchar_t* mask,
wchar_t wordlist[RES_CROS_MAX][DIC_WORD_MAX]);
/**
* Search for words matching a regular expression
@ -102,7 +112,18 @@ void Dic_search_Cros(Dictionary dic, const char* mask, char wordlist[RES_CROS_MA
* @param re : regular expression
* @param wordlist : results
*/
void Dic_search_RegE(Dictionary dic, const char* re, char wordlist[RES_REGE_MAX][DIC_WORD_MAX], struct search_RegE_list_t *list);
void Dic_search_RegE(Dictionary dic,
const wchar_t* re,
wchar_t wordlist[RES_REGE_MAX][DIC_WORD_MAX],
struct search_RegE_list_t *list);
/**
* Internal version of Dic_search_RegE, used inside the dictionary.
* Please use Dic_search_RegE instead from outside the dic library.
*/
void Dic_search_RegE_inner(const Dictionary dic, const char* re,
char wordlist[RES_REGE_MAX][DIC_WORD_MAX],
struct search_RegE_list_t *list);
#if defined(__cplusplus)
}

View file

@ -156,7 +156,7 @@ print_header(char* filename)
printf("0x%s nodes saved : %6d %s\n",offset(&header,&header.nodessaved),header.nodessaved,hexl(header.nodessaved));
printf("0x%s edges saved : %6d %s\n",offset(&header,&header.edgessaved),header.edgessaved,hexl(header.edgessaved));
printf("\n");
printf("sizeof(header) = 0x%s (%d)\n",hexb(sizeof(header)),sizeof(header));
printf("sizeof(header) = 0x%s (%lu)\n", hexb(sizeof(header)), sizeof(header));
}
void

View file

@ -124,7 +124,7 @@ int main(int argc, char* argv[])
/* automaton */
init_letter_lists(&list);
Dic_search_RegE(dic,er,wordlist,&list);
Dic_search_RegE_inner(dic,er,wordlist,&list);
fprintf(stdout,"résultat:\n");
for(i=0; i<RES_REGE_MAX && wordlist[i][0]; i++)

View file

@ -31,6 +31,7 @@ libgame_a_SOURCES= \
board_cross.cpp \
board_search.cpp \
duplicate.cpp duplicate.h \
encoding.cpp encoding.h \
freegame.cpp freegame.h \
game.cpp game.h \
game_factory.cpp game_factory.h \

View file

@ -84,7 +84,7 @@ unsigned int Bag::nConsonants() const
void Bag::takeTile(const Tile &iTile)
{
ASSERT(in(iTile),
string("The bag does not contain the letter ") + iTile.toChar());
(wstring(L"The bag does not contain the letter ") + iTile.toChar()).c_str());
m_tilesMap[iTile]--;
m_ntiles--;
@ -94,7 +94,7 @@ void Bag::takeTile(const Tile &iTile)
void Bag::replaceTile(const Tile &iTile)
{
ASSERT(in(iTile) < iTile.maxNumber(),
string("Cannot replace tile: ") + iTile.toChar());
(wstring(L"Cannot replace tile: ") + iTile.toChar()).c_str());
m_tilesMap[iTile]++;
m_ntiles++;

View file

@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
#include <wctype.h>
#include "dic.h"
#include "tile.h"
#include "round.h"
@ -104,15 +105,15 @@ Board::Board():
}
char Board::getChar(int iRow, int iCol) const
wchar_t Board::getChar(int iRow, int iCol) const
{
char letter = 0;
wchar_t letter = 0;
Tile tile = getTile(iRow, iCol);
if (!tile.isEmpty())
{
letter = tile.toChar();
if (isJoker(iRow, iCol))
letter = tolower(letter);
letter = towlower(letter);
}
return letter;
}

View file

@ -79,8 +79,8 @@ public:
#define ATTR_JOKER 1
#define ATTR_TEST 2
char getChar (int iRow, int iCol) const;
int getCharAttr(int iRow, int iCol) const;
wchar_t getChar (int iRow, int iCol) const;
int getCharAttr(int iRow, int iCol) const;
Tile getTile(int iRow, int iCol) const;
bool isJoker(int iRow, int iCol) const;

View file

@ -219,6 +219,12 @@ static void BoardSearchAux(const Board &iBoard,
{
int row, col, lastanchor;
Round partialword;
list<Tile> rackTiles;
iRack.getTiles(rackTiles);
list<Tile>::const_iterator it;
bool match;
for (row = 1; row <= BOARD_DIM; row++)
{
partialword.init();
@ -233,20 +239,35 @@ static void BoardSearchAux(const Board &iBoard,
!iTilesMx[row - 1][col].isEmpty() ||
!iTilesMx[row + 1][col].isEmpty()))
{
if (!iTilesMx[row][col - 1].isEmpty())
// 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
match = false;
for (it = rackTiles.begin();
!match && it != rackTiles.end(); it++)
{
partialword.accessCoord().setCol(lastanchor + 1);
ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
iJokerMx, iRack, partialword, iResults,
Dic_root(iDic), row, lastanchor + 1, col);
if (iCrossMx[row][col].check(*it))
{
match = true;
}
}
else
if (match)
{
partialword.accessCoord().setCol(col);
LeftPart(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
iJokerMx, iRack, partialword, iResults,
Dic_root(iDic), row, col, col -
lastanchor - 1);
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;
}

View file

@ -25,9 +25,11 @@
*/
#include <string>
#include <wchar.h>
#include "coord.h"
#include "board.h" // for BOARD_MIN and BOARD_MAX (TODO: remove this include)
#include "debug.h"
#include "encoding.h"
Coord::Coord(int iRow, int iCol, Direction iDir)
@ -37,7 +39,7 @@ Coord::Coord(int iRow, int iCol, Direction iDir)
m_dir = iDir;
}
Coord::Coord(const string &iStr)
Coord::Coord(const wstring &iStr)
{
setFromString(iStr);
}
@ -62,8 +64,13 @@ void Coord::swap()
m_row = tmp;
}
void Coord::setFromString(const string &iStr)
void Coord::setFromString(const wstring &iWStr)
{
// TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
// Temporary implementation: convert the wchar_t* string into a char* one
string iStr = convertToMb(iWStr);
char l[4];
int col;
@ -85,34 +92,35 @@ void Coord::setFromString(const string &iStr)
setRow(row);
}
string Coord::toString(coord_mode_t mode) const
wstring Coord::toString(coord_mode_t mode) const
{
ASSERT(isValid(), "Invalid coordinates");
char res[7];
char srow[3];
char scol[3];
wchar_t res[7];
wchar_t srow[3];
wchar_t scol[3];
sprintf(scol, "%d", m_col);
sprintf(srow, "%c", m_row + 'A' - 1);
_swprintf(scol, 3, L"%d", m_col);
_swprintf(srow, 3, L"%c", m_row + 'A' - 1);
switch (mode)
{
case COORD_MODE_COMPACT:
if (getDir() == HORIZONTAL)
sprintf(res,"%s%s",srow,scol);
else
sprintf(res,"%s%s",scol,srow);
break;
if (getDir() == HORIZONTAL)
_swprintf(res, 7, L"%ls%ls", srow, scol);
else
_swprintf(res, 7, L"%ls%ls", scol, srow);
break;
case COORD_MODE_LONG:
if (getDir() == HORIZONTAL)
sprintf(res,"%2s %2s",srow,scol);
else
sprintf(res,"%2s %2s",scol,srow);
break;
if (getDir() == HORIZONTAL)
_swprintf(res, 7, L"%2ls %2ls", srow, scol);
else
_swprintf(res, 7, L"%2ls %2ls", scol, srow);
break;
}
return string(res);
return res;
}
/// Local Variables:

View file

@ -28,6 +28,7 @@
#define _COORD_H
using std::string;
using std::wstring;
class Coord
{
@ -37,7 +38,7 @@ public:
// Construction, destruction
Coord(int iRow = -1, int iCol = -1, Direction iDir = HORIZONTAL);
Coord(const string &iStr);
Coord(const wstring &iStr);
virtual ~Coord() {}
// Accessors
@ -54,13 +55,14 @@ public:
// Swap the coordinates (without changing the direction)
void swap();
void setFromString(const string &iStr);
typedef enum {
COORD_MODE_COMPACT,
COORD_MODE_LONG
} coord_mode_t;
string toString(coord_mode_t mode = COORD_MODE_COMPACT) const;
enum coord_mode_t
{
COORD_MODE_COMPACT,
COORD_MODE_LONG
};
void setFromString(const wstring &iStr);
wstring toString(coord_mode_t mode = COORD_MODE_COMPACT) const;
private:
Direction m_dir;

View file

@ -22,45 +22,33 @@
Cross::Cross()
{
// the default behaviour is to match everything
// The default behaviour is to match everything
m_any = true;
m_mask = 0xFFFFFFFF;
}
void Cross::clear()
{
m_tilesSet.clear();
m_any = false;
m_mask = 0;
}
bool Cross::check(const Tile& iTile) const
{
if (m_any || (iTile.isJoker() && !m_tilesSet.empty()))
if (m_any || (iTile.isJoker() && m_mask != 0))
return true;
set<Tile>::const_iterator it = m_tilesSet.find(iTile);
return it != m_tilesSet.end();
return m_mask & (1 << iTile.toCode());
}
bool Cross::operator==(const Cross &iOther) const
{
if (isAny() && iOther.isAny())
return true;
// Two sets are equal if they have the same size and one of them contains
// the other one
if (m_tilesSet.size() == iOther.m_tilesSet.size())
{
set<Tile>::const_iterator it;
for (it = m_tilesSet.begin(); it != m_tilesSet.end(); it++)
{
if (!iOther.check(*it))
return false;
}
return true;
}
else
return false;
if (isAny() || iOther.isAny())
return isAny() && iOther.isAny();
return m_mask == iOther.m_mask;
}
/// Local Variables:

View file

@ -20,8 +20,8 @@
#ifndef _CROSS_H_
#define _CROSS_H_
#include "tile.h"
#include <set>
#include "tile.h"
using namespace std;
@ -44,15 +44,14 @@ public:
bool operator!=(const Cross &iOther) const { return !(*this == iOther); }
// Standard set methods (almost)
unsigned int size() const { return m_tilesSet.size(); }
void insert(const Tile& iTile) { m_tilesSet.insert(iTile); }
void insert(const Tile& iTile) { m_mask |= (1 << iTile.toCode()); }
void clear();
private:
// Set of the tiles accepted for the cross check
set<Tile> m_tilesSet;
/// 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
/// When this value is true, any letter matches the cross check
bool m_any;
};

View file

@ -50,7 +50,7 @@ int Duplicate::setRackRandom(int p, bool iCheck, set_rack_mode mode)
}
int Duplicate::play(const string &iCoord, const string &iWord)
int Duplicate::play(const wstring &iCoord, const wstring &iWord)
{
/* Perform all the validity checks, and fill a round */
Round round;

View file

@ -23,6 +23,7 @@
#include "game.h"
using std::string;
using std::wstring;
/**
@ -58,7 +59,7 @@ public:
*************************/
virtual int start();
virtual int setRackRandom(int, bool, set_rack_mode);
virtual int play(const string &iCoord, const string &iWord);
virtual int play(const wstring &iCoord, const wstring &iWord);
virtual int endTurn();
int setPlayer(int);

104
game/encoding.cpp Normal file
View file

@ -0,0 +1,104 @@
/* Eliot */
/* Copyright (C) 1999 Antoine Fraboulet */
/* */
/* This file is part of Eliot. */
/* */
/* Eliot 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. */
/* */
/* Eliot 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 */
/**
* \file encoding.cpp
* \brief Utility functions to ease manipulation of wide-character strings
* \author Olivier Teuliere
* \date 2005
*/
#include <stdlib.h>
#include <stdarg.h>
#include <wchar.h>
#include <wctype.h>
#include "encoding.h"
int _wtoi(const wchar_t *iWStr)
{
int res = 0;
while (iswdigit(iWStr[0]))
{
res = 10 * res + (iWStr[0] - '0');
iWStr++;
}
return res;
}
int _swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...)
{
int res;
va_list argp;
va_start(argp, format);
#ifdef WIN32
// Mingw32 does not take the maxlen argument
res = vswprintf(wcs, format, argp);
#else
res = vswprintf(wcs, maxlen, format, argp);
#endif
va_end(argp);
return res;
}
wstring convertToWc(const string& iStr)
{
// Get the needed length (we _can't_ use string::size())
size_t len = mbstowcs(NULL, iStr.c_str(), 0);
if (len == (size_t)-1)
return L"";
wchar_t *tmp = new wchar_t[len + 1];
len = mbstowcs(tmp, iStr.c_str(), len + 1);
wstring res = tmp;
delete[] tmp;
return res;
}
string convertToMb(const wstring& iWStr)
{
// Get the needed length (we _can't_ use wstring::size())
size_t len = wcstombs(NULL, iWStr.c_str(), 0);
if (len == (size_t)-1)
return "";
char *tmp = new char[len + 1];
len = wcstombs(tmp, iWStr.c_str(), len + 1);
string res = tmp;
delete[] tmp;
return res;
}
string convertToMb(wchar_t iWChar)
{
char res[MB_CUR_MAX + 1];
int len = wctomb(res, iWChar);
if (len == -1)
return "";
res[len] = '\0';
return res;
}

52
game/encoding.h Normal file
View file

@ -0,0 +1,52 @@
/* Eliot */
/* Copyright (C) 1999 Antoine Fraboulet */
/* */
/* This file is part of Eliot. */
/* */
/* Eliot 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. */
/* */
/* Eliot 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 */
/**
* \file encoding.h
* \brief Utility functions to ease manipulation of wide-character strings
* \author Olivier Teuliere
* \date 2005
*/
#ifndef _ENCODING_H_
#define _ENCODING_H_
#include <string>
using std::string;
using std::wstring;
/// Equivalent of atoi for wide-caracter strings
int _wtoi(const wchar_t *iWStr);
/// Equivalent of swprintf, but working also with mingw32
int _swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);
/// Convert a multi-byte string into a wide-character string
wstring convertToWc(const string& iStr);
/// Convert a wide-character string into a multi-byte string
string convertToMb(const wstring& iWStr);
/// Convert a wide character into a multi-byte string
string convertToMb(wchar_t iWChar);
#endif

View file

@ -18,6 +18,7 @@
*****************************************************************************/
#include <iomanip>
#include <wctype.h>
#include "dic.h"
#include "tile.h"
#include "rack.h"
@ -52,7 +53,7 @@ int FreeGame::setRackRandom(int p, bool iCheck, set_rack_mode mode)
}
int FreeGame::play(const string &iCoord, const string &iWord)
int FreeGame::play(const wstring &iCoord, const wstring &iWord)
{
/* Perform all the validity checks, and fill a round */
Round round;
@ -188,7 +189,7 @@ void FreeGame::end()
}
int FreeGame::pass(const string &iToChange, int n)
int FreeGame::pass(const wstring &iToChange, int n)
{
if (m_finished)
return 3;
@ -204,7 +205,7 @@ int FreeGame::pass(const string &iToChange, int n)
vector<Tile> tilesVect;
for (unsigned int i = 0; i < iToChange.size(); i++)
{
Tile tile(toupper(iToChange[i]));
Tile tile(towupper(iToChange[i]));
tilesVect.push_back(tile);
}

View file

@ -24,6 +24,7 @@
#include "tile.h"
using std::string;
using std::wstring;
using std::vector;
@ -49,9 +50,9 @@ public:
*************************/
virtual int start();
virtual int setRackRandom(int, bool, set_rack_mode);
virtual int play(const string &iCoord, const string &iWord);
virtual int play(const wstring &iCoord, const wstring &iWord);
virtual int endTurn();
int pass(const string &iToChange, int n);
int pass(const wstring &iToChange, int n);
private:
// Private constructor and destructor to force using the GameFactory class

View file

@ -30,6 +30,7 @@
#include "game.h"
#include "game_factory.h"
#include "turn.h"
#include "encoding.h"
#include "debug.h"
@ -156,8 +157,8 @@ int Game::back(int n)
if (n < 0)
{
debug("Game::back negative argument\n");
n = -n;
debug("Game::back negative argument\n");
n = -n;
}
debug("Game::back %d\n",n);
for (i = 0; i < n; i++)
@ -167,7 +168,8 @@ int Game::back(int n)
prevPlayer();
player = m_players[m_currPlayer];
const Round &lastround = m_history.getPreviousTurn().getRound();
debug("Game::back last round %s\n",lastround.toString().c_str());
debug("Game::back last round %s\n",
convertToMb(lastround.toString()).c_str());
/* Remove the word from the board, and put its letters back
* into the bag */
m_board.removeRound(*m_dic, lastround);
@ -184,8 +186,8 @@ int Game::back(int n)
/* Remove the points of this round */
player->addPoints(- lastround.getPoints());
m_points -= lastround.getPoints();
/* Remove the turns */
player->removeLastTurn();
/* Remove the turns */
player->removeLastTurn();
m_history.removeLastTurn();
}
else
@ -411,7 +413,7 @@ bool Game::rackInBag(const Rack &iRack, const Bag &iBag) const
/**
* Set the rack of the player p manually.
*/
int Game::helperSetRackManual(int p, bool iCheck, const string &iLetters)
int Game::helperSetRackManual(int p, bool iCheck, const wstring &iLetters)
{
int min, ret;
@ -513,8 +515,8 @@ void Game::nextPlayer()
* 10: first word not horizontal
* 11: first word not covering the H8 square
*/
int Game::checkPlayedWord(const string &iCoord,
const string &iWord, Round &oRound)
int Game::checkPlayedWord(const wstring &iCoord,
const wstring &iWord, Round &oRound)
{
ASSERT(getNPlayers() != 0, "Expected at least one player");

View file

@ -143,7 +143,7 @@ public:
*************************/
static const int RACK_SIZE;
enum set_rack_mode {RACK_ALL, RACK_NEW, RACK_MANUAL};
int setRack(int player, set_rack_mode mode, bool check, const string& str);
int setRack(int player, set_rack_mode mode, bool check, const wstring& str);
/**
* Methods to access already played words.
@ -166,7 +166,7 @@ public:
* Game handling
*/
virtual int start() = 0;
virtual int play(const string &iCoord, const string &iWord) = 0;
virtual int play(const wstring &iCoord, const wstring &iWord) = 0;
virtual int endTurn() = 0;
protected:
@ -206,14 +206,14 @@ protected:
int helperPlayRound(const Round &iRound);
int helperSetRackRandom(int p, bool iCheck, set_rack_mode mode);
int helperSetRackManual(int p, bool iCheck, const string &iLetters);
int helperSetRackManual(int p, bool iCheck, const wstring &iLetters);
void prevPlayer();
void nextPlayer();
bool rackInBag(const Rack &iRack, const Bag &iBag) const;
void realBag(Bag &iBag) const;
int checkPlayedWord(const string &iCoord,
const string &iWord, Round &oRound);
int checkPlayedWord(const wstring &iCoord,
const wstring &iWord, Round &oRound);
/**
* load games from File using the first format.

View file

@ -31,6 +31,7 @@
#include "player.h"
#include "game.h"
#include "game_factory.h"
#include "encoding.h"
#include "debug.h"
using namespace std;
@ -78,16 +79,16 @@ Game * Game::load(FILE *fin, const Dictionary& iDic)
}
if ((token = strtok(NULL, delim)) == NULL)
{
debug("Game_io::loading file format 1.4\n");
return Game::gameLoadFormat_14(fin,iDic);
}
{
debug("Game_io::loading file format 1.4\n");
return Game::gameLoadFormat_14(fin,iDic);
}
if (string(token) == string(IDENT_FORMAT_15))
{
debug("Game_io::loading file format 1.5\n");
return Game::gameLoadFormat_15(fin,iDic);
}
{
debug("Game_io::loading file format 1.5\n");
return Game::gameLoadFormat_15(fin,iDic);
}
debug("Game::load unknown format %s\n",token);
return NULL;
@ -109,65 +110,66 @@ Game* Game::gameLoadFormat_14(FILE *fin, const Dictionary& iDic)
pGame = GameFactory::Instance()->createTraining(iDic);
pGame->start();
/* rack word ?bonus pts coord */
/* EUOFMIE FUMEE * 26 H 4 */
/* read all turns until total */
while(fgets(buff,sizeof(buff),fin))
while (fgets(buff, sizeof(buff), fin))
{
token = strtok(buff,delim);
token = strtok(buff, delim);
if (token != NULL)
{
if (strcmp(token,"total")==0)
if (strcmp(token, "total") == 0)
{
break;
}
/* rack */
strncpy(rack,token,sizeof(rack));
((Training*)pGame)->setRack(RACK_MANUAL,false,string(rack));
debug("%s ",rack);
strncpy(rack, token, sizeof(rack));
static_cast<Training*>(pGame)->setRack(RACK_MANUAL, false,
convertToWc(rack));
debug("%s ", rack);
/* word */
token = strtok(NULL,delim);
if (!token || strcmp(token,"total")==0)
token = strtok(NULL, delim);
if (!token || strcmp(token, "total") == 0)
{
break;
}
strncpy(word,token,sizeof(word));
debug("\t%s ",word);
strncpy(word, token, sizeof(word));
debug("\t%s ", word);
/* bonus */
if ((token = strtok(NULL,delim)) == NULL)
if ((token = strtok(NULL, delim)) == NULL)
break;
/* points */
if (token[0]=='*')
if (token[0] == '*')
{
debug("%s\t",token);
if ((token = strtok(NULL,delim)) == NULL)
debug("%s\t", token);
if ((token = strtok(NULL, delim)) == NULL)
break;
}
/* pos 1 */
if ((token = strtok(NULL,delim)) == NULL)
if ((token = strtok(NULL, delim)) == NULL)
break;
debug("(%s ",token);
strncpy(pos,token,sizeof(pos));
debug("(%s ", token);
strncpy(pos, token, sizeof(pos));
/* pos 2 */
if ((token = strtok(NULL,delim)) == NULL)
if ((token = strtok(NULL, delim)) == NULL)
break;
debug("%s)",token);
strncat(pos,token,sizeof(pos));
debug("%s\n",pos);
debug("%s)", token);
strncat(pos, token, sizeof(pos));
debug("%s\n", pos);
debug(" play %s %s\n",pos, word);
pGame->play(string(pos),string(word));
debug(" play %s %s\n", pos, word);
pGame->play(convertToWc(pos), convertToWc(word));
}
}
return pGame;
@ -263,7 +265,7 @@ Game* Game::gameLoadFormat_15(FILE *fin, const Dictionary& iDic)
{
debug(" add Computer player\n");
pGame->addAIPlayer();
}
}
}
else
{
@ -312,101 +314,101 @@ Game* Game::gameLoadFormat_15(FILE *fin, const Dictionary& iDic)
char bonus = 0;
int res = sscanf(buff, " %2d | %8s | %s | %3s | %3d | %1d | %c",
&num, rack, word, ref, &pts, &player, &bonus);
debug(" -- line %s",buff);
if (res < 6)
{
debug(" Game::load15 invalid line -%s-\n",buff);
continue;
}
{
debug(" Game::load15 invalid line -%s-\n",buff);
continue;
}
debug(" %2d | %8s | %s | %3s | %3d | %1d | %c \n",
num, rack, word, ref, pts, player, bonus);
// Integrity checks
// TODO: add more checks
if (pts < 0)
{
debug(" Game::load15 line -%s- points < 0 ?\n",buff);
continue;
}
{
debug(" Game::load15 line -%s- points < 0 ?\n",buff);
continue;
}
if (player < 0 || player > pGame->getNPlayers())
{
debug(" Game::load15 line -%s- too much player (%d>%d)",buff,player,pGame->getNPlayers());
continue;
}
{
debug(" Game::load15 line -%s- too much player (%d>%d)",buff,player,pGame->getNPlayers());
continue;
}
if (bonus && bonus != '*')
{
debug(" Game::load15 line -%s- wring bonus sign\n",buff);
continue;
}
{
debug(" Game::load15 line -%s- wring bonus sign\n",buff);
continue;
}
// Build a rack for the correct player
PlayedRack pldrack;
if ((res = pldrack.setManual(string(rack))) > 0)
if ((res = pldrack.setManual(convertToWc(rack))) > 0)
{
debug(" Game::load15 set rack manual returned with error %d\n",res);
}
debug(" history rack %s\n",pldrack.toString().c_str());
debug(" history rack %s\n", convertToMb(pldrack.toString()).c_str());
// Build a round
Round round;
round.setPoints(pts);
if (bonus == '*')
round.setBonus(1);
if (isalpha(ref[0]))
{
// Horizontal word
round.accessCoord().setDir(Coord::HORIZONTAL);
round.accessCoord().setRow(ref[0] - 'A' + 1);
round.accessCoord().setCol(atoi(ref + 1));
for (unsigned int i = 0; i < strlen(word); i++)
{
// Horizontal word
round.accessCoord().setDir(Coord::HORIZONTAL);
round.accessCoord().setRow(ref[0] - 'A' + 1);
round.accessCoord().setCol(atoi(ref + 1));
for (unsigned int i = 0; i < strlen(word); i++)
{
tile = Tile(word[i]);
if (!pGame->m_board.getTile(round.getCoord().getRow(), round.getCoord().getCol() + i).isEmpty())
{
round.addRightFromBoard(tile);
}
else
{
round.addRightFromRack(tile, islower(word[i]));
pGame->m_bag.takeTile((islower(word[i])) ? Tile::Joker() : tile);
}
}
tile = Tile(word[i]);
if (!pGame->m_board.getTile(round.getCoord().getRow(), round.getCoord().getCol() + i).isEmpty())
{
round.addRightFromBoard(tile);
}
else
{
round.addRightFromRack(tile, islower(word[i]));
pGame->m_bag.takeTile((islower(word[i])) ? Tile::Joker() : tile);
}
}
}
else
{
// Vertical word
round.accessCoord().setDir(Coord::VERTICAL);
round.accessCoord().setRow(ref[strlen(ref) - 1] - 'A' + 1);
round.accessCoord().setCol(atoi(ref));
for (unsigned int i = 0; i < strlen(word); i++)
{
// Vertical word
round.accessCoord().setDir(Coord::VERTICAL);
round.accessCoord().setRow(ref[strlen(ref) - 1] - 'A' + 1);
round.accessCoord().setCol(atoi(ref));
for (unsigned int i = 0; i < strlen(word); i++)
{
tile = Tile(word[i]);
if (!pGame->m_board.getTile(round.getCoord().getRow() + i, round.getCoord().getCol()).isEmpty())
{
round.addRightFromBoard(tile);
}
else
{
round.addRightFromRack(tile, islower(word[i]));
pGame->m_bag.takeTile((islower(word[i])) ? Tile::Joker() : tile);
}
}
tile = Tile(word[i]);
if (!pGame->m_board.getTile(round.getCoord().getRow() + i, round.getCoord().getCol()).isEmpty())
{
round.addRightFromBoard(tile);
}
else
{
round.addRightFromRack(tile, islower(word[i]));
pGame->m_bag.takeTile((islower(word[i])) ? Tile::Joker() : tile);
}
}
}
// pGame->m_currPlayer = player;
// // Update the rack for the player
// pGame->m_players[player]->setCurrentRack(pldrack);
// // End the turn for the current player (this creates a new rack)
// pGame->m_players[player]->endTurn(round,num - 1);
// Play the round
pGame->helperPlayRound(round);
}
@ -425,15 +427,15 @@ Game* Game::gameLoadFormat_15(FILE *fin, const Dictionary& iDic)
{
// Create the played rack
PlayedRack pldrack;
pldrack.setManual(string(letters));
pldrack.setManual(convertToWc(letters));
// Give the rack to the player
pGame->m_players[nb]->setCurrentRack(pldrack);
}
// Read next line
// continue;
}
// Finalize the game
if (pGame)
{
@ -461,13 +463,13 @@ Game* Game::gameLoadFormat_15(FILE *fin, const Dictionary& iDic)
void Game::save(ostream &out, game_file_format format) const
{
if (getMode() == kTRAINING && format == FILE_FORMAT_STANDARD)
{
gameSaveFormat_14(out);
}
{
gameSaveFormat_14(out);
}
else
{
gameSaveFormat_15(out);
}
{
gameSaveFormat_15(out);
}
}
@ -479,25 +481,25 @@ void Game::gameSaveFormat_14(ostream &out) const
out << IDENT_STRING << endl << endl;
for(i = 0; i < m_history.getSize(); i++)
{
const Turn& turn = m_history.getTurn(i);
string rack = turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA);
string word = turn.getRound().getWord();
string coord = turn.getRound().getCoord().toString(Coord::COORD_MODE_LONG);
{
const Turn& turn = m_history.getTurn(i);
string rack = convertToMb(turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA));
string word = convertToMb(turn.getRound().getWord());
string coord = convertToMb(turn.getRound().getCoord().toString(Coord::COORD_MODE_LONG));
// rack [space] word [space] bonus points coord
sprintf(line,"%s%s%s%s%c%4d %s",
rack.c_str(),
string(12 - rack.size(), ' ').c_str(),
word.c_str(),
string(16 - word.size(), ' ').c_str(),
turn.getRound().getBonus() ? '*' : ' ',
turn.getRound().getPoints(),
coord.c_str()
);
// rack [space] word [space] bonus points coord
sprintf(line,"%s%s%s%s%c%4d %s",
rack.c_str(),
string(12 - rack.size(), ' ').c_str(),
word.c_str(),
string(16 - word.size(), ' ').c_str(),
turn.getRound().getBonus() ? '*' : ' ',
turn.getRound().getPoints(),
coord.c_str()
);
out << decal << line << endl;
}
out << decal << line << endl;
}
out << endl;
out << decal << "total" << string(24,' ');
@ -532,18 +534,19 @@ void Game::gameSaveFormat_15(ostream &out) const
// Print the game itself
for (int i = 0; i < m_history.getSize(); i++)
{
const Turn& turn = m_history.getTurn(i);
string word = turn.getRound().getWord();
string coord = turn.getRound().getCoord().toString();
const Turn& turn = m_history.getTurn(i);
string rack = convertToMb(turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA));
string word = convertToMb(turn.getRound().getWord());
string coord = convertToMb(turn.getRound().getCoord().toString());
sprintf(line, "%2d | %8s | %s%s | %3s | %3d | %1d | %c",
i + 1,
turn.getPlayedRack().toString().c_str(), /* pldrack */
word.c_str(), /* word */
rack.c_str(), /* pldrack */
word.c_str(), /* word */
string(15 - word.size(), ' ').c_str(), /* fill spaces */
coord.c_str(), /* coord */
turn.getRound().getPoints(),
turn.getRound().getPoints(),
turn.getPlayer(),
turn.getRound().getBonus() ? '*' : ' ');
turn.getRound().getBonus() ? '*' : ' ');
out << decal << line << endl;
}
@ -566,8 +569,8 @@ void Game::gameSaveFormat_15(ostream &out) const
out << endl;
for (int i = 0; i < getNPlayers(); i++)
{
string rack = m_players[i]->getCurrentRack().toString();
out << "Rack " << i << ": " << rack << endl;
wstring rack = m_players[i]->getCurrentRack().toString();
out << "Rack " << i << ": " << convertToMb(rack) << endl;
}
}

View file

@ -29,8 +29,10 @@
#include "pldrack.h"
#include "round.h"
#include "turn.h"
#include "debug.h"
#include "history.h"
#include "encoding.h"
#include "debug.h"
/* ******************************************************** */
/* ******************************************************** */
@ -154,19 +156,18 @@ void History::removeLastTurn()
}
string History::toString() const
wstring History::toString() const
{
unsigned int i;
string rs = "";
wstring rs;
#ifdef DEBUG
char buff[20];
sprintf(buff,"%d",m_history.size());
rs = "history size = " + string(buff) + "\n\n";
wchar_t buff[5];
_swprintf(buff, 4, L"%ld", m_history.size());
rs = L"history size = " + wstring(buff) + L"\n\n";
#endif
for (i = 0; i < m_history.size(); i++)
for (unsigned int i = 0; i < m_history.size(); i++)
{
Turn *t = m_history[i];
rs += t->toString() + string("\n");
rs += t->toString() + L"\n";
}
return rs;
}

View file

@ -30,14 +30,13 @@
#include <string>
#include <vector>
using std::string;
using std::wstring;
using std::vector;
class Round;
class Turn;
class PlayedRack;
/**
* History stores all the turns that have been played
* This class is used many times in the game
@ -89,7 +88,7 @@ class History
void removeLastTurn();
/// String handling
string toString() const;
wstring toString() const;
private:
vector<Turn*> m_history;

View file

@ -26,6 +26,7 @@
#include "player.h"
#include "turn.h"
#include "history.h"
#include "encoding.h"
#include "debug.h"
@ -76,17 +77,16 @@ void Player::removeLastTurn()
m_history.removeLastTurn();
}
const string Player::toString() const
wstring Player::toString() const
{
char buff[20];
string res;
wstring res;
sprintf(buff,"Player %d\n",m_id);
res = string(buff);
res += m_history.toString();
res += "\n";
sprintf(buff,"score %d\n",m_score);
res += string(buff);
wchar_t buff[6];
_swprintf(buff, 5, L"Player %d\n", m_id);
res = wstring(buff);
res += m_history.toString() + L"\n";
_swprintf(buff, 5, L"score %d\n", m_score);
res += wstring(buff);
return res;
}

View file

@ -69,7 +69,7 @@ public:
// A new rack is created with the remaining letters
void endTurn(const Round &iRound, int iTurn);
const string toString() const;
wstring toString() const;
private:
/// ID of the player

View file

@ -147,7 +147,7 @@ void PlayedRack::setNew(const Rack &iRack)
}
}
int PlayedRack::setManual(const string& iLetters)
int PlayedRack::setManual(const wstring& iLetters)
{
unsigned int i;
reset();
@ -157,17 +157,17 @@ int PlayedRack::setManual(const string& iLetters)
return 0; /* empty is ok */
}
for (i = 0; i < iLetters.size() && iLetters[i] != '+'; i++)
for (i = 0; i < iLetters.size() && iLetters[i] != L'+'; i++)
{
Tile tile(iLetters[i]);
if (tile.isEmpty())
{
return 1; /* */
return 1; /* */
}
addOld(tile);
}
if (i < iLetters.size() && iLetters[i] == '+')
if (i < iLetters.size() && iLetters[i] == L'+')
{
for (i++; i < iLetters.size(); i++)
{
@ -210,33 +210,33 @@ void PlayedRack::operator=(const PlayedRack &iOther)
}
string PlayedRack::toString(display_mode mode) const
wstring PlayedRack::toString(display_mode mode) const
{
string s("");
wstring s;
vector<Tile>::const_iterator it;
if (nOld() > 0)
{
for (it = m_oldTiles.begin(); it != m_oldTiles.end(); it++)
s += it->toChar();
for (it = m_oldTiles.begin(); it != m_oldTiles.end(); it++)
s += it->toChar();
}
if (mode > RACK_SIMPLE && nOld() > 0 && nNew() > 0)
{
s += "+";
s += L"+";
}
if (mode > RACK_EXTRA && reject)
{
s += "-";
// nouveau tirage : rejet
// pas après un scrabble
s += L"-";
// new rack: reject
// not after a scrabble
}
if (nNew() > 0)
{
for (it = m_newTiles.begin(); it != m_newTiles.end(); it++)
s += it->toChar();
for (it = m_newTiles.begin(); it != m_newTiles.end(); it++)
s += it->toChar();
}
return s;

View file

@ -58,7 +58,7 @@ public:
void setOld(const Rack &iRack);
void setNew(const Rack &iRack);
int setManual(const string& iLetters);
int setManual(const wstring& iLetters);
int nTiles() const { return nNew() + nOld(); }
int nNew() const { return m_newTiles.size(); }
@ -74,12 +74,13 @@ public:
void operator=(const PlayedRack &iOther);
typedef enum {
RACK_SIMPLE,
RACK_EXTRA,
RACK_DEBUG
} display_mode;
string toString(display_mode iShowExtraSigns = RACK_EXTRA) const;
enum display_mode
{
RACK_SIMPLE,
RACK_EXTRA,
RACK_DEBUG
};
wstring toString(display_mode iShowExtraSigns = RACK_EXTRA) const;
private:
bool reject;

View file

@ -26,35 +26,61 @@
*/
#include "rack.h"
#include "encoding.h"
#include "debug.h"
// FIXME: should not be here (duplicated from tile.cpp)
#define TILES_NUMBER 28
#define MIN_CODE 1
Rack::Rack()
: m_tiles(TILES_NUMBER, 0), m_ntiles(0)
{
}
void Rack::remove(const Tile &t)
{
multiset<Tile>::const_iterator it = m_tiles.find(t);
if (it != m_tiles.end())
m_tiles.erase(it);
ASSERT(in(t),
"The rack does not contain the letter " + convertToMb(t.toChar()));
m_tiles[t.toCode()]--;
m_ntiles--;
}
void Rack::clear()
{
for (unsigned int i = 0; i < m_tiles.size(); i++)
{
m_tiles[i] = 0;
}
m_ntiles = 0;
}
void Rack::getTiles(list<Tile> &oTiles) const
{
multiset<Tile>::const_iterator it;
for (it = m_tiles.begin(); it != m_tiles.end(); it++)
for (unsigned int i = MIN_CODE; i < m_tiles.size(); i++)
{
oTiles.push_back(*it);
for (unsigned int j = 0; j < m_tiles[i]; j++)
{
oTiles.push_back(Tile::GetTileFromCode(i));
}
}
}
string Rack::toString()
wstring Rack::toString()
{
string rs("");
multiset<Tile>::const_iterator it;
for (it = m_tiles.begin(); it != m_tiles.end(); it++)
wstring rs;
for (unsigned int i = MIN_CODE; i < m_tiles.size(); i++)
{
rs += it->toChar();
for (unsigned int j = 0; j < m_tiles[i]; j++)
{
rs += Tile::GetTileFromCode(i).toChar();
}
}
return rs;
return rs;
}
/// Local Variables:

View file

@ -43,22 +43,24 @@ using namespace std;
class Rack
{
public:
Rack() {}
Rack();
virtual ~Rack() {}
int nTiles() const { return m_tiles.size(); }
int nTiles() const { return m_ntiles; }
bool isEmpty() const { return nTiles() == 0; }
unsigned int in(const Tile &t) const { return m_tiles.count(t); }
void add(const Tile &t) { m_tiles.insert(t); }
unsigned int in(const Tile &t) const { return m_tiles[t.toCode()]; }
void add(const Tile &t) { m_tiles[t.toCode()]++; m_ntiles++; }
void remove(const Tile &t);
void clear() { m_tiles.clear(); }
void clear();
void getTiles(list<Tile> &oTiles) const;
string toString();
wstring toString();
private:
multiset<Tile> m_tiles;
/// Vector indexed by tile codes, containing the number of tiles
vector<unsigned int> m_tiles;
int m_ntiles;
};
#endif

View file

@ -19,8 +19,10 @@
*****************************************************************************/
#include <string>
#include <wctype.h>
#include "tile.h"
#include "round.h"
#include "encoding.h"
#define FROMBOARD 0x1
@ -141,34 +143,34 @@ void Round::removeRightToRack(Tile c, bool iJoker)
m_tileOrigin.pop_back();
}
string Round::getWord() const
wstring Round::getWord() const
{
char c;
string s;
wchar_t c;
wstring s;
for (int i = 0; i < getWordLen(); i++)
for (int i = 0; i < getWordLen(); i++)
{
c = getTile(i).toChar();
if (isJoker(i))
c = tolower(c);
s += c;
c = getTile(i).toChar();
if (isJoker(i))
c = towlower(c);
s += c;
}
return s;
return s;
}
string Round::toString() const
wstring Round::toString() const
{
char buff[5];
string rs(" ");
wstring rs = L" ";
if (getWord().size() > 0)
{
rs = getWord();
rs += string(16 - getWord().size(), ' ');
rs += getBonus() ? '*' : ' ';
sprintf(buff,"%4d",getPoints());
rs += wstring(16 - getWord().size(), ' ');
rs += getBonus() ? L'*' : L' ';
wchar_t buff[5];
_swprintf(buff, 4, L"%d", getPoints());
rs += buff;
rs += " " + getCoord().toString();
rs += L" " + getCoord().toString();
}
return rs;

View file

@ -70,19 +70,20 @@ public:
bool isJoker (int iIndex) const;
bool isPlayedFromRack(int iIndex) const;
const Tile& getTile (int iIndex) const;
string getWord() const;
int getWordLen() const;
int getPoints() const { return m_points; }
int getBonus() const { return m_bonus; }
wstring getWord() const;
int getWordLen() const;
int getPoints() const { return m_points; }
int getBonus() const { return m_bonus; }
/*************************
* Coordinates
*************************/
const Coord& getCoord() const { return m_coord; }
Coord& accessCoord() { return m_coord; }
string toString() const;
wstring toString() const;
private:
vector<Tile> m_word;

View file

@ -18,7 +18,8 @@
*****************************************************************************/
#include "tile.h"
#include <ctype.h>
#include <wctype.h>
/*************************
* French tiles
@ -66,30 +67,35 @@ const unsigned int Tiles_points[TILES_NUMBER] =
/***************************
***************************/
list<Tile> Tile::m_tilesList;
const Tile Tile::m_TheJoker(TILE_JOKER);
const Tile Tile::m_TheDummy(0);
list<Tile> Tile::m_tilesList;
vector<Tile> Tile::m_tilesVect(TILES_NUMBER, Tile::dummy());
bool Tile::m_vectInitialized(false);
Tile::Tile(char c)
Tile::Tile(wchar_t c)
{
if (c == TILE_JOKER)
{
m_joker = true;
m_dummy = false;
m_char = TILE_JOKER;
m_code = 27;
}
else if (isalpha(c))
{
m_joker = islower(c);
m_dummy = false;
m_char = toupper(c);
m_char = towupper(c);
m_code = m_char - 'A' + 1;
}
else
{
m_joker = false;
m_dummy = true;
m_char = 0;
m_code = 0;
}
}
@ -147,27 +153,37 @@ const list<Tile>& Tile::getAllTiles()
}
char Tile::toChar() const
const Tile& Tile::GetTileFromCode(unsigned int iCode)
{
if (!m_vectInitialized)
{
// XXX: this should be filled from a "language file" instead
for (char i = TILE_IDX_START; i <= TILE_IDX_END; i++)
Tile::m_tilesVect[i] = Tile(i + 'A' - TILE_IDX_START);
m_tilesVect[TILE_IDX_JOKER] = Tile::Joker();
m_vectInitialized = true;
}
return Tile::m_tilesVect[iCode];
}
wchar_t Tile::toChar() const
{
if (m_dummy)
return TILE_DUMMY;
if (m_joker)
{
if (isalpha(m_char))
return tolower(m_char);
if (iswalpha(m_char))
return towlower(m_char);
else
return TILE_JOKER;
}
return m_char;
}
int Tile::toCode() const
unsigned int Tile::toCode() const
{
if (m_dummy)
return TILE_IDX_DUMMY;
if (m_joker)
return TILE_IDX_DUMMY;
return (TILE_IDX_START + m_char - TILE_START);
return m_code;
}
bool Tile::operator <(const Tile &iOther) const

View file

@ -21,9 +21,11 @@
#define _TILE_H_
#include <list>
#include <vector>
using namespace std;
/*************************
* A Tile is the internal representation
* used within the game library to
@ -39,7 +41,7 @@ public:
// - we need to pay attention when inserting character taken
// from user input
Tile(char c = 0);
Tile(wchar_t c = 0);
virtual ~Tile() {}
bool isEmpty() const { return m_dummy; }
@ -48,28 +50,39 @@ public:
bool isConsonant() const;
unsigned int maxNumber() const;
unsigned int getPoints() const;
char toChar() const;
int toCode() const;
wchar_t toChar() const;
unsigned int toCode() const;
static const Tile &dummy() { return m_TheDummy; }
static const Tile &Joker() { return m_TheJoker; }
static const list<Tile>& getAllTiles();
static const Tile &GetTileFromCode(unsigned int iCode);
bool operator <(const Tile &iOther) const;
bool operator ==(const Tile &iOther) const;
bool operator !=(const Tile &iOther) const;
private:
char m_char;
wchar_t m_char;
bool m_joker;
bool m_dummy;
/**
* Internal code, used in the dictionary to represent the letter.
* It is mainly used by the Cross class.
*/
int m_code;
// Special tiles are declared static
static const Tile m_TheJoker;
static const Tile m_TheDummy;
// List of available tiles
/// List of available tiles
static list<Tile> m_tilesList;
/// Vector of tiles indexed by their code, for fast look-up
static vector<Tile> m_tilesVect;
/// True when m_tilesVect is correctly initialized
static bool m_vectInitialized;
};
#endif

View file

@ -25,6 +25,7 @@
#include "pldrack.h"
#include "player.h"
#include "training.h"
#include "encoding.h"
#include "debug.h"
@ -58,21 +59,21 @@ int Training::setRackRandom(bool iCheck, set_rack_mode mode)
return res;
}
int Training::setRackManual(bool iCheck, const string &iLetters)
int Training::setRackManual(bool iCheck, const wstring &iLetters)
{
int res;
int p = m_currPlayer;
string::iterator it;
string uLetters; // uppercase letters
wstring::iterator it;
wstring uLetters; // uppercase letters
// letters can be lowercase or uppercase as they are
// coming from user input. We do not consider a lowercase
// letter to be a joker which has been assigned to a letter.
m_results.clear();
uLetters = iLetters;
for(it = uLetters.begin(); it != uLetters.end(); it ++)
{
*it = toupper(*it);
}
for (it = uLetters.begin(); it != uLetters.end(); it ++)
{
*it = towupper(*it);
}
res = helperSetRackManual(p, iCheck, uLetters);
// 0 : ok
// 1 : not enough tiles
@ -80,25 +81,25 @@ int Training::setRackManual(bool iCheck, const string &iLetters)
return res;
}
int Training::setRack(set_rack_mode iMode, bool iCheck, const string &iLetters)
int Training::setRack(set_rack_mode iMode, bool iCheck, const wstring &iLetters)
{
int res = 0;
switch(iMode)
{
case RACK_MANUAL:
res = setRackManual(iCheck, iLetters);
break;
case RACK_ALL:
res = setRackRandom(iCheck, iMode);
break;
case RACK_NEW:
res = setRackRandom(iCheck, iMode);
break;
}
{
case RACK_MANUAL:
res = setRackManual(iCheck, iLetters);
break;
case RACK_ALL:
res = setRackRandom(iCheck, iMode);
break;
case RACK_NEW:
res = setRackRandom(iCheck, iMode);
break;
}
return res;
}
int Training::play(const string &iCoord, const string &iWord)
int Training::play(const wstring &iCoord, const wstring &iWord)
{
/* Perform all the validity checks, and fill a round */
Round round;
@ -147,7 +148,7 @@ void Training::search()
// Search for the current player
Rack r;
m_players[m_currPlayer]->getCurrentRack().getRack(r);
debug("Training::search for %s\n",r.toString().c_str());
debug("Training::search for %s\n", convertToMb(r.toString()).c_str());
m_results.search(*m_dic, m_board, r, m_history.getSize());
}
@ -204,7 +205,7 @@ void Training::removeTestPlay()
m_testRound = Round();
}
std::string Training::getTestPlayWord() const
wstring Training::getTestPlayWord() const
{
return m_testRound.getWord();
}

View file

@ -27,6 +27,7 @@
#include "results.h"
using std::string;
using std::wstring;
/**
@ -47,14 +48,14 @@ public:
* Game handling
*************************/
virtual int start();
virtual int play(const string &iCoord, const string &iWord);
virtual int play(const wstring &iCoord, const wstring &iWord);
virtual int endTurn();
void search();
int playResult(int);
int setRackRandom(bool, set_rack_mode);
int setRackManual(bool iCheck, const string &iLetters);
int setRack(set_rack_mode iMode, bool iCheck, const string &iLetters);
int setRackManual(bool iCheck, const wstring &iLetters);
int setRack(set_rack_mode iMode, bool iCheck, const wstring &iLetters);
/*************************
* Override the default behaviour of these methods, because in training
@ -74,7 +75,7 @@ public:
/// Remove the temporary word(s)
void removeTestPlay();
/// Get the temporary word
string getTestPlayWord() const;
wstring getTestPlayWord() const;
private:
// Private constructor and destructor to force using the GameFactory class

View file

@ -54,14 +54,14 @@ void Turn::operator=(const Turn &iOther)
}
#endif
string Turn::toString(bool iShowExtraSigns) const
wstring Turn::toString(bool iShowExtraSigns) const
{
string rs = "";
wstring rs = L"";
if (iShowExtraSigns)
{
rs = ""; // TODO
// TODO
}
rs = rs + m_pldrack.toString() + " " + m_round.toString();
rs = rs + m_pldrack.toString() + L" " + m_round.toString();
return rs;
}

View file

@ -48,7 +48,7 @@ public:
#if 0
void operator=(const Turn &iOther);
#endif
string toString(bool iShowExtraSigns = false) const;
wstring toString(bool iShowExtraSigns = false) const;
private:
int m_num;

File diff suppressed because it is too large Load diff

View file

@ -20,11 +20,13 @@
#include <iomanip>
#include <string>
#include "stdlib.h"
#include "game_io.h"
#include "game.h"
#include "training.h"
#include "player.h"
#include "encoding.h"
using namespace std;
@ -124,7 +126,7 @@ void GameIO::printBoardMultipliers2(ostream &out, const Game &iGame)
out << " " << (char)(row - BOARD_MIN + 'A') << " ";
for (col = BOARD_MIN; col <= BOARD_MAX; col++)
{
char l = iGame.getBoard().getChar(row, col);
wchar_t l = iGame.getBoard().getChar(row, col);
int wm = iGame.getBoard().getWordMultiplier(row, col);
int tm = iGame.getBoard().getLetterMultiplier(row, col);
@ -134,7 +136,7 @@ void GameIO::printBoardMultipliers2(ostream &out, const Game &iGame)
out << " " << ((tm == 3) ? '*' : '+');
else
out << " -";
out << (l ? l : '-');
out << (l ? convertToMb(l) : "-");
}
out << endl;
}
@ -150,7 +152,7 @@ void GameIO::printNonPlayed(ostream &out, const Game &iGame)
{
if (iGame.getBag().in(it->toChar()) > 9)
out << " ";
out << setw(2) << it->toChar();
out << setw(2) << convertToMb(it->toChar());
}
out << endl;
@ -164,7 +166,7 @@ void GameIO::printNonPlayed(ostream &out, const Game &iGame)
void GameIO::printPlayedRack(ostream &out, const Game &iGame, int n)
{
out << iGame.getCurrentPlayer().getCurrentRack().toString(PlayedRack::RACK_SIMPLE) << endl;
out << convertToMb(iGame.getCurrentPlayer().getCurrentRack().toString(PlayedRack::RACK_SIMPLE)) << endl;
}
@ -173,7 +175,7 @@ void GameIO::printAllRacks(ostream &out, const Game &iGame)
for (int j = 0; j < iGame.getNPlayers(); j++)
{
out << "Joueur " << j << ": ";
out << iGame.getPlayer(j).getCurrentRack().toString(PlayedRack::RACK_SIMPLE) << endl;
out << convertToMb(iGame.getPlayer(j).getCurrentRack().toString(PlayedRack::RACK_SIMPLE)) << endl;
}
}
@ -182,13 +184,13 @@ static void searchResultLine(ostream &out, const Training &iGame, int num)
{
const Results &res = iGame.getResults();
Round r = res.get(num);
string word = r.getWord();
wstring word = r.getWord();
if (word.size() == 0)
return;
out << word << string(16 - word.size(), ' ')
out << convertToMb(word) << string(16 - word.size(), ' ')
<< (r.getBonus() ? '*' : ' ')
<< setw(4) << r.getPoints()
<< ' ' << r.getCoord().toString();
<< ' ' << convertToMb(r.getCoord().toString());
}

View file

@ -38,6 +38,7 @@
#include "player.h"
#include "history.h"
#include "turn.h"
#include "encoding.h"
using namespace std;
@ -199,9 +200,9 @@ void CursesIntf::drawScoresRacks(WINDOW *win, int y, int x) const
drawBox(win, y + yOff, x, m_game->getNPlayers() + 2, 25, _(" Racks "));
for (int i = 0; i < m_game->getNPlayers(); i++)
{
string rack = m_game->getPlayer(i).getCurrentRack().toString(PlayedRack::RACK_SIMPLE);
if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
attron(A_BOLD);
string rack = convertToMb(m_game->getPlayer(i).getCurrentRack().toString(PlayedRack::RACK_SIMPLE));
mvwprintw(win, y + yOff + i + 1, x + 2,
_("Player %d: %s"), i, rack.c_str());
if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
@ -212,7 +213,7 @@ void CursesIntf::drawScoresRacks(WINDOW *win, int y, int x) const
// Display a message when the search is complete
if (m_game->getMode() == Game::kTRAINING &&
static_cast<Training*>(m_game)->getHistory().getSize())
static_cast<Training*>(m_game)->getResults().size())
{
mvwprintw(win, y + 2*yOff - 1, x + 2, _("Search complete"));
}
@ -231,7 +232,7 @@ void CursesIntf::drawResults(WINDOW *win, int y, int x)
drawBox(win, y, x, h, 25, _(" Search results "));
m_boxY = y + 1;
m_boxLines = h - 2;
m_boxLinesData = tr_game->getHistory().getSize();
m_boxLinesData = tr_game->getResults().size();
int i;
const Results& res = tr_game->getResults();
@ -239,12 +240,12 @@ void CursesIntf::drawResults(WINDOW *win, int y, int x)
i < m_boxStart + m_boxLines; i++)
{
const Round &r = res.get(i);
string coord = r.getCoord().toString();
wstring coord = r.getCoord().toString();
boxPrint(win, i, x + 1, "%3d %s%s %3s",
r.getPoints(),
r.getWord().c_str(),
convertToMb(r.getWord()).c_str(),
string(h - 3 - r.getWordLen(), ' ').c_str(),
coord.c_str());
convertToMb(coord).c_str());
}
// Complete the list with empty lines, to avoid trails
for (; i < m_boxStart + m_boxLines; i++)
@ -275,12 +276,12 @@ void CursesIntf::drawHistory(WINDOW *win, int y, int x)
{
const Turn& t = m_game->getHistory().getTurn(i);
const Round& r = t.getRound();
string word = r.getWord();
string coord = r.getCoord().toString();
string word = convertToMb(r.getWord());
string coord = convertToMb(r.getCoord().toString());
boxPrint(win, i + 2, x + 2,
"%2d %8s %s%s %3s %3d %1d %c",
i + 1, t.getPlayedRack().toString().c_str(), word.c_str(),
string(15 - word.size(), ' ').c_str(),
i + 1, convertToMb(t.getPlayedRack().toString()).c_str(),
word.c_str(), string(15 - word.size(), ' ').c_str(),
coord.c_str(), r.getPoints(),
t.getPlayer(), r.getBonus() ? '*' : ' ');
}
@ -362,7 +363,7 @@ void CursesIntf::playWord(WINDOW *win, int y, int x)
if (readString(win, y + 1, x + xOff, 15, word) &&
readString(win, y + 2, x + xOff, 3, coord))
{
int res = m_game->play(coord, word);
int res = m_game->play(convertToWc(coord), convertToWc(word));
if (res)
{
drawStatus(win, LINES - 1, 0, _("Incorrect or misplaced word"));
@ -382,7 +383,7 @@ void CursesIntf::checkWord(WINDOW *win, int y, int x)
string word;
if (readString(win, y + 2, x + 2, 15, word))
{
int res = Dic_search_word(m_game->getDic(), word.c_str());
int res = Dic_search_word(m_game->getDic(), convertToWc(word).c_str());
char s[100];
if (res)
snprintf(s, 100, _("The word '%s' exists"), word.c_str());
@ -471,7 +472,7 @@ void CursesIntf::passTurn(WINDOW *win, int y, int x, FreeGame &iGame)
string letters;
if (readString(win, y + 2, x + 2, 7, letters))
{
int res = iGame.pass(letters, m_game->currPlayer());
int res = iGame.pass(convertToWc(letters), m_game->currPlayer());
if (res)
{
drawStatus(win, LINES - 1, 0, _("Cannot pass the turn"));
@ -491,7 +492,7 @@ void CursesIntf::setRack(WINDOW *win, int y, int x, Training &iGame)
string letters;
if (readString(win, y + 2, x + 2, 7, letters, kJOKER))
{
iGame.setRackManual(false, letters);
iGame.setRackManual(false, convertToWc(letters));
}
m_state = DEFAULT;
clearRect(win, y, x, 4, 32);
@ -718,7 +719,7 @@ int CursesIntf::handleKey(int iKey)
else
m_state = RESULTS;
m_boxStart = 0;
clear();
clearRect(m_win, 3, 54, 30, 25);
return 1;
// Toggle dots display

View file

@ -41,6 +41,7 @@
#include "training.h"
#include "player.h"
#include "game.h"
#include "encoding.h"
#include "configdb.h"
#include "auxframes.h"
@ -258,7 +259,7 @@ VerifFrame::verif()
result->SetLabel(wxT("pas de dictionnaire"));
return;
}
if (Dic_search_word(dic, word->GetValue().mb_str()))
if (Dic_search_word(dic, word->GetValue().wc_str()))
result->SetLabel(wxT("existe"));
else
result->SetLabel(wxT("n'existe pas"));
@ -294,7 +295,7 @@ AuxFrameList::AuxFrameList(wxFrame* parent, int _id, wxString _name, wxString _c
{
game = g;
savedword = "";
savedword = L"";
wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);
listbox = new wxListBox(this, ListBoxID);
@ -380,20 +381,19 @@ AuxFrameList::Refresh(refresh_t force)
void
Plus1Frame::refresh()
{
std::string rack;
//debug(" Plus1Frame::refresh start\n");
rack = game->getCurrentPlayer().getCurrentRack().toString();
std::wstring rack = game->getCurrentPlayer().getCurrentRack().toString();
//debug(" CurrentPlayer -> rack : %s\n",rack.c_str());
if (savedword == rack)
{
noresult = false; // keep old results
//debug(" Plus1Frame::refresh end, no change\n");
return;
}
{
noresult = false; // keep old results
//debug(" Plus1Frame::refresh end, no change\n");
return;
}
savedword = rack;
char buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX];
wchar_t buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX];
Dic_search_7pl1(game->getDic(), rack.c_str(), buff, config.getJokerPlus1());
listbox->Clear();
@ -403,15 +403,15 @@ Plus1Frame::refresh()
for (int i = 0; i < DIC_LETTERS; i++)
{
if (i && buff[i][0][0])
{
res[resnum++] = wxString(wxT("+")) + (wxChar)(i + 'A' - 1);
noresult = false;
}
for (int j = 0; j < RES_7PL1_MAX && buff[i][j][0]; j++)
{
res[resnum++] = wxString(wxT(" ")) + wxU(buff[i][j]);
noresult = false;
}
{
res[resnum++] = wxString(wxT("+")) + (wxChar)(i + 'A' - 1);
noresult = false;
}
for (int j = 0; j < RES_7PL1_MAX && buff[i][j][0]; j++)
{
res[resnum++] = wxString(wxT(" ")) + wxU(buff[i][j]);
noresult = false;
}
}
listbox->Set(resnum, res);
//debug(" Plus1Frame::refresh end\n");
@ -424,30 +424,28 @@ Plus1Frame::refresh()
void
BenjFrame::refresh()
{
std::string word;
if (game->getMode() != Game::kTRAINING)
return;
return;
word = ((Training*)game)->getTestPlayWord();
std::wstring word = static_cast<Training*>(game)->getTestPlayWord();
if (savedword == word)
{
noresult = false; // keep old results
return;
}
{
noresult = false; // keep old results
return;
}
savedword = word;
//debug(" BenjFrame::refresh : %s\n",word.c_str());
char wordlist[RES_BENJ_MAX][DIC_WORD_MAX];
wchar_t wordlist[RES_BENJ_MAX][DIC_WORD_MAX];
Dic_search_Benj(game->getDic(), word.c_str(), wordlist);
wxString res[RES_BENJ_MAX];
int resnum = 0;
for (int i = 0; (i < RES_BENJ_MAX) && (wordlist[i][0]); i++)
{
res[resnum++] = wxU(wordlist[i]);
//debug(" BenjFrame : %s (%d)\n",wordlist[i],resnum);
noresult = false;
}
{
res[resnum++] = wxU(wordlist[i]);
//debug(" BenjFrame : %s (%d)\n",wordlist[i],resnum);
noresult = false;
}
listbox->Set(resnum, res);
}
@ -459,30 +457,28 @@ BenjFrame::refresh()
void
RaccFrame::refresh()
{
std::string word;
if (game->getMode() != Game::kTRAINING)
return;
return;
word = ((Training*)game)->getTestPlayWord();
std::wstring word = static_cast<Training*>(game)->getTestPlayWord();
if (savedword == word)
{
noresult = false; // keep old results
return;
}
{
noresult = false; // keep old results
return;
}
savedword = word;
//debug(" RaccFrame::refresh : %s\n",word.c_str());
char wordlist[RES_RACC_MAX][DIC_WORD_MAX];
wchar_t wordlist[RES_RACC_MAX][DIC_WORD_MAX];
Dic_search_Racc(game->getDic(), word.c_str(), wordlist);
wxString res[RES_RACC_MAX];
int resnum = 0;
for (int i = 0; (i < RES_RACC_MAX) && (wordlist[i][0]); i++)
{
res[resnum++] = wxU(wordlist[i]);
//debug(" RaccFrame : %s (%d)\n",wordlist[i],resnum);
noresult = false;
}
{
res[resnum++] = wxU(wordlist[i]);
//debug(" RaccFrame : %s (%d)\n",wordlist[i],resnum);
noresult = false;
}
listbox->Set(resnum, res);
}
@ -532,10 +528,10 @@ GameFrame::Refresh(refresh_t force)
#ifdef DEBUG
mos << std::string(30,'-') << std::endl;
mos << "Player History\n";
mos << m_game.getPlayer(0).toString();
mos << convertToMb(m_game.getPlayer(0).toString());
mos << std::string(30,'-') << std::endl;
mos << "Game History\n";
mos << m_game.getHistory().toString();
mos << convertToMb(m_game.getHistory().toString());
#endif
textbox->Clear();
textbox->AppendText( wxU( mos.str().c_str() ) );
@ -570,30 +566,30 @@ void
ResultFrame::Refresh(refresh_t WXUNUSED(force))
{
if (reslist != NULL)
{
reslist->Show(false);
//debug("ResultFrame refresh\n");
reslist->Refresh();
reslist->Show(true);
}
{
reslist->Show(false);
//debug("ResultFrame refresh\n");
reslist->Refresh();
reslist->Show(true);
}
}
void
ResultFrame::Search()
{
if (reslist != NULL)
{
reslist->Search();
}
{
reslist->Search();
}
}
int
ResultFrame::GetSelected()
{
if (reslist != NULL)
{
return reslist->GetSelected();
}
{
return reslist->GetSelected();
}
return -1;
}

View file

@ -78,12 +78,12 @@ protected:
ConfigDB config;
public:
AuxFrame (wxFrame*, int, wxString, wxString);
AuxFrame(wxFrame*, int, wxString, wxString);
~AuxFrame();
typedef enum {
REFRESH,
FORCE_REFRESH
REFRESH,
FORCE_REFRESH
} refresh_t;
void SwitchDisplay();
@ -99,7 +99,7 @@ class AuxFrameList: public AuxFrame
{
protected:
bool noresult;
string savedword;
wstring savedword;
Game *game;
wxButton *button;
wxListBox *listbox;

View file

@ -57,7 +57,7 @@ GfxResult::GfxResult(wxFrame *parent, MainFrame* _mf, Game* _game) :
{
mf = _mf;
game = _game;
savedrack = std::string("");
savedrack = L"";
results = new wxListCtrl(this, ListCtrl_ID);
#if defined(ENABLE_LC_NO_HEADER)
results->SetSingleStyle(wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL);
@ -99,7 +99,7 @@ void
GfxResult::SetGame(Game* g)
{
game = g;
savedrack = std::string("");
savedrack = L"";
results->DeleteAllItems();
}
@ -110,21 +110,21 @@ void
GfxResult::Refresh()
{
if (game == NULL)
return;
return;
debug(" GfxResult::Refresh : ");
std::string rack = game->getCurrentPlayer().getCurrentRack().toString();
std::wstring rack = game->getCurrentPlayer().getCurrentRack().toString();
if (savedrack != rack)
{
debug("changed (%s -> %s)",savedrack.c_str(),rack.c_str());
savedrack = rack;
results->DeleteAllItems();
}
{
debug("changed (%ls -> %ls)",savedrack.c_str(),rack.c_str());
savedrack = rack;
results->DeleteAllItems();
}
else
{
debug("unchanged");
}
{
debug("unchanged");
}
debug("\n");
}
@ -136,7 +136,7 @@ GfxResult::Search()
{
debug("GfxResult::Search()\n");
if (game == NULL)
return;
return;
((Training*)game)->search();
@ -146,21 +146,21 @@ GfxResult::Search()
const Results &res = ((Training*)game)->getResults();
debug(" GfxResult::Search size = %d\n",res.size());
for (int i = 0; i < res.size(); i++)
{
Round r = res.get(i);
//debug(" adding %s\n",r.toString().c_str());
wxString pts;
wxString word = wxU(r.getWord().c_str());
wxString coords = wxU(r.getCoord().toString().c_str());
wxChar bonus = r.getBonus() ? wxT('*') : wxT(' ');
pts << r.getPoints();
{
Round r = res.get(i);
//debug(" adding %s\n",r.toString().c_str());
wxString pts;
wxString word = wxU(r.getWord().c_str());
wxString coords = wxU(r.getCoord().toString().c_str());
wxChar bonus = r.getBonus() ? wxT('*') : wxT(' ');
pts << r.getPoints();
long tmp = results->InsertItem(i, word);
results->SetItemData(tmp, i);
tmp = results->SetItem(i, 1, bonus);
tmp = results->SetItem(i, 2, coords);
tmp = results->SetItem(i, 3, pts);
}
long tmp = results->InsertItem(i, word);
results->SetItemData(tmp, i);
tmp = results->SetItem(i, 1, bonus);
tmp = results->SetItem(i, 2, coords);
tmp = results->SetItem(i, 3, pts);
}
for (int i = 0; i < 4; i++)
results->SetColumnWidth(i, wxLIST_AUTOSIZE);
@ -168,10 +168,10 @@ GfxResult::Search()
//results->Show();
if (res.size() > 0)
{
results->SetItemState(0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED | wxLIST_MASK_STATE);
((Training*)game)->testPlay(0);
}
{
results->SetItemState(0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED | wxLIST_MASK_STATE);
((Training*)game)->testPlay(0);
}
}
/* ************************************************** */
@ -194,9 +194,9 @@ GfxResult::OnListCtrlSelected(wxListEvent& event)
{
//debug(" GfxResult::OnListCtrlSelected\n");
if (event.m_itemIndex > -1)
{
mf->TestPlay(event.m_itemIndex);
}
{
mf->TestPlay(event.m_itemIndex);
}
}
/* ************************************************** */
@ -207,10 +207,10 @@ GfxResult::OnListCtrlActivated(wxListEvent& event)
{
//debug(" GfxResult::OnListCtrlActivated");
if (event.m_itemIndex > -1)
{
mf->Play(1);
results->DeleteAllItems();
}
{
mf->Play(1);
results->DeleteAllItems();
}
}
/* ************************************************** */

View file

@ -27,18 +27,17 @@
#ifndef _RESLIST_H
#define _RESLIST_H
/**
*
*/
#include <string>
#include <wx/listctrl.h>
class MainFrame;
class GfxResult : public wxControl
{
private:
MainFrame *mf;
std::string savedrack;
std::wstring savedrack;
Game *game;
wxListCtrl *results;
ConfigDB config;

View file

@ -443,12 +443,12 @@ MainFrame::OnMenuGameOpen(wxCommandEvent&)
return;
}
std::string r = "";
std::wstring r;
if (m_game->getHistory().getSize() >= 0)
{
r = m_game->getCurrentPlayer().getCurrentRack().toString();
}
{
r = m_game->getCurrentPlayer().getCurrentRack().toString();
}
rack->SetValue(wxU(r.c_str()));
// update gfxboard and all frames
@ -962,13 +962,12 @@ void
MainFrame::SetRack(Game::set_rack_mode mode, wxString srack)
{
int res = 0;
std::string str;
wxString msg;
bool check = config.getRackChecking();
((Training*)m_game)->removeTestPlay();
str = (const char*)srack.mb_str();
res = ((Training*)m_game)->setRack(mode, check, str);
static_cast<Training*>(m_game)->removeTestPlay();
std::wstring str = srack.c_str();
res = static_cast<Training*>(m_game)->setRack(mode, check, str);
switch (res)
{
@ -993,8 +992,8 @@ MainFrame::SetRack(Game::set_rack_mode mode, wxString srack)
break;
}
std::string r = m_game->getCurrentPlayer().getCurrentRack().toString();
debug("MainFrame::SetRack : setvalue %s\n",r.c_str());
std::wstring r = m_game->getCurrentPlayer().getCurrentRack().toString();
debug("MainFrame::SetRack : setvalue %ls\n",r.c_str());
rack->SetValue(wxU(r.c_str()));
UpdateFrames();
UpdateStatusBar();

View file

@ -139,8 +139,8 @@ void
PCross::compute_enter(wxCommandEvent&)
{
int i;
char rack[DIC_WORD_MAX];
char buff[RES_CROS_MAX][DIC_WORD_MAX];
wchar_t rack[DIC_WORD_MAX];
wchar_t buff[RES_CROS_MAX][DIC_WORD_MAX];
if (!check_dic())
return;
@ -154,7 +154,7 @@ PCross::compute_enter(wxCommandEvent&)
return;
}
strncpy(rack, t->GetValue().mb_str(), DIC_WORD_MAX);
wcsncpy(rack, t->GetValue().wc_str(), DIC_WORD_MAX);
Dic_search_Cros(dic,rack,buff);
int resnum = 0;
@ -183,8 +183,8 @@ void
PPlus1::compute_enter(wxCommandEvent&)
{
int i,j;
char rack[DIC_WORD_MAX];
char buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX];
wchar_t rack[DIC_WORD_MAX];
wchar_t buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX];
if (!check_dic())
return;
@ -198,7 +198,7 @@ PPlus1::compute_enter(wxCommandEvent&)
return;
}
strncpy(rack, t->GetValue().mb_str(), DIC_WORD_MAX);
wcsncpy(rack, t->GetValue().wc_str(), DIC_WORD_MAX);
Dic_search_7pl1(dic,rack,buff,TRUE);
int resnum = 0;
@ -308,15 +308,15 @@ PRegExp::panel_options()
void
PRegExp::compute_enter(wxCommandEvent&)
{
char re[DIC_RE_MAX];
char buff[RES_REGE_MAX][DIC_WORD_MAX];
wchar_t re[DIC_RE_MAX];
wchar_t buff[RES_REGE_MAX][DIC_WORD_MAX];
if (!check_dic())
return;
build_letter_lists();
strncpy(re, t->GetValue().mb_str(),DIC_RE_MAX);
debug("PRegExp::compute_enter for %s",re);
wcsncpy(re, t->GetValue().wc_str(),DIC_RE_MAX);
debug("PRegExp::compute_enter for %ls",re);
int lmin = atoi((const char*)omin->GetValue().mb_str());
int lmax = atoi((const char*)omax->GetValue().mb_str());