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

10
TODO
View file

@ -3,14 +3,6 @@
* 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
file saving for freegames and duplicate need a serious
rewrite. We need to specifie a file format that can handle
@ -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,14 +71,12 @@ 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);
@ -85,6 +84,25 @@ Dic_search_word(const Dictionary dic, const char* word)
}
/**
* 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;
}
/**
* global variables for Dic_search_word_by_len :
*
@ -159,8 +177,8 @@ 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,
static void
Dic_search_7pl1_inner(const Dictionary dic, const char* rack,
char buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX],
int joker)
{
@ -235,11 +253,40 @@ 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,
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,12 +335,36 @@ 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,
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;
@ -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];
}
}
}
/****************************************/
/****************************************/
@ -380,9 +475,8 @@ Dic_search_cross_rec(struct params_cross_t *params,
}
void
Dic_search_Cros(const Dictionary dic, const char* mask,
static void
Dic_search_Cros_inner(const Dictionary dic, const char* mask,
char wordlist[RES_CROS_MAX][DIC_WORD_MAX])
{
int i;
@ -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];
}
}
}
/****************************************/
/****************************************/
@ -470,7 +589,7 @@ int regexpparse(yyscan_t scanner, NODE** root,
struct regexp_error_report_t *err);
void
Dic_search_RegE(const Dictionary dic, const char* re,
Dic_search_RegE_inner(const Dictionary dic, const char* re,
char wordlist[RES_REGE_MAX][DIC_WORD_MAX],
struct search_RegE_list_t *list)
{
@ -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,7 +79,7 @@ public:
#define ATTR_JOKER 1
#define ATTR_TEST 2
char getChar (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;

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();
@ -232,6 +238,20 @@ static void BoardSearchAux(const Board &iBoard,
!iTilesMx[row][col + 1].isEmpty() ||
!iTilesMx[row - 1][col].isEmpty() ||
!iTilesMx[row + 1][col].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++)
{
if (iCrossMx[row][col].check(*it))
{
match = true;
}
}
if (match)
{
if (!iTilesMx[row][col - 1].isEmpty())
{
@ -248,6 +268,7 @@ static void BoardSearchAux(const Board &iBoard,
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);
_swprintf(res, 7, L"%ls%ls", srow, scol);
else
sprintf(res,"%s%s",scol,srow);
_swprintf(res, 7, L"%ls%ls", scol, srow);
break;
case COORD_MODE_LONG:
if (getDir() == HORIZONTAL)
sprintf(res,"%2s %2s",srow,scol);
_swprintf(res, 7, L"%2ls %2ls", srow, scol);
else
sprintf(res,"%2s %2s",scol,srow);
_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 {
enum coord_mode_t
{
COORD_MODE_COMPACT,
COORD_MODE_LONG
} coord_mode_t;
string toString(coord_mode_t mode = COORD_MODE_COMPACT) const;
};
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"
@ -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);
@ -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;
@ -126,7 +127,8 @@ Game* Game::gameLoadFormat_14(FILE *fin, const Dictionary& iDic)
/* rack */
strncpy(rack, token, sizeof(rack));
((Training*)pGame)->setRack(RACK_MANUAL,false,string(rack));
static_cast<Training*>(pGame)->setRack(RACK_MANUAL, false,
convertToWc(rack));
debug("%s ", rack);
/* word */
@ -167,7 +169,7 @@ Game* Game::gameLoadFormat_14(FILE *fin, const Dictionary& iDic)
debug("%s\n", pos);
debug(" play %s %s\n", pos, word);
pGame->play(string(pos),string(word));
pGame->play(convertToWc(pos), convertToWc(word));
}
}
return pGame;
@ -344,11 +346,11 @@ Game* Game::gameLoadFormat_15(FILE *fin, const Dictionary& iDic)
// 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;
@ -425,7 +427,7 @@ 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);
}
@ -481,9 +483,9 @@ void Game::gameSaveFormat_14(ostream &out) const
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);
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",
@ -533,11 +535,12 @@ void Game::gameSaveFormat_15(ostream &out) const
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();
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 */
rack.c_str(), /* pldrack */
word.c_str(), /* word */
string(15 - word.size(), ' ').c_str(), /* fill spaces */
coord.c_str(), /* coord */
@ -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,7 +157,7 @@ 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())
@ -167,7 +167,7 @@ int PlayedRack::setManual(const string& iLetters)
addOld(tile);
}
if (i < iLetters.size() && iLetters[i] == '+')
if (i < iLetters.size() && iLetters[i] == L'+')
{
for (i++; i < iLetters.size(); i++)
{
@ -210,9 +210,9 @@ 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)
@ -223,14 +223,14 @@ string PlayedRack::toString(display_mode mode) const
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)

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 {
enum display_mode
{
RACK_SIMPLE,
RACK_EXTRA,
RACK_DEBUG
} display_mode;
string toString(display_mode iShowExtraSigns = RACK_EXTRA) const;
};
wstring toString(display_mode iShowExtraSigns = RACK_EXTRA) const;
private:
bool reject;

View file

@ -26,33 +26,59 @@
*/
#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;
}

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++)
{
c = getTile(i).toChar();
if (isJoker(i))
c = tolower(c);
c = towlower(c);
s += c;
}
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

@ -71,7 +71,7 @@ public:
bool isPlayedFromRack(int iIndex) const;
const Tile& getTile (int iIndex) const;
string getWord() const;
wstring getWord() const;
int getWordLen() const;
int getPoints() const { return m_points; }
int getBonus() const { return m_bonus; }
@ -82,7 +82,8 @@ public:
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,12 +59,12 @@ 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.
@ -71,7 +72,7 @@ int Training::setRackManual(bool iCheck, const string &iLetters)
uLetters = iLetters;
for (it = uLetters.begin(); it != uLetters.end(); it ++)
{
*it = toupper(*it);
*it = towupper(*it);
}
res = helperSetRackManual(p, iCheck, uLetters);
// 0 : ok
@ -80,7 +81,7 @@ 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)
@ -98,7 +99,7 @@ int Training::setRack(set_rack_mode iMode, bool iCheck, const string &iLetters)
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;

View file

@ -22,7 +22,9 @@
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
#include <wctype.h>
#include <wchar.h>
#include <fstream>
#include <readline/readline.h>
#include <readline/history.h>
@ -35,16 +37,19 @@
#include "training.h"
#include "duplicate.h"
#include "freegame.h"
#include "encoding.h"
/* A static variable for holding the line. */
static char *line_read = NULL;
/* Wide version of the line */
static wchar_t *wline_read = NULL;
/**
* Read a string, and return a pointer to it.
* Returns NULL on EOF.
*/
char *rl_gets()
wchar_t *rl_gets()
{
// If the buffer has already been allocated, return the memory to the free
// pool
@ -53,6 +58,11 @@ char *rl_gets()
free(line_read);
line_read = NULL;
}
if (wline_read)
{
free(wline_read);
wline_read = NULL;
}
// Get a line from the user
line_read = readline("commande> ");
@ -61,117 +71,116 @@ char *rl_gets()
if (line_read && *line_read)
add_history(line_read);
return line_read;
// Convert the line into wide characters
// Get the needed length (we _can't_ use string::size())
size_t len = mbstowcs(NULL, line_read, 0);
if (len == (size_t)-1)
return NULL;
wline_read = new wchar_t[len + 1];
len = mbstowcs(wline_read, line_read, len + 1);
return wline_read;
}
char *
next_token_alpha(char *cmd, const char *delim)
wchar_t * next_token_alpha(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
{
int i;
char *token = strtok(cmd, delim);
wchar_t *token = wcstok(cmd, delim, state);
if (token == NULL)
return NULL;
for (i = 0; token[i] && isalpha(token[i]); i++)
int i;
for (i = 0; token[i] && iswalpha(token[i]); i++)
;
token[i] = '\0';
token[i] = L'\0';
return token;
}
char *
next_token_alphanum(char *cmd, const char *delim)
wchar_t * next_token_alphanum(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
{
int i;
char *token = strtok(cmd, delim);
wchar_t *token = wcstok(cmd, delim, state);
if (token == NULL)
return NULL;
for (i = 0; token[i] && isalnum(token[i]); i++)
int i;
for (i = 0; token[i] && iswalnum(token[i]); i++)
;
token[i] = '\0';
token[i] = L'\0';
return token;
}
char *
next_token_alphaplusjoker(char *cmd, const char *delim)
wchar_t * next_token_alphaplusjoker(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
{
int i;
char *token = strtok(cmd, delim);
wchar_t *token = wcstok(cmd, delim, state);
if (token == NULL)
return NULL;
for (i = 0; token[i] && (isalpha(token[i]) ||
token[i] == '?' ||
token[i] == '+');
int i;
for (i = 0; token[i] && (iswalpha(token[i]) ||
token[i] == L'?' ||
token[i] == L'+');
i++)
;
token[i] = '\0';
token[i] = L'\0';
return token;
}
char *
next_token_digit(char *cmd, const char *delim)
wchar_t * next_token_digit(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
{
int i;
char *token = strtok(cmd, delim);
wchar_t *token = wcstok(cmd, delim, state);
if (token == NULL)
return NULL;
for (i = 0; token[i] && (isdigit(token[i]) || token[i] == '-'); i++)
int i;
for (i = 0; token[i] && (iswdigit(token[i]) || token[i] == L'-'); i++)
;
token[i] = '\0';
token[i] = L'\0';
return token;
}
char *
next_token_cross(char *cmd, const char *delim)
wchar_t * next_token_cross(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
{
int i;
char *token = strtok(cmd, delim);
wchar_t *token = wcstok(cmd, delim, state);
if (token == NULL)
return NULL;
int i;
for (i = 0; token[i] &&
(isalpha(token[i]) || token[i] == '.');
(iswalpha(token[i]) || token[i] == L'.');
i++)
;
token[i] = '\0';
token[i] = L'\0';
return token;
}
char *
next_token_filename(char *cmd, const char *delim)
wchar_t * next_token_filename(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
{
int i;
char *token = strtok(cmd, delim);
wchar_t *token = wcstok(cmd, delim, state);
if (token == NULL)
return NULL;
for (i = 0; token[i] && (isalnum(token[i]) ||
token[i] == '.' ||
token[i] == '_'); i++)
int i;
for (i = 0; token[i] && (iswalnum(token[i]) ||
token[i] == L'.' ||
token[i] == L'_'); i++)
;
token[i] = '\0';
token[i] = L'\0';
return token;
}
void
eliottxt_get_cross(const Dictionary &iDic, char* cros)
void eliottxt_get_cross(const Dictionary &iDic, wchar_t *cros)
{
int i;
// (Dictionary dic, char* regx, char wordlist[RES_REGX_MAX][DIC_WORD_MAX])
char wordlist[RES_CROS_MAX][DIC_WORD_MAX];
wchar_t wordlist[RES_CROS_MAX][DIC_WORD_MAX];
Dic_search_Cros(iDic, cros, wordlist);
for (i = 0; i<RES_CROS_MAX && wordlist[i][0]; i++)
for (int i = 0; i < RES_CROS_MAX && wordlist[i][0]; i++)
{
printf(" %s\n", wordlist[i]);
printf(" %s\n", convertToMb(wordlist[i]).c_str());
}
}
void
help_training()
void help_training()
{
printf(" ? : aide -- cette page\n");
printf(" a [g|l|p|r|t] : afficher :\n");
@ -198,8 +207,7 @@ help_training()
}
void
help_freegame()
void help_freegame()
{
printf(" ? : aide -- cette page\n");
printf(" a [g|l|p|s|t] : afficher :\n");
@ -224,8 +232,7 @@ help_freegame()
}
void
help_duplicate()
void help_duplicate()
{
printf(" ? : aide -- cette page\n");
printf(" a [g|l|p|s|t] : afficher :\n");
@ -249,8 +256,7 @@ help_duplicate()
}
void
help()
void help()
{
printf(" ? : aide -- cette page\n");
printf(" e : démarrer le mode entraînement\n");
@ -269,12 +275,11 @@ help()
}
void
display_data(const Game &iGame, const char *delim)
void display_data(const Game &iGame, const wchar_t *delim, wchar_t **state)
{
char *token;
wchar_t *token;
token = next_token_alpha(NULL, delim);
token = next_token_alpha(NULL, delim, state);
if (token == NULL)
{
cout << "commande incomplète\n";
@ -282,19 +287,19 @@ display_data(const Game &iGame, const char *delim)
}
switch (token[0])
{
case 'g':
case L'g':
switch (token[1])
{
case '\0':
case L'\0':
GameIO::printBoard(cout, iGame);
break;
case 'j':
case L'j':
GameIO::printBoardJoker(cout, iGame);
break;
case 'm':
case L'm':
GameIO::printBoardMultipliers(cout, iGame);
break;
case 'n':
case L'n':
GameIO::printBoardMultipliers2(cout, iGame);
break;
default:
@ -302,20 +307,20 @@ display_data(const Game &iGame, const char *delim)
break;
}
break;
case 'j':
case L'j':
cout << "Joueur " << iGame.currPlayer() << endl;
break;
case 'l':
case L'l':
GameIO::printNonPlayed(cout, iGame);
break;
case 'p':
case L'p':
iGame.save(cout,Game::FILE_FORMAT_ADVANCED);
break;
case 'P':
case L'P':
iGame.save(cout,Game::FILE_FORMAT_STANDARD);
break;
case 'r':
token = next_token_digit(NULL, delim);
case L'r':
token = next_token_digit(NULL, delim, state);
if (token == NULL)
GameIO::printSearchResults(cout,
static_cast<const Training&>(iGame),
@ -323,18 +328,18 @@ display_data(const Game &iGame, const char *delim)
else
GameIO::printSearchResults(cout,
static_cast<const Training&>(iGame),
atoi(token));
_wtoi(token));
break;
case 's':
case L's':
GameIO::printPoints(cout, iGame);
break;
case 'S':
case L'S':
GameIO::printAllPoints(cout, iGame);
break;
case 't':
case L't':
GameIO::printPlayedRack(cout, iGame, iGame.getHistory().getSize());
break;
case 'T':
case L'T':
GameIO::printAllRacks(cout, iGame);
break;
default:
@ -344,12 +349,12 @@ display_data(const Game &iGame, const char *delim)
}
void
loop_training(Training &iGame)
void loop_training(Training &iGame)
{
char *token;
char *commande = NULL;
char delim[] = " \t";
wchar_t *token;
wchar_t *state;
wchar_t *commande = NULL;
wchar_t delim[] = L" \t";
int quit = 0;
cout << "mode entraînement\n";
@ -357,37 +362,43 @@ loop_training(Training &iGame)
while (quit == 0)
{
commande = rl_gets();
token = strtok(commande, delim);
token = wcstok(commande, delim, &state);
if (token)
{
switch (token[0])
{
case '?':
case L'?':
help_training();
break;
case 'a':
display_data(iGame, delim);
case L'a':
display_data(iGame, delim, &state);
break;
case 'd':
token = next_token_alpha(NULL, delim);
case L'd':
token = next_token_alpha(NULL, delim, &state);
if (token == NULL)
help_training();
else
{
if (Dic_search_word(iGame.getDic(), token))
printf("le mot -%s- existe\n", token);
{
printf("le mot -%s- existe\n",
convertToMb(token).c_str());
}
else
printf("le mot -%s- n'existe pas\n", token);
{
printf("le mot -%s- n'existe pas\n",
convertToMb(token).c_str());
}
}
break;
case 'j':
token = next_token_alpha(NULL, delim);
case L'j':
token = next_token_alpha(NULL, delim, &state);
if (token == NULL)
help_training();
else
{
int res;
char *coord = next_token_alphanum(NULL, delim);
wchar_t *coord = next_token_alphanum(NULL, delim, &state);
if (coord == NULL)
{
help_training();
@ -401,13 +412,13 @@ loop_training(Training &iGame)
}
}
break;
case 'n':
token = next_token_digit(NULL, delim);
case L'n':
token = next_token_digit(NULL, delim, &state);
if (token == NULL)
help_training();
else
{
int n = atoi(token);
int n = _wtoi(token);
if (n <= 0)
iGame.back(n == 0 ? 1 : -n);
else
@ -417,45 +428,47 @@ loop_training(Training &iGame)
}
}
break;
case 'r':
case L'r':
iGame.search();
break;
case 't':
token = next_token_alphaplusjoker(NULL, delim);
case L't':
token = next_token_alphaplusjoker(NULL, delim, &state);
if (token == NULL)
help_training();
else
if (iGame.setRackManual(0, token))
printf("le sac ne contient pas assez de lettres\n");
break;
case 'x':
token = next_token_cross(NULL, delim);
case L'x':
token = next_token_cross(NULL, delim, &state);
if (token == NULL)
help_training();
else
eliottxt_get_cross(iGame.getDic(), token);
break;
case '*':
case L'*':
iGame.setRackRandom(false, Game::RACK_ALL);
break;
case '+':
case L'+':
iGame.setRackRandom(false, Game::RACK_NEW);
break;
case 's':
token = next_token_filename(NULL, delim);
case L's':
token = next_token_filename(NULL, delim, &state);
if (token != NULL)
{
ofstream fout(token);
string filename = convertToMb(token);
ofstream fout(filename.c_str());
if (fout.rdstate() == ios::failbit)
{
printf("impossible d'ouvrir %s\n", token);
printf("impossible d'ouvrir %s\n",
filename.c_str());
break;
}
iGame.save(fout);
fout.close();
}
break;
case 'q':
case L'q':
quit = 1;
break;
default:
@ -468,12 +481,12 @@ loop_training(Training &iGame)
}
void
loop_freegame(FreeGame &iGame)
void loop_freegame(FreeGame &iGame)
{
char *token;
char *commande = NULL;
char delim[] = " \t";
wchar_t *token;
wchar_t *state;
wchar_t *commande = NULL;
wchar_t delim[] = L" \t";
int quit = 0;
printf("mode partie libre\n");
@ -481,37 +494,43 @@ loop_freegame(FreeGame &iGame)
while (quit == 0)
{
commande = rl_gets();
token = strtok(commande, delim);
token = wcstok(commande, delim, &state);
if (token)
{
switch (token[0])
{
case '?':
case L'?':
help_freegame();
break;
case 'a':
display_data(iGame, delim);
case L'a':
display_data(iGame, delim, &state);
break;
case 'd':
token = next_token_alpha(NULL, delim);
case L'd':
token = next_token_alpha(NULL, delim, &state);
if (token == NULL)
help_freegame();
else
{
if (Dic_search_word(iGame.getDic(), token))
printf("le mot -%s- existe\n", token);
{
printf("le mot -%s- existe\n",
convertToMb(token).c_str());
}
else
printf("le mot -%s- n'existe pas\n", token);
{
printf("le mot -%s- n'existe pas\n",
convertToMb(token).c_str());
}
}
break;
case 'j':
token = next_token_alpha(NULL, delim);
case L'j':
token = next_token_alpha(NULL, delim, &state);
if (token == NULL)
help_freegame();
else
{
int res;
char *coord = next_token_alphanum(NULL, delim);
wchar_t *coord = next_token_alphanum(NULL, delim, &state);
if (coord == NULL)
{
help_freegame();
@ -525,30 +544,32 @@ loop_freegame(FreeGame &iGame)
}
}
break;
case 'p':
token = next_token_alpha(NULL, delim);
case L'p':
token = next_token_alpha(NULL, delim, &state);
/* You can pass your turn without changing any letter */
if (token == NULL)
token = "";
token = L"";
if (iGame.pass(token, iGame.currPlayer()) != 0)
break;
break;
case 's':
token = next_token_filename(NULL, delim);
case L's':
token = next_token_filename(NULL, delim, &state);
if (token != NULL)
{
ofstream fout(token);
string filename = convertToMb(token);
ofstream fout(filename.c_str());
if (fout.rdstate() == ios::failbit)
{
printf("impossible d'ouvrir %s\n", token);
printf("impossible d'ouvrir %s\n",
filename.c_str());
break;
}
iGame.save(fout);
fout.close();
}
break;
case 'q':
case L'q':
quit = 1;
break;
default:
@ -561,12 +582,12 @@ loop_freegame(FreeGame &iGame)
}
void
loop_duplicate(Duplicate &iGame)
void loop_duplicate(Duplicate &iGame)
{
char *token;
char *commande = NULL;
char delim[] = " \t";
wchar_t *token;
wchar_t *state;
wchar_t *commande = NULL;
wchar_t delim[] = L" \t";
int quit = 0;
printf("mode duplicate\n");
@ -574,37 +595,43 @@ loop_duplicate(Duplicate &iGame)
while (quit == 0)
{
commande = rl_gets();
token = strtok(commande, delim);
token = wcstok(commande, delim, &state);
if (token)
{
switch (token[0])
{
case '?':
case L'?':
help_duplicate();
break;
case 'a':
display_data(iGame, delim);
case L'a':
display_data(iGame, delim, &state);
break;
case 'd':
token = next_token_alpha(NULL, delim);
case L'd':
token = next_token_alpha(NULL, delim, &state);
if (token == NULL)
help_duplicate();
else
{
if (Dic_search_word(iGame.getDic(), token))
printf("le mot -%s- existe\n", token);
{
printf("le mot -%s- existe\n",
convertToMb(token).c_str());
}
else
printf("le mot -%s- n'existe pas\n", token);
{
printf("le mot -%s- n'existe pas\n",
convertToMb(token).c_str());
}
}
break;
case 'j':
token = next_token_alpha(NULL, delim);
case L'j':
token = next_token_alpha(NULL, delim, &state);
if (token == NULL)
help_duplicate();
else
{
int res;
char *coord = next_token_alphanum(NULL, delim);
wchar_t *coord = next_token_alphanum(NULL, delim, &state);
if (coord == NULL)
{
help_duplicate();
@ -618,34 +645,36 @@ loop_duplicate(Duplicate &iGame)
}
}
break;
case 'n':
token = next_token_digit(NULL, delim);
case L'n':
token = next_token_digit(NULL, delim, &state);
if (token == NULL)
help_duplicate();
else
{
int res = iGame.setPlayer(atoi(token));
int res = iGame.setPlayer(_wtoi(token));
if (res == 1)
fprintf(stderr, "Numéro de joueur invalide\n");
else if (res == 2)
fprintf(stderr, "Impossible de choisir un joueur non humain\n");
}
break;
case 's':
token = next_token_filename(NULL, delim);
case L's':
token = next_token_filename(NULL, delim, &state);
if (token != NULL)
{
ofstream fout(token);
string filename = convertToMb(token);
ofstream fout(filename.c_str());
if (fout.rdstate() == ios::failbit)
{
printf("impossible d'ouvrir %s\n", token);
printf("impossible d'ouvrir %s\n",
filename.c_str());
break;
}
iGame.save(fout);
fout.close();
}
break;
case 'q':
case L'q':
quit = 1;
break;
default:
@ -658,8 +687,7 @@ loop_duplicate(Duplicate &iGame)
}
void
eliot_regexp_build_default_llist(struct search_RegE_list_t &llist)
void eliot_regexp_build_default_llist(struct search_RegE_list_t &llist)
{
memset(&llist, 0, sizeof(llist));
@ -705,8 +733,8 @@ eliot_regexp_build_default_llist(struct search_RegE_list_t &llist)
}
}
void
eliot_regexp(const Dictionary iDic)
void eliot_regexp(const Dictionary& iDic, wchar_t *cmd,
const wchar_t *delim, wchar_t **state)
{
/*
printf(" x [] {1} {2} {3} : expressions rationnelles\n");
@ -718,26 +746,23 @@ eliot_regexp(const Dictionary iDic)
#define DIC_RE_MAX (3*DIC_WORD_MAX) // yes, it's 3
char re[DIC_RE_MAX];
char buff[RES_REGE_MAX][DIC_WORD_MAX];
struct search_RegE_list_t llist;
eliot_regexp_build_default_llist(llist);
char *exp, *cnres, *clmin, *clmax;
wchar_t *exp, *cnres, *clmin, *clmax;
char delim[] = " \t";
exp = strtok(NULL,delim);
cnres = strtok(NULL,delim);
clmin = strtok(NULL,delim);
clmax = strtok(NULL,delim);
exp = wcstok(NULL, delim, state);
cnres = wcstok(NULL, delim, state);
clmin = wcstok(NULL, delim, state);
clmax = wcstok(NULL, delim, state);
if (exp == NULL)
{
return;
}
int nres = cnres ? atoi(cnres) : 50;
int lmin = clmin ? atoi(clmin) : 1;
int lmax = clmax ? atoi(clmax) : DIC_WORD_MAX - 1;
int nres = cnres ? _wtoi(cnres) : 50;
int lmin = clmin ? _wtoi(clmin) : 1;
int lmax = clmax ? _wtoi(clmax) : DIC_WORD_MAX - 1;
if (lmax <= (DIC_WORD_MAX - 1) && lmin >= 1 && lmin <= lmax)
{
@ -750,50 +775,56 @@ eliot_regexp(const Dictionary iDic)
return;
}
strncpy(re,exp,DIC_RE_MAX);
wchar_t re[DIC_RE_MAX];
wcsncpy(re, exp, DIC_RE_MAX);
wchar_t buff[RES_REGE_MAX][DIC_WORD_MAX];
printf("search for %s (%d,%d,%d)\n",re,nres,lmin,lmax);
printf("search for %s (%d,%d,%d)\n", convertToMb(exp).c_str(),
nres, lmin, lmax);
Dic_search_RegE(iDic, re, buff, &llist);
int nresult = 0;
for (int i = 0; i < RES_REGE_MAX && i < nres && buff[i][0]; i++)
{
printf("%s\n",buff[i]);
printf("%s\n", convertToMb(buff[i]).c_str());
nresult++;
}
printf("%d printed results\n", nresult);
}
void
main_loop(const Dictionary &iDic)
void main_loop(const Dictionary &iDic)
{
char *token;
char *commande = NULL;
char delim[] = " \t";
wchar_t *token;
wchar_t *state;
wchar_t *commande = NULL;
wchar_t delim[] = L" \t";
int quit = 0;
printf("[?] pour l'aide\n");
while (quit == 0)
{
commande = rl_gets();
token = strtok(commande, delim);
token = wcstok(commande, delim, &state);
if (token)
{
switch (token[0])
{
case '?':
case L'?':
help();
break;
case 'c':
token = next_token_filename(NULL, delim);
case L'c':
token = next_token_filename(NULL, delim, &state);
if (token == NULL)
{}
else
{
string filename = convertToMb(token);
FILE* fin;
if ((fin = fopen(token, "r")) == NULL)
if ((fin = fopen(filename.c_str(), "r")) == NULL)
{
printf("impossible d'ouvrir %s\n", token);
printf("impossible d'ouvrir %s\n",
filename.c_str());
break;
}
Game *game = Game::load(fin, iDic);
@ -813,7 +844,7 @@ main_loop(const Dictionary &iDic)
}
}
break;
case 'e':
case L'e':
{
// New training game
Training *game = GameFactory::Instance()->createTraining(iDic);
@ -822,59 +853,59 @@ main_loop(const Dictionary &iDic)
GameFactory::Instance()->releaseGame(*game);
break;
}
case 'd':
case L'd':
{
int i;
// New duplicate game
token = next_token_digit(NULL, delim);
token = next_token_digit(NULL, delim, &state);
if (token == NULL)
{
help();
break;
}
Duplicate *game = GameFactory::Instance()->createDuplicate(iDic);
for (i = 0; i < atoi(token); i++)
for (i = 0; i < _wtoi(token); i++)
game->addHumanPlayer();
token = next_token_digit(NULL, delim);
token = next_token_digit(NULL, delim, &state);
if (token == NULL)
{
help();
break;
}
for (i = 0; i < atoi(token); i++)
for (i = 0; i < _wtoi(token); i++)
game->addAIPlayer();
game->start();
loop_duplicate(*game);
GameFactory::Instance()->releaseGame(*game);
break;
}
case 'l':
case L'l':
{
int i;
// New free game
token = next_token_digit(NULL, delim);
token = next_token_digit(NULL, delim, &state);
if (token == NULL)
{
help();
break;
}
FreeGame *game = GameFactory::Instance()->createFreeGame(iDic);
for (i = 0; i < atoi(token); i++)
for (i = 0; i < _wtoi(token); i++)
game->addHumanPlayer();
token = next_token_digit(NULL, delim);
token = next_token_digit(NULL, delim, &state);
if (token == NULL)
{
help();
break;
}
for (i = 0; i < atoi(token); i++)
for (i = 0; i < _wtoi(token); i++)
game->addAIPlayer();
game->start();
loop_freegame(*game);
GameFactory::Instance()->releaseGame(*game);
break;
}
case 'D':
case L'D':
{
// New duplicate game
Duplicate *game = GameFactory::Instance()->createDuplicate(iDic);
@ -885,7 +916,7 @@ main_loop(const Dictionary &iDic)
GameFactory::Instance()->releaseGame(*game);
break;
}
case 'L':
case L'L':
{
// New free game
FreeGame *game = GameFactory::Instance()->createFreeGame(iDic);
@ -896,11 +927,11 @@ main_loop(const Dictionary &iDic)
GameFactory::Instance()->releaseGame(*game);
break;
}
case 'x':
case L'x':
// Regular expression tests
eliot_regexp(iDic);
eliot_regexp(iDic, NULL, delim, &state);
break;
case 'q':
case L'q':
quit = 1;
break;
default:
@ -912,11 +943,13 @@ main_loop(const Dictionary &iDic)
}
int
main(int argc, char *argv[])
int main(int argc, char *argv[])
{
char dic_path[100];
// Let the user choose the locale
setlocale(LC_ALL, "");
Dictionary dic = NULL;
if (argc != 2 && argc != 3)
@ -968,9 +1001,11 @@ main(int argc, char *argv[])
Dic_destroy(dic);
// Free the readline static variable
// Free the readline static variable and its wide equivalent
if (line_read)
free(line_read);
if (wline_read)
free(wline_read);
return 0;
}

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,9 +381,8 @@ 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)
@ -393,7 +393,7 @@ Plus1Frame::refresh()
}
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();
@ -424,12 +424,10 @@ Plus1Frame::refresh()
void
BenjFrame::refresh()
{
std::string word;
if (game->getMode() != Game::kTRAINING)
return;
word = ((Training*)game)->getTestPlayWord();
std::wstring word = static_cast<Training*>(game)->getTestPlayWord();
if (savedword == word)
{
noresult = false; // keep old results
@ -437,7 +435,7 @@ BenjFrame::refresh()
}
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];
@ -459,12 +457,10 @@ BenjFrame::refresh()
void
RaccFrame::refresh()
{
std::string word;
if (game->getMode() != Game::kTRAINING)
return;
word = ((Training*)game)->getTestPlayWord();
std::wstring word = static_cast<Training*>(game)->getTestPlayWord();
if (savedword == word)
{
noresult = false; // keep old results
@ -472,7 +468,7 @@ RaccFrame::refresh()
}
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];
@ -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() ) );

View file

@ -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();
}
@ -113,11 +113,11 @@ GfxResult::Refresh()
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());
debug("changed (%ls -> %ls)",savedrack.c_str(),rack.c_str());
savedrack = rack;
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,7 +443,7 @@ MainFrame::OnMenuGameOpen(wxCommandEvent&)
return;
}
std::string r = "";
std::wstring r;
if (m_game->getHistory().getSize() >= 0)
{
@ -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());