mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
+ 3 new games
* little reorganisation: move all french games to pysollib/games + new command-line option: `--french-only' (undocumented) * misc. improvements git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@41 39dd0a4e-7c14-0410-91b3-c4f2d318f732
This commit is contained in:
parent
91fae82cdd
commit
a19c507d5e
28 changed files with 858 additions and 816 deletions
|
@ -195,7 +195,7 @@ class PysolMenubarActions:
|
||||||
tkopt.negative_bottom.set(opt.negative_bottom)
|
tkopt.negative_bottom.set(opt.negative_bottom)
|
||||||
for w in TOOLBAR_BUTTONS:
|
for w in TOOLBAR_BUTTONS:
|
||||||
tkopt.toolbar_vars[w].set(opt.toolbar_vars[w])
|
tkopt.toolbar_vars[w].set(opt.toolbar_vars[w])
|
||||||
if game.gameinfo.category == GI.GC_FRENCH:
|
if game.canFindCard():
|
||||||
connect_game_find_card_dialog(game)
|
connect_game_find_card_dialog(game)
|
||||||
else:
|
else:
|
||||||
destroy_find_card_dialog()
|
destroy_find_card_dialog()
|
||||||
|
@ -282,7 +282,7 @@ class PysolMenubarActions:
|
||||||
ms.quickplay = 1
|
ms.quickplay = 1
|
||||||
if opt.highlight_piles and game.getHighlightPilesStacks():
|
if opt.highlight_piles and game.getHighlightPilesStacks():
|
||||||
ms.highlight_piles = 1
|
ms.highlight_piles = 1
|
||||||
if game.gameinfo.category == GI.GC_FRENCH:
|
if game.canFindCard():
|
||||||
ms.find_card = 1
|
ms.find_card = 1
|
||||||
if game.app.getGameRulesFilename(game.id): # note: this may return ""
|
if game.app.getGameRulesFilename(game.id): # note: this may return ""
|
||||||
ms.rules = 1
|
ms.rules = 1
|
||||||
|
|
|
@ -1380,7 +1380,7 @@ Please select a %s type %s.
|
||||||
return None
|
return None
|
||||||
config = CardsetConfig()
|
config = CardsetConfig()
|
||||||
if not self._parseCardsetConfig(config, lines):
|
if not self._parseCardsetConfig(config, lines):
|
||||||
##print filename, 'invalide config'
|
##print filename, 'invalid config'
|
||||||
return None
|
return None
|
||||||
if config.CARDD > self.top.winfo_screendepth():
|
if config.CARDD > self.top.winfo_screendepth():
|
||||||
return None
|
return None
|
||||||
|
@ -1444,7 +1444,7 @@ Please select a %s type %s.
|
||||||
return 0
|
return 0
|
||||||
cs.year = int(m.group(1))
|
cs.year = int(m.group(1))
|
||||||
if len(cs.ext) < 2 or cs.ext[0] != ".":
|
if len(cs.ext) < 2 or cs.ext[0] != ".":
|
||||||
if _debug: print_err(1, msg='invalide extention')
|
if _debug: print_err(1, msg='invalid extention')
|
||||||
return 0
|
return 0
|
||||||
# line[1]: identifier/name
|
# line[1]: identifier/name
|
||||||
if not line[1]:
|
if not line[1]:
|
||||||
|
@ -1453,19 +1453,19 @@ Please select a %s type %s.
|
||||||
cs.ident = line[1]
|
cs.ident = line[1]
|
||||||
m = re.search(r"^(.*;)?([^;]+)$", cs.ident)
|
m = re.search(r"^(.*;)?([^;]+)$", cs.ident)
|
||||||
if not m:
|
if not m:
|
||||||
if _debug: print_err(2, msg='invalide format')
|
if _debug: print_err(2, msg='invalid format')
|
||||||
return 0
|
return 0
|
||||||
cs.name = m.group(2).strip()
|
cs.name = m.group(2).strip()
|
||||||
# line[2]: CARDW, CARDH, CARDD
|
# line[2]: CARDW, CARDH, CARDD
|
||||||
m = re.search(r"^(\d+)\s+(\d+)\s+(\d+)", line[2])
|
m = re.search(r"^(\d+)\s+(\d+)\s+(\d+)", line[2])
|
||||||
if not m:
|
if not m:
|
||||||
if _debug: print_err(3, msg='invalide format')
|
if _debug: print_err(3, msg='invalid format')
|
||||||
return 0
|
return 0
|
||||||
cs.CARDW, cs.CARDH, cs.CARDD = int(m.group(1)), int(m.group(2)), int(m.group(3))
|
cs.CARDW, cs.CARDH, cs.CARDD = int(m.group(1)), int(m.group(2)), int(m.group(3))
|
||||||
# line[3]: CARD_UP_YOFFSET, CARD_DOWN_YOFFSET, SHADOW_XOFFSET, SHADOW_YOFFSET
|
# line[3]: CARD_UP_YOFFSET, CARD_DOWN_YOFFSET, SHADOW_XOFFSET, SHADOW_YOFFSET
|
||||||
m = re.search(r"^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", line[3])
|
m = re.search(r"^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", line[3])
|
||||||
if not m:
|
if not m:
|
||||||
if _debug: print_err(4, msg='invalide format')
|
if _debug: print_err(4, msg='invalid format')
|
||||||
return 0
|
return 0
|
||||||
cs.CARD_XOFFSET = int(m.group(1))
|
cs.CARD_XOFFSET = int(m.group(1))
|
||||||
cs.CARD_YOFFSET = int(m.group(2))
|
cs.CARD_YOFFSET = int(m.group(2))
|
||||||
|
|
|
@ -1590,7 +1590,7 @@ for %d moves.
|
||||||
return card1.color != card2.color and abs(card1.rank-card2.rank) == 1
|
return card1.color != card2.color and abs(card1.rank-card2.rank) == 1
|
||||||
|
|
||||||
def _shallHighlightMatch_ACW(self, stack1, card1, stack2, card2):
|
def _shallHighlightMatch_ACW(self, stack1, card1, stack2, card2):
|
||||||
# by alternate color with wrapping (only for france games)
|
# by alternate color with wrapping (only for french games)
|
||||||
return (card1.color != card2.color
|
return (card1.color != card2.color
|
||||||
and ((card1.rank + 1) % 13 == card2.rank
|
and ((card1.rank + 1) % 13 == card2.rank
|
||||||
or (card2.rank + 1) % 13 == card1.rank))
|
or (card2.rank + 1) % 13 == card1.rank))
|
||||||
|
@ -1600,7 +1600,7 @@ for %d moves.
|
||||||
return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1
|
return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1
|
||||||
|
|
||||||
def _shallHighlightMatch_SSW(self, stack1, card1, stack2, card2):
|
def _shallHighlightMatch_SSW(self, stack1, card1, stack2, card2):
|
||||||
# by same suit with wrapping (only for france games)
|
# by same suit with wrapping (only for french games)
|
||||||
return (card1.suit == card2.suit
|
return (card1.suit == card2.suit
|
||||||
and ((card1.rank + 1) % 13 == card2.rank
|
and ((card1.rank + 1) % 13 == card2.rank
|
||||||
or (card2.rank + 1) % 13 == card1.rank))
|
or (card2.rank + 1) % 13 == card1.rank))
|
||||||
|
@ -1610,7 +1610,7 @@ for %d moves.
|
||||||
return abs(card1.rank-card2.rank) == 1
|
return abs(card1.rank-card2.rank) == 1
|
||||||
|
|
||||||
def _shallHighlightMatch_RKW(self, stack1, card1, stack2, card2):
|
def _shallHighlightMatch_RKW(self, stack1, card1, stack2, card2):
|
||||||
# by rank with wrapping (only for france games)
|
# by rank with wrapping (only for french games)
|
||||||
return ((card1.rank + 1) % 13 == card2.rank
|
return ((card1.rank + 1) % 13 == card2.rank
|
||||||
or (card2.rank + 1) % 13 == card1.rank)
|
or (card2.rank + 1) % 13 == card1.rank)
|
||||||
|
|
||||||
|
@ -2640,6 +2640,10 @@ in the current implementation.''' % version
|
||||||
sd.delete()
|
sd.delete()
|
||||||
self.stackdesc_list = []
|
self.stackdesc_list = []
|
||||||
|
|
||||||
|
## for find_card_dialog
|
||||||
|
def canFindCard(self):
|
||||||
|
return self.gameinfo.category == GI.GC_FRENCH
|
||||||
|
|
||||||
#
|
#
|
||||||
# subclass hooks
|
# subclass hooks
|
||||||
#
|
#
|
||||||
|
|
|
@ -490,16 +490,22 @@ class GameManager:
|
||||||
raise GameInfoException, "wrong GameInfo class"
|
raise GameInfoException, "wrong GameInfo class"
|
||||||
gi.plugin = self.loading_plugin
|
gi.plugin = self.loading_plugin
|
||||||
if self.__all_games.has_key(gi.id):
|
if self.__all_games.has_key(gi.id):
|
||||||
raise GameInfoException, "duplicate game ID " + str(gi.id)
|
raise GameInfoException, "duplicate game ID %s: %s and %s" % \
|
||||||
|
(gi.id, str(gi.gameclass),
|
||||||
|
str(self.__all_games[gi.id].gameclass))
|
||||||
if self.__all_gamenames.has_key(gi.name):
|
if self.__all_gamenames.has_key(gi.name):
|
||||||
raise GameInfoException, "duplicate game name " + str(gi.id) + ": " + gi.name
|
raise GameInfoException, "duplicate game name %s: %s and %s" % \
|
||||||
|
(gi.id, gi.name, str(self.__all_games[gi.id].gameclass))
|
||||||
if 1:
|
if 1:
|
||||||
for id, game in self.__all_games.items():
|
for id, game in self.__all_games.items():
|
||||||
if gi.gameclass is game.gameclass:
|
if gi.gameclass is game.gameclass:
|
||||||
raise GameInfoException, "duplicate game class " + str(gi.id)
|
raise GameInfoException, \
|
||||||
|
"duplicate game class %s: %s and %s" % \
|
||||||
|
(gi.id, str(gi.gameclass), str(game.gameclass))
|
||||||
for n in gi.altnames:
|
for n in gi.altnames:
|
||||||
if self.__all_gamenames.has_key(n):
|
if self.__all_gamenames.has_key(n):
|
||||||
raise GameInfoException, "duplicate altgame name " + str(gi.id) + ": " + n
|
raise GameInfoException, "duplicate game altname %s: %s" % \
|
||||||
|
(gi.id, n)
|
||||||
##if 0 and gi.si.game_flags & GI.GT_XORIGINAL:
|
##if 0 and gi.si.game_flags & GI.GT_XORIGINAL:
|
||||||
## return
|
## return
|
||||||
##print gi.id, gi.name
|
##print gi.id, gi.name
|
||||||
|
|
|
@ -30,6 +30,7 @@ import headsandtails
|
||||||
import katzenschwanz
|
import katzenschwanz
|
||||||
import klondike
|
import klondike
|
||||||
import labyrinth
|
import labyrinth
|
||||||
|
import larasgame
|
||||||
import matriarchy
|
import matriarchy
|
||||||
import montana
|
import montana
|
||||||
import montecarlo
|
import montecarlo
|
||||||
|
@ -46,6 +47,7 @@ import pushpin
|
||||||
import pyramid
|
import pyramid
|
||||||
import royalcotillion
|
import royalcotillion
|
||||||
import royaleast
|
import royaleast
|
||||||
|
import sanibel
|
||||||
import siebenbisas
|
import siebenbisas
|
||||||
import simplex
|
import simplex
|
||||||
import spider
|
import spider
|
||||||
|
@ -53,6 +55,7 @@ import sthelena
|
||||||
import sultan
|
import sultan
|
||||||
import takeaway
|
import takeaway
|
||||||
import terrace
|
import terrace
|
||||||
|
import threepeaks
|
||||||
import tournament
|
import tournament
|
||||||
import unionsquare
|
import unionsquare
|
||||||
import wavemotion
|
import wavemotion
|
||||||
|
|
|
@ -128,7 +128,7 @@ class Strata(Game):
|
||||||
s.foundations.append(DieRussische_Foundation(x, y, self,
|
s.foundations.append(DieRussische_Foundation(x, y, self,
|
||||||
suit=i%4, max_cards=8))
|
suit=i%4, max_cards=8))
|
||||||
x = x + l.XS
|
x = x + l.XS
|
||||||
x, y, = l.XM+l.XS, l.YM+l.YS
|
x, y, = l.XM+l.XS/2, l.YM+l.YS
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
s.rows.append(AC_RowStack(x, y, self, max_move=1, max_accept=1))
|
s.rows.append(AC_RowStack(x, y, self, max_move=1, max_accept=1))
|
||||||
x = x + l.XS
|
x = x + l.XS
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
import sanibel
|
|
|
@ -277,118 +277,6 @@ class Escalator(Elevator):
|
||||||
self.s.talon.dealRow()
|
self.s.talon.dealRow()
|
||||||
self.s.talon.dealCards() # deal first card to WasteStack
|
self.s.talon.dealCards() # deal first card to WasteStack
|
||||||
|
|
||||||
# /***********************************************************************
|
|
||||||
# // Tri Peaks - Relaxed Golf in a Pyramid layout
|
|
||||||
# ************************************************************************/
|
|
||||||
|
|
||||||
class TriPeaks_RowStack(Elevator_RowStack):
|
|
||||||
STEP = (1, 2, 2, 3+12, 3+12, 3+12,
|
|
||||||
1, 2, 2, 3+ 9, 3+ 9, 3+ 9,
|
|
||||||
1, 2, 2, 3+ 6, 3+ 6, 3+ 6)
|
|
||||||
|
|
||||||
|
|
||||||
class TriPeaks(RelaxedGolf):
|
|
||||||
|
|
||||||
#
|
|
||||||
# game layout
|
|
||||||
#
|
|
||||||
|
|
||||||
def createGame(self):
|
|
||||||
# create layout
|
|
||||||
l, s = Layout(self), self.s
|
|
||||||
|
|
||||||
# set window
|
|
||||||
l.XOFFSET = int(l.XS * 9 / self.gameinfo.ncards)
|
|
||||||
self.setSize(10*l.XS+l.XM, 4*l.YS+l.YM)
|
|
||||||
|
|
||||||
# extra settings
|
|
||||||
self.talon_card_ids = {}
|
|
||||||
|
|
||||||
# create stacks
|
|
||||||
for i in range(3):
|
|
||||||
for d in ((2, 0), (1, 1), (3, 1), (0, 2), (2, 2), (4, 2)):
|
|
||||||
x = l.XM + (6*i+1+d[0]) * l.XS / 2
|
|
||||||
y = l.YM + d[1] * l.YS / 2
|
|
||||||
s.rows.append(TriPeaks_RowStack(x, y, self))
|
|
||||||
x, y = l.XM, 3*l.YS/2
|
|
||||||
for i in range(10):
|
|
||||||
s.rows.append(Golf_RowStack(x, y, self))
|
|
||||||
x = x + l.XS
|
|
||||||
x, y = l.XM, self.height - l.YS
|
|
||||||
s.talon = Golf_Talon(x, y, self, max_rounds=1)
|
|
||||||
l.createText(s.talon, "nn")
|
|
||||||
x = x + l.XS
|
|
||||||
s.waste = self.Waste_Class(x, y, self)
|
|
||||||
s.waste.CARD_XOFFSET = l.XOFFSET
|
|
||||||
l.createText(s.waste, "nn")
|
|
||||||
# the Waste is also our only Foundation in this game
|
|
||||||
s.foundations.append(s.waste)
|
|
||||||
|
|
||||||
self.texts.score = MfxCanvasText(self.canvas,
|
|
||||||
self.width - 8, self.height - 8,
|
|
||||||
anchor="se",
|
|
||||||
font=self.app.getFont("canvas_large"))
|
|
||||||
|
|
||||||
# define stack-groups (non default)
|
|
||||||
self.sg.openstacks = [s.waste]
|
|
||||||
self.sg.talonstacks = [s.talon]
|
|
||||||
self.sg.dropstacks = s.rows
|
|
||||||
|
|
||||||
#
|
|
||||||
# game overrides
|
|
||||||
#
|
|
||||||
|
|
||||||
def startGame(self):
|
|
||||||
self.startDealSample()
|
|
||||||
self.s.talon.dealRow(rows=self.s.rows[:18], flip=0)
|
|
||||||
self.s.talon.dealRow(rows=self.s.rows[18:])
|
|
||||||
# extra settings: remember cards from the talon
|
|
||||||
self.talon_card_ids = {}
|
|
||||||
for c in self.s.talon.cards:
|
|
||||||
self.talon_card_ids[c.id] = 1
|
|
||||||
self.s.talon.dealCards() # deal first card to WasteStack
|
|
||||||
|
|
||||||
def getGameScore(self):
|
|
||||||
v = -24 * 5
|
|
||||||
if not self.s.waste.cards:
|
|
||||||
return v
|
|
||||||
# compute streaks for cards on the waste
|
|
||||||
streak = 0
|
|
||||||
for c in self.s.waste.cards:
|
|
||||||
if self.talon_card_ids.get(c.id):
|
|
||||||
streak = 0
|
|
||||||
else:
|
|
||||||
streak = streak + 1
|
|
||||||
v = v + streak
|
|
||||||
# each cleared peak gains $15 bonus, and all 3 gain extra $30
|
|
||||||
extra = 30
|
|
||||||
for i in (0, 6, 12):
|
|
||||||
if not self.s.rows[i].cards:
|
|
||||||
v = v + 15
|
|
||||||
else:
|
|
||||||
extra = 0
|
|
||||||
return v + extra
|
|
||||||
|
|
||||||
getGameBalance = getGameScore
|
|
||||||
|
|
||||||
def updateText(self):
|
|
||||||
if self.preview > 1:
|
|
||||||
return
|
|
||||||
b1, b2 = self.app.stats.gameid_balance, 0
|
|
||||||
if self.shallUpdateBalance():
|
|
||||||
b2 = self.getGameBalance()
|
|
||||||
t = _("Balance $%4d") % (b1 + b2)
|
|
||||||
self.texts.score.config(text=t)
|
|
||||||
|
|
||||||
def _restoreGameHook(self, game):
|
|
||||||
self.talon_card_ids = game.loadinfo.talon_card_ids
|
|
||||||
|
|
||||||
def _loadGameHook(self, p):
|
|
||||||
self.loadinfo.addattr(talon_card_ids=p.load(types.DictType))
|
|
||||||
|
|
||||||
def _saveGameHook(self, p):
|
|
||||||
p.dump(self.talon_card_ids)
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // Black Hole
|
# // Black Hole
|
||||||
|
@ -679,8 +567,6 @@ registerGame(GameInfo(260, RelaxedGolf, "Relaxed Golf",
|
||||||
registerGame(GameInfo(40, Elevator, "Elevator",
|
registerGame(GameInfo(40, Elevator, "Elevator",
|
||||||
GI.GT_GOLF, 1, 0, GI.SL_BALANCED,
|
GI.GT_GOLF, 1, 0, GI.SL_BALANCED,
|
||||||
altnames=("Egyptian Solitaire", "Pyramid Golf") ))
|
altnames=("Egyptian Solitaire", "Pyramid Golf") ))
|
||||||
registerGame(GameInfo(237, TriPeaks, "Tri Peaks",
|
|
||||||
GI.GT_GOLF | GI.GT_SCORE, 1, 0, GI.SL_MOSTLY_SKILL))
|
|
||||||
registerGame(GameInfo(98, BlackHole, "Black Hole",
|
registerGame(GameInfo(98, BlackHole, "Black Hole",
|
||||||
GI.GT_GOLF | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
|
GI.GT_GOLF | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
|
||||||
registerGame(GameInfo(267, FourLeafClovers, "Four Leaf Clovers",
|
registerGame(GameInfo(267, FourLeafClovers, "Four Leaf Clovers",
|
||||||
|
|
449
pysollib/games/larasgame.py
Normal file
449
pysollib/games/larasgame.py
Normal file
|
@ -0,0 +1,449 @@
|
||||||
|
##---------------------------------------------------------------------------##
|
||||||
|
##
|
||||||
|
## Ultrasol -- a Python Solitaire game
|
||||||
|
##
|
||||||
|
## Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
## Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
## Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
## Copyright (C) 1999 Matthew Hohlfeld <hohlfeld@cs.ucsd.edu>
|
||||||
|
##
|
||||||
|
## 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 2 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; see the file COPYING.
|
||||||
|
## If not, write to the Free Software Foundation, Inc.,
|
||||||
|
## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
##
|
||||||
|
##---------------------------------------------------------------------------##
|
||||||
|
|
||||||
|
__all__ = []
|
||||||
|
|
||||||
|
# imports
|
||||||
|
|
||||||
|
# PySol imports
|
||||||
|
from pysollib.gamedb import registerGame, GameInfo, GI
|
||||||
|
from pysollib.util import *
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# //
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class LarasGame_Hint(CautiousDefaultHint):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# //
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class LarasGame_Talon(WasteTalonStack):
|
||||||
|
# Deal a card to each of the RowStacks. Then deal
|
||||||
|
# cards to the talon. Return number of cards dealt.
|
||||||
|
def dealRow(self, rows=None, flip=1, reverse=0, frames=-1, sound=0):
|
||||||
|
game = self.game
|
||||||
|
if rows is None:
|
||||||
|
rows = game.s.rows
|
||||||
|
old_state = game.enterState(game.S_DEAL)
|
||||||
|
cards = self.dealToStacks(rows[:game.MAX_ROW], flip, reverse, frames)
|
||||||
|
if sound and frames and self.game.app.opt.animations:
|
||||||
|
self.game.startDealSample()
|
||||||
|
for i in range(game.DEAL_TO_TALON):
|
||||||
|
if self.cards:
|
||||||
|
game.moveMove(1, self, game.s.rows[-1], frames=frames)
|
||||||
|
cards = cards + 1
|
||||||
|
game.leaveState(old_state)
|
||||||
|
if sound:
|
||||||
|
self.game.stopSamples()
|
||||||
|
return cards
|
||||||
|
|
||||||
|
def dealToStacks(self, stacks, flip=1, reverse=0, frames=-1):
|
||||||
|
game = self.game
|
||||||
|
i, move = 0, game.moveMove
|
||||||
|
for r in stacks:
|
||||||
|
if not self.cards:
|
||||||
|
return 0
|
||||||
|
assert not self.getCard().face_up
|
||||||
|
assert r is not self
|
||||||
|
if flip:
|
||||||
|
game.flipMove(self)
|
||||||
|
move(1, self, r, frames=frames)
|
||||||
|
# Dealing has extra rules in this game type:
|
||||||
|
# If card rank == card location then add one card to talon
|
||||||
|
# If card rank == ACE then add two cards to talon
|
||||||
|
# If card rank == JACK, or higher then add one card to talon
|
||||||
|
# After all the rows have been dealt, deal cards to talon in self.dealRow
|
||||||
|
rank = r.getCard().rank
|
||||||
|
if rank == i: # Is the rank == position?
|
||||||
|
if not self.cards:
|
||||||
|
return 0
|
||||||
|
move(1, self, game.s.rows[-1], frames=frames)
|
||||||
|
i = i + 1
|
||||||
|
if rank == 0: # Is this an Ace?
|
||||||
|
for j in range(2):
|
||||||
|
if not self.cards:
|
||||||
|
return 0
|
||||||
|
move(1, self, game.s.rows[-1], frames=frames)
|
||||||
|
if rank >= 10: # Is it a Jack or better?
|
||||||
|
if not self.cards:
|
||||||
|
return 0
|
||||||
|
move(1, self, game.s.rows[-1], frames=frames)
|
||||||
|
return len(stacks)
|
||||||
|
|
||||||
|
def dealCards(self, sound=0):
|
||||||
|
game = self.game
|
||||||
|
if sound and self.game.app.opt.animations:
|
||||||
|
self.game.startDealSample()
|
||||||
|
for r in game.s.reserves[:20]:
|
||||||
|
while r.cards:
|
||||||
|
game.moveMove(1, r, game.s.rows[game.active_row], frames=3, shadow=0)
|
||||||
|
if self.cards:
|
||||||
|
game.active_row = self.getActiveRow()
|
||||||
|
game.flipMove(self)
|
||||||
|
game.moveMove(1, self, game.s.reserves[0], frames=4, shadow=0)
|
||||||
|
ncards = len(game.s.rows[game.active_row].cards)
|
||||||
|
if ncards >= 20:
|
||||||
|
# We have encountered an extreme situation.
|
||||||
|
# In some game type variations it's possible
|
||||||
|
# to have up to 28 cards on a row stack.
|
||||||
|
# We'll have to double up on some of the reserves.
|
||||||
|
for i in range(ncards - 19):
|
||||||
|
game.moveMove(1, game.s.rows[game.active_row],
|
||||||
|
game.s.reserves[19 - i], frames=4, shadow=0)
|
||||||
|
ncards = len(game.s.rows[game.active_row].cards)
|
||||||
|
assert ncards <= 19
|
||||||
|
for i in range(ncards):
|
||||||
|
game.moveMove(1, game.s.rows[game.active_row],
|
||||||
|
game.s.reserves[ncards - i], frames=4, shadow=0)
|
||||||
|
num_cards = len(self.cards) or self.canDealCards()
|
||||||
|
else: # not self.cards
|
||||||
|
if self.round < self.max_rounds:
|
||||||
|
ncards = 0
|
||||||
|
rows = list(game.s.rows)[:game.MAX_ROW]
|
||||||
|
rows.reverse()
|
||||||
|
for r in rows:
|
||||||
|
while r.cards:
|
||||||
|
ncards += 1
|
||||||
|
if r.cards[-1].face_up:
|
||||||
|
game.flipMove(r)
|
||||||
|
game.moveMove(1, r, self, frames=0)
|
||||||
|
assert len(self.cards) == ncards
|
||||||
|
if ncards != 0:
|
||||||
|
game.nextRoundMove(self)
|
||||||
|
game.dealToRows()
|
||||||
|
num_cards = len(self.cards)
|
||||||
|
if sound:
|
||||||
|
game.stopSamples()
|
||||||
|
return num_cards
|
||||||
|
|
||||||
|
def canDealCards(self):
|
||||||
|
if self.game.demo and self.game.moves.index >= 400:
|
||||||
|
return 0
|
||||||
|
return (self.cards or (self.round < self.max_rounds and not self.game.isGameWon()))
|
||||||
|
|
||||||
|
def updateText(self):
|
||||||
|
if self.game.preview > 1:
|
||||||
|
return
|
||||||
|
WasteTalonStack.updateText(self, update_rounds=0)
|
||||||
|
if not self.max_rounds - 1:
|
||||||
|
return
|
||||||
|
t = _("Round %d") % self.round
|
||||||
|
self.texts.rounds.config(text=t)
|
||||||
|
|
||||||
|
def getActiveRow(self):
|
||||||
|
return self.getCard().rank
|
||||||
|
|
||||||
|
|
||||||
|
class LarasGame_RowStack(OpenStack):
|
||||||
|
def __init__(self, x, y, game, yoffset = 1, **cap):
|
||||||
|
apply(OpenStack.__init__, (self, x, y, game), cap)
|
||||||
|
self.CARD_YOFFSET = yoffset
|
||||||
|
|
||||||
|
|
||||||
|
class LarasGame_ReserveStack(OpenStack):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LarasGame_Reserve(OpenStack):
|
||||||
|
|
||||||
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
if not OpenStack.acceptsCards(self, from_stack, cards):
|
||||||
|
return 0
|
||||||
|
return from_stack in self.game.s.rows
|
||||||
|
|
||||||
|
def getBottomImage(self):
|
||||||
|
return self.game.app.images.getReserveBottom()
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // Lara's Game
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class LarasGame(Game):
|
||||||
|
Hint_Class = LarasGame_Hint
|
||||||
|
Talon_Class = LarasGame_Talon
|
||||||
|
Reserve_Class = None
|
||||||
|
DEAL_TO_TALON = 2
|
||||||
|
MAX_ROUNDS = 1
|
||||||
|
ROW_LENGTH = 4
|
||||||
|
MAX_ROW = 13
|
||||||
|
DIR = (-1, 1)
|
||||||
|
|
||||||
|
#
|
||||||
|
# game layout
|
||||||
|
#
|
||||||
|
|
||||||
|
def createGame(self):
|
||||||
|
# create layout
|
||||||
|
l, s = Layout(self), self.s
|
||||||
|
ROW_LENGTH = self.ROW_LENGTH
|
||||||
|
|
||||||
|
# set window
|
||||||
|
w, h = l.XM + l.XS * (ROW_LENGTH + 5), l.YM + l.YS * (ROW_LENGTH + (ROW_LENGTH != 6))
|
||||||
|
self.setSize(w, h)
|
||||||
|
|
||||||
|
# extra settings
|
||||||
|
self.active_row = None
|
||||||
|
|
||||||
|
# Create foundations
|
||||||
|
x, y = l.XM, l.YM
|
||||||
|
for j in range(2):
|
||||||
|
for i in range(ROW_LENGTH):
|
||||||
|
s.foundations.append(SS_FoundationStack(x, y, self, self.Base_Suit(i, j),
|
||||||
|
max_cards = self.Max_Cards(i), mod = self.Mod(i),
|
||||||
|
dir = self.DIR[j], base_rank = self.Base_Rank(i, j)))
|
||||||
|
y = y + l.YS * (not j)
|
||||||
|
x = x + l.XS * j
|
||||||
|
x, y = x + l.XS * 2, l.YM
|
||||||
|
|
||||||
|
# Create rows
|
||||||
|
x, y = l.XM + l.XS, y + l.YS
|
||||||
|
for i in range(self.MAX_ROW):
|
||||||
|
s.rows.append(LarasGame_RowStack(x, y, self))
|
||||||
|
x = x + l.XS
|
||||||
|
if i == ROW_LENGTH or i == ROW_LENGTH * 2 + 1 or i == ROW_LENGTH * 3 + 2:
|
||||||
|
x, y = l.XM + l.XS, y + l.YS
|
||||||
|
|
||||||
|
# Create reserves
|
||||||
|
x, y = l.XM + l.XS * (ROW_LENGTH == 6), l.YM + l.YS * (ROW_LENGTH - (ROW_LENGTH == 6))
|
||||||
|
for i in range(20):
|
||||||
|
s.reserves.append(LarasGame_ReserveStack(x, y, self, max_cards=2))
|
||||||
|
x = x + l.XS * (i < (ROW_LENGTH + 4)) - l.XS * (i == (ROW_LENGTH + 9))
|
||||||
|
y = y - l.YS * (i > (ROW_LENGTH + 3) and i < (ROW_LENGTH + 9)) + l.YS * (i > (ROW_LENGTH + 9))
|
||||||
|
|
||||||
|
# Create talon
|
||||||
|
x, y = l.XM + l.XS * (ROW_LENGTH + 2), h - l.YM - l.YS * 3
|
||||||
|
s.talon = self.Talon_Class(x, y, self, max_rounds=self.MAX_ROUNDS)
|
||||||
|
l.createText(s.talon, "s")
|
||||||
|
if self.MAX_ROUNDS - 1:
|
||||||
|
tx, ty, ta, tf = l.getTextAttr(s.talon, "nn")
|
||||||
|
s.talon.texts.rounds = MfxCanvasText(self.canvas,
|
||||||
|
tx, ty, anchor=ta,
|
||||||
|
font=self.app.getFont("canvas_default"))
|
||||||
|
y = h - l.YS * 2
|
||||||
|
s.rows.append(LarasGame_RowStack(x, y, self, yoffset=0))
|
||||||
|
|
||||||
|
# Define stack-groups (not default)
|
||||||
|
self.sg.openstacks = s.foundations + s.rows[:self.MAX_ROW]
|
||||||
|
self.sg.talonstacks = [s.talon] + s.rows[-1:]
|
||||||
|
self.sg.dropstacks = s.rows[:self.MAX_ROW] + s.reserves
|
||||||
|
|
||||||
|
# Create relaxed reserve
|
||||||
|
if self.Reserve_Class != None:
|
||||||
|
x, y = l.XM + l.XS * (ROW_LENGTH + 2), l.YM + l.YS * .5
|
||||||
|
s.reserves.append(self.Reserve_Class(x, y, self,
|
||||||
|
max_accept=1, max_cards=self.Reserve_Cards))
|
||||||
|
self.sg.openstacks = self.sg.openstacks + s.reserves[19:]
|
||||||
|
self.sg.dropstacks = self.sg.dropstacks + s.reserves[19:]
|
||||||
|
self.setRegion(s.reserves[19:], (x - l.XM / 2, 0, 99999, 99999))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Game extras
|
||||||
|
#
|
||||||
|
|
||||||
|
def Max_Cards(self, i):
|
||||||
|
return 13
|
||||||
|
|
||||||
|
def Mod(self, i):
|
||||||
|
return 13
|
||||||
|
|
||||||
|
def Base_Rank(self, i, j):
|
||||||
|
return 12 * (not j)
|
||||||
|
|
||||||
|
def Deal_Rows(self, i):
|
||||||
|
return 13
|
||||||
|
|
||||||
|
def Base_Suit(self, i, j):
|
||||||
|
return i
|
||||||
|
|
||||||
|
#
|
||||||
|
# game overrides
|
||||||
|
#
|
||||||
|
|
||||||
|
def startGame(self):
|
||||||
|
assert len(self.s.talon.cards) == self.gameinfo.ncards
|
||||||
|
self.dealToRows()
|
||||||
|
|
||||||
|
def dealToRows(self):
|
||||||
|
frames, ncards = 0, len(self.s.talon.cards)
|
||||||
|
for i in range(8):
|
||||||
|
if not self.s.talon.cards:
|
||||||
|
break
|
||||||
|
if i == 4 or len(self.s.talon.cards) <= ncards / 2:
|
||||||
|
self.startDealSample()
|
||||||
|
frames = 4
|
||||||
|
self.s.talon.dealRow(rows=self.s.rows[:self.Deal_Rows(i)], frames=frames)
|
||||||
|
self.moveMove(len(self.s.rows[-1].cards), self.s.rows[-1], self.s.talon, frames=0)
|
||||||
|
self.active_row = None
|
||||||
|
|
||||||
|
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||||
|
i, j = (stack1 in self.s.foundations), (stack2 in self.s.foundations)
|
||||||
|
if not (i or j): return 0
|
||||||
|
if i: stack = stack1
|
||||||
|
else: stack = stack2
|
||||||
|
i = 0
|
||||||
|
for f in self.s.foundations:
|
||||||
|
if f == stack: break
|
||||||
|
i = i + 1 % self.ROW_LENGTH
|
||||||
|
return (card1.suit == card2.suit and
|
||||||
|
((card1.rank + 1) % self.Mod(i) == card2.rank
|
||||||
|
or (card1.rank - 1) % self.Mod(i) == card2.rank))
|
||||||
|
|
||||||
|
def getHighlightPilesStacks(self):
|
||||||
|
return ()
|
||||||
|
|
||||||
|
# Finish the current move.
|
||||||
|
# Append current active_row to moves.current.
|
||||||
|
# Append moves.current to moves.history.
|
||||||
|
def finishMove(self):
|
||||||
|
moves, stats = self.moves, self.stats
|
||||||
|
if not moves.current:
|
||||||
|
return 0
|
||||||
|
# invalidate hints
|
||||||
|
self.hints.list = None
|
||||||
|
# resize (i.e. possibly shorten list from previous undos)
|
||||||
|
if not moves.index == 0:
|
||||||
|
m = moves.history[len(moves.history) - 1]
|
||||||
|
del moves.history[moves.index : ]
|
||||||
|
# update stats
|
||||||
|
if self.demo:
|
||||||
|
stats.demo_moves = stats.demo_moves + 1
|
||||||
|
if moves.index == 0:
|
||||||
|
stats.player_moves = 0 # clear all player moves
|
||||||
|
else:
|
||||||
|
stats.player_moves = stats.player_moves + 1
|
||||||
|
if moves.index == 0:
|
||||||
|
stats.demo_moves = 0 # clear all demo moves
|
||||||
|
stats.total_moves = stats.total_moves + 1
|
||||||
|
# add current move to history (which is a list of lists)
|
||||||
|
moves.current.append(self.active_row)
|
||||||
|
moves.history.append(moves.current)
|
||||||
|
moves.index = moves.index + 1
|
||||||
|
assert moves.index == len(moves.history)
|
||||||
|
moves.current = []
|
||||||
|
self.updateText()
|
||||||
|
self.updateStatus(moves=(moves.index, self.stats.total_moves))
|
||||||
|
self.updateMenus()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
assert self.canUndo()
|
||||||
|
assert self.moves.state == self.S_PLAY and self.moves.current == []
|
||||||
|
assert 0 <= self.moves.index <= len(self.moves.history)
|
||||||
|
if self.moves.index == 0:
|
||||||
|
return
|
||||||
|
self.moves.index = self.moves.index - 1
|
||||||
|
m = self.moves.history[self.moves.index]
|
||||||
|
m = m[:len(m) - 1]
|
||||||
|
m.reverse()
|
||||||
|
self.moves.state = self.S_UNDO
|
||||||
|
for atomic_move in m:
|
||||||
|
atomic_move.undo(self)
|
||||||
|
self.moves.state = self.S_PLAY
|
||||||
|
m = self.moves.history[max(0, self.moves.index - 1)]
|
||||||
|
self.active_row = m[len(m) - 1]
|
||||||
|
self.stats.undo_moves = self.stats.undo_moves + 1
|
||||||
|
self.stats.total_moves = self.stats.total_moves + 1
|
||||||
|
self.hints.list = None
|
||||||
|
self.updateText()
|
||||||
|
self.updateStatus(moves=(self.moves.index, self.stats.total_moves))
|
||||||
|
self.updateMenus()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
assert self.canRedo()
|
||||||
|
assert self.moves.state == self.S_PLAY and self.moves.current == []
|
||||||
|
assert 0 <= self.moves.index <= len(self.moves.history)
|
||||||
|
if self.moves.index == len(self.moves.history):
|
||||||
|
return
|
||||||
|
m = self.moves.history[self.moves.index]
|
||||||
|
self.moves.index = self.moves.index + 1
|
||||||
|
self.active_row = m[len(m) - 1]
|
||||||
|
m = m[:len(m) - 1]
|
||||||
|
self.moves.state = self.S_REDO
|
||||||
|
for atomic_move in m:
|
||||||
|
atomic_move.redo(self)
|
||||||
|
self.moves.state = self.S_PLAY
|
||||||
|
self.stats.redo_moves = self.stats.redo_moves + 1
|
||||||
|
self.stats.total_moves = self.stats.total_moves + 1
|
||||||
|
self.hints.list = None
|
||||||
|
self.updateText()
|
||||||
|
self.updateStatus(moves=(self.moves.index, self.stats.total_moves))
|
||||||
|
self.updateMenus()
|
||||||
|
|
||||||
|
def _restoreGameHook(self, game):
|
||||||
|
self.active_row = game.loadinfo.active_row
|
||||||
|
|
||||||
|
def _loadGameHook(self, p):
|
||||||
|
self.loadinfo.addattr(active_row=0) # register extra load var.
|
||||||
|
self.loadinfo.active_row = p.load()
|
||||||
|
|
||||||
|
def _saveGameHook(self, p):
|
||||||
|
p.dump(self.active_row)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // Relaxed Lara's Game
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class RelaxedLarasGame(LarasGame):
|
||||||
|
Reserve_Class = LarasGame_Reserve
|
||||||
|
Reserve_Cards = 1
|
||||||
|
DEAL_TO_TALON = 3
|
||||||
|
MAX_ROUNDS = 2
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // Double Lara's Game
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class DoubleLarasGame(RelaxedLarasGame):
|
||||||
|
Reserve_Cards = 2
|
||||||
|
MAX_ROUNDS = 3
|
||||||
|
def Max_Cards(self, i):
|
||||||
|
return 26
|
||||||
|
|
||||||
|
|
||||||
|
# register the game
|
||||||
|
|
||||||
|
registerGame(GameInfo(37, LarasGame, "Lara's Game",
|
||||||
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
||||||
|
registerGame(GameInfo(13006, RelaxedLarasGame, "Lara's Game Relaxed",
|
||||||
|
GI.GT_2DECK_TYPE, 2, 1, GI.SL_BALANCED))
|
||||||
|
registerGame(GameInfo(13007, DoubleLarasGame, "Lara's Game Doubled",
|
||||||
|
GI.GT_2DECK_TYPE, 4, 2, GI.SL_BALANCED))
|
||||||
|
|
||||||
|
|
|
@ -767,8 +767,8 @@ class CircleNine(Game):
|
||||||
stack.CARD_YOFFSET = 0
|
stack.CARD_YOFFSET = 0
|
||||||
|
|
||||||
x, y = l.XM+3.5*l.XS, l.YM+l.YS
|
x, y = l.XM+3.5*l.XS, l.YM+l.YS
|
||||||
stack = RK_FoundationStack(x, y, self, suit=ANY_SUIT,
|
stack = RK_FoundationStack(x, y, self, suit=ANY_SUIT, max_cards=52,
|
||||||
max_cards=52, max_move=0, mod=13)
|
max_move=0, mod=13, base_rank=ANY_RANK)
|
||||||
s.foundations.append(stack)
|
s.foundations.append(stack)
|
||||||
l.createText(stack, 'ne')
|
l.createText(stack, 'ne')
|
||||||
x, y = l.XM, l.YM
|
x, y = l.XM, l.YM
|
||||||
|
@ -794,6 +794,44 @@ class CircleNine(Game):
|
||||||
self.leaveState(old_state)
|
self.leaveState(old_state)
|
||||||
|
|
||||||
|
|
||||||
|
class Measure(CircleNine):
|
||||||
|
|
||||||
|
Foundation_Class = StackWrapper(RK_FoundationStack, max_cards=52)
|
||||||
|
|
||||||
|
def createGame(self, rows=8):
|
||||||
|
l, s = Layout(self), self.s
|
||||||
|
self.setSize(l.XM+rows*l.XS, l.YM+2*l.YS+10*l.YOFFSET)
|
||||||
|
|
||||||
|
x, y = l.XM, l.YM
|
||||||
|
s.talon = Strategerie_Talon(x, y, self)
|
||||||
|
l.createText(s.talon, 'ne')
|
||||||
|
x = self.width-l.XS
|
||||||
|
stack = self.Foundation_Class(x, y, self, suit=ANY_SUIT, max_cards=52,
|
||||||
|
max_move=0, mod=13, base_rank=ANY_RANK)
|
||||||
|
s.foundations.append(stack)
|
||||||
|
l.createText(stack, 'nw')
|
||||||
|
|
||||||
|
x, y = l.XM, l.YM+l.YS
|
||||||
|
for i in range(rows):
|
||||||
|
s.rows.append(CircleNine_RowStack(x, y, self, max_accept=1,
|
||||||
|
max_move=1, base_rank=NO_RANK))
|
||||||
|
x += l.XS
|
||||||
|
|
||||||
|
l.defaultStackGroups()
|
||||||
|
self.sg.dropstacks.append(s.talon)
|
||||||
|
|
||||||
|
def startGame(self):
|
||||||
|
self.startDealSample()
|
||||||
|
self.s.talon.dealRow()
|
||||||
|
self.s.talon.fillStack()
|
||||||
|
|
||||||
|
|
||||||
|
class DoubleMeasure(Measure):
|
||||||
|
Foundation_Class = StackWrapper(RK_FoundationStack, max_cards=104)
|
||||||
|
|
||||||
|
def createGame(self, rows=8):
|
||||||
|
Measure.createGame(self, rows=10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
|
@ -833,4 +871,8 @@ registerGame(GameInfo(613, Fanny, "Fanny",
|
||||||
GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED))
|
GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(641, CircleNine, "Circle Nine",
|
registerGame(GameInfo(641, CircleNine, "Circle Nine",
|
||||||
GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED))
|
GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED))
|
||||||
|
registerGame(GameInfo(643, Measure, "Measure",
|
||||||
|
GI.GT_NUMERICA | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL))
|
||||||
|
registerGame(GameInfo(644, DoubleMeasure, "Double Measure",
|
||||||
|
GI.GT_NUMERICA | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL))
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
__all__ = []
|
__all__ = []
|
||||||
|
|
||||||
# Imports
|
# Imports
|
||||||
import sys, math
|
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
from pysollib.gamedb import registerGame, GameInfo, GI
|
from pysollib.gamedb import registerGame, GameInfo, GI
|
||||||
|
@ -40,7 +39,7 @@ from pysollib.layout import Layout
|
||||||
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
|
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
|
||||||
from pysollib.pysoltk import MfxCanvasText, MfxCanvasImage, bind, ANCHOR_NW
|
from pysollib.pysoltk import MfxCanvasText, MfxCanvasImage, bind, ANCHOR_NW
|
||||||
|
|
||||||
from pysollib.games.golf import Golf_Waste, Golf_Hint
|
from golf import Golf_Waste, Golf_Hint
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
@ -77,7 +76,7 @@ class ThreePeaks_TalonStack(WasteTalonStack):
|
||||||
class ThreePeaks_RowStack(OpenStack):
|
class ThreePeaks_RowStack(OpenStack):
|
||||||
|
|
||||||
def __init__(self, x, y, game, **cap):
|
def __init__(self, x, y, game, **cap):
|
||||||
kwdefault(cap, max_move=0, max_accept=0, max_cards=1,
|
kwdefault(cap, max_move=1, max_accept=0, max_cards=1,
|
||||||
base_rank=ANY_RANK)
|
base_rank=ANY_RANK)
|
||||||
apply(OpenStack.__init__, (self, x, y, game), cap)
|
apply(OpenStack.__init__, (self, x, y, game), cap)
|
||||||
|
|
||||||
|
@ -134,9 +133,11 @@ class ThreePeaks(Game):
|
||||||
l, s = Layout(self), self.s
|
l, s = Layout(self), self.s
|
||||||
|
|
||||||
# set window
|
# set window
|
||||||
# (compute best XOFFSET - up to 64/72 cards can be in the Waste)
|
|
||||||
decks = self.gameinfo.decks
|
decks = self.gameinfo.decks
|
||||||
l.XOFFSET = int(l.XS * 9 / self.gameinfo.ncards)
|
# compute best XOFFSET
|
||||||
|
xoffset = int(l.XS * 8 / self.gameinfo.ncards)
|
||||||
|
if xoffset < l.XOFFSET:
|
||||||
|
l.XOFFSET = xoffset
|
||||||
|
|
||||||
# Set window size
|
# Set window size
|
||||||
w, h = l.XM + l.XS * 10, l.YM + l.YS * 4
|
w, h = l.XM + l.XS * 10, l.YM + l.YS * 4
|
||||||
|
@ -170,12 +171,12 @@ class ThreePeaks(Game):
|
||||||
# Create talon
|
# Create talon
|
||||||
x, y = l.XM, y + l.YM + l.YS
|
x, y = l.XM, y + l.YM + l.YS
|
||||||
s.talon = ThreePeaks_TalonStack(x, y, self, num_deal=1, max_rounds=1)
|
s.talon = ThreePeaks_TalonStack(x, y, self, num_deal=1, max_rounds=1)
|
||||||
l.createText(s.talon, "ss")
|
l.createText(s.talon, "s")
|
||||||
x = x + l.XS
|
x = x + l.XS
|
||||||
s.waste = self.Waste_Class(x, y, self)
|
s.waste = self.Waste_Class(x, y, self)
|
||||||
s.waste.CARD_XOFFSET = l.XOFFSET
|
s.waste.CARD_XOFFSET = l.XOFFSET
|
||||||
s.foundations.append(s.waste)
|
s.foundations.append(s.waste)
|
||||||
l.createText(s.waste, "ss")
|
l.createText(s.waste, "s")
|
||||||
|
|
||||||
# Create text for scores
|
# Create text for scores
|
||||||
if self.preview <= 1:
|
if self.preview <= 1:
|
||||||
|
@ -279,21 +280,10 @@ class ThreePeaksNoScore(ThreePeaks):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
|
||||||
# // Le Grande Teton
|
|
||||||
# ************************************************************************/
|
|
||||||
|
|
||||||
class LeGrandeTeton(ThreePeaksNoScore):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
registerGame(GameInfo(22216, ThreePeaks, "Three Peaks",
|
registerGame(GameInfo(22216, ThreePeaks, "Three Peaks",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_BALANCED))
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(22231, ThreePeaksNoScore, "Three Peaks Non-scoring",
|
registerGame(GameInfo(22231, ThreePeaksNoScore, "Three Peaks Non-scoring",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_BALANCED))
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(22232, LeGrandeTeton, "Le Grande Teton",
|
|
||||||
GI.GT_TAROCK, 1, 0, GI.SL_BALANCED,
|
|
||||||
ranks=range(14), trumps=range(22)))
|
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ class Tournament(Game):
|
||||||
# game layout
|
# game layout
|
||||||
#
|
#
|
||||||
|
|
||||||
def createGame(self, **layout):
|
def createGame(self):
|
||||||
|
|
||||||
# create layout
|
# create layout
|
||||||
l, s = Layout(self), self.s
|
l, s = Layout(self), self.s
|
||||||
|
@ -121,8 +121,9 @@ class Tournament(Game):
|
||||||
s.talon = Tournament_Talon(l.XM, l.YM, self, max_rounds=3)
|
s.talon = Tournament_Talon(l.XM, l.YM, self, max_rounds=3)
|
||||||
l.createText(s.talon, "se")
|
l.createText(s.talon, "se")
|
||||||
tx, ty, ta, tf = l.getTextAttr(s.talon, "ne")
|
tx, ty, ta, tf = l.getTextAttr(s.talon, "ne")
|
||||||
s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty, anchor=ta,
|
font = self.app.getFont("canvas_default")
|
||||||
font=self.app.getFont("canvas_default"))
|
s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty,
|
||||||
|
anchor=ta, font=font)
|
||||||
|
|
||||||
# define stack-groups
|
# define stack-groups
|
||||||
l.defaultStackGroups()
|
l.defaultStackGroups()
|
||||||
|
@ -130,6 +131,7 @@ class Tournament(Game):
|
||||||
#
|
#
|
||||||
# game overrides
|
# game overrides
|
||||||
#
|
#
|
||||||
|
|
||||||
def _shuffleHook(self, cards):
|
def _shuffleHook(self, cards):
|
||||||
for c in cards[-8:]:
|
for c in cards[-8:]:
|
||||||
if c.rank in (ACE, KING):
|
if c.rank in (ACE, KING):
|
||||||
|
@ -189,7 +191,7 @@ class KingsdownEights(Game):
|
||||||
|
|
||||||
Hint_Class = CautiousDefaultHint
|
Hint_Class = CautiousDefaultHint
|
||||||
|
|
||||||
def createGame(self, **layout):
|
def createGame(self):
|
||||||
|
|
||||||
# create layout
|
# create layout
|
||||||
l, s = Layout(self), self.s
|
l, s = Layout(self), self.s
|
||||||
|
@ -232,6 +234,54 @@ class KingsdownEights(Game):
|
||||||
shallHighlightMatch = Game._shallHighlightMatch_AC
|
shallHighlightMatch = Game._shallHighlightMatch_AC
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // Saxony
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class Saxony_Reserve(SS_RowStack):
|
||||||
|
def getBottomImage(self):
|
||||||
|
return self.game.app.images.getReserveBottom()
|
||||||
|
def getHelp(self):
|
||||||
|
return _('Reserve. Build down by suit.')
|
||||||
|
|
||||||
|
|
||||||
|
class Saxony(Game):
|
||||||
|
|
||||||
|
def createGame(self):
|
||||||
|
l, s = Layout(self), self.s
|
||||||
|
self.setSize(l.XM+11*l.XS, 2*l.YM+max(2*l.YS+12*l.YOFFSET, 5*l.YS))
|
||||||
|
|
||||||
|
x, y, = l.XM+1.5*l.XS, l.YM
|
||||||
|
for i in range(8):
|
||||||
|
s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4))
|
||||||
|
x = x + l.XS
|
||||||
|
x, y = l.XM+1.5*l.XS, 2*l.YM+l.YS
|
||||||
|
for i in range(8):
|
||||||
|
s.rows.append(BasicRowStack(x, y, self, max_move=1, max_accept=0))
|
||||||
|
x = x + l.XS
|
||||||
|
x, y = l.XM, 2*l.YM+l.YS
|
||||||
|
for i in range(4):
|
||||||
|
stack = Saxony_Reserve(x, y, self, max_move=1)
|
||||||
|
self.s.reserves.append(stack)
|
||||||
|
stack.CARD_YOFFSET = 0
|
||||||
|
y += l.YS
|
||||||
|
x, y = self.width-l.XS, 2*l.YM+l.YS
|
||||||
|
for i in range(4):
|
||||||
|
self.s.reserves.append(ReserveStack(x, y, self))
|
||||||
|
y += l.YS
|
||||||
|
s.talon = DealRowTalonStack(l.XM, l.YM, self)
|
||||||
|
l.createText(s.talon, "ne")
|
||||||
|
|
||||||
|
l.defaultStackGroups()
|
||||||
|
|
||||||
|
|
||||||
|
def startGame(self):
|
||||||
|
self.s.talon.dealRow(rows=self.s.reserves, frames=0)
|
||||||
|
self.startDealSample()
|
||||||
|
self.s.talon.dealRow()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(303, Tournament, "Tournament",
|
registerGame(GameInfo(303, Tournament, "Tournament",
|
||||||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_MOSTLY_LUCK))
|
GI.GT_2DECK_TYPE, 2, 2, GI.SL_MOSTLY_LUCK))
|
||||||
|
@ -240,6 +290,8 @@ registerGame(GameInfo(304, LaNivernaise, "La Nivernaise",
|
||||||
altnames = ("Napoleon's Flank", ),))
|
altnames = ("Napoleon's Flank", ),))
|
||||||
registerGame(GameInfo(386, KingsdownEights, "Kingsdown Eights",
|
registerGame(GameInfo(386, KingsdownEights, "Kingsdown Eights",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
||||||
|
registerGame(GameInfo(645, Saxony, "Saxony",
|
||||||
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_SKILL))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,3 @@ import larasgame
|
||||||
import matrix
|
import matrix
|
||||||
import mughal
|
import mughal
|
||||||
import tarock
|
import tarock
|
||||||
import threepeaks
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
__all__ = []
|
__all__ = []
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
import sys, types
|
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
from pysollib.gamedb import registerGame, GameInfo, GI
|
from pysollib.gamedb import registerGame, GameInfo, GI
|
||||||
|
@ -38,165 +37,25 @@ from pysollib.layout import Layout
|
||||||
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
|
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
|
||||||
from pysollib.pysoltk import MfxCanvasText
|
from pysollib.pysoltk import MfxCanvasText
|
||||||
|
|
||||||
|
from pysollib.games.larasgame import LarasGame_Talon, LarasGame, LarasGame_Reserve
|
||||||
# /***********************************************************************
|
|
||||||
# //
|
|
||||||
# ************************************************************************/
|
|
||||||
|
|
||||||
class LarasGame_Hint(CautiousDefaultHint):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# //
|
# //
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
class LarasGame_Talon(WasteTalonStack):
|
|
||||||
# Deal a card to each of the RowStacks. Then deal
|
|
||||||
# cards to the talon. Return number of cards dealt.
|
|
||||||
def dealRow(self, rows=None, flip=1, reverse=0, frames=-1, sound=0):
|
|
||||||
game = self.game
|
|
||||||
if rows is None:
|
|
||||||
rows = game.s.rows
|
|
||||||
old_state = game.enterState(game.S_DEAL)
|
|
||||||
cards = self.dealToStacks(rows[:game.MAX_ROW], flip, reverse, frames)
|
|
||||||
if sound and frames and self.game.app.opt.animations:
|
|
||||||
self.game.startDealSample()
|
|
||||||
for i in range(game.DEAL_TO_TALON):
|
|
||||||
if self.cards:
|
|
||||||
game.moveMove(1, self, game.s.rows[-1], frames=frames)
|
|
||||||
cards = cards + 1
|
|
||||||
game.leaveState(old_state)
|
|
||||||
if sound:
|
|
||||||
self.game.stopSamples()
|
|
||||||
return cards
|
|
||||||
|
|
||||||
def dealToStacks(self, stacks, flip=1, reverse=0, frames=-1):
|
|
||||||
game = self.game
|
|
||||||
i, move = 0, game.moveMove
|
|
||||||
for r in stacks:
|
|
||||||
if not self.cards:
|
|
||||||
return 0
|
|
||||||
assert not self.getCard().face_up
|
|
||||||
assert r is not self
|
|
||||||
if flip:
|
|
||||||
game.flipMove(self)
|
|
||||||
move(1, self, r, frames=frames)
|
|
||||||
# Dealing has extra rules in this game type:
|
|
||||||
# If card rank == card location then add one card to talon
|
|
||||||
# If card rank == ACE then add two cards to talon
|
|
||||||
# If card rank == JACK, or higher then add one card to talon
|
|
||||||
# After all the rows have been dealt, deal cards to talon in self.dealRow
|
|
||||||
rank = r.getCard().rank
|
|
||||||
if rank == i: # Is the rank == position?
|
|
||||||
if not self.cards:
|
|
||||||
return 0
|
|
||||||
move(1, self, game.s.rows[-1], frames=frames)
|
|
||||||
i = i + 1
|
|
||||||
if rank == 0: # Is this an Ace?
|
|
||||||
for j in range(2):
|
|
||||||
if not self.cards:
|
|
||||||
return 0
|
|
||||||
move(1, self, game.s.rows[-1], frames=frames)
|
|
||||||
if rank >= 10: # Is it a Jack or better?
|
|
||||||
if not self.cards:
|
|
||||||
return 0
|
|
||||||
move(1, self, game.s.rows[-1], frames=frames)
|
|
||||||
return len(stacks)
|
|
||||||
|
|
||||||
def dealCards(self, sound=0):
|
|
||||||
game = self.game
|
|
||||||
if sound and self.game.app.opt.animations:
|
|
||||||
self.game.startDealSample()
|
|
||||||
for r in game.s.reserves[:20]:
|
|
||||||
while r.cards:
|
|
||||||
game.moveMove(1, r, game.s.rows[game.active_row], frames=3, shadow=0)
|
|
||||||
if self.cards:
|
|
||||||
game.active_row = self.getActiveRow()
|
|
||||||
game.flipMove(self)
|
|
||||||
game.moveMove(1, self, game.s.reserves[0], frames=4, shadow=0)
|
|
||||||
ncards = len(game.s.rows[game.active_row].cards)
|
|
||||||
if ncards >= 20:
|
|
||||||
# We have encountered an extreme situation.
|
|
||||||
# In some game type variations it's possible
|
|
||||||
# to have up to 28 cards on a row stack.
|
|
||||||
# We'll have to double up on some of the reserves.
|
|
||||||
for i in range(ncards - 19):
|
|
||||||
game.moveMove(1, game.s.rows[game.active_row],
|
|
||||||
game.s.reserves[19 - i], frames=4, shadow=0)
|
|
||||||
ncards = len(game.s.rows[game.active_row].cards)
|
|
||||||
assert ncards <= 19
|
|
||||||
for i in range(ncards):
|
|
||||||
game.moveMove(1, game.s.rows[game.active_row],
|
|
||||||
game.s.reserves[ncards - i], frames=4, shadow=0)
|
|
||||||
num_cards = len(self.cards) or self.canDealCards()
|
|
||||||
else: # not self.cards
|
|
||||||
if self.round < self.max_rounds:
|
|
||||||
ncards = 0
|
|
||||||
rows = list(game.s.rows)[:game.MAX_ROW]
|
|
||||||
rows.reverse()
|
|
||||||
for r in rows:
|
|
||||||
while r.cards:
|
|
||||||
ncards += 1
|
|
||||||
if r.cards[-1].face_up:
|
|
||||||
game.flipMove(r)
|
|
||||||
game.moveMove(1, r, self, frames=0)
|
|
||||||
assert len(self.cards) == ncards
|
|
||||||
if ncards != 0:
|
|
||||||
game.nextRoundMove(self)
|
|
||||||
game.dealToRows()
|
|
||||||
num_cards = len(self.cards)
|
|
||||||
if sound:
|
|
||||||
game.stopSamples()
|
|
||||||
return num_cards
|
|
||||||
|
|
||||||
def canDealCards(self):
|
|
||||||
if self.game.demo and self.game.moves.index >= 400:
|
|
||||||
return 0
|
|
||||||
return (self.cards or (self.round < self.max_rounds and not self.game.isGameWon()))
|
|
||||||
|
|
||||||
def updateText(self):
|
|
||||||
if self.game.preview > 1:
|
|
||||||
return
|
|
||||||
WasteTalonStack.updateText(self, update_rounds=0)
|
|
||||||
if not self.max_rounds - 1:
|
|
||||||
return
|
|
||||||
t = _("Round %d") % self.round
|
|
||||||
self.texts.rounds.config(text=t)
|
|
||||||
|
|
||||||
def getActiveRow(self):
|
|
||||||
return self.getCard().rank
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DojoujisGame_Talon(LarasGame_Talon):
|
class DojoujisGame_Talon(LarasGame_Talon):
|
||||||
|
|
||||||
def getActiveRow(self):
|
def getActiveRow(self):
|
||||||
card = self.getCard()
|
card = self.getCard()
|
||||||
return card.rank + card.deck * 4
|
return card.rank + card.deck * 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DoubleKalisGame_Talon(LarasGame_Talon):
|
class DoubleKalisGame_Talon(LarasGame_Talon):
|
||||||
|
|
||||||
def getActiveRow(self):
|
def getActiveRow(self):
|
||||||
card = self.getCard()
|
card = self.getCard()
|
||||||
return card.rank + card.deck * 12
|
return card.rank + card.deck * 12
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LarasGame_RowStack(OpenStack):
|
|
||||||
def __init__(self, x, y, game, yoffset = 1, **cap):
|
|
||||||
apply(OpenStack.__init__, (self, x, y, game), cap)
|
|
||||||
self.CARD_YOFFSET = yoffset
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LarasGame_ReserveStack(OpenStack):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BridgetsGame_Reserve(OpenStack):
|
class BridgetsGame_Reserve(OpenStack):
|
||||||
|
|
||||||
def acceptsCards(self, from_stack, cards):
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
@ -210,270 +69,6 @@ class BridgetsGame_Reserve(OpenStack):
|
||||||
return self.game.app.images.getReserveBottom()
|
return self.game.app.images.getReserveBottom()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LarasGame_Reserve(BridgetsGame_Reserve):
|
|
||||||
|
|
||||||
def acceptsCards(self, from_stack, cards):
|
|
||||||
if not OpenStack.acceptsCards(self, from_stack, cards):
|
|
||||||
return 0
|
|
||||||
return from_stack in self.game.s.rows
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
|
||||||
# // Lara's Game
|
|
||||||
# ************************************************************************/
|
|
||||||
|
|
||||||
class LarasGame(Game):
|
|
||||||
Hint_Class = LarasGame_Hint
|
|
||||||
Talon_Class = LarasGame_Talon
|
|
||||||
Reserve_Class = None
|
|
||||||
DEAL_TO_TALON = 2
|
|
||||||
MAX_ROUNDS = 1
|
|
||||||
ROW_LENGTH = 4
|
|
||||||
MAX_ROW = 13
|
|
||||||
DIR = (-1, 1)
|
|
||||||
|
|
||||||
#
|
|
||||||
# game layout
|
|
||||||
#
|
|
||||||
|
|
||||||
def createGame(self):
|
|
||||||
# create layout
|
|
||||||
l, s = Layout(self), self.s
|
|
||||||
ROW_LENGTH = self.ROW_LENGTH
|
|
||||||
|
|
||||||
# set window
|
|
||||||
w, h = l.XM + l.XS * (ROW_LENGTH + 5), l.YM + l.YS * (ROW_LENGTH + (ROW_LENGTH != 6))
|
|
||||||
self.setSize(w, h)
|
|
||||||
|
|
||||||
# extra settings
|
|
||||||
self.active_row = None
|
|
||||||
|
|
||||||
# Create foundations
|
|
||||||
x, y = l.XM, l.YM
|
|
||||||
for j in range(2):
|
|
||||||
for i in range(ROW_LENGTH):
|
|
||||||
s.foundations.append(SS_FoundationStack(x, y, self, self.Base_Suit(i, j),
|
|
||||||
max_cards = self.Max_Cards(i), mod = self.Mod(i),
|
|
||||||
dir = self.DIR[j], base_rank = self.Base_Rank(i, j)))
|
|
||||||
y = y + l.YS * (not j)
|
|
||||||
x = x + l.XS * j
|
|
||||||
x, y = x + l.XS * 2, l.YM
|
|
||||||
|
|
||||||
# Create rows
|
|
||||||
x, y = l.XM + l.XS, y + l.YS
|
|
||||||
for i in range(self.MAX_ROW):
|
|
||||||
s.rows.append(LarasGame_RowStack(x, y, self))
|
|
||||||
x = x + l.XS
|
|
||||||
if i == ROW_LENGTH or i == ROW_LENGTH * 2 + 1 or i == ROW_LENGTH * 3 + 2:
|
|
||||||
x, y = l.XM + l.XS, y + l.YS
|
|
||||||
|
|
||||||
# Create reserves
|
|
||||||
x, y = l.XM + l.XS * (ROW_LENGTH == 6), l.YM + l.YS * (ROW_LENGTH - (ROW_LENGTH == 6))
|
|
||||||
for i in range(20):
|
|
||||||
s.reserves.append(LarasGame_ReserveStack(x, y, self, max_cards=2))
|
|
||||||
x = x + l.XS * (i < (ROW_LENGTH + 4)) - l.XS * (i == (ROW_LENGTH + 9))
|
|
||||||
y = y - l.YS * (i > (ROW_LENGTH + 3) and i < (ROW_LENGTH + 9)) + l.YS * (i > (ROW_LENGTH + 9))
|
|
||||||
|
|
||||||
# Create talon
|
|
||||||
x, y = l.XM + l.XS * (ROW_LENGTH + 2), h - l.YM - l.YS * 3
|
|
||||||
s.talon = self.Talon_Class(x, y, self, max_rounds=self.MAX_ROUNDS)
|
|
||||||
l.createText(s.talon, "s")
|
|
||||||
if self.MAX_ROUNDS - 1:
|
|
||||||
tx, ty, ta, tf = l.getTextAttr(s.talon, "nn")
|
|
||||||
s.talon.texts.rounds = MfxCanvasText(self.canvas,
|
|
||||||
tx, ty, anchor=ta,
|
|
||||||
font=self.app.getFont("canvas_default"))
|
|
||||||
y = h - l.YS * 2
|
|
||||||
s.rows.append(LarasGame_RowStack(x, y, self, yoffset=0))
|
|
||||||
|
|
||||||
# Define stack-groups (not default)
|
|
||||||
self.sg.openstacks = s.foundations + s.rows[:self.MAX_ROW]
|
|
||||||
self.sg.talonstacks = [s.talon] + s.rows[-1:]
|
|
||||||
self.sg.dropstacks = s.rows[:self.MAX_ROW] + s.reserves
|
|
||||||
|
|
||||||
# Create relaxed reserve
|
|
||||||
if self.Reserve_Class != None:
|
|
||||||
x, y = l.XM + l.XS * (ROW_LENGTH + 2), l.YM + l.YS * .5
|
|
||||||
s.reserves.append(self.Reserve_Class(x, y, self,
|
|
||||||
max_accept=1, max_cards=self.Reserve_Cards))
|
|
||||||
self.sg.openstacks = self.sg.openstacks + s.reserves[19:]
|
|
||||||
self.sg.dropstacks = self.sg.dropstacks + s.reserves[19:]
|
|
||||||
self.setRegion(s.reserves[19:], (x - l.XM / 2, 0, 99999, 99999))
|
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
|
||||||
return 13
|
|
||||||
|
|
||||||
def Mod(self, i):
|
|
||||||
return 13
|
|
||||||
|
|
||||||
def Base_Rank(self, i, j):
|
|
||||||
return 12 * (not j)
|
|
||||||
|
|
||||||
def Deal_Rows(self, i):
|
|
||||||
return 13
|
|
||||||
|
|
||||||
def Base_Suit(self, i, j):
|
|
||||||
return i
|
|
||||||
|
|
||||||
#
|
|
||||||
# game overrides
|
|
||||||
#
|
|
||||||
|
|
||||||
def startGame(self):
|
|
||||||
assert len(self.s.talon.cards) == self.gameinfo.ncards
|
|
||||||
self.dealToRows()
|
|
||||||
|
|
||||||
def dealToRows(self):
|
|
||||||
frames, ncards = 0, len(self.s.talon.cards)
|
|
||||||
for i in range(8):
|
|
||||||
if not self.s.talon.cards:
|
|
||||||
break
|
|
||||||
if i == 4 or len(self.s.talon.cards) <= ncards / 2:
|
|
||||||
self.startDealSample()
|
|
||||||
frames = 4
|
|
||||||
self.s.talon.dealRow(rows=self.s.rows[:self.Deal_Rows(i)], frames=frames)
|
|
||||||
self.moveMove(len(self.s.rows[-1].cards), self.s.rows[-1], self.s.talon, frames=0)
|
|
||||||
self.active_row = None
|
|
||||||
|
|
||||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
|
||||||
i, j = (stack1 in self.s.foundations), (stack2 in self.s.foundations)
|
|
||||||
if not (i or j): return 0
|
|
||||||
if i: stack = stack1
|
|
||||||
else: stack = stack2
|
|
||||||
i = 0
|
|
||||||
for f in self.s.foundations:
|
|
||||||
if f == stack: break
|
|
||||||
i = i + 1 % self.ROW_LENGTH
|
|
||||||
return (card1.suit == card2.suit and
|
|
||||||
((card1.rank + 1) % self.Mod(i) == card2.rank
|
|
||||||
or (card1.rank - 1) % self.Mod(i) == card2.rank))
|
|
||||||
|
|
||||||
def getHighlightPilesStacks(self):
|
|
||||||
return ()
|
|
||||||
|
|
||||||
# Finish the current move.
|
|
||||||
# Append current active_row to moves.current.
|
|
||||||
# Append moves.current to moves.history.
|
|
||||||
def finishMove(self):
|
|
||||||
moves, stats = self.moves, self.stats
|
|
||||||
if not moves.current:
|
|
||||||
return 0
|
|
||||||
# invalidate hints
|
|
||||||
self.hints.list = None
|
|
||||||
# resize (i.e. possibly shorten list from previous undos)
|
|
||||||
if not moves.index == 0:
|
|
||||||
m = moves.history[len(moves.history) - 1]
|
|
||||||
del moves.history[moves.index : ]
|
|
||||||
# update stats
|
|
||||||
if self.demo:
|
|
||||||
stats.demo_moves = stats.demo_moves + 1
|
|
||||||
if moves.index == 0:
|
|
||||||
stats.player_moves = 0 # clear all player moves
|
|
||||||
else:
|
|
||||||
stats.player_moves = stats.player_moves + 1
|
|
||||||
if moves.index == 0:
|
|
||||||
stats.demo_moves = 0 # clear all demo moves
|
|
||||||
stats.total_moves = stats.total_moves + 1
|
|
||||||
# add current move to history (which is a list of lists)
|
|
||||||
moves.current.append(self.active_row)
|
|
||||||
moves.history.append(moves.current)
|
|
||||||
moves.index = moves.index + 1
|
|
||||||
assert moves.index == len(moves.history)
|
|
||||||
moves.current = []
|
|
||||||
self.updateText()
|
|
||||||
self.updateStatus(moves=(moves.index, self.stats.total_moves))
|
|
||||||
self.updateMenus()
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def undo(self):
|
|
||||||
assert self.canUndo()
|
|
||||||
assert self.moves.state == self.S_PLAY and self.moves.current == []
|
|
||||||
assert 0 <= self.moves.index <= len(self.moves.history)
|
|
||||||
if self.moves.index == 0:
|
|
||||||
return
|
|
||||||
self.moves.index = self.moves.index - 1
|
|
||||||
m = self.moves.history[self.moves.index]
|
|
||||||
m = m[:len(m) - 1]
|
|
||||||
m.reverse()
|
|
||||||
self.moves.state = self.S_UNDO
|
|
||||||
for atomic_move in m:
|
|
||||||
atomic_move.undo(self)
|
|
||||||
self.moves.state = self.S_PLAY
|
|
||||||
m = self.moves.history[max(0, self.moves.index - 1)]
|
|
||||||
self.active_row = m[len(m) - 1]
|
|
||||||
self.stats.undo_moves = self.stats.undo_moves + 1
|
|
||||||
self.stats.total_moves = self.stats.total_moves + 1
|
|
||||||
self.hints.list = None
|
|
||||||
self.updateText()
|
|
||||||
self.updateStatus(moves=(self.moves.index, self.stats.total_moves))
|
|
||||||
self.updateMenus()
|
|
||||||
|
|
||||||
def redo(self):
|
|
||||||
assert self.canRedo()
|
|
||||||
assert self.moves.state == self.S_PLAY and self.moves.current == []
|
|
||||||
assert 0 <= self.moves.index <= len(self.moves.history)
|
|
||||||
if self.moves.index == len(self.moves.history):
|
|
||||||
return
|
|
||||||
m = self.moves.history[self.moves.index]
|
|
||||||
self.moves.index = self.moves.index + 1
|
|
||||||
self.active_row = m[len(m) - 1]
|
|
||||||
m = m[:len(m) - 1]
|
|
||||||
self.moves.state = self.S_REDO
|
|
||||||
for atomic_move in m:
|
|
||||||
atomic_move.redo(self)
|
|
||||||
self.moves.state = self.S_PLAY
|
|
||||||
self.stats.redo_moves = self.stats.redo_moves + 1
|
|
||||||
self.stats.total_moves = self.stats.total_moves + 1
|
|
||||||
self.hints.list = None
|
|
||||||
self.updateText()
|
|
||||||
self.updateStatus(moves=(self.moves.index, self.stats.total_moves))
|
|
||||||
self.updateMenus()
|
|
||||||
|
|
||||||
def _restoreGameHook(self, game):
|
|
||||||
self.active_row = game.loadinfo.active_row
|
|
||||||
|
|
||||||
def _loadGameHook(self, p):
|
|
||||||
self.loadinfo.addattr(active_row=0) # register extra load var.
|
|
||||||
self.loadinfo.active_row = p.load()
|
|
||||||
|
|
||||||
def _saveGameHook(self, p):
|
|
||||||
p.dump(self.active_row)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
|
||||||
# // Relaxed Lara's Game
|
|
||||||
# ************************************************************************/
|
|
||||||
|
|
||||||
class RelaxedLarasGame(LarasGame):
|
|
||||||
Reserve_Class = LarasGame_Reserve
|
|
||||||
Reserve_Cards = 1
|
|
||||||
DEAL_TO_TALON = 3
|
|
||||||
MAX_ROUNDS = 2
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
|
||||||
# // Double Lara's Game
|
|
||||||
# ************************************************************************/
|
|
||||||
|
|
||||||
class DoubleLarasGame(RelaxedLarasGame):
|
|
||||||
Reserve_Cards = 2
|
|
||||||
MAX_ROUNDS = 3
|
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
|
||||||
return 26
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // Katrina's Game
|
# // Katrina's Game
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
@ -528,10 +123,6 @@ class DoubleKatrinasGame(RelaxedKatrinasGame):
|
||||||
Reserve_Cards = 3
|
Reserve_Cards = 3
|
||||||
MAX_ROUNDS = 3
|
MAX_ROUNDS = 3
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
def Max_Cards(self, i):
|
||||||
return 28 + 16 * (i == 4)
|
return 28 + 16 * (i == 4)
|
||||||
|
|
||||||
|
@ -552,10 +143,6 @@ class BridgetsGame(LarasGame):
|
||||||
ROW_LENGTH = 5
|
ROW_LENGTH = 5
|
||||||
MAX_ROW = 16
|
MAX_ROW = 16
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
def Max_Cards(self, i):
|
||||||
return 16 - 12 * (i == 4)
|
return 16 - 12 * (i == 4)
|
||||||
|
|
||||||
|
@ -580,10 +167,6 @@ class DoubleBridgetsGame(BridgetsGame):
|
||||||
Reserve_Cards = 3
|
Reserve_Cards = 3
|
||||||
MAX_ROUNDS = 3
|
MAX_ROUNDS = 3
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
def Max_Cards(self, i):
|
||||||
return 32 - 24 * (i == 4)
|
return 32 - 24 * (i == 4)
|
||||||
|
|
||||||
|
@ -598,10 +181,6 @@ class FatimehsGame(LarasGame):
|
||||||
MAX_ROW = 12
|
MAX_ROW = 12
|
||||||
DIR = (1, 1)
|
DIR = (1, 1)
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
def Max_Cards(self, i):
|
||||||
return 12
|
return 12
|
||||||
|
|
||||||
|
@ -635,10 +214,6 @@ class KalisGame(FatimehsGame):
|
||||||
DEAL_TO_TALON = 6
|
DEAL_TO_TALON = 6
|
||||||
ROW_LENGTH = 5
|
ROW_LENGTH = 5
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Base_Suit(self, i, j):
|
def Base_Suit(self, i, j):
|
||||||
return i + j * 5
|
return i + j * 5
|
||||||
|
|
||||||
|
@ -662,10 +237,6 @@ class DoubleKalisGame(RelaxedKalisGame):
|
||||||
MAX_ROUNDS = 4
|
MAX_ROUNDS = 4
|
||||||
MAX_ROW = 24
|
MAX_ROW = 24
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
def Max_Cards(self, i):
|
||||||
return 24
|
return 24
|
||||||
|
|
||||||
|
@ -683,10 +254,6 @@ class DojoujisGame(LarasGame):
|
||||||
MAX_ROW = 8
|
MAX_ROW = 8
|
||||||
DIR = (-1, -1)
|
DIR = (-1, -1)
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
def Max_Cards(self, i):
|
||||||
return 8
|
return 8
|
||||||
|
|
||||||
|
@ -703,7 +270,6 @@ class DojoujisGame(LarasGame):
|
||||||
return i + j * 6
|
return i + j * 6
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // Double Dojouji's Game
|
# // Double Dojouji's Game
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
@ -711,10 +277,6 @@ class DojoujisGame(LarasGame):
|
||||||
class DoubleDojoujisGame(DojoujisGame):
|
class DoubleDojoujisGame(DojoujisGame):
|
||||||
MAX_ROW = 16
|
MAX_ROW = 16
|
||||||
|
|
||||||
#
|
|
||||||
# Game extras
|
|
||||||
#
|
|
||||||
|
|
||||||
def Max_Cards(self, i):
|
def Max_Cards(self, i):
|
||||||
return 16
|
return 16
|
||||||
|
|
||||||
|
@ -724,59 +286,39 @@ class DoubleDojoujisGame(DojoujisGame):
|
||||||
|
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(37, LarasGame, "Lara's Game",
|
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
|
||||||
|
|
||||||
registerGame(GameInfo(13001, KatrinasGame, "Katrina's Game",
|
registerGame(GameInfo(13001, KatrinasGame, "Katrina's Game",
|
||||||
GI.GT_TAROCK, 2, 1, GI.SL_BALANCED,
|
GI.GT_TAROCK, 2, 1, GI.SL_BALANCED,
|
||||||
ranks = range(14), trumps = range(22)))
|
ranks = range(14), trumps = range(22)))
|
||||||
|
|
||||||
registerGame(GameInfo(13002, BridgetsGame, "Bridget's Game",
|
registerGame(GameInfo(13002, BridgetsGame, "Bridget's Game",
|
||||||
GI.GT_HEXADECK, 2, 1, GI.SL_BALANCED,
|
GI.GT_HEXADECK, 2, 1, GI.SL_BALANCED,
|
||||||
ranks = range(16), trumps = range(4)))
|
ranks = range(16), trumps = range(4)))
|
||||||
|
|
||||||
registerGame(GameInfo(13003, FatimehsGame, "Fatimeh's Game",
|
registerGame(GameInfo(13003, FatimehsGame, "Fatimeh's Game",
|
||||||
GI.GT_MUGHAL_GANJIFA, 1, 2, GI.SL_BALANCED,
|
GI.GT_MUGHAL_GANJIFA, 1, 2, GI.SL_BALANCED,
|
||||||
suits = range(8), ranks = range(12)))
|
suits = range(8), ranks = range(12)))
|
||||||
|
|
||||||
registerGame(GameInfo(13004, KalisGame, "Kali's Game",
|
registerGame(GameInfo(13004, KalisGame, "Kali's Game",
|
||||||
GI.GT_DASHAVATARA_GANJIFA, 1, 2, GI.SL_BALANCED,
|
GI.GT_DASHAVATARA_GANJIFA, 1, 2, GI.SL_BALANCED,
|
||||||
suits = range(10), ranks = range(12)))
|
suits = range(10), ranks = range(12)))
|
||||||
|
|
||||||
registerGame(GameInfo(13005, DojoujisGame, "Dojouji's Game",
|
registerGame(GameInfo(13005, DojoujisGame, "Dojouji's Game",
|
||||||
GI.GT_HANAFUDA, 2, 0, GI.SL_BALANCED,
|
GI.GT_HANAFUDA, 2, 0, GI.SL_BALANCED,
|
||||||
suits = range(12), ranks = range(4)))
|
suits = range(12), ranks = range(4)))
|
||||||
|
|
||||||
registerGame(GameInfo(13006, RelaxedLarasGame, "Lara's Game Relaxed",
|
|
||||||
GI.GT_2DECK_TYPE, 2, 1, GI.SL_BALANCED))
|
|
||||||
|
|
||||||
registerGame(GameInfo(13007, DoubleLarasGame, "Lara's Game Doubled",
|
|
||||||
GI.GT_2DECK_TYPE, 4, 2, GI.SL_BALANCED))
|
|
||||||
|
|
||||||
registerGame(GameInfo(13008, RelaxedKatrinasGame, "Katrina's Game Relaxed",
|
registerGame(GameInfo(13008, RelaxedKatrinasGame, "Katrina's Game Relaxed",
|
||||||
GI.GT_TAROCK, 2, 1, GI.SL_BALANCED,
|
GI.GT_TAROCK, 2, 1, GI.SL_BALANCED,
|
||||||
ranks = range(14), trumps = range(22)))
|
ranks = range(14), trumps = range(22)))
|
||||||
|
|
||||||
registerGame(GameInfo(13009, DoubleKatrinasGame, "Katrina's Game Doubled",
|
registerGame(GameInfo(13009, DoubleKatrinasGame, "Katrina's Game Doubled",
|
||||||
GI.GT_TAROCK, 4, 2, GI.SL_BALANCED,
|
GI.GT_TAROCK, 4, 2, GI.SL_BALANCED,
|
||||||
ranks = range(14), trumps = range(22)))
|
ranks = range(14), trumps = range(22)))
|
||||||
|
|
||||||
registerGame(GameInfo(13010, DoubleBridgetsGame, "Bridget's Game Doubled",
|
registerGame(GameInfo(13010, DoubleBridgetsGame, "Bridget's Game Doubled",
|
||||||
GI.GT_HEXADECK, 4, 2, GI.SL_BALANCED,
|
GI.GT_HEXADECK, 4, 2, GI.SL_BALANCED,
|
||||||
ranks = range(16), trumps = range(4)))
|
ranks = range(16), trumps = range(4)))
|
||||||
|
|
||||||
registerGame(GameInfo(13011, RelaxedKalisGame, "Kali's Game Relaxed",
|
registerGame(GameInfo(13011, RelaxedKalisGame, "Kali's Game Relaxed",
|
||||||
GI.GT_DASHAVATARA_GANJIFA, 1, 2, GI.SL_BALANCED,
|
GI.GT_DASHAVATARA_GANJIFA, 1, 2, GI.SL_BALANCED,
|
||||||
suits = range(10), ranks = range(12)))
|
suits = range(10), ranks = range(12)))
|
||||||
|
|
||||||
registerGame(GameInfo(13012, DoubleKalisGame, "Kali's Game Doubled",
|
registerGame(GameInfo(13012, DoubleKalisGame, "Kali's Game Doubled",
|
||||||
GI.GT_DASHAVATARA_GANJIFA, 2, 3, GI.SL_BALANCED,
|
GI.GT_DASHAVATARA_GANJIFA, 2, 3, GI.SL_BALANCED,
|
||||||
suits = range(10), ranks = range(12)))
|
suits = range(10), ranks = range(12)))
|
||||||
|
|
||||||
registerGame(GameInfo(13013, RelaxedFatimehsGame, "Fatimeh's Game Relaxed",
|
registerGame(GameInfo(13013, RelaxedFatimehsGame, "Fatimeh's Game Relaxed",
|
||||||
GI.GT_MUGHAL_GANJIFA, 1, 2, GI.SL_BALANCED,
|
GI.GT_MUGHAL_GANJIFA, 1, 2, GI.SL_BALANCED,
|
||||||
suits = range(8), ranks = range(12)))
|
suits = range(8), ranks = range(12)))
|
||||||
|
|
||||||
registerGame(GameInfo(13014, DoubleDojoujisGame, "Dojouji's Game Doubled",
|
registerGame(GameInfo(13014, DoubleDojoujisGame, "Dojouji's Game Doubled",
|
||||||
GI.GT_HANAFUDA, 4, 0, GI.SL_BALANCED,
|
GI.GT_HANAFUDA, 4, 0, GI.SL_BALANCED,
|
||||||
suits = range(12), ranks = range(4)))
|
suits = range(12), ranks = range(4)))
|
||||||
|
|
|
@ -39,6 +39,7 @@ from pysollib.layout import Layout
|
||||||
#from pysollib.pysoltk import MfxCanvasText
|
#from pysollib.pysoltk import MfxCanvasText
|
||||||
|
|
||||||
from pysollib.games.special.tarock import AbstractTarockGame, Grasshopper
|
from pysollib.games.special.tarock import AbstractTarockGame, Grasshopper
|
||||||
|
from pysollib.games.threepeaks import ThreePeaksNoScore
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
@ -254,6 +255,15 @@ class Rambling(Corkscrew):
|
||||||
sequence = row.isSuitSequence
|
sequence = row.isSuitSequence
|
||||||
return (sequence([card1, card2]) or sequence([card2, card1]))
|
return (sequence([card1, card2]) or sequence([card2, card1]))
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // Le Grande Teton
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class LeGrandeTeton(ThreePeaksNoScore):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // register the games
|
# // register the games
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
@ -270,5 +280,6 @@ r(13164, DoubleCockroach, 'Double Cockroach', GI.GT_TAROCK, 2, 0, GI.SL_MOSTLY_S
|
||||||
r(13165, Corkscrew, 'Corkscrew', GI.GT_TAROCK, 2, 0, GI.SL_MOSTLY_SKILL)
|
r(13165, Corkscrew, 'Corkscrew', GI.GT_TAROCK, 2, 0, GI.SL_MOSTLY_SKILL)
|
||||||
r(13166, Serpent, 'Serpent', GI.GT_TAROCK, 2, 0, GI.SL_MOSTLY_SKILL)
|
r(13166, Serpent, 'Serpent', GI.GT_TAROCK, 2, 0, GI.SL_MOSTLY_SKILL)
|
||||||
r(13167, Rambling, 'Rambling', GI.GT_TAROCK, 2, 0, GI.SL_MOSTLY_SKILL)
|
r(13167, Rambling, 'Rambling', GI.GT_TAROCK, 2, 0, GI.SL_MOSTLY_SKILL)
|
||||||
|
r(22232, LeGrandeTeton, 'Le Grande Teton', GI.GT_TAROCK, 1, 0, GI.SL_BALANCED)
|
||||||
|
|
||||||
|
|
||||||
del r
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ def parse_option(argv):
|
||||||
"fg=", "foreground=",
|
"fg=", "foreground=",
|
||||||
"bg=", "background=",
|
"bg=", "background=",
|
||||||
"fn=", "font=",
|
"fn=", "font=",
|
||||||
|
"french-only",
|
||||||
"noplugins",
|
"noplugins",
|
||||||
"nosound",
|
"nosound",
|
||||||
"debug=",
|
"debug=",
|
||||||
|
@ -103,6 +104,7 @@ def parse_option(argv):
|
||||||
"fg": None,
|
"fg": None,
|
||||||
"bg": None,
|
"bg": None,
|
||||||
"fn": None,
|
"fn": None,
|
||||||
|
"french-only": False,
|
||||||
"noplugins": False,
|
"noplugins": False,
|
||||||
"nosound": False,
|
"nosound": False,
|
||||||
"debug": 0,
|
"debug": 0,
|
||||||
|
@ -120,6 +122,8 @@ def parse_option(argv):
|
||||||
opts["bg"] = i[1]
|
opts["bg"] = i[1]
|
||||||
elif i[0] in ("--fn", "--font"):
|
elif i[0] in ("--fn", "--font"):
|
||||||
opts["fn"] = i[1]
|
opts["fn"] = i[1]
|
||||||
|
elif i[0] == "--french-only":
|
||||||
|
opts["french-only"] = True
|
||||||
elif i[0] == "--noplugins":
|
elif i[0] == "--noplugins":
|
||||||
opts["noplugins"] = True
|
opts["noplugins"] = True
|
||||||
elif i[0] == "--nosound":
|
elif i[0] == "--nosound":
|
||||||
|
@ -146,7 +150,7 @@ def parse_option(argv):
|
||||||
return None
|
return None
|
||||||
filename = args and args[0] or None
|
filename = args and args[0] or None
|
||||||
if filename and not os.path.isfile(filename):
|
if filename and not os.path.isfile(filename):
|
||||||
print _("%s: invalide file name\ntry %s --help for more information") % (prog_name, prog_name)
|
print _("%s: invalid file name\ntry %s --help for more information") % (prog_name, prog_name)
|
||||||
return None
|
return None
|
||||||
return opts, filename
|
return opts, filename
|
||||||
|
|
||||||
|
@ -190,15 +194,19 @@ def pysol_init(app, args):
|
||||||
try:
|
try:
|
||||||
app.commandline.gameid = int(opts['gameid'])
|
app.commandline.gameid = int(opts['gameid'])
|
||||||
except:
|
except:
|
||||||
print >> sys.stderr, 'WARNING: invalide game id:', opts['gameid']
|
print >> sys.stderr, 'WARNING: invalid game id:', opts['gameid']
|
||||||
app.debug = int(opts['debug'])
|
try:
|
||||||
|
app.debug = int(opts['debug'])
|
||||||
|
except:
|
||||||
|
print >> sys.stderr, 'invalid argument for debug'
|
||||||
|
|
||||||
# init games database
|
# init games database
|
||||||
import games
|
import games
|
||||||
import games.contrib
|
if not opts['french-only']:
|
||||||
import games.special
|
#import games.contrib
|
||||||
import games.ultra
|
import games.ultra
|
||||||
import games.mahjongg
|
import games.mahjongg
|
||||||
|
import games.special
|
||||||
|
|
||||||
# init DataLoader
|
# init DataLoader
|
||||||
f = os.path.join("html", "license.html")
|
f = os.path.join("html", "license.html")
|
||||||
|
@ -322,7 +330,7 @@ def pysol_init(app, args):
|
||||||
try:
|
try:
|
||||||
f = Font(top, font)
|
f = Font(top, font)
|
||||||
except:
|
except:
|
||||||
print >> sys.stderr, "invalide font name:", font
|
print >> sys.stderr, "invalid font name:", font
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if font:
|
if font:
|
||||||
|
@ -345,8 +353,7 @@ Main data directory is:
|
||||||
%s
|
%s
|
||||||
|
|
||||||
Please check your %s installation.
|
Please check your %s installation.
|
||||||
''') % (app.dataloader.dir, PACKAGE),
|
''') % (app.dataloader.dir, PACKAGE), bitmap="error", strings=(_("&Quit"),))
|
||||||
bitmap="error", strings=(_("&Quit"),))
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# init cardsets
|
# init cardsets
|
||||||
|
|
|
@ -23,7 +23,7 @@ __all__ = ['ColorsDialog']
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
import os, sys
|
import os, sys
|
||||||
from Tkinter import *
|
import Tkinter
|
||||||
from tkColorChooser import askcolor
|
from tkColorChooser import askcolor
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
|
@ -44,40 +44,40 @@ class ColorsDialog(MfxDialog):
|
||||||
top_frame, bottom_frame = self.createFrames(kw)
|
top_frame, bottom_frame = self.createFrames(kw)
|
||||||
self.createBitmaps(top_frame, kw)
|
self.createBitmaps(top_frame, kw)
|
||||||
|
|
||||||
frame = Frame(top_frame)
|
frame = Tkinter.Frame(top_frame)
|
||||||
frame.pack(expand=YES, fill=BOTH, padx=5, pady=10)
|
frame.pack(expand=True, fill='both', padx=5, pady=10)
|
||||||
frame.columnconfigure(0, weight=1)
|
frame.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
self.table_text_color_var = BooleanVar()
|
self.table_text_color_var = Tkinter.BooleanVar()
|
||||||
self.table_text_color_var.set(app.opt.table_text_color)
|
self.table_text_color_var.set(app.opt.table_text_color)
|
||||||
self.table_text_color_value_var = StringVar()
|
self.table_text_color_value_var = Tkinter.StringVar()
|
||||||
self.table_text_color_value_var.set(app.opt.table_text_color_value)
|
self.table_text_color_value_var.set(app.opt.table_text_color_value)
|
||||||
##self.table_color_var = StringVar()
|
##self.table_color_var = StringVar()
|
||||||
##self.table_color_var.set(app.opt.table_color)
|
##self.table_color_var.set(app.opt.table_color)
|
||||||
self.highlight_piles_colors_var = StringVar()
|
self.highlight_piles_colors_var = Tkinter.StringVar()
|
||||||
self.highlight_piles_colors_var.set(app.opt.highlight_piles_colors[1])
|
self.highlight_piles_colors_var.set(app.opt.highlight_piles_colors[1])
|
||||||
self.highlight_cards_colors_1_var = StringVar()
|
self.highlight_cards_colors_1_var = Tkinter.StringVar()
|
||||||
self.highlight_cards_colors_1_var.set(app.opt.highlight_cards_colors[1])
|
self.highlight_cards_colors_1_var.set(app.opt.highlight_cards_colors[1])
|
||||||
self.highlight_cards_colors_2_var = StringVar()
|
self.highlight_cards_colors_2_var = Tkinter.StringVar()
|
||||||
self.highlight_cards_colors_2_var.set(app.opt.highlight_cards_colors[3])
|
self.highlight_cards_colors_2_var.set(app.opt.highlight_cards_colors[3])
|
||||||
self.highlight_samerank_colors_1_var = StringVar()
|
self.highlight_samerank_colors_1_var = Tkinter.StringVar()
|
||||||
self.highlight_samerank_colors_1_var.set(app.opt.highlight_samerank_colors[1])
|
self.highlight_samerank_colors_1_var.set(app.opt.highlight_samerank_colors[1])
|
||||||
self.highlight_samerank_colors_2_var = StringVar()
|
self.highlight_samerank_colors_2_var = Tkinter.StringVar()
|
||||||
self.highlight_samerank_colors_2_var.set(app.opt.highlight_samerank_colors[3])
|
self.highlight_samerank_colors_2_var.set(app.opt.highlight_samerank_colors[3])
|
||||||
self.hintarrow_color_var = StringVar()
|
self.hintarrow_color_var = Tkinter.StringVar()
|
||||||
self.hintarrow_color_var.set(app.opt.hintarrow_color)
|
self.hintarrow_color_var.set(app.opt.hintarrow_color)
|
||||||
self.highlight_not_matching_color_var = StringVar()
|
self.highlight_not_matching_color_var = Tkinter.StringVar()
|
||||||
self.highlight_not_matching_color_var.set(app.opt.highlight_not_matching_color)
|
self.highlight_not_matching_color_var.set(app.opt.highlight_not_matching_color)
|
||||||
#
|
#
|
||||||
c = Checkbutton(frame, variable=self.table_text_color_var,
|
c = Tkinter.Checkbutton(frame, variable=self.table_text_color_var,
|
||||||
text=_("Text foreground:"), anchor=W)
|
text=_("Text foreground:"), anchor='w')
|
||||||
c.grid(row=0, column=0, sticky=W+E)
|
c.grid(row=0, column=0, sticky='we')
|
||||||
l = Label(frame, width=10, height=2,
|
l = Tkinter.Label(frame, width=10, height=2,
|
||||||
bg=self.table_text_color_value_var.get(),
|
bg=self.table_text_color_value_var.get(),
|
||||||
textvariable=self.table_text_color_value_var)
|
textvariable=self.table_text_color_value_var)
|
||||||
l.grid(row=0, column=1, padx=5)
|
l.grid(row=0, column=1, padx=5)
|
||||||
b = Button(frame, text=_('Change...'), width=10,
|
b = Tkinter.Button(frame, text=_('Change...'), width=10,
|
||||||
command=lambda l=l: self.selectColor(l))
|
command=lambda l=l: self.selectColor(l))
|
||||||
b.grid(row=0, column=2)
|
b.grid(row=0, column=2)
|
||||||
row = 1
|
row = 1
|
||||||
for title, var in (
|
for title, var in (
|
||||||
|
@ -90,12 +90,13 @@ class ColorsDialog(MfxDialog):
|
||||||
(_('Hint arrow:'), self.hintarrow_color_var),
|
(_('Hint arrow:'), self.hintarrow_color_var),
|
||||||
(_('Highlight not matching:'), self.highlight_not_matching_color_var),
|
(_('Highlight not matching:'), self.highlight_not_matching_color_var),
|
||||||
):
|
):
|
||||||
Label(frame, text=title, anchor=W).grid(row=row, column=0, sticky=W+E)
|
Tkinter.Label(frame, text=title, anchor='w'
|
||||||
l = Label(frame, width=10, height=2,
|
).grid(row=row, column=0, sticky='we')
|
||||||
bg=var.get(), textvariable=var)
|
l = Tkinter.Label(frame, width=10, height=2,
|
||||||
|
bg=var.get(), textvariable=var)
|
||||||
l.grid(row=row, column=1, padx=5)
|
l.grid(row=row, column=1, padx=5)
|
||||||
b = Button(frame, text=_('Change...'), width=10,
|
b = Tkinter.Button(frame, text=_('Change...'), width=10,
|
||||||
command=lambda l=l: self.selectColor(l))
|
command=lambda l=l: self.selectColor(l))
|
||||||
b.grid(row=row, column=2)
|
b.grid(row=row, column=2)
|
||||||
row += 1
|
row += 1
|
||||||
#
|
#
|
||||||
|
|
|
@ -24,7 +24,7 @@ __all__ = ['FontsDialog']
|
||||||
# imports
|
# imports
|
||||||
import os, sys
|
import os, sys
|
||||||
import types
|
import types
|
||||||
from Tkinter import *
|
import Tkinter
|
||||||
import tkFont
|
import tkFont
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
|
@ -71,38 +71,40 @@ class FontChooserDialog(MfxDialog):
|
||||||
else:
|
else:
|
||||||
raise TypeError, 'invalid font style: '+ init_font[3]
|
raise TypeError, 'invalid font style: '+ init_font[3]
|
||||||
|
|
||||||
#self.family_var = StringVar()
|
#self.family_var = Tkinter.StringVar()
|
||||||
self.weight_var = BooleanVar()
|
self.weight_var = Tkinter.BooleanVar()
|
||||||
self.slant_var = BooleanVar()
|
self.slant_var = Tkinter.BooleanVar()
|
||||||
self.size_var = IntVar()
|
self.size_var = Tkinter.IntVar()
|
||||||
|
|
||||||
frame = Frame(top_frame)
|
frame = Tkinter.Frame(top_frame)
|
||||||
frame.pack(expand=YES, fill=BOTH, padx=5, pady=10)
|
frame.pack(expand=True, fill='both', padx=5, pady=10)
|
||||||
frame.columnconfigure(0, weight=1)
|
frame.columnconfigure(0, weight=1)
|
||||||
#frame.rowconfigure(1, weight=1)
|
#frame.rowconfigure(1, weight=1)
|
||||||
self.entry = Entry(frame, bg='white')
|
self.entry = Tkinter.Entry(frame, bg='white')
|
||||||
self.entry.grid(row=0, column=0, columnspan=2, sticky=W+E+N+S)
|
self.entry.grid(row=0, column=0, columnspan=2, sticky='news')
|
||||||
self.entry.insert(END, _('abcdefghABCDEFGH'))
|
self.entry.insert('end', _('abcdefghABCDEFGH'))
|
||||||
self.list_box = Listbox(frame, width=36, exportselection=False)
|
self.list_box = Tkinter.Listbox(frame, width=36, exportselection=False)
|
||||||
sb = Scrollbar(frame)
|
sb = Tkinter.Scrollbar(frame)
|
||||||
self.list_box.configure(yscrollcommand=sb.set)
|
self.list_box.configure(yscrollcommand=sb.set)
|
||||||
sb.configure(command=self.list_box.yview)
|
sb.configure(command=self.list_box.yview)
|
||||||
self.list_box.grid(row=1, column=0, sticky=W+E+N+S) # rowspan=4
|
self.list_box.grid(row=1, column=0, sticky='news') # rowspan=4
|
||||||
sb.grid(row=1, column=1, sticky=N+S)
|
sb.grid(row=1, column=1, sticky='ns')
|
||||||
bind(self.list_box, '<<ListboxSelect>>', self.fontupdate)
|
bind(self.list_box, '<<ListboxSelect>>', self.fontupdate)
|
||||||
##self.list_box.focus()
|
##self.list_box.focus()
|
||||||
cb1 = Checkbutton(frame, anchor=W, text=_('Bold'),
|
cb1 = Tkinter.Checkbutton(frame, anchor='w', text=_('Bold'),
|
||||||
command=self.fontupdate, variable=self.weight_var)
|
command=self.fontupdate,
|
||||||
cb1.grid(row=2, column=0, columnspan=2, sticky=W+E)
|
variable=self.weight_var)
|
||||||
cb2 = Checkbutton(frame, anchor=W, text=_('Italic'),
|
cb1.grid(row=2, column=0, columnspan=2, sticky='we')
|
||||||
command=self.fontupdate, variable=self.slant_var)
|
cb2 = Tkinter.Checkbutton(frame, anchor='w', text=_('Italic'),
|
||||||
cb2.grid(row=3, column=0, columnspan=2, sticky=W+E)
|
command=self.fontupdate,
|
||||||
|
variable=self.slant_var)
|
||||||
|
cb2.grid(row=3, column=0, columnspan=2, sticky='we')
|
||||||
|
|
||||||
sc = Scale(frame, from_=6, to=40, resolution=1,
|
sc = Tkinter.Scale(frame, from_=6, to=40, resolution=1,
|
||||||
#label='Size',
|
#label='Size',
|
||||||
orient=HORIZONTAL,
|
orient='horizontal',
|
||||||
command=self.fontupdate, variable=self.size_var)
|
command=self.fontupdate, variable=self.size_var)
|
||||||
sc.grid(row=4, column=0, columnspan=2, sticky=W+E+N+S)
|
sc.grid(row=4, column=0, columnspan=2, sticky='news')
|
||||||
#
|
#
|
||||||
self.size_var.set(self.font_size)
|
self.size_var.set(self.font_size)
|
||||||
self.weight_var.set(self.font_weight == 'bold')
|
self.weight_var.set(self.font_weight == 'bold')
|
||||||
|
@ -111,10 +113,11 @@ class FontChooserDialog(MfxDialog):
|
||||||
font_families.sort()
|
font_families.sort()
|
||||||
selected = -1
|
selected = -1
|
||||||
n = 0
|
n = 0
|
||||||
|
self.list_box.insert('end', *font_families)
|
||||||
for font in font_families:
|
for font in font_families:
|
||||||
self.list_box.insert(END, font)
|
|
||||||
if font.lower() == self.font_family.lower():
|
if font.lower() == self.font_family.lower():
|
||||||
selected = n
|
selected = n
|
||||||
|
break
|
||||||
n += 1
|
n += 1
|
||||||
if selected >= 0:
|
if selected >= 0:
|
||||||
self.list_box.select_set(selected)
|
self.list_box.select_set(selected)
|
||||||
|
@ -155,35 +158,33 @@ class FontsDialog(MfxDialog):
|
||||||
top_frame, bottom_frame = self.createFrames(kw)
|
top_frame, bottom_frame = self.createFrames(kw)
|
||||||
self.createBitmaps(top_frame, kw)
|
self.createBitmaps(top_frame, kw)
|
||||||
|
|
||||||
frame = Frame(top_frame)
|
frame = Tkinter.Frame(top_frame)
|
||||||
frame.pack(expand=YES, fill=BOTH, padx=5, pady=10)
|
frame.pack(expand=True, fill='both', padx=5, pady=10)
|
||||||
frame.columnconfigure(0, weight=1)
|
frame.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
self.fonts = {}
|
self.fonts = {}
|
||||||
row = 0
|
row = 0
|
||||||
for fn in (#"default",
|
for fn, title in (##('default', _('Default')),
|
||||||
"sans",
|
('sans', _('HTML: ')),
|
||||||
"small",
|
('small', _('Small: ')),
|
||||||
"fixed",
|
('fixed', _('Fixed: ')),
|
||||||
"canvas_default",
|
('canvas_default', _('Tableau default: ')),
|
||||||
#"canvas_card",
|
('canvas_fixed', _('Tableau fixed: ')),
|
||||||
"canvas_fixed",
|
('canvas_large', _('Tableau large: ')),
|
||||||
"canvas_large",
|
('canvas_small', _('Tableau small: ')),
|
||||||
"canvas_small",
|
):
|
||||||
#"tree_small",
|
|
||||||
):
|
|
||||||
font = app.opt.fonts[fn]
|
font = app.opt.fonts[fn]
|
||||||
self.fonts[fn] = font
|
self.fonts[fn] = font
|
||||||
title = fn.replace("_", " ").capitalize()+": "
|
Tkinter.Label(frame, text=title, anchor='w'
|
||||||
Label(frame, text=title, anchor=W).grid(row=row, column=0, sticky=W+E)
|
).grid(row=row, column=0, sticky='we')
|
||||||
if font:
|
if font:
|
||||||
title = " ".join([str(i) for i in font if not i in ('roman', 'normal')])
|
title = ' '.join([str(i) for i in font if not i in ('roman', 'normal')])
|
||||||
elif font is None:
|
elif font is None:
|
||||||
title = 'Default'
|
title = 'Default'
|
||||||
l = Label(frame, font=font, text=title)
|
l = Tkinter.Label(frame, font=font, text=title)
|
||||||
l.grid(row=row, column=1)
|
l.grid(row=row, column=1)
|
||||||
b = Button(frame, text=_('Change...'), width=10,
|
b = Tkinter.Button(frame, text=_('Change...'), width=10,
|
||||||
command=lambda l=l, fn=fn: self.selectFont(l, fn))
|
command=lambda l=l, fn=fn: self.selectFont(l, fn))
|
||||||
b.grid(row=row, column=2)
|
b.grid(row=row, column=2)
|
||||||
row += 1
|
row += 1
|
||||||
#
|
#
|
||||||
|
@ -192,16 +193,16 @@ class FontsDialog(MfxDialog):
|
||||||
|
|
||||||
|
|
||||||
def selectFont(self, label, fn):
|
def selectFont(self, label, fn):
|
||||||
d = FontChooserDialog(self.top, _("Select font"), self.fonts[fn])
|
d = FontChooserDialog(self.top, _('Select font'), self.fonts[fn])
|
||||||
if d.status == 0 and d.button == 0:
|
if d.status == 0 and d.button == 0:
|
||||||
self.fonts[fn] = d.font
|
self.fonts[fn] = d.font
|
||||||
title = " ".join([str(i) for i in d.font if not i in ('roman', 'normal')])
|
title = ' '.join([str(i) for i in d.font if not i in ('roman', 'normal')])
|
||||||
label.configure(font=d.font, text=title)
|
label.configure(font=d.font, text=title)
|
||||||
|
|
||||||
|
|
||||||
def initKw(self, kw):
|
def initKw(self, kw):
|
||||||
kw = KwStruct(kw,
|
kw = KwStruct(kw,
|
||||||
strings=(_("&OK"), _("&Cancel")),
|
strings=(_('&OK'), _('&Cancel')),
|
||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
return MfxDialog.initKw(self, kw)
|
return MfxDialog.initKw(self, kw)
|
||||||
|
|
|
@ -24,7 +24,7 @@ __all__ = ['GameInfoDialog']
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
import os, sys
|
import os, sys
|
||||||
from Tkinter import *
|
import Tkinter
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
from pysollib.mfxutil import KwStruct
|
from pysollib.mfxutil import KwStruct
|
||||||
|
@ -44,8 +44,8 @@ class GameInfoDialog(MfxDialog):
|
||||||
top_frame, bottom_frame = self.createFrames(kw)
|
top_frame, bottom_frame = self.createFrames(kw)
|
||||||
self.createBitmaps(top_frame, kw)
|
self.createBitmaps(top_frame, kw)
|
||||||
|
|
||||||
frame = Frame(top_frame)
|
frame = Tkinter.Frame(top_frame)
|
||||||
frame.pack(expand=YES, fill=BOTH, padx=5, pady=10)
|
frame.pack(expand=True, fill='both', padx=5, pady=10)
|
||||||
frame.columnconfigure(0, weight=1)
|
frame.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
game = app.game
|
game = app.game
|
||||||
|
@ -108,8 +108,10 @@ class GameInfoDialog(MfxDialog):
|
||||||
('Hint:', hint),
|
('Hint:', hint),
|
||||||
):
|
):
|
||||||
if t:
|
if t:
|
||||||
Label(frame, text=n, anchor=W).grid(row=row, column=0, sticky=N+W)
|
Tkinter.Label(frame, text=n, anchor='w'
|
||||||
Label(frame, text=t, anchor=W, justify=LEFT).grid(row=row, column=1, sticky=N+W)
|
).grid(row=row, column=0, sticky='nw')
|
||||||
|
Tkinter.Label(frame, text=t, anchor='w', justify='left'
|
||||||
|
).grid(row=row, column=1, sticky='nw')
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
if game.s.talon:
|
if game.s.talon:
|
||||||
|
@ -131,9 +133,9 @@ class GameInfoDialog(MfxDialog):
|
||||||
focus = self.createButtons(bottom_frame, kw)
|
focus = self.createButtons(bottom_frame, kw)
|
||||||
self.mainloop(focus, kw.timeout)
|
self.mainloop(focus, kw.timeout)
|
||||||
|
|
||||||
|
|
||||||
def showStacks(self, frame, row, title, stacks):
|
def showStacks(self, frame, row, title, stacks):
|
||||||
Label(frame, text=title, anchor=W).grid(row=row, column=0, sticky=N+W)
|
Tkinter.Label(frame, text=title, anchor='w'
|
||||||
|
).grid(row=row, column=0, sticky='nw')
|
||||||
if isinstance(stacks, (list, tuple)):
|
if isinstance(stacks, (list, tuple)):
|
||||||
fs = {}
|
fs = {}
|
||||||
for f in stacks:
|
for f in stacks:
|
||||||
|
@ -145,8 +147,8 @@ class GameInfoDialog(MfxDialog):
|
||||||
t = '\n'.join(['%s (%d)' % (i[0], i[1]) for i in fs.items()])
|
t = '\n'.join(['%s (%d)' % (i[0], i[1]) for i in fs.items()])
|
||||||
else:
|
else:
|
||||||
t = stacks.__class__.__name__
|
t = stacks.__class__.__name__
|
||||||
Label(frame, text=t, anchor=W, justify=LEFT).grid(row=row, column=1, sticky=N+W)
|
Tkinter.Label(frame, text=t, anchor='w', justify='left'
|
||||||
|
).grid(row=row, column=1, sticky='nw')
|
||||||
|
|
||||||
def initKw(self, kw):
|
def initKw(self, kw):
|
||||||
kw = KwStruct(kw,
|
kw = KwStruct(kw,
|
||||||
|
|
|
@ -721,14 +721,18 @@ class PysolMenubar(PysolMenubarActions):
|
||||||
submenu = self.__menupath[".menubar.file.favoritegames"][2]
|
submenu = self.__menupath[".menubar.file.favoritegames"][2]
|
||||||
submenu.delete(0, "last")
|
submenu.delete(0, "last")
|
||||||
# insert games
|
# insert games
|
||||||
g = [self.app.getGameInfo(id) for id in gameids]
|
games = []
|
||||||
if len(g) > self.__cb_max*4:
|
for id in gameids:
|
||||||
g.sort(lambda a, b: cmp(gettext(a.name), gettext(b.name)))
|
gi = self.app.getGameInfo(id)
|
||||||
self._addSelectAllGameSubMenu(submenu, g,
|
if gi:
|
||||||
|
games.append(gi)
|
||||||
|
if len(games) > self.__cb_max*4:
|
||||||
|
games.sort(lambda a, b: cmp(gettext(a.name), gettext(b.name)))
|
||||||
|
self._addSelectAllGameSubMenu(submenu, games,
|
||||||
command=self.mSelectGame,
|
command=self.mSelectGame,
|
||||||
variable=self.tkopt.gameid)
|
variable=self.tkopt.gameid)
|
||||||
else:
|
else:
|
||||||
self._addSelectGameSubSubMenu(submenu, g,
|
self._addSelectGameSubSubMenu(submenu, games,
|
||||||
command=self.mSelectGame,
|
command=self.mSelectGame,
|
||||||
variable=self.tkopt.gameid)
|
variable=self.tkopt.gameid)
|
||||||
state = self._getEnabledState
|
state = self._getEnabledState
|
||||||
|
|
|
@ -99,13 +99,14 @@ class SelectGameData(SelectDialogTreeData):
|
||||||
self.all_games_gi = map(app.gdb.get, app.gdb.getGamesIdSortedByName())
|
self.all_games_gi = map(app.gdb.get, app.gdb.getGamesIdSortedByName())
|
||||||
self.no_games = [ SelectGameLeaf(None, None, _("(no games)"), None), ]
|
self.no_games = [ SelectGameLeaf(None, None, _("(no games)"), None), ]
|
||||||
#
|
#
|
||||||
s_by_type = s_oriental = s_special = s_original = s_contrib = None
|
s_by_type = s_oriental = s_special = s_original = s_contrib = s_mahjongg = None
|
||||||
g = []
|
g = []
|
||||||
for data in (GI.SELECT_GAME_BY_TYPE,
|
for data in (GI.SELECT_GAME_BY_TYPE,
|
||||||
GI.SELECT_ORIENTAL_GAME_BY_TYPE,
|
GI.SELECT_ORIENTAL_GAME_BY_TYPE,
|
||||||
GI.SELECT_SPECIAL_GAME_BY_TYPE,
|
GI.SELECT_SPECIAL_GAME_BY_TYPE,
|
||||||
GI.SELECT_ORIGINAL_GAME_BY_TYPE,
|
GI.SELECT_ORIGINAL_GAME_BY_TYPE,
|
||||||
GI.SELECT_CONTRIB_GAME_BY_TYPE):
|
GI.SELECT_CONTRIB_GAME_BY_TYPE,
|
||||||
|
):
|
||||||
gg = []
|
gg = []
|
||||||
for name, select_func in data:
|
for name, select_func in data:
|
||||||
if name is None or not filter(select_func, self.all_games_gi):
|
if name is None or not filter(select_func, self.all_games_gi):
|
||||||
|
@ -114,21 +115,23 @@ class SelectGameData(SelectDialogTreeData):
|
||||||
name = name.replace("&", "")
|
name = name.replace("&", "")
|
||||||
gg.append(SelectGameNode(None, name, select_func))
|
gg.append(SelectGameNode(None, name, select_func))
|
||||||
g.append(gg)
|
g.append(gg)
|
||||||
if 1 and g[0]:
|
select_mahjongg_game = lambda gi: gi.si.game_type == GI.GT_MAHJONGG
|
||||||
|
gg = None
|
||||||
|
if filter(select_mahjongg_game, self.all_games_gi):
|
||||||
|
gg = SelectGameNode(None, _("Mahjongg Games"), select_mahjongg_game)
|
||||||
|
g.append(gg)
|
||||||
|
if g[0]:
|
||||||
s_by_type = SelectGameNode(None, _("French games"), tuple(g[0]), expanded=1)
|
s_by_type = SelectGameNode(None, _("French games"), tuple(g[0]), expanded=1)
|
||||||
pass
|
if g[1]:
|
||||||
if 1 and g[1]:
|
|
||||||
s_oriental = SelectGameNode(None, _("Oriental Games"), tuple(g[1]))
|
s_oriental = SelectGameNode(None, _("Oriental Games"), tuple(g[1]))
|
||||||
pass
|
if g[2]:
|
||||||
if 1 and g[2]:
|
|
||||||
s_special = SelectGameNode(None, _("Special Games"), tuple(g[2]))
|
s_special = SelectGameNode(None, _("Special Games"), tuple(g[2]))
|
||||||
pass
|
if g[3]:
|
||||||
if 1 and g[3]:
|
|
||||||
s_original = SelectGameNode(None, _("Original Games"), tuple(g[3]))
|
s_original = SelectGameNode(None, _("Original Games"), tuple(g[3]))
|
||||||
pass
|
## if g[4]:
|
||||||
if 1 and g[4]:
|
## s_contrib = SelectGameNode(None, "Contributed Games", tuple(g[4]))
|
||||||
##s_contrib = SelectGameNode(None, "Contributed Games", tuple(g[4]))
|
if g[5]:
|
||||||
pass
|
s_mahjongg = g[5]
|
||||||
#
|
#
|
||||||
s_by_compatibility, gg = None, []
|
s_by_compatibility, gg = None, []
|
||||||
for name, games in GI.GAMES_BY_COMPATIBILITY:
|
for name, games in GI.GAMES_BY_COMPATIBILITY:
|
||||||
|
@ -140,16 +143,6 @@ class SelectGameData(SelectDialogTreeData):
|
||||||
if 1 and gg:
|
if 1 and gg:
|
||||||
s_by_compatibility = SelectGameNode(None, _("by Compatibility"), tuple(gg))
|
s_by_compatibility = SelectGameNode(None, _("by Compatibility"), tuple(gg))
|
||||||
pass
|
pass
|
||||||
## #
|
|
||||||
## s_mahjongg, gg = None, []
|
|
||||||
## for name, games in GI.GAMES_BY_COMPATIBILITY:
|
|
||||||
## select_func = lambda gi, games=games: gi.id in games
|
|
||||||
## if name is None or not filter(select_func, self.all_games_gi):
|
|
||||||
## continue
|
|
||||||
## gg.append(SelectGameNode(None, name, select_func))
|
|
||||||
## if 1 and gg:
|
|
||||||
## s_by_compatibility = SelectGameNode(None, "by Compatibility", tuple(gg))
|
|
||||||
## pass
|
|
||||||
#
|
#
|
||||||
s_by_pysol_version, gg = None, []
|
s_by_pysol_version, gg = None, []
|
||||||
for name, games in GI.GAMES_BY_PYSOL_VERSION:
|
for name, games in GI.GAMES_BY_PYSOL_VERSION:
|
||||||
|
@ -169,9 +162,7 @@ class SelectGameData(SelectDialogTreeData):
|
||||||
SelectGameNode(None, _("All Games"), None, expanded=0),
|
SelectGameNode(None, _("All Games"), None, expanded=0),
|
||||||
SelectGameNode(None, _("Alternate Names"), ul_alternate_names),
|
SelectGameNode(None, _("Alternate Names"), ul_alternate_names),
|
||||||
SelectGameNode(None, _("Popular Games"), lambda gi: gi.si.game_flags & GI.GT_POPULAR, expanded=0),
|
SelectGameNode(None, _("Popular Games"), lambda gi: gi.si.game_flags & GI.GT_POPULAR, expanded=0),
|
||||||
SelectGameNode(None, _("Mahjongg Games"),
|
s_mahjongg,
|
||||||
lambda gi: gi.si.game_type == GI.GT_MAHJONGG,
|
|
||||||
expanded=0),
|
|
||||||
s_oriental,
|
s_oriental,
|
||||||
s_special,
|
s_special,
|
||||||
s_by_type,
|
s_by_type,
|
||||||
|
@ -398,7 +389,8 @@ class SelectGameDialogWithPreview(SelectGameDialog):
|
||||||
padx=padx, pady=pady, sticky='nsew')
|
padx=padx, pady=pady, sticky='nsew')
|
||||||
right_frame.columnconfigure(1, weight=1)
|
right_frame.columnconfigure(1, weight=1)
|
||||||
right_frame.rowconfigure(1, weight=1)
|
right_frame.rowconfigure(1, weight=1)
|
||||||
|
#
|
||||||
|
focus = self.createButtons(bottom_frame, kw)
|
||||||
# set the scale factor
|
# set the scale factor
|
||||||
self.preview.canvas.preview = 2
|
self.preview.canvas.preview = 2
|
||||||
# create a preview of the current game
|
# create a preview of the current game
|
||||||
|
@ -406,8 +398,6 @@ class SelectGameDialogWithPreview(SelectGameDialog):
|
||||||
self.preview_game = None
|
self.preview_game = None
|
||||||
self.preview_app = None
|
self.preview_app = None
|
||||||
self.updatePreview(gameid, animations=0)
|
self.updatePreview(gameid, animations=0)
|
||||||
#
|
|
||||||
focus = self.createButtons(bottom_frame, kw)
|
|
||||||
##focus = self.tree.frame
|
##focus = self.tree.frame
|
||||||
SelectGameTreeWithPreview.html_viewer = None
|
SelectGameTreeWithPreview.html_viewer = None
|
||||||
self.mainloop(focus, kw.timeout)
|
self.mainloop(focus, kw.timeout)
|
||||||
|
@ -532,6 +522,12 @@ class SelectGameDialogWithPreview(SelectGameDialog):
|
||||||
self.preview_key = gameid
|
self.preview_key = gameid
|
||||||
#
|
#
|
||||||
self.updateInfo(gameid)
|
self.updateInfo(gameid)
|
||||||
|
#
|
||||||
|
rules_button = self.buttons[1]
|
||||||
|
if self.app.getGameRulesFilename(gameid):
|
||||||
|
rules_button.config(state="normal")
|
||||||
|
else:
|
||||||
|
rules_button.config(state="disabled")
|
||||||
|
|
||||||
def updateInfo(self, gameid):
|
def updateInfo(self, gameid):
|
||||||
gi = self.app.gdb.get(gameid)
|
gi = self.app.gdb.get(gameid)
|
||||||
|
|
|
@ -37,7 +37,7 @@ __all__ = ['SoundOptionsDialog']
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
import os, sys, string
|
import os, sys, string
|
||||||
from Tkinter import *
|
import Tkinter
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
|
@ -63,87 +63,88 @@ class SoundOptionsDialog(MfxDialog):
|
||||||
self.createBitmaps(top_frame, kw)
|
self.createBitmaps(top_frame, kw)
|
||||||
#
|
#
|
||||||
self.saved_opt = app.opt.copy()
|
self.saved_opt = app.opt.copy()
|
||||||
self.sound = BooleanVar()
|
self.sound = Tkinter.BooleanVar()
|
||||||
self.sound.set(app.opt.sound != 0)
|
self.sound.set(app.opt.sound != 0)
|
||||||
self.sound_mode = BooleanVar()
|
self.sound_mode = Tkinter.BooleanVar()
|
||||||
self.sound_mode.set(app.opt.sound_mode != 0)
|
self.sound_mode.set(app.opt.sound_mode != 0)
|
||||||
self.sample_volume = IntVar()
|
self.sample_volume = Tkinter.IntVar()
|
||||||
self.sample_volume.set(app.opt.sound_sample_volume)
|
self.sample_volume.set(app.opt.sound_sample_volume)
|
||||||
self.music_volume = IntVar()
|
self.music_volume = Tkinter.IntVar()
|
||||||
self.music_volume.set(app.opt.sound_music_volume)
|
self.music_volume.set(app.opt.sound_music_volume)
|
||||||
self.samples = [
|
self.samples = [
|
||||||
('areyousure', _('Are You Sure'), BooleanVar()),
|
('areyousure', _('Are You Sure'), Tkinter.BooleanVar()),
|
||||||
|
|
||||||
('deal', _('Deal'), BooleanVar()),
|
('deal', _('Deal'), Tkinter.BooleanVar()),
|
||||||
('dealwaste', _('Deal waste'), BooleanVar()),
|
('dealwaste', _('Deal waste'), Tkinter.BooleanVar()),
|
||||||
|
|
||||||
('turnwaste', _('Turn waste'), BooleanVar()),
|
('turnwaste', _('Turn waste'), Tkinter.BooleanVar()),
|
||||||
('startdrag', _('Start drag'), BooleanVar()),
|
('startdrag', _('Start drag'), Tkinter.BooleanVar()),
|
||||||
|
|
||||||
('drop', _('Drop'), BooleanVar()),
|
('drop', _('Drop'), Tkinter.BooleanVar()),
|
||||||
('droppair', _('Drop pair'), BooleanVar()),
|
('droppair', _('Drop pair'), Tkinter.BooleanVar()),
|
||||||
('autodrop', _('Auto drop'), BooleanVar()),
|
('autodrop', _('Auto drop'), Tkinter.BooleanVar()),
|
||||||
|
|
||||||
('flip', _('Flip'), BooleanVar()),
|
('flip', _('Flip'), Tkinter.BooleanVar()),
|
||||||
('autoflip', _('Auto flip'), BooleanVar()),
|
('autoflip', _('Auto flip'), Tkinter.BooleanVar()),
|
||||||
('move', _('Move'), BooleanVar()),
|
('move', _('Move'), Tkinter.BooleanVar()),
|
||||||
('nomove', _('No move'), BooleanVar()),
|
('nomove', _('No move'), Tkinter.BooleanVar()),
|
||||||
|
|
||||||
('undo', _('Undo'), BooleanVar()),
|
('undo', _('Undo'), Tkinter.BooleanVar()),
|
||||||
('redo', _('Redo'), BooleanVar()),
|
('redo', _('Redo'), Tkinter.BooleanVar()),
|
||||||
|
|
||||||
('autopilotlost', _('Autopilot lost'), BooleanVar()),
|
('autopilotlost', _('Autopilot lost'), Tkinter.BooleanVar()),
|
||||||
('autopilotwon', _('Autopilot won'), BooleanVar()),
|
('autopilotwon', _('Autopilot won'), Tkinter.BooleanVar()),
|
||||||
|
|
||||||
('gamefinished', _('Game finished'), BooleanVar()),
|
('gamefinished', _('Game finished'), Tkinter.BooleanVar()),
|
||||||
('gamelost', _('Game lost'), BooleanVar()),
|
('gamelost', _('Game lost'), Tkinter.BooleanVar()),
|
||||||
('gamewon', _('Game won'), BooleanVar()),
|
('gamewon', _('Game won'), Tkinter.BooleanVar()),
|
||||||
('gameperfect', _('Perfect game'), BooleanVar()),
|
('gameperfect', _('Perfect game'), Tkinter.BooleanVar()),
|
||||||
]
|
]
|
||||||
|
|
||||||
#
|
#
|
||||||
frame = Frame(top_frame)
|
frame = Tkinter.Frame(top_frame)
|
||||||
frame.pack(expand=1, fill='both', padx=5, pady=5)
|
frame.pack(expand=True, fill='both', padx=5, pady=5)
|
||||||
frame.columnconfigure(1, weight=1)
|
frame.columnconfigure(1, weight=1)
|
||||||
#
|
#
|
||||||
row = 0
|
row = 0
|
||||||
w = Checkbutton(frame, variable=self.sound,
|
w = Tkinter.Checkbutton(frame, variable=self.sound,
|
||||||
text=_("Sound enabled"), anchor='w')
|
text=_("Sound enabled"), anchor='w')
|
||||||
w.grid(row=row, column=0, columnspan=2, sticky='ew')
|
w.grid(row=row, column=0, columnspan=2, sticky='ew')
|
||||||
#
|
#
|
||||||
if os.name == "nt" and pysolsoundserver:
|
if os.name == "nt" and pysolsoundserver:
|
||||||
row += 1
|
row += 1
|
||||||
w = Checkbutton(frame, variable=self.sound_mode,
|
w = Tkinter.Checkbutton(frame, variable=self.sound_mode,
|
||||||
text=_("Use DirectX for sound playing"),
|
text=_("Use DirectX for sound playing"),
|
||||||
command=self.mOptSoundDirectX, anchor='w')
|
command=self.mOptSoundDirectX, anchor='w')
|
||||||
w.grid(row=row, column=0, columnspan=2, sticky='ew')
|
w.grid(row=row, column=0, columnspan=2, sticky='ew')
|
||||||
#
|
#
|
||||||
if pysolsoundserver and app.startup_opt.sound_mode > 0:
|
if pysolsoundserver and app.startup_opt.sound_mode > 0:
|
||||||
row += 1
|
row += 1
|
||||||
w = Label(frame, text=_('Sample volume:'))
|
w = Tkinter.Label(frame, text=_('Sample volume:'))
|
||||||
w.grid(row=row, column=0, sticky='w')
|
w.grid(row=row, column=0, sticky='w')
|
||||||
w = Scale(frame, from_=0, to=128, resolution=1,
|
w = Tkinter.Scale(frame, from_=0, to=128, resolution=1,
|
||||||
orient='horizontal', takefocus=0,
|
orient='horizontal', takefocus=0,
|
||||||
length="3i", #label=_('Sample volume'),
|
length="3i", #label=_('Sample volume'),
|
||||||
variable=self.sample_volume)
|
variable=self.sample_volume)
|
||||||
w.grid(row=row, column=1, sticky='w', padx=5)
|
w.grid(row=row, column=1, sticky='w', padx=5)
|
||||||
row += 1
|
row += 1
|
||||||
w = Label(frame, text=_('Music volume:'))
|
w = Tkinter.Label(frame, text=_('Music volume:'))
|
||||||
w.grid(row=row, column=0, sticky='w', padx=5)
|
w.grid(row=row, column=0, sticky='w', padx=5)
|
||||||
w = Scale(frame, from_=0, to=128, resolution=1,
|
w = Tkinter.Scale(frame, from_=0, to=128, resolution=1,
|
||||||
orient='horizontal', takefocus=0,
|
orient='horizontal', takefocus=0,
|
||||||
length="3i", #label=_('Music volume'),
|
length="3i", #label=_('Music volume'),
|
||||||
variable=self.music_volume)
|
variable=self.music_volume)
|
||||||
w.grid(row=row, column=1, sticky='w', padx=5)
|
w.grid(row=row, column=1, sticky='w', padx=5)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# remove "Apply" button
|
# remove "Apply" button
|
||||||
kw.strings[1] = None
|
kw.strings[1] = None
|
||||||
#
|
#
|
||||||
if TkVersion >= 8.4:
|
if Tkinter.TkVersion >= 8.4:
|
||||||
frame = LabelFrame(top_frame, text=_('Enable samles'), padx=5, pady=5)
|
frame = Tkinter.LabelFrame(top_frame, text=_('Enable samles'),
|
||||||
|
padx=5, pady=5)
|
||||||
else:
|
else:
|
||||||
frame = Frame(top_frame)
|
frame = Tkinter.Frame(top_frame)
|
||||||
frame.pack(expand=1, fill='both', padx=5, pady=5)
|
frame.pack(expand=1, fill='both', padx=5, pady=5)
|
||||||
frame.columnconfigure(0, weight=1)
|
frame.columnconfigure(0, weight=1)
|
||||||
frame.columnconfigure(1, weight=1)
|
frame.columnconfigure(1, weight=1)
|
||||||
|
@ -152,7 +153,7 @@ class SoundOptionsDialog(MfxDialog):
|
||||||
col = 0
|
col = 0
|
||||||
for n, t, v in self.samples:
|
for n, t, v in self.samples:
|
||||||
v.set(app.opt.sound_samples[n])
|
v.set(app.opt.sound_samples[n])
|
||||||
w = Checkbutton(frame, text=t, anchor='w', variable=v)
|
w = Tkinter.Checkbutton(frame, text=t, anchor='w', variable=v)
|
||||||
w.grid(row=row, column=col, sticky='ew')
|
w.grid(row=row, column=col, sticky='ew')
|
||||||
if col == 1:
|
if col == 1:
|
||||||
col = 0
|
col = 0
|
||||||
|
@ -203,7 +204,9 @@ class SoundOptionsDialog(MfxDialog):
|
||||||
def mOptSoundDirectX(self, *event):
|
def mOptSoundDirectX(self, *event):
|
||||||
##print self.sound_mode.get()
|
##print self.sound_mode.get()
|
||||||
d = MfxMessageDialog(self.top, title=_("Sound preferences info"),
|
d = MfxMessageDialog(self.top, title=_("Sound preferences info"),
|
||||||
text=_("Changing DirectX settings will take effect\nthe next time you restart ")+PACKAGE,
|
text=_("""\
|
||||||
|
Changing DirectX settings will take effect
|
||||||
|
the next time you restart """)+PACKAGE,
|
||||||
bitmap="warning",
|
bitmap="warning",
|
||||||
default=0, strings=(_("&OK"),))
|
default=0, strings=(_("&OK"),))
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,12 @@ __all__ = ['PysolStatusbar',
|
||||||
# imports
|
# imports
|
||||||
import os, sys, Tkinter
|
import os, sys, Tkinter
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
d = os.path.abspath(os.path.join(sys.path[0], '..', '..'))
|
||||||
|
sys.path.append(d)
|
||||||
|
import gettext
|
||||||
|
gettext.install('pysol', d, unicode=True)
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
from pysollib.mfxutil import destruct
|
from pysollib.mfxutil import destruct
|
||||||
|
|
||||||
|
@ -61,6 +67,7 @@ class MfxStatusbar:
|
||||||
self._columnspan = columnspan
|
self._columnspan = columnspan
|
||||||
#
|
#
|
||||||
self.padx = 1
|
self.padx = 1
|
||||||
|
self.label_relief = 'sunken'
|
||||||
self.frame = Tkinter.Frame(self.top, bd=1)
|
self.frame = Tkinter.Frame(self.top, bd=1)
|
||||||
self.frame.grid(row=self._row, column=self._column,
|
self.frame.grid(row=self._row, column=self._column,
|
||||||
columnspan=self._columnspan, sticky='ew',
|
columnspan=self._columnspan, sticky='ew',
|
||||||
|
@ -70,13 +77,28 @@ class MfxStatusbar:
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
self.frame.config(relief='raised')
|
self.frame.config(relief='raised')
|
||||||
self.padx = 0
|
self.padx = 0
|
||||||
|
if 0:
|
||||||
|
self.frame.config(bd=0)
|
||||||
|
self.label_relief = 'flat'
|
||||||
|
self.padx = 0
|
||||||
|
|
||||||
# util
|
# util
|
||||||
def _createLabel(self, name, side='left',
|
def _createLabel(self, name, side='left',
|
||||||
fill='none', expand=0, width=0,
|
fill='none', expand=0, width=0,
|
||||||
tooltip=None):
|
tooltip=None):
|
||||||
label = Tkinter.Label(self.frame, width=width, relief='sunken', bd=1)
|
if 0:
|
||||||
label.pack(side=side, fill=fill, padx=self.padx, expand=expand)
|
frame = Tkinter.Frame(self.frame, bd=1, relief=self.label_relief,
|
||||||
|
highlightbackground='#9e9a9e',
|
||||||
|
highlightthickness=1)
|
||||||
|
frame.pack(side=side, fill=fill, padx=self.padx, expand=expand)
|
||||||
|
label = Tkinter.Label(frame, width=width, bd=0)
|
||||||
|
label.pack(expand=True, fill='both')
|
||||||
|
else:
|
||||||
|
label = Tkinter.Label(self.frame, width=width,
|
||||||
|
relief=self.label_relief, bd=1,
|
||||||
|
highlightbackground='black'
|
||||||
|
)
|
||||||
|
label.pack(side=side, fill=fill, padx=self.padx, expand=expand)
|
||||||
setattr(self, name + "_label", label)
|
setattr(self, name + "_label", label)
|
||||||
self._widgets.append(label)
|
self._widgets.append(label)
|
||||||
if tooltip:
|
if tooltip:
|
||||||
|
|
|
@ -23,7 +23,7 @@ __all__ = ['TimeoutsDialog']
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
import os, sys
|
import os, sys
|
||||||
from Tkinter import *
|
import Tkinter
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
from pysollib.mfxutil import destruct, kwdefault, KwStruct, Struct
|
from pysollib.mfxutil import destruct, kwdefault, KwStruct, Struct
|
||||||
|
@ -43,24 +43,24 @@ class TimeoutsDialog(MfxDialog):
|
||||||
top_frame, bottom_frame = self.createFrames(kw)
|
top_frame, bottom_frame = self.createFrames(kw)
|
||||||
#self.createBitmaps(top_frame, kw)
|
#self.createBitmaps(top_frame, kw)
|
||||||
|
|
||||||
frame = Frame(top_frame)
|
frame = Tkinter.Frame(top_frame)
|
||||||
frame.pack(expand=YES, fill=BOTH, padx=5, pady=10)
|
frame.pack(expand=True, fill='both', padx=5, pady=10)
|
||||||
frame.columnconfigure(0, weight=1)
|
frame.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
self.demo_sleep_var = DoubleVar()
|
self.demo_sleep_var = Tkinter.DoubleVar()
|
||||||
self.demo_sleep_var.set(app.opt.demo_sleep)
|
self.demo_sleep_var.set(app.opt.demo_sleep)
|
||||||
self.hint_sleep_var = DoubleVar()
|
self.hint_sleep_var = Tkinter.DoubleVar()
|
||||||
self.hint_sleep_var.set(app.opt.hint_sleep)
|
self.hint_sleep_var.set(app.opt.hint_sleep)
|
||||||
self.raise_card_sleep_var = DoubleVar()
|
self.raise_card_sleep_var = Tkinter.DoubleVar()
|
||||||
self.raise_card_sleep_var.set(app.opt.raise_card_sleep)
|
self.raise_card_sleep_var.set(app.opt.raise_card_sleep)
|
||||||
self.highlight_piles_sleep_var = DoubleVar()
|
self.highlight_piles_sleep_var = Tkinter.DoubleVar()
|
||||||
self.highlight_piles_sleep_var.set(app.opt.highlight_piles_sleep)
|
self.highlight_piles_sleep_var.set(app.opt.highlight_piles_sleep)
|
||||||
self.highlight_cards_sleep_var = DoubleVar()
|
self.highlight_cards_sleep_var = Tkinter.DoubleVar()
|
||||||
self.highlight_cards_sleep_var.set(app.opt.highlight_cards_sleep)
|
self.highlight_cards_sleep_var.set(app.opt.highlight_cards_sleep)
|
||||||
self.highlight_samerank_sleep_var = DoubleVar()
|
self.highlight_samerank_sleep_var = Tkinter.DoubleVar()
|
||||||
self.highlight_samerank_sleep_var.set(app.opt.highlight_samerank_sleep)
|
self.highlight_samerank_sleep_var.set(app.opt.highlight_samerank_sleep)
|
||||||
#
|
#
|
||||||
#Label(frame, text='Set delays in seconds').grid(row=0, column=0, columnspan=2)
|
#Tkinter.Label(frame, text='Set delays in seconds').grid(row=0, column=0, columnspan=2)
|
||||||
row = 0
|
row = 0
|
||||||
for title, var in ((_('Demo:'), self.demo_sleep_var),
|
for title, var in ((_('Demo:'), self.demo_sleep_var),
|
||||||
(_('Hint:'), self.hint_sleep_var),
|
(_('Hint:'), self.hint_sleep_var),
|
||||||
|
@ -69,11 +69,11 @@ class TimeoutsDialog(MfxDialog):
|
||||||
(_('Highlight cards:'), self.highlight_cards_sleep_var),
|
(_('Highlight cards:'), self.highlight_cards_sleep_var),
|
||||||
(_('Highlight same rank:'), self.highlight_samerank_sleep_var),
|
(_('Highlight same rank:'), self.highlight_samerank_sleep_var),
|
||||||
):
|
):
|
||||||
Label(frame, text=title, anchor=W).grid(row=row, column=0, sticky=W+E)
|
Tkinter.Label(frame, text=title, anchor='w'
|
||||||
widget = Scale(frame, from_=0.2, to=9.9,
|
).grid(row=row, column=0, sticky='we')
|
||||||
resolution=0.1, orient=HORIZONTAL,
|
widget = Tkinter.Scale(frame, from_=0.2, to=9.9,
|
||||||
length="3i",
|
resolution=0.1, orient='horizontal',
|
||||||
variable=var, takefocus=0)
|
length="3i", variable=var, takefocus=0)
|
||||||
widget.grid(row=row, column=1)
|
widget.grid(row=row, column=1)
|
||||||
row += 1
|
row += 1
|
||||||
#
|
#
|
||||||
|
|
|
@ -40,13 +40,19 @@ import os, sys, re, types
|
||||||
import htmllib, formatter
|
import htmllib, formatter
|
||||||
import Tkinter
|
import Tkinter
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
d = os.path.abspath(os.path.join(sys.path[0], '..', '..'))
|
||||||
|
sys.path.append(d)
|
||||||
|
import gettext
|
||||||
|
gettext.install('pysol', d, unicode=True)
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
from pysollib.mfxutil import Struct, openURL
|
from pysollib.mfxutil import Struct, openURL
|
||||||
from pysollib.settings import PACKAGE
|
from pysollib.settings import PACKAGE
|
||||||
|
|
||||||
# Toolkit imports
|
# Toolkit imports
|
||||||
from tkutil import bind, unbind_destroy, loadImage
|
from tkutil import bind, unbind_destroy, loadImage
|
||||||
from tkwidget import MfxDialog
|
from tkwidget import MfxMessageDialog
|
||||||
from statusbar import HtmlStatusbar
|
from statusbar import HtmlStatusbar
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,9 +71,13 @@ class tkHTMLWriter(formatter.DumbWriter):
|
||||||
self.viewer = viewer
|
self.viewer = viewer
|
||||||
|
|
||||||
##
|
##
|
||||||
font = app.getFont("sans")
|
if app:
|
||||||
|
font = app.getFont("sans")
|
||||||
|
fixed = app.getFont("fixed")
|
||||||
|
else:
|
||||||
|
font = ('helvetica', 12)
|
||||||
|
fixed = ('courier', 12)
|
||||||
size = font[1]
|
size = font[1]
|
||||||
fixed = app.getFont("fixed")
|
|
||||||
sign = 1
|
sign = 1
|
||||||
if size < 0: sign = -1
|
if size < 0: sign = -1
|
||||||
self.fontmap = {
|
self.fontmap = {
|
||||||
|
@ -121,14 +131,21 @@ class tkHTMLWriter(formatter.DumbWriter):
|
||||||
if self.anchor:
|
if self.anchor:
|
||||||
url = self.anchor[0]
|
url = self.anchor[0]
|
||||||
tag = "href_" + url
|
tag = "href_" + url
|
||||||
self.text.tag_add(tag, self.anchor_mark, "insert")
|
anchor_mark = self.anchor_mark
|
||||||
|
if self.text.get(anchor_mark) == ' ': # FIXME
|
||||||
|
try:
|
||||||
|
y, x = anchor_mark.split('.')
|
||||||
|
anchor_mark = y+'.'+str(int(x)+1)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.text.tag_add(tag, anchor_mark, "insert")
|
||||||
self.text.tag_bind(tag, "<1>", self.createCallback(url))
|
self.text.tag_bind(tag, "<1>", self.createCallback(url))
|
||||||
self.text.tag_bind(tag, "<Enter>", lambda e: self.anchor_enter(url))
|
self.text.tag_bind(tag, "<Enter>", lambda e: self.anchor_enter(url))
|
||||||
self.text.tag_bind(tag, "<Leave>", self.anchor_leave)
|
self.text.tag_bind(tag, "<Leave>", self.anchor_leave)
|
||||||
fg = 'blue'
|
fg = 'blue'
|
||||||
u = self.viewer.normurl(url, with_protocol=False)
|
u = self.viewer.normurl(url, with_protocol=False)
|
||||||
if u in self.viewer.visited_urls:
|
if u in self.viewer.visited_urls:
|
||||||
fg = '#303080'
|
fg = '#660099'
|
||||||
self.text.tag_config(tag, foreground=fg, underline=1)
|
self.text.tag_config(tag, foreground=fg, underline=1)
|
||||||
self.anchor = None
|
self.anchor = None
|
||||||
|
|
||||||
|
@ -379,7 +396,7 @@ class tkHTMLViewer:
|
||||||
for p in REMOTE_PROTOCOLS:
|
for p in REMOTE_PROTOCOLS:
|
||||||
if url.startswith(p):
|
if url.startswith(p):
|
||||||
if not openURL(url):
|
if not openURL(url):
|
||||||
self.errorDialog(PACKAGE + _(''' HTML limitation:
|
self.errorDialog(PACKAGE + _('''HTML limitation:
|
||||||
The %s protocol is not supported yet.
|
The %s protocol is not supported yet.
|
||||||
|
|
||||||
Please use your standard web browser
|
Please use your standard web browser
|
||||||
|
@ -491,9 +508,9 @@ to open the following URL:
|
||||||
self.display(self.home, relpath=0)
|
self.display(self.home, relpath=0)
|
||||||
|
|
||||||
def errorDialog(self, msg):
|
def errorDialog(self, msg):
|
||||||
d = MfxDialog(self.parent, title=PACKAGE+" HTML Problem",
|
d = MfxMessageDialog(self.parent, title=PACKAGE+" HTML Problem",
|
||||||
text=msg, bitmap="warning",
|
text=msg, bitmap="warning",
|
||||||
strings=(_("&OK"),), default=0)
|
strings=(_("&OK"),), default=0)
|
||||||
|
|
||||||
def getImage(self, fn):
|
def getImage(self, fn):
|
||||||
if self.images.has_key(fn):
|
if self.images.has_key(fn):
|
||||||
|
@ -526,6 +543,7 @@ def tkhtml_main(args):
|
||||||
top = Tkinter.Tk()
|
top = Tkinter.Tk()
|
||||||
top.wm_minsize(400, 200)
|
top.wm_minsize(400, 200)
|
||||||
viewer = tkHTMLViewer(top)
|
viewer = tkHTMLViewer(top)
|
||||||
|
viewer.app = None
|
||||||
viewer.display(url)
|
viewer.display(url)
|
||||||
top.mainloop()
|
top.mainloop()
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -70,6 +70,7 @@ class MfxDialog: # ex. _ToplevelDialog
|
||||||
self.status = 0
|
self.status = 0
|
||||||
self.button = default
|
self.button = default
|
||||||
self.timer = None
|
self.timer = None
|
||||||
|
self.buttons = []
|
||||||
self.accel_keys = {}
|
self.accel_keys = {}
|
||||||
self.top = makeToplevel(parent, title=title)
|
self.top = makeToplevel(parent, title=title)
|
||||||
self.top.wm_resizable(resizable, resizable)
|
self.top.wm_resizable(resizable, resizable)
|
||||||
|
@ -231,6 +232,7 @@ class MfxDialog: # ex. _ToplevelDialog
|
||||||
if button == kw.default:
|
if button == kw.default:
|
||||||
focus = b
|
focus = b
|
||||||
focus.config(default="active")
|
focus.config(default="active")
|
||||||
|
self.buttons.append(b)
|
||||||
#
|
#
|
||||||
b.config(width=button_width)
|
b.config(width=button_width)
|
||||||
if accel_indx >= 0:
|
if accel_indx >= 0:
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
import sys, os, re, time
|
import sys, os, re, time
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
|
os.environ['LANG'] = 'C'
|
||||||
import gettext
|
import gettext
|
||||||
gettext.install('pysol', 'locale', unicode=True)
|
gettext.install('pysol', 'locale', unicode=True)
|
||||||
|
|
||||||
|
@ -15,7 +16,6 @@ rules_dir = os.path.normpath(os.path.join(pysollib_path, 'data/html/rules'))
|
||||||
#print rules_dir
|
#print rules_dir
|
||||||
|
|
||||||
import pysollib.games
|
import pysollib.games
|
||||||
import pysollib.games.contrib
|
|
||||||
import pysollib.games.special
|
import pysollib.games.special
|
||||||
import pysollib.games.ultra
|
import pysollib.games.ultra
|
||||||
import pysollib.games.mahjongg
|
import pysollib.games.mahjongg
|
||||||
|
@ -138,17 +138,17 @@ def all_games(sort_by='id'):
|
||||||
gt = CSI.TYPE_NAME[gi.category]
|
gt = CSI.TYPE_NAME[gi.category]
|
||||||
if gt == 'French':
|
if gt == 'French':
|
||||||
gt = 'French (%s)' % GAME_BY_TYPE[gi.si.game_type]
|
gt = 'French (%s)' % GAME_BY_TYPE[gi.si.game_type]
|
||||||
|
name = gi.name.encode('utf-8')
|
||||||
|
altnames = '<br>'.join(gi.altnames).encode('utf-8')
|
||||||
if 1 and os.path.exists(os.path.join(rules_dir, rules_fn)):
|
if 1 and os.path.exists(os.path.join(rules_dir, rules_fn)):
|
||||||
fn = '../data/html/rules/'+rules_fn
|
fn = '../data/html/rules/'+rules_fn
|
||||||
print '''<tr><td>%s</td><td>
|
print '''<tr><td>%s</td><td>
|
||||||
<a href="%s" title="Rules for this game">%s</a>
|
<a href="%s" title="Rules for this game">%s</a>
|
||||||
</td><td>%s</td><td>%s</td></tr>
|
</td><td>%s</td><td>%s</td></tr>
|
||||||
''' % (id, fn,
|
''' % (id, fn, name, altnames, gt)
|
||||||
gi.name.encode('utf-8'), '<br>'.join(gi.altnames).encode('utf-8'), gt)
|
|
||||||
else:
|
else:
|
||||||
print '''<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>
|
print '''<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>
|
||||||
''' % (id, gi.name.encode('utf-8'),
|
''' % (id, name, altnames, gt)
|
||||||
'<br>'.join(gi.altnames).encode('utf-8'), gt)
|
|
||||||
print '</table>'
|
print '</table>'
|
||||||
|
|
||||||
def create_html(sort_by):
|
def create_html(sort_by):
|
||||||
|
@ -219,6 +219,7 @@ def plain_text():
|
||||||
for id in get_games_func():
|
for id in get_games_func():
|
||||||
gi = GAME_DB.get(id)
|
gi = GAME_DB.get(id)
|
||||||
if gi.category == GI.GC_FRENCH:
|
if gi.category == GI.GC_FRENCH:
|
||||||
|
##print str(gi.gameclass)
|
||||||
print gi.name.encode('utf-8')
|
print gi.name.encode('utf-8')
|
||||||
##name = gi.name.lower()
|
##name = gi.name.lower()
|
||||||
##name = re.sub('\W', '', name)
|
##name = re.sub('\W', '', name)
|
||||||
|
@ -235,6 +236,8 @@ elif sys.argv[1] == 'gettext':
|
||||||
get_text()
|
get_text()
|
||||||
elif sys.argv[1] == 'text':
|
elif sys.argv[1] == 'text':
|
||||||
plain_text()
|
plain_text()
|
||||||
|
else:
|
||||||
|
sys.exit('invalid argument')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue