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

- new option: `save games geometry'

- 5 new games: `double russian solitaire', `zodiac', `spike',
  `phantom blockade', `moving left'
- tkhtmlviewer: highlight visited urls


git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@8 39dd0a4e-7c14-0410-91b3-c4f2d318f732
This commit is contained in:
skomoroh 2006-06-14 21:19:47 +00:00
parent 314f1a54b6
commit f9c7a04cc5
19 changed files with 386 additions and 139 deletions

View file

@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PySol 0.0.1\n"
"POT-Creation-Date: Sun Jun 11 00:30:03 2006\n"
"POT-Creation-Date: Sun Jun 11 10:16:06 2006\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

View file

@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: Sun Jun 11 00:29:57 2006\n"
"POT-Creation-Date: Sun Jun 11 10:16:01 2006\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -2142,7 +2142,7 @@ msgid "Show hint arrow (in Shisen-Sho games)"
msgstr ""
#: pysollib/tk/menubar.py:341
msgid "&Sound"
msgid "&Sound..."
msgstr ""
#: pysollib/tk/menubar.py:349

View file

@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PySol 0.0.1\n"
"POT-Creation-Date: Sun Jun 11 00:30:03 2006\n"
"POT-Creation-Date: Sun Jun 11 10:16:06 2006\n"
"PO-Revision-Date: 2006-06-10 11:07+0400\n"
"Last-Translator: Скоморох <skomoroh@gmail.com>\n"
"Language-Team: Russian <ru@li.org>\n"

View file

@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: PySol 0.0.1\n"
"POT-Creation-Date: Sun Jun 11 00:29:57 2006\n"
"PO-Revision-Date: 2006-06-11 00:32+0400\n"
"POT-Creation-Date: Sun Jun 11 10:16:01 2006\n"
"PO-Revision-Date: 2006-06-12 15:31+0400\n"
"Last-Translator: Скоморох <skomoroh@gmail.com>\n"
"Language-Team: Russian <ru@li.org>\n"
"MIME-Version: 1.0\n"
@ -2280,8 +2280,8 @@ msgid "Show hint arrow (in Shisen-Sho games)"
msgstr "Показывать стрелку (в Шисен-Сё)"
#: pysollib/tk/menubar.py:341
msgid "&Sound"
msgstr "&Звук"
msgid "&Sound..."
msgstr "&Звук..."
#: pysollib/tk/menubar.py:349
msgid "Cards&et..."
@ -2289,7 +2289,7 @@ msgstr "Коло&да..."
#: pysollib/tk/menubar.py:350
msgid "Table t&ile..."
msgstr "&Игровой стол..."
msgstr "Игровой &стол..."
#: pysollib/tk/menubar.py:352
msgid "Card &background"
@ -2313,7 +2313,7 @@ msgstr "&Негативные контуры карты"
#: pysollib/tk/menubar.py:357
msgid "A&nimations"
msgstr "&Анимация"
msgstr "Анимаци&я"
#: pysollib/tk/menubar.py:358
msgid "&None"
@ -2353,11 +2353,11 @@ msgstr "Тайма&уты..."
#: pysollib/tk/menubar.py:369
msgid "&Toolbar"
msgstr "Панель &инструментов"
msgstr "Панель и&нструментов"
#: pysollib/tk/menubar.py:371
msgid "Stat&usbar"
msgstr "Панель состояния"
msgstr "Панель с&остояния"
#: pysollib/tk/menubar.py:372
msgid "Show &statusbar"
@ -2373,11 +2373,11 @@ msgstr "Показывать панель помощи"
#: pysollib/tk/menubar.py:375
msgid "&Demo logo"
msgstr "&Демо лого"
msgstr "Д&емо лого"
#: pysollib/tk/menubar.py:376
msgid "Startup splash sc&reen"
msgstr "Окно &запуска"
msgstr "О&кно запуска"
#: pysollib/tk/menubar.py:380
msgid "&Help"
@ -2809,7 +2809,7 @@ msgstr "Все фоновые изображения"
#: pysollib/tk/selecttile.py:158
msgid "&Solid color..."
msgstr "&Монотонный цвет..."
msgstr "М&онотонный цвет..."
#: pysollib/tk/soundoptionsdialog.py:111
msgid "Sound enabled"
@ -2837,7 +2837,7 @@ msgstr "&Применить"
#: pysollib/tk/soundoptionsdialog.py:169 pysollib/tk/soundoptionsdialog.py:171
msgid "&Mixer..."
msgstr "&Миксер..."
msgstr "Ми&ксер..."
#: pysollib/tk/soundoptionsdialog.py:220
msgid "Sound preferences info"

