changeset 39:305e81c7a32c

Tarot game: a game can now be finished
author Goffi <goffi@goffi.org>
date Sun, 22 May 2011 00:15:01 +0200
parents 7bea2ae0c4fb
children 49f1829fb928
files browser_side/card_game.py browser_side/dialog.py browser_side/panels.py libervia.py libervia.tac
diffstat 5 files changed, 146 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/browser_side/card_game.py	Thu May 19 02:00:59 2011 +0200
+++ b/browser_side/card_game.py	Sun May 22 00:15:01 2011 +0200
@@ -39,6 +39,7 @@
 from pyjamas.dnd import makeDraggable
 from pyjamas.ui.DragWidget import DragWidget, DragContainer
 from jid import JID
+from dialog import ConfirmDialog
 from tools import html_sanitize
 from datetime import datetime
 from time import time
@@ -48,7 +49,7 @@
 
 CARD_WIDTH = 74
 CARD_HEIGHT = 136
-CARD_DELTA_Y = 10
+CARD_DELTA_Y = 30
 MIN_WIDTH = 950 #Minimum size of the panel
 MIN_HEIGHT = 500
 
@@ -96,11 +97,23 @@
         self.addMouseListener(self)
 
     def onMouseEnter(self, sender):
-        if self._parent.state == "ecart":
+        if self._parent.state == "ecart" or self._parent.state == "play":
             DOM.setStyleAttribute(self.getElement(), "top", "0px")
 
     def onMouseLeave(self, sender):
-        DOM.setStyleAttribute(self.getElement(), "top", "%dpx" % CARD_DELTA_Y)
+        if not self in self._parent.hand:
+            return
+        if not self in list(self._parent.selected): #FIXME: Workaround pyjs bug, must report it
+            DOM.setStyleAttribute(self.getElement(), "top", "%dpx" % CARD_DELTA_Y)
+
+    def onMouseUp(self, sender, x, y):
+        if self._parent.state == "ecart":
+            if self not in list(self._parent.selected):
+                self._parent.addToSelection(self)
+            else:
+                self._parent.removeFromSelection(self)
+        elif self._parent.state == "play":
+            self._parent.playCard(self)
 
 class CardPanel(DockPanel, ClickHandler):
 
@@ -124,7 +137,7 @@
         idx = (idx + 1) % len(self.players)
         self.left_nick = self.players[idx]
         self.bottom_nick = player_nick
-        self.selected = [] #Card choosed by the player (e.g. during ecart)
+        self.selected = set() #Card choosed by the player (e.g. during ecart)
         self.hand_size = 13 #number of cards in a hand
         self.hand = []
         self.to_show = []
@@ -163,25 +176,27 @@
 
         self.center_panel = DockPanel()
         self.inner_left = SimplePanel()
+        self.inner_left.setSize("%dpx" % CARD_WIDTH, "%dpx" % CARD_HEIGHT)
         self.center_panel.add(self.inner_left, DockPanel.WEST)
         self.center_panel.setCellHeight(self.inner_left, '100%')
         self.center_panel.setCellHorizontalAlignment(self.inner_left, HasAlignment.ALIGN_RIGHT)
         self.center_panel.setCellVerticalAlignment(self.inner_left, HasAlignment.ALIGN_MIDDLE)
 
         self.inner_right = SimplePanel()
+        self.inner_right.setSize("%dpx" % CARD_WIDTH, "%dpx" % CARD_HEIGHT)
         self.center_panel.add(self.inner_right, DockPanel.EAST)
         self.center_panel.setCellHeight(self.inner_right, '100%')
         self.center_panel.setCellVerticalAlignment(self.inner_right, HasAlignment.ALIGN_MIDDLE)
         
         self.inner_top = SimplePanel()
+        self.inner_top.setSize("%dpx" % CARD_WIDTH, "%dpx" % CARD_HEIGHT)
         self.center_panel.add(self.inner_top, DockPanel.NORTH)
-        self.center_panel.setCellWidth(self.inner_top, '100%')
         self.center_panel.setCellHorizontalAlignment(self.inner_top, HasAlignment.ALIGN_CENTER)
         self.center_panel.setCellVerticalAlignment(self.inner_top, HasAlignment.ALIGN_BOTTOM)
         
         self.inner_bottom = SimplePanel()
