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
405 lines
14 KiB
Python
405 lines
14 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/>.
|
|
#
|
|
# ---------------------------------------------------------------------------##
|
|
|
|
from pysollib.game import Game
|
|
from pysollib.gamedb import GI, GameInfo, registerGame
|
|
from pysollib.hint import Yukon_Hint
|
|
from pysollib.layout import Layout
|
|
from pysollib.stack import \
|
|
AC_RowStack, \
|
|
BO_RowStack, \
|
|
DealReserveRedealTalonStack, \
|
|
DealRowRedealTalonStack, \
|
|
GroundsForADivorceTalonStack, \
|
|
InitialDealTalonStack, \
|
|
OpenStack, \
|
|
RK_RowStack, \
|
|
ReserveStack, \
|
|
SC_RowStack, \
|
|
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, \
|
|
StackWrapper, \
|
|
SuperMoveAC_RowStack, \
|
|
SuperMoveBO_RowStack, \
|
|
SuperMoveRK_RowStack, \
|
|
SuperMoveSC_RowStack, \
|
|
SuperMoveSS_RowStack, \
|
|
UD_AC_RowStack, \
|
|
UD_BO_RowStack, \
|
|
UD_RK_RowStack, \
|
|
UD_SC_RowStack, \
|
|
UD_SS_RowStack, \
|
|
WasteStack, \
|
|
WasteTalonStack, \
|
|
Yukon_AC_RowStack, \
|
|
Yukon_BO_RowStack, \
|
|
Yukon_RK_RowStack, \
|
|
Yukon_SC_RowStack, \
|
|
Yukon_SS_RowStack
|
|
from pysollib.util import ACE, ANY_RANK, ANY_SUIT, \
|
|
KING, \
|
|
UNLIMITED_MOVES
|
|
from pysollib.wizardutil import WizardWidgets
|
|
|
|
# ************************************************************************
|
|
# *
|
|
# ************************************************************************
|
|
|
|
|
|
def get_settings(ss):
|
|
s = {}
|
|
for w in WizardWidgets:
|
|
if isinstance(w, str):
|
|
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):
|
|
|
|
s = get_settings(self.SETTINGS)
|
|
# from pprint import pprint; pprint(s)
|
|
|
|
# foundations
|
|
kw = {
|
|
'dir': s['found_dir'],
|
|
'base_rank': s['found_base_card'],
|
|
'mod': 13,
|
|
}
|
|
# max_move
|
|
if s['found_type'] not in (Spider_SS_Foundation,
|
|
Spider_AC_Foundation,
|
|
Spider_RK_Foundation,
|
|
Spider_SC_Foundation,
|
|
Spider_BO_Foundation,):
|
|
kw['max_move'] = s['found_max_move']
|
|
# suit
|
|
if s['found_type'] in (Spider_SS_Foundation,
|
|
Spider_AC_Foundation,
|
|
Spider_RK_Foundation,
|
|
Spider_SC_Foundation,
|
|
Spider_BO_Foundation,):
|
|
kw['suit'] = ANY_SUIT
|
|
# fix dir and base_rank for Spider foundations
|
|
if s['found_type'] in (Spider_SS_Foundation,
|
|
Spider_AC_Foundation,
|
|
Spider_RK_Foundation,
|
|
Spider_SC_Foundation,
|
|
Spider_BO_Foundation,):
|
|
kw['dir'] = -kw['dir']
|
|
if s['found_base_card'] == KING:
|
|
kw['base_rank'] = ACE
|
|
elif s['found_base_card'] == ACE:
|
|
kw['base_rank'] = KING
|
|
foundation = StackWrapper(s['found_type'], **kw)
|
|
|
|
# talon
|
|
kw = {
|
|
'max_rounds': s['redeals'],
|
|
}
|
|
if s['redeals'] >= 0:
|
|
kw['max_rounds'] += 1
|
|
if s['talon'] is WasteTalonStack:
|
|
kw['num_deal'] = s['deal_to_waste']
|
|
talon = StackWrapper(s['talon'], **kw)
|
|
|
|
# rows
|
|
kw = {
|
|
'base_rank': s['rows_base_card'],
|
|
'dir': s['rows_dir'],
|
|
'max_move': s['rows_max_move'],
|
|
}
|
|
if s['rows_wrap']:
|
|
kw['mod'] = 13
|
|
if s['rows_type'] in (UD_SS_RowStack, UD_AC_RowStack,
|
|
UD_RK_RowStack, UD_SC_RowStack,
|
|
UD_BO_RowStack):
|
|
kw['max_move'] = 1
|
|
# Super Move
|
|
if s['rows_super_move'] and kw['max_move'] == 1:
|
|
for s1, s2 in ((SS_RowStack, SuperMoveSS_RowStack),
|
|
(AC_RowStack, SuperMoveAC_RowStack),
|
|
(RK_RowStack, SuperMoveRK_RowStack),
|
|
(SC_RowStack, SuperMoveSC_RowStack),
|
|
(BO_RowStack, SuperMoveBO_RowStack)):
|
|
if s['rows_type'] is s1:
|
|
s['rows_type'] = s2
|
|
kw['max_move'] = UNLIMITED_MOVES
|
|
break
|
|
row = StackWrapper(s['rows_type'], **kw)
|
|
|
|
# layout
|
|
layout_kw = {
|
|
'rows': s['rows_num'],
|
|
'reserves': s['reserves_num'],
|
|
'waste': False,
|
|
'texts': True,
|
|
}
|
|
playcards = 0
|
|
if s['talon'] is InitialDealTalonStack:
|
|
layout_kw['texts'] = False
|
|
playcards = 12 + 52 * s['decks'] / s['rows_num']
|
|
else:
|
|
playcards = 12 + s['deal_face_down'] + s['deal_face_up']
|
|
layout_kw['playcards'] = max(16, playcards)
|
|
if s['talon'] in (DealRowRedealTalonStack,
|
|
SpiderTalonStack,
|
|
GroundsForADivorceTalonStack):
|
|
layout_kw['playcards'] += 2 * s['decks']
|
|
|
|
# reserves
|
|
if s['reserves_num']:
|
|
kw = {
|
|
'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 or s['deal_to_reserves'] > 1:
|
|
layout_kw['reserve_texts'] = True
|
|
|
|
# waste
|
|
if s['talon'] is WasteTalonStack:
|
|
layout_kw['waste'] = True
|
|
layout_kw['waste_class'] = WasteStack
|
|
|
|
Layout(self).createGame(
|
|
layout_method=s['layout'],
|
|
talon_class=talon,
|
|
foundation_class=foundation,
|
|
row_class=row,
|
|
**layout_kw
|
|
)
|
|
|
|
# shuffle
|
|
if s['talon_shuffle'] and s['talon'] in (WasteTalonStack,
|
|
DealRowRedealTalonStack):
|
|
self.s.talon.dealCards = self.s.talon.shuffleAndDealCards
|
|
|
|
# shallHighlightMatch
|
|
for c, f in (
|
|
((Spider_AC_RowStack, Spider_SS_RowStack,
|
|
Spider_SC_RowStack, Spider_BO_RowStack),
|
|
(self._shallHighlightMatch_RK,
|
|
self._shallHighlightMatch_RKW)),
|
|
((AC_RowStack, UD_AC_RowStack,
|
|
Yukon_AC_RowStack, SuperMoveAC_RowStack),
|
|
(self._shallHighlightMatch_AC,
|
|
self._shallHighlightMatch_ACW)),
|
|
((SS_RowStack, UD_SS_RowStack,
|
|
Yukon_SS_RowStack, SuperMoveSS_RowStack),
|
|
(self._shallHighlightMatch_SS,
|
|
self._shallHighlightMatch_SSW)),
|
|
((RK_RowStack, UD_RK_RowStack,
|
|
Yukon_RK_RowStack, SuperMoveRK_RowStack),
|
|
(self._shallHighlightMatch_RK,
|
|
self._shallHighlightMatch_RKW)),
|
|
((SC_RowStack, UD_SC_RowStack,
|
|
Yukon_SC_RowStack, SuperMoveSC_RowStack),
|
|
(self._shallHighlightMatch_SC,
|
|
self._shallHighlightMatch_SCW)),
|
|
((BO_RowStack, UD_BO_RowStack,
|
|
Yukon_SC_RowStack, SuperMoveBO_RowStack),
|
|
(self._shallHighlightMatch_BO,
|
|
self._shallHighlightMatch_BOW)),
|
|
):
|
|
if s['rows_type'] in c:
|
|
if s['rows_wrap']:
|
|
self.shallHighlightMatch = f[1]
|
|
else:
|
|
self.shallHighlightMatch = f[0]
|
|
break
|
|
|
|
# getQuickPlayScore
|
|
if s['rows_type'] in (Spider_AC_RowStack,
|
|
Spider_SS_RowStack,
|
|
Spider_BO_RowStack,
|
|
Spider_SC_RowStack,):
|
|
self.getQuickPlayScore = self._getSpiderQuickPlayScore
|
|
|
|
# canDropCards
|
|
if s['found_type'] in (Spider_SS_Foundation,
|
|
Spider_AC_Foundation,
|
|
Spider_RK_Foundation,
|
|
Spider_SC_Foundation,
|
|
Spider_BO_Foundation,):
|
|
for stack in self.s.rows:
|
|
stack.canDropCards = stack.spiderCanDropCards
|
|
|
|
# acceptsCards
|
|
if s['found_base_card'] == ANY_RANK and s['found_equal']:
|
|
for stack in self.s.foundations:
|
|
stack.acceptsCards = stack.varyAcceptsCards
|
|
stack.getBaseCard = stack.varyGetBaseCard
|
|
|
|
# getBottomImage
|
|
if s['deal_face_down'] + s['deal_face_up'] == 0:
|
|
for stack in self.s.rows:
|
|
stack.getBottomImage = stack.getReserveBottomImage
|
|
|
|
# Hint_Class
|
|
# TODO
|
|
if s['rows_type'] in (Yukon_SS_RowStack,
|
|
Yukon_AC_RowStack,
|
|
Yukon_RK_RowStack,
|
|
Yukon_SC_RowStack,
|
|
Yukon_BO_RowStack,):
|
|
self.Hint_Class = Yukon_Hint
|
|
|
|
def _shuffleHook(self, cards):
|
|
s = get_settings(self.SETTINGS)
|
|
if not s['deal_found']:
|
|
return cards
|
|
if s['found_type'] in (Spider_SS_Foundation,
|
|
Spider_AC_Foundation,
|
|
Spider_RK_Foundation,
|
|
Spider_SC_Foundation,
|
|
Spider_BO_Foundation,):
|
|
return cards
|
|
base_card = s['found_base_card']
|
|
if base_card == ANY_RANK:
|
|
base_card = cards[0].rank
|
|
# move base_card to top of the Talon (i.e. first cards to be dealt)
|
|
return self._shuffleHookMoveToTop(
|
|
cards,
|
|
lambda c, rank=base_card: (c.rank == rank, c.suit))
|
|
|
|
def startGame(self):
|
|
|
|
s = get_settings(self.SETTINGS)
|
|
anim_frames = -1
|
|
|
|
def deal(rows, flip, frames, max_cards):
|
|
if frames == 0:
|
|
if len(self.s.talon.cards) <= min_cards or \
|
|
max_cards <= min_cards:
|
|
frames = anim_frames
|
|
self.startDealSample()
|
|
if max_cards <= 0:
|
|
return frames, 0
|
|
max_cards -= self.s.talon.dealRowAvail(rows=rows, flip=flip,
|
|
frames=frames)
|
|
return frames, max_cards
|
|
|
|
frames = 0
|
|
if isinstance(self.s.talon, InitialDealTalonStack):
|
|
max_cards = 52 * s['decks']
|
|
else:
|
|
max_cards = s['deal_max_cards']
|
|
|
|
min_cards = max(len(self.s.rows), 8)
|
|
max_rows = s['deal_face_down'] + s['deal_face_up'] \
|
|
+ s['deal_to_reserves']
|
|
if max_rows <= 1:
|
|
min_cards = max_cards
|
|
|
|
# deal to foundations
|
|
if s['deal_found']:
|
|
frames, max_cards = deal(self.s.foundations,
|
|
True, frames, max_cards)
|
|
|
|
# deal to reserves
|
|
n = s['deal_to_reserves']
|
|
for i in range(n):
|
|
frames, max_cards = deal(self.s.reserves[:max_cards],
|
|
True, frames, max_cards)
|
|
|
|
# deal to rows
|
|
face_down = s['deal_face_down']
|
|
max_rows = s['deal_face_down'] + s['deal_face_up']
|
|
if s['deal_type'] == 'triangle':
|
|
# triangle
|
|
for i in range(1, len(self.s.rows)):
|
|
if max_rows <= 1:
|
|
break
|
|
flip = (face_down <= 0)
|
|
mc = max_cards - len(self.s.rows)
|
|
frames, max_cards = deal(self.s.rows[i:i+mc],
|
|
flip, frames, max_cards)
|
|
face_down -= 1
|
|
max_rows -= 1
|
|
elif s['deal_type'] == 'pyramid':
|
|
# pyramid
|
|
for i in range(1, len(self.s.rows)):
|
|
if max_rows <= 1:
|
|
break
|
|
flip = (face_down <= 0)
|
|
mc = max_cards - len(self.s.rows)
|
|
frames, max_cards = deal(self.s.rows[i:min(i+mc, -i)],
|
|
flip, frames, max_cards)
|
|
face_down -= 1
|
|
max_rows -= 1
|
|
else:
|
|
# rectangle
|
|
for i in range(max_rows-1):
|
|
flip = (face_down <= 0)
|
|
mc = max_cards - len(self.s.rows)
|
|
frames, max_cards = deal(self.s.rows[:mc],
|
|
flip, frames, max_cards)
|
|
face_down -= 1
|
|
|
|
if isinstance(self.s.talon, InitialDealTalonStack):
|
|
while self.s.talon.cards:
|
|
frames, max_cards = deal(self.s.rows, True, frames, max_cards)
|
|
else:
|
|
if max_rows > 0:
|
|
deal(self.s.rows, True, frames, len(self.s.rows))
|
|
|
|
# deal to waste
|
|
if self.s.waste:
|
|
if frames == 0:
|
|
self.startDealSample()
|
|
self.s.talon.dealCards()
|
|
|
|
|
|
def registerCustomGame(gameclass):
|
|
|
|
s = get_settings(gameclass.SETTINGS)
|
|
gameid = gameclass.SETTINGS['gameid']
|
|
|
|
registerGame(GameInfo(gameid, gameclass, s['name'],
|
|
GI.GT_CUSTOM | GI.GT_ORIGINAL,
|
|
s['decks'], s['redeals'], s['skill_level']))
|
|
|
|
|
|
def no_use():
|
|
pass
|