diff --git a/frontends/primitivus/card_game.py b/frontends/primitivus/card_game.py
new file mode 100644
index 00000000..812a0da6
--- /dev/null
+++ b/frontends/primitivus/card_game.py
@@ -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 .
+"""
+
+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"""
+
diff --git a/frontends/primitivus/chat.py b/frontends/primitivus/chat.py
index f1fbadf0..a8a073e2 100644
--- a/frontends/primitivus/chat.py
+++ b/frontends/primitivus/chat.py
@@ -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)
diff --git a/frontends/primitivus/custom_widgets.py b/frontends/primitivus/custom_widgets.py
index 60a2c892..2edc97fa 100644
--- a/frontends/primitivus/custom_widgets.py
+++ b/frontends/primitivus/custom_widgets.py
@@ -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):
diff --git a/frontends/primitivus/primitivus b/frontends/primitivus/primitivus
index 4038783b..bc95aaa8 100755
--- a/frontends/primitivus/primitivus
+++ b/frontends/primitivus/primitivus
@@ -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"""
diff --git a/frontends/primitivus/xmlui.py b/frontends/primitivus/xmlui.py
new file mode 100644
index 00000000..62ac3ab5
--- /dev/null
+++ b/frontends/primitivus/xmlui.py
@@ -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 .
+"""
+
+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 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()
diff --git a/frontends/quick_frontend/quick_app.py b/frontends/quick_frontend/quick_app.py
index e7d2c01f..82077d53 100644
--- a/frontends/quick_frontend/quick_app.py
+++ b/frontends/quick_frontend/quick_app.py
@@ -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"))
diff --git a/frontends/quick_frontend/quick_card_game.py b/frontends/quick_frontend/quick_card_game.py
new file mode 100644
index 00000000..f0664df4
--- /dev/null
+++ b/frontends/quick_frontend/quick_card_game.py
@@ -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 .
+"""
+
+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()
+
diff --git a/frontends/quick_frontend/quick_chat.py b/frontends/quick_frontend/quick_chat.py
index 338af6a6..1c487a21 100644
--- a/frontends/quick_frontend/quick_chat.py
+++ b/frontends/quick_frontend/quick_chat.py
@@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-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'))
diff --git a/frontends/wix/card_game.py b/frontends/wix/card_game.py
index c3253350..79641eed 100644
--- a/frontends/wix/card_game.py
+++ b/frontends/wix/card_game.py
@@ -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 \