eliot-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Eliot-dev] eliot configure.in dic/Makefile.am dic/compdic.... [cppdic]


From: eliot-dev
Subject: [Eliot-dev] eliot configure.in dic/Makefile.am dic/compdic.... [cppdic]
Date: Tue, 27 Nov 2007 18:01:07 +0000

CVSROOT:        /cvsroot/eliot
Module name:    eliot
Branch:         cppdic
Changes by:     Olivier Teulière <ipkiss>      07/11/27 18:01:07

Modified files:
        .              : configure.in 
        dic            : Makefile.am compdic.cpp dic.cpp dic.h 
                         dic_search.cpp header.cpp header.h 
        game           : Makefile.am bag.cpp bag.h board.cpp 
                         board_cross.cpp board_search.cpp freegame.cpp 
                         game.cpp history.cpp pldrack.cpp rack.cpp 
                         rack.h 
        utils          : eliottxt.cpp game_io.cpp 
        wxwin          : auxframes.cc searchpanel.cc 
Added files:
        dic            : tile.cpp tile.h 
        m4             : ax_boost_base.m4 
Removed files:
        game           : tile.cpp tile.h 

Log message:
         - Removed wrappers in the DicSearch functions (except the regexp 
ones): wide characters are now handled directly
         - Added support for letter points, frequency, and for vowel/consonant 
information in the dictionary header
         - Moved the Tile class from game/ to dic/
         - The tiles points, frequency, vowel/consonant info are not hard-coded 
anymore but taken from the dictionary header
         - Removed the Tile::m_dummy attribute, it was confusing and not really 
useful
         - The Tile::getAllTiles() method has been moved to the Dictionary class
         - The Rack class has been changed not to use the internal letter codes 
anymore
         - There is a new dependency on Boost (checked by configure). In fact, 
only Boost.Tokenizer is used at the moment (which only provides header files, 
no library)

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/eliot/configure.in?cvsroot=eliot&only_with_tag=cppdic&r1=1.19.2.2&r2=1.19.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/Makefile.am?cvsroot=eliot&only_with_tag=cppdic&r1=1.14.4.5&r2=1.14.4.6
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/compdic.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.8&r2=1.1.2.9
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.6&r2=1.1.2.7
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.13.2.4&r2=1.13.2.5
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_search.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.2&r2=1.1.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/header.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.7&r2=1.1.2.8
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/header.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.5&r2=1.1.2.6
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/tile.cpp?cvsroot=eliot&only_with_tag=cppdic&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/tile.h?cvsroot=eliot&only_with_tag=cppdic&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/game/Makefile.am?cvsroot=eliot&only_with_tag=cppdic&r1=1.13.2.1&r2=1.13.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/bag.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.7.2.1&r2=1.7.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/bag.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.8.2.1&r2=1.8.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/board.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.14.2.3&r2=1.14.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/board_cross.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.6.2.3&r2=1.6.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/board_search.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.11.2.3&r2=1.11.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/freegame.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.18&r2=1.18.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.31.2.3&r2=1.31.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/history.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.10.2.1&r2=1.10.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/pldrack.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.9&r2=1.9.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/game/rack.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.7&r2=1.7.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/game/rack.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.9&r2=1.9.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/game/tile.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.7&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/game/tile.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.8&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/m4/ax_boost_base.m4?cvsroot=eliot&only_with_tag=cppdic&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/eliottxt.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.16.2.6&r2=1.16.2.7
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/game_io.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.9.2.2&r2=1.9.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/auxframes.cc?cvsroot=eliot&only_with_tag=cppdic&r1=1.22.2.2&r2=1.22.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/searchpanel.cc?cvsroot=eliot&only_with_tag=cppdic&r1=1.15.2.1&r2=1.15.2.2

Patches:
Index: configure.in
===================================================================
RCS file: /cvsroot/eliot/eliot/configure.in,v
retrieving revision 1.19.2.2
retrieving revision 1.19.2.3
diff -u -b -r1.19.2.2 -r1.19.2.3
--- configure.in        11 Nov 2007 19:56:57 -0000      1.19.2.2
+++ configure.in        27 Nov 2007 18:01:04 -0000      1.19.2.3
@@ -86,12 +86,12 @@
 AC_TYPE_SIZE_T
 AC_C_BIGENDIAN
 AC_C_INLINE
-AC_CHECK_SIZEOF(char, 1)
-AC_CHECK_SIZEOF(short, 2)
-AC_CHECK_SIZEOF(int *, 4)
-AC_CHECK_SIZEOF(int, 4)
-AC_CHECK_SIZEOF(long, 4)
-AC_CHECK_SIZEOF(long long, 0)
+dnl AC_CHECK_SIZEOF(char, 1)
+dnl AC_CHECK_SIZEOF(short, 2)
+dnl AC_CHECK_SIZEOF(int *, 4)
+dnl AC_CHECK_SIZEOF(int, 4)
+dnl AC_CHECK_SIZEOF(long, 4)
+dnl AC_CHECK_SIZEOF(long long, 0)
 
 dnl --------------------------------------------------------------
 dnl Checks for library functions.
@@ -102,6 +102,9 @@
 dnl Checks for libraries.
 dnl --------------------------------------------------------------
 
+dnl Check for the Boost libraries (in fact we only need the headers)
+AX_BOOST_BASE([1.33.1])
+
 dnl Check for wxWidgets
 AC_ARG_ENABLE([wxwidgets],AC_HELP_STRING([--enable-wxwidgets],[wxWidgets 
interface support (default disabled)]))
 if test "${enable_wxwidgets}" = "yes"

Index: dic/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Makefile.am,v
retrieving revision 1.14.4.5
retrieving revision 1.14.4.6
diff -u -b -r1.14.4.5 -r1.14.4.6
--- dic/Makefile.am     21 Nov 2007 16:25:43 -0000      1.14.4.5
+++ dic/Makefile.am     27 Nov 2007 18:01:04 -0000      1.14.4.6
@@ -29,11 +29,11 @@
        dic_exception.cpp dic_exception.h \
        header.cpp header.h \
        dic_internals.h \
+       tile.cpp tile.h \
        dic_search.cpp dic_search.h \
        dic.cpp dic.h \
        encoding.cpp encoding.h \
        automaton.cpp automaton.h \
-       hashtable.h hashtable.cpp \
        regexp.cpp regexp.h
 
 BUILT_SOURCES= \
@@ -62,7 +62,8 @@
        listdic \
        regexp
 
-compdic_SOURCES=compdic.cpp
+compdic_SOURCES=compdic.cpp \
+       hashtable.h hashtable.cpp
 compdic_LDADD=libdic.a
 
 listdic_SOURCES=listdic.cpp

Index: dic/compdic.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/compdic.cpp,v
retrieving revision 1.1.2.8
retrieving revision 1.1.2.9
diff -u -b -r1.1.2.8 -r1.1.2.9
--- dic/compdic.cpp     21 Nov 2007 16:25:44 -0000      1.1.2.8
+++ dic/compdic.cpp     27 Nov 2007 18:01:04 -0000      1.1.2.9
@@ -25,9 +25,11 @@
  */
 
 #include <fstream>
+#include <sstream>
 #include <iostream>
 #include <vector>
 #include <map>
+#include <boost/tokenizer.hpp>
 #include <iconv.h>
 #include <getopt.h>
 #include <time.h>
@@ -54,14 +56,12 @@
 
 wchar_t* load_uncompressed(const string &iFileName, unsigned int &ioDicSize)
 {
-    // TODO: we should throw exceptions everywhere instead of returning NULL
-
     ifstream file(iFileName.c_str());
     if (!file.is_open())
-        return NULL;
+        throw DicException("Could not open file " + iFileName);
 
     // Place the buffer in a vector to avoid worrying about memory handling
-    std::vector<char> buffer(ioDicSize);
+    vector<char> buffer(ioDicSize);
     // Load the file data, everything in one shot
     file.read(&buffer.front(), ioDicSize);
     file.close();
@@ -70,7 +70,7 @@
     // wide characters
     iconv_t handle = iconv_open("WCHAR_T", "UTF-8");
     if (handle == (iconv_t)(-1))
-        return NULL;
+        throw DicException("load_uncompressed: Error in iconv_open");
 
     // Buffer for the wide characters (it will use at most as many characters
     // as the utf-8 version)
@@ -85,7 +85,7 @@
     iconv_close(handle);
     // Problem during encoding conversion?
     if (res == (size_t)(-1))
-        return NULL;
+        throw DicException("load_uncompressed: Error while interpreting 
UTF-8");
 
     // Update ioDicSize with the actual length of the wchar_t array
     ioDicSize -= outChars / sizeof(wchar_t);
@@ -94,7 +94,83 @@
 }
 
 
-Header skip_init_header(ostream &outfile, Dict_header_info &ioHeaderInfo)
+void readLetters(const char *iFileName, DictHeaderInfo &ioHeaderInfo)
+{
+    ifstream in(iFileName);
+    if (!in.is_open())
+        throw DicException("Could not open file " + string(iFileName));
+
+    // Use a more friendly type name
+    typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
+
+    int lineNb = 1;
+    string line;
+    while (getline(in, line))
+    {
+        // Split the lines on space characters
+        vector<string> tokens;
+        boost::char_separator<char> sep(" ");
+        Tokenizer tok(line, sep);
+        Tokenizer::iterator it;
+        for (it = tok.begin(); it != tok.end(); ++it)
+        {
+            tokens.push_back(*it);
+        }
+
+        // Ignore empty lines
+        if (tokens.empty())
+            continue;
+
+        // We expect 5 fields on the line, and the first one is a letter, so
+        // it cannot exceed 4 bytes
+        if (tokens.size() != 5 || tokens[0].size() > 4)
+        {
+            ostringstream ss;
+            ss << "readLetters: Invalid line in " << iFileName;
+            ss << " (line " << lineNb;
+            throw DicException(ss.str());
+        }
+
+#define MAX_SIZE 4
+        wchar_t letter[MAX_SIZE];
+        char buff[MAX_SIZE];
+        strncpy(buff, tokens[0].c_str(), MAX_SIZE);
+
+        // The letter is supposed to be in utf-8, so convert it to
+        // wide characters
+        iconv_t handle = iconv_open("WCHAR_T", "UTF-8");
+        if (handle == (iconv_t)(-1))
+            throw DicException("readLetters: Error in iconv_open");
+        size_t inChars = tokens[0].size();
+        size_t outChars = sizeof(wchar_t) * MAX_SIZE;
+        char *in = buff;
+        char *out = (char*)letter;
+        size_t res = iconv(handle, &in, &inChars, &out, &outChars);
+        iconv_close(handle);
+        // Problem during encoding conversion?
+        if (res == (size_t)(-1))
+            throw DicException("readLetters: Error while interpreting UTF-8");
+        if (outChars != sizeof(wchar_t) * (MAX_SIZE - 1))
+        {
+            ostringstream ss;
+            ss << "readLetters: Invalid letter at line " << lineNb;
+            throw DicException(ss.str());
+        }
+#undef MAX_SIZE
+
+        ioHeaderInfo.letters += towupper(letter[0]);
+
+        ioHeaderInfo.points.push_back(atoi(tokens[1].c_str()));
+        ioHeaderInfo.frequency.push_back(atoi(tokens[2].c_str()));
+        ioHeaderInfo.vowels.push_back(atoi(tokens[3].c_str()));
+        ioHeaderInfo.consonants.push_back(atoi(tokens[4].c_str()));
+
+        ++lineNb;
+    }
+}
+
+
+Header skip_init_header(ostream &outfile, DictHeaderInfo &ioHeaderInfo)
 {
     ioHeaderInfo.root       = 0;
     ioHeaderInfo.nwords     = 0;
@@ -109,7 +185,7 @@
 }
 
 
-void fix_header(ostream &outfile, Dict_header_info &ioHeaderInfo)
+void fix_header(ostream &outfile, DictHeaderInfo &ioHeaderInfo)
 {
     ioHeaderInfo.root = ioHeaderInfo.edgesused;
     // Go back to the beginning of the stream to overwrite the header
@@ -209,7 +285,7 @@
  *      the (wide) chars and their corresponding internal code
  */
 unsigned int makenode(const wchar_t *iPrefix, ostream &outfile,
-                      Dict_header_info &ioHeaderInfo, const Header &iHeader)
+                      DictHeaderInfo &ioHeaderInfo, const Header &iHeader)
 {
 #ifdef CHECK_RECURSION
     IncDec inc(current_rec);
@@ -300,13 +376,26 @@
     cout << "Usage: " << iBinaryName << " [options]" << endl
          << "Mandatory options:" << endl
          << "  -d, --dicname <string>  Set the dictionary name and version" << 
endl
-         << "  -l, --letters <string>  Set the dictionary letters" << endl
-         << "  -i, --input <string>    Name of the uncompressed dictionary 
file" << endl
-         << "  -o, --output <string    Name of the generated compressed 
dictionary file" << endl
+         << "  -l, --letters <string>  Path to the file containing the letters 
(see below)" << endl
+         << "  -i, --input <string>    Path to the uncompressed dictionary 
file" << endl
+         << "  -o, --output <string    Path to the generated compressed 
dictionary file" << endl
          << "Other options:" << endl
          << "  -h, --help              Print this help and exit" << endl
          << "Example:" << endl
-         << "  " << iBinaryName << " -d 'ODS 5.0' -l 
ABCDEFGHIJKLMNOPQRSTUVWXYZ -i list -o ods5.dawg" << endl;
+         << "  " << iBinaryName << " -d 'ODS 5.0' -l letters -i list -o 
ods5.dawg" << endl
+         << endl
+         << "The file containing the letters (--letters switch) must be UTF-8 
encoded." << endl
+         << "Each line corresponds to one letter, and must contains 5 fields 
separated with " << endl
+         << "one or more space(s). " << endl
+         << " - 1st field: the letter itself" << endl
+         << " - 2nd field: the points of the letter" << endl
+         << " - 3rd field: the frequency of the letter (how many letters of 
this kind in the game)" << endl
+         << " - 4th field: 1 if the letter is considered as a vowel in 
Scrabble game, 0 otherwise" << endl
+         << " - 5th field: 1 if the letter is considered as a consonant in 
Scrabble game, 0 otherwise" << endl
+         << "Example for french:" << endl
+         << "A 1 9 1 0" << endl
+         << "B 3 2 0 1" << endl
+         << "etc." << endl;
 }
 
 
