Primitivus: Tarot card game implementation

- quick frontend: card_game added
- wix: card_game splitted with quick frontend
- tools: new game library
- primitivus: new card_game widget (not finished yet)
- primitivus: SàT XML UI management: first draft
This commit is contained in:
Goffi 2010-07-26 19:43:44 +08:00
commit 3d5c5ada3c
9 changed files with 557 additions and 105 deletions

View file

@ -0,0 +1,149 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Primitivus: a SAT frontend
Copyright (C) 2009, 2010 Jérôme Poisson (goffi@goffi.org)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import urwid
from tools.games import TarotCard
from quick_frontend.quick_card_game import QuickCardGame
from xmlui import XMLUI
class Hand(urwid.WidgetWrap):
"""Used to display several cards, and manage a hand"""
def __init__(self):
self.columns = urwid.Columns([])
urwid.WidgetWrap.__init__(self, self.columns)
def update(self, hand):
"""Update the hand displayed in this widget"""
del self.columns.widget_list[:]
del self.columns.column_types[:]
for card in hand:
self.columns.widget_list.append(urwid.Text(card.getAttrText()))
self.columns.column_types.append(('weight',1))
class Card(TarotCard):
"""This class is used to represent a card, logically
and give a text representation with attributes"""
def __init__(self, suit, value):
"""@param file: path of the PNG file"""
TarotCard.__init__(self, (suit, value))
def getAttrText(self):
"""return text representation of the card with attributes"""
try:
value = "%02i" % int(self.value)
except ValueError:
value = self.value[0].upper()+self.value[1]
if self.suit == "atout":
if self.value == "excuse":
suit = 'c'
else:
suit = 'A'
color = 'neutral'
elif self.suit == "pique":
suit = u'♠'
color = 'black'
elif self.suit == "trefle":
suit = u'♣'
color = 'black'
elif self.suit == "coeur":
suit = u'♥'
color = 'red'
elif self.suit == "carreau":
suit = u'♦'
color = 'red'
if self.bout:
color = 'special'
return ('card_%s' % color,u"%s%s" % (value,suit))
class CardGame(QuickCardGame,urwid.WidgetWrap):
"""Widget for card games"""
def __init__(self, parent, referee, players, player_nick):
QuickCardGame.__init__(self, parent, referee, players, player_nick)
self.loadCards()
self.top = urwid.Pile([urwid.Padding(urwid.Text(self.top_nick), 'center')])
self.top_card_wid = urwid.Text('')
self.center_cards_wid = urwid.Text(' - ')
self.bottom_card_wid = urwid.Text('')
center = urwid.Pile([urwid.Padding(self.top_card_wid,'center'),
urwid.Columns([('fixed',len(self.left_nick),urwid.Text(self.left_nick)),
urwid.Padding(self.center_cards_wid,'center'),
('fixed',len(self.right_nick),urwid.Text(self.right_nick))
]),
urwid.Padding(self.bottom_card_wid,'center')
])
body = urwid.Filler(center)
self.hand_wid = Hand()
self.main_frame = urwid.Frame(body,header=self.top, footer=self.hand_wid)
urwid.WidgetWrap.__init__(self,self.main_frame)
self.parent.host.bridge.tarotGameReady(player_nick, referee, profile_key = self.parent.host.profile)
def loadCards(self):
"""Load all the cards in memory"""
QuickCardGame.loadCards(self)
for value in map(str,range(1,22))+['excuse']:
card = Card('atout',value)
self.cards[card.suit, card.value]=card
self.deck.append(card)
for suit in ["pique", "coeur", "carreau", "trefle"]:
for value in map(str,range(1,11))+["valet","cavalier","dame","roi"]:
card = Card(suit,value)
self.cards[card.suit, card.value]=card
self.deck.append(card)
def newGame(self, hand):
"""Start a new game, with given hand"""
QuickCardGame.newGame(self, hand)
self.hand_wid.update(self.hand)
self.parent.host.redraw()
def contratSelected(self, data):
"""Called when the contrat has been choosed
@param data: form result"""
contrat = data[0][1]
QuickCardGame.contratSelected(self, contrat)
def chooseContrat(self, xml_data):
"""Called when the player as to select his contrat
@param xml_data: SàT xml representation of the form"""
misc = {'callback': self.contratSelected}
form = XMLUI(self.parent.host, xml_data, title = _('Please choose your contrat'), options = ['NO_CANCEL'], misc = misc)
form.show()
"""def selectable(self):
return True
def keypress(self, size, key):
return key
def render(self, size, focus=False):
return self.display_widget(size, focus).render(size, focus)
def display_widget(self, size, focus):
(maxcol,maxrow) = size
return self.main_frame"""

