eliot-dev
[Top][All Lists]
Advanced

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

[Eliot-dev] eliot game/ai_percent.cpp game/ai_percent.h gam...


From: Olivier Teuličre
Subject: [Eliot-dev] eliot game/ai_percent.cpp game/ai_percent.h gam...
Date: Thu, 22 Jan 2009 18:30:33 +0000

CVSROOT:        /cvsroot/eliot
Module name:    eliot
Changes by:     Olivier Teulière <ipkiss>       09/01/22 18:30:32

Modified files:
        game           : ai_percent.cpp ai_percent.h game.cpp 
                         results.cpp results.h settings.cpp training.cpp 
                         training.h 
        qt             : prefs_dialog.cpp 
        qt/ui          : prefs_dialog.ui 
        test           : training_search.input training_search.ref 

Log message:
        Sorting the search results happens to be quite slow, often much slower 
than the search itself.
        But we don't need to sort them all the time, and in general we don't 
even need to keep all the rounds.
        
        This commit greatly improves the search performance by filtering the 
results in 3 different ways, depending on the context:
         - A limit to the number of results can be given (useful for the 
training mode). The kept results are the best ones, not the first ones found by 
the search.
         - When only the best round is needed (when the AI is playing with 
level 100, or when preparing the rack for an explosive game), we don't need to 
keep rounds with a lower score
         - When the AI has a level lower than 100, it is still possible to skip 
many rounds
        
        The search limit in training mode is configurable (defaulting to 100) 
and can be deactivated.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/eliot/game/ai_percent.cpp?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/game/ai_percent.h?cvsroot=eliot&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game.cpp?cvsroot=eliot&r1=1.52&r2=1.53
http://cvs.savannah.gnu.org/viewcvs/eliot/game/results.cpp?cvsroot=eliot&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/eliot/game/results.h?cvsroot=eliot&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/eliot/game/settings.cpp?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/game/training.cpp?cvsroot=eliot&r1=1.30&r2=1.31
http://cvs.savannah.gnu.org/viewcvs/eliot/game/training.h?cvsroot=eliot&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/prefs_dialog.cpp?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/ui/prefs_dialog.ui?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_search.input?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_search.ref?cvsroot=eliot&r1=1.9&r2=1.10

Patches:
Index: game/ai_percent.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/ai_percent.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- game/ai_percent.cpp 30 Nov 2008 21:09:37 -0000      1.11
+++ game/ai_percent.cpp 22 Jan 2009 18:30:22 -0000      1.12
@@ -29,29 +29,39 @@
 
 
 AIPercent::AIPercent(float iPercent)
-    : m_percent(iPercent)
 {
-    // Ensure the decimal value of the percentage is between 0 and 1
-    if (m_percent < 0)
-        m_percent = 0;
-    if (m_percent > 1)
-        m_percent = 1;
+    if (iPercent < 0)
+        iPercent = 0;
+    if (iPercent > 1)
+        iPercent = 1;
+
+    // Use BestResults to be slightly faster when the percentage is 100%
+    if (iPercent == 1)
+        m_results = new BestResults;
+    else
+        m_results = new PercentResults(iPercent);
+}
+
+
+AIPercent::~AIPercent()
+{
+    delete m_results;
 }
 
 
 void AIPercent::compute(const Dictionary &iDic, const Board &iBoard, bool 
iFirstWord)
 {
-    m_results.clear();
+    m_results->clear();
 
     Rack rack;
     getCurrentRack().getRack(rack);
-    m_results.search(iDic, iBoard, rack, iFirstWord);
+    m_results->search(iDic, iBoard, rack, iFirstWord);
 }
 
 
 Move AIPercent::getMove() const
 {
-    if (m_results.size() == 0)
+    if (m_results->size() == 0)
     {
         // If there is no result, pass the turn.
         // XXX: it is forbidden in duplicate mode (even passing is forbidden),
@@ -60,25 +70,7 @@
     }
     else
     {
-        // If there are results, apply the algorithm
-        double wantedScore = m_percent * m_results.get(0).getPoints();
-        // Look for the first round giving at least 'wantedScore' points
-        // Browse the results 10 by 10 (a dichotomy would be better, but this
-        // is not performance critical)
-        unsigned int index = 0;
-        while (index < m_results.size() &&
-               m_results.get(index).getPoints() > wantedScore)
-        {
-            index += 10;
-        }
-        // Now the wanted round is in the last 10 indices
-        if (index >= m_results.size())
-            index = m_results.size() - 1;
-        while (m_results.get(index).getPoints() < wantedScore)
-        {
-            --index;
-        }
-        return Move(m_results.get(index));
+        return Move(m_results->get(0));
     }
 }
 

