mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
This is artisanal manual craftwork :-) def mDone(self, button): if button == 0: # "OK" or double click - if isinstance(self.tree.selection_key, six.string_types): - self.key = str(self.tree.selection_key) - else: - self.key = self.tree.selection_key + self.key = self.tree.selection_key
493 lines
15 KiB
Python
493 lines
15 KiB
Python
#!/usr/bin/env python
|
|
# -*- mode: python; coding: utf-8; -*-
|
|
# ---------------------------------------------------------------------------
|
|
#
|
|
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
|
|
# Copyright (C) 2003 Mt. Hood Playing Card Co.
|
|
# Copyright (C) 2005-2009 Skomoroh
|
|
#
|
|
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
# ---------------------------------------------------------------------------
|
|
|
|
import os
|
|
|
|
from pysollib.gamedb import GI, hideGame, loadGame
|
|
from pysollib.layout import Layout
|
|
from pysollib.mygettext import _, n_
|
|
from pysollib.stack import AC_FoundationStack, \
|
|
AC_RowStack, \
|
|
BO_FoundationStack, \
|
|
BO_RowStack, \
|
|
BasicRowStack, \
|
|
DealFirstRowRedealTalonStack, \
|
|
DealReserveRedealTalonStack, \
|
|
DealRowRedealTalonStack, \
|
|
GroundsForADivorceTalonStack, \
|
|
InitialDealTalonStack, \
|
|
RK_FoundationStack, \
|
|
RK_RowStack, \
|
|
SC_FoundationStack, \
|
|
SC_RowStack, \
|
|
SS_FoundationStack, \
|
|
SS_RowStack, \
|
|
SpiderTalonStack, \
|
|
Spider_AC_Foundation, \
|
|
Spider_AC_RowStack, \
|
|
Spider_BO_Foundation, \
|
|
Spider_BO_RowStack, \
|
|
Spider_RK_Foundation, \
|
|
Spider_SC_Foundation, \
|
|
Spider_SC_RowStack, \
|
|
Spider_SS_Foundation, \
|
|
Spider_SS_RowStack, \
|
|
UD_AC_RowStack, \
|
|
UD_BO_RowStack, \
|
|
UD_RK_RowStack, \
|
|
UD_SC_RowStack, \
|
|
UD_SS_RowStack, \
|
|
WasteTalonStack, \
|
|
Yukon_AC_RowStack, \
|
|
Yukon_BO_RowStack, \
|
|
Yukon_RK_RowStack, \
|
|
Yukon_SC_RowStack, \
|
|
Yukon_SS_RowStack
|
|
from pysollib.util import ACE, ANY_RANK, KING, NO_RANK, UNLIMITED_MOVES
|
|
from pysollib.wizardpresets import presets
|
|
|
|
# ************************************************************************
|
|
# *
|
|
# ************************************************************************
|
|
|
|
|
|
class WizSetting:
|
|
def __init__(self, values_map, default, var_name,
|
|
label, widget='menu'):
|
|
self.values_map = values_map
|
|
self.default = default
|
|
# self.values_dict = dict(self.values_map)
|
|
self.translation_map = {} # for backward translation
|
|
if widget == 'menu':
|
|
self.values = []
|
|
for k, v in self.values_map:
|
|
self.values.append(k)
|
|
self.translation_map[_(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[_(v)] = v
|
|
assert self.default in self.values
|
|
else:
|
|
self.values = self.values_map
|
|
self.var_name = var_name
|
|
self.label = label
|
|
self.widget = widget
|
|
self.variable = None # Tk variable
|
|
self.current_value = None
|
|
|
|
|
|
WizardPresets = WizSetting(
|
|
values_map=list(presets.keys()),
|
|
default='None',
|
|
widget='preset',
|
|
label=_('Initial setting:'),
|
|
var_name='preset',
|
|
)
|
|
GameName = WizSetting(
|
|
values_map=(),
|
|
default=_('My Game'),
|
|
widget='entry',
|
|
label=_('Name:'),
|
|
var_name='name',
|
|
)
|
|
SkillLevel = WizSetting(
|
|
values_map=((n_('Luck only'), GI.SL_LUCK),
|
|
(n_('Mostly luck'), GI.SL_MOSTLY_LUCK),
|
|
(n_('Balanced'), GI.SL_BALANCED),
|
|
(n_('Mostly skill'), GI.SL_MOSTLY_SKILL),
|
|
(n_('Skill only'), GI.SL_SKILL),
|
|
),
|
|
default=n_('Balanced'),
|
|
label=_('Skill level:'),
|
|
var_name='skill_level',
|
|
)
|
|
NumDecks = WizSetting(
|
|
values_map=((n_('One'), 1),
|
|
(n_('Two'), 2),
|
|
(n_('Three'), 3),
|
|
(n_('Four'), 4)),
|
|
default=n_('One'),
|
|
label=_('Number of decks:'),
|
|
var_name='decks',
|
|
)
|
|
LayoutType = WizSetting(
|
|
values_map=((n_('FreeCell'), Layout.freeCellLayout),
|
|
(n_('Klondike'), Layout.klondikeLayout),
|
|
(n_('Gypsy'), Layout.gypsyLayout),
|
|
(n_('Harp'), Layout.harpLayout),
|
|
),
|
|
default=n_('FreeCell'),
|
|
label=_('Layout:'),
|
|
var_name='layout',
|
|
)
|
|
TalonType = WizSetting(
|
|
values_map=((n_('Deal all cards at the beginning'), InitialDealTalonStack),
|
|
(n_('Deal to waste'), WasteTalonStack),
|
|
(n_('Deal to tableau'), DealRowRedealTalonStack),
|
|
(n_('Deal to first tableau'), DealFirstRowRedealTalonStack),
|
|
(n_('Deal to reserves'), DealReserveRedealTalonStack),
|
|
(n_('Spider'), SpiderTalonStack),
|
|
(n_('Grounds for a Divorce'), GroundsForADivorceTalonStack),
|
|
),
|
|
default=n_('Deal all cards at the beginning'),
|
|
label=_('Type:'),
|
|
var_name='talon',
|
|
)
|
|
Redeals = WizSetting(
|
|
values_map=((n_('No redeals'), 0),
|
|
(n_('One redeal'), 1),
|
|
(n_('Two redeals'), 2),
|
|
(n_('Three redeals'), 3),
|
|
(n_('Unlimited redeals'), -1),
|
|
),
|
|
default=n_('No redeals'),
|
|
label=_('Number of redeals:'),
|
|
var_name='redeals',
|
|
)
|
|
DealToWaste = WizSetting(
|
|
values_map=(1, 5),
|
|
default=1,
|
|
widget='spin',
|
|
label=_('# of cards dealt to the waste:'),
|
|
var_name='deal_to_waste',
|
|
)
|
|
TalonShuffle = WizSetting(
|
|
values_map=(0, 1),
|
|
default=0,
|
|
label=_('Shuffle during redeal:'),
|
|
var_name='talon_shuffle',
|
|
widget='check',
|
|
)
|
|
FoundType = WizSetting(
|
|
values_map=((n_('Same suit'), SS_FoundationStack),
|
|
(n_('Alternate color'), AC_FoundationStack),
|
|
(n_('Same color'), SC_FoundationStack),
|
|
(n_('Rank'), RK_FoundationStack),
|
|
(n_('Any suit but the same'), BO_FoundationStack),
|
|
(n_('Spider same suit'), Spider_SS_Foundation),
|
|
(n_('Spider alternate color'), Spider_AC_Foundation),
|
|
(n_('Spider same color'), Spider_SC_Foundation),
|
|
(n_('Spider rank'), Spider_RK_Foundation),
|
|
(n_('Spider any suit but the same'), Spider_BO_Foundation),
|
|
),
|
|
default=n_('Same suit'),
|
|
label=_('Type:'),
|
|
var_name='found_type',
|
|
)
|
|
FoundBaseCard = WizSetting(
|
|
values_map=((n_('Ace'), ACE),
|
|
(n_('King'), KING),
|
|
(n_('Any'), ANY_RANK),
|
|
),
|
|
default=n_('Ace'),
|
|
label=_('Base card:'),
|
|
var_name='found_base_card',
|
|
)
|
|
FoundDir = WizSetting(
|
|
values_map=((n_('Up'), 1), (n_('Down'), -1)),
|
|
default=n_('Up'),
|
|
label=_('Direction:'),
|
|
var_name='found_dir',
|
|
)
|
|
FoundMaxMove = WizSetting(
|
|
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 base cards:'),
|
|
var_name='found_equal',
|
|
widget='check',
|
|
)
|
|
RowsNum = WizSetting(
|
|
values_map=(1, 20),
|
|
default=8,
|
|
widget='spin',
|
|
label=_('Number of tableau piles:'),
|
|
var_name='rows_num',
|
|
)
|
|
RowsType = WizSetting(
|
|
values_map=((n_('No building'), BasicRowStack),
|
|
|
|
(n_('Same suit'), SS_RowStack),
|
|
(n_('Alternate color'), AC_RowStack),
|
|
(n_('Same color'), SC_RowStack),
|
|
(n_('Rank'), RK_RowStack),
|
|
(n_('Any suit but the same'), BO_RowStack),
|
|
|
|
(n_('Up or down by same suit'), UD_SS_RowStack),
|
|
(n_('Up or down by alternate color'), UD_AC_RowStack),
|
|
(n_('Up or down by same color'), UD_SC_RowStack),
|
|
(n_('Up or down by rank'), UD_RK_RowStack),
|
|
(n_('Up or down by any suit but the same'), UD_BO_RowStack),
|
|
|
|
(n_('Spider same suit'), Spider_SS_RowStack),
|
|
(n_('Spider alternate color'), Spider_AC_RowStack),
|
|
(n_('Spider same color'), Spider_SC_RowStack),
|
|
(n_('Spider any suit but the same'), Spider_BO_RowStack),
|
|
|
|
(n_('Yukon same suit'), Yukon_SS_RowStack),
|
|
(n_('Yukon alternate color'), Yukon_AC_RowStack),
|
|
(n_('Yukon same color'), Yukon_SC_RowStack),
|
|
(n_('Yukon rank'), Yukon_RK_RowStack),
|
|
(n_('Yukon any suit but the same'), Yukon_BO_RowStack),
|
|
),
|
|
default=n_('Alternate color'),
|
|
label=_('Type:'),
|
|
var_name='rows_type',
|
|
)
|
|
RowsBaseCard = WizSetting(
|
|
values_map=((n_('Ace'), ACE),
|
|
(n_('King'), KING),
|
|
(n_('Any'), ANY_RANK),
|
|
(n_('None'), NO_RANK),
|
|
),
|
|
default=n_('Any'),
|
|
label=_('Base card:'),
|
|
var_name='rows_base_card',
|
|
)
|
|
RowsDir = WizSetting(
|
|
values_map=((n_('Up'), 1), (n_('Down'), -1), (n_('Same rank'), 0)),
|
|
default=n_('Down'),
|
|
label=_('Direction:'),
|
|
var_name='rows_dir',
|
|
)
|
|
RowsMaxMove = WizSetting(
|
|
values_map=((n_('Top card'), 1), (n_('Sequence'), UNLIMITED_MOVES)),
|
|
default=n_('Sequence'),
|
|
label=_('Move:'),
|
|
var_name='rows_max_move',
|
|
)
|
|
RowsWrap = WizSetting(
|
|
values_map=(0, 1),
|
|
default=0,
|
|
label=_('Wrapping:'),
|
|
var_name='rows_wrap',
|
|
widget='check',
|
|
)
|
|
RowsSuperMove = WizSetting(
|
|
values_map=(0, 1),
|
|
default=0,
|
|
label=_('Use "Super Move" feature:'),
|
|
var_name='rows_super_move',
|
|
widget='check',
|
|
)
|
|
ReservesNum = WizSetting(
|
|
values_map=(0, 20),
|
|
default=4,
|
|
widget='spin',
|
|
label=_('Number of reserves:'),
|
|
var_name='reserves_num',
|
|
)
|
|
ReservesMaxAccept = WizSetting(
|
|
values_map=(0, 20),
|
|
default=1,
|
|
widget='spin',
|
|
label=_('Max # of accepted cards:'),
|
|
var_name='reserves_max_accept',
|
|
)
|
|
DealType = WizSetting(
|
|
values_map=((n_('Triangle'), 'triangle'),
|
|
(n_('Rectangle'), 'rectangle'),
|
|
(n_('Pyramid'), 'pyramid')
|
|
),
|
|
default=n_('Rectangle'),
|
|
label=_('Type:'),
|
|
var_name='deal_type',
|
|
)
|
|
DealFaceDown = WizSetting(
|
|
values_map=(0, 20),
|
|
default=0,
|
|
widget='spin',
|
|
label=_('# of face-down cards dealt to the tableau pile:'),
|
|
var_name='deal_face_down',
|
|
)
|
|
DealFaceUp = WizSetting(
|
|
values_map=(0, 20),
|
|
default=8,
|
|
widget='spin',
|
|
label=_('# of face-up cards dealt to the tableau pile:'),
|
|
var_name='deal_face_up',
|
|
)
|
|
DealToReseves = WizSetting(
|
|
values_map=(0, 208),
|
|
default=0,
|
|
widget='spin',
|
|
label=_('# of cards dealt to the reserve:'),
|
|
var_name='deal_to_reserves',
|
|
)
|
|
DealMaxCards = WizSetting(
|
|
values_map=(0, 208),
|
|
default=52,
|
|
widget='spin',
|
|
label=_('Max # of dealt cards:'),
|
|
var_name='deal_max_cards',
|
|
)
|
|
DealToFound = WizSetting(
|
|
values_map=(0, 1),
|
|
default=0,
|
|
label=_('Deal first cards to the foundations:'),
|
|
var_name='deal_found',
|
|
widget='check',
|
|
)
|
|
|
|
WizardWidgets = (
|
|
_('General'),
|
|
WizardPresets,
|
|
GameName,
|
|
SkillLevel,
|
|
NumDecks,
|
|
LayoutType,
|
|
_('Talon'),
|
|
TalonType,
|
|
Redeals,
|
|
DealToWaste,
|
|
TalonShuffle,
|
|
_('Foundations'),
|
|
FoundType,
|
|
FoundBaseCard,
|
|
FoundDir,
|
|
FoundMaxMove,
|
|
FoundEqual,
|
|
_('Tableau'),
|
|
RowsNum,
|
|
RowsType,
|
|
RowsBaseCard,
|
|
RowsDir,
|
|
RowsMaxMove,
|
|
RowsWrap,
|
|
RowsSuperMove,
|
|
_('Reserves'),
|
|
ReservesNum,
|
|
ReservesMaxAccept,
|
|
_('Opening deal'),
|
|
DealType,
|
|
DealFaceDown,
|
|
DealFaceUp,
|
|
DealToReseves,
|
|
DealMaxCards,
|
|
DealToFound,
|
|
)
|
|
|
|
|
|
def write_game(app, game=None):
|
|
import pysollib.customgame # for py2exe
|
|
pysollib.customgame.no_use()
|
|
if game is None:
|
|
# new game
|
|
d = app.dn.plugins
|
|
n = 1
|
|
while True:
|
|
fn = os.path.join(d, 'customgame%d.py' % n) # file name
|
|
mn = 'customgame%d' % n # module name
|
|
gameid = 200000+n
|
|
if not os.path.exists(fn):
|
|
break
|
|
n += 1
|
|
check_game = True
|
|
else:
|
|
# edit current game
|
|
fn = game.MODULE_FILENAME
|
|
mn = game.__module__
|
|
gameid = game.SETTINGS['gameid']
|
|
check_game = False
|
|
|
|
# print '===>', fn
|
|
with open(fn, 'w') as fd:
|
|
|
|
fd.write('''\
|
|
## -*- coding: utf-8 -*-
|
|
## THIS FILE WAS GENERATED AUTOMATICALLY BY THE SOLITAIRE WIZARD
|
|
## DO NOT EDIT
|
|
|
|
from pysollib.customgame import CustomGame, registerCustomGame
|
|
|
|
class MyCustomGame(CustomGame):
|
|
WIZARD_VERSION = 1
|
|
SETTINGS = {
|
|
''')
|
|
|
|
for w in WizardWidgets:
|
|
if isinstance(w, str):
|
|
continue
|
|
v = w.variable.get()
|
|
if w.widget in ('menu', 'preset'):
|
|
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("'", "\\'")
|
|
v = v.replace("\n", "\\n")
|
|
v = v.replace("\r", "\\r")
|
|
v = v.replace("\t", "\\t")
|
|
# See: https://github.com/shlomif/PySolFC/issues/177
|
|
# if isinstance(v, str):
|
|
# v = v.encode('utf-8')
|
|
if not v:
|
|
v = 'Invalid Game Name'
|
|
fd.write(" '{}': '{}',\n".format(w.var_name, v))
|
|
fd.write(" 'gameid': %i,\n" % gameid)
|
|
|
|
fd.write('''\
|
|
}
|
|
|
|
registerCustomGame(MyCustomGame)
|
|
''')
|
|
|
|
loadGame(mn, fn, check_game=check_game)
|
|
|
|
return gameid
|
|
|
|
|
|
def delete_game(game):
|
|
hideGame(game)
|
|
fn = game.MODULE_FILENAME
|
|
os.remove(fn)
|
|
|
|
|
|
def reset_wizard(game):
|
|
for w in WizardWidgets:
|
|
if isinstance(w, str):
|
|
continue
|
|
if game is None:
|
|
# set to default
|
|
v = w.default
|
|
else:
|
|
# set from current game
|
|
if w.var_name in game.SETTINGS:
|
|
v = game.SETTINGS[w.var_name]
|
|
else:
|
|
v = w.default
|
|
w.current_value = v
|