View file

@ -25,6 +25,7 @@ from quick_frontend.quick_chat import QuickChat
import custom_widgets
import time
from tools.jid import JID
from card_game import CardGame
class ChatText(urwid.FlowWidget):
@ -79,8 +80,10 @@ class Chat(urwid.WidgetWrap, QuickChat):
self.content = urwid.SimpleListWalker([])
self.text_list = urwid.ListBox(self.content)
self.chat_widget = urwid.Frame(self.text_list)
self.columns = urwid.Columns([('weight', 8, self.chat_widget)])
urwid.WidgetWrap.__init__(self, self.__getDecoration(self.columns))
self.chat_colums = urwid.Columns([('weight', 8, self.chat_widget)])
self.chat_colums = urwid.Columns([('weight', 8, self.chat_widget)])
self.pile = urwid.Pile([self.chat_colums])
urwid.WidgetWrap.__init__(self, self.__getDecoration(self.pile))
self.setType(type)
self.day_change = time.strptime(time.strftime("%a %b %d 00:00:00 %Y")) #struct_time of day changing time
self.show_timestamp = True
@ -91,7 +94,7 @@ class Chat(urwid.WidgetWrap, QuickChat):
def keypress(self, size, key):
if key == "meta p": #user wants to (un)hide the presents panel
if self.type == 'group':
widgets = self.columns.widget_list
widgets = self.chat_colums.widget_list
if self.present_panel in widgets:
self.__removePresentPanel()
else:
@ -135,7 +138,7 @@ class Chat(urwid.WidgetWrap, QuickChat):
if type == 'one2one':
self.historyPrint(profile=self.host.profile)
elif type == 'group':
if len(self.columns.widget_list) == 1:
if len(self.chat_colums.widget_list) == 1:
present_widget = self.__buildPresentList()
self.present_panel = custom_widgets.VerticalSeparator(present_widget)
self.__appendPresentPanel()
@ -144,10 +147,11 @@ class Chat(urwid.WidgetWrap, QuickChat):
return custom_widgets.LabelLine(widget, custom_widgets.SurroundedText(unicode(self.target)))
def showDecoration(self, show=True):
"""Show/Hide the decoration around the chat window"""
if show:
main_widget = self.__getDecoration(self.columns)
main_widget = self.__getDecoration(self.pile)
else:
main_widget = self.columns
main_widget = self.pile
self._w = main_widget
@ -156,13 +160,28 @@ class Chat(urwid.WidgetWrap, QuickChat):
return self.present_wid
def __appendPresentPanel(self):
self.columns.widget_list.append(self.present_panel)
self.columns.column_types.append(('weight', 2))
self.chat_colums.widget_list.append(self.present_panel)
self.chat_colums.column_types.append(('weight', 2))
def __removePresentPanel(self):
self.columns.set_focus(0) #necessary as the focus change to the next object, we can go out of range if we are on the last object of self.columns
self.columns.widget_list.remove(self.present_panel)
del self.columns.column_types[-1]
self.chat_colums.set_focus(0) #necessary as the focus change to the next object, we can go out of range if we are on the last object of self.chat_colums
self.chat_colums.widget_list.remove(self.present_panel)
del self.chat_colums.column_types[-1]
def __appendGamePanel(self, widget):
assert (len(self.pile.widget_list) == 1)
self.pile.widget_list.insert(0,widget)
self.pile.item_types.insert(0,('weight', 1))
self.pile.widget_list.insert(1,urwid.Filler(urwid.Divider('-')))
self.pile.item_types.insert(1,('fixed', 1))
self.host.redraw()
def __removeGamePanel(self):
assert (len(self.pile.widget_list) == 3)
self.pile.set_focus(0) #necessary as the focus change to the next object, we can go out of range if we are on the last object of self.chat_colums
del self.pile.widget_list[0]
del self.pile.item_types[0]
self.host.redraw()
def setSubject(self, subject, wrap='space'):
"""Set title for a group chat"""
@ -209,11 +228,25 @@ class Chat(urwid.WidgetWrap, QuickChat):
self.content.append(ChatText(self, timestamp or None, my_jid, from_jid, msg))
self.text_list.set_focus(len(self.content)-1)
self.host.redraw()
def startGame(self, game_type, referee, players):
"""Configure the chat window to start a game"""
if game_type=="Tarot":
try:
self.tarot_wid = CardGame(self, referee, players, self.nick)
self.__appendGamePanel(self.tarot_wid)
except e:
self.host.debug()
def getGame(self, game_type):
"""Return class managing the game type"""
#TODO: check that the game is launched, and manage errors
if game_type=="Tarot":
return self.tarot_wid
#MENU EVENTS#
def onTarotRequest(self, menu):
if len(self.occupants) != 4:
self.host.debug()
self.host.showPopUp(custom_widgets.Alert(_("Can't start game"), _("You need to be exactly 4 peoples in the room to start a Tarot game"), ok_cb=self.host.removePopUp))
else:
self.host.bridge.tarotGameCreate(self.id, list(self.occupants), self.host.profile)

View file

@ -23,7 +23,6 @@ import urwid
from urwid.escape import utf8decode
class Password(urwid.Edit):
toto=0
"""Edit box which doesn't show what is entered (show '*' or other char instead)"""
def __init__(self, *args, **kwargs):
@ -47,11 +46,6 @@ class Password(urwid.Edit):
super(Password,self).insert_text(text)
def render(self, size, focus=False):
Password.toto+=1
if Password.toto==30:
import os,pdb
os.system('reset')
pdb.set_trace()
return super(Password, self).render(size, focus)
class AdvancedEdit(urwid.Edit):

View file

@ -69,6 +69,14 @@ const_PALETTE = [('title', 'black', 'light gray', 'standout,underline'),
('selected_menu', 'light gray,bold', 'dark green'),
('menuitem', 'light gray,bold', 'dark red'),
('menuitem_focus', 'light gray,bold', 'dark green'),
('card_neutral', 'dark gray', 'white', 'standout,underline'),
('card_neutral_selected', 'dark gray', 'dark green', 'standout,underline'),
('card_special', 'brown', 'white', 'standout,underline'),
('card_special_selected', 'brown', 'dark green', 'standout,underline'),
('card_red', 'dark red', 'white', 'standout,underline'),
('card_red_selected', 'dark red', 'dark green', 'standout,underline'),
('card_black', 'black', 'white', 'standout,underline'),
('card_black_selected', 'black', 'dark green', 'standout,underline'),
]
class ChatList(QuickChatList):
@ -205,7 +213,7 @@ class PrimitivusApp(QuickApp):
if contact:
assert(len(self.center_part.widget_list)==2)
self.center_part.widget_list[1] = self.chat_wins[contact]
self.menu_roller.addMenu(_('Chat Menu'), self.chat_wins[contact].getMenu())
self.menu_roller.addMenu(_('Chat menu'), self.chat_wins[contact].getMenu())
def onTextEntered(self, editBar):
"""Called when text is entered in the main edit bar"""

View file

@ -0,0 +1,196 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Primitivus: a SAT frontend
Copyright (C) 2009, 2010 Jérôme Poisson (goffi@goffi.org)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import urwid
import custom_widgets
from xml.dom import minidom
class Pairs(urwid.WidgetWrap):
def __init__(self, weight_0='1', weight_1='1'):
self.idx = 0
self.weight_0 = weight_0
self.weight_1 = weight_1
columns = urwid.Columns([urwid.Text(''), urwid.Text('')])
#XXX: empty Text hack needed because Pile doesn't support empty list
urwid.WidgetWrap.__init__(self,columns)
def append(self, widget):
pile = self._w.widget_list[self.idx]
if pile.__class__ == urwid.Text:
self._w.widget_list[self.idx] = urwid.Pile([widget])
else:
pile.widget_list.append(widget)
pile.item_types.append(('weight',getattr(self,'weight_'+str(self.idx))))
self.idx = (self.idx + 1) % 2
class XMLUI(urwid.WidgetWrap):
def __init__(self, host, xml_data, title = None, options = [], misc={}):
self.host = host
self.title = title
self.options = options
self.misc = misc
self.ctrl_list = {} # usefull to access ctrl
widget = self.constructUI(xml_data)
urwid.WidgetWrap.__init__(self,widget)
def __parseElems(self, node, parent):
"""Parse elements inside a <layout> tags, and add them to the parent"""
for elem in node.childNodes:
if elem.nodeName != "elem":
message=_("Unmanaged tag")
error(message)
raise Exception(message)
id = elem.getAttribute("id")
name = elem.getAttribute("name")
type = elem.getAttribute("type")
value = elem.getAttribute("value") if elem.hasAttribute('value') else u''
if type=="empty":
ctrl = urwid.Text('')
elif type=="text":
try:
value = elem.childNodes[0].wholeText
except KeyError:
warning (_("text node has no child !"))
ctrl = urwid.Text(value)
elif type=="label":
ctrl = urwid.Text(value+": ")
elif type=="string":
ctrl = urwid.Edit(edit_text = value)
self.ctrl_list[name] = ({'type':type, 'control':ctrl})
elif type=="password":
ctrl = custom_widgets.Password(edit_text = value)
self.ctrl_list[name] = ({'type':type, 'control':ctrl})
elif type=="textbox":
ctrl = urwid.Edit(edit_text = value, multiline=True)
self.ctrl_list[name] = ({'type':type, 'control':ctrl})
elif type=="list":
style=[] if elem.getAttribute("multi")=='yes' else ['single']
ctrl = custom_widgets.List(options=[option.getAttribute("value") for option in elem.getElementsByTagName("option")], style=style)
self.ctrl_list[name] = ({'type':type, 'control':ctrl})
elif type=="button":
callback_id = elem.getAttribute("callback_id")
ctrl = urwid.Button(value, on_press=self.onButtonPress)
ctrl.param_id = (callback_id,[field.getAttribute('name') for field in elem.getElementsByTagName("field_back")])
else:
error(_("FIXME FIXME FIXME: type [%s] is not implemented") % type) #FIXME !
raise NotImplementedError
parent.append(ctrl)
def __parseChilds(self, current, elem, wanted = ['layout']):
"""Recursively parse childNodes of an elemen
@param current: widget container with 'append' method
@param elem: element from which childs will be parsed
@param wanted: list of tag names that can be present in the childs to be SàT XMLUI compliant"""
for node in elem.childNodes:
if wanted and not node.nodeName in wanted:
raise Exception("Invalid XMLUI") #TODO: make a custom exception
if node.nodeName == "layout":
type = node.getAttribute('type')
if type == "tabs":
raise NotImplementedError
self.__parseChilds(current, None, node, ['category'])
else:
if type == "vertical":
pass
elif type == "pairs":
pairs = Pairs()
current.append(pairs)
current = pairs
else:
warning(_("Unknown layout, using default one"))
self.__parseElems(node, current)
elif node.nodeName == "category":
raise NotImplementedError
"""name = node.getAttribute('name')
if not node.nodeName in wanted or not name or not isinstance(parent,wx.Notebook):
raise Exception("Invalid XMLUI") #TODO: make a custom exception
notebook = parent
tab_panel = wx.Panel(notebook, -1)
tab_panel.sizer = wx.BoxSizer(wx.VERTICAL)
tab_panel.SetSizer(tab_panel.sizer)
notebook.AddPage(tab_panel, name)
self.__parseChilds(tab_panel, None, node, ['layout'])"""
else:
message=_("Unknown tag")
error(message)
raise Exception(message) #TODO: raise a custom exception here
def constructUI(self, xml_data):
list_box = urwid.ListBox(urwid.SimpleListWalker([]))
cat_dom = minidom.parseString(xml_data.encode('utf-8'))
top= cat_dom.documentElement
self.type = top.getAttribute("type")
if not self.title:
self.title = top.getAttribute("title") #TODO: manage title
if top.nodeName != "sat_xmlui" or not self.type in ['form', 'param', 'window']:
raise Exception("Invalid XMLUI") #TODO: make a custom exception
self.__parseChilds(list_box.body, cat_dom.documentElement)
if self.type == 'form':
buttons = []
buttons.append(urwid.Button(_('Submit'),self.onFormSubmitted))
if not 'NO_CANCEL' in self.options:
buttons.append(urwid.Button(_('Cancel'),self.onFormCancelled))
max_len = max([len(button.get_label()) for button in buttons])
grid_wid = urwid.GridFlow(buttons,max_len+4,1,0,'center')
list_box.body.append(grid_wid)
return list_box
def show(self):
"""Show the constructed UI"""
decorated = custom_widgets.LabelLine(self, custom_widgets.SurroundedText(self.title or ''))
self.host.showPopUp(decorated)
self.host.redraw()
##EVENTS##
def onButtonPress(self, button):
self.host.debug()
def onFormSubmitted(self, button):
data = []
for ctrl_name in self.ctrl_list:
ctrl = self.ctrl_list[ctrl_name]
if isinstance(ctrl['control'], custom_widgets.List):
data.append((ctrl_name, ctrl['control'].getSelectedValue()))
else:
data.append((ctrl_name, ctrl['control'].get_edit_text()))
if self.misc.has_key('action_back'): #FIXME FIXME FIXME: WTF ! Must be cleaned
raise NotImplementedError
self.host.debug()
elif self.misc.has_key('callback'):
self.misc['callback'](data)
else:
warning (_("The form data is not sent back, the type is not managed properly"))
self.host.removePopUp()
def onFormCancelled(self, button):
self.host.removePopUp()

