1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00

+ 7 new games

* improved progressbar
* misc.improvements


git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@36 39dd0a4e-7c14-0410-91b3-c4f2d318f732
This commit is contained in:
skomoroh 2006-08-02 21:13:23 +00:00
parent 88081dd989
commit 2c578eb8cf
9 changed files with 399 additions and 17 deletions

View file

@ -633,7 +633,9 @@ class Application:
# widgets
#
# create the menubar
self.menubar = PysolMenubar(self, self.top)
if self.intro.progress: self.intro.progress.update(step=1)
self.menubar = PysolMenubar(self, self.top,
progress=self.intro.progress)
# create the statusbar(s)
self.statusbar = PysolStatusbar(self.top)
self.statusbar.show(self.opt.statusbar)

View file

@ -22,7 +22,6 @@
__all__ = []
# imports
import sys
# PySol imports
from pysollib.gamedb import registerGame, GameInfo, GI
@ -31,6 +30,9 @@ from pysollib.stack import *
from pysollib.game import Game
from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
from numerica import Numerica_Hint
# /***********************************************************************
@ -174,7 +176,6 @@ class Camelot(Game):
def startGame(self):
self.is_fill = False
self.nnn = 0
self.s.talon.fillStack()
@ -212,8 +213,129 @@ class Camelot(Game):
return [self.is_fill]
# /***********************************************************************
# // Sly Fox
# ************************************************************************/
class SlyFox_Foundation(SS_FoundationStack):
def acceptsCards(self, from_stack, cards):
if not SS_FoundationStack.acceptsCards(self, from_stack, cards):
return False
if from_stack in self.game.s.rows:
return self.game.num_dealled <= 0
return True
class SlyFox_Talon(OpenTalonStack):
rightclickHandler = OpenStack.rightclickHandler
doubleclickHandler = OpenStack.doubleclickHandler
def moveMove(self, ncards, to_stack, frames=-1, shadow=-1):
old_state = self.game.enterState(self.game.S_FILL)
self.game.saveStateMove(2|16) # for undo
if old_state == self.game.S_PLAY and to_stack in self.game.s.rows:
n = self.game.num_dealled
if n < 0: n = 0
self.game.num_dealled = (n+1)%20
self.game.saveStateMove(1|16) # for redo
self.game.leaveState(old_state)
OpenTalonStack.moveMove(self, ncards, to_stack, frames, shadow)
class SlyFox_RowStack(ReserveStack):
def acceptsCards(self, from_stack, cards):
if not ReserveStack.acceptsCards(self, from_stack, cards):
return False
return from_stack is self.game.s.talon
class SlyFox(Game):
Hint_Class = Numerica_Hint
num_dealled = -1
def createGame(self):
l, s = Layout(self), self.s
self.setSize(l.XM+9*l.XS, l.YM+4*l.YS)
x, y = l.XM, l.YM
s.talon = SlyFox_Talon(x, y, self)
s.waste = s.talon
l.createText(s.talon, 'ne')
tx, ty, ta, tf = l.getTextAttr(s.talon, "ss")
font = self.app.getFont("canvas_default")
self.texts.misc = MfxCanvasText(self.canvas, tx, ty,
anchor=ta, font=font)
y = l.YM
for i in range(4):
x = l.XM+1.5*l.XS
for j in range(5):
stack = SlyFox_RowStack(x, y, self, max_cards=UNLIMITED_CARDS)
stack.CARD_YOFFSET = 0
s.rows.append(stack)
x += l.XS
y += l.YS
x, y = self.width-2*l.XS, l.YM
for i in range(4):
s.foundations.append(SlyFox_Foundation(x, y, self, suit=i))
s.foundations.append(SlyFox_Foundation(x+l.XS, y, self, suit=i,
base_rank=KING, dir=-1))
y += l.YS
l.defaultStackGroups()
def _shuffleHook(self, cards):
return self._shuffleHookMoveToTop(cards,
lambda c: (c.rank in (ACE, KING) and c.deck == 0, (c.suit, c.rank)))
def startGame(self):
self.num_dealled = -1
self.s.talon.dealRow(rows=self.s.foundations, frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.fillStack()
def _restoreGameHook(self, game):
self.num_dealled = game.loadinfo.num_dealled
def _loadGameHook(self, p):
self.loadinfo.addattr(num_dealled=p.load())
def _saveGameHook(self, p):
p.dump(self.num_dealled)
def setState(self, state):
# restore saved vars (from undo/redo)
self.num_dealled = state[0]
def getState(self):
# save vars (for undo/redo)
return [self.num_dealled]
def fillStack(self, stack):
if self.num_dealled == -1 and stack in self.s.rows and not stack.cards:
old_state = self.enterState(self.S_FILL)
self.s.talon.moveMove(1, stack)
self.leaveState(old_state)
def updateText(self):
if self.preview > 1:
return
n = self.num_dealled
if n < 0: n = 0
text=str(n)+'/20'
self.texts.misc.config(text=text)
# register the game
registerGame(GameInfo(280, Camelot, "Camelot",
GI.GT_1DECK_TYPE, 1, 0, GI.SL_BALANCED))
registerGame(GameInfo(610, SlyFox, "Sly Fox",
GI.GT_NUMERICA, 2, 0, GI.SL_MOSTLY_SKILL))

View file

@ -266,7 +266,7 @@ class SalicLaw(DerKatzenschwanz):
l, s = Layout(self), self.s
# set size
self.setSize(l.XM + 10*l.XS, l.YM + 7*l.YS)
self.setSize(l.XM+10*l.XS, l.YM+(5+len(self.Foundation_Classes))*l.YS)
#
playcards = 4*l.YS / l.YOFFSET
@ -288,8 +288,8 @@ class SalicLaw(DerKatzenschwanz):
x += l.XS
y += l.YS
x, y = l.XM, l.YM+2*l.YS
self.setRegion(s.foundations[8:], (-999, -999, 999999, y - l.XM / 2))
x, y = l.XM, l.YM+l.YS*len(self.Foundation_Classes)
self.setRegion(s.foundations[-8:], (-999, -999, 999999, y - l.XM / 2))
for i in range(8):
stack = self.RowStack_Class(x, y, self, max_move=1)
stack.CARD_XOFFSET = xoffset
@ -388,6 +388,66 @@ class LaggardLady(SalicLaw):
return True
# /***********************************************************************
# // Faerie Queen
# ************************************************************************/
class FaerieQueen_RowStack(RK_RowStack):
def acceptsCards(self, from_stack, cards):
if self.game.s.talon.cards:
return False
if len(self.cards) == 1:
return True
return RK_RowStack.acceptsCards(self, from_stack, cards)
class FaerieQueen(SalicLaw):
Foundation_Classes = [
StackWrapper(RK_FoundationStack, max_move=0, max_cards=12)
]
RowStack_Class = StackWrapper(FaerieQueen_RowStack, min_cards=1, max_move=1)
def isGameWon(self):
if self.s.talon.cards:
return False
for s in self.s.foundations:
if len(s.cards) != 12:
return False
return True
def getQuickPlayScore(self, ncards, from_stack, to_stack):
return int(len(to_stack.cards) > 1)
shallHighlightMatch = Game._shallHighlightMatch_RK
# /***********************************************************************
# // Glencoe
# ************************************************************************/
class Glencoe_Foundation(RK_FoundationStack):
def acceptsCards(self, from_stack, cards):
if not RK_FoundationStack.acceptsCards(self, from_stack, cards):
return False
c = cards[0]
if c.rank in (4, 5):
i = list(self.game.s.foundations).index(self) % 8
r = self.game.s.rows[i]
if not r.cards:
return False
return c.suit == r.cards[0].suit
return True
class Glencoe(LaggardLady):
Foundation_Classes = [
StackWrapper(Glencoe_Foundation, base_rank=5, max_cards=6),
StackWrapper(Glencoe_Foundation, base_rank=4, max_cards=6, dir=-1, mod=13),
]
# register the game
registerGame(GameInfo(141, DerKatzenschwanz, "Cat's Tail",
@ -406,5 +466,9 @@ registerGame(GameInfo(442, Deep, "Deep",
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(523, LaggardLady, "Laggard Lady",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(611, FaerieQueen, "Faerie Queen",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(612, Glencoe, "Glencoe",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))

View file

@ -1204,6 +1204,24 @@ class LuckyPiles(LuckyThirteen):
shallHighlightMatch = Game._shallHighlightMatch_SS
# /***********************************************************************
# // Legion
# ************************************************************************/
class Legion(Klondike):
def createGame(self):
Klondike.createGame(self, max_rounds=1, rows=8)
def startGame(self):
self.startDealSample()
self.s.talon.dealRow()
for i in (1,2,3):
self.s.talon.dealRow(rows=self.s.rows[i:-i], flip=0)
self.s.talon.dealRow(rows=self.s.rows[i:-i])
self.s.talon.dealCards()
# register the game
registerGame(GameInfo(2, Klondike, "Klondike",
@ -1330,4 +1348,6 @@ registerGame(GameInfo(601, AmericanCanister, "American Canister",
GI.GT_BELEAGUERED_CASTLE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(602, BritishCanister, "British Canister",
GI.GT_BELEAGUERED_CASTLE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(607, Legion, "Legion",
GI.GT_KLONDIKE, 1, 0, GI.SL_BALANCED))

View file

@ -319,6 +319,7 @@ class PussInTheCorner(Numerica):
# /***********************************************************************
# // Frog
# // Fly
# // Fanny
# ************************************************************************/
class Frog(Game):
@ -399,6 +400,18 @@ class Fly(Frog):
self.s.talon.dealCards()
class Fanny(Frog):
Foundation_Class = RK_FoundationStack
def startGame(self):
self.startDealSample()
for i in range(11):
self.s.talon.dealRow(self.s.reserves, flip=0)
self.s.talon.dealRow(self.s.reserves)
self.s.talon.dealCards()
# /***********************************************************************
# // Gnat
# ************************************************************************/
@ -751,4 +764,6 @@ registerGame(GameInfo(599, Assembly, "Assembly",
GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED))
registerGame(GameInfo(600, AnnoDomini, "Anno Domini",
GI.GT_NUMERICA, 1, 2, GI.SL_BALANCED))
registerGame(GameInfo(613, Fanny, "Fanny",
GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED))

View file

@ -42,6 +42,9 @@ from pysollib.game import Game
from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from unionsquare import UnionSquare_Foundation
# /***********************************************************************
# // Royal Cotillion
# ************************************************************************/
@ -220,6 +223,7 @@ class Kingdom(RoyalCotillion):
# /***********************************************************************
# // Alhambra
# // Granada
# // Grant's Reinforcement
# ************************************************************************/
@ -267,12 +271,14 @@ class Alhambra_Talon(DealRowTalonStack):
class Alhambra(Game):
Hint_Class = Alhambra_Hint
def createGame(self, rows=1):
RowStack_Class = StackWrapper(Alhambra_RowStack, base_rank=ANY_RANK)
def createGame(self, rows=1, reserves=8, playcards=3):
# create layout
l, s = Layout(self), self.s
# set window
self.setSize(l.XM + 8*l.XS, l.YM + 4*l.YS)
self.setSize(l.XM+8*l.XS, l.YM+3.5*l.YS+playcards*l.YOFFSET)
# create stacks
x, y, = l.XM, l.YM
@ -284,22 +290,23 @@ class Alhambra(Game):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i,
max_move=0, base_rank=KING, dir=-1))
x = x + l.XS
x, y, = l.XM, y + l.YS
for i in range(8):
x, y, = l.XM+(8-reserves)*l.XS/2, y+l.YS
for i in range(reserves):
stack = OpenStack(x, y, self, max_accept=0)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, l.YOFFSET
s.reserves.append(stack)
x = x + l.XS
x, y = l.XM+(8-1-rows)*l.XS/2, y+l.YS+5*l.YOFFSET
x, y = l.XM+(8-1-rows)*l.XS/2, self.height-l.YS
s.talon = Alhambra_Talon(x, y, self, max_rounds=3)
l.createText(s.talon, "sw")
x += l.XS
for i in range(rows):
stack = Alhambra_RowStack(x, y, self, mod=13,
max_accept=1, base_rank=ANY_RANK)
stack = self.RowStack_Class(x, y, self, mod=13, max_accept=1)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
s.rows.append(stack)
x += l.XS
if rows == 1:
l.createText(stack, 'se')
# define stack-groups (non default)
l.defaultStackGroups()
@ -328,6 +335,31 @@ class Granada(Alhambra):
Alhambra.createGame(self, rows=4)
class GrantsReinforcement(Alhambra):
RowStack_Class = StackWrapper(Alhambra_RowStack, base_rank=NO_RANK)
def createGame(self):
Alhambra.createGame(self, reserves=4, playcards=11)
def startGame(self):
self.s.talon.dealRow(rows=self.s.foundations, frames=0)
for i in range(11):
self.s.talon.dealRow(rows=self.s.reserves, frames=0)
self.startDealSample()
self.s.talon.dealRow(rows=self.s.reserves)
self.s.talon.dealCards()
def fillStack(self, stack):
for r in self.s.reserves:
if r.cards:
continue
if self.s.talon.cards:
old_state = self.enterState(self.S_FILL)
self.s.talon.flipMove()
self.s.talon.moveMove(1, r)
self.leaveState(old_state)
# /***********************************************************************
# // Carpet
# ************************************************************************/
@ -589,6 +621,105 @@ class ThreePirates(Game):
shallHighlightMatch = Game._shallHighlightMatch_SS
# /***********************************************************************
# // Frames
# ************************************************************************/
class Frames_Foundation(UnionSquare_Foundation):
def acceptsCards(self, from_stack, cards):
if not UnionSquare_Foundation.acceptsCards(self, from_stack, cards):
return False
return from_stack in self.game.s.rows
class Frames_RowStack(UD_SS_RowStack):
def acceptsCards(self, from_stack, cards):
if not UD_SS_RowStack.acceptsCards(self, from_stack, cards):
return False
if not (from_stack in self.game.s.reserves or
from_stack in self.game.s.rows):
return False
if len(self.cards) > 1:
cs = self.cards+cards
if not (isSameSuitSequence(cs, dir=1) or
isSameSuitSequence(cs, dir=-1)):
return False
if from_stack in self.game.s.reserves:
if (hasattr(self.cap, 'column') and
self.cap.column != from_stack.cap.column):
return False
if (hasattr(self.cap, 'row') and
self.cap.row != from_stack.cap.row):
return False
return True
class Frames(Game):
Hint_Class = CautiousDefaultHint
def createGame(self):
l, s = Layout(self), self.s
self.setSize(l.XM+8*l.XS, l.YM+5*l.YS)
x0, y0 = l.XM+2*l.XS, l.YM
# foundations (corners)
suit = 0
for i, j in ((0,0),(5,0),(0,4),(5,4)):
x, y = x0+i*l.XS, y0+j*l.YS
s.foundations.append(Frames_Foundation(x, y, self,
suit=suit, dir=0, max_cards=26))
suit += 1
# rows (frame)
for i in (1,2,3,4):
for j in (0,4):
x, y = x0+i*l.XS, y0+j*l.YS
stack = Frames_RowStack(x, y, self)
s.rows.append(stack)
stack.cap.addattr(column=i)
stack.CARD_YOFFSET = 0
for i in (0,5):
for j in (1,2,3):
x, y = x0+i*l.XS, y0+j*l.YS
stack = Frames_RowStack(x, y, self)
s.rows.append(stack)
stack.cap.addattr(row=j)
stack.CARD_YOFFSET = 0
# reserves (picture)
for j in (1,2,3):
for i in (1,2,3,4):
x, y = x0+i*l.XS, y0+j*l.YS
stack = OpenStack(x, y, self)
s.reserves.append(stack)
stack.cap.addattr(column=i)
stack.cap.addattr(row=j)
# talon & waste
x, y, = l.XM, l.YM
s.talon = WasteTalonStack(x, y, self, max_rounds=1)
l.createText(s.talon, 'ne')
y += l.YS
s.waste = WasteStack(x, y, self)
l.createText(s.waste, 'ne')
l.defaultStackGroups()
def startGame(self):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow(rows=self.s.reserves)
self.s.talon.dealCards()
def fillStack(self, stack):
if not stack.cards and stack in self.s.reserves:
if not self.s.waste.cards:
self.s.talon.dealCards()
if self.s.waste.cards:
old_state = self.enterState(self.S_FILL)
self.s.waste.moveMove(1, stack)
self.leaveState(old_state)
shallHighlightMatch = Game._shallHighlightMatch_SS
# register the game
registerGame(GameInfo(54, RoyalCotillion, "Royal Cotillion",
@ -615,4 +746,8 @@ registerGame(GameInfo(465, Granada, "Granada",
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED))
registerGame(GameInfo(579, ThreePirates, "Three Pirates",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(608, Frames, "Frames",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(609, GrantsReinforcement, "Grant's Reinforcement",
GI.GT_2DECK_TYPE, 2, 2, GI.SL_MOSTLY_SKILL))

View file

@ -431,7 +431,7 @@ Sounds and background music will be disabled.'''),
if app.tabletile_index > 0:
color = "#008200"
app.intro.progress = PysolProgressBar(app, top, title=title, color=color,
images=app.progress_images)
images=app.progress_images, norm=1.32)
# prepare other images
app.loadImages2()

View file

@ -196,7 +196,7 @@ class MfxMenu(MfxMenubar):
# ************************************************************************/
class PysolMenubar(PysolMenubarActions):
def __init__(self, app, top):
def __init__(self, app, top, progress=None):
PysolMenubarActions.__init__(self, app, top)
# init columnbreak
self.__cb_max = int(self.top.winfo_screenheight()/23)
@ -205,11 +205,15 @@ class PysolMenubar(PysolMenubarActions):
## if sh >= 600: self.__cb_max = 27
## if sh >= 768: self.__cb_max = 32
## if sh >= 1024: self.__cb_max = 40
self.progress = progress
# create menus
self.__menubar = None
self.__menupath = {}
self.__keybindings = {}
self._createMenubar()
if self.progress: self.progress.update(step=1)
# set the menubar
self.updateBackgroundImagesMenu()
self.top.config(menu=self.__menubar)
@ -225,6 +229,9 @@ class PysolMenubar(PysolMenubarActions):
return "normal"
return "disabled"
def updateProgress(self):
if self.progress: self.progress.update(step=1)
#
# create the menubar
@ -268,9 +275,13 @@ class PysolMenubar(PysolMenubarActions):
menu.add_command(label=n_("&Hold and quit"), command=self.mHoldAndQuit)
menu.add_command(label=n_("&Quit"), command=self.mQuit, accelerator=m+"Q")
if self.progress: self.progress.update(step=1)
menu = MfxMenu(self.__menubar, label=n_("&Select"))
self._addSelectGameMenu(menu)
if self.progress: self.progress.update(step=1)
menu = MfxMenu(self.__menubar, label=n_("&Edit"))
menu.add_command(label=n_("&Undo"), command=self.mUndo, accelerator="Z")
menu.add_command(label=n_("&Redo"), command=self.mRedo, accelerator="R")
@ -321,6 +332,9 @@ class PysolMenubar(PysolMenubarActions):
menu.add_command(label=n_("Demo (&all games)"), command=self.mMixedDemo)
menu.add_separator()
menu.add_command(label=n_("Piles description"), command=self.mStackDesk, accelerator="F2")
if self.progress: self.progress.update(step=1)
menu = MfxMenu(self.__menubar, label=n_("&Options"))
menu.add_command(label=n_("&Player options..."), command=self.mOptPlayerOptions)
submenu = MfxMenu(menu, label=n_("&Automatic play"))
@ -383,6 +397,8 @@ class PysolMenubar(PysolMenubarActions):
### menu.add_separator()
### menu.add_command(label="Save options", command=self.mOptSave)
if self.progress: self.progress.update(step=1)
menu = MfxMenu(self.__menubar, label=n_("&Help"))
menu.add_command(label=n_("&Contents"), command=self.mHelp, accelerator=m+"F1")
menu.add_command(label=n_("&How to play"), command=self.mHelpHowToPlay)
@ -511,6 +527,7 @@ class PysolMenubar(PysolMenubarActions):
submenu = MfxMenu(menu, label=n_("&French games"))
self._addSelectGameSubMenu(submenu, games, GI.SELECT_GAME_BY_TYPE,
self.mSelectGame, self.tkopt.gameid)
if self.progress: self.progress.update(step=1)
submenu = MfxMenu(menu, label=n_("&Mahjongg games"))
self._addSelectMahjonggGameSubMenu(submenu,
self.mSelectGame, self.tkopt.gameid)
@ -522,6 +539,7 @@ class PysolMenubar(PysolMenubarActions):
self._addSelectGameSubMenu(submenu, games, GI.SELECT_SPECIAL_GAME_BY_TYPE,
self.mSelectGame, self.tkopt.gameid)
menu.add_separator()
if self.progress: self.progress.update(step=1)
submenu = MfxMenu(menu, label=n_("All games by name"))
self._addSelectAllGameSubMenu(submenu, games,
self.mSelectGame, self.tkopt.gameid)
@ -620,6 +638,7 @@ class PysolMenubar(PysolMenubarActions):
n, d = 0, self.__cb_max
i = 0
while True:
if self.progress: self.progress.update(step=1)
columnbreak = i > 0 and (i % d) == 0
i += 1
if not g[n:n+d]:

View file

@ -48,8 +48,8 @@ from tkutil import makeToplevel, setTransient, wm_set_icon
# ************************************************************************/
class PysolProgressBar:
def __init__(self, app, parent, title=None, images=None,
color="blue", width=300, height=25, show_text=1):
def __init__(self, app, parent, title=None, images=None, color="blue",
width=300, height=25, show_text=1, norm=1):
self.parent = parent
self.percent = 0
self.top = makeToplevel(parent, title=title)
@ -84,6 +84,8 @@ class PysolProgressBar:
setTransient(self.top, None, relx=0.5, rely=0.5)
else:
self.update(percent=0)
self.norm = norm
self.steps_sum = 0
def wmDeleteWindow(self):
return EVENT_HANDLED
@ -104,6 +106,9 @@ class PysolProgressBar:
self.percent = percent
def update(self, percent=None, step=1):
self.steps_sum += step
##print self.steps_sum
step = step/self.norm
if self.top is None: # already destroyed
return
if percent is None: