1#!/usr/bin/env python 2# -*- mode: python; coding: utf-8; -*- 3# ---------------------------------------------------------------------------## 4# 5# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer 6# Copyright (C) 2003 Mt. Hood Playing Card Co. 7# Copyright (C) 2005-2009 Skomoroh 8# 9# This program is free software: you can redistribute it and/or modify 10# it under the terms of the GNU General Public License as published by 11# the Free Software Foundation, either version 3 of the License, or 12# (at your option) any later version. 13# 14# This program is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with this program. If not, see <http://www.gnu.org/licenses/>. 21# 22# ---------------------------------------------------------------------------## 23 24from pysollib.game import Game 25from pysollib.gamedb import GI, GameInfo, registerGame 26from pysollib.layout import Layout 27from pysollib.mygettext import _ 28from pysollib.pysoltk import MfxCanvasText 29from pysollib.stack import \ 30 InitialDealTalonStack, \ 31 InvisibleStack, \ 32 OpenStack 33 34# ************************************************************************ 35# * 36# ************************************************************************ 37 38 39class Memory_RowStack(OpenStack): 40 def clickHandler(self, event): 41 game = self.game 42 if len(self.cards) != 1 or self.cards[-1].face_up: 43 return 1 44 if game.other_stack is None: 45 game.playSample("flip", priority=5) 46 self.flipMove() 47 game.other_stack = self 48 else: 49 assert len(game.other_stack.cards) == 1 and \ 50 game.other_stack.cards[-1].face_up 51 c1, c2 = self.cards[-1], game.other_stack.cards[0] 52 self.flipMove() 53 if self.game.cardsMatch(c1, c2): 54 self._dropPairMove(1, game.other_stack) 55 else: 56 game.playSample("flip", priority=5) 57 game.score = game.score - 1 58 game.updateStatus(moves=game.moves.index+1) # update moves now 59 game.updateText() 60 game.canvas.update_idletasks() 61 game.sleep(0.5) 62 game.other_stack.flipMove() 63 game.canvas.update_idletasks() 64 game.sleep(0.2) 65 self.flipMove() 66 game.other_stack = None 67 self.game.finishMove() 68 self.game.checkForWin() 69 return 1 70 71 def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1): 72 game = self.game 73 game.playSample("droppair", priority=200) 74 game.closed_cards = game.closed_cards - 2 75 game.score = game.score + 5 76 77 rightclickHandler = clickHandler 78 doubleclickHandler = clickHandler 79 80 def controlclickHandler(self, event): 81 return 0 82 83 def shiftclickHandler(self, event): 84 return 0 85 86 87# ************************************************************************ 88# * Memory 89# ************************************************************************ 90 91class Memory24(Game): 92 Hint_Class = None 93 94 COLUMNS = 6 95 ROWS = 4 96 WIN_SCORE = 40 97 PERFECT_SCORE = 60 # 5 * (6*4)/2 98 99 # 100 # game layout 101 # 102 103 def createGame(self): 104 # create layout 105 l, s = Layout(self), self.s 106 107 # game extras 108 self.other_stack = None 109 self.closed_cards = -1 110 self.score = 0 111 112 # create text 113 x, y = l.XM, self.ROWS*l.YS 114 if self.preview <= 1: 115 self.texts.score = MfxCanvasText( 116 self.canvas, x, y, anchor="sw", 117 font=self.app.getFont("canvas_large")) 118 x = self.texts.score.bbox()[1][0] + 16 119 120 # set window 121 w = max(2*l.XS, x) 122 self.setSize(l.XM + w + self.COLUMNS*l.XS, l.YM + self.ROWS*l.YS) 123 124 # create stacks 125 for i in range(self.ROWS): 126 for j in range(self.COLUMNS): 127 x, y = l.XM + w + j*l.XS, l.YM + i*l.YS 128 s.rows.append(Memory_RowStack(x, y, self, 129 max_move=0, max_accept=0, max_cards=1)) 130 x, y = l.XM, l.YM 131 s.talon = InitialDealTalonStack(x, y, self) 132 l.createText(s.talon, anchor="n", text_format="%D") 133 s.internals.append(InvisibleStack(self)) 134 135 # define stack-groups 136 l.defaultStackGroups() 137 138 # 139 # game overrides 140 # 141 142 def startGame(self): 143 n = self.COLUMNS * self.ROWS 144 assert len(self.s.talon.cards) == n 145 self.other_stack = None 146 self.closed_cards = n 147 self.score = 0 148 self.updateText() 149 n = n - self.COLUMNS 150 self.s.talon.dealRow(rows=self.s.rows[:n], flip=0, frames=0) 151 self.startDealSample() 152 self.s.talon.dealRow(rows=self.s.rows[n:], flip=0) 153 assert len(self.s.talon.cards) == 0 154 155 def isGameWon(self): 156 return self.closed_cards == 0 and self.score >= self.WIN_SCORE 157 158 def getAutoStacks(self, event=None): 159 return ((), (), ()) 160 161 # 162 # scoring 163 # 164 165 def updateText(self): 166 if self.preview > 1 or not self.texts.score: 167 return 168 t = "" 169 if self.closed_cards: 170 t = _("Points: %d") % self.score 171 else: 172 if self.score >= self.WIN_SCORE: 173 t = _("WON\n\n") 174 t = t + _("Total: %d") % self.score 175 self.texts.score.config(text=t) 176 177 def getGameScore(self): 178 return self.score 179 180 # Memory special: check score for a perfect game 181 def getWinStatus(self): 182 won, status, updated = Game.getWinStatus(self) 183 if status == 2 and self.score < self.PERFECT_SCORE: 184 return won, 1, self.U_WON 185 return won, status, updated 186 187 # 188 # game extras 189 # 190 191 def cardsMatch(self, card1, card2): 192 return card1.suit == card2.suit and card1.rank == card2.rank 193 194 def canSaveGame(self): 195 return 0 196 197 def canUndo(self): 198 return 0 199 200 def _restoreGameHook(self, game): 201 if game.loadinfo.other_stack_id >= 0: 202 self.other_stack = self.allstacks[game.loadinfo.other_stack_id] 203 else: 204 self.other_stack = None 205 self.closed_cards = game.loadinfo.closed_cards 206 self.score = game.loadinfo.score 207 208 def _loadGameHook(self, p): 209 self.loadinfo.addattr(other_stack_id=p.load()) 210 self.loadinfo.addattr(closed_cards=p.load()) 211 self.loadinfo.addattr(score=p.load()) 212 213 def _saveGameHook(self, p): 214 if self.other_stack: 215 p.dump(self.other_stack.id) 216 else: 217 p.dump(-1) 218 p.dump(self.closed_cards) 219 p.dump(self.score) 220 221 222class Memory30(Memory24): 223 COLUMNS = 6 224 ROWS = 5 225 WIN_SCORE = 45 226 PERFECT_SCORE = 75 # 5 * (6*5)/2 227 228 229class Memory40(Memory24): 230 COLUMNS = 8 231 ROWS = 5 232 WIN_SCORE = 50 233 PERFECT_SCORE = 100 # 5 * (8*5)/2 234 235 236# ************************************************************************ 237# * Concentration 238# ************************************************************************ 239 240class Concentration_RowStack(Memory_RowStack): 241 def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1): 242 game = self.game 243 game.playSample("droppair", priority=200) 244 game.closed_cards = game.closed_cards - 2 245 game.score = game.score + 5 246 # 247 old_state = game.enterState(game.S_FILL) 248 f = game.s.talon 249 game.moveMove(n, self, f, frames=frames, shadow=shadow) 250 game.moveMove(n, other_stack, f, frames=frames, shadow=shadow) 251 game.leaveState(old_state) 252 253 254class Concentration(Memory24): 255 COLUMNS = 13 256 ROWS = 4 257 WIN_SCORE = 50 258 PERFECT_SCORE = 130 # 5 * (13*4)/2 259 260 # 261 # game layout 262 # 263 264 def createGame(self): 265 # create layout 266 l, s = Layout(self, card_x_space=4), self.s 267 268 # game extras 269 self.other_stack = None 270 self.closed_cards = -1 271 self.score = 0 272 273 # set window 274 self.setSize(l.XM + self.COLUMNS*l.XS, l.YM + (self.ROWS+1)*l.YS) 275 276 # create stacks 277 for i in range(self.ROWS): 278 for j in range(self.COLUMNS): 279 x, y = l.XM + j*l.XS, l.YM + i*l.YS 280 s.rows.append(Concentration_RowStack(x, y, self, 281 max_move=0, max_accept=0, max_cards=1)) 282 x, y = l.XM + self.COLUMNS*l.XS//2, self.height - l.YS 283 s.talon = InitialDealTalonStack(x, y, self) 284 l.createText(s.talon, dx=-10, anchor="sw", text_format="%D") 285 286 # create text 287 x, y = l.XM, self.height - l.YM 288 if self.preview <= 1: 289 self.texts.score = MfxCanvasText( 290 self.canvas, x, y, 291 anchor="sw", 292 font=self.app.getFont("canvas_large")) 293 294 # define stack-groups 295 l.defaultStackGroups() 296 297 # 298 # game extras 299 # 300 301 def cardsMatch(self, card1, card2): 302 return card1.rank == card2.rank 303 304 305# register the game 306registerGame(GameInfo(176, Memory24, "Memory 24", 307 GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL, 308 suits=(0, 2), ranks=(0, 8, 9, 10, 11, 12))) 309registerGame(GameInfo(219, Memory30, "Memory 30", 310 GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL, 311 suits=(0, 2, 3), ranks=(0, 9, 10, 11, 12))) 312registerGame(GameInfo(177, Memory40, "Memory 40", 313 GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL, 314 suits=(0, 2), ranks=(0, 4, 5, 6, 7, 8, 9, 10, 11, 12))) 315registerGame(GameInfo(178, Concentration, "Concentration", 316 GI.GT_MEMORY | GI.GT_SCORE, 1, 0, GI.SL_SKILL)) 317