@@ -329,10 +418,9 @@
     bool found_l = false;
     bool found_i = false;
     bool found_o = false;
-    wstring dicName;
-    wstring letters;
     string inFileName;
     string outFileName;
+    DictHeaderInfo headerInfo;
 
     int res;
     int option_index = 1;
@@ -346,14 +434,11 @@
                 exit(0);
             case 'd':
                 found_d = true;
-                dicName = convertToWc(optarg);
+                headerInfo.dicName = convertToWc(optarg);
                 break;
             case 'l':
                 found_l = true;
-                letters = convertToWc(optarg);
-                // Ensure that the letters are uppercase
-                for (unsigned int i = 0; i < letters.size(); ++i)
-                    letters[i] = towupper(letters[i]);
+                readLetters(optarg, headerInfo);
                 break;
             case 'i':
                 found_i = true;
@@ -392,12 +477,8 @@
     try
     {
         clock_t startLoadTime = clock();
+        // FIXME: not exception safe
         wchar_t *uncompressed = load_uncompressed(inFileName, dicsize);
-        if (uncompressed == NULL)
-        {
-            fprintf(stderr, "Cannot load uncompressed dictionary into 
memory\n");
-            exit(1);
-        }
         clock_t endLoadTime = clock();
 
         global_input = uncompressed;
@@ -407,9 +488,6 @@
         global_hashtable = new HashTable<vector<Dawg_edge>, unsigned int, 
HashVector>((unsigned int)(dicsize * SCALE));
 #undef SCALE
 
-        Dict_header_info headerInfo;
-        headerInfo.dicName = dicName;
-        headerInfo.letters = letters;
         headerInfo.dawg = true;
         Header tempHeader = skip_init_header(outfile, headerInfo);
 

Index: dic/dic.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/dic.cpp,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.7
diff -u -b -r1.1.2.6 -r1.1.2.7
--- dic/dic.cpp 21 Nov 2007 16:25:44 -0000      1.1.2.6
+++ dic/dic.cpp 27 Nov 2007 18:01:04 -0000      1.1.2.7
@@ -20,7 +20,7 @@
 /**
  *  \file   dic.c
  *  \brief  Dawg dictionary
- *  \author Antoine Fraboulet
+ *  \author Antoine Fraboulet & Olivier Teuliere
  *  \date   2002
  */
 
@@ -35,6 +35,7 @@
 #include "header.h"
 #include "dic_exception.h"
 #include "dic_internals.h"
+#include "tile.h"
 
 
 // FIXME: duplicated in header.cpp
@@ -89,6 +90,8 @@
     }
 
     convertDataToArch();
+
+    initializeTiles();
 }
 
 
@@ -99,6 +102,23 @@
 }
 
 
+void Dictionary::initializeTiles()
+{
+    // "Activate" the dictionary by giving the header to the Tile class
+    Tile::SetHeader(*m_header);
+
+    // XXX: temp
+    Tile::m_TheJoker = Tile(TILE_JOKER);
+
+    m_tilesVect.reserve(m_header->getLetters().size() + 1);
+    // Create a tile for each letter in the dictionary header
+    for (unsigned int i = 0; i < m_header->getLetters().size(); ++i)
+        m_tilesVect.push_back(Tile(m_header->getLetters()[i]));
+    // Another tile for the joker
+    m_tilesVect.push_back(Tile::Joker());
+}
+
+
 const dic_elt_t Dictionary::getNext(const dic_elt_t &e) const
 {
      if (!isLast(e))
@@ -116,7 +136,6 @@
 const dic_elt_t Dictionary::getRoot() const
 {
     return m_header->getRoot();
-
 }
 
 
@@ -126,13 +145,9 @@
 }
 
 
-char Dictionary::getChar(const dic_elt_t &e) const
+wchar_t Dictionary::getChar(const dic_elt_t &e) const
 {
-    char c = (m_dawg[e]).chr;
-    if (c)
-        return c + 'A' - 1;
-    else
-        return 0;
+    return m_header->getCharFromCode(m_dawg[e].chr);
 }
 
 
@@ -175,7 +190,7 @@
     return 0;
 }
 
-unsigned int Dictionary::charLookup(const dic_elt_t &iRoot, const char *s) 
const
+unsigned int Dictionary::charLookup(const dic_elt_t &iRoot, const wchar_t *s) 
const
 {
     unsigned int p;
     dic_elt_t rootCopy = iRoot;

Index: dic/dic.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/dic.h,v
retrieving revision 1.13.2.4
retrieving revision 1.13.2.5
diff -u -b -r1.13.2.4 -r1.13.2.5
--- dic/dic.h   21 Nov 2007 16:25:44 -0000      1.13.2.4
+++ dic/dic.h   27 Nov 2007 18:01:04 -0000      1.13.2.5
@@ -20,7 +20,7 @@
 /**
  *  \file   dic.h
  *  \brief  Dawg dictionary
- *  \author Antoine Fraboulet
+ *  \author Antoine Fraboulet & Olivier Teuliere
  *  \date   2002
  */
 
@@ -28,6 +28,11 @@
 #define _DIC_H_
 
 #include <string>
+#include <vector>
+
+#include "tile.h"
+
+using namespace std;
 
 
 /**
@@ -45,8 +50,6 @@
 typedef unsigned int dic_elt_t;
 typedef unsigned char dic_code_t;
 
-using namespace std;
-
 class Dictionary
 {
 public:
@@ -62,6 +65,9 @@
     /** Give access to the dictionary header */
     const Header& getHeader() const { return *m_header; }
 
+    /** Return a vector containing one of each possible tile */
+    const vector<Tile>& getAllTiles() const { return m_tilesVect; }
+
     /**
      * Returns the character code associated with an element,
      * codes may range from 0 to 31. 0 is the null character.
@@ -70,11 +76,10 @@
     const dic_code_t getCode(const dic_elt_t &elt) const;
 
     /**
-     * Returns the character associated with an element
-     * (in the range ['A'-'Z']), or the null character ('\0').
-     * @returns ASCII code for the character
+     * Returns the wide character associated with an element.
+     * @returns wide character for the element
      */
-    char getChar(const dic_elt_t &elt) const;
+    wchar_t getChar(const dic_elt_t &elt) const;
 
     /**
      * Returns a boolean to show if there is another available
@@ -132,7 +137,7 @@
      * element that results from walking the dictionary according to the
      * pattern
      */
-    unsigned int charLookup(const dic_elt_t &iRoot, const char *iPattern) 
const;
+    unsigned int charLookup(const dic_elt_t &iRoot, const wchar_t *iPattern) 
const;
 
     /// Getter for the dawg
     const Dawg_edge *getDawg() const { return m_dawg; }
@@ -145,7 +150,11 @@
     Header *m_header;
     Dawg_edge *m_dawg;
 
+    /// Vector of available tiles
+    vector<Tile> m_tilesVect;
+
     void convertDataToArch();
+    void initializeTiles();
 };
 
 #endif /* _DIC_H_ */

Index: dic/dic_search.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/dic_search.cpp,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -u -b -r1.1.2.2 -r1.1.2.3
--- dic/dic_search.cpp  11 Nov 2007 19:56:58 -0000      1.1.2.2
+++ dic/dic_search.cpp  27 Nov 2007 18:01:04 -0000      1.1.2.3
@@ -24,13 +24,14 @@
  *  \date   2002
  */
 
-#include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
+#include <wctype.h>
 
 #include "dic_internals.h"
 #include "dic.h"
+#include "header.h"
 #include "encoding.h"
 #include "regexp.h"
 #include "dic_search.h"
@@ -50,18 +51,18 @@
 /**
  * Dic_seel_edgeptr
  * walk the dictionary until the end of the word
- * @param iDic : dictionnary
- * @param s : current pointer to letters
- * @param eptr : current edge in the dawg
+ * @param iDic: dictionnary
+ * @param s: current pointer to letters
+ * @param eptr: current edge in the dawg
  */