Index: game/ai_percent.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/ai_percent.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- game/ai_percent.h   22 Nov 2008 14:40:25 -0000      1.10
+++ game/ai_percent.h   22 Jan 2009 18:30:28 -0000      1.11
@@ -40,7 +40,7 @@
 public:
     /// Constructor, taking the percentage (0.0 <= iPercent <= 1.0)
     AIPercent(float iPercent);
-    virtual ~AIPercent() {}
+    virtual ~AIPercent();
 
     /**
      * This method does the actual computation. It will be called before any
@@ -52,11 +52,8 @@
     virtual Move getMove() const;
 
 private:
-    /// Percentage used for this player
-    float m_percent;
-
     /// Container for all the found solutions
-    Results m_results;
+    Results *m_results;
 };
 
 #endif

Index: game/game.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game.cpp,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -b -r1.52 -r1.53
--- game/game.cpp       14 Jan 2009 21:53:37 -0000      1.52
+++ game/game.cpp       22 Jan 2009 18:30:28 -0000      1.53
@@ -331,7 +331,7 @@
         Rack rack;
         pld.getRack(rack);
 
-        Results res;
+        BestResults res;
         res.search(getDic(), getBoard(), rack,  
getHistory().beforeFirstRound());
         if (res.size())
         {

Index: game/results.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/results.cpp,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- game/results.cpp    22 Nov 2008 14:40:26 -0000      1.16
+++ game/results.cpp    22 Jan 2009 18:30:30 -0000      1.17
@@ -19,9 +19,11 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *****************************************************************************/
 
+#include <boost/foreach.hpp>
 #include <algorithm>
 #include <functional>
 #include <cwctype>
+#include <cmath>
 
 #include "tile.h"
 #include "round.h"
@@ -98,27 +100,204 @@
 }
 
 