View file

@ -130,6 +130,7 @@ class PysolMenubarActions:
statusbar = BooleanVar(),
num_cards = BooleanVar(),
helpbar = BooleanVar(),
save_games_geometry = BooleanVar(),
splashscreen = BooleanVar(),
demo_logo = BooleanVar(),
sticky_mouse = BooleanVar(),
@ -180,6 +181,7 @@ class PysolMenubarActions:
tkopt.statusbar.set(opt.statusbar)
tkopt.num_cards.set(opt.num_cards)
tkopt.helpbar.set(opt.helpbar)
tkopt.save_games_geometry.set(opt.save_games_geometry)
tkopt.demo_logo.set(opt.demo_logo)
tkopt.splashscreen.set(opt.splashscreen)
tkopt.sticky_mouse.set(opt.sticky_mouse)
@ -743,19 +745,19 @@ class PysolMenubarActions:
if self._cancelDrag(): return
if self.app.opt.hint:
if self.game.showHint(0, self.app.opt.hint_sleep):
self.game.stats.hints = self.game.stats.hints + 1
self.game.stats.hints += 1
def mHint1(self, *args):
if self._cancelDrag(): return
if self.app.opt.hint:
if self.game.showHint(1, self.app.opt.hint_sleep):
self.game.stats.hints = self.game.stats.hints + 1
self.game.stats.hints += 1
def mHighlightPiles(self, *args):
if self._cancelDrag(): return
if self.app.opt.highlight_piles:
if self.game.highlightPiles(self.app.opt.highlight_piles_sleep):
self.game.stats.highlight_piles = self.game.stats.highlight_piles + 1
self.game.stats.highlight_piles += 1
def mDemo(self, *args):
if self._cancelDrag(): return

View file

@ -129,14 +129,14 @@ class Options:
'autopilotlost' : True,
'autopilotwon' : True,
'deal' : True,
'deal01' : True,
'deal02' : True,
'deal04' : True,
'deal08' : True,
#'deal01' : True,
#'deal02' : True,
#'deal04' : True,
#'deal08' : True,
'dealwaste' : True,
'droppair' : True,
'drop' : True,
'extra' : True,
#'extra' : True,
'flip' : True,
'move' : True,
'nomove' : True,
@ -184,6 +184,7 @@ class Options:
self.highlight_cards_sleep = 1.0
self.highlight_samerank_sleep = 1.0
# additional startup information
self.num_recent_games = 15
self.recent_gameid = []
self.favorite_gameid = []
self.last_gameid = 0 # last game played
@ -191,6 +192,8 @@ class Options:
#self.last_save_dir = None # last directory for load/save
self.game_holded = 0
self.wm_maximized = 0
self.save_games_geometry = False
self.games_geometry = {} # saved games geometry (gameid: (width, height))
#
self.splashscreen = True
self.sticky_mouse = False
@ -668,7 +671,13 @@ class Application:
self.game._saveGame(self.fn.holdgame)
self.opt.game_holded = self.game.id
except:
traceback.print_exc()
pass
# save game geometry
self.wm_save_state()
if self.opt.save_games_geometry and not self.opt.wm_maximized:
geom = (self.canvas.winfo_width(), self.canvas.winfo_height())
self.opt.games_geometry[self.game.id] = geom
self.freeGame()
#
if self.nextgame.id <= 0:
@ -681,35 +690,25 @@ class Application:
finally:
# update options
self.opt.last_gameid = id
## if self.debug:
## self.wm_save_state()
## # save options
## self.saveOptions()
## # save statistics
## self.saveStatistics()
## # save comments
## self.saveComments()
## # shut down audio
## self.audio.destroy()
## else:
try: self.wm_save_state()
except:
pass
# save options
try: self.saveOptions()
except:
traceback.print_exc()
pass
# save statistics
try: self.saveStatistics()
except:
traceback.print_exc()
pass
# save comments
try: self.saveComments()
except:
traceback.print_exc()
pass
# shut down audio
try: self.audio.destroy()
except:
traceback.print_exc()
pass
@ -741,7 +740,7 @@ class Application:
if id in self.opt.recent_gameid:
self.opt.recent_gameid.remove(id)
self.opt.recent_gameid.insert(0, id)
del self.opt.recent_gameid[15:]
del self.opt.recent_gameid[self.opt.num_recent_games:]
self.menubar.updateRecentGamesMenu(self.opt.recent_gameid)
self.menubar.updateFavoriteGamesMenu()
# delete intro progress bar
@ -789,7 +788,6 @@ class Application:
self.toolbar.connectGame(None, None)
self.menubar.connectGame(None)
# clean up the canvas
unbind_destroy(self.canvas)
self.canvas.deleteAllItems()
self.canvas.update_idletasks()
# destruct the game
@ -808,7 +806,7 @@ class Application:
if self.top:
s = self.top.wm_state()
##print "wm_save_state", s
if s == "zoomed":
if s == "zoomed": # Windows only
self.opt.wm_maximized = 1
elif s == "normal":
self.opt.wm_maximized = 0
@ -842,7 +840,7 @@ class Application:
for f in ("demo01", "demo02", "demo03", "demo04", "demo05",):
self.gimages.demo.append(self.dataloader.findImage(f, dir))
dir = os.path.join("images", "pause")
for f in ("pause01", "pause02",):
for f in ("pause01", "pause02", "pause03",):
self.gimages.pause.append(self.dataloader.findImage(f, dir))
##dir = os.path.join("images", "stats")
##for f in ("barchart",):
@ -950,8 +948,7 @@ class Application:
self.opt.cardset[gi.category] = (cs.name, cs.backname)
if update & 8:
self.opt.cardset[(1, gi.id)] = (cs.name, cs.backname)
#from pprint import pprint
#pprint(self.opt.cardset)
#from pprint import pprint; pprint(self.opt.cardset)
def loadCardset(self, cs, id=0, update=7, progress=None):
#print 'loadCardset', cs.ident
@ -1146,8 +1143,7 @@ Please select a %s type %s.
return
opt = unpickle(self.fn.opt)
if opt:
##import pprint
##pprint.pprint(opt.__dict__)
##import pprint; pprint.pprint(opt.__dict__)
#cardset = self.opt.cardset
#cardset.update(opt.cardset)
self.opt.__dict__.update(opt.__dict__)