View file

@ -297,7 +297,7 @@ class QuickApp():
self.chat_wins[room_jid].getGame("Tarot").newGame(hand)
def tarotChooseContrat(self, room_jid, xml_data, profile):
"""Called when the player has too select his contrat"""
"""Called when the player has to select his contrat"""
if not self.check_profile(profile):
return
debug (_("Tarot: need to select a contrat"))

View file

@ -0,0 +1,131 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
helper class for making a SAT frontend
Copyright (C) 2009, 2010 Jérôme Poisson (goffi@goffi.org)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from logging import debug, info, error
from tools.jid import JID
class QuickCardGame():
def __init__(self, parent, referee, players, player_nick):
self.parent = parent
self.referee = referee
self.players = players
self.played = {}
for player in players:
self.played[player] = None
self.player_nick = player_nick
self.bottom_nick = unicode(self.player_nick)
idx = self.players.index(self.player_nick)
idx = (idx + 1) % len(self.players)
self.right_nick = unicode(self.players[idx])
idx = (idx + 1) % len(self.players)
self.top_nick = unicode(self.players[idx])
idx = (idx + 1) % len(self.players)
self.left_nick = unicode(self.players[idx])
self.bottom_nick = unicode(player_nick)
self.selected = [] #Card choosed by the player (e.g. during ecart)
self.hand_size = 13 #number of cards in a hand
self.hand = []
self.to_show = []
self.state = None
def loadCards(self):
"""Load all the cards in memory
@param dir: directory where the PNG files are"""
self.cards={}
self.deck=[]
self.cards["atout"]={} #As Tarot is a french game, it's more handy & logical to keep french names
self.cards["pique"]={} #spade
self.cards["coeur"]={} #heart
self.cards["carreau"]={} #diamond
self.cards["trefle"]={} #club
def newGame(self, hand):
"""Start a new game, with given hand"""
assert (len(self.hand) == 0)
for suit, value in hand:
self.hand.append(self.cards[suit, value])
self.hand.sort()
self.state = "init"
def contratSelected(self, contrat):
"""Called when the contrat has been choosed
@param data: form result"""
self.parent.host.bridge.tarotGameContratChoosed(self.player_nick, self.referee, contrat or 'Passe', self.parent.host.profile)
def chooseContrat(self, xml_data):
"""Called when the player as to select his contrat
@param xml_data: SàT xml representation of the form"""
raise NotImplementedError
def showCards(self, game_stage, cards, data):
"""Display cards in the middle of the game (to show for e.g. chien ou poignée)"""
self.to_show = []
for suit, value in cards:
self.to_show.append(self.cards[suit, value])
if game_stage == "chien" and data['attaquant'] == self.player_nick:
self.state = "wait_for_ecart"
else:
self.state = "chien"
def MyTurn(self):
"""Called when we have to play :)"""
if self.state == "chien":
self.to_show = []
self.state = "play"
def showScores(self, xml_data, winners, loosers):
"""Called when the player as to select hist contrat
@param xml_data: SàT xml representation of the form"""
raise NotImplementedError
def cardsPlayed(self, player, cards):
"""A card has been played by player"""
if self.to_show:
self.to_show = []
pl_cards = []
if self.played[player] != None: #gof: à supprimer
for pl in self.played:
self.played[pl] = None
for suit, value in cards:
pl_cards.append(self.cards[suit, value])
self.played[player] = pl_cards[0]
def invalidCards(self, phase, played_cards, invalid_cards):
"""Invalid cards have been played
@param phase: phase of the game
@param played_cards: all the cards played
@param invalid_cards: cards which are invalid"""
if phase == "play":
self.state = "play"
elif phase == "ecart":
self.state = "ecart"
else:
error ('INTERNAL ERROR: unmanaged game phase')
for suit, value in played_cards:
self.hand.append(self.cards[suit, value])
self.hand.sort()