-static const Dawg_edge* Dic_seek_edgeptr(const Dictionary &iDic, const char* 
s, const Dawg_edge *eptr)
+static const Dawg_edge* Dic_seek_edgeptr(const Dictionary &iDic, const 
wchar_t* s, const Dawg_edge *eptr)
 {
     if (*s)
     {
         const Dawg_edge *p = iDic.getDawg() + eptr->ptr;
         do
         {
-            if (p->chr == (unsigned)(*s & DIC_CHAR_MASK))
+            if (p->chr == iDic.getHeader().getCodeFromChar(*s))
                 return Dic_seek_edgeptr(iDic, s + 1, p);
         } while (!(*p++).last);
         return iDic.getDawg();
@@ -72,12 +73,12 @@
 
 
 /**
- * Dic_search_word_inner : direct application of Dic_seek_edgeptr
- * @param iDic : dictionary
- * @param word : word to lookup
+ * searchWord: direct application of Dic_seek_edgeptr
+ * @param iDic: dictionary
+ * @param iWord: word to lookup
  * @result 0 not a valid word, 1 ok
  */
-static int Dic_search_word_inner(const Dictionary &iDic, const string &iWord)
+int DicSearch::searchWord(const Dictionary &iDic, const wstring &iWord)
 {
     const Dawg_edge *e = Dic_seek_edgeptr(iDic, iWord.c_str(), iDic.getDawg() 
+ iDic.getRoot());
     return e->term;
@@ -85,17 +86,7 @@
 
 
 /**
- * Wrapper around Dic_search_word_inner, until we have multibyte support in
- * the dictionary
- */
-int DicSearch::searchWord(const Dictionary &iDic, const wstring &iWord)
-{
-    return Dic_search_word_inner(iDic, convertToMb(iWord));
-}
-
-
-/**
- * global variables for Dic_search_word_by_len :
+ * global variables for Dic_search_word_by_len:
  *
  * a pointer to the structure is passed as a parameter
  * so that all the search_* variables appear to the functions
@@ -105,16 +96,16 @@
 
 struct params_7plus1_t
 {
-    const Dictionary *search_dic;
-    char added_char;
-    map<char, list<string> > *results;
+    wchar_t added_char;
+    map<wchar_t, list<wstring> > *results;
     int search_len;
-    char search_wordtst[DIC_WORD_MAX];
-    char search_letters[DIC_LETTERS];
+    wchar_t search_wordtst[DIC_WORD_MAX];
+    wchar_t search_letters[DIC_LETTERS];
 };
 
 static void
-Dic_search_word_by_len(struct params_7plus1_t *params, int i, const Dawg_edge 
*edgeptr)
+Dic_search_word_by_len(const Dictionary &iDic, struct params_7plus1_t *params,
+                       int i, const Dawg_edge *edgeptr)
 {
     /* depth first search in the dictionary */
     do
@@ -125,7 +116,7 @@
             /* is the letter available in search_letters */
             if (params->search_letters[edgeptr->chr])
             {
-                params->search_wordtst[i] = edgeptr->chr + 'A' - 1;
+                params->search_wordtst[i] = 
iDic.getHeader().getCharFromCode(edgeptr->chr);
                 params->search_letters[edgeptr->chr] --;
                 if (i == params->search_len)
                 {
@@ -136,16 +127,16 @@
                 }
                 else
                 {
-                    Dic_search_word_by_len(params, i + 1, 
params->search_dic->getDawg() + edgeptr->ptr);
+                    Dic_search_word_by_len(iDic, params, i + 1, iDic.getDawg() 
+ edgeptr->ptr);
                 }
                 params->search_letters[edgeptr->chr] ++;
-                params->search_wordtst[i] = '\0';
+                params->search_wordtst[i] = L'\0';
             }
 
             /* the letter is of course available if we have a joker available 
*/
             if (params->search_letters[0])
             {
-                params->search_wordtst[i] = edgeptr->chr + 'a' - 1;
+                params->search_wordtst[i] = 
iDic.getHeader().getCharFromCode(edgeptr->chr);
                 params->search_letters[0] --;
                 if (i == params->search_len)
                 {
@@ -156,39 +147,45 @@
                 }
                 else
                 {
-                    Dic_search_word_by_len(params, i + 1, 
params->search_dic->getDawg() + edgeptr->ptr);
+                    Dic_search_word_by_len(iDic, params, i + 1, iDic.getDawg() 
+ edgeptr->ptr);
                 }
                 params->search_letters[0] ++;
-                params->search_wordtst[i] = '\0';
+                params->search_wordtst[i] = L'\0';
             }
         }
     } while (! (*edgeptr++).last);
 }
 