+        self.inner_bottom.setSize("%dpx" % CARD_WIDTH, "%dpx" % CARD_HEIGHT)
         self.center_panel.add(self.inner_bottom, DockPanel.SOUTH)
-        self.center_panel.setCellWidth(self.inner_bottom, '100%')
         self.center_panel.setCellHorizontalAlignment(self.inner_bottom, HasAlignment.ALIGN_CENTER)
         self.center_panel.setCellVerticalAlignment(self.inner_bottom, HasAlignment.ALIGN_TOP)
         
@@ -274,6 +289,47 @@
             x_pos+=CARD_WIDTH + 5
         self.inner_center.setWidget(panel)
 
+    def _ecartConfirm(self, confirm):
+        if not confirm:
+            return
+        ecart = []
+        for card in self.selected:
+            ecart.append((card.suit, card.value))
+            self.hand.remove(card)
+        self.selected.clear()
+        self._parent.host.bridge.call('tarotGamePlayCards', None, self.player_nick, self.referee, ecart)
+        self.state = "wait"
+        self.updateHand()
+    
+    def addToSelection(self, card):
+        self.selected.add(card)
+        if len(self.selected) == 6:
+            ConfirmDialog(self._ecartConfirm, "Put these cards into chien ?").show()
+
+    def tarotGameInvalidCards(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()
+        self.updateHand()
+        Window.alert('Cards played are invalid !')
+
+    def removeFromSelection(self, card):
+        self.selected.remove(card)
+        if len(self.selected) == 6:
+            ConfirmDialog(self._ecartConfirm, "Put these cards into chien ?").show()
 
     def tarotGameChooseContrat(self, xml_data):
         """Called when the player as to select his contrat
@@ -286,11 +342,8 @@
     def contratSelected(self, contrat):
         """Must be called when the contrat is selected
         @param contrat: one of the valid contrat value"""
-        print "Contrat choosed:", contrat
         self._parent.host.bridge.call('tarotGameContratChoosed', None, self.player_nick, self.referee, contrat or 'Passe')
 
-
-
     def tarotGameShowCards(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 = []
@@ -302,3 +355,45 @@
         else:
             self.state = "chien"
 
+    def getPlayerLocation(self, nick):
+        """return player location (top,bottom,left or right)"""
+        for location in ['top','left','bottom','right']:
+            if getattr(self,'%s_nick' % location) == nick:
+                return location
+        print ("ERROR: This line should not be reached")
+
+    def tarotGameCardsPlayed(self, player, cards):
+        """A card has been played by player"""
+        if not len(cards):
+            print ("WARNING: cards should not be empty")
+            return
+        if len(cards) > 1:
+            print ("ERROR: can't manage several cards played")
+        if self.to_show:
+            self.to_show = []
+            self.updateToShow()
+        suit, value = cards[0]
+        player_pos = self.getPlayerLocation(player)
+        player_panel = getattr(self, "inner_%s" % player_pos)
+
+        if player_panel.getWidget() != None:
+            #We have already cards on the table, we remove them
+            for pos in ['top','left','bottom','right']:
+                getattr(self, "inner_%s" % pos).setWidget(None)
+       
+        card = self.cards[(suit, value)]
+        DOM.setElemAttribute(card.getElement(), "style", "")
+        player_panel.setWidget(card)
+    
+    def tarotGameYourTurn(self):
+        """Called when we have to play :)"""
+        if self.state == "chien":
+            self.to_show = []
+            self.updateToShow()
+        self.state = "play"
+
+    def playCard(self, card):
+        self.hand.remove(card)
+        self._parent.host.bridge.call('tarotGamePlayCards', None, self.player_nick, self.referee, [(card.suit, card.value)])
+        self.state = "wait"
+        self.updateHand()
--- a/browser_side/dialog.py	Thu May 19 02:00:59 2011 +0200
+++ b/browser_side/dialog.py	Sun May 22 00:15:01 2011 +0200
@@ -81,3 +81,31 @@
     def onCancel(self):
         self.hide()
 
+class ConfirmDialog(DialogBox):
+
+    def __init__(self, callback, text='Are you sure ?'):
+        """
+        Dialog to confirm an action
+        @param callback: method to call when contacts have been choosed
+        """
+        self.callback = callback
+        DialogBox.__init__(self, centered=True)
+
+        content = VerticalPanel()
+        content.setWidth('100%')
+        button_panel = HorizontalPanel()
+        self.confirm_button = Button("OK", self.onConfirm)
+        button_panel.add(self.confirm_button)
+        button_panel.add(Button("Cancel", self.onCancel))
+        content.add(button_panel)
+        self.setHTML(text)
+        self.setWidget(content)	
+    
+    def onConfirm(self):
+        self.hide()
+        self.callback(True)
+
+    def onCancel(self):
+        self.hide()
+        self.callback(False)
+
--- a/browser_side/panels.py	Thu May 19 02:00:59 2011 +0200
+++ b/browser_side/panels.py	Sun May 22 00:15:01 2011 +0200
@@ -147,6 +147,8 @@
             _new_panel.historyPrint()
         elif item_type=="CONTACT_TITLE":
             _new_panel = MicroblogPanel(self.host, accept_all=True)
+        else:
+            return
         self.host.mpanels.remove(self)
         self.host.mpanels.append(_new_panel)
         grid = self.getParent()
--- a/libervia.py	Thu May 19 02:00:59 2011 +0200
+++ b/libervia.py	Sun May 22 00:15:01 2011 +0200
@@ -66,7 +66,8 @@
     def __init__(self):
         LiberviaJsonProxy.__init__(self, "/json_api",
                         ["getContacts", "sendMessage", "sendMblog", "getMblogNodes", "getProfileJid", "getHistory",
-                         "getPresenceStatus", "getRoomJoined", "launchTarotGame", "getTarotCardsPaths", "tarotGameReady", "tarotGameContratChoosed"])
+                         "getPresenceStatus", "getRoomJoined", "launchTarotGame", "getTarotCardsPaths", "tarotGameReady", "tarotGameContratChoosed",
+                         "tarotGamePlayCards"])
 
 class BridgeSignals(LiberviaJsonProxy):
     def __init__(self):
@@ -173,7 +174,10 @@
             self._tarotGameStartedCb(*args)
         elif name == 'tarotGameNew' or \
              name == 'tarotGameChooseContrat' or \
-             name == 'tarotGameShowCards':
+             name == 'tarotGameShowCards' or \
+             name == 'tarotGameInvalidCards' or \
+             name == 'tarotGameCardsPlayed' or \
+             name == 'tarotGameYourTurn':
             self._tarotGameGenericCb(name, args[0], args[1:])
 
     def _getProfileJidCB(self, jid):
--- a/libervia.tac	Thu May 19 02:00:59 2011 +0200
+++ b/libervia.tac	Sun May 22 00:15:01 2011 +0200
@@ -137,6 +137,11 @@
         """Tell to the server that we are ready to start the game"""
         profile = self.session.sat_profile
         self.sat_host.bridge.tarotGameContratChoosed(player_nick, referee, contrat, profile)
+    
+    def jsonrpc_tarotGamePlayCards(self, player_nick, referee, cards):
+        """Tell to the server that we are ready to start the game"""
+        profile = self.session.sat_profile
+        self.sat_host.bridge.tarotGamePlayCards(player_nick, referee, cards, profile)
 
 class Register(jsonrpc.JSONRPC):
     """This class manage the registration procedure with SàT
@@ -362,7 +367,7 @@
         self.bridge.register("connected", self.signal_handler.connected)
         self.bridge.register("connectionError", self.signal_handler.connectionError)
         for signal_name in ['presenceUpdate', 'personalEvent', 'newMessage', 'roomJoined', 'roomUserJoined', 'roomUserLeft', 'tarotGameStarted', 'tarotGameNew',
-                            'tarotGameChooseContrat', 'tarotGameShowCards']:
+                            'tarotGameChooseContrat', 'tarotGameShowCards', 'tarotGameInvalidCards', 'tarotGameCardsPlayed', 'tarotGameYourTurn']:
             self.bridge.register(signal_name, self.signal_handler.getGenericCb(signal_name))
         root.putChild('json_signal_api', self.signal_handler)
         root.putChild('json_api', MethodHandler(self))