View file

@ -184,12 +184,18 @@ class Game:
if not self.cards:
self.cards = self.createCards(progress=self.app.intro.progress)
self.initBindings()
self.top.bind('<ButtonPress>', self.top._sleepEvent)
self.top.bind('<3>', self.top._sleepEvent)
##self.top.bind('<ButtonPress>', self.top._sleepEvent)
##self.top.bind('<3>', self.top._sleepEvent)
##print timer
# update display properties
self.top.wm_geometry("") # cancel user-specified geometry
self.canvas.setInitialSize(self.width, self.height)
# restore game geometry
if self.app.opt.save_games_geometry:
w, h = self.app.opt.games_geometry.get(self.id, (0, 0))
w, h = max(w, self.width), max(h, self.height)
self.canvas.config(width=w, height=h)
#
self.stats.update_time = time.time()
self.busy = old_busy
##print timer
@ -784,7 +790,8 @@ class Game:
#
def playSample(self, name, priority=0, loop=0):
if not self.app.opt.sound_samples[name]:
if self.app.opt.sound_samples.has_key(name) and \
not self.app.opt.sound_samples[name]:
return 0
##print "playSample:", name, priority, loop
if self.app.audio:

View file

@ -57,3 +57,4 @@ import unionsquare
import wavemotion
import windmill
import yukon
import zodiac

View file

@ -187,22 +187,25 @@ class Dover_RowStack(RK_RowStack):
class Dover(Bristol):
Talon_Class = Bristol_Talon
Foundation_Class = SS_FoundationStack
RowStack_Class = Dover_RowStack
Foundation_Class = StackWrapper(SS_FoundationStack, max_move=0)
RowStack_Class = StackWrapper(Dover_RowStack, base_rank=NO_RANK, max_move=1)
ReserveStack_Class = StackWrapper(ReserveStack, max_accept=0, max_cards=UNLIMITED_CARDS)
def createGame(self, text=False):
def createGame(self, rows=8, text=False):
# create layout
l, s = Layout(self), self.s
# set window
self.setSize(2*l.XM+9*l.XS, l.YM+20+5*l.YS)
max_rows = max(rows, self.gameinfo.decks*4)
w, h = 2*l.XM+l.XS+max_rows*l.XS, l.YM+20+5*l.YS
self.setSize(w, h)
# create stacks
x, y, = l.XM+l.XM+l.XS, l.YM
for i in range(8):
s.foundations.append(self.Foundation_Class(x, y, self, suit=i/2, max_move=0))
x += l.XS
x, y, = 2*l.XM+l.XS+l.XS*(max_rows-self.gameinfo.decks*4), l.YM
for j in range(self.gameinfo.decks):
for i in range(4):
s.foundations.append(self.Foundation_Class(x, y, self, suit=i))
x += l.XS
if text:
x, y = l.XM+8*l.XS, l.YM
tx, ty, ta, tf = l.getTextAttr(None, "s")
@ -210,12 +213,12 @@ class Dover(Bristol):
font = self.app.getFont("canvas_default")
self.texts.info = MfxCanvasText(self.canvas, tx, ty, anchor=ta, font=font)
x, y = l.XM+l.XM, l.YM+l.YS
x, y = 2*l.XM+(max_rows-rows)*l.XS, l.YM+l.YS
if text:
y += 20
for i in range(8):
for i in range(rows):
x += l.XS
stack = self.RowStack_Class(x, y, self, base_rank=NO_RANK, max_move=1)
stack = self.RowStack_Class(x, y, self)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, l.YOFFSET
s.rows.append(stack)
x, y, = l.XM, l.YM
@ -262,9 +265,9 @@ class NewYork_RowStack(AC_RowStack):
class NewYork(Dover):
Foundation_Class = StackWrapper(SS_FoundationStack, mod=13)
Foundation_Class = StackWrapper(SS_FoundationStack, mod=13, max_move=0)
Talon_Class = NewYork_Talon
RowStack_Class = StackWrapper(NewYork_RowStack, base_rank=ANY_RANK, mod=13)
RowStack_Class = StackWrapper(NewYork_RowStack, base_rank=ANY_RANK, mod=13, max_move=1)
ReserveStack_Class = StackWrapper(NewYork_ReserveStack, max_accept=1, max_cards=UNLIMITED_CARDS, mod=13)
def createGame(self):
@ -315,6 +318,30 @@ class NewYork(Dover):
p.dump(self.base_card.id)
# /***********************************************************************
# // Spike
# ************************************************************************/
class Spike(Dover):
Foundation_Class = SS_FoundationStack
RowStack_Class = KingAC_RowStack
def createGame(self):
Dover.createGame(self, rows=7)
def startGame(self):
for i in range(1, 7):
self.s.talon.dealRow(rows=self.s.rows[i:], flip=0, frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealCards()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.color != card2.color and
abs(card1.rank-card2.rank) == 1)
# register the game
registerGame(GameInfo(42, Bristol, "Bristol",
GI.GT_FAN_TYPE, 1, 0))
@ -324,4 +351,6 @@ registerGame(GameInfo(266, Dover, "Dover",
GI.GT_FAN_TYPE, 2, 0))
registerGame(GameInfo(425, NewYork, "New York",
GI.GT_FAN_TYPE, 2, 0))
registerGame(GameInfo(468, Spike, "Spike",
GI.GT_KLONDIKE, 1, 0))

View file

@ -325,6 +325,8 @@ class LexingtonHarp(MilliganHarp):
GAME_VERSION = 2
RowStack_Class = Yukon_AC_RowStack
Hint_Class = YukonType_Hint
def getHighlightPilesStacks(self):
return ()
class Brunswick(LexingtonHarp):
@ -344,6 +346,7 @@ class Griffon(Mississippi):
# /***********************************************************************
# // Blockade
# // Phantom Blockade
# ************************************************************************/
class Blockade(Gypsy):
@ -364,6 +367,24 @@ class Blockade(Gypsy):
self.s.talon.moveMove(1, stack)
self.leaveState(old_state)
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and
abs(card1.rank-card2.rank) == 1)
class PhantomBlockade(Gypsy):
Layout_Method = Layout.klondikeLayout
RowStack_Class = KingAC_RowStack
def createGame(self):
Gypsy.createGame(self, rows=13, playcards=24)
def startGame(self):
self.s.talon.dealRow(frames=0)
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
# /***********************************************************************
# // Cone
@ -507,4 +528,6 @@ registerGame(GameInfo(412, Cone, "Cone",
GI.GT_GYPSY, 2, 0))
registerGame(GameInfo(463, Surprise, "Surprise",
GI.GT_GYPSY, 2, 0))
registerGame(GameInfo(469, PhantomBlockade, "Phantom Blockade",
GI.GT_GYPSY, 2, 0))

View file

