From 2022dbe5995c4c4ba9deb7e0cffe3f5c98ecea6f Mon Sep 17 00:00:00 2001 From: skomoroh Date: Tue, 8 May 2007 21:21:33 +0000 Subject: [PATCH] * improved solitaire wizard git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@162 efabe8c0-fbe8-4139-b769-b5e6d273206e --- pysollib/customgame.py | 78 +++++++++++---------- pysollib/game.py | 13 +++- pysollib/layout.py | 54 +++++++++++--- pysollib/stack.py | 25 +++++++ pysollib/tile/wizarddialog.py | 43 ++++++++++-- pysollib/tk/wizarddialog.py | 42 +++++++++-- pysollib/wizardpresets.py | 128 ++++++++++++++++++++++++++++++++++ pysollib/wizardutil.py | 59 ++++++++++------ 8 files changed, 361 insertions(+), 81 deletions(-) create mode 100644 pysollib/wizardpresets.py diff --git a/pysollib/customgame.py b/pysollib/customgame.py index b768de59..bb1a0e9e 100644 --- a/pysollib/customgame.py +++ b/pysollib/customgame.py @@ -30,26 +30,32 @@ from hint import AbstractHint, DefaultHint, CautiousDefaultHint, Yukon_Hint from wizardutil import WizardWidgets +gettext = _ + # /*********************************************************************** # // # ************************************************************************/ +def get_settings(ss): + s = {} + for w in WizardWidgets: + if isinstance(w, basestring): + continue + if w.var_name in ss: + v = ss[w.var_name] + else: + v = w.default + if w.widget == 'menu': + v = dict(w.values_map)[v] + s[w.var_name] = v + return s + + class CustomGame(Game): def createGame(self): - ss = self.SETTINGS - s = {} - for w in WizardWidgets: - if isinstance(w, basestring): - continue - if w.var_name in ss: - v = ss[w.var_name] - else: - v = w.default - if w.widget == 'menu': - v = dict(w.values_map)[v] - s[w.var_name] = v + s = get_settings(self.SETTINGS) ##from pprint import pprint; pprint(s) # foundations @@ -119,17 +125,25 @@ class CustomGame(Game): } if s['talon'] is InitialDealTalonStack: layout_kw['texts'] = False - layout_kw['playcards'] = max(16, 12+s['deal_face_down']+s['deal_face_up']) + layout_kw['playcards'] = max( + 16, 12+s['deal_face_down']+s['deal_face_up']) + if s['talon'] in (DealRowRedealTalonStack, + SpiderTalonStack, + GroundForADivorceTalonStack): + layout_kw['playcards'] += 2 * s['decks'] # reserves if s['reserves_num']: kw = { - 'max_accept': s['reserves_max_accept'], + 'max_cards': s['reserves_max_accept'], } if s['reserves_max_accept']: layout_kw['reserve_class'] = StackWrapper(ReserveStack, **kw) else: layout_kw['reserve_class'] = StackWrapper(OpenStack, **kw) + if s['talon'] is DealReserveRedealTalonStack or \ + s['reserves_max_accept'] > 1: + layout_kw['reserve_texts'] = True # waste if s['talon'] is WasteTalonStack: @@ -153,19 +167,22 @@ class CustomGame(Game): ((Spider_AC_RowStack, Spider_SS_RowStack), (self._shallHighlightMatch_RK, self._shallHighlightMatch_RKW)), - ((AC_RowStack, UD_AC_RowStack, Yukon_AC_RowStack), + ((AC_RowStack, UD_AC_RowStack, + Yukon_AC_RowStack, SuperMoveAC_RowStack), (self._shallHighlightMatch_AC, self._shallHighlightMatch_ACW)), - ((SS_RowStack, UD_SS_RowStack, Yukon_SS_RowStack), + ((SS_RowStack, UD_SS_RowStack, + Yukon_SS_RowStack, SuperMoveSS_RowStack), (self._shallHighlightMatch_SS, self._shallHighlightMatch_SSW)), - ((RK_RowStack, UD_RK_RowStack, Yukon_RK_RowStack), + ((RK_RowStack, UD_RK_RowStack, + Yukon_RK_RowStack, SuperMoveRK_RowStack), (self._shallHighlightMatch_RK, self._shallHighlightMatch_RKW)), - ((SC_RowStack, UD_SC_RowStack), + ((SC_RowStack, UD_SC_RowStack, SuperMoveSC_RowStack), (self._shallHighlightMatch_SC, self._shallHighlightMatch_SCW)), - ((BO_RowStack,), + ((BO_RowStack, SuperMoveBO_RowStack), (self._shallHighlightMatch_BO, self._shallHighlightMatch_BOW)), ): @@ -214,7 +231,7 @@ class CustomGame(Game): frames=frames) frames = 0 - s = self.SETTINGS + s = get_settings(self.SETTINGS) max_cards = s['deal_max_cards'] - len(self.s.rows) if self.s.waste: max_cards -= 1 @@ -232,7 +249,7 @@ class CustomGame(Game): # deal to rows face_down = s['deal_face_down'] max_rows = s['deal_face_down'] + s['deal_face_up'] - if s['deal_type'] == 'Triangle': + if s['deal_type'] == 'triangle': # triangle for i in range(1, len(self.s.rows)): flip = (face_down <= 0) @@ -269,25 +286,12 @@ class CustomGame(Game): self.s.talon.dealCards() - def registerCustomGame(gameclass): - s = gameclass.SETTINGS - for w in WizardWidgets: - if isinstance(w, basestring): - continue - if w.var_name == 'decks': - v = s['decks'] - decks = dict(w.values_map)[v] - elif w.var_name == 'redeals': - v = s['redeals'] - redeals = dict(w.values_map)[v] - elif w.var_name == 'skill_level': - v = s['skill_level'] - skill_level = dict(w.values_map)[v] - gameid = s['gameid'] + s = get_settings(gameclass.SETTINGS) + gameid = gameclass.SETTINGS['gameid'] registerGame(GameInfo(gameid, gameclass, s['name'], GI.GT_CUSTOM | GI.GT_ORIGINAL, - decks, redeals, skill_level)) + s['decks'], s['redeals'], s['skill_level'])) diff --git a/pysollib/game.py b/pysollib/game.py index f3cd1eb6..6b67a47e 100644 --- a/pysollib/game.py +++ b/pysollib/game.py @@ -2064,15 +2064,22 @@ for %d moves. # def getQuickPlayScore(self, ncards, from_stack, to_stack): + if to_stack in self.s.reserves: + # if to_stack in reserves prefer empty stack + return 1000-len(to_stack.cards) # prefer non-empty piles in to_stack - return (len(to_stack.cards) != 0) + return 1001 + int(len(to_stack.cards) != 0) def _getSpiderQuickPlayScore(self, ncards, from_stack, to_stack): + if to_stack in self.s.reserves: + # if to_stack in reserves prefer empty stack + return 1000-len(to_stack.cards) # for spider-type stacks if to_stack.cards: # check suit - return int(from_stack.cards[-ncards].suit == to_stack.cards[-1].suit)+1 - return 0 + same_suit = from_stack.cards[-ncards].suit == to_stack.cards[-1].suit + return int(same_suit)+1002 + return 1001 # # Score (I really don't like scores in Patience games...) diff --git a/pysollib/layout.py b/pysollib/layout.py index 4f010962..8e064127 100644 --- a/pysollib/layout.py +++ b/pysollib/layout.py @@ -192,6 +192,14 @@ class Layout: s.reserves.append(reserve_class(r.x, r.y, game)) # default self.defaultAll() + # reserves texts + if self.s.reserves and ('reserve_texts' in kw) and kw['reserve_texts']: + game = self.game + for i in range(len(game.s.reserves)): + s1 = game.s.reserves[i] + s2 = self.s.reserves[i] + s1.texts.ncards = self.defaultText(s2) + # # public util for use by class Game @@ -333,7 +341,8 @@ class Layout: # - left bottom: talon, waste # - def freeCellLayout(self, rows, reserves, waste=0, texts=0, playcards=18): + def freeCellLayout(self, rows, reserves, waste=0, + texts=0, reserve_texts=False, playcards=18): S = self.__createStack CW, CH = self.CW, self.CH XM, YM = self.XM, self.YM @@ -351,12 +360,17 @@ class Layout: # set size so that at least 2/3 of a card is visible with 18 cards h = CH*2/3 + (playcards-1)*self.YOFFSET h = YM + YS + max(h, 3*YS) + if reserves and reserve_texts: + h += self.TEXT_HEIGHT # create reserves & foundations x, y = (w - (toprows*XS - XM))/2, YM if reserves: for i in range(reserves): - self.s.reserves.append(S(x, y)) + s = S(x, y) + self.s.reserves.append(s) + if reserve_texts: + self._setText(s, anchor="s") x += XS x += XS for suit in range(suits): @@ -366,6 +380,8 @@ class Layout: # create rows x, y = (w - (rows*XS - XM))/2, YM + YS + if reserves and reserve_texts: + y += self.TEXT_HEIGHT for i in range(rows): self.s.rows.append(S(x, y)) x += XS @@ -399,7 +415,8 @@ class Layout: # - bottom: reserves # - def gypsyLayout(self, rows, waste=0, reserves=0, texts=1, playcards=25): + def gypsyLayout(self, rows, waste=0, reserves=0, + texts=1, reserve_texts=False, playcards=25): S = self.__createStack CW, CH = self.CW, self.CH XM, YM = self.XM, self.YM @@ -415,6 +432,8 @@ class Layout: # set size so that at least 2/3 of a card is visible with 25 cards h = CH*2/3 + (playcards-1)*self.YOFFSET h = YM + max(h, (suits+1)*YS) + if reserves and reserve_texts: + h += self.TEXT_HEIGHT # create rows x, y = XM, YM @@ -451,7 +470,10 @@ class Layout: # create reserves x, y = XM, h-YS for i in range(reserves): - self.s.reserves.append(S(x, y)) + s = S(x, y) + self.s.reserves.append(s) + if reserve_texts: + self._setText(s, anchor="n") x += XS # set window @@ -464,7 +486,8 @@ class Layout: # - bottom: foundations, waste, talon # - def harpLayout(self, rows, waste, reserves=0, texts=1, playcards=19): + def harpLayout(self, rows, waste, reserves=0, + texts=1, reserve_texts=False, playcards=19): S = self.__createStack CW, CH = self.CW, self.CH XM, YM = self.XM, self.YM @@ -483,14 +506,21 @@ class Layout: if texts: h += self.TEXT_HEIGHT if reserves: h += YS + if reserves and reserve_texts: + h += self.TEXT_HEIGHT # top y = YM if reserves: + if reserve_texts: + y += self.TEXT_HEIGHT x = (w - (reserves*XS - XM))/2 for i in range(reserves): - self.s.reserves.append(S(x, y)) + s = S(x, y) + self.s.reserves.append(s) x += XS + if reserve_texts: + self._setText(s, anchor="n") y += YS x = (w - (rows*XS - XM))/2 for i in range(rows): @@ -505,6 +535,8 @@ class Layout: x += XS if reserves: yy = YM + YS - CH/2 + if reserve_texts: + yy += self.TEXT_HEIGHT else: yy = -999 self.setRegion(self.s.rows, (-999, yy, 999999, y - YS / 2)) @@ -532,7 +564,8 @@ class Layout: # def klondikeLayout(self, rows, waste, reserves=0, - texts=1, playcards=16, center=1, text_height=0): + texts=1, reserve_texts=False, + playcards=16, center=1, text_height=0): S = self.__createStack CW, CH = self.CW, self.CH XM, YM = self.XM, self.YM @@ -549,6 +582,8 @@ class Layout: h = CH * 2 / 3 + (playcards - 1) * self.YOFFSET h = max(h, 2 * YS) h += YM + YS * foundrows + if reserves and reserve_texts: + h += self.TEXT_HEIGHT # top ##text_height = 0 @@ -601,8 +636,11 @@ class Layout: y = h h += YS for i in range(reserves): - self.s.reserves.append(S(x, y)) + s = S(x, y) + self.s.reserves.append(s) x += XS + if reserve_texts: + self._setText(s, anchor="n") # set window self.size = (XM + maxrows * XS, h) diff --git a/pysollib/stack.py b/pysollib/stack.py index 4c2d0e6e..e1ceb546 100644 --- a/pysollib/stack.py +++ b/pysollib/stack.py @@ -52,6 +52,8 @@ __all__ = ['cardsFaceUp', 'RedealTalonStack', 'DealRowRedealTalonStack', 'DealReserveRedealTalonStack', + 'SpiderTalonStack', + 'GroundForADivorceTalonStack', 'OpenStack', 'AbstractFoundationStack', 'SS_FoundationStack', @@ -1875,6 +1877,29 @@ class DealReserveRedealTalonStack(DealRowRedealTalonStack): return DealRowRedealTalonStack.dealCards(self, sound=sound, rows=self.game.s.reserves) +# Spider Talons +class SpiderTalonStack(DealRowRedealTalonStack): + def canDealCards(self): + if not DealRowRedealTalonStack.canDealCards(self): + return False + # no row may be empty + for r in self.game.s.rows: + if not r.cards: + return False + return True + +class GroundForADivorceTalonStack(DealRowRedealTalonStack): + # A single click deals a new cards to each non-empty row. + def dealCards(self, sound=1): + if self.cards: + rows = filter(lambda r: r.cards, self.game.s.rows) +## if not rows: +## # deal one card to first row if all rows are emtpy +## rows = self.game.s.rows[:1] + return DealRowRedealTalonStack.dealRowAvail(self, rows=rows, + sound=sound) + return 0 + # /*********************************************************************** # // An OpenStack is a stack where cards can be placed and dragged diff --git a/pysollib/tile/wizarddialog.py b/pysollib/tile/wizarddialog.py index 226b96e9..90ff2e9f 100644 --- a/pysollib/tile/wizarddialog.py +++ b/pysollib/tile/wizarddialog.py @@ -28,12 +28,15 @@ from Tile import * # PySol imports from pysollib.mfxutil import destruct, kwdefault, KwStruct, Struct from pysollib.wizardutil import WizardWidgets +from pysollib.wizardpresets import presets # Toolkit imports from tkwidget import MfxDialog from tkwidget import PysolScale +gettext = _ + # /*********************************************************************** # // # ************************************************************************/ @@ -62,7 +65,21 @@ class WizardDialog(MfxDialog): Label(frame, text=w.label).grid(row=row, column=0) - if w.widget == 'entry': + if w.widget == 'preset': + if w.variable is None: + w.variable = StringVar() + values = [gettext(v) for v in w.values] + default = gettext(w.default) + values.remove(default) + values.sort() + values.insert(0, default) + cb = Combobox(frame, values=tuple(values), + textvariable=w.variable, + state='readonly', width=32) + cb.grid(row=row, column=1, sticky='ew', padx=2, pady=2) + callback = lambda e, w=w: self.presetSelected(e, w) + cb.bind('<>', callback) + elif w.widget == 'entry': if w.variable is None: w.variable = StringVar() en = Entry(frame, textvariable=w.variable) @@ -70,7 +87,8 @@ class WizardDialog(MfxDialog): elif w.widget == 'menu': if w.variable is None: w.variable = StringVar() - cb = Combobox(frame, values=tuple(w.values), + values = [gettext(v) for v in w.values] + cb = Combobox(frame, values=tuple(values), textvariable=w.variable, state='readonly', width=32) cb.grid(row=row, column=1, sticky='ew', padx=2, pady=2) @@ -94,17 +112,32 @@ class WizardDialog(MfxDialog): ch.grid(row=row, column=1, sticky='ew', padx=2, pady=2) if w.current_value is None: - w.variable.set(w.default) + w.variable.set(gettext(w.default)) else: - w.variable.set(w.current_value) + w.variable.set(gettext(w.current_value)) row += 1 - focus = self.createButtons(bottom_frame, kw) self.mainloop(focus, kw.timeout) + def presetSelected(self, e, w): + n = e.widget.get() + n = w.translation_map[n] + p = presets[n] + for w in WizardWidgets: + if isinstance(w, basestring): + continue + if w.var_name in p: + v = p[w.var_name] + else: + v = w.default + if w.widget in ('menu', 'preset'): + v = gettext(v) + w.variable.set(v) + + def initKw(self, kw): kw = KwStruct(kw, strings=(_('&OK'), _('&Cancel')), diff --git a/pysollib/tk/wizarddialog.py b/pysollib/tk/wizarddialog.py index c737a657..8d775034 100644 --- a/pysollib/tk/wizarddialog.py +++ b/pysollib/tk/wizarddialog.py @@ -29,11 +29,14 @@ from tabpage import TabPageSet # PySol imports from pysollib.mfxutil import destruct, kwdefault, KwStruct, Struct from pysollib.wizardutil import WizardWidgets +from pysollib.wizardpresets import presets # Toolkit imports from tkwidget import MfxDialog +gettext = _ + # /*********************************************************************** # // # ************************************************************************/ @@ -63,7 +66,19 @@ class WizardDialog(MfxDialog): Label(frame, text=w.label).grid(row=row, column=0, padx=2) - if w.widget == 'entry': + if w.widget == 'preset': + if w.variable is None: + w.variable = StringVar() + values = [gettext(v) for v in w.values] + default = gettext(w.default) + values.remove(default) + values.sort() + values.insert(0, default) + callback = lambda v, w=w: self.presetSelected(v, w) + om = OptionMenu(frame, w.variable, + command=callback, *values) + om.grid(row=row, column=1, sticky='ew', padx=2) + elif w.widget == 'entry': if w.variable is None: w.variable = StringVar() en = Entry(frame, textvariable=w.variable) @@ -71,15 +86,15 @@ class WizardDialog(MfxDialog): elif w.widget == 'menu': if w.variable is None: w.variable = StringVar() - om = OptionMenu(frame, w.variable, *w.values) + values = [gettext(v) for v in w.values] + om = OptionMenu(frame, w.variable, *values) om.grid(row=row, column=1, sticky='ew', padx=2) elif w.widget == 'spin': if w.variable is None: w.variable = IntVar() from_, to = w.values s = Scale(frame, from_=from_, to=to, resolution=1, - orient='horizontal', - variable=w.variable) + orient='horizontal', length=200, variable=w.variable) s.grid(row=row, column=1, sticky='ew', padx=2) elif w.widget == 'check': if w.variable is None: @@ -89,9 +104,9 @@ class WizardDialog(MfxDialog): ch.grid(row=row, column=1, sticky='ew', padx=2, pady=2) if w.current_value is None: - w.variable.set(w.default) + w.variable.set(gettext(w.default)) else: - w.variable.set(w.current_value) + w.variable.set(gettext(w.current_value)) row += 1 @@ -101,6 +116,21 @@ class WizardDialog(MfxDialog): self.mainloop(focus, kw.timeout) + def presetSelected(self, v, w): + n = w.translation_map[v] + p = presets[n] + for w in WizardWidgets: + if isinstance(w, basestring): + continue + if w.var_name in p: + v = p[w.var_name] + else: + v = w.default + if w.widget in ('menu', 'preset'): + v = gettext(v) + w.variable.set(v) + + def initKw(self, kw): kw = KwStruct(kw, strings=(_('&OK'), _('&Cancel')), diff --git a/pysollib/wizardpresets.py b/pysollib/wizardpresets.py new file mode 100644 index 00000000..dd03082c --- /dev/null +++ b/pysollib/wizardpresets.py @@ -0,0 +1,128 @@ +##---------------------------------------------------------------------------## +## +## PySol -- a Python Solitaire game +## +## 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; see the file COPYING. +## If not, write to the Free Software Foundation, Inc., +## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +##---------------------------------------------------------------------------## + +n_ = lambda x: x + +presets = { + 'None': { + 'preset': 'None', + 'name': n_('My Game'), + }, + + 'Klondike': { + 'preset': 'Klondike', + 'name': n_('My Klondike'), + 'layout': 'Klondike', + 'talon': 'Deal to waste', + 'redeals': 'Unlimited redeals', + 'rows_num': 7, + 'rows_base_card': 'King', + 'reserves_num': 0, + 'deal_type': 'Triangle', + 'deal_face_down': 6, + 'deal_face_up': 1, + }, + + 'FreeCell': { + 'preset': 'FreeCell', + 'name': n_('My FreeCell'), + 'skill_level': 'Mostly skill', + 'rows_max_move': 'Top card', + 'rows_super_move': 1, + 'deal_face_up': 6, + }, + + 'Spider': { + 'preset': 'Spider', + 'name': n_('My Spider'), + 'skill_level': 'Mostly skill', + 'decks': 'Two', + 'layout': 'Klondike', + 'talon': 'Spider', + 'found_type': 'Spider same suit', + 'found_max_move': 'None', + 'rows_num': 10, + 'rows_type': 'Spider same suit', + 'reserves_num': 0, + 'deal_face_down': 5, + 'deal_face_up': 1, + 'deal_max_cards': 54, + }, + + 'Gypsy': { + 'preset': 'Gypsy', + 'name': n_('My Gypsy'), + 'skill_level': 'Mostly skill', + 'decks': 'Two', + 'layout': 'Gypsy', + 'talon': 'Deal to tableau', + 'found_max_move': 'None', + 'reserves_num': 0, + 'deal_face_down': 2, + 'deal_face_up': 1, + }, + + 'Ground for a Divorce': { + 'preset': 'Ground for a Divorce', + 'name': n_('My Ground for a Divorce'), + 'skill_level': 'Mostly skill', + 'decks': 'Two', + 'layout': 'Harp', + 'talon': 'Ground for a Divorce', + 'found_type': 'Spider same suit', + 'found_base_card': 'Any', + 'found_equal': 0, + 'rows_num': 10, + 'rows_type': 'Spider same suit', + 'rows_wrap': 1, + 'reserves_num': 0, + 'deal_face_up': 5, + }, + + 'Double Klondike': { + 'preset': 'Double Klondike', + 'name': n_('My Double Klondike'), + 'decks': 'Two', + 'layout': 'Harp', + 'talon': 'Deal to waste', + 'redeals': 'Unlimited redeals', + 'rows_num': 9, + 'rows_base_card': 'King', + 'reserves_num': 0, + 'deal_type': 'Triangle', + 'deal_face_down': 8, + 'deal_face_up': 1, + }, + + 'Simple Simon': { + 'preset': 'Simple Simon', + 'name': n_('My Simple Simon'), + 'skill_level': 'Mostly skill', + 'found_type': 'Spider same suit', + 'found_max_move': 'None', + 'rows_num': 10, + 'rows_type': 'Spider same suit', + 'reserves_num': 0, + 'deal_type': 'Triangle', + }, + +} + diff --git a/pysollib/wizardutil.py b/pysollib/wizardutil.py index 4e2c60b4..292661c4 100644 --- a/pysollib/wizardutil.py +++ b/pysollib/wizardutil.py @@ -24,10 +24,8 @@ import sys, os from gamedb import GI, loadGame from util import * from stack import * -#from game import Game from layout import Layout -#from hint import AbstractHint, DefaultHint, CautiousDefaultHint -#from pysoltk import MfxCanvasText +from wizardpresets import presets gettext = _ n_ = lambda x: x @@ -40,15 +38,20 @@ class WizSetting: def __init__(self, values_map, default, var_name, label, widget='menu'): self.values_map = values_map - self.default = gettext(default) + self.default = default ##self.values_dict = dict(self.values_map) self.translation_map = {} if widget == 'menu': self.values = [] for k, v in self.values_map: - t = gettext(k) - self.values.append(t) - self.translation_map[t] = k + self.values.append(k) + self.translation_map[gettext(k)] = k + assert self.default in self.values + elif widget == 'preset': + self.values = [] + for v in self.values_map: + self.values.append(v) + self.translation_map[gettext(v)] = v assert self.default in self.values else: self.values = self.values_map @@ -59,6 +62,13 @@ class WizSetting: self.current_value = None +WizardPresets = WizSetting( + values_map = presets.keys(), + default = 'None', + widget = 'preset', + label = _('Initial setting:'), + var_name = 'preset', + ) GameName = WizSetting( values_map = (), default = 'My Game', @@ -97,10 +107,12 @@ LayoutType = WizSetting( var_name = 'layout', ) TalonType = WizSetting( - values_map = ((n_('Initial dealing'), InitialDealTalonStack), - (n_('Deal to waste'), WasteTalonStack), - (n_('Deal to tableau'), DealRowRedealTalonStack), - (n_('Deal to reserves'), DealReserveRedealTalonStack), + values_map = ((n_('Initial dealing'), InitialDealTalonStack), + (n_('Deal to waste'), WasteTalonStack), + (n_('Deal to tableau'), DealRowRedealTalonStack), + (n_('Deal to reserves'), DealReserveRedealTalonStack), + (n_('Spider'), SpiderTalonStack), + (n_('Ground for a Divorce'), GroundForADivorceTalonStack), ), default = n_('Initial dealing'), label = _('Type:'), @@ -166,15 +178,15 @@ FoundWrap = WizSetting( widget = 'check', ) FoundMaxMove = WizSetting( - values_map = ((n_('None'), 0,), (n_('One card'), 1)), - default = n_('One card'), - label = _('Max move cards:'), + values_map = ((n_('None'), 0,), (n_('Top card'), 1)), + default = n_('Top card'), + label = _('Move:'), var_name = 'found_max_move', ) FoundEqual = WizSetting( values_map = (0, 1), default = 1, - label = _('First card sets first rank:'), + label = _('First card sets base rank:'), var_name = 'found_equal', widget = 'check', ) @@ -225,9 +237,9 @@ RowsDir = WizSetting( var_name = 'rows_dir', ) RowsMaxMove = WizSetting( - values_map = ((n_('One card'), 1), (n_('Unlimited'), UNLIMITED_MOVES)), - default = n_('Unlimited'), - label = _('Max # of moved cards:'), + values_map = ((n_('Top card'), 1), (n_('Sequence'), UNLIMITED_MOVES)), + default = n_('Sequence'), + label = _('Move:'), var_name = 'rows_max_move', ) RowsWrap = WizSetting( @@ -284,7 +296,7 @@ DealToReseves = WizSetting( values_map = (0, 20), default = 0, widget = 'spin', - label = _('# cards dealt to reserve:'), + label = _('# of cards dealt to reserve:'), var_name = 'deal_to_reserves', ) DealMaxCards = WizSetting( @@ -297,6 +309,7 @@ DealMaxCards = WizSetting( WizardWidgets = ( _('General'), + WizardPresets, GameName, SkillLevel, NumDecks, @@ -374,12 +387,16 @@ class MyCustomGame(CustomGame): if isinstance(w, basestring): continue v = w.variable.get() - if w.widget == 'menu': + if w.widget in ('menu', 'presets'): v = w.translation_map[v] + if v == w.default: + # save only unique values + continue if isinstance(v, int): fd.write(" '%s': %i,\n" % (w.var_name, v)) else: if w.var_name == 'name': + # escape v = v.replace('\\', '\\\\') v = v.replace("'", "\\'") if isinstance(v, unicode): @@ -413,8 +430,6 @@ def reset_wizard(game): v = game.SETTINGS[w.var_name] else: v = w.default - if w.widget == 'menu': - v = gettext(v) w.current_value = v