#!/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 . # # ---------------------------------------------------------------------------## import math from pysollib.game import Game from pysollib.gamedb import GI, GameInfo, registerGame from pysollib.hint import AbstractHint, DefaultHint from pysollib.layout import Layout from pysollib.mfxutil import kwdefault from pysollib.mygettext import _ from pysollib.pysoltk import MfxCanvasText from pysollib.stack import \ AC_RowStack, \ AbstractFoundationStack, \ BasicRowStack, \ DealRowTalonStack, \ InitialDealTalonStack, \ OpenStack, \ RK_RowStack, \ ReserveStack, \ SS_FoundationStack, \ SS_RowStack, \ StackWrapper, \ WasteStack, \ WasteTalonStack, \ isSameSuitSequence from pysollib.util import ANY_RANK, ANY_SUIT, NO_RANK, UNLIMITED_ACCEPTS, \ UNLIMITED_CARDS, UNLIMITED_MOVES # ************************************************************************ # * Mughal Foundation Stacks # ***********************************************************************/ class Mughal_FoundationStack(AbstractFoundationStack): def __init__(self, x, y, game, suit, **cap): kwdefault(cap, max_move=0) SS_FoundationStack.__init__(self, x, y, game, suit, **cap) def updateText(self): AbstractFoundationStack.updateText(self) self.game.updateText() class Triumph_Foundation(AbstractFoundationStack): def __init__(self, x, y, game, suit, **cap): kwdefault(cap, mod=12, dir=0, base_rank=NO_RANK, max_move=0) AbstractFoundationStack.__init__(self, x, y, game, suit, **cap) def acceptsCards(self, from_stack, cards): if not AbstractFoundationStack.acceptsCards(self, from_stack, cards): return 0 if not self.cards: return 1 stack_dir = self.game.getFoundationDir() if stack_dir == 0: card_dir = (cards[0].rank - self.cards[-1].rank) % self.cap.mod return card_dir in (1, 11) else: return (self.cards[-1].rank + stack_dir) % self.cap.mod \ == cards[0].rank # ************************************************************************ # * Mughal Row Stacks # ***********************************************************************/ class Mughal_OpenStack(OpenStack): def __init__(self, x, y, game, yoffset, **cap): kwdefault(cap, max_move=UNLIMITED_MOVES, max_cards=UNLIMITED_CARDS, max_accept=UNLIMITED_ACCEPTS, base_rank=0, dir=-1) OpenStack.__init__(self, x, y, game, **cap) self.CARD_YOFFSET = yoffset def isRankSequence(self, cards, dir=None): if not dir: dir = self.cap.dir c1 = cards[0] for c2 in cards[1:]: if not c1.rank + dir == c2.rank: return 0 c1 = c2 return 1 def isAlternateColorSequence(self, cards, dir=None): if not dir: dir = self.cap.dir c1 = cards[0] for c2 in cards[1:]: if not ((c1.suit + c2.suit) % 2 and c1.rank + dir == c2.rank): return 0 c1 = c2 return 1 def isAlternateForceSequence(self, cards, dir=None): if not dir: dir = self.cap.dir c1 = cards[0] for c2 in cards[1:]: if not ((c1.suit < 4 and c2.suit > 3 or c1.suit > 3 and c2.suit < 4) and c1.rank + dir == c2.rank): return 0 c1 = c2 return 1 def isSuitSequence(self, cards, dir=None): if not dir: dir = self.cap.dir c1 = cards[0] for c2 in cards[1:]: if not (c1.suit == c2.suit and c1.rank + dir == c2.rank): return 0 c1 = c2 return 1 class Mughal_AC_RowStack(Mughal_OpenStack): def acceptsCards(self, from_stack, cards): if (not self.basicAcceptsCards(from_stack, cards) or not self.isAlternateColorSequence(cards)): return 0 stackcards = self.cards if not len(stackcards): return cards[0].rank == 11 or self.cap.base_rank == ANY_RANK return self.isAlternateColorSequence([stackcards[-1], cards[0]]) class Mughal_AF_RowStack(Mughal_OpenStack): def acceptsCards(self, from_stack, cards): if (not self.basicAcceptsCards(from_stack, cards) or not self.isAlternateForceSequence(cards)): return 0 stackcards = self.cards if not len(stackcards): return cards[0].rank == 11 or self.cap.base_rank == ANY_RANK return self.isAlternateForceSequence([stackcards[-1], cards[0]]) class Mughal_RK_RowStack(Mughal_OpenStack): def acceptsCards(self, from_stack, cards): if (not self.basicAcceptsCards(from_stack, cards) or not self.isRankSequence(cards)): return 0 stackcards = self.cards if not len(stackcards): return cards[0].rank == 11 or self.cap.base_rank == ANY_RANK return self.isRankSequence([stackcards[-1], cards[0]]) class Mughal_SS_RowStack(Mughal_OpenStack): def acceptsCards(self, from_stack, cards): if (not self.basicAcceptsCards(from_stack, cards) or not self.isSuitSequence(cards)): return 0 stackcards = self.cards if not len(stackcards): return cards[0].rank == 11 or self.cap.base_rank == ANY_RANK return self.isSuitSequence([stackcards[-1], cards[0]]) class Circles_RowStack(SS_RowStack): def __init__(self, x, y, game, base_rank, yoffset): SS_RowStack.__init__( self, x, y, game, base_rank=base_rank, max_accept=1, max_move=1) self.CARD_YOFFSET = 1 class Triumph_BraidStack(OpenStack): def __init__(self, x, y, game, xoffset, yoffset): OpenStack.__init__(self, x, y, game) self.CARD_YOFFSET = int(self.game.app.images.CARD_YOFFSET * yoffset) # use a sine wave for the x offsets self.CARD_XOFFSET = [] j = 1 for i in range(30): self.CARD_XOFFSET.append(int(math.cos(j) * xoffset)) j = j + .9 class Triumph_StrongStack(ReserveStack): def fillStack(self): if not self.cards: if self.game.s.braidstrong.cards: self.game.moveMove(1, self.game.s.braidstrong, self) elif self.game.s.braidweak.cards: self.game.moveMove(1, self.game.s.braidweak, self) def getBottomImage(self): return self.game.app.images.getBraidBottom() class Triumph_WeakStack(ReserveStack): def fillStack(self): if not self.cards: if self.game.s.braidweak.cards: self.game.moveMove(1, self.game.s.braidweak, self) elif self.game.s.braidstrong.cards: self.game.moveMove(1, self.game.s.braidstrong, self) def getBottomImage(self): return self.game.app.images.getBraidBottom() class Triumph_ReserveStack(ReserveStack): def acceptsCards(self, from_stack, cards): if (from_stack is self.game.s.braidstrong or from_stack is self.game.s.braidweak or from_stack in self.game.s.rows): return 0 return ReserveStack.acceptsCards(self, from_stack, cards) def getBottomImage(self): return self.game.app.images.getTalonBottom() # ************************************************************************ # * # ***********************************************************************/ class AbstractMughalGame(Game): SUITS = (_("Crown"), _("Silver"), _("Saber"), _("Servant"), _("Harp"), _("Gold"), _("Document"), _("Stores")) RANKS = (_("Ace"), "2", "3", "4", "5", "6", "7", "8", "9", "10", _("Pradhan"), _("Raja")) COLORS = (_("Brown"), _("Black"), _("Red"), _("Yellow"), _("Green"), _("Grey"), _("Orange"), _("Tan")) FORCE = (_("Strong"), _("Weak")) def updateText(self): pass def shallHighlightMatch(self, stack1, card1, stack2, card2): return (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank) class Triumph_Hint(DefaultHint): # FIXME: demo is not too clever in this game pass # ************************************************************************ # * Mughal Circles # ***********************************************************************/ class MughalCircles(AbstractMughalGame): # # Game layout # def createGame(self): l, s = Layout(self), self.s # Set window size w, h = l.XM + l.XS * 9, l.YM + l.YS * 7 self.setSize(w, h) # Create row stacks x = w // 2 - l.CW // 2 y = h // 2 - l.YS // 2 x0 = (-1, -.8, 0, .8, 1, .8, 0, -.8, -2, -1.9, -1.5, -.8, 0, .8, 1.5, 1.9, 2, 1.9, 1.5, .8, 0, -.8, -1.5, -1.9) y0 = (0, -.8, -1, -.8, 0, .8, 1, .8, 0, -.8, -1.5, -1.9, -2, -1.9, -1.5, -.8, 0, .8, 1.5, 1.9, 2, 1.9, 1.5, .8) for i in range(24): # FIXME: _x, _y = x+l.XS*x0[i]+l.XM*x0[i]*2, y+l.YS*y0[i]+l.YM*y0[i]*2 if _x < 0: _x = 0 if _y < 0: _y = 0 s.rows.append( Circles_RowStack(_x, _y, self, base_rank=ANY_RANK, yoffset=0)) # Create reserve stacks s.reserves.append(ReserveStack(l.XM, h - l.YS, self)) s.reserves.append(ReserveStack(w - l.XS, h - l.YS, self)) # Create foundations x = l.XM y = l.YM for i in range(4): s.foundations.append( SS_FoundationStack( x, y, self, i, mod=12, max_move=0, max_cards=12)) y = y + l.YS x = self.width - l.XS y = l.YM for i in range(4): s.foundations.append( SS_FoundationStack( x, y, self, i + 4, mod=12, max_move=0, max_cards=12)) y = y + l.YS # FIXME: _x1, _x2 = l.XM + l.XS, w - l.XS - l.XM for i in s.rows: if i.x < _x1: i.x = _x1 elif i.x > _x2: i.x = _x2 self.setRegion(s.rows, (_x1, 0, _x2, 999999)) # Create talon s.talon = InitialDealTalonStack(l.XM + l.XS, l.YM, self) # Define stack groups l.defaultStackGroups() # # Game over rides # def startGame(self): assert len(self.s.talon.cards) == 96 self._startDealNumRowsAndDealRowAndCards(3) def shallHighlightMatch(self, stack1, card1, stack2, card2): return ((card1.suit == card2.suit) and ((card1.rank + 1 == card2.rank) or (card1.rank - 1 == card2.rank))) # ************************************************************************ # * Eight Legions # ***********************************************************************/ class EightLegions(AbstractMughalGame): # # Game layout # def createGame(self): l, s = Layout(self), self.s # Set window size self.setSize(l.XM * 3 + l.XS * 9, l.YM + l.YS * 6) # Create row stacks x = l.XM y = l.YM for i in range(8): s.rows.append(RK_RowStack(x, y, self, base_rank=11, max_move=12, max_cards=99)) x = x + l.XS # Create reserve stacks x = self.width - l.XS y = l.YM for i in range(6): s.reserves.append(ReserveStack(x, y, self)) y = y + l.YS y = y - l.YS for i in range(4): x = x - l.XS s.reserves.append(ReserveStack(x, y, self)) self.setRegion(s.rows, (0, 0, l.XM + l.XS * 8, l.YS * 5)) # Create talon s.talon = DealRowTalonStack(l.XM, self.height - l.YS, self) l.createText(s.talon, "n") # Define stack groups l.defaultStackGroups() # # Game over rides # def startGame(self): assert len(self.s.talon.cards) == 96 self._startDealNumRows(4) self.s.talon.dealCards() def isGameWon(self): if len(self.s.talon.cards): return 0 for s in self.s.rows: if len(s.cards) != 12 or not isSameSuitSequence(s.cards): return 0 return 1 # ************************************************************************ # * Shamsher # ***********************************************************************/ class Shamsher(AbstractMughalGame): Layout_Method = staticmethod(Layout.ghulamLayout) Talon_Class = InitialDealTalonStack Foundation_Class = SS_FoundationStack RowStack_Class = RK_RowStack BASE_RANK = ANY_RANK # # Game layout # def createGame(self, **layout): l, s = Layout(self), self.s kwdefault(layout, rows=14, reserves=4, texts=0) self.Layout_Method(l, **layout) self.setSize(l.size[0], l.size[1]) # Create foundations for r in l.s.foundations: s.foundations.append( self.Foundation_Class( r.x, r.y, self, r.suit, mod=12, max_cards=12)) # Create reserve stacks for r in l.s.reserves: s.reserves.append(ReserveStack(r.x, r.y, self, )) # Create row stacks for r in l.s.rows: s.rows.append( self.RowStack_Class( r.x, r.y, self, max_cards=12, suit=ANY_SUIT, base_rank=self.BASE_RANK)) # Create talon s.talon = self.Talon_Class(l.s.talon.x, l.s.talon.y, self) # Define stack groups l.defaultAll() # # Game over rides # def startGame(self): assert len(self.s.talon.cards) == 96 self._startDealNumRows(6) self.s.talon.dealRow(rows=self.s.rows[:12]) self.s.talon.dealCards() # ************************************************************************ # * Ashrafi # ***********************************************************************/ class Ashrafi(Shamsher): Layout_Method = staticmethod(Layout.ghulamLayout) Talon_Class = InitialDealTalonStack Foundation_Class = SS_FoundationStack RowStack_Class = RK_RowStack BASE_RANK = 11 # # Game layout # def createGame(self, **layout): Shamsher.createGame(self) # ************************************************************************ # * Ghulam # ***********************************************************************/ class Ghulam(Shamsher): Layout_Method = staticmethod(Layout.ghulamLayout) Talon_Class = InitialDealTalonStack Foundation_Class = SS_FoundationStack RowStack_Class = SS_RowStack BASE_RANK = ANY_RANK # # Game layout # def createGame(self, **layout): Shamsher.createGame(self) def shallHighlightMatch(self, stack1, card1, stack2, card2): return ((card1.suit == card2.suit) and ((card1.rank + 1 == card2.rank) or (card1.rank - 1 == card2.rank))) # ************************************************************************ # * Tipati # ***********************************************************************/ class Tipati(AbstractMughalGame): Layout_Method = staticmethod(Layout.klondikeLayout) Talon_Class = WasteTalonStack Foundation_Class = SS_FoundationStack RowStack_Class = RK_RowStack BASE_RANK = 11 MAX_MOVE = 0 # # Game layout # def createGame(self, max_rounds=1, num_deal=1, **layout): l, s = Layout(self), self.s kwdefault(layout, rows=8, waste=1) self.Layout_Method(l, **layout) self.setSize(l.size[0], l.size[1]) # Create talon s.talon = self.Talon_Class( l.s.talon.x, l.s.talon.y, self, max_rounds=max_rounds, num_deal=num_deal) s.waste = WasteStack(l.s.waste.x, l.s.waste.y, self) # Create foundations for r in l.s.foundations: s.foundations.append( self.Foundation_Class( r.x, r.y, self, r.suit, mod=12, max_cards=12, max_move=self.MAX_MOVE)) # Create row stacks for r in l.s.rows: s.rows.append( self.RowStack_Class( r.x, r.y, self, suit=ANY_SUIT, base_rank=self.BASE_RANK)) # Define stack groups l.defaultAll() # # Game over rides # def startGame(self): assert len(self.s.talon.cards) == 96 for i in range(8): self.s.talon.dealRow(rows=self.s.rows[i+1:], flip=0, frames=0) self.startDealSample() self.s.talon.dealRow() self.s.talon.dealCards() # ************************************************************************ # * Ashwapati # ***********************************************************************/ class Ashwapati(Tipati): RowStack_Class = SS_RowStack BASE_RANK = ANY_RANK MAX_MOVE = 1 # # Game layout # def createGame(self, **layout): Tipati.createGame(self, max_rounds=-1, num_deal=1) def shallHighlightMatch(self, stack1, card1, stack2, card2): return ((card1.suit == card2.suit) and ((card1.rank + 1 == card2.rank) or (card1.rank - 1 == card2.rank))) # ************************************************************************ # * Gajapati # ***********************************************************************/ class Gajapati(Tipati): RowStack_Class = SS_RowStack BASE_RANK = ANY_RANK MAX_MOVE = 1 # # Game layout # def createGame(self, **layout): Tipati.createGame(self, max_rounds=-1, num_deal=3) def shallHighlightMatch(self, stack1, card1, stack2, card2): return ((card1.suit == card2.suit) and ((card1.rank + 1 == card2.rank) or (card1.rank - 1 == card2.rank))) # ************************************************************************ # * Narpati # ***********************************************************************/ class Narpati(Tipati): RowStack_Class = AC_RowStack MAX_MOVE = 1 # # Game layout # def createGame(self, **layout): Tipati.createGame(self, max_rounds=1, num_deal=1) # ************************************************************************ # * Garhpati # ***********************************************************************/ class Garhpati(Tipati): RowStack_Class = AC_RowStack # # Game layout # def createGame(self, **layout): Tipati.createGame(self, max_rounds=-1, num_deal=3) # ************************************************************************ # * Dhanpati # ***********************************************************************/ class Dhanpati(Tipati): # # Game layout # def createGame(self, **layout): Tipati.createGame(self, max_rounds=2, num_deal=3) # ************************************************************************ # * Akbar's Triumph # ************************************************************************ class AkbarsTriumph(AbstractMughalGame): Hint_Class = Triumph_Hint BRAID_CARDS = 12 BRAID_OFFSET = 1.1 # # game layout # def createGame(self): # create layout l, s = Layout(self), self.s # set window # (piles up to 20 cards are playable - needed for Braid_BraidStack) decks = self.gameinfo.decks h = max(5 * l.YS + 35, l.YS + (self.BRAID_CARDS - 1) * l.YOFFSET) self.setSize(l.XM + l.XS * (7 + decks * 2), l.YM + h) # extra settings self.base_card = None # Create foundations, rows, reserves s.addattr(braidstrong=None) # register extra stack variable s.addattr(braidweak=None) # register extra stack variable x, y = l.XM, l.YM for j in range(4): for i in range(decks): s.foundations.append( Triumph_Foundation( x + l.XS * i, y, self, j, mod=12, max_cards=12)) s.rows.append(Triumph_StrongStack(x + l.XS * decks, y, self)) s.rows.append(Triumph_ReserveStack( x + l.XS * (1 + decks), y, self)) y = y + l.YS x, y = x + l.XS * (5 + decks), l.YM for j in range(4): s.rows.append(Triumph_ReserveStack(x, y, self)) s.rows.append(Triumph_WeakStack(x + l.XS, y, self)) for i in range(decks, 0, -1): s.foundations.append(Triumph_Foundation( x + l.XS * (1 + i), y, self, j + 4, mod=12, max_cards=12)) y = y + l.YS self.texts.info = MfxCanvasText( self.canvas, self.width // 2, h - l.YM // 2, anchor="center", font=self.app.getFont("canvas_default")) # Create braids x, y = l.XM + l.XS * 2.3 + l.XS * decks, l.YM s.braidstrong = Triumph_BraidStack( x, y, self, xoffset=12, yoffset=self.BRAID_OFFSET) x += l.XS * 1.4 s.braidweak = Triumph_BraidStack( x, y, self, xoffset=-12, yoffset=self.BRAID_OFFSET) # Create talon x, y = l.XM + l.XS * 2 + l.XS * decks, h - l.YS - l.YM s.talon = WasteTalonStack(x, y, self, max_rounds=3) l.createText(s.talon, "s") s.talon.texts.rounds = MfxCanvasText( self.canvas, self.width // 2, h - l.YM * 2.5, anchor="center", font=self.app.getFont("canvas_default")) x += l.XS * 2 s.waste = WasteStack(x, y, self) l.createText(s.waste, "s") # define stack-groups self.sg.talonstacks = [s.talon] + [s.waste] self.sg.openstacks = s.foundations + s.rows self.sg.dropstacks = [s.braidstrong] + [s.braidweak] + s.rows \ + [s.waste] # # game overrides # def startGame(self): self.startDealSample() self.base_card = None self.updateText() for i in range(self.BRAID_CARDS): self.s.talon.dealRow(rows=[self.s.braidstrong]) for i in range(self.BRAID_CARDS): self.s.talon.dealRow(rows=[self.s.braidweak]) self.s.talon.dealRow() # deal base_card to foundations, update cap.base_rank self.base_card = self.s.talon.getCard() to_stack = self.s.foundations[ self.base_card.suit * self.gameinfo.decks] self.flipMove(self.s.talon) self.moveMove(1, self.s.talon, to_stack) self.updateText() for s in self.s.foundations: s.cap.base_rank = self.base_card.rank # deal first card to WasteStack self.s.talon.dealCards() def shallHighlightMatch(self, stack1, card1, stack2, card2): return (card1.suit == card2.suit and ((card1.rank + 1) % 12 == card2.rank or (card2.rank + 1) % 12 == card1.rank)) def getHighlightPilesStacks(self): return () def _restoreGameHook(self, game): self.base_card = self.cards[game.loadinfo.base_card_id] for s in self.s.foundations: s.cap.base_rank = self.base_card.rank def _loadGameHook(self, p): self.loadinfo.addattr(base_card_id=None) # register extra load var. self.loadinfo.base_card_id = p.load() def _saveGameHook(self, p): p.dump(self.base_card.id) # # game extras # def updateText(self): if self.preview > 1 or not self.texts.info: return if not self.base_card: t = "" else: t = self.RANKS[self.base_card.rank] dir = self.getFoundationDir() % 12 if dir == 1: t = t + _(" Ascending") elif dir == 11: t = t + _(" Descending") self.texts.info.config(text=t) # ************************************************************************ # * Akbar's Conquest # ************************************************************************ class AkbarsConquest(AkbarsTriumph): BRAID_CARDS = 16 BRAID_OFFSET = .9 # ************************************************************************ # * # ************************************************************************ class Vajra(AbstractMughalGame): RowStack_Class = StackWrapper(Mughal_RK_RowStack, base_rank=NO_RANK) # # game layout # def createGame(self, rows=9, reserves=8): # create layout l, s = Layout(self), self.s # set size maxrows = max(rows, reserves) self.setSize(l.XM + (maxrows + 2) * l.XS, l.YM + 6 * l.YS) # playcards = 4 * l.YS // l.YOFFSET xoffset, yoffset = [], [] for i in range(playcards): xoffset.append(0) yoffset.append(l.YOFFSET) for i in range(96 * self.gameinfo.decks - playcards): xoffset.append(l.XOFFSET) yoffset.append(0) # create stacks x, y = l.XM + (maxrows - reserves) * l.XS // 2, l.YM for i in range(reserves): s.reserves.append(ReserveStack(x, y, self)) x = x + l.XS x, y = l.XM + (maxrows - rows) * l.XS // 2, l.YM + l.YS self.setRegion(s.reserves, (-999, -999, 999999, y - l.YM // 2)) for i in range(rows): stack = self.RowStack_Class(x, y, self, yoffset=l.YOFFSET) stack.CARD_XOFFSET = xoffset stack.CARD_YOFFSET = yoffset s.rows.append(stack) x = x + l.XS x, y = l.XM + maxrows * l.XS, l.YM for i in range(2): for suit in range(4): s.foundations.append( SS_FoundationStack(x, y, self, suit=suit+(4 * i))) y = y + l.YS x, y = x + l.XS, l.YM self.setRegion(self.s.foundations, (x - l.XS * 2, -999, 999999, self.height - (l.YS + l.YM)), priority=1) s.talon = InitialDealTalonStack( self.width - 3 * l.XS // 2, self.height - l.YS, self) # define stack-groups l.defaultStackGroups() # # game overrides # def startGame(self): self.startDealSample() i = 0 while self.s.talon.cards: if self.s.talon.cards[-1].rank == 11: if self.s.rows[i].cards: i = i + 1 self.s.talon.dealRow(rows=[self.s.rows[i]], frames=4) # must look at cards def _getClosestStack(self, cx, cy, stacks, dragstack): closest, cdist = None, 999999999 for stack in stacks: if stack.cards and stack is not dragstack: dist = (stack.cards[-1].x - cx)**2 + \ (stack.cards[-1].y - cy)**2 else: dist = (stack.x - cx)**2 + (stack.y - cy)**2 if dist < cdist: closest, cdist = stack, dist return closest def shallHighlightMatch(self, stack1, card1, stack2, card2): row = self.s.rows[0] sequence = row.isRankSequence return (sequence([card1, card2]) or sequence([card2, card1])) # ************************************************************************ # * # ************************************************************************ class Danda(Vajra): RowStack_Class = StackWrapper(Mughal_AF_RowStack, base_rank=NO_RANK) def shallHighlightMatch(self, stack1, card1, stack2, card2): row = self.s.rows[0] sequence = row.isAlternateForceSequence return (sequence([card1, card2]) or sequence([card2, card1])) # ************************************************************************ # * # ************************************************************************ class Khadga(Vajra): RowStack_Class = StackWrapper(Mughal_AC_RowStack, base_rank=NO_RANK) def shallHighlightMatch(self, stack1, card1, stack2, card2): row = self.s.rows[0] sequence = row.isAlternateColorSequence return (sequence([card1, card2]) or sequence([card2, card1])) # ************************************************************************ # * # ************************************************************************ class Makara(Vajra): RowStack_Class = StackWrapper(Mughal_SS_RowStack, base_rank=NO_RANK) def shallHighlightMatch(self, stack1, card1, stack2, card2): row = self.s.rows[0] sequence = row.isSuitSequence return (sequence([card1, card2]) or sequence([card2, card1])) # ************************************************************************ # * Ashta Dikapala Game Stacks # ************************************************************************ class Dikapala_TableauStack(Mughal_OpenStack): def __init__(self, x, y, game, base_rank, yoffset, **cap): kwdefault(cap, dir=3, max_move=99, max_cards=4, max_accept=1, base_rank=base_rank) OpenStack.__init__(self, x, y, game, **cap) self.CARD_YOFFSET = yoffset def acceptsCards(self, from_stack, cards): if not self.basicAcceptsCards(from_stack, cards): return 0 # check that the base card is correct if self.cards and self.cards[0].rank != self.cap.base_rank: return 0 if not self.cards: return cards[0].rank == self.cap.base_rank return (self.cards[-1].suit == cards[0].suit and self.cards[-1].rank + self.cap.dir == cards[0].rank) def getBottomImage(self): return self.game.app.images.getLetter(self.cap.base_rank) class Dikapala_ReserveStack(ReserveStack): def __init__(self, x, y, game, **cap): kwdefault(cap, max_cards=1, max_accept=1, base_rank=ANY_RANK) OpenStack.__init__(self, x, y, game, **cap) def acceptsCards(self, from_stack, cards): return (ReserveStack.acceptsCards(self, from_stack, cards) and self.game.s.talon.cards) class Dikapala_RowStack(BasicRowStack): def acceptsCards(self, from_stack, cards): if not BasicRowStack.acceptsCards(self, from_stack, cards): return 0 # check return not (self.cards or self.game.s.talon.cards) def canMoveCards(self, cards): return 1 def getBottomImage(self): return self.game.app.images.getTalonBottom() # ************************************************************************ # * Dikapala Hint # ************************************************************************ class Dikapala_Hint(AbstractHint): def computeHints(self): game = self.game # 2)See if we can move a card to the tableaux if not self.hints: for r in game.sg.dropstacks: pile = r.getPile() if not pile or len(pile) != 1: continue if r in game.s.tableaux: rr = self.ClonedStack(r, stackcards=r.cards[:-1]) if rr.acceptsCards(None, pile): # do not move a card that is already in correct place continue base_score = 80000 + (4 - r.cap.base_suit) else: base_score = 80000 # find a stack that would accept this card for t in game.s.tableaux: if t is not r and t.acceptsCards(r, pile): score = base_score + 100 * (self.K - pile[0].rank) self.addHint(score, 1, r, t) break # 3)See if we can move a card from the tableaux # to a row stack. This can only happen if there are # no more cards to deal. if not self.hints: for r in game.s.tableaux: pile = r.getPile() if not pile or len(pile) != 1: continue rr = self.ClonedStack(r, stackcards=r.cards[:-1]) if rr.acceptsCards(None, pile): # do not move a card that is already in correct place continue # find a stack that would accept this card for t in game.s.rows: if t is not r and t.acceptsCards(r, pile): score = 70000 + 100 * (self.K - pile[0].rank) self.addHint(score, 1, r, t) break # 4)See if we can move a card within the row stacks if not self.hints: for r in game.s.rows: pile = r.getPile() if not pile or len(pile) != 1 or len(pile) == len(r.cards): continue base_score = 60000 # find a stack that would accept this card for t in game.s.rows: if t is not r and t.acceptsCards(r, pile): score = base_score + 100 * (self.K - pile[0].rank) self.addHint(score, 1, r, t) break # 5)See if we can deal cards if self.level >= 2: if game.canDealCards(): self.addHint(self.SCORE_DEAL, 0, game.s.talon, None) # ************************************************************************ # * Ashta Dikapala # ************************************************************************ class AshtaDikapala(Game): Hint_Class = Dikapala_Hint # # game layout # def createGame(self): # create layout l, s = Layout(self), self.s TABLEAU_YOFFSET = min(9, max(3, l.YOFFSET // 3)) # set window th = l.YS + 3 * TABLEAU_YOFFSET # (set piles so that at least 2/3 of a card is visible with 10 cards) h = 8 * l.YOFFSET + l.CH * 2//3 self.setSize(9 * l.XS + l.XM * 2, l.YM + 3 * th + l.YM + h) # create stacks s.addattr(tableaux=[]) # register extra stack variable x = l.XM + 8 * l.XS + l.XS // 2 y = l.YM for i in range(3, 0, -1): x = l.XM for j in range(8): s.tableaux.append( Dikapala_TableauStack( x, y, self, i - 1, TABLEAU_YOFFSET)) x = x + l.XS x = x + l.XM s.reserves.append(Dikapala_ReserveStack(x, y, self)) y = y + th x, y = l.XM, y + l.YM for i in range(8): s.rows.append(Dikapala_RowStack(x, y, self, max_accept=1)) x = x + l.XS x = self.width - l.XS y = self.height - l.YS s.talon = DealRowTalonStack(x, y, self) l.createText(s.talon, "sw") # define stack-groups self.sg.openstacks = s.tableaux + s.rows + s.reserves self.sg.talonstacks = [s.talon] self.sg.dropstacks = s.tableaux + s.rows # # game overrides # def startGame(self): self.s.talon.dealRow(rows=self.s.tableaux, frames=0) self._startAndDealRow() def isGameWon(self): for stack in self.s.tableaux: if len(stack.cards) != 4: return 0 return 1 def fillStack(self, stack): if self.s.talon.cards: if stack in self.s.rows and len(stack.cards) == 0: self.s.talon.dealRow(rows=[stack]) def shallHighlightMatch(self, stack1, card1, stack2, card2): return (card1.suit == card2.suit and (card1.rank + 3 == card2.rank or card2.rank + 3 == card1.rank)) def getHighlightPilesStacks(self): return () # ************************************************************************ # * # ************************************************************************ def r(id, gameclass, name, game_type, decks, redeals, skill_level): game_type = game_type | GI.GT_MUGHAL_GANJIFA gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level, suits=list(range(8)), ranks=list(range(12))) registerGame(gi) return gi r(14401, MughalCircles, 'Mughal Circles', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(14402, Ghulam, 'Ghulam', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(14403, Shamsher, 'Shamsher', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(14404, EightLegions, 'Eight Legions', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(14405, Ashrafi, 'Ashrafi', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(14406, Tipati, 'Tipati', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_BALANCED) r(14407, Ashwapati, 'Ashwapati', GI.GT_MUGHAL_GANJIFA, 1, -1, GI.SL_BALANCED) r(14408, Gajapati, 'Gajapati', GI.GT_MUGHAL_GANJIFA, 1, -1, GI.SL_BALANCED) r(14409, Narpati, 'Narpati', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_BALANCED) r(14410, Garhpati, 'Garhpati', GI.GT_MUGHAL_GANJIFA, 1, -1, GI.SL_BALANCED) r(14411, Dhanpati, 'Dhanpati', GI.GT_MUGHAL_GANJIFA, 1, 1, GI.SL_BALANCED) r(14412, AkbarsTriumph, 'Akbar\'s Triumph', GI.GT_MUGHAL_GANJIFA, 1, 2, GI.SL_BALANCED) r(14413, AkbarsConquest, 'Akbar\'s Conquest', GI.GT_MUGHAL_GANJIFA, 2, 2, GI.SL_BALANCED) r(16000, Vajra, 'Vajra', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(16001, Danda, 'Danda', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(16002, Khadga, 'Khadga', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(16003, Makara, 'Makara', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL) r(16004, AshtaDikapala, 'Ashta Dikapala', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_BALANCED) del r