@ -950,6 +950,27 @@ class SevenDevils(Klondike):
self.s.talon.dealRow(rows=self.s.reserves)
# /***********************************************************************
# // Moving Left
# ************************************************************************/
class MovingLeft(Klondike):
def createGame(self):
Klondike.createGame(self, max_rounds=1, rows=10, playcards=24)
def fillStack(self, stack):
if not stack.cards:
old_state = self.enterState(self.S_FILL)
if stack in self.s.rows:
i = list(self.s.rows).index(stack)
if i < 9:
from_stack = self.s.rows[i+1]
pile = from_stack.getPile()
if pile:
from_stack.moveMove(len(pile), stack)
self.leaveState(old_state)
# register the game
registerGame(GameInfo(2, Klondike, "Klondike",
@ -1042,4 +1063,6 @@ registerGame(GameInfo(452, DoubleEasthaven, "Double Easthaven",
GI.GT_GYPSY, 2, 0))
registerGame(GameInfo(453, TripleEasthaven, "Triple Easthaven",
GI.GT_GYPSY, 3, 0))
registerGame(GameInfo(470, MovingLeft, "Moving Left",
GI.GT_KLONDIKE, 2, 0))

View file

@ -640,6 +640,9 @@ class Chelicera(Game):
for i in range(3):
self.s.talon.dealRow(rows=self.s.rows[4:])
def getHighlightPilesStacks(self):
return ()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1
@ -793,6 +796,9 @@ class Applegate(Game):
return False
return True
def getHighlightPilesStacks(self):
return ()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and
((card1.rank + 1) % stack1.cap.mod == card2.rank or

View file

@ -347,21 +347,31 @@ Diamond: 4 8 Q 3 7 J 2 6 T A 5 9 K'''))
# /***********************************************************************
# // Double Yukon
# // Double Russian Solitaire
# ************************************************************************/
class DoubleYukon(Yukon):
def createGame(self):
Yukon.createGame(self, rows=10)
def startGame(self):
for i in range(1, len(self.s.rows)):
for i in range(1, len(self.s.rows)-1):
self.s.talon.dealRow(rows=self.s.rows[i:], flip=0, frames=0)
#self.s.talon.dealRow(rows=self.s.rows, flip=0, frames=0)
for i in range(5):
self.s.talon.dealRow(rows=self.s.rows, flip=1, frames=0)
self.s.talon.dealRow(flip=1, frames=0)
self.startDealSample()
self.s.talon.dealRow(rows=self.s.rows[:-1])
self.s.talon.dealRow()
assert len(self.s.talon.cards) == 0
class DoubleRussianSolitaire(DoubleYukon):
RowStack_Class = StackWrapper(Yukon_SS_RowStack, base_rank=KING)
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and
(card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank))
# /***********************************************************************
# // Triple Yukon
# ************************************************************************/
@ -543,3 +553,5 @@ registerGame(GameInfo(450, RawPrawn, "Raw Prawn",
GI.GT_YUKON, 1, 0))
registerGame(GameInfo(456, BimBom, "Bim Bom",
GI.GT_YUKON | GI.GT_ORIGINAL, 2, 0))
registerGame(GameInfo(466, DoubleRussianSolitaire, "Double Russian Solitaire",
GI.GT_YUKON | GI.GT_ORIGINAL, 2, 0))

126
pysollib/games/zodiac.py Normal file
View file

@ -0,0 +1,126 @@
##---------------------------------------------------------------------------##
##
## PySol -- a Python Solitaire game
##
## 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
import sys
# PySol imports
from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.util import *
from pysollib.mfxutil import kwdefault
from pysollib.stack import *
from pysollib.game import Game
from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
# /***********************************************************************
# // Zodiac
# ************************************************************************/
class Zodiac_Foundation(SS_FoundationStack):
def acceptsCards(self, from_stack, cards):
if not SS_FoundationStack.acceptsCards(self, from_stack, cards):
return False
if self.game.s.waste.cards or self.game.s.talon.cards:
return False
return True
class Zodiac_RowStack(UD_SS_RowStack):
def acceptsCards(self, from_stack, cards):
if not UD_SS_RowStack.acceptsCards(self, from_stack, cards):
return False
if from_stack in self.game.s.rows:
return False
return True
class Zodiac_ReserveStack(ReserveStack):
def acceptsCards(self, from_stack, cards):
if not ReserveStack.acceptsCards(self, from_stack, cards):
return False
if from_stack in self.game.s.rows:
return False
return True
class Zodiac(Game):
def createGame(self):
# create layout
l, s = Layout(self), self.s
# set window
w, h = l.XM+12*l.XS, l.YM+5*l.YS
self.setSize(w, h)
# create stacks
x = l.XM
for i in range(12):
for y in (l.YM, l.YM+4*l.YS):
stack = Zodiac_RowStack(x, y, self, base_rank=NO_RANK)
s.rows.append(stack)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
x += l.XS
x = l.XM+4*l.XS
for i in range(4):
y = l.YM+l.YS
s.foundations.append(Zodiac_Foundation(x, y, self, suit=i))
y += 2*l.YS
s.foundations.append(Zodiac_Foundation(x, y, self, suit=i,
base_rank=KING, dir=-1))
x += l.XS
x, y = l.XM+2*l.XS, l.YM+2*l.YS
for i in range(8):
s.reserves.append(Zodiac_ReserveStack(x, y, self))
x += l.XS
x, y = l.XM+l.XS, l.YM+l.YS
s.talon = WasteTalonStack(x, y, self,
max_rounds=UNLIMITED_REDEALS)
l.createText(s.talon, 'sw')
x += l.XS
s.waste = WasteStack(x, y, self)
l.createText(s.waste, 'se')
# define stack-groups
l.defaultStackGroups()
def startGame(self):
self.startDealSample()
self.s.talon.dealRow(rows=self.s.reserves)
self.s.talon.dealRow()
self.s.talon.dealCards()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1
# register the game
registerGame(GameInfo(467, Zodiac, "Zodiac",
GI.GT_2DECK_TYPE, 2, -1))

View file

@ -338,7 +338,7 @@ class PysolMenubar(PysolMenubarActions):
submenu.add_checkbutton(label=n_("Show removed tiles (in Mahjongg games)"), variable=self.tkopt.mahjongg_show_removed, command=self.mOptMahjonggShowRemoved)
submenu.add_checkbutton(label=n_("Show hint arrow (in Shisen-Sho games)"), variable=self.tkopt.shisen_show_hint, command=self.mOptShisenShowHint)
menu.add_separator()
label = n_("&Sound")
label = n_("&Sound...")
if self.app.audio.audiodev is None:
menu.add_checkbutton(label=label, variable=self.tkopt.sound, command=self.mOptSoundDialog, state=Tkinter.DISABLED)
else:
@ -372,6 +372,7 @@ class PysolMenubar(PysolMenubarActions):
submenu.add_checkbutton(label=n_("Show &statusbar"), variable=self.tkopt.statusbar, command=self.mOptStatusbar)
submenu.add_checkbutton(label=n_("Show &number of cards"), variable=self.tkopt.num_cards, command=self.mOptNumCards)
submenu.add_checkbutton(label=n_("Show &help bar"), variable=self.tkopt.helpbar, command=self.mOptHelpbar)
menu.add_checkbutton(label=n_("Save games &geometry"), variable=self.tkopt.save_games_geometry, command=self.mOptSaveGamesGeometry)
menu.add_checkbutton(label=n_("&Demo logo"), variable=self.tkopt.demo_logo, command=self.mOptDemoLogo)
menu.add_checkbutton(label=n_("Startup splash sc&reen"), variable=self.tkopt.splashscreen, command=self.mOptSplashscreen)
### menu.add_separator()
@ -866,6 +867,7 @@ class PysolMenubar(PysolMenubarActions):
self._cancelDrag()
self.game.endGame(bookmark=1)
self.game.quitGame(bookmark=1)
self.app.opt.games_geometry = {} # clear saved games geometry
def _mOptCardback(self, index):
if self._cancelDrag(break_pause=False): return
@ -958,7 +960,8 @@ class PysolMenubar(PysolMenubarActions):
if not self.app.statusbar: return
side = self.tkopt.statusbar.get()
self.app.opt.statusbar = side
if self.app.statusbar.show(side):
resize = not self.app.opt.save_games_geometry
if self.app.statusbar.show(side, resize=resize):
self.top.update_idletasks()
def mOptNumCards(self, *event):
@ -970,9 +973,14 @@ class PysolMenubar(PysolMenubarActions):
if not self.app.helpbar: return
show = self.tkopt.helpbar.get()
self.app.opt.helpbar = show
if self.app.helpbar.show(show):
resize = not self.app.opt.save_games_geometry
if self.app.helpbar.show(show, resize=resize):
self.top.update_idletasks()
def mOptSaveGamesGeometry(self, *event):
if self._cancelDrag(break_pause=False): return
self.app.opt.save_games_geometry = self.tkopt.save_games_geometry.get()
def mOptDemoLogo(self, *event):
if self._cancelDrag(break_pause=False): return
self.app.opt.demo_logo = self.tkopt.demo_logo.get()
@ -1002,7 +1010,8 @@ class PysolMenubar(PysolMenubarActions):
if self._cancelDrag(break_pause=False): return
self.app.opt.toolbar = side
self.tkopt.toolbar.set(side) # update radiobutton
if self.app.toolbar.show(side):
resize = not self.app.opt.save_games_geometry
if self.app.toolbar.show(side, resize=resize):
self.top.update_idletasks()
def setToolbarSize(self, size):

View file

@ -74,31 +74,33 @@ class SoundOptionsDialog(MfxDialog):
self.music_volume = IntVar()
self.music_volume.set(app.opt.sound_music_volume)
self.samples = [
('areyousure', 'AreYouSure', BooleanVar()),
('autodrop', 'AutoDrop', BooleanVar()),
('autoflip', 'AutoFlip', BooleanVar()),
('autopilotlost', 'AutopilotLost', BooleanVar()),
('autopilotwon', 'AutopilotWon', BooleanVar()),
('deal', 'Deal', BooleanVar()),
#('deal01', 'Deal01', BooleanVar()),
#('deal02', 'Deal02', BooleanVar()),
#('deal04', 'Deal04', BooleanVar()),
#('deal08', 'Deal08', BooleanVar()),
('dealwaste', 'DealWaste', BooleanVar()),
('droppair', 'DropPair', BooleanVar()),
('drop', 'Drop', BooleanVar()),
#('extra', 'Extra', BooleanVar()),
('flip', 'Flip', BooleanVar()),
('move', 'Move', BooleanVar()),
('nomove', 'NoMove', BooleanVar()),
('redo', 'Redo', BooleanVar()),
('startdrag', 'StartDrag', BooleanVar()),
('turnwaste', 'TurnWaste', BooleanVar()),
('undo', 'Undo', BooleanVar()),
('gamefinished', 'GameFinished', BooleanVar()),
('gamelost', 'GameLost', BooleanVar()),
('gameperfect', 'GamePerfect', BooleanVar()),
('gamewon', 'GameWon', BooleanVar()),
('areyousure', _('Are You Sure'), BooleanVar()),
('deal', _('Deal'), BooleanVar()),
('dealwaste', _('Deal waste'), BooleanVar()),
('turnwaste', _('Turn waste'), BooleanVar()),
('startdrag', _('Start drag'), BooleanVar()),
('drop', _('Drop'), BooleanVar()),
('droppair', _('Drop pair'), BooleanVar()),
('autodrop', _('Auto drop'), BooleanVar()),
('flip', _('Flip'), BooleanVar()),
('autoflip', _('Auto flip'), BooleanVar()),
('move', _('Move'), BooleanVar()),
('nomove', _('No move'), BooleanVar()),
('undo', _('Undo'), BooleanVar()),
('redo', _('Redo'), BooleanVar()),
('autopilotlost', _('Autopilot lost'), BooleanVar()),
('autopilotwon', _('Autopilot won'), BooleanVar()),
('gamefinished', _('Game finished'), BooleanVar()),
('gamelost', _('Game lost'), BooleanVar()),
('gamewon', _('Game won'), BooleanVar()),
('gameperfect', _('Perfect game'), BooleanVar()),
]
#

View file

@ -125,15 +125,15 @@ class tkHTMLWriter(formatter.DumbWriter):
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, "<Leave>", self.anchor_leave)
self.text.tag_config(tag, foreground="blue", underline=1)
fg = 'blue'
u = self.viewer.normurl(url, with_protocol=False)
if u in self.viewer.visited_urls:
fg = '#303080'
self.text.tag_config(tag, foreground=fg, underline=1)
self.anchor = None
def anchor_enter(self, url):
for p in REMOTE_PROTOCOLS:
if url.startswith(p):
break
else:
url = 'file://'+self.viewer.basejoin(url)
url = self.viewer.normurl(url)
self.viewer.statusbar.updateText(url=url)
self.text.config(cursor=self.viewer.handcursor)
@ -219,6 +219,7 @@ class tkHTMLViewer:
list = [],
index = 0,
)
self.visited_urls = []
self.images = {} # need to keep a reference because of garbage collection
self.defcursor = parent["cursor"]
##self.defcursor = 'xterm'
@ -247,7 +248,8 @@ class tkHTMLViewer:
text_frame = Tkinter.Frame(parent)
text_frame.grid(row=1, column=0, columnspan=4, sticky='nsew')
self.text = Tkinter.Text(text_frame,
fg='black', bg='white', bd=0,
fg='black', bg='white',
bd=1, relief='sunken',
cursor=self.defcursor,
wrap='word', padx=20, pady=20)
self.text.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
@ -287,24 +289,22 @@ class tkHTMLViewer:
except: pass
self.parent = None
def _yview(self, *args):
apply(self.text.yview, args, {})
return 'break'
def page_up(self, *event):
self.text.yview_scroll(-1, "page")
return "break"
return self._yview('scroll', -1, 'page')
def page_down(self, *event):
self.text.yview_scroll(1, "page")
return "break"
return self._yview('scroll', 1, 'page')
def unit_up(self, *event):
self.text.yview_scroll(-1, "unit")
return "break"
return self._yview('scroll', -1, 'unit')
def unit_down(self, *event):
self.text.yview_scroll(1, "unit")
return "break"
return self._yview('scroll', 1, 'unit')
def scroll_top(self, *event):
self.text.yview_moveto(0)
return "break"
return self._yview('moveto', 0)
def scroll_bottom(self, *event):
self.text.yview_moveto(1)
return "break"
return self._yview('moveto', 1)
# locate a file relative to the current self.url
def basejoin(self, url, baseurl=None, relpath=1):
@ -325,6 +325,18 @@ class tkHTMLViewer:
url = os.path.normpath(url)
return url
def normurl(self, url, with_protocol=True):
for p in REMOTE_PROTOCOLS:
if url.startswith(p):
break
else:
url = self.basejoin(url)
if with_protocol:
if os.name == 'nt':
url = url.replace('\\', '/')
url = 'file://'+url
return url
def openfile(self, url):
if url[-1:] == "/" or os.path.isdir(url):
url = os.path.join(url, "index.html")
@ -338,6 +350,7 @@ class tkHTMLViewer:
if self.app and self.app.game:
self.app.game.stopDemo()
##self.app.game._cancelDrag()
##pass
# ftp: and http: would work if we use urllib, but this widget is
# far too limited to display anything but our documentation...
@ -418,6 +431,8 @@ to open the following URL:
##self.frame.config(cursor=self.defcursor)
def addHistory(self, url, xview=0, yview=0):
if not url in self.visited_urls:
self.visited_urls.append(url)
if self.history.index > 0:
u, xv, yv = self.history.list[self.history.index-1]
if cmp(u, url) == 0:

View file

@ -38,7 +38,7 @@ import os, string, types
import Tkinter
# Toolkit imports
from tkutil import bind, unbind_destroy
from tkutil import bind
from tkwidget import MfxScrolledCanvas
@ -244,6 +244,7 @@ class MfxTreeInCanvas(MfxScrolledCanvas):
def __init__(self, parent, rootnodes, **kw):
bg = kw["bg"] = kw.get("bg") or parent.cget("bg")
kw['bd'] = 0
apply(MfxScrolledCanvas.__init__, (self, parent,), kw)
#
self.rootnodes = rootnodes

View file

@ -420,7 +420,7 @@ class MfxTooltip:
class MfxScrolledCanvas:
def __init__(self, parent, hbar=2, vbar=2, **kw):
bg = kw.get("bg", parent.cget("bg"))
kwdefault(kw, bg=bg, highlightthickness=0)
kwdefault(kw, bg=bg, highlightthickness=0, bd=1, relief='sunken')
self.parent = parent
self.createFrame(kw)
self.canvas = None
@ -629,41 +629,36 @@ class MfxScrolledCanvas:
self.vbar_show = show
return 1
def _xview(self, *args):
if self.hbar_show: apply(self.canvas.xview, args, {})
return 'break'
def _yview(self, *args):
if self.vbar_show: apply(self.canvas.yview, args, {})
return 'break'
def page_up(self, *event):
self.canvas.yview_scroll(-1, "page")
return "break"
return self._yview('scroll', -1, 'page')
def page_down(self, *event):
self.canvas.yview_scroll(1, "page")
return "break"
return self._yview('scroll', 1, 'page')
def unit_up(self, *event):
self.canvas.yview_scroll(-1, "unit")
return "break"
return self._yview('scroll', -1, 'unit')
def unit_down(self, *event):
self.canvas.yview_scroll(1, "unit")
return "break"
return self._yview('scroll', 1, 'unit')
def mouse_wheel_up(self, *event):
self.canvas.yview_scroll(-5, "unit")
return "break"
return self._yview('scroll', -5, 'unit')
def mouse_wheel_down(self, *event):
self.canvas.yview_scroll(5, "unit")
return "break"
return self._yview('scroll', 5, 'unit')
def page_left(self, *event):
self.canvas.xview_scroll(-1, "page")
return "break"
return self._xview('scroll', -1, 'page')
def page_right(self, *event):
self.canvas.xview_scroll(1, "page")
return "break"
return self._xview('scroll', 1, 'page')
def unit_left(self, *event):
self.canvas.xview_scroll(-1, "unit")
return "break"
return self._xview('scroll', -1, 'unit')
def unit_right(self, *event):
self.canvas.xview_scroll(1, "unit")
return "break"
return self._xview('scroll', 1, 'unit')
def scroll_top(self, *event):
self.canvas.yview_moveto(0)
return "break"
return self._yview('moveto', 0)
def scroll_bottom(self, *event):
self.canvas.yview_moveto(1)
return "break"
return self._yview('moveto', 1)