View file

@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from logging import debug, info, error
from logging import debug, info, warning, error
from tools.jid import JID
@ -92,3 +92,12 @@ class QuickChat():
"""Print message in chat window. Must be implemented by child class"""
raise NotImplementedError
def startGame(self, game_type, referee, players):
"""Configure the chat window to start a game"""
#No need to raise an error as game are not mandatory
warning(_('startGame is not implemented in this frontend'))
def getGame(self, game_type):
"""Return class managing the game type"""
#No need to raise an error as game are not mandatory
warning(_('getGame is not implemented in this frontend'))

View file

@ -27,6 +27,7 @@ import pdb
from logging import debug, info, error
from tools.jid import JID
from tools.games import TarotCard
from quick_frontend.quick_card_game import QuickCardGame
from xmlui import XMLUI
CARD_WIDTH = 74
@ -34,16 +35,16 @@ CARD_HEIGHT = 136
MIN_WIDTH = 950 #Minimum size of the panel
MIN_HEIGHT = 500
class wxCard(TarotCard):
class WxCard(TarotCard):
"""This class is used to represent a card, graphically and logically"""
def __init__(self, file):
"""@param file: path of the PNG file"""
self.bitmap = wx.Image(file).ConvertToBitmap()
root_name = os.path.splitext(os.path.basename(file))[0]
self.suit,self.value=root_name.split('_')
TarotCard.__init__(self, (self.suit, self.value))
print "Carte:",self.suit, self.value #, self.bout
suit,value = root_name.split('_')
TarotCard.__init__(self, (suit, value))
print "Carte:",suit, value #, self.bout
def draw(self, dc, x, y):
"""Draw the card on the device context
@ -53,32 +54,15 @@ class wxCard(TarotCard):
dc.DrawBitmap(self.bitmap, x, y, True)
class CardPanel(wx.Panel):
class CardPanel(QuickCardGame,wx.Panel):
"""This class is used to display the cards"""
def __init__(self, parent, referee, players, player_nick):
QuickCardGame.__init__(self, parent, referee, players, player_nick)
wx.Panel.__init__(self, parent)
self.parent = parent
self.referee = referee
self.players = players
self.played = {}
for player in players:
self.played[player] = None
self.player_nick = player_nick
self.bottom_nick = self.player_nick
idx = self.players.index(self.player_nick)
idx = (idx + 1) % len(self.players)
self.right_nick = self.players[idx]
idx = (idx + 1) % len(self.players)
self.top_nick = self.players[idx]
idx = (idx + 1) % len(self.players)
self.left_nick = self.players[idx]
self.bottom_nick = player_nick
self.SetMinSize(wx.Size(MIN_WIDTH, MIN_HEIGHT))
self.load_cards("/home/goffi/dev/divers/images/cards/")
self.loadCards("/home/goffi/dev/divers/images/cards/")
self.mouse_over_card = None #contain the card to highlight
self.selected = [] #Card choosed by the player (e.g. during ecart)
self.hand_size = 13 #number of cards in a hand
self.visible_size = CARD_WIDTH/2 #number of pixels visible for cards
self.hand = []
self.to_show = []
@ -90,33 +74,18 @@ class CardPanel(wx.Panel):
self.Bind(wx.EVT_LEFT_UP, self.onMouseClick)
self.parent.host.bridge.tarotGameReady(player_nick, referee, profile_key = self.parent.host.profile)
def load_cards(self, dir):
def loadCards(self, dir):
"""Load all the cards in memory
@param dir: directory where the PNG files are"""
self.cards={}
self.deck=[]
self.cards["atout"]={} #As Tarot is a french game, it's more handy & logical to keep french names
self.cards["pique"]={} #spade
self.cards["coeur"]={} #heart
self.cards["carreau"]={} #diamond
self.cards["trefle"]={} #club
QuickCardGame.loadCards(self)
for file in glob.glob(dir+'/*_*.png'):
card = wxCard(file)
card = WxCard(file)
self.cards[card.suit, card.value]=card
self.deck.append(card)
"""for value in map(str,range(1,22))+['excuse']:
self.idx_cards.append(self.cards["atout",value])
for suit in ["pique", "coeur", "carreau", "trefle"]:
for value in map(str,range(1,11))+["valet","cavalier","dame","roi"]:
self.idx_cards.append(self.cards[suit, value])""" #XXX: no need to sort the cards !
def newGame(self, hand):
"""Start a new game, with given hand"""
assert (len(self.hand) == 0)
for suit, value in hand:
self.hand.append(self.cards[suit, value])
self.hand.sort()
self.state = "init"
QuickCardGame.newGame(self, hand)
self._recalc_ori()
self.Refresh()
@ -125,30 +94,14 @@ class CardPanel(wx.Panel):
@param data: form result"""
debug (_("Contrat choosed"))
contrat = data[0][1]
self.parent.host.bridge.tarotGameContratChoosed(self.player_nick, self.referee, contrat or 'Passe', self.parent.host.profile)
QuickCardGame.contratSelected(self, contrat)
def chooseContrat(self, xml_data):
"""Called when the player as to select hist contrat
"""Called when the player as to select his contrat
@param xml_data: SàT xml representation of the form"""
misc = {'callback': self.contratSelected}
form = XMLUI(self.parent.host, xml_data, title = _('Please choose your contrat'), options = ['NO_CANCEL'], misc = misc)
def showCards(self, game_stage, cards, data):
"""Display cards in the middle of the game (to show for e.g. chien ou poignée)"""
self.to_show = []
for suit, value in cards:
self.to_show.append(self.cards[suit, value])
if game_stage == "chien" and data['attaquant'] == self.player_nick:
self.state = "wait_for_ecart"
else:
self.state = "chien"
def MyTurn(self):
"""Called when we have to play :)"""
if self.state == "chien":
self.to_show = []
self.state = "play"
def showScores(self, xml_data, winners, loosers):
"""Called when the player as to select hist contrat
@param xml_data: SàT xml representation of the form"""
@ -156,15 +109,7 @@ class CardPanel(wx.Panel):
def cardsPlayed(self, player, cards):
"""A card has been played by player"""
if self.to_show:
self.to_show = []
pl_cards = []
if self.played[player] != None: #gof: à supprimer
for pl in self.played:
self.played[pl] = None
for suit, value in cards:
pl_cards.append(self.cards[suit, value])
self.played[player] = pl_cards[0]
QuickCardGame.cardsPlayed(self, player, cards)
self.Refresh()
def invalidCards(self, phase, played_cards, invalid_cards):
@ -172,25 +117,12 @@ class CardPanel(wx.Panel):
@param phase: phase of the game
@param played_cards: all the cards played
@param invalid_cards: cards which are invalid"""
QuickCardGame.invalidCards(self, phase, played_cards, invalid_cards)
if phase == "play":
self.state = "play"
elif phase == "ecart":
self.state = "ecart"
else:
error ('INTERNAL ERROR: unmanaged game phase')
for suit, value in played_cards:
self.hand.append(self.cards[suit, value])
self._recalc_ori()
self.Refresh()
self.hand.sort()
wx.MessageDialog(self, _("Cards played are invalid !"), _("Error"), wx.OK | wx.ICON_ERROR).ShowModal()
def _is_on_hand(self, pos_x, pos_y):
"""Return True if the coordinate are on the hand cards"""
if pos_x > self.orig_x and pos_y > self.orig_y \