changeset 150:63d20bda5754

Primitivus: Tarot game Tarot game is now playable, scores are not showed yet.
author Goffi <goffi@goffi.org>
date Wed, 28 Jul 2010 19:58:10 +0800
parents 3c3f70c01333
children 7fcb4f083686
files frontends/primitivus/card_game.py frontends/quick_frontend/quick_app.py frontends/wix/card_game.py
diffstat 3 files changed, 204 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/frontends/primitivus/card_game.py	Wed Jul 28 19:56:56 2010 +0800
+++ b/frontends/primitivus/card_game.py	Wed Jul 28 19:58:10 2010 +0800
@@ -23,28 +23,104 @@
 from tools.games import TarotCard
 from quick_frontend.quick_card_game import QuickCardGame
 from xmlui import XMLUI
+import custom_widgets
+
+class CardDisplayer(urwid.Text):
+    """Show a card"""
+    signals = ['click']
+
+    def __init__(self, card):
+        self.__selected = False
+        self.card = card
+        urwid.Text.__init__(self, card.getAttrText())
+
+    def selectable(self):
+        return True
+
+    def keypress(self, size, key):
+        if key == ' ':
+            self.select(not self.__selected)
+            self._emit('click')
+        return key
+
+    def select(self, state=True):
+        self.__selected = state
+        attr,txt = self.card.getAttrText()
+        if self.__selected:
+            attr+='_selected'
+        self.set_text((attr,txt))
+        self._invalidate()
+
+    def isSelected(self):
+        return self.__selected
+
+    def getCard(self):
+        return self.card
+
+    def render(self, size, focus=False):
+        canvas = urwid.CompositeCanvas(urwid.Text.render(self, size, focus))
+        if focus:
+            canvas.set_cursor((0,0))
+        return canvas
 
 class Hand(urwid.WidgetWrap):
     """Used to display several cards, and manage a hand"""
+    signals = ['click']
 
-    def __init__(self):
-        self.columns = urwid.Columns([])
+    def __init__(self, hand=[], selectable = False, on_click=None, user_data=None):
+        """@param hand: list of Card"""
+        self.__selectable = selectable
+        self.columns = urwid.Columns([],dividechars=1)
+        if on_click:
+            urwid.connect_signal(self, 'click', on_click, user_data)
+        if hand:
+            self.update(hand)
         urwid.WidgetWrap.__init__(self, self.columns)
 
+    def selectable(self):
+        return self.__selectable
+
+    def keypress(self, size, key):
+
+        if CardDisplayer in [wid.__class__ for wid in self.columns.widget_list]:
+            return self.columns.keypress(size,key)
+        else:
+            #No card displayed, we still have to manage the clicks
+            if key == ' ':
+                self._emit('click', None)
+            return key
+
+    def getSelected(self):
+        """Return a list of selected cards"""
+        _selected = []
+        for wid in self.columns.widget_list:
+            if wid.__class__ == CardDisplayer and wid.isSelected():
+                _selected.append(wid.getCard())
+        return _selected
+
     def update(self, hand):
-        """Update the hand displayed in this widget"""
+        """Update the hand displayed in this widget
+        @param hand: list of Card"""
         del self.columns.widget_list[:]
         del self.columns.column_types[:]
+        self.columns.widget_list.append(urwid.Text(''))
+        self.columns.column_types.append(('weight',1))
         for card in hand:
-            self.columns.widget_list.append(urwid.Text(card.getAttrText()))
-            self.columns.column_types.append(('weight',1))
-            
+            widget = CardDisplayer(card)
+            self.columns.widget_list.append(widget)
+            self.columns.column_types.append(('fixed',3))
+            urwid.connect_signal(widget, 'click', self.__onClick)
+        self.columns.widget_list.append(urwid.Text(''))
+        self.columns.column_types.append(('weight',1))
+        self.columns.set_focus(1)
 
-        
+    def __onClick(self,card_wid):
+        self._emit('click', card_wid)
 
 class Card(TarotCard):
     """This class is used to represent a card, logically
     and give a text representation with attributes"""
+    SIZE = 3 #size of a displayed card
 
     def __init__(self, suit, value):
         """@param file: path of the PNG file"""
@@ -78,6 +154,49 @@
             color = 'special'
         return ('card_%s' % color,u"%s%s" % (value,suit))
 
+    def getWidget(self):
+        """Return a widget representing the card"""
+        return CardDisplayer(self)
+
+class Table(urwid.FlowWidget):
+    """Represent the cards currently on the table"""
+
+    def __init__(self):
+        self.top = self.left = self.bottom = self.right = None
+
+    def putCard(self, location, card):
+        """Put a card on the table
+        @param location: where to put the card (top, left, bottom or right)
+        @param card: Card to play or None"""
+        assert location in ['top','left','bottom','right']
+        assert card.__class__ == Card or card == None
+        if [getattr(self, place) for place in ['top','left','bottom','right']].count(None) == 0:
+            #If the table is full of card, we remove them
+            self.top = self.left = self.bottom = self.right = None
+        setattr(self, location, card)
+        self._invalidate()
+    
+    def rows(self,size,focus=False):
+        return self.display_widget(size, focus).rows(size, focus)
+
+    def render(self, size, focus=False):
+        return self.display_widget(size, focus).render(size, focus)
+
+    def display_widget(self, size, focus):
+        cards={}
+        max_col, = size
+        separator = " - "
+        margin = max((max_col-Card.SIZE)/2,0) * ' '
+        margin_center = max((max_col-Card.SIZE*2-len(separator))/2,0) * ' '
+        for location in ['top', 'left', 'bottom', 'right']:
+            card = getattr(self,location)
+            cards[location] = card.getAttrText() if card else Card.SIZE * ' '
+        render_wid = [urwid.Text([margin,cards['top']]),
+                      urwid.Text([margin_center,cards['left'],separator,cards['right']]),
+                      urwid.Text([margin,cards['bottom']])]
+        return urwid.Pile(render_wid)
+        
+
 class CardGame(QuickCardGame,urwid.WidgetWrap):
     """Widget for card games"""
     
