diff --git a/pysollib/app.py b/pysollib/app.py index 7da29e8a..32faa22f 100644 --- a/pysollib/app.py +++ b/pysollib/app.py @@ -67,6 +67,7 @@ from pysoltk import PysolToolbar from pysoltk import PysolStatusbar, HelpStatusbar from pysoltk import SelectCardsetByTypeDialogWithPreview from pysoltk import SelectDialogTreeData +from pysoltk import tkHTMLViewer from pysoltk import TOOLBAR_BUTTONS from pysoltk import destroy_find_card_dialog from help import helpAbout, destroy_help @@ -888,6 +889,10 @@ class Application: fn = self.dataloader.findImage(f, dir) im = loadImage(fn) SelectDialogTreeData.img.append(im) + dir = os.path.join('images', 'htmlviewer') + # + fn = self.dataloader.findImage('disk', dir) + tkHTMLViewer.symbols_fn['disk'] = fn def loadImages4(self): # load all remaining images diff --git a/pysollib/games/auldlangsyne.py b/pysollib/games/auldlangsyne.py index bcbbec16..d69286dc 100644 --- a/pysollib/games/auldlangsyne.py +++ b/pysollib/games/auldlangsyne.py @@ -116,6 +116,7 @@ class AuldLangSyne(TamOShanter): # /*********************************************************************** # // Strategy +# // Strategy + # ************************************************************************/ class Strategy_Foundation(SS_FoundationStack): @@ -158,12 +159,12 @@ class Strategy_RowStack(BasicRowStack): class Strategy(Game): - def createGame(self): + def createGame(self, rows=8): # 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 + rows*l.XS, l.YM + 4*l.YS) # create stacks x, y, = l.XM, l.YM @@ -172,10 +173,11 @@ class Strategy(Game): for i in range(4): x, y = l.XM + (i+2)*l.XS, l.YM s.foundations.append(Strategy_Foundation(x, y, self, suit=i, max_move=0)) - for i in range(8): - x, y = l.XM + i*l.XS, l.YM + l.YS - s.rows.append(Strategy_RowStack(x, y, self, max_move=1, max_accept=1)) - x = x + l.XS + x, y = l.XM, l.YM+l.YS + for i in range(rows): + s.rows.append(Strategy_RowStack(x, y, + self, max_move=1, max_accept=1)) + x += l.XS # define stack-groups l.defaultStackGroups() @@ -194,6 +196,28 @@ class Strategy(Game): self.s.talon.fillStack() +class StrategyPlus(Strategy): + + def createGame(self): + Strategy.createGame(self, rows=6) + + def _shuffleHook(self, cards): + return cards + + def startGame(self): + self.s.talon.fillStack() + + def fillStack(self, stack): + if stack is self.s.talon and stack.cards: + c = stack.cards[-1] + if c.rank == ACE: + old_state = self.enterState(self.S_FILL) + self.moveMove(1, stack, self.s.foundations[c.suit]) + if stack.canFlipCard(): + stack.flipMove() + self.leaveState(old_state) + + # /*********************************************************************** # // Interregnum # ************************************************************************/ @@ -538,4 +562,6 @@ registerGame(GameInfo(560, DoubleAcquaintance, "Double Acquaintance", GI.GT_NUMERICA, 2, 2, GI.SL_BALANCED)) registerGame(GameInfo(569, Primrose, "Primrose", GI.GT_NUMERICA, 2, 8, GI.SL_BALANCED)) +registerGame(GameInfo(636, StrategyPlus, "Strategy +", + GI.GT_NUMERICA, 1, 0, GI.SL_SKILL)) diff --git a/pysollib/games/canfield.py b/pysollib/games/canfield.py index 9be4bf61..4549b951 100644 --- a/pysollib/games/canfield.py +++ b/pysollib/games/canfield.py @@ -807,6 +807,59 @@ class Skippy(Canfield): shallHighlightMatch = Game._shallHighlightMatch_RKW +# /*********************************************************************** +# // Lafayette +# ************************************************************************/ + +class Lafayette(Game): + def createGame(self): + l, s = Layout(self), self.s + self.setSize(l.XM+8*l.XS, l.YM+2*l.YS+12*l.YOFFSET) + + x, y = l.XM, l.YM + for i in range(4): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i)) + s.foundations.append(SS_FoundationStack(x+4*l.XS, y, self, suit=i, + base_rank=KING, dir=-1)) + x += l.XS + x, y = l.XM, l.YM+l.YS + s.talon = WasteTalonStack(x, y, self, max_rounds=UNLIMITED_REDEALS, + num_deal=3) + l.createText(s.talon, 'ne') + y += l.YS + s.waste = WasteStack(x, y, self) + l.createText(s.waste, 'ne') + x, y = l.XM+2*l.XS, l.YM+l.YS + for i in range(4): + s.rows.append(AC_RowStack(x, y, self, base_rank=6)) + x += l.XS + x += l.XS + stack = OpenStack(x, y, self) + s.reserves.append(stack) + stack.CARD_YOFFSET = l.YOFFSET + + l.defaultStackGroups() + + + def startGame(self): + for i in range(13): + self.s.talon.dealRow(rows=self.s.reserves, frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + + def fillStack(self, stack): + if stack in self.s.rows and not stack.cards: + if self.s.reserves[0].cards: + old_state = self.enterState(self.S_FILL) + self.s.reserves[0].moveMove(1, stack) + self.leaveState(old_state) + + + shallHighlightMatch = Game._shallHighlightMatch_AC + + # register the game registerGame(GameInfo(105, Canfield, "Canfield", # was: 262 @@ -856,4 +909,6 @@ registerGame(GameInfo(527, Doorway, "Doorway", altnames=('Solstice',) )) registerGame(GameInfo(605, Skippy, "Skippy", GI.GT_FAN_TYPE, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(642, Lafayette, "Lafayette", + GI.GT_CANFIELD, 1, -1, GI.SL_BALANCED)) diff --git a/pysollib/games/fortythieves.py b/pysollib/games/fortythieves.py index 8a8d5ba7..9115b21d 100644 --- a/pysollib/games/fortythieves.py +++ b/pysollib/games/fortythieves.py @@ -967,6 +967,7 @@ class DoubleGoldMine(Streets): # // Unlimited # // Breakwater # // Forty Nine +# // Alternations # ************************************************************************/ class Interchange(FortyThieves): @@ -1019,6 +1020,11 @@ class FortyNine(Interchange): shallHighlightMatch = Game._shallHighlightMatch_AC +class Alternations(Interchange): + RowStack_Class = AC_RowStack + shallHighlightMatch = Game._shallHighlightMatch_AC + + # /*********************************************************************** # // Indian Patience # ************************************************************************/ @@ -1054,6 +1060,51 @@ class IndianPatience(Indian): self.leaveState(old_state) +# /*********************************************************************** +# // Floradora +# ************************************************************************/ + +class Floradora(Game): + Hint_Class = CautiousDefaultHint + + def createGame(self): + + l, s = Layout(self), self.s + + self.setSize(l.XM+10*l.XS, l.YM+2*l.YS+12*l.YOFFSET+l.TEXT_HEIGHT) + + x, y = l.XM, l.YM + s.talon = WasteTalonStack(x, y, self, max_rounds=1) + l.createText(s.talon, 's') + x += l.XS + s.waste = WasteStack(x, y, self) + l.createText(s.waste, 's') + x += l.XS + for i in range(8): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4, + max_cards=12)) + x += l.XS + x, y = l.XM, l.YM+l.YS+l.TEXT_HEIGHT + s.foundations.append(RK_FoundationStack(x, y, self, suit=ANY_SUIT, + base_rank=KING, dir=0, max_cards=8)) + x += 3*l.XS + for i in range(6): + s.rows.append(RK_RowStack(x, y, self, max_move=1)) + x += l.XS + + l.defaultStackGroups() + + def startGame(self): + for i in range(5): + self.s.talon.dealRow(frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + shallHighlightMatch = Game._shallHighlightMatch_RK + + + # register the game registerGame(GameInfo(13, FortyThieves, "Forty Thieves", GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL, @@ -1162,4 +1213,8 @@ registerGame(GameInfo(588, Roosevelt, "Roosevelt", GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(628, Crossroads, "Crossroads", GI.GT_FORTY_THIEVES, 4, 0, GI.SL_BALANCED)) +registerGame(GameInfo(631, Alternations, "Alternations", + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) +registerGame(GameInfo(632, Floradora, "Floradora", + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_LUCK)) diff --git a/pysollib/games/gypsy.py b/pysollib/games/gypsy.py index 9435b043..3b84e649 100644 --- a/pysollib/games/gypsy.py +++ b/pysollib/games/gypsy.py @@ -703,6 +703,25 @@ class Eclipse(Gypsy): shallHighlightMatch = Game._shallHighlightMatch_SS +# /*********************************************************************** +# // Brazilian Patience +# ************************************************************************/ + +class BrazilianPatience(Gypsy): + Layout_Method = Layout.klondikeLayout + RowStack_Class = KingAC_RowStack + + def createGame(self): + Gypsy.createGame(self, rows=10, playcards=22) + + def startGame(self, flip=0, reverse=1): + for i in range(1, 10): + self.s.talon.dealRow(rows=self.s.rows[i:], flip=0, frames=0) + self.startDealSample() + self.s.talon.dealRow() + + + # register the game registerGame(GameInfo(1, Gypsy, "Gypsy", GI.GT_GYPSY, 2, 0, GI.SL_MOSTLY_SKILL)) @@ -763,4 +782,6 @@ registerGame(GameInfo(581, Flamenco, "Flamenco", GI.GT_GYPSY | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(584, Eclipse, "Eclipse", GI.GT_GYPSY, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(640, BrazilianPatience, "Brazilian Patience", + GI.GT_GYPSY, 2, 0, GI.SL_MOSTLY_SKILL)) diff --git a/pysollib/games/klondike.py b/pysollib/games/klondike.py index 191236fc..a7bf7d45 100644 --- a/pysollib/games/klondike.py +++ b/pysollib/games/klondike.py @@ -139,6 +139,7 @@ class KlondikeByThrees(Klondike): # /*********************************************************************** # // Thumb and Pouch +# // Chinaman # ************************************************************************/ class ThumbAndPouch(Klondike): @@ -153,6 +154,13 @@ class ThumbAndPouch(Klondike): or card2.rank + 1 == card1.rank)) +class Chinaman(ThumbAndPouch): + RowStack_Class = StackWrapper(BO_RowStack, base_rank=KING) + + def createGame(self): + Klondike.createGame(self, num_deal=3, max_rounds=2) + + # /*********************************************************************** # // Whitehead # ************************************************************************/ @@ -1272,6 +1280,20 @@ class BigBertha(Game): shallHighlightMatch = Game._shallHighlightMatch_AC +# /*********************************************************************** +# // Athena +# ************************************************************************/ + +class Athena(Klondike): + + def startGame(self): + self.s.talon.dealRow(frames=0, flip=0) + self.s.talon.dealRow(frames=0) + self.s.talon.dealRow(frames=0, flip=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + # register the game registerGame(GameInfo(2, Klondike, "Klondike", @@ -1404,5 +1426,9 @@ registerGame(GameInfo(627, QueenVictoria, "Queen Victoria", GI.GT_RAGLAN | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(630, BigBertha, "Big Bertha", GI.GT_RAGLAN | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(633, Athena, "Athena", + GI.GT_KLONDIKE, 1, -1, GI.SL_BALANCED)) +registerGame(GameInfo(634, Chinaman, "Chinaman", + GI.GT_KLONDIKE, 1, 1, GI.SL_BALANCED)) diff --git a/pysollib/games/numerica.py b/pysollib/games/numerica.py index 14fe6608..ea0d6df0 100644 --- a/pysollib/games/numerica.py +++ b/pysollib/games/numerica.py @@ -729,6 +729,72 @@ class AnnoDomini(Numerica): shallHighlightMatch = Game._shallHighlightMatch_ACW +# /*********************************************************************** +# // Circle Nine +# ************************************************************************/ + +class CircleNine_RowStack(BasicRowStack): + def acceptsCards(self, from_stack, cards): + if not BasicRowStack.acceptsCards(self, from_stack, cards): + return False + return from_stack is self.game.s.talon + + def getHelp(self): + return _('Tableau. Build regardless of rank and suit.') + + +class CircleNine(Game): + Hint_Class = Numerica_Hint + + def createGame(self): + l, s = Layout(self), self.s + self.setSize(l.XM+7*l.XS, l.YM+3*l.YS) + + for i, j in ((1,0), + (2,0), + (3,0), + (4,0), + (5,1), + (3.5,2), + (2.5,2), + (1.5,2), + (0,1), + ): + x, y = l.XM+(1+i)*l.XS, l.YM+j*l.YS + stack = CircleNine_RowStack(x, y, self, max_accept=1, + max_move=1, base_rank=NO_RANK) + s.rows.append(stack) + stack.CARD_YOFFSET = 0 + + x, y = l.XM+3.5*l.XS, l.YM+l.YS + stack = RK_FoundationStack(x, y, self, suit=ANY_SUIT, + max_cards=52, max_move=0, mod=13) + s.foundations.append(stack) + l.createText(stack, 'ne') + x, y = l.XM, l.YM + s.talon = Strategerie_Talon(x, y, self) + l.createText(s.talon, 'ne') + + l.defaultStackGroups() + self.sg.dropstacks.append(s.talon) + + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow(rows=self.s.foundations) + self.s.talon.dealRow() + self.s.talon.fillStack() + + + def fillStack(self, stack): + if stack in self.s.rows and not stack.cards: + if self.s.talon.cards: + old_state = self.enterState(self.S_FILL) + self.s.talon.moveMove(1, stack) + self.leaveState(old_state) + + + # register the game registerGame(GameInfo(257, Numerica, "Numerica", @@ -765,4 +831,6 @@ 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)) +registerGame(GameInfo(641, CircleNine, "Circle Nine", + GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED)) diff --git a/pysollib/games/royalcotillion.py b/pysollib/games/royalcotillion.py index 606802a3..44d6491f 100644 --- a/pysollib/games/royalcotillion.py +++ b/pysollib/games/royalcotillion.py @@ -721,6 +721,187 @@ class Frames(Game): shallHighlightMatch = Game._shallHighlightMatch_SS +# /*********************************************************************** +# // Royal Rendezvous +# ************************************************************************/ + +class RoyalRendezvous(Game): + + def createGame(self): + l, s = Layout(self), self.s + self.setSize(l.XM+9.5*l.XS, l.YM+4.5*l.YS) + + y = l.YM + # kings + suit = 0 + for i in (0,1,6,7): + x = l.XM+(1.5+i)*l.XS + s.foundations.append(SS_FoundationStack(x, y, self, suit=suit, + base_rank=KING, max_cards=1)) + suit += 1 + # aces + suit = 0 + for i in (2,3,4,5): + x = l.XM+(1.5+i)*l.XS + s.foundations.append(SS_FoundationStack(x, y, self, suit=suit)) + suit += 1 + y += l.YS + # twos + suit = 0 + for i in (0,1,6,7): + x = l.XM+(1.5+i)*l.XS + s.foundations.append(SS_FoundationStack(x, y, self, suit=suit, + base_rank=1, dir=2, max_cards=6)) + suit += 1 + # aces + suit = 0 + for i in (2,3,4,5): + x = l.XM+(1.5+i)*l.XS + s.foundations.append(SS_FoundationStack(x, y, self, suit=suit, + dir=2, max_cards=6)) + suit += 1 + + y += 1.5*l.YS + for i in (0,1): + x = l.XM+1.5*l.XS + for j in range(8): + s.rows.append(OpenStack(x, y, self, max_accept=0)) + x += l.XS + y += l.YS + + 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 _shuffleHook(self, cards): + # move twos to top + cards = self._shuffleHookMoveToTop(cards, + lambda c: (c.rank == 1 and c.deck == 0, c.suit)) + # move aces to top + cards = self._shuffleHookMoveToTop(cards, + lambda c: (c.rank == ACE, (c.deck, c.suit))) + return cards + + + def startGame(self): + # deal aces + self.s.talon.dealRow(rows=self.s.foundations[4:8], frames=0) + self.s.talon.dealRow(rows=self.s.foundations[12:16], frames=0) + # deal twos + self.s.talon.dealRow(rows=self.s.foundations[8:12], frames=0) + # + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + + def fillStack(self, stack): + if not stack.cards and stack in self.s.rows: + 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) + + +# /*********************************************************************** +# // Shady Lanes +# ************************************************************************/ + +class ShadyLanes_Hint(CautiousDefaultHint): + def computeHints(self): + CautiousDefaultHint.computeHints(self) + if self.hints: + return + for r in self.game.s.rows: + if not r.cards: + for s in self.game.s.reserves: + if s.cards: + self.addHint(5000-s.cards[0].rank, 1, s, r) + + +class ShadyLanes_Foundation(AbstractFoundationStack): + def acceptsCards(self, from_stack, cards): + if not AbstractFoundationStack.acceptsCards(self, from_stack, cards): + return False + if self.cards: + # check the rank + if self.cards[-1].rank+1 != cards[0].rank: + return False + return True + + def getHelp(self): + return _('Foundation. Build up by color.') + + +class ShadyLanes_RowStack(AC_RowStack): + def acceptsCards(self, from_stack, cards): + if not AC_RowStack.acceptsCards(self, from_stack, cards): + return False + if not self.cards: + return from_stack in self.game.s.reserves + return True + + +class ShadyLanes(Game): + Hint_Class = ShadyLanes_Hint + + def createGame(self): + l, s = Layout(self), self.s + self.setSize(l.XM+8*l.XS, l.YM+5*l.YS) + + x, y = l.XM, l.YM + for i in range(8): + suit = i/2 + color = suit/2 + s.foundations.append(ShadyLanes_Foundation(x, y, self, + base_suit=suit, suit=ANY_SUIT, color=color)) + x += l.XS + x, y = l.XM, l.YM+l.YS + 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') + x, y = l.XM+2*l.XS, l.YM+l.YS + for i in range(4): + s.rows.append(ShadyLanes_RowStack(x, y, self, max_move=1)) + x += l.XS + + x, y = self.width-l.XS, l.YM+l.YS + for i in range(4): + s.reserves.append(OpenStack(x, y, self, max_accept=0)) + y += l.YS + + l.defaultStackGroups() + + + 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) + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow(rows=self.s.reserves) + self.s.talon.dealRow() + self.s.talon.dealCards() + + shallHighlightMatch = Game._shallHighlightMatch_AC + + + # register the game registerGame(GameInfo(54, RoyalCotillion, "Royal Cotillion", GI.GT_2DECK_TYPE, 2, 0, GI.SL_LUCK)) @@ -750,4 +931,8 @@ 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)) +registerGame(GameInfo(638, RoyalRendezvous, "Royal Rendezvous", + GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) +registerGame(GameInfo(639, ShadyLanes, "Shady Lanes", + GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) diff --git a/pysollib/games/sultan.py b/pysollib/games/sultan.py index d358bf25..0e95f691 100644 --- a/pysollib/games/sultan.py +++ b/pysollib/games/sultan.py @@ -864,6 +864,51 @@ class RoyalAids(Game): shallHighlightMatch = Game._shallHighlightMatch_AC +# /*********************************************************************** +# // Circle Eight +# ************************************************************************/ + +class CircleEight(Game): + + def createGame(self): + + l, s = Layout(self), self.s + self.setSize(l.XM+5*l.XS, l.YM+3*l.YS) + + for i, j in ((1,0), + (2,0), + (3,0), + (4,1), + (3,2), + (2,2), + (1,2), + (0,1), + ): + x, y = l.XM+i*l.XS, l.YM+j*l.YS + stack = RK_RowStack(x, y, self, dir=1, mod=13, max_move=0) + s.rows.append(stack) + stack.CARD_YOFFSET = 0 + + x, y = l.XM+1.5*l.XS, l.YM+l.YS + s.talon = WasteTalonStack(x, y, self, max_rounds=2) + l.createText(s.talon, 'nw') + x += l.XS + s.waste = WasteStack(x, y, self) + l.createText(s.waste, 'ne') + + l.defaultStackGroups() + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + def isGameWon(self): + return len(self.s.talon.cards) == 0 and len(self.s.waste.cards) == 0 + + shallHighlightMatch = Game._shallHighlightMatch_RKW + + # register the game registerGame(GameInfo(330, Sultan, "Sultan", GI.GT_2DECK_TYPE, 2, 2, GI.SL_MOSTLY_LUCK, @@ -898,3 +943,5 @@ registerGame(GameInfo(565, RoyalAids, "Royal Aids", GI.GT_2DECK_TYPE, 2, UNLIMITED_REDEALS, GI.SL_BALANCED)) registerGame(GameInfo(598, PicturePatience, "Picture Patience", GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK)) +registerGame(GameInfo(635, CircleEight, "Circle Eight", + GI.GT_1DECK_TYPE, 1, 1, GI.SL_MOSTLY_LUCK)) diff --git a/pysollib/games/terrace.py b/pysollib/games/terrace.py index b24bdfaa..14f953cb 100644 --- a/pysollib/games/terrace.py +++ b/pysollib/games/terrace.py @@ -343,6 +343,102 @@ class MamySusan(Terrace): pass +# /*********************************************************************** +# // Bastille Day +# ************************************************************************/ + +class BastilleDay_BastilleStack(Stack): + def clickHandler(self, event): + return self.dealCards(sound=1) + + def rightclickHandler(self, event): + return self.clickHandler(event) + + def canDealCards(self): + if self.game.s.reserves[-1].cards: + return 0 < len(self.cards) < 12 + return len(self.cards) > 0 + + def dealCards(self, sound=0): + if not self.canDealCards(): + return 0 + old_state = self.game.enterState(self.game.S_DEAL) + if sound and not self.game.demo: + self.game.playSample("dealwaste") + self.flipMove() + self.moveMove(1, self.game.s.reserves[-1], frames=4, shadow=0) + self.game.leaveState(old_state) + return 1 + + def getHelp(self): + return '' # FIXME + + +class BastilleDay(Game): + + def createGame(self, rows=9, max_rounds=1, num_deal=1, playcards=16): + l, s = Layout(self), self.s + self.setSize(l.XM+8*l.XS, l.YM+3*l.YS+12*l.YOFFSET+l.TEXT_HEIGHT) + + x, y = l.XM, l.YM + s.talon = WasteTalonStack(x, y, self, max_rounds=1) + l.createText(s.talon, 's') + x += l.XS + s.waste = WasteStack(x, y, self) + l.createText(s.waste, 's') + x += 2*l.XS + stack = BastilleDay_BastilleStack(x, y, self) + s.reserves.append(stack) + l.createText(stack, 's') + x += l.XS + stack = OpenStack(x, y, self) + stack.CARD_XOFFSET = l.XOFFSET + l.createText(stack, 's') + s.reserves.append(stack) + + x, y = l.XM, l.YM+l.YS+l.TEXT_HEIGHT + for i in range(8): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4)) + x = x + l.XS + x, y = l.XM, l.YM+2*l.YS+l.TEXT_HEIGHT + for i in range(8): + s.rows.append(AC_RowStack(x, y, self)) + x = x + l.XS + + l.defaultStackGroups() + + + def _shuffleHook(self, cards): + # move Kings to top + cards = self._shuffleHookMoveToTop(cards, + lambda c: (c.rank == KING, None)) + # move any 4 cards to top + cards = cards[4:]+cards[:4] + return cards + + def startGame(self, nrows=4): + for i in range(12): # deal to Bastille + self.s.talon.dealRow(flip=0, rows=[self.s.reserves[0]], frames=0) + for i in range(9): + self.s.talon.dealRow(rows=[self.s.reserves[-1]], frames=0) + for i in range(3): + self.s.talon.dealRow(flip=0, frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + def dealCards(self, sound=1): + # for demo-mode + if self.demo: + r = self.s.reserves[0] + if r.canDealCards(): + self.demo.last_deal = [] # don't check last deal + return r.dealCards(sound=sound) + return Game.dealCards(self, sound=sound) + + shallHighlightMatch = Game._shallHighlightMatch_AC + + # register the game registerGame(GameInfo(135, Terrace, "Terrace", @@ -363,4 +459,6 @@ registerGame(GameInfo(533, MamySusan, "Mamy Susan", GI.GT_TERRACE, 2, 0, GI.SL_BALANCED)) registerGame(GameInfo(582, Wood, "Wood", GI.GT_TERRACE, 2, 0, GI.SL_BALANCED)) +registerGame(GameInfo(637, BastilleDay, "Bastille Day", + GI.GT_TERRACE, 2, 0, GI.SL_BALANCED)) diff --git a/pysollib/main.py b/pysollib/main.py index 4c0629a1..e9f14010 100644 --- a/pysollib/main.py +++ b/pysollib/main.py @@ -445,7 +445,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, norm=1.32) + images=app.progress_images, norm=1.4) # prepare other images app.loadImages2() diff --git a/pysollib/stack.py b/pysollib/stack.py index 21cc6fc1..082c0749 100644 --- a/pysollib/stack.py +++ b/pysollib/stack.py @@ -2163,6 +2163,7 @@ class FaceUpWasteTalonStack(WasteTalonStack): def fillStack(self): if self.canFlipCard(): self.game.flipMove(self) + self.game.fillStack(self) class OpenTalonStack(TalonStack, OpenStack): @@ -2183,6 +2184,7 @@ class OpenTalonStack(TalonStack, OpenStack): def fillStack(self): if self.canFlipCard(): self.game.flipMove(self) + self.game.fillStack(self) def clickHandler(self, event): if self.canDealCards(): diff --git a/pysollib/tk/selecttree.py b/pysollib/tk/selecttree.py index db299b57..5486c387 100644 --- a/pysollib/tk/selecttree.py +++ b/pysollib/tk/selecttree.py @@ -91,7 +91,7 @@ class SelectDialogTreeNode(MfxTreeNode): # ************************************************************************/ class SelectDialogTreeData: - img = None + img = [] # loaded in Application.loadImages3 def __init__(self): self.tree_xview = (0.0, 1.0) self.tree_yview = (0.0, 1.0) diff --git a/pysollib/tk/tkhtml.py b/pysollib/tk/tkhtml.py index 2ce7d6e0..8c735d90 100644 --- a/pysollib/tk/tkhtml.py +++ b/pysollib/tk/tkhtml.py @@ -166,7 +166,18 @@ class tkHTMLWriter(formatter.DumbWriter): self.indent = " " * level def send_label_data(self, data): - self.__write(self.indent + data + " ") + ##self.__write(self.indent + data + " ") + self.__write(self.indent) + if data == '*': #