-static void
-Dic_search_7pl1_inner(const Dictionary &iDic, const string &iRack,
-                      map<char, list<string> > &oWordList,
+
+/**
+ * Wrapper around Dic_search_7pl1_inner, until we have multibyte support in
+ * the dictionary
+ */
+void DicSearch::search7pl1(const Dictionary &iDic, const wstring &iRack,
+                           map<wchar_t, list<wstring> > &oWordList,
                       bool joker)
 {
-    int i, wordlen;
-    const char* r = iRack.c_str();
+    if (iRack == L"" || iRack.size() > DIC_WORD_MAX)
+        return;
+
     struct params_7plus1_t params;
 
-    for (i = 0; i < DIC_LETTERS; i++)
+    for (int i = 0; i < DIC_LETTERS; i++)
         params.search_letters[i] = 0;
 
     /*
      * the letters are verified and changed to the dic internal
-     * representation (*r & DIC_CHAR_MASK)
+     * representation (using getCodeFromChar(*r))
      */
-    for (wordlen=0; wordlen < DIC_WORD_MAX && *r; r++)
+    int wordlen = 0;
+    for (const wchar_t* r = iRack.c_str(); *r; r++)
     {
-        if (isalpha(*r))
+        if (iswalpha(*r))
         {
-            params.search_letters[(int)*r & DIC_CHAR_MASK]++;
+            params.search_letters[iDic.getHeader().getCodeFromChar(*r)]++;
             wordlen++;
         }
-        else if (*r == '?')
+        else if (*r == L'?')
         {
             if (joker)
             {
@@ -197,7 +194,7 @@
             }
             else
             {
-                oWordList[0].push_back("** joker **");
+                oWordList[0].push_back(L"** joker **");
                 return;
             }
         }
@@ -209,77 +206,49 @@
     const Dawg_edge *root_edge =
         iDic.getDawg() + (iDic.getDawg()[iDic.getRoot()].ptr);
 
-    params.search_dic = &iDic;
     params.results = &oWordList;
 
     /* search for all the words that can be done with the letters */
-    params.added_char = 0;
+    params.added_char = L'\0';
     params.search_len = wordlen - 1;
-    params.search_wordtst[wordlen]='\0';
-    Dic_search_word_by_len(&params, 0, root_edge);
+    params.search_wordtst[wordlen] = L'\0';
+    Dic_search_word_by_len(iDic, &params, 0, root_edge);
 
     /* search for all the words that can be done with the letters +1 */
     params.search_len = wordlen;
-    params.search_wordtst[wordlen + 1]='\0';
-    for (i = 'a'; i <= 'z'; i++)
+    params.search_wordtst[wordlen + 1] = L'\0';
+    const wstring &letters = iDic.getHeader().getLetters();
+    for (unsigned int i = 0; i <= letters.size(); i++)
     {
-        params.added_char = i & DIC_CHAR_MASK;
-        params.search_letters[i & DIC_CHAR_MASK]++;
+        params.added_char = letters[i];
+        unsigned int code = iDic.getHeader().getCodeFromChar(letters[i]);
+        params.search_letters[code]++;
 
-        Dic_search_word_by_len(&params, 0, root_edge);
+        Dic_search_word_by_len(iDic, &params, 0, root_edge);
 
-        params.search_letters[i & DIC_CHAR_MASK]--;
-    }
-}
-
-
-/**
- * Wrapper around Dic_search_7pl1_inner, until we have multibyte support in
- * the dictionary
- */
-void DicSearch::search7pl1(const Dictionary &iDic, const wstring &iRack,
-                           map<wchar_t, list<wstring> > &oWordList,
-                           bool joker)
-{
-    if (iRack == L"")
-        return;
-
-    map<char, list<string> > wordList;
-    // Do the actual work
-    Dic_search_7pl1_inner(iDic, convertToMb(iRack), wordList, joker);
-
-    map<char, list<string> >::const_iterator it;
-    for (it = wordList.begin(); it != wordList.end(); it++)
-    {
-        wchar_t letter = 0;
-        if (it->first)
-        {
-            letter = convertToWc(string(1, it->first + 'A' - 1))[0];
-        }
-        list<string>::const_iterator itWord;
-        for (itWord = it->second.begin(); itWord != it->second.end(); itWord++)
-        {
-            oWordList[letter].push_back(convertToWc(*itWord));
-        }
+        params.search_letters[code]--;
     }
 }
 
 /****************************************/
 /****************************************/
 
-static void
-Dic_search_Racc_inner(const Dictionary &iDic, const string &iWord,
-                      list<string> &oWordList)
+void DicSearch::searchRacc(const Dictionary &iDic, const wstring &iWord,
+                           list<wstring> &oWordList)
 {
+    if (iWord == L"")
+        return;
+
     /* search_racc will try to add a letter in front and at the end of a word 
*/
 
     /* let's try for the front */
-    char wordtst[DIC_WORD_MAX];
-    strcpy(wordtst+1, iWord.c_str());
-    for (int i = 'a'; i <= 'z'; i++)
+    wchar_t wordtst[DIC_WORD_MAX];
+    wcscpy(wordtst + 1, iWord.c_str());
+    const wstring &letters = iDic.getHeader().getLetters();
+    for (unsigned int i = 0; i <= letters.size(); i++)
     {
-        wordtst[0] = i;
-        if (Dic_search_word_inner(iDic, wordtst))
+        wordtst[0] = letters[i];
+        if (searchWord(iDic, wordtst))
             oWordList.push_back(wordtst);
     }
 
@@ -302,57 +271,37 @@
         {
             if (edge->term)
             {
-                wordtst[i] = edge->chr + 'a' - 1;
+                wordtst[i] = iDic.getHeader().getCharFromCode(edge->chr);
                 oWordList.push_back(wordtst);
             }
         } while (!(*edge++).last);
     }
 }
 
-/**
- * Wrapper around Dic_search_Racc_inner, until we have multibyte support in
- * the dictionary
- */
-void DicSearch::searchRacc(const Dictionary &iDic, const wstring &iWord,
+/****************************************/
+/****************************************/
+
+void DicSearch::searchBenj(const Dictionary &iDic, const wstring &iWord,
                            list<wstring> &oWordList)
 {
     if (iWord == L"")
         return;
 
-    list<string> tmpWordList;
-    // Do the actual work
-    Dic_search_Racc_inner(iDic, convertToMb(iWord), tmpWordList);
-
-    list<string>::const_iterator it;
-    for (it = tmpWordList.begin(); it != tmpWordList.end(); it++)
-    {
-        oWordList.push_back(convertToWc(*it));
-    }
-}
-
-/****************************************/
-/****************************************/
-
-
-static void Dic_search_Benj_inner(const Dictionary &iDic,
-                                  const string &iWord,
-                                  list<string> &oWordList)
-{
-    char wordtst[DIC_WORD_MAX];
-    strcpy(wordtst + 3, iWord.c_str());
+    wchar_t wordtst[DIC_WORD_MAX];
+    wcscpy(wordtst + 3, iWord.c_str());
     const Dawg_edge *edge0, *edge1, *edge2, *edgetst;
     edge0 = iDic.getDawg() + (iDic.getDawg()[iDic.getRoot()].ptr);
     do
     {
-        wordtst[0] = edge0->chr + 'a' - 1;
+        wordtst[0] = iDic.getHeader().getCharFromCode(edge0->chr);
         edge1 = iDic.getDawg() + edge0->ptr;
         do
         {
-            wordtst[1] = edge1->chr + 'a' - 1;
+            wordtst[1] = iDic.getHeader().getCharFromCode(edge1->chr);
             edge2 = iDic.getDawg() + edge1->ptr;
             do
             {
-                wordtst[2] = edge2->chr + 'a' - 1;
+                wordtst[2] = iDic.getHeader().getCharFromCode(edge2->chr);
                 edgetst = Dic_seek_edgeptr(iDic, iWord.c_str(), edge2);
                 if (edgetst->term)
                     oWordList.push_back(wordtst);
@@ -361,44 +310,23 @@
     } while (!(*edge0++).last);
 }
 
-/**
- * Wrapper around Dic_search_Benj_inner, until we have multibyte support in
- * the dictionary
- */
-void DicSearch::searchBenj(const Dictionary &iDic, const wstring &iWord,
-                           list<wstring> &oWordList)
-{
-    if (iWord == L"")
-        return;
-
-    list<string> tmpWordList;
-    // Do the actual work
-    Dic_search_Benj_inner(iDic, convertToMb(iWord), tmpWordList);
-
-    list<string>::const_iterator it;
-    for (it = tmpWordList.begin(); it != tmpWordList.end(); it++)
-    {
-        oWordList.push_back(convertToWc(*it));
-    }
-}
-
 
 /****************************************/
 /****************************************/
 
 struct params_cross_t
 {
-    const Dictionary *dic;
     int wordlen;
-    char mask[DIC_WORD_MAX];
+    wchar_t mask[DIC_WORD_MAX];
 };
 
 
-static void Dic_search_cross_rec(struct params_cross_t *params,
-                                 list<string> &oWordList,
+static void Dic_search_cross_rec(const Dictionary &iDic,
+                                 struct params_cross_t *params,
+                                 list<wstring> &oWordList,
                                  const Dawg_edge *edgeptr)
 {
-    const Dawg_edge *current = params->dic->getDawg() + edgeptr->ptr;
+    const Dawg_edge *current = iDic.getDawg() + edgeptr->ptr;
 
     if (params->mask[params->wordlen] == '\0' && edgeptr->term)
     {
@@ -408,9 +336,9 @@
     {
         do
         {
-            params->mask[params->wordlen] = current->chr + 'a' - 1;
+            params->mask[params->wordlen] = 
iDic.getHeader().getCharFromCode(current->chr);
             params->wordlen ++;
-            Dic_search_cross_rec(params, oWordList, current);
+            Dic_search_cross_rec(iDic, params, oWordList, current);
             params->wordlen --;
             params->mask[params->wordlen] = '.';
         }
@@ -420,10 +348,10 @@
     {
         do
         {
-            if (current->chr == (unsigned int)(params->mask[params->wordlen] & 
DIC_CHAR_MASK))
+            if (current->chr == 
iDic.getHeader().getCodeFromChar(params->mask[params->wordlen]))
             {
                 params->wordlen ++;
-                Dic_search_cross_rec(params, oWordList, current);
+                Dic_search_cross_rec(iDic, params, oWordList, current);
                 params->wordlen --;
                 break;
             }
@@ -433,46 +361,26 @@
 }
 
 
-static void Dic_search_Cros_inner(const Dictionary &iDic, const string &iMask,
-                                  list<string> &oWordList)
+void DicSearch::searchCros(const Dictionary &iDic, const wstring &iMask,
+                           list<wstring> &oWordList)
 {
+    if (iMask == L"")
+        return;
+
     struct params_cross_t params;
 
     int i;
     for (i = 0; i < DIC_WORD_MAX && iMask[i]; i++)
     {
-        if (isalpha(iMask[i]))
-            params.mask[i] = (iMask[i] & DIC_CHAR_MASK) + 'A' - 1;
+        if (iswalpha(iMask[i]))
+            params.mask[i] = towupper(iMask[i]);
         else
             params.mask[i] = '.';
     }
     params.mask[i] = '\0';
 
-    params.dic            = &iDic;
     params.wordlen        = 0;
-    Dic_search_cross_rec(&params, oWordList, iDic.getDawg() + iDic.getRoot());
-}
-
-
-/**
- * Wrapper around Dic_search_Cros_inner, until we have multibyte support in
- * the dictionary
- */
-void DicSearch::searchCros(const Dictionary &iDic, const wstring &iMask,
-                           list<wstring> &oWordList)
-{
-    if (iMask == L"")
-        return;
-
-    list<string> tmpWordList;
-    // Do the actual work
-    Dic_search_Cros_inner(iDic, convertToMb(iMask), tmpWordList);
-
-    list<string>::const_iterator it;
-    for (it = tmpWordList.begin(); it != tmpWordList.end(); it++)
-    {
-        oWordList.push_back(convertToWc(*it));
-    }
+    Dic_search_cross_rec(iDic, &params, oWordList, iDic.getDawg() + 
iDic.getRoot());
 }
 
 /****************************************/
@@ -511,7 +419,7 @@
     {
         /* the current letter is current->chr */
         next_state = params->automaton_field->getNextState(state, 
current->chr);
-        /* 1 : the letter appears in the automaton as is */
+        /* 1: the letter appears in the automaton as is */
         if (next_state)
         {
             params->word[params->wordlen] = current->chr + 'a' - 1;
@@ -557,7 +465,7 @@
     if (value)
     {
 #ifdef DEBUG_FLEX_IS_BROKEN
-        fprintf(stderr, "parser error at pos %d - %d : %s\n",
+        fprintf(stderr, "parser error at pos %d - %d: %s\n",
                 report.pos1, report.pos2, report.msg);
 #endif
         regexp_delete_tree(root);

Index: dic/header.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/header.cpp,v
retrieving revision 1.1.2.7
retrieving revision 1.1.2.8
diff -u -b -r1.1.2.7 -r1.1.2.8
--- dic/header.cpp      21 Nov 2007 16:25:44 -0000      1.1.2.7
+++ dic/header.cpp      27 Nov 2007 18:01:04 -0000      1.1.2.8
@@ -78,6 +78,7 @@
 // Do not change these values, as they impact the size of the structure
 #define _USER_HOST_MAX_ 24
 #define _MAX_DIC_NAME_SIZE_ 32
+#define _MAX_LETTERS_NB_ 63
 #define _MAX_LETTERS_SIZE_ 80
 
 /** Extension of the old format */
@@ -89,7 +90,7 @@
     uint64_t compileDate;
 
     // Compression algorithm (1 = DAWG, 2 = GADDAG)
-    char algorithm;
+    uint8_t algorithm;
     // Endianness (XXX: currently unused)
     char bigEndian;
 
@@ -100,12 +101,22 @@
 
     // Letters used in the dictionary
     // We should have: nbLetters <= lettersSize <= _MAX_LETTERS_SIZE_
+    // and: nbLetters <= _MAX_LETTERS_NB_
     // The letters themselves, in UTF-8
     char letters[_MAX_LETTERS_SIZE_];
     // Size taken by the letters
     uint32_t lettersSize;
     // Number of letters (XXX: in theory useless, but allows a sanity check)
     uint32_t nbLetters;
+
+    // Points of the letters (indexed by their code)
+    uint8_t points[_MAX_LETTERS_NB_];
+    // Frequency of the letters (indexedy their code)
+    uint8_t frequency[_MAX_LETTERS_NB_];
+    // Bitfield indicating whether letters are vowels
+    uint64_t vowels;
+    // Bitfield indicating whether letters are consonants
+    uint64_t consonants;
     //@}
 };
 
@@ -122,11 +133,41 @@
 }
 
 
-Header::Header(const Dict_header_info &iInfo)
+Header::Header(const DictHeaderInfo &iInfo)
 {
     // Use the latest serialization format
     m_version = 1;
 
+    // Sanity checks
+    if (iInfo.letters.size() >= _MAX_LETTERS_NB_)
+    {
+        ostringstream ss;
+        ss << _MAX_LETTERS_NB_;
+        throw DicException("Header::Header: Too many different letters for "
+                           "the current format; only " + ss.str() +
+                           " are supported");
+    }
+    if (iInfo.points.size() != iInfo.letters.size())
+    {
+        throw DicException("Header::Header: Different sizes for "
+                           "iInfo.points and iInfo.letters");
+    }
+    if (iInfo.frequency.size() != iInfo.letters.size())
+    {
+        throw DicException("Header::Header: Different sizes for "
+                           "iInfo.frequency and iInfo.letters");
+    }
+    if (iInfo.vowels.size() != iInfo.letters.size())
+    {
+        throw DicException("Header::Header: Different sizes for "
+                           "iInfo.vowels and iInfo.letters");
+    }
+    if (iInfo.consonants.size() != iInfo.letters.size())
+    {
+        throw DicException("Header::Header: Different sizes for "
+                           "iInfo.consonants and iInfo.letters");
+    }
+
     m_root = iInfo.root;
     m_nbWords = iInfo.nwords;
     m_nodesUsed = iInfo.nodesused;
@@ -135,13 +176,12 @@
     m_edgesSaved = iInfo.edgessaved;
     m_type = iInfo.dawg ? kDAWG : kGADDAG;
     m_dicName = iInfo.dicName;
-    // First protection, but it is not enough
-    if (iInfo.letters.size() >= _MAX_LETTERS_SIZE_)
-    {
-        throw DicException("Header::Header: Too many different letters for "
-                           "the current format");
-    }
     m_letters = iInfo.letters;
+    m_points = iInfo.points;
+    m_frequency = iInfo.frequency;
+    m_vowels = iInfo.vowels;
+    m_consonants = iInfo.consonants;
+
     buildMapCodeFromChar();
 }
 
@@ -244,6 +284,21 @@
         {
             throw DicException("Header::read: inconsistent header");
         }
+
+        // Letters points and frequency
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            m_points.push_back(aHeaderExt.points[i]);
+            m_frequency.push_back(aHeaderExt.frequency[i]);
+        }
+
+        // Vowels and consonants
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            m_vowels.push_back(aHeaderExt.vowels & (1 << i));
+            m_consonants.push_back(aHeaderExt.consonants & (1 << i));
+        }
+
     }
 }
 
@@ -284,6 +339,24 @@
                         _MAX_LETTERS_SIZE_, "dictionary letters");
         aHeaderExt.nbLetters = (uint32_t)m_letters.size();
 
+        // Letters points and frequency
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            aHeaderExt.points[i] = m_points[i];
+            aHeaderExt.frequency[i] = m_frequency[i];
+        }
+
+        // Vowels and consonants
+        aHeaderExt.vowels = 0;
+        aHeaderExt.consonants = 0;
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            if (m_vowels[i])
+                aHeaderExt.vowels |= 1 << i;
+            if (m_consonants[i])
+                aHeaderExt.consonants |= 1 << i;
+        }
+
         // Write the extension
         oStream.write((char*)&aHeaderExt, sizeof(Dict_header_ext));
         if (!oStream.good())
@@ -344,7 +417,6 @@
 
 void Header::print() const
 {
-    printf("============================\n");
     printf("dictionary name: %s\n", convertToMb(m_dicName).c_str());
     printf("dictionary type: %s\n", m_type == kDAWG ? "DAWG" : "GADDAG");
     printf("letters: %s\n", convertToMb(m_letters).c_str());
@@ -353,26 +425,16 @@
     printf("header size: %u bytes\n", sizeof(Dict_header_old) +
            m_version ? sizeof(Dict_header_ext) : 0);
     printf("root: %d (edge)\n", m_root);
-//     printf("root: %7u (byte)\n", m_root * sizeof(Dawg_edge));
     printf("nodes: %d used + %d saved\n", m_nodesUsed, m_nodesSaved);
     printf("edges: %d used + %d saved\n", m_edgesUsed, m_edgesSaved);
-    printf("============================\n");
-
-#if 0
-#define OO(IDENT) (unsigned long)offsetof(Dict_header_old, IDENT)
-
-    printf("Dictionary header information\n");
-    printf("0x%02lx ident      : %s\n",       OO(ident)     , 
_COMPIL_KEYWORD_);
-    printf("0x%02lx unused 1   : %6d %06x\n", OO(unused_1)  , header.unused_1  
, header.unused_1);
-    printf("0x%02lx unused 2   : %6d %06x\n", OO(unused_2)  , header.unused_2  
, header.unused_2);
-    printf("0x%02lx root       : %6d %06x\n", OO(root)      , m_root      , 
m_root);
-    printf("0x%02lx words      : %6d %06x\n", OO(nwords)    , m_nbWords   , 
m_nbWords);
-    printf("0x%02lx edges used : %6d %06x\n", OO(edgesused) , m_edgesUsed , 
m_edgesUsed);
-    printf("0x%02lx nodes used : %6d %06x\n", OO(nodesused) , m_nodesUsed , 
m_nodesUsed);
-    printf("0x%02lx edges saved: %6d %06x\n", OO(edgessaved), m_edgesSaved, 
m_edgesSaved);
-    printf("0x%02lx nodes saved: %6d %06x\n", OO(nodessaved), m_nodesSaved, 
m_nodesSaved);
-    printf("\n");
-    printf("sizeof(header) = 0x%lx (%lu)\n", sizeof(header), sizeof(header));
-#endif
+    printf("===============================================\n");
+    printf("letter | points | frequency | vowel | consonant\n");
+    printf("-------+--------+-----------+-------+----------\n");
+    for (unsigned int i = 0; i < m_letters.size(); ++i)
+    {
+        printf("   %lc   |   %2d   |    %2d     |   %d   |    %d\n", 
m_letters[i],
+               m_points[i], m_frequency[i], m_vowels[i], m_consonants[i]);
+    }
+    printf("===============================================\n");
 }
 

Index: dic/header.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/header.h,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -u -b -r1.1.2.5 -r1.1.2.6
--- dic/header.h        21 Nov 2007 16:25:44 -0000      1.1.2.5
+++ dic/header.h        27 Nov 2007 18:01:05 -0000      1.1.2.6
@@ -22,6 +22,7 @@
 
 #include <iosfwd>
 #include <map>
+#include <vector>
 
 using namespace std;
 
@@ -31,24 +32,28 @@
  * Note: this structure doesn't pretend to map the way the data is stored in a
  * file. For (de)serialization, always use a Header object
  */
-struct Dict_header_info
+struct DictHeaderInfo
 {
-    int root;
-    int nwords;
-    unsigned int edgesused;
-    unsigned int nodesused;
-    unsigned int nodessaved;
-    unsigned int edgessaved;
+    uint32_t root;
+    uint32_t nwords;
+    uint32_t edgesused;
+    uint32_t nodesused;
+    uint32_t nodessaved;
+    uint32_t edgessaved;
     bool dawg;
-    wstring letters;
     wstring dicName;
+    wstring letters;
+    vector<uint8_t> points;
+    vector<uint8_t> frequency;
+    vector<bool> vowels;
+    vector<bool> consonants;
 };
 
 
 /**
  * Dictionary header.
  * There are 2 ways to create a Header object:
- *  - fill a Dict_header_info structure and give it in the constructor of the
+ *  - fill a DictHeaderInfo structure and give it in the constructor of the
  *    Header class (usually to call write() afterwards)
  *  - give it an input stream on a compiled dictionary
  *
@@ -82,7 +87,7 @@
      * Constructor from a filled structure
      * @param iInfo: info needed to build the header
      */
-    Header(const Dict_header_info &iInfo);
+    Header(const DictHeaderInfo &iInfo);
 
     /// Getters
     //@{
@@ -94,6 +99,10 @@
     unsigned int getNbEdgesSaved() const { return m_edgesSaved; }
     DictType     getType()         const { return m_type; }
     wstring      getLetters()      const { return m_letters; }
+    uint8_t      getPoints(unsigned int iCode) const { return m_points[iCode - 
1]; }
+    uint8_t      getFrequency(unsigned int iCode) const { return 
m_frequency[iCode - 1]; }
+    bool         isVowel(unsigned int iCode) const { return m_vowels[iCode - 
1]; }
+    bool         isConsonant(unsigned int iCode) const { return 
m_consonants[iCode - 1]; }
     //@}
 
     /**
@@ -138,6 +147,18 @@
     /// The letters constituting the words of the dictionary
     wstring m_letters;
 
+    /// Points of the letters
+    vector<uint8_t> m_points;
+
+    /// Frequency of the letters
+    vector<uint8_t> m_frequency;
+
+    /// Vowels
+    vector<bool> m_vowels;
+
+    /// Consonants
+    vector<bool> m_consonants;
+
     map<wchar_t, unsigned int> m_mapCodeFromChar;
 
     /**

Index: game/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/game/Makefile.am,v
retrieving revision 1.13.2.1
retrieving revision 1.13.2.2
diff -u -b -r1.13.2.1 -r1.13.2.2
--- game/Makefile.am    15 Oct 2006 11:07:55 -0000      1.13.2.1
+++ game/Makefile.am    27 Nov 2007 18:01:05 -0000      1.13.2.2
@@ -23,7 +23,6 @@
 libgame_a_SOURCES=           \
        ai_percent.cpp ai_percent.h     \
        ai_player.h                     \
-       tile.cpp tile.h                 \
        bag.cpp bag.h                   \
        coord.cpp coord.h               \
        cross.cpp cross.h               \

Index: game/bag.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/bag.cpp,v
retrieving revision 1.7.2.1
retrieving revision 1.7.2.2
diff -u -b -r1.7.2.1 -r1.7.2.2
--- game/bag.cpp        23 Dec 2006 13:51:13 -0000      1.7.2.1
+++ game/bag.cpp        27 Nov 2007 18:01:05 -0000      1.7.2.2
@@ -20,22 +20,17 @@
 
 #include <string>
 
-#include "tile.h"
+#include <dic.h>
 #include "bag.h"
 #include "debug.h"
 
 
-Bag::Bag()
-{
-    init();
-}
-
-
-void Bag::init()
+Bag::Bag(const Dictionary &iDic)
+    : m_dic(iDic)
 {
     m_ntiles = 0;
-    const list<Tile>& allTiles = Tile::getAllTiles();
-    list<Tile>::const_iterator it;
+    const vector<Tile>& allTiles = m_dic.getAllTiles();
+    vector<Tile>::const_iterator it;
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
         m_tilesMap[*it] = it->maxNumber();
@@ -115,7 +110,7 @@
         n -= it->second;
     }
     ASSERT(false, "We should not come here");
-    return Tile::dummy();
+    return Tile();
 }
 
 

Index: game/bag.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/bag.h,v
retrieving revision 1.8.2.1
retrieving revision 1.8.2.2
diff -u -b -r1.8.2.1 -r1.8.2.2
--- game/bag.h  23 Dec 2006 16:48:33 -0000      1.8.2.1
+++ game/bag.h  27 Nov 2007 18:01:05 -0000      1.8.2.2
@@ -21,11 +21,13 @@
 #ifndef _BAG_H_
 #define _BAG_H_
 
-#include "tile.h"
 #include <map>
+#include "tile.h"
 
 using std::map;
 
+class Dictionary;
+
 
 /**
  * A bag stores the set of free tiles for the game.
@@ -33,9 +35,7 @@
 class Bag
 {
 public:
-    Bag();
-    virtual ~Bag() {}
-    void init();
+    Bag(const Dictionary &iDic);
 
     /// Take a tile in the bag
     void takeTile(const Tile &iTile);
@@ -66,8 +66,12 @@
     void dumpAll() const;
 
 private:
+    /// Dictionary
+    const Dictionary &m_dic;
+
     /// Associate to each tile its number of occurrences in the bag
     map<Tile, int> m_tilesMap;
+
     /// Total number of tiles in the bag
     int m_ntiles;
 };

Index: game/board.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/board.cpp,v
retrieving revision 1.14.2.3
retrieving revision 1.14.2.4
diff -u -b -r1.14.2.3 -r1.14.2.4
--- game/board.cpp      11 Nov 2007 19:56:59 -0000      1.14.2.3
+++ game/board.cpp      27 Nov 2007 18:01:05 -0000      1.14.2.4
@@ -82,8 +82,8 @@
 
 
 Board::Board():
-    m_tilesRow(BOARD_REALDIM, Tile::dummy()),
-    m_tilesCol(BOARD_REALDIM, Tile::dummy()),
+    m_tilesRow(BOARD_REALDIM, Tile()),
+    m_tilesCol(BOARD_REALDIM, Tile()),
     m_jokerRow(BOARD_REALDIM, false),
     m_jokerCol(BOARD_REALDIM, false),
     m_crossRow(BOARD_REALDIM, Cross()),
@@ -205,10 +205,10 @@
         {
             if (iRound.isPlayedFromRack(i))
             {
-                m_tilesRow[row][col + i] = Tile::dummy();
+                m_tilesRow[row][col + i] = Tile();
                 m_jokerRow[row][col + i] = false;
                 m_crossRow[row][col + i].setAny();
-                m_tilesCol[col + i][row] = Tile::dummy();
+                m_tilesCol[col + i][row] = Tile();
                 m_jokerCol[col + i][row] = false;
                 m_crossCol[col + i][row].setAny();
             }
@@ -220,10 +220,10 @@
         {
             if (iRound.isPlayedFromRack(i))
             {
-                m_tilesRow[row + i][col] = Tile::dummy();
+                m_tilesRow[row + i][col] = Tile();
                 m_jokerRow[row + i][col] = false;
                 m_crossRow[row + i][col].setAny();
-                m_tilesCol[col][row + i] = Tile::dummy();
+                m_tilesCol[col][row + i] = Tile();
                 m_jokerCol[col][row + i] = false;
                 m_crossCol[col][row + i].setAny();
             }
@@ -430,11 +430,11 @@
         {
             if (m_testsRow[row][col])
             {
-                m_tilesRow[row][col] = Tile::dummy();
+                m_tilesRow[row][col] = Tile();
                 m_testsRow[row][col] = 0;
                 m_jokerRow[row][col] = false;
 
-                m_tilesCol[col][row] = Tile::dummy();
+                m_tilesCol[col][row] = Tile();
                 m_jokerCol[col][row] = false;
             }
         }

Index: game/board_cross.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/board_cross.cpp,v
retrieving revision 1.6.2.3
retrieving revision 1.6.2.4
diff -u -b -r1.6.2.3 -r1.6.2.4
--- game/board_cross.cpp        23 Dec 2006 13:51:13 -0000      1.6.2.3
+++ game/board_cross.cpp        27 Nov 2007 18:01:05 -0000      1.6.2.4
@@ -25,11 +25,14 @@
  *  \date   2005
  */
 
+#include <wctype.h>
+
 #include <dic.h>
 #include "tile.h"
 #include "board.h"
 #include "debug.h"
 
+
 static void Board_checkout_tile(const Dictionary &iDic,
                                 vector<Tile>& iTiles,
                                 vector<bool> & iJoker,
@@ -52,15 +55,15 @@
     }
 
     // FIXME: create temporary strings until the dictionary uses Tile objects
-    char leftTiles [BOARD_DIM + 1];
-    char rightTiles[BOARD_DIM + 1];
+    wchar_t leftTiles [BOARD_DIM + 1];
+    wchar_t rightTiles[BOARD_DIM + 1];
 
     for (i = left; i < index; i++)
-        leftTiles[i - left] = toupper(iTiles[i].toChar());
+        leftTiles[i - left] = towupper(iTiles[i].toChar());
     leftTiles[index - left] = 0;
 
     for (i = index + 1; !iTiles[i].isEmpty(); i++)
-        rightTiles[i - index - 1] = toupper(iTiles[i].toChar());
+        rightTiles[i - index - 1] = towupper(iTiles[i].toChar());
     rightTiles[i - index - 1] = 0;
 
     /* Tiles that can be played */
@@ -80,8 +83,8 @@
     }
 
     /* Points on the right part */
-    /* yes, it is REALLY [index+1] */
-    while (!iTiles[index+1].isEmpty())
+    /* yes, it is REALLY [index + 1] */
+    while (!iTiles[index + 1].isEmpty())
     {
         index++;
         if (!iJoker[index])

Index: game/board_search.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/board_search.cpp,v
retrieving revision 1.11.2.3
retrieving revision 1.11.2.4
diff -u -b -r1.11.2.3 -r1.11.2.4
--- game/board_search.cpp       11 Nov 2007 19:56:59 -0000      1.11.2.3
+++ game/board_search.cpp       27 Nov 2007 18:01:05 -0000      1.11.2.4
@@ -146,7 +146,7 @@
         l = iTilesMx[iRow][iCol];
         for (succ = iDic.getSucc(iNode); succ ; succ = iDic.getNext(succ))
         {
-            if (iDic.getChar(succ) == toupper(l.toChar()))
+            if ((wint_t)iDic.getChar(succ) == towupper(l.toChar()))
             {
                 ioPartialWord.addRightFromBoard(l);
                 ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
@@ -221,9 +221,9 @@
     int row, col, lastanchor;
     Round partialword;
 
-    list<Tile> rackTiles;
+    vector<Tile> rackTiles;
     iRack.getTiles(rackTiles);
-    list<Tile>::const_iterator it;
+    vector<Tile>::const_iterator it;
     bool match;
 
     for (row = 1; row <= BOARD_DIM; row++)

Index: game/freegame.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/freegame.cpp,v
retrieving revision 1.18
retrieving revision 1.18.2.1
diff -u -b -r1.18 -r1.18.2.1
--- game/freegame.cpp   22 Jan 2006 12:23:53 -0000      1.18
+++ game/freegame.cpp   27 Nov 2007 18:01:06 -0000      1.18.2.1
@@ -222,7 +222,7 @@
 
     // It is forbidden to change letters when the bag does not contain at
     // least 7 letters (this is explicitely stated in the ODS).
-    Bag bag;
+    Bag bag(*m_dic);
     realBag(bag);
     if (bag.nTiles() < 7)
     {

Index: game/game.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game.cpp,v
retrieving revision 1.31.2.3
retrieving revision 1.31.2.4
diff -u -b -r1.31.2.3 -r1.31.2.4
--- game/game.cpp       11 Nov 2007 19:56:59 -0000      1.31.2.3
+++ game/game.cpp       27 Nov 2007 18:01:06 -0000      1.31.2.4
@@ -39,7 +39,7 @@
 const int Game::BONUS_POINTS = 50;
 
 Game::Game(const Dictionary &iDic):
-    m_dic(&iDic)
+    m_dic(&iDic), m_bag(iDic)
 {
     m_variant = kNONE;
     m_points = 0;
@@ -93,7 +93,7 @@
                 // Is the represented letter still available in the bag?
                 // FIXME: this way to get the represented letter sucks...
                 Tile t(towupper(iRound.getTile(i).toChar()));
-                Bag bag;
+                Bag bag(*m_dic);
                 realBag(bag);
                 // FIXME: realBag() does not give us a real bag in this
                 // particular case! This is because Player::endTurn() is called
@@ -252,7 +252,7 @@
     // Create a copy of the bag in which we can do everything we want,
     // and take from it the tiles of the players rack so that "bag"
     // contains the right number of tiles.
-    Bag bag;
+    Bag bag(*m_dic);
     realBag(bag);
 
     if (mode == RACK_NEW && nold != 0)
@@ -403,8 +403,8 @@
  */
 bool Game::rackInBag(const Rack &iRack, const Bag &iBag) const
 {
-    const list<Tile>& allTiles = Tile::getAllTiles();
-    list<Tile>::const_iterator it;
+    const vector<Tile>& allTiles = m_dic->getAllTiles();
+    vector<Tile>::const_iterator it;
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
         if (iRack.in(*it) > iBag.in(*it))

Index: game/history.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/history.cpp,v
retrieving revision 1.10.2.1
retrieving revision 1.10.2.2
diff -u -b -r1.10.2.1 -r1.10.2.2
--- game/history.cpp    13 Jan 2007 21:37:45 -0000      1.10.2.1
+++ game/history.cpp    27 Nov 2007 18:01:06 -0000      1.10.2.2
@@ -51,11 +51,7 @@
 {
     for (unsigned int i = 0; i < m_history.size(); i++)
     {
-        if (m_history[i] != NULL)
-        {
             delete m_history[i];
-            m_history[i] = NULL;
-        }
     }
 }
 
@@ -145,7 +141,7 @@
         delete t;
     }
 
-    // now we have the previous played round in back()
+    // Now we have the previous played round in back()
     Turn* t = m_history.back();
     t->setNum(0);
     t->setPlayer(0);

Index: game/pldrack.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/pldrack.cpp,v
retrieving revision 1.9
retrieving revision 1.9.2.1
diff -u -b -r1.9 -r1.9.2.1
--- game/pldrack.cpp    22 Jan 2006 12:23:53 -0000      1.9
+++ game/pldrack.cpp    27 Nov 2007 18:01:06 -0000      1.9.2.1
@@ -122,29 +122,17 @@
 
 void PlayedRack::setOld(const Rack &iRack)
 {
-    list<Tile> l;
+    vector<Tile> l;
     iRack.getTiles(l);
-
-    m_oldTiles.clear();
-    list<Tile>::const_iterator it;
-    for (it = l.begin(); it != l.end(); it++)
-    {
-        addOld(*it);
-    }
+    m_oldTiles = l;
 }
 
 
 void PlayedRack::setNew(const Rack &iRack)
 {
-    list<Tile> l;
+    vector<Tile> l;
     iRack.getTiles(l);
-
-    m_newTiles.clear();
-    list<Tile>::const_iterator it;
-    for (it = l.begin(); it != l.end(); it++)
-    {
-        addNew(*it);
-    }
+    m_newTiles = l;
 }
 
 int PlayedRack::setManual(const wstring& iLetters)
@@ -152,7 +140,7 @@
     unsigned int i;
     reset();
 
-    if (iLetters.size() == 0)
+    if (iLetters.empty())
     {
         return 0; /* empty is ok */
     }

Index: game/rack.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/rack.cpp,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -b -r1.7 -r1.7.2.1
--- game/rack.cpp       22 Jan 2006 12:23:53 -0000      1.7
+++ game/rack.cpp       27 Nov 2007 18:01:06 -0000      1.7.2.1
@@ -22,50 +22,53 @@
  *  \file   rack.cpp
  *  \brief  Rack class : multiset of tiles
  *  \author Antoine Fraboulet & Olivier Teuliere
- *  \date   2002 - 2005
+ *  \date   2002 - 2007
  */
 
 #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)
+    : m_ntiles(0)
+{
+}
+
+
+unsigned int Rack::in(const Tile &t) const
 {
+    map<Tile, unsigned int>::const_iterator it = m_tiles.find(t);
+    if (it == m_tiles.end())
+        return 0;
+    return it->second;
 }
 
+
 void Rack::remove(const Tile &t)
 {
     ASSERT(in(t),
            "The rack does not contain the letter " + convertToMb(t.toChar()));
-    m_tiles[t.toCode()]--;
+    m_tiles[t]--;
     m_ntiles--;
 }
 
 
 void Rack::clear()
 {
-    for (unsigned int i = 0; i < m_tiles.size(); i++)
-    {
-        m_tiles[i] = 0;
-    }
+    m_tiles.clear();
     m_ntiles = 0;
 }
 
 
-void Rack::getTiles(list<Tile> &oTiles) const
+void Rack::getTiles(vector<Tile> &oTiles) const
 {
-    for (unsigned int i = MIN_CODE; i < m_tiles.size(); i++)
-    {
-        for (unsigned int j = 0; j < m_tiles[i]; j++)
+    oTiles.reserve(m_ntiles);
+    map<Tile, unsigned int>::const_iterator it;
+    for (it = m_tiles.begin(); it != m_tiles.end(); ++it)
         {
-            oTiles.push_back(Tile::GetTileFromCode(i));
-        }
+        // Add it->second copies of the tile at the end of the vector
+        oTiles.insert(oTiles.end(), it->second, it->first);
     }
 }
 
@@ -73,12 +76,11 @@
 wstring Rack::toString()
 {
     wstring rs;
-    for (unsigned int i = MIN_CODE; i < m_tiles.size(); i++)
-    {
-        for (unsigned int j = 0; j < m_tiles[i]; j++)
+    map<Tile, unsigned int>::const_iterator it;
+    for (it = m_tiles.begin(); it != m_tiles.end(); ++it)
         {
-            rs += Tile::GetTileFromCode(i).toChar();
-        }
+        // Append it->second copies of the char
+        rs.append(it->second, it->first.toChar());
     }
     return rs;
 }

Index: game/rack.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/rack.h,v
retrieving revision 1.9
retrieving revision 1.9.2.1
diff -u -b -r1.9 -r1.9.2.1
--- game/rack.h 22 Jan 2006 12:23:53 -0000      1.9
+++ game/rack.h 27 Nov 2007 18:01:06 -0000      1.9.2.1
@@ -22,15 +22,15 @@
  *  \file   rack.h
  *  \brief  Rack class : multiset of tiles
  *  \author Antoine Fraboulet & Olivier Teuliere
- *  \date   2002 - 2005
+ *  \date   2002 - 2007
  */
 
 #ifndef _RACK_H_
 #define _RACK_H_
 
 #include "tile.h"
-#include <set>
-#include <list>
+#include <map>
+#include <vector>
 #include <string>
 
 using namespace std;
@@ -49,17 +49,17 @@
     int nTiles() const          { return m_ntiles; }
     bool isEmpty() const        { return nTiles() == 0; }
 
-    unsigned int in(const Tile &t) const { return m_tiles[t.toCode()]; }
-    void add(const Tile &t)     { m_tiles[t.toCode()]++; m_ntiles++; }
+    unsigned int in(const Tile &t) const;
+    void add(const Tile &t)     { m_tiles[t]++; m_ntiles++; }
     void remove(const Tile &t);
     void clear();
-    void getTiles(list<Tile> &oTiles) const;
+    void getTiles(vector<Tile> &oTiles) const;
 
     wstring toString();
 
 private:
-    /// Vector indexed by tile codes, containing the number of tiles
-    vector<unsigned int> m_tiles;
+    /// Map associating to tiles their number in the rack
+    map<Tile, unsigned int> m_tiles;
     int m_ntiles;
 };
 

Index: utils/eliottxt.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/eliottxt.cpp,v
retrieving revision 1.16.2.6
retrieving revision 1.16.2.7
diff -u -b -r1.16.2.6 -r1.16.2.7
--- utils/eliottxt.cpp  21 Nov 2007 16:25:45 -0000      1.16.2.6
+++ utils/eliottxt.cpp  27 Nov 2007 18:01:06 -0000      1.16.2.7
@@ -705,7 +705,8 @@
 }
 
 
-void eliot_regexp_build_default_llist(struct search_RegE_list_t &llist)
+void eliot_regexp_build_default_llist(const Dictionary &iDic,
+                                      struct search_RegE_list_t &llist)
 {
     memset(&llist, 0, sizeof(llist));
 
@@ -729,8 +730,8 @@
         memset(llist.letters[i], 0, sizeof(llist.letters[i]));
     }
 
-    const list<Tile>& allTiles = Tile::getAllTiles();
-    list<Tile>::const_iterator it;
+    const vector<Tile>& allTiles = iDic.getAllTiles();
+    vector<Tile>::const_iterator it;
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
         if (! it->isJoker() && ! it->isEmpty())
@@ -765,7 +766,7 @@
 #define DIC_RE_MAX (3*DIC_WORD_MAX) // yes, it's 3
 
     struct search_RegE_list_t llist;
-    eliot_regexp_build_default_llist(llist);
+    eliot_regexp_build_default_llist(iDic, llist);
 
     wchar_t *regexp = wcstok(NULL, delim, state);
     wchar_t *cnres = wcstok(NULL, delim, state);

Index: utils/game_io.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/game_io.cpp,v
retrieving revision 1.9.2.2
retrieving revision 1.9.2.3
diff -u -b -r1.9.2.2 -r1.9.2.3
--- utils/game_io.cpp   11 Nov 2007 19:56:59 -0000      1.9.2.2
+++ utils/game_io.cpp   27 Nov 2007 18:01:07 -0000      1.9.2.3
@@ -20,8 +20,9 @@
 
 #include <iomanip>
 #include <string>
-#include "stdlib.h"
+#include <stdlib.h>
 
+#include <dic.h>
 #include "game_io.h"
 #include "game.h"
 #include "training.h"
@@ -172,8 +173,8 @@
 
 void GameIO::printNonPlayed(ostream &out, const Game &iGame)
 {
-    const list<Tile>& allTiles = Tile::getAllTiles();
-    list<Tile>::const_iterator it;
+    const vector<Tile>& allTiles = iGame.getDic().getAllTiles();
+    vector<Tile>::const_iterator it;
 
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {

Index: wxwin/auxframes.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/auxframes.cc,v
retrieving revision 1.22.2.2
retrieving revision 1.22.2.3
diff -u -b -r1.22.2.2 -r1.22.2.3
--- wxwin/auxframes.cc  11 Nov 2007 19:57:00 -0000      1.22.2.2
+++ wxwin/auxframes.cc  27 Nov 2007 18:01:07 -0000      1.22.2.3
@@ -182,8 +182,8 @@
 
     tiles->ClearAll();
 
-    std::list<Tile>::const_iterator it;
-    const std::list<Tile>& allTiles = Tile::getAllTiles();
+    std::vector<Tile>::const_iterator it;
+    const std::vector<Tile>& allTiles = m_game.getDic().getAllTiles();
     for (index = 0, it = allTiles.begin(); it != allTiles.end(); index++, it++)
     {
        n = m_game.getBag().in(*it);

Index: wxwin/searchpanel.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/searchpanel.cc,v
retrieving revision 1.15.2.1
retrieving revision 1.15.2.2
diff -u -b -r1.15.2.1 -r1.15.2.2
--- wxwin/searchpanel.cc        15 Oct 2006 11:07:55 -0000      1.15.2.1
+++ wxwin/searchpanel.cc        27 Nov 2007 18:01:07 -0000      1.15.2.2
@@ -273,8 +273,8 @@
       memset(llist.letters[i],0,sizeof(llist.letters[i]));
     }
 
-  const std::list<Tile>& allTiles = Tile::getAllTiles();
-  std::list<Tile>::const_iterator it;
+  const std::vector<Tile>& allTiles = dic->getAllTiles();
+  std::vector<Tile>::const_iterator it;
   for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
       if (! it->isJoker() && ! it->isEmpty())

Index: dic/tile.cpp
===================================================================
RCS file: dic/tile.cpp
diff -N dic/tile.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/tile.cpp        27 Nov 2007 18:01:05 -0000      1.1.2.1
@@ -0,0 +1,156 @@
+/*****************************************************************************
+ * Copyright (C) 1999-2007 Eliot
+ * Authors: Olivier Teuliere  <ipkiss address@hidden gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include <sstream>
+#include <string>
+#include <wctype.h>
+#include "tile.h"
+#include "header.h"
+#include "encoding.h"
+#include "dic_exception.h"
+
+
+const Header * Tile::m_header = NULL;
+Tile Tile::m_TheJoker;
+
+
+Tile::Tile(wchar_t c)
+{
+    if (iswalpha(c))
+    {
+        m_joker = iswlower(c);
+        m_char = towupper(c);
+        m_code = m_header->getCodeFromChar(m_char);
+    }
+    else if (c == TILE_JOKER)
+    {
+        m_joker = true;
+        m_char = TILE_JOKER;
+        m_code = m_header->getLetters().size() + 1;
+    }
+    else if (c == TILE_DUMMY)
+    {
+        // The char and the code are chosen to be different from any possible
+        // real tile
+        m_joker = false;
+        m_char = TILE_DUMMY;
+        m_code = 0;
+    }
+    else
+    {
+        ostringstream ss;
+        ss << "Tile::Tile: Unknown character: " << convertToMb(c);
+        throw DicException(ss.str());
+    }
+}
+
+
+bool Tile::isVowel() const
+{
+    if (m_code == 0)
+        throw DicException("Tile::isVowel: Invalid tile");
+    if (m_joker)
+        return true;
+    return m_header->isVowel(m_code);
+}
+
+
+bool Tile::isConsonant() const
+{
+    if (m_code == 0)
+        throw DicException("Tile::isConsonant: Invalid tile");
+    if (m_joker)
+        return true;
+    return m_header->isConsonant(m_code);
+}
+
+
+unsigned int Tile::maxNumber() const
+{
+    if (m_code == 0)
+        throw DicException("Tile::maxNumber: Invalid tile");
+    if (m_joker)
+        return 2;
+    return m_header->getFrequency(m_code);
+}
+
+
+unsigned int Tile::getPoints() const
+{
+    if (m_code == 0)
+        throw DicException("Tile::getPoints: Invalid tile");
+    if (m_joker)
+        return 0;
+    return m_header->getPoints(m_code);
+}
+
+
+wchar_t Tile::toChar() const
+{
+    if (m_joker)
+    {
+        if (iswalpha(m_char))
+            return towlower(m_char);
+        else
+            return TILE_JOKER;
+    }
+    return m_char;
+}
+
+
+unsigned int Tile::toCode() const
+{
+    return m_code;
+}
+
+
+bool Tile::operator<(const Tile &iOther) const
+{
+    if (m_joker)
+        return false;
+    else if (iOther.m_joker)
+        return true;
+    else
+        return m_char < iOther.m_char;
+}
+
+
+bool Tile::operator==(const Tile &iOther) const
+{
+    if (m_joker || iOther.m_joker)
+    {
+        if (m_joker != iOther.m_joker)
+            return false;
+        return m_char == iOther.m_char;
+    }
+    return m_char == iOther.m_char;
+}
+
+
+bool Tile::operator!=(const Tile &iOther) const
+{
+    return !(*this == iOther);
+}
+
+/// Local Variables:
+/// mode: c++
+/// mode: hs-minor
+/// c-basic-offset: 4
+/// indent-tabs-mode: nil
+/// End:

Index: dic/tile.h
===================================================================
RCS file: dic/tile.h
diff -N dic/tile.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/tile.h  27 Nov 2007 18:01:05 -0000      1.1.2.1
@@ -0,0 +1,97 @@
+/*****************************************************************************
+ * Copyright (C) 1999-2007 Eliot
+ * Authors: Olivier Teuliere  <ipkiss address@hidden gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#ifndef _TILE_H_
+#define _TILE_H_
+
+#include <list>
+#include <vector>
+
+using namespace std;
+
+class Header;
+
+
+/*************************
+ * A Tile is the internal representation
+ * used within the game library to
+ * handle letters
+ *************************/
+
+// XXX
+#define TILE_DUMMY L'%'
+#define TILE_JOKER L'?'
+
+
+class Tile
+{
+    friend class Dictionary;
+public:
+
+    // a lowercase character is always a joker
+    // - this permits to detect joker in already played games
+    // - we need to pay attention when inserting characters taken
+    //   from user input
+
+    Tile(wchar_t c = TILE_DUMMY);
+    virtual ~Tile() {}
+
+    bool isEmpty() const        { return m_char == TILE_DUMMY; }
+    bool isJoker() const        { return m_joker; }
+    bool isVowel() const;
+    bool isConsonant() const;
+    unsigned int maxNumber() const;
+    unsigned int getPoints() const;
+    wchar_t toChar() const;
+    unsigned int toCode() const;
+
+    static const Tile &Joker()  { return m_TheJoker; }
+
+    bool operator <(const Tile &iOther) const;
+    bool operator ==(const Tile &iOther) const;
+    bool operator !=(const Tile &iOther) const;
+
+private:
+    wchar_t m_char;
+    bool m_joker;
+
+    /**
+     * 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 Tile m_TheJoker;
+
+    /// Dictionary header
+    static const Header *m_header;
+
+    /// Update the dictionary header
+    static void SetHeader(const Header &iHeader) { m_header = &iHeader; }
+};
+
+#endif
+
+/// Local Variables:
+/// mode: c++
+/// mode: hs-minor
+/// c-basic-offset: 4
+/// indent-tabs-mode: nil
+/// End:

Index: m4/ax_boost_base.m4
===================================================================
RCS file: m4/ax_boost_base.m4
diff -N m4/ax_boost_base.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ m4/ax_boost_base.m4 27 Nov 2007 18:01:06 -0000      1.1.2.1
@@ -0,0 +1,198 @@
+##### http://autoconf-archive.cryp.to/ax_boost_base.html
+#
+# SYNOPSIS
+#
+#   AX_BOOST_BASE([MINIMUM-VERSION])
+#
+# DESCRIPTION
+#
+#   Test for the Boost C++ libraries of a particular version (or newer)
+#
+#   If no path to the installed boost library is given the macro
+#   searchs under /usr, /usr/local, and /opt, and evaluates the
+#   $BOOST_ROOT environment variable. Further documentation is
+#   available at <http://randspringer.de/boost/index.html>.
+#
+#   This macro calls:
+#
+#     AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
+#
+#   And sets:
+#
+#     HAVE_BOOST
+#
+# LAST MODIFICATION
+#
+#   2007-03-15
+#
+# COPYLEFT
+#
+#   Copyright (c) 2007 Thomas Porschberg <address@hidden>
+#
+#   Copying and distribution of this file, with or without
+#   modification, are permitted in any medium without royalty provided
+#   the copyright notice and this notice are preserved.
+
+AC_DEFUN([AX_BOOST_BASE],
+[
+AC_ARG_WITH([boost],
+       AS_HELP_STRING([--with-boost@<:@=DIR@:>@], [use boost (default is yes) 
- it is possible to specify the root directory for boost (optional)]),
+       [
+    if test "$withval" = "no"; then
+               want_boost="no"
+    elif test "$withval" = "yes"; then
+        want_boost="yes"
+        ac_boost_path=""
+    else
+           want_boost="yes"
+        ac_boost_path="$withval"
+       fi
+    ],
+    [want_boost="yes"])
+
+if test "x$want_boost" = "xyes"; then
+       boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
+       boost_lib_version_req_shorten=`expr $boost_lib_version_req : 
'\([[0-9]]*\.[[0-9]]*\)'`
+       boost_lib_version_req_major=`expr $boost_lib_version_req : 
'\([[0-9]]*\)'`
+       boost_lib_version_req_minor=`expr $boost_lib_version_req : 
'[[0-9]]*\.\([[0-9]]*\)'`
+       boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : 
'[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+       if test "x$boost_lib_version_req_sub_minor" = "x" ; then
+               boost_lib_version_req_sub_minor="0"
+       fi
+       WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+  
$boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
+       AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
+       succeeded=no
+
+       dnl first we check the system location for boost libraries
+       dnl this location ist chosen if boost libraries are installed with the 
--layout=system option
+       dnl or if you install boost with RPM
+       if test "$ac_boost_path" != ""; then
+               BOOST_LDFLAGS="-L$ac_boost_path/lib"
+               BOOST_CPPFLAGS="-I$ac_boost_path/include"
+       else
+               for ac_boost_path_tmp in /usr /usr/local /opt ; do
+                       if test -d "$ac_boost_path_tmp/include/boost" && test 
-r "$ac_boost_path_tmp/include/boost"; then
+                               BOOST_LDFLAGS="-L$ac_boost_path_tmp/lib"
+                               BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
+                               break;
+                       fi
+               done
+       fi
+
+       CPPFLAGS_SAVED="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+       export CPPFLAGS
+
+       LDFLAGS_SAVED="$LDFLAGS"
+       LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+       export LDFLAGS
+
+       AC_LANG_PUSH(C++)
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+       @%:@include <boost/version.hpp>
+       ]], [[
+       #if BOOST_VERSION >= $WANT_BOOST_VERSION
+       // Everything is okay
+       #else
+       #  error Boost version is too old
+       #endif
+       ]])],[
+        AC_MSG_RESULT(yes)
+       succeeded=yes
+       found_system=yes
+               ],[
+               ])
+       AC_LANG_POP([C++])
+
+
+
+       dnl if we found no boost with system layout we search for boost 
libraries
+       dnl built and installed without the --layout=system option or for a 
staged(not installed) version
+       if test "x$succeeded" != "xyes"; then
+               _version=0
+               if test "$ac_boost_path" != ""; then
+                               BOOST_LDFLAGS="-L$ac_boost_path/lib"
+                       if test -d "$ac_boost_path" && test -r 
"$ac_boost_path"; then
+                               for i in `ls -d $ac_boost_path/include/boost-* 
2>/dev/null`; do
+                                       _version_tmp=`echo $i | sed 
"s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+                                       V_CHECK=`expr $_version_tmp \> 
$_version`
+                                       if test "$V_CHECK" = "1" ; then
+                                               _version=$_version_tmp
+                                       fi
+                                       VERSION_UNDERSCORE=`echo $_version | 
sed 's/\./_/'`
+                                       
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
+                               done
+                       fi
+               else
+                       for ac_boost_path in /usr /usr/local /opt ; do
+                               if test -d "$ac_boost_path" && test -r 
"$ac_boost_path"; then
+                                       for i in `ls -d 
$ac_boost_path/include/boost-* 2>/dev/null`; do
+                                               _version_tmp=`echo $i | sed 
"s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+                                               V_CHECK=`expr $_version_tmp \> 
$_version`
+                                               if test "$V_CHECK" = "1" ; then
+                                                       _version=$_version_tmp
+                                                       best_path=$ac_boost_path
+                                               fi
+                                       done
+                               fi
+                       done
+
+                       VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
+                       
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
+                       BOOST_LDFLAGS="-L$best_path/lib"
+
+                       if test "x$BOOST_ROOT" != "x"; then
+                               if test -d "$BOOST_ROOT" && test -r 
"$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/lib" && test -r 
"$BOOST_ROOT/stage/lib"; then
+                                       version_dir=`expr //$BOOST_ROOT : 
'.*/\(.*\)'`
+                                       stage_version=`echo $version_dir | sed 
's/boost_//' | sed 's/_/./g'`
+                                       stage_version_shorten=`expr 
$stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
+                                       V_CHECK=`expr $stage_version_shorten 
\>\= $_version`
+                                       if test "$V_CHECK" = "1" ; then
+                                               AC_MSG_NOTICE(We will use a 
staged boost library from $BOOST_ROOT)
+                                               BOOST_CPPFLAGS="-I$BOOST_ROOT"
+                                               
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/lib"
+                                       fi
+                               fi
+                       fi
+               fi
+
+               CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+               export CPPFLAGS
+               LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+               export LDFLAGS
+
+               AC_LANG_PUSH(C++)
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+               @%:@include <boost/version.hpp>
+               ]], [[
+               #if BOOST_VERSION >= $WANT_BOOST_VERSION
+               // Everything is okay
+               #else
+               #  error Boost version is too old
+               #endif
+               ]])],[
+               AC_MSG_RESULT(yes)
+               succeeded=yes
+               found_system=yes
+                       ],[
+               ])
+               AC_LANG_POP([C++])
+       fi
+
+       if test "$succeeded" != "yes" ; then
+               if test "$_version" = "0" ; then
+                       AC_MSG_ERROR([[We could not detect the boost libraries 
(version $boost_lib_version_req_shorten or higher). If you have a staged boost 
library (still not installed) please specify \$BOOST_ROOT in your environment 
and do not give a PATH to --with-boost option.  If you are sure you have boost 
installed, then check your version number looking in <boost/version.hpp>. See 
http://randspringer.de/boost for more documentation.]])
+               else
+                       AC_MSG_NOTICE([Your boost libraries seems to old 
(version $_version).])
+               fi
+       else
+               AC_SUBST(BOOST_CPPFLAGS)
+               AC_SUBST(BOOST_LDFLAGS)
+               AC_DEFINE(HAVE_BOOST,,[define if the Boost library is 
available])
+       fi
+
+        CPPFLAGS="$CPPFLAGS_SAVED"
+               LDFLAGS="$LDFLAGS_SAVED"
+fi
+
+])

Index: game/tile.cpp
===================================================================
RCS file: game/tile.cpp
diff -N game/tile.cpp
--- game/tile.cpp       22 Jan 2006 12:23:53 -0000      1.7
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,233 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *****************************************************************************/
-
-#include "tile.h"
-#include <wctype.h>
-
-
-/*************************
- * French tiles
- * Zero + 26 letters + joker
- * tiles ares supposed to be contiguous and joker is separated
- *************************/
-
-#define TILE_START     'A'
-#define TILE_END       'Z'
-#define TILE_JOKER     '?'
-#define TILE_DUMMY     '%'
-
-#define TILE_IDX_DUMMY   0
-#define TILE_IDX_START   1
-#define TILE_IDX_END    26
-#define TILE_IDX_JOKER  27
-
-#define TILES_NUMBER    28
-
-/* The jokers and the 'Y' can be considered both as vowels or consonants */
-const unsigned int Tiles_vowels[TILES_NUMBER] =
-{
-/* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ? */
-   0,1,0,0,0, 1,0,0,0,1,0, 0,0,0,0,1,0,0,0,0,0,1,0, 0, 0, 1, 0,1
-};
-
-const unsigned int Tiles_consonants[TILES_NUMBER] =
-{
-/* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ? */
-   0,0,1,1,1, 0,1,1,1,0,1, 1,1,1,1,0,1,1,1,1,1,0,1, 1, 1, 1, 1,1
-};
-
-const unsigned int Tiles_numbers[TILES_NUMBER] =
-{
-/* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ? */
-   0,9,2,2,3,15,2,2,2,8,1, 1,5,3,6,6,2,1,6,6,6,6,2, 1, 1, 1, 1,2
-};
-
-const unsigned int Tiles_points[TILES_NUMBER] =
-{
-/* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ? */
-   0,1,3,3,2, 1,4,2,4,1,8,10,1,2,1,1,3,8,1,1,1,1,4,10,10,10,10,0
-};
-
-/***************************
- ***************************/
-
-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(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 = towupper(c);
-        m_code = m_char - 'A' + 1;
-    }
-    else
-    {
-        m_joker = false;
-        m_dummy = true;
-        m_char = 0;
-        m_code = 0;
-    }
-}
-
-
-bool Tile::isVowel() const
-{
-    if (m_dummy)
-        return false;
-    if (m_joker)
-        return Tiles_vowels[TILE_IDX_JOKER];
-    return Tiles_vowels[TILE_IDX_START + m_char - TILE_START];
-}
-
-
-bool Tile::isConsonant() const
-{
-    if (m_dummy)
-        return false;
-    if (m_joker)
-        return Tiles_consonants[TILE_IDX_JOKER];
-    return Tiles_consonants[TILE_IDX_START + m_char - TILE_START];
-}
-
-
-unsigned int Tile::maxNumber() const
-{
-    if (m_dummy)
-        return false;
-    if (m_joker)
-        return Tiles_numbers[TILE_IDX_JOKER];
-    return Tiles_numbers[TILE_IDX_START + m_char - TILE_START];
-}
-
-
-unsigned int Tile::getPoints() const
-{
-    if (m_dummy)
-        return false;
-    if (m_joker)
-        return Tiles_points[TILE_IDX_JOKER];
-    return Tiles_points[TILE_IDX_START + m_char - TILE_START];
-}
-
-
-const list<Tile>& Tile::getAllTiles()
-{
-    if (Tile::m_tilesList.size() == 0)
-    {
-        // XXX: this should be filled from a "language file" instead
-        for (char i = TILE_START; i <= TILE_END; i++)
-            Tile::m_tilesList.push_back(Tile(i));
-        m_tilesList.push_back(Tile(TILE_JOKER));
-    }
-    return Tile::m_tilesList;
-}
-
-
-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 (iswalpha(m_char))
-            return towlower(m_char);
-        else
-            return TILE_JOKER;
-    }
-    return m_char;
-}
-
-unsigned int Tile::toCode() const
-{
-    return m_code;
-}
-
-bool Tile::operator <(const Tile &iOther) const
-{
-    if (iOther.m_dummy)
-        return false;
-    else if (m_dummy)
-        return true;
-    else if (m_joker)
-        return false;
-    else if (iOther.m_joker)
-        return true;
-    else
-        return m_char < iOther.m_char;
-}
-
-
-bool Tile::operator ==(const Tile &iOther) const
-{
-    if (m_dummy || iOther.m_dummy)
-        return m_dummy == iOther.m_dummy;
-    if (m_joker || iOther.m_joker)
-    {
-        if (m_joker != iOther.m_joker)
-            return false;
-        return m_char == iOther.m_char;
-    }
-    return m_char == iOther.m_char;
-//     return (m_joker && iOther.m_joker && m_char == iOther.m_char) ||
-//            (m_dummy && iOther.m_dummy) ||
-//            (!m_dummy && !iOther.m_dummy
-//             && !m_joker && !iOther.m_joker
-//             && m_char == iOther.m_char);
-}
-
-
-bool Tile::operator !=(const Tile &iOther) const
-{
-    return !(*this == iOther);
-}
-
-/// Local Variables:
-/// mode: c++
-/// mode: hs-minor
-/// c-basic-offset: 4
-/// indent-tabs-mode: nil
-/// End:

Index: game/tile.h
===================================================================
RCS file: game/tile.h
diff -N game/tile.h
--- game/tile.h 22 Jan 2006 12:23:53 -0000      1.8
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,95 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *****************************************************************************/
-
-#ifndef _TILE_H_
-#define _TILE_H_
-
-#include <list>
-#include <vector>
-
-using namespace std;
-
-
-/*************************
- * A Tile is the internal representation
- * used within the game library to
- * handle letters
- *************************/
-
-class Tile
-{
-public:
-
-  // a lowercase character always a joker
-  // - this permits to detect joker in already played games
-  // - we need to pay attention when inserting character taken
-  //   from user input
-
-    Tile(wchar_t c = 0);
-    virtual ~Tile() {}
-
-    bool isEmpty() const        { return m_dummy; }
-    bool isJoker() const        { return m_joker; }
-    bool isVowel() const;
-    bool isConsonant() const;
-    unsigned int maxNumber() const;
-    unsigned int getPoints() 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:
-    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
-    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
-
-/// Local Variables:
-/// mode: c++
-/// mode: hs-minor
-/// c-basic-offset: 4
-/// indent-tabs-mode: nil
-/// End:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]