@@ -85,19 +204,21 @@
         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'),
+        #self.parent.host.debug()
+        self.table = Table()
+        self.center = urwid.Columns([('fixed',len(self.left_nick),urwid.Filler(urwid.Text(self.left_nick))),
+                                urwid.Filler(self.table),
+                                ('fixed',len(self.right_nick),urwid.Filler(urwid.Text(self.right_nick)))
+                               ])
+        """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)
+                             ])"""
+        self.hand_wid = Hand(selectable = True, on_click = self.onClick)
+        self.main_frame = urwid.Frame(self.center,header=self.top, footer=self.hand_wid, focus_part='footer')
         urwid.WidgetWrap.__init__(self,self.main_frame)
         self.parent.host.bridge.tarotGameReady(player_nick, referee, profile_key = self.parent.host.profile)
 
@@ -133,17 +254,71 @@
         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 showCards(self, game_stage, cards, data):
+        """Display cards in the middle of the game (to show for e.g. chien ou poignée)"""
+        QuickCardGame.showCards(self, game_stage, cards, data)
+        self.center.widget_list[1] = urwid.Filler(Hand(self.to_show))
+        self.parent.host.redraw()
+
+    def myTurn(self):
+        QuickCardGame.myTurn(self)
+
+    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"""
+        form = XMLUI(self.parent.host, xml_data, title = _('You win \o/') if self.player_nick in winners else _('You loose :('), options = ['NO_CANCEL'])
+
+    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"""
+        QuickCardGame.invalidCards(self, phase, played_cards, invalid_cards)
+        self.hand_wid.update(self.hand)
+        self.parent.host.redraw()
+    
+    def cardsPlayed(self, player, cards):
+        """A card has been played by player"""
+        QuickCardGame.cardsPlayed(self, player, cards)
+        self.table.putCard(self.getPlayerLocation(player),self.played[player])
+        self.parent.host.redraw()
     
-    def keypress(self, size, key):
-        return key
-        
-    def render(self, size, focus=False):
-        return self.display_widget(size, focus).render(size, focus)
+    ##EVENTS##
+    def onClick(self, hand, card_wid):
+        """Called when user do an action on the hand"""
+        if not self.state in ['play','ecart','wait_for_ecart']:
+            #it's not our turn, we ignore the click
+            card_wid.select(False)
+            return
+        if self.center.widget_list[1].original_widget.__class__ == Hand: #if we have a hand displayed
+            self.center.widget_list[1] = urwid.Filler(self.table) #we show again the table
+            if self.state == "chien":
+                self.to_show = []
+                self.state = "wait"
+            elif self.state == "wait_for_ecart":
+                self.state = "ecart"
+                self.hand.extend(self.to_show)
+                self.hand.sort()
+                self.to_show = []
+                self.hand_wid.update(self.hand)
+        if self.state ==  "ecart":
+            if len(self.hand_wid.getSelected()) == 6:
+                pop_up_widget = custom_widgets.ConfirmDialog(_("Do you put these cards in chien ?"), yes_cb=self.onEcartDone, no_cb=self.parent.host.removePopUp)
+                self.parent.host.showPopUp(pop_up_widget)
+        elif self.state == "play":
+            card = card_wid.getCard()
+            self.parent.host.bridge.tarotGamePlayCards(self.player_nick, self.referee, [(card.suit, card.value)], profile_key = self.parent.host.profile)
+            self.hand.remove(card)
+            self.hand_wid.update(self.hand)
+            self.state = "wait"
 
-    def display_widget(self, size, focus):
-        (maxcol,maxrow) = size
-
-        return self.main_frame"""
-
+    def onEcartDone(self,button):
+        """Called when player has finished is écart"""
+        ecart = []
+        for card in self.hand_wid.getSelected():
+            ecart.append((card.suit, card.value))
+            self.hand.remove(card)
+        self.hand_wid.update(self.hand)
+        self.parent.host.bridge.tarotGamePlayCards(self.player_nick, self.referee, ecart, profile_key = self.parent.host.profile)
+        self.state = "wait"
+        self.parent.host.removePopUp()
--- a/frontends/quick_frontend/quick_app.py	Wed Jul 28 19:56:56 2010 +0800
+++ b/frontends/quick_frontend/quick_app.py	Wed Jul 28 19:58:10 2010 +0800
@@ -316,7 +316,7 @@
             return
         debug (_("My turn to play"))
         if self.chat_wins.has_key(room_jid):
-            self.chat_wins[room_jid].getGame("Tarot").MyTurn()
+            self.chat_wins[room_jid].getGame("Tarot").myTurn()
     
     def tarotScore(self, room_jid, xml_data, winners, loosers, profile): 
         """Called when the game is finished and the score are updated"""
--- a/frontends/wix/card_game.py	Wed Jul 28 19:56:56 2010 +0800
+++ b/frontends/wix/card_game.py	Wed Jul 28 19:58:10 2010 +0800
@@ -121,7 +121,7 @@
 
         self._recalc_ori()
         self.Refresh()
-        wx.MessageDialog(self, _("Cards played are invalid !"), _("Error"), wx.OK | wx.ICON_ERROR).ShowModal()
+        #gof: 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"""