-void Results::search(const Dictionary &iDic, const Board &iBoard,
+void Results::sort()
+{
+    less_points lp;
+    std::sort(m_rounds.begin(), m_rounds.end(), lp);
+}
+
+
+BestResults::BestResults()
+    : m_bestScore(0)
+{
+}
+
+
+void BestResults::search(const Dictionary &iDic, const Board &iBoard,
                      const Rack &iRack, bool iFirstWord)
 {
     clear();
 
     if (iFirstWord)
-    {
         iBoard.searchFirst(iDic, iRack, *this);
+    else
+        iBoard.search(iDic, iRack, *this);
+
+    sort();
+}
+
+
+void BestResults::add(const Round &iRound)
+{
+    // Ignore too low scores
+    if (m_bestScore > iRound.getPoints())
+        return;
+
+    if (m_bestScore < iRound.getPoints())
+    {
+        // New best score: clear the stored results
+        m_bestScore = iRound.getPoints();
+        m_rounds.clear();
+    }
+    m_rounds.push_back(iRound);
+}
+
+
+void BestResults::clear()
+{
+    m_rounds.clear();
+    m_bestScore = 0;
+}
+
+
+
+PercentResults::PercentResults(float iPercent)
+    : m_percent(iPercent)
+{
+}
+
+class Predicate
+{
+public:
+    Predicate(int iPoints) : m_chosenPoints(iPoints) {}
+    bool operator()(const Round &iRound) const
+    {
+        return iRound.getPoints() != m_chosenPoints;
     }
+
+private:
+    const int m_chosenPoints;
+};
+
+
+void PercentResults::search(const Dictionary &iDic, const Board &iBoard,
+                            const Rack &iRack, bool iFirstWord)
+{
+    clear();
+
+    if (iFirstWord)
+        iBoard.searchFirst(iDic, iRack, *this);
     else
+        iBoard.search(iDic, iRack, *this);
+
+    if (m_rounds.empty())
+        return;
+
+    // At this point, add() has been called, so the best score is valid
+
+    // Find the lowest score at least equal to the min_score
+    int chosenPoints = m_bestScore;
+    BOOST_FOREACH(const Round &iRound, m_rounds)
+    {
+        int points = iRound.getPoints();
+        if (points >= m_minScore && points < chosenPoints)
     {
+            chosenPoints = points;
+        }
+    }
+
+    // Keep only the rounds with the "chosenPoints" score
+    std::remove_if(m_rounds.begin(), m_rounds.end(), Predicate(chosenPoints));
+    ASSERT(!m_rounds.empty(), "Bug in PercentResults");
+
+    // Sort the remaining rounds
+    sort();
+}
+
+
+void PercentResults::add(const Round &iRound)
+{
+    // Ignore too low scores
+    if (m_minScore > iRound.getPoints())
+        return;
+
+    if (m_bestScore < iRound.getPoints())
+    {
+        m_bestScore = iRound.getPoints();
+        m_minScore = (int)ceil(m_bestScore * m_percent);
+    }
+    m_rounds.push_back(iRound);
+}
+
+
+void PercentResults::clear()
+{
+    m_rounds.clear();
+    m_bestScore = 0;
+    m_minScore = 0;
+}
+
+
+
+LimitResults::LimitResults(int iLimit)
+    : m_limit(iLimit), m_total(0), m_minScore(-1)
+{
+}
+
+
+void LimitResults::search(const Dictionary &iDic, const Board &iBoard,
+                          const Rack &iRack, bool iFirstWord)
+{
+    clear();
+
+    if (iFirstWord)
+        iBoard.searchFirst(iDic, iRack, *this);
+    else
         iBoard.search(iDic, iRack, *this);
+
+    if (m_rounds.empty())
+        return;
+
+    // Sort the rounds
+    sort();
+
+    // Truncate the results to respect the limit
+    if (m_limit != 0 && m_rounds.size() > (unsigned int) m_limit)
+        m_rounds.resize(m_limit);
+}
+
+
+void LimitResults::add(const Round &iRound)
+{
+    // If we ignore the limit, simply add the round
+    if (m_limit == 0)
+    {
+        m_rounds.push_back(iRound);
+        return;
     }
 
-    sortByPoints();
+    // Ignore too low scores
+    if (m_minScore >= iRound.getPoints())
+        return;
+
+    // Add the round
+    m_rounds.push_back(iRound);
+    ++m_total;
+    ++m_scoresCount[iRound.getPoints()];
+
+    // Can we increase the minimum score required?
+    if (m_total - m_scoresCount[m_minScore] >= m_limit)
+    {
+        // Yes! "Forget" the rounds of score m_minScore
+        // They are still present in m_rounds, but they will be removed
+        // for real later in the search() method
+        m_total -= m_scoresCount[m_minScore];
+        m_scoresCount.erase(m_minScore);
+
+        // Find the new min score
+        map<int, int>::const_iterator it =
+            m_scoresCount.lower_bound(m_minScore);
+        ASSERT(it != m_scoresCount.end(), "Bug in LimitResults::add())");
+        m_minScore = it->first;
+    }
 }
 
 
-void Results::sortByPoints()
+void LimitResults::clear()
 {
-    less_points lp;
-    std::sort(m_rounds.begin(), m_rounds.end(), lp);
+    m_rounds.clear();
+    m_scoresCount.clear();
+    m_minScore = -1;
+    m_total = 0;
 }
 

Index: game/results.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/results.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- game/results.h      14 Jan 2009 21:53:38 -0000      1.12
+++ game/results.h      22 Jan 2009 18:30:30 -0000      1.13
@@ -23,6 +23,7 @@
 #define _RESULTS_H_
 
 #include <vector>
+#include <map>
 #include "round.h"
 
 using namespace std;
@@ -33,31 +34,104 @@
 
 
 /**
- * This class allows to perform a search on the board for a given rack,
- * and it offers accessors to the resulting rounds.
- * The rounds are sorted by decreasing number of points, then by alphabetical
- * order (case insensitive), then by coordinates, then by alphabetical orderi
- * again (case sensitive this time).
+ * This abstract class defines the interface to perform a search on the board
+ * for a given rack, and it offers accessors to the resulting rounds.
+ * Not all the rounds found by the search are necessarily kept, it depends
+ * on the implementation (see below in the file for the various
+ * implementations).
+ *
+ * After the search, the rounds are sorted by decreasing number of points,
+ * then by alphabetical order (case insensitive), then by coordinates,
+ * then by alphabetical order again (case sensitive this time).
  */
 class Results
 {
 public:
     unsigned int size() const    { return m_rounds.size(); }
-    void clear()        { m_rounds.clear(); }
     const Round & get(unsigned int) const;
 
-    /// Perform a search on the board
-    void search(const Dictionary &iDic, const Board &iBoard,
+    /**
+     * Perform a search on the board. Every time a word is found,
+     * the add() method will be called. At the end of the search,
+     * results are sorted.
+     */
+    virtual void search(const Dictionary &iDic, const Board &iBoard,
+                        const Rack &iRack, bool iFirstWord) = 0;
+
+    /** Add a round */
+    virtual void add(const Round &iRound) = 0;
+
+    /** Clear the stored rounds, and get ready for a new search */
+    virtual void clear() = 0;
+
+protected:
+    vector<Round> m_rounds;
+    void sort();
+};
+
+/**
+ * This implementation keeps only the rounds corresponding to the best score.
+ * If there are several rounds with the same score, they are all kept.
+ * All other rounds are ignored.
+ */
+class BestResults: public Results
+{
+public:
+    BestResults();
+    virtual void search(const Dictionary &iDic, const Board &iBoard,
                 const Rack &iRack, bool iFirstWord);
+    virtual void clear();
+    virtual void add(const Round &iRound);
 
-    // FIXME: This method is used to fill the container with the rounds,
-    // but it should not be part of the public interface
-    void add(const Round &iRound)   { m_rounds.push_back(iRound); }
+private:
+    int m_bestScore;
+};
+
+/**
+ * This implementation finds the best score possible, and keeps only
+ * the rounds whose score is closest to (but not lower than) the given
+ * percentage of the best score.
+ * All the rounds with this closest score are kept, rounds with a different
+ * score are ignored.
+ */
+class PercentResults: public Results
+{
+public:
+    /** The percentage is given as a float between 0 (0%) and 1 (100%) */
+    PercentResults(float iPercent);
+    virtual void search(const Dictionary &iDic, const Board &iBoard,
+                        const Rack &iRack, bool iFirstWord);
+    virtual void clear();
+    virtual void add(const Round &iRound);
 
 private:
-    vector<Round> m_rounds;
+    const float m_percent;
+    int m_bestScore;
+    int m_minScore;
+};
+
+/**
+ * This implementation keeps the N best rounds, N being the given limit.
+ * All other rounds are ignored.
+ * In the special case where the limit is 0, all rounds are kept (but you can
+ * expect the sorting of the rounds to be much slower...)
+ */
+class LimitResults: public Results
+{
+public:
+    LimitResults(int iLimit);
+    virtual void search(const Dictionary &iDic, const Board &iBoard,
+                        const Rack &iRack, bool iFirstWord);
+    virtual void clear();
+    virtual void add(const Round &iRound);
+
+    void setLimit(int iNewLimit) { m_limit = iNewLimit; }
 
-    void sortByPoints();
+private:
+    int m_limit;
+    map<int, int> m_scoresCount;
+    int m_total;
+    int m_minScore;
 };
 
 #endif

Index: game/settings.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/settings.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- game/settings.cpp   25 Sep 2008 20:39:38 -0000      1.6
+++ game/settings.cpp   22 Jan 2009 18:30:31 -0000      1.7
@@ -119,6 +119,18 @@
 #endif
         return fileName;
     }
+
+
+    template<typename T>
+    void copySetting(const Config &srcConf, Config &dstConf, const char *path)
+    {
+        if (srcConf.exists(path))
+        {
+            T t;
+            srcConf.lookupValue(path, t);
+            dstConf.lookup(path) = t;
+        }
+    }
 }
 
 
@@ -131,6 +143,10 @@
     // ============== General options ==============
 
     // ============== Training mode options ==============
+    Setting &training = m_conf->getRoot().add("training", Setting::TypeGroup);
+
+    // Number of search results kept in a search
+    training.add("search-limit", Setting::TypeInt) = 100;
 
     // ============== Duplicate mode options ==============
     Setting &dupli = m_conf->getRoot().add("duplicate", Setting::TypeGroup);
@@ -159,7 +175,16 @@
     // Try to read the values from the configuration file
     try
     {
-        m_conf->readFile(m_fileName.c_str());
+        // We cannot call readFile() on m_conf, as it removes the previous
+        // settings. So we create a temporary config, and copy the settings
+        // one by one...
+        Config tmpConf;
+        tmpConf.readFile(m_fileName.c_str());
+        copySetting<int>(tmpConf, *m_conf, "training.search-limit");
+        copySetting<int>(tmpConf, *m_conf, "duplicate.solo-players");
+        copySetting<int>(tmpConf, *m_conf, "duplicate.solo-value");
+        copySetting<bool>(tmpConf, *m_conf, "duplicate.reject-invalid");
+        copySetting<bool>(tmpConf, *m_conf, "freegame.reject-invalid");
     }
     catch (...)
     {
@@ -236,9 +261,11 @@
     }
 #else
     // Dummy implementation
-    if (iName == "duplicate.solo-players")
+    if (iName == "training.search-limit")
+        return 100;
+    else if (iName == "duplicate.solo-players")
         return 16;
-    else if (iName == "duplicate.solo-bonus")
+    else if (iName == "duplicate.solo-value")
         return 10;
     return 0;
 #endif

Index: game/training.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/training.cpp,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -b -r1.30 -r1.31
--- game/training.cpp   11 Jan 2009 14:20:36 -0000      1.30
+++ game/training.cpp   22 Jan 2009 18:30:31 -0000      1.31
@@ -28,8 +28,10 @@
 #   define _(String) String
 #endif
 
+#include "training.h"
 #include "dic.h"
 #include "tile.h"
+#include "settings.h"
 #include "rack.h"
 #include "round.h"
 #include "move.h"
@@ -38,14 +40,13 @@
 #include "player_move_cmd.h"
 #include "player_rack_cmd.h"
 #include "game_move_cmd.h"
-#include "training.h"
 #include "encoding.h"
 
 #include "debug.h"
 
 
 Training::Training(const Dictionary &iDic)
-    : Game(iDic)
+    : Game(iDic), m_results(1000)
 {
     // Training mode implicitly uses 1 human player
     Game::addPlayer(new HumanPlayer);
@@ -147,6 +148,8 @@
     // Search for the current player
     Rack r;
     m_players[m_currPlayer]->getCurrentRack().getRack(r);
+    int limit = Settings::Instance().getInt("training.search-limit");
+    m_results.setLimit(limit);
     m_results.search(getDic(), getBoard(), r, getHistory().beforeFirstRound());
 }
 

Index: game/training.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/training.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- game/training.h     11 Jan 2009 14:20:36 -0000      1.22
+++ game/training.h     22 Jan 2009 18:30:31 -0000      1.23
@@ -97,8 +97,8 @@
 
     void endTurn();
 
-    /// Search results, with all the possible rounds
-    Results m_results;
+    /// Search results, with all the possible rounds up to a predefined limit
+    LimitResults m_results;
 
     /// Round corresponding to the last test play (if any)
     Round m_testRound;

Index: qt/prefs_dialog.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/prefs_dialog.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- qt/prefs_dialog.cpp 4 Jan 2009 17:39:27 -0000       1.9
+++ qt/prefs_dialog.cpp 22 Jan 2009 18:30:31 -0000      1.10
@@ -64,7 +64,7 @@
         
checkBoxFreeRefuseInvalid->setChecked(Settings::Instance().getBool("freegame.reject-invalid"));
 
         // Training settings
-
+        
spinBoxTrainSearchLimit->setValue(Settings::Instance().getInt("training.search-limit"));
     }
     catch (GameException &e)
     {
@@ -133,7 +133,8 @@
                                      checkBoxFreeRefuseInvalid->isChecked());
 
         // Training settings
