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

+ 3 new games

+ new stack - ArbitraryStack, new AtomicMove - ASingleCardMove


git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@22 39dd0a4e-7c14-0410-91b3-c4f2d318f732
This commit is contained in:
skomoroh 2006-07-20 21:26:13 +00:00
parent d71672694a
commit 2c7c722413
6 changed files with 272 additions and 21 deletions

View file

@ -62,7 +62,7 @@ from pysoltk import Card
from move import AMoveMove, AFlipMove, ATurnStackMove
from move import ANextRoundMove, ASaveSeedMove, AShuffleStackMove
from move import AUpdateStackMove, AFlipAllMove, ASaveStateMove
from move import ACloseStackMove
from move import ACloseStackMove, ASingleCardMove
from hint import DefaultHint
from help import helpAbout
@ -228,6 +228,7 @@ class Game:
start_y = 0, # Y coord of initial drag event
stack = None, #
cards = [], #
index = -1, #
shadows = [], # list of canvas images
shade_stack = None, # stack currently shaded
shade_img = None, # canvas image
@ -1963,6 +1964,13 @@ for %d moves.
self.__storeMove(am)
am.do(self)
def singleCardMove(self, from_stack, to_stack, position, frames=-1, shadow=-1):
am = ASingleCardMove(from_stack, to_stack, position, frames, shadow)
self.__storeMove(am)
am.do(self)
self.hints.list = None
# Finish the current move.
def finishMove(self):

View file

@ -219,6 +219,35 @@ class Arabella(DoubleKlondike):
return 0
# /***********************************************************************
# // Big Deal
# ************************************************************************/
class BigDeal(DoubleKlondike):
def createGame(self, rows=12, max_rounds=2):
l, s = Layout(self), self.s
self.setSize(l.XM+(rows+2)*l.XS, l.YM+8*l.YS)
x, y = l.XM, l.YM
for i in range(rows):
s.rows.append(AC_RowStack(x, y, self, base_rank=KING))
x += l.XS
for i in range(2):
y = l.YM
for j in range(8):
s.foundations.append(SS_FoundationStack(x, y, self, suit=j%4))
y += l.YS
x += l.XS
x, y = l.XM, self.height-l.YS
s.talon = WasteTalonStack(x, y, self, max_rounds=max_rounds)
l.createText(s.talon, 'n')
x += l.XS
s.waste = WasteStack(x, y, self)
l.createText(s.waste, 'n')
self.setRegion(s.rows, (-999, -999, l.XM+rows*l.XS-l.CW/2, 999999), priority=1)
l.defaultStackGroups()
# register the game
registerGame(GameInfo(21, DoubleKlondike, "Double Klondike",
GI.GT_KLONDIKE, 2, -1, GI.SL_BALANCED))
@ -241,4 +270,6 @@ registerGame(GameInfo(496, Inquisitor, "Inquisitor",
GI.GT_KLONDIKE, 2, 2, GI.SL_BALANCED))
registerGame(GameInfo(497, Arabella, "Arabella",
GI.GT_KLONDIKE, 3, 0, GI.SL_BALANCED))
registerGame(GameInfo(545, BigDeal, "Big Deal",
GI.GT_KLONDIKE | GI.GT_ORIGINAL, 4, 1, GI.SL_BALANCED))

View file

@ -486,7 +486,7 @@ class FlowerGarden(Stonewall):
# // Brigade
# ************************************************************************/
class KingAlbert(Klondike):
class KingAlbertOld(Klondike):
Talon_Class = InitialDealTalonStack
RowStack_Class = StackWrapper(AC_RowStack, max_move=1)
Hint_Class = CautiousDefaultHint
@ -511,6 +511,19 @@ class KingAlbert(Klondike):
self.s.talon.dealRow(rows=self.s.reserves)
class KingAlbert(KingAlbertOld):
def createGame(self):
l = Klondike.createGame(self, max_rounds=1, rows=self.ROWS, waste=0, texts=0)
self.setSize(self.width+l.XM+l.XS, self.height)
self.s.reserves.append(ArbitraryStack(self.width-l.XS, l.YM, self))
l.defaultStackGroups()
def startGame(self):
Klondike.startGame(self, flip=1, reverse=0)
self.s.talon.dealRow(rows=self.s.reserves*7)
class Raglan(KingAlbert):
RESERVES = (2, 2, 2)

View file

@ -396,11 +396,13 @@ class Wasp(Scorpion):
# /***********************************************************************
# // Three Blind Mice
# // Farmer's Wife
# ************************************************************************/
class ThreeBlindMice(Scorpion):
Talon_Class = InitialDealTalonStack
ReserveStack_Class = OpenStack
def createGame(self):
# create layout
@ -420,7 +422,7 @@ class ThreeBlindMice(Scorpion):
x += l.XS
x, y = l.XM, l.YM
for i in range(2):
s.reserves.append(OpenStack(x, y, self, max_move=1, max_accept=0))
s.reserves.append(self.ReserveStack_Class(x, y, self))
x += l.XS
# default
l.defaultAll()
@ -435,6 +437,15 @@ class ThreeBlindMice(Scorpion):
self.s.talon.dealRow(rows=self.s.reserves)
class FarmersWife(ThreeBlindMice):
Foundation_Class = Spider_AC_Foundation
RowStack_Class = StackWrapper(ScorpionTail_RowStack, base_rank=KING)
class HowTheyRun(ThreeBlindMice):
ReserveStack_Class = ReserveStack
# /***********************************************************************
# // Rouge et Noir
# ************************************************************************/
@ -1109,4 +1120,8 @@ registerGame(GameInfo(511, DoubleScorpion, "Double Scorpion",
GI.GT_SPIDER, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(512, TripleScorpion, "Triple Scorpion",
GI.GT_SPIDER, 3, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(543, FarmersWife, "Farmer's Wife",
GI.GT_SPIDER, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(544, HowTheyRun, "How They Run",
GI.GT_SPIDER, 1, 0, GI.SL_MOSTLY_SKILL))

View file

@ -446,15 +446,79 @@ class ACloseStackMove(AtomicMove):
def redo(self, game):
stack = game.allstacks[self.stack_id]
assert stack.cards
stack.is_closed = True
stack.is_filled = True
stack._shadeStack()
def undo(self, game):
stack = game.allstacks[self.stack_id]
assert stack.cards
stack.is_closed = False
stack.is_filled = False
stack._unshadeStack()
def cmpForRedo(self, other):
return cmp(self.stack_id, other.stack_id)
# /***********************************************************************
# // ASingleCardMove - move single card from *anyone* position
# ************************************************************************/
class ASingleCardMove(AtomicMove):
def __init__(self, from_stack, to_stack, from_pos, frames, shadow=-1):
self.from_stack_id = from_stack.id
self.to_stack_id = to_stack.id
self.from_pos = from_pos
self.frames = frames
self.shadow = shadow
def redo(self, game):
from_stack = game.allstacks[self.from_stack_id]
to_stack = game.allstacks[self.to_stack_id]
from_pos = self.from_pos
if game.moves.state == game.S_PLAY:
assert to_stack.acceptsCards(from_stack, [from_stack.cards[from_pos]])
card = from_stack.cards[from_pos]
card = from_stack.removeCard(card, update_positions=1)
if self.frames != 0:
x, y = to_stack.getPositionFor(card)
game.animatedMoveTo(from_stack, to_stack, [card], x, y,
frames=self.frames, shadow=self.shadow)
to_stack.addCard(card)
def undo(self, game):
from_stack = game.allstacks[self.from_stack_id]
to_stack = game.allstacks[self.to_stack_id]
from_pos = self.from_pos
card = to_stack.removeCard()
## if self.frames != 0:
## x, y = to_stack.getPositionFor(card)
## game.animatedMoveTo(from_stack, to_stack, [card], x, y,
## frames=self.frames, shadow=self.shadow)
from_stack.insertCard(card, from_pos)
def cmpForRedo(self, other):
return cmp((self.from_stack_id, self.to_stack_id, self.from_pos),
(other.from_stack_id, other.to_stack_id, other.from_pos))
# /***********************************************************************
# // AInnerMove - change position of single card in stack
# ************************************************************************/
class AInnerMove(AtomicMove):
def __init__(self, stack, from_pos, to_pos):
self.stack_id = stack.id
self.from_pos, self.to_pos = from_pos, to_pos
def redo(self, game):
pass
def undo(self, game):
pass
def cmpForRedo(self, other):
return cmp((self.stack_id, self.from_pos, self.to_pos),
(other.stack_id, other.from_pos, other.to_pos))

View file

@ -84,6 +84,7 @@ __all__ = ['cardsFaceUp',
'StackWrapper',
'WeakStackWrapper',
'FullStackWrapper',
'ArbitraryStack',
]
# imports
@ -301,7 +302,7 @@ class Stack:
view.can_hide_cards = -1
view.max_shadow_cards = -1
#
view.is_closed = False
view.is_filled = False
def destruct(self):
# help breaking circular references
@ -431,8 +432,24 @@ class Stack:
self.closeStackMove()
return card
def insertCard(self, card, positon, unhide=1, update=1):
model, view = self, self
model.cards.insert(positon, card)
for c in model.cards[positon:]:
c.tkraise(unhide=unhide)
if view.can_hide_cards and len(model.cards) >= 3 and len(model.cards)-positon <= 2:
# we only need to display the 2 top cards
model.cards[-3].hide(self)
card.item.addtag(view.group)
for c in model.cards[positon:]:
view._position(c)
if update:
view.updateText()
self.closeStackMove()
return card
# Remove a card from the stack. Also update display. {model -> view}
def removeCard(self, card=None, unhide=1, update=1):
def removeCard(self, card=None, unhide=1, update=1, update_positions=0):
model, view = self, self
assert len(model.cards) > 0
if card is None:
@ -453,12 +470,16 @@ class Stack:
if card is model.cards[-1] or model is self.cards[-2]:
# Make sure that 2 top cards will be un-hidden.
model.cards[-3].unhide()
card_index = model.cards.index(card)
model.cards.remove(card)
if update_positions:
for c in model.cards[card_index:]:
view._position(c)
if update:
view.updateText()
if self.is_closed:
if self.is_filled:
self._unshadeStack()
self.is_closed = False
self.is_filled = False
return card
# Get the top card {model}
@ -979,6 +1000,9 @@ class Stack:
# Drag internals {controller -> model -> view}
#
def getDragCards(self, index):
return self.cards[index:]
# begin a drag operation
def startDrag(self, event, sound=1):
#print event.x, event.y
@ -986,7 +1010,7 @@ class Stack:
i = self._findCard(event)
if i < 0 or not self.canMoveCards(self.cards[i:]):
return
if self.is_closed:
if self.is_filled:
self.items.shade_item.config(state='hidden')
x_offset, y_offset = self.cards[i].x, self.cards[i].y
if sound:
@ -999,7 +1023,8 @@ class Stack:
drag.start_y = event.y
drag.stack = self
drag.noshade_stacks = [ self ]
drag.cards = self.cards[i:]
drag.cards = self.getDragCards(i)
drag.index = i
images = game.app.images
drag.shadows = self.createShadows(drag.cards)
##sx, sy = 0, 0
@ -1199,7 +1224,7 @@ class Stack:
drag.shadows = []
drag.stack = None
drag.cards = []
if self.is_closed:
if self.is_filled:
self.items.shade_item.config(state='normal')
self.items.shade_item.tkraise()
@ -1639,6 +1664,9 @@ class OpenStack(Stack):
return self.highlightMatchingCards(event)
return 0
def dragMove(self, drag, stack, sound=1):
self.playMoveMove(len(drag.cards), stack, frames=0, sound=sound)
def releaseHandler(self, event, drag, sound=1):
cards = drag.cards
# check if we moved the card by at least 10 pixels
@ -1657,7 +1685,8 @@ class OpenStack(Stack):
Stack.releaseHandler(self, event, drag, sound=sound)
else:
# this code actually moves the cards to the new stack
self.playMoveMove(len(cards), stack, frames=0, sound=sound)
##self.playMoveMove(len(cards), stack, frames=0, sound=sound)
self.dragMove(drag, stack, sound=sound)
def quickPlayHandler(self, event, from_stacks=None, to_stacks=None):
##print 'quickPlayHandler', from_stacks, to_stacks
@ -1697,12 +1726,11 @@ class OpenStack(Stack):
#
if moves:
moves.sort()
moves.reverse()
##from pprint import pprint
##pprint(moves)
if moves[0][0] >= 0:
##from pprint import pprint; pprint(moves)
score, len_moves, ncards, from_stack, to_stack = moves[-1]
if score >= 0:
##self.game.playSample("startdrag")
moves[0][3].playMoveMove(moves[0][2], moves[0][4])
from_stack.playMoveMove(ncards, to_stack)
return 1
return 0
@ -2163,6 +2191,101 @@ class InvisibleStack(Stack):
return None
# /***********************************************************************
# // ArbitraryStack (stack with arbitrary access)
# ************************************************************************/
class ArbitraryStack(OpenStack):
def __init__(self, x, y, game, **cap):
kwdefault(cap, max_accept=0)
apply(OpenStack.__init__, (self, x, y, game), cap)
self.CARD_YOFFSET = game.app.images.CARD_YOFFSET
def canMoveCards(self, cards):
return True
def getDragCards(self, index):
return [ self.cards[index] ]
def startDrag(self, event, sound=1):
OpenStack.startDrag(self, event, sound=sound)
def doubleclickHandler(self, event):
# flip or drop a card
flipstacks, dropstacks, quickstacks = self.game.getAutoStacks(event)
if self in flipstacks and self.canFlipCard():
self.playFlipMove()
return -1 # continue this event (start a drag)
if self in dropstacks:
i = self._findCard(event)
if i < 0:
return 0
cards = [ self.cards[i] ]
for s in self.game.s.foundations:
if s is not self and s.acceptsCards(self, cards):
self.game.playSample("autodrop", priority=30)
self.playSingleCardMove(i, s, sound=0)
return 1
return 0
## def moveMove(self, ncards, to_stack, frames=-1, shadow=-1):
## i = len(self.cards)-1
## self.singleCardMove(i, to_stack, frames=frames, shadow=shadow)
def moveCardsBackHandler(self, event, drag):
i = self.cards.index(drag.cards[0])
for card in self.cards[i:]:
self._position(card)
card.tkraise()
def singleCardMove(self, index, to_stack, frames=-1, shadow=-1):
self.game.singleCardMove(self, to_stack, index, frames=frames, shadow=shadow)
self.fillStack()
def dragMove(self, drag, to_stack, sound=1):
self.playSingleCardMove(drag.index, to_stack, frames=0, sound=sound)
def playSingleCardMove(self, index, to_stack, frames=-1, shadow=-1, sound=1):
if sound:
if to_stack in self.game.s.foundations:
self.game.playSample("drop", priority=30)
else:
self.game.playSample("move", priority=10)
self.singleCardMove(index, to_stack, frames=frames, shadow=shadow)
if not self.game.checkForWin():
# let the player put cards back from the foundations
if not self in self.game.s.foundations:
self.game.autoPlay()
self.game.finishMove()
def quickPlayHandler(self, event, from_stacks=None, to_stacks=None):
if to_stacks is None:
to_stacks = self.game.s.foundations + self.game.sg.dropstacks
if not self.cards:
return 0
#
moves = []
i = self._findCard(event)
if i < 0:
return 0
pile = [ self.cards[i] ]
for s in to_stacks:
if s is not self and s.acceptsCards(self, pile):
score = self.game.getQuickPlayScore(1, self, s)
moves.append((score, -len(moves), i, s))
#
if moves:
moves.sort()
##from pprint import pprint; pprint(moves)
score, len_moves, index, to_stack = moves[-1]
if score >= 0:
##self.game.playSample("startdrag")
self.playSingleCardMove(index, to_stack)
return 1
return 0
# /***********************************************************************
# // A StackWrapper is a functor (function object) that creates a
# // new stack when called, i.e. it wraps the constructor.
@ -2199,7 +2322,4 @@ class FullStackWrapper(StackWrapper):
return apply(self.stack_class, (x, y, game), self.cap)
# /***********************************************************************
# //
# ************************************************************************/