gnome-games r7578 - in trunk/gnome-sudoku: . src/lib



Author: thinkle
Date: Mon Apr  7 02:08:39 2008
New Revision: 7578
URL: http://svn.gnome.org/viewvc/gnome-games?rev=7578&view=rev

Log:
2008-04-06  Thomas Mills HInkle  <tmhinkle gmail com>

	* src/lib/sudoku_maker.py (SudokuMaker.get_puzzles): By default,
	randomize our new puzzle selection. Otherwise, the same puzzle
	will come up for each difficulty level until it has been finished
	or saved.
	(SudokuMaker.get_puzzles_random): A variant of the previous
	get_puzzles method that randomizes the selection. This is
	accomplished by reading the puzzle data file into memory and
	shuffling the lines around before looping through the lines until
	retrieving the desired number of puzzles. This doesn't appear to
	cause any substantial performance/memory problems (they are just
	small text files after all) but this may theoretically introduce a
	regression in the case of very large data files (large numbers of
	generated puzzles) if reading those lines into memory and
	shuffling them would cause a slow-down.
	* src/lib/game_selector.py (NewOrSavedGameSelector.make_new_game_model):
	Check to make sure we have enough puzzles for our difficulty
	level. If we're out of puzzles, print a warning and repeat a
	puzzle (reverse it so it at least looks new). If we're really out
	of puzzles (as in we somehow have an empty data file), then we
	simply don't display the icon in question for the difficulty
	level. This fixes bug #516903


Modified:
   trunk/gnome-sudoku/ChangeLog
   trunk/gnome-sudoku/src/lib/game_selector.py
   trunk/gnome-sudoku/src/lib/sudoku_maker.py

Modified: trunk/gnome-sudoku/src/lib/game_selector.py
==============================================================================
--- trunk/gnome-sudoku/src/lib/game_selector.py	(original)
+++ trunk/gnome-sudoku/src/lib/game_selector.py	Mon Apr  7 02:08:39 2008
@@ -100,9 +100,23 @@
             rng = DR.categories[cat]; label = DR.label_by_cat[cat]
             #puzzle,diff = self.sudoku_maker.get_new_puzzle(.01*random.randint(*[r*100 for r in rng]))
             #diff_val = diff.value
-            puzzle,diff_val = self.sudoku_maker.get_puzzles(1,[cat],new=True,
-                                                            exclude=saved_games_to_exclude
-                                                            )[0]
+            puzzles = self.sudoku_maker.get_puzzles(1,[cat],new=True,
+                                                    exclude=saved_games_to_exclude
+                                                    )
+            if puzzles:
+                puzzle,diff_val = puzzles[0]
+            else:
+                print 'WARNING: Repeating puzzle for difficulty %s -- generate more puzzles to avoid this.'%cat
+                puzzles = self.sudoku_maker.get_puzzles(1,[cat],new=False)
+                if puzzles:
+                    puzzle,diff_val = puzzles[0]
+                    lpuz = list(puzzle)
+                    lpuz.reverse() # we reverse the puzzle so it at least looks different :-)
+                    puzzle = ''
+                    for n in lpuz: puzzle += n
+                else:
+                    print 'WARNING: No puzzle for difficulty',cat
+                    continue
             #print 'Got new puzzle for ',cat,'difficulty:',diff
             grid = sudoku.sudoku_grid_from_string(puzzle).grid
             self.new_game_model.append(('<b><i>'+label+'</i></b>',

Modified: trunk/gnome-sudoku/src/lib/sudoku_maker.py
==============================================================================
--- trunk/gnome-sudoku/src/lib/sudoku_maker.py	(original)
+++ trunk/gnome-sudoku/src/lib/sudoku_maker.py	Mon Apr  7 02:08:39 2008
@@ -407,13 +407,63 @@
                         puzzle_list.append(puzzle)
         return puzzle_list
 
-    def get_puzzles (self, n, levels, new=True,
+    def get_puzzles_random (self, n, levels, new=True, exclude=[]):
+        """Return a list of n puzzles and difficulty values (as floats).
+
+        The puzzles will correspond as closely as possible to levels.
+        If new, we only return puzzles not yet played.
+        """
+        if not n: return []
+        assert(levels)
+        puzzles = []
+        # Open files to read puzzles...
+        puzzles_by_level = {}; files = {}
+        for l in levels:
+            files[l] = os.path.join(self.pickle_to,
+                                    l.replace(' ','_'))
+            fi = file(files[l],'r')
+            puzzles_by_level[l] = fi.readlines(); fi.close()
+            random.shuffle(puzzles_by_level[l])
+        i = 0; il = 0
+        n_per_level = {}
+        finished = []
+        while i < n and len(finished) < len(levels):
+            if il >= len(levels): il = 0
+            lev = levels[il]
+            # skip any levels that we've exhausted
+            if lev in finished:
+                il += 1
+                continue
+            try:
+                line = puzzles_by_level[lev].pop()
+            except IndexError:
+                finished.append(lev)
+            else:
+                try:
+                    p,d = line.split('\t')
+                except ValueError:
+                    print 'WARNING: invalid line %s in file %s'%(line,files[lev])
+                    continue
+                if sudoku.is_valid_puzzle(p):
+                    if (p not in exclude) and (not new or p not in self.played):
+                        puzzles.append((p,float(d)))
+                        i += 1
+                else:
+                    print 'WARNING: invalid puzzle %s in file %s'%(p,files[lev])
+            il += 1
+        if i < n:
+            print 'WARNING: Not able to provide %s puzzles in levels %s'%(n,levels)
+            print 'WARNING: Generate more puzzles if you really need this many puzzles!'
+        return puzzles    
+
+    def get_puzzles (self, n, levels, new=True, randomize=True,
                      exclude=[]):
         """Return a list of n puzzles and difficulty values (as floats).
 
         The puzzles will correspond as closely as possible to levels.
         If new, we only return puzzles not yet played.
         """
+        if randomize: return self.get_puzzles_random(n,levels,new=new,exclude=exclude)
         if not n: return []
         assert(levels)
         puzzles = []



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