-
+        Settings::Instance().setInt("training.search-limit",
+                                    spinBoxTrainSearchLimit->value());
     }
     catch (GameException &e)
     {

Index: qt/ui/prefs_dialog.ui
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/ui/prefs_dialog.ui,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- qt/ui/prefs_dialog.ui       4 Jan 2009 17:39:27 -0000       1.9
+++ qt/ui/prefs_dialog.ui       22 Jan 2009 18:30:32 -0000      1.10
@@ -1,6 +1,14 @@
 <ui version="4.0" >
  <class>PrefsDialog</class>
  <widget class="QDialog" name="PrefsDialog" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>414</width>
+    <height>526</height>
+   </rect>
+  </property>
   <property name="windowTitle" >
    <string>_("Preferences")</string>
   </property>
@@ -194,6 +202,45 @@
         </property>
        </widget>
       </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout" >
+        <item>
+         <widget class="QLabel" name="label" >
+          <property name="text" >
+           <string>_("Search results limit:")</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="spinBoxTrainSearchLimit" >
+          <property name="toolTip" >
+           <string>_("Maximum number of results returned by a search. The 
returned
+results will always be the best ones. Use 0 to disable the limit (warning:
+searches yielding many results can be extremely slow in this case!).")</string>
+          </property>
+          <property name="maximum" >
+           <number>100000</number>
+          </property>
+          <property name="value" >
+           <number>100</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_2" >
+          <property name="orientation" >
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0" >
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
      </layout>
     </widget>
    </item>

Index: test/training_search.input
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_search.input,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/training_search.input  16 Apr 2005 15:47:59 -0000      1.1
+++ test/training_search.input  22 Jan 2009 18:30:32 -0000      1.2
@@ -1,3 +1,4 @@
+s i training.search-limit 1000
 e
 t QpiNZ?s
 a t

Index: test/training_search.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_search.ref,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- test/training_search.ref    23 Nov 2008 08:33:18 -0000      1.9
+++ test/training_search.ref    22 Jan 2009 18:30:32 -0000      1.10
@@ -1,5 +1,6 @@
 Using seed: 0
 [?] pour l'aide
+commande> s i training.search-limit 1000
 commande> e
 mode entraĂŽnement
 [?] pour l'aide




reply via email to

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