comparison plugins/plugin_misc_tarot.py @ 91:39c672544593

Tarot: bidding phase - quick_app: command line is now parsed, "profile" option allow to select it - xml_tools: list-single is now managed - plugin tarot: method and signal to manage contract (contrat): tarotChooseContrat & tarotGameContratChoosed - wix: Q&D Form hack to manage more generic form (not only registration), used to show contract selection form
author Goffi <goffi@goffi.org>
date Thu, 27 May 2010 19:26:19 +0930
parents 4020931569b8
children 2503de7fb4c7
comparison
equal deleted inserted replaced
90:4020931569b8 91:39c672544593
29 import pdb 29 import pdb
30 import random 30 import random
31 31
32 from zope.interface import implements 32 from zope.interface import implements
33 33
34 from wokkel import disco, iwokkel, muc 34 from wokkel import disco, iwokkel, data_form
35 from tools.xml_tools import XMLTools
35 36
36 from base64 import b64decode 37 from base64 import b64decode
37 from hashlib import sha1 38 from hashlib import sha1
38 from time import sleep 39 from time import sleep
39 40
62 63
63 def __init__(self, host): 64 def __init__(self, host):
64 info(_("Plugin Tarot initialization")) 65 info(_("Plugin Tarot initialization"))
65 self.host = host 66 self.host = host
66 self.games={} 67 self.games={}
68 self.contrats = [_('Passe'), _('Petite'), _('Garde'), _('Garde Sans'), _('Garde Contre')]
67 host.bridge.addMethod("tarotGameCreate", ".communication", in_sign='sass', out_sign='', method=self.createGame) #args: room_jid, players, profile 69 host.bridge.addMethod("tarotGameCreate", ".communication", in_sign='sass', out_sign='', method=self.createGame) #args: room_jid, players, profile
68 host.bridge.addMethod("tarotGameReady", ".communication", in_sign='sss', out_sign='', method=self.newPlayerReady) #args: user, referee, profile 70 host.bridge.addMethod("tarotGameReady", ".communication", in_sign='sss', out_sign='', method=self.newPlayerReady) #args: user, referee, profile
71 host.bridge.addMethod("tarotGameContratChoosed", ".communication", in_sign='ssss', out_sign='', method=self.contratChoosed) #args: user, referee, contrat, profile
69 host.bridge.addSignal("tarotGameStarted", ".communication", signature='ssass') #args: room_jid, referee, players, profile 72 host.bridge.addSignal("tarotGameStarted", ".communication", signature='ssass') #args: room_jid, referee, players, profile
70 host.bridge.addSignal("tarotGameNew", ".communication", signature='sa(ss)s') #args: room_jid, hand, profile 73 host.bridge.addSignal("tarotGameNew", ".communication", signature='sa(ss)s') #args: room_jid, hand, profile
74 host.bridge.addSignal("tarotChooseContrat", ".communication", signature='sss') #args: room_jid, xml_data, profile
71 self.deck_ordered = [] 75 self.deck_ordered = []
72 for value in map(str,range(1,22))+['excuse']: 76 for value in map(str,range(1,22))+['excuse']:
73 self.deck_ordered.append(("atout",value)) 77 self.deck_ordered.append(("atout",value))
74 for family in ["pique", "coeur", "carreau", "trefle"]: 78 for family in ["pique", "coeur", "carreau", "trefle"]:
75 for value in map(str,range(1,11))+["valet","cavalier","dame","roi"]: 79 for value in map(str,range(1,11))+["valet","cavalier","dame","roi"]:
108 player_elt.addContent(player) 112 player_elt.addContent(player)
109 player_elt['index'] = str(idx) 113 player_elt['index'] = str(idx)
110 idx+=1 114 idx+=1
111 started_elt.addChild(player_elt) 115 started_elt.addChild(player_elt)
112 return started_elt 116 return started_elt
117
118 def __ask_contrat(self):
119 """Create a element for asking contrat"""
120 contrat_elt = domish.Element(('','contrat'))
121 form = data_form.Form('form', title=_('contrat selection'))
122 field = data_form.Field('list-single', 'contrat', options=map(data_form.Option, self.contrats), required=True)
123 form.addField(field)
124 contrat_elt.addChild(form.toElement())
125 return contrat_elt
126
127
128
129
130 def __next_player(self, game_data):
131 """It's next player turn
132 Increment player number & return player name"""
133 pl_idx = game_data['current_player'] = (game_data['current_player'] + 1) % len(game_data['players'])
134 return game_data['players'][pl_idx]
113 135
114 def createGame(self, room_jid_param, players, profile_key='@DEFAULT@'): 136 def createGame(self, room_jid_param, players, profile_key='@DEFAULT@'):
115 """Create a new game""" 137 """Create a new game"""
116 debug (_("Creating Tarot game")) 138 debug (_("Creating Tarot game"))
117 room_jid = jid.JID(room_jid_param) 139 room_jid = jid.JID(room_jid_param)
121 return 143 return
122 if False: #gof: self.games.has_key(room_jid): 144 if False: #gof: self.games.has_key(room_jid):
123 warning (_("Tarot game already started in room %s") % room_jid.userhost()) 145 warning (_("Tarot game already started in room %s") % room_jid.userhost())
124 else: 146 else:
125 status = {} 147 status = {}
148 players_data = {}
126 for player in players: 149 for player in players:
150 players_data[player] = {}
127 status[player] = "init" 151 status[player] = "init"
128 self.games[room_jid.userhost()] = {'players':players, 'status':status, 'profile':profile, 'hand_size':18, 'player_start':0} 152 self.games[room_jid.userhost()] = {'players':players, 'status':status, 'players_data':players_data, 'referee_profile':profile, 'hand_size':18, 'init_player':0, 'current_player': None}
129 for player in players: 153 for player in players:
130 mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+player)) 154 mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+player))
131 mess.firstChildElement().addChild(self.__create_started_elt(players)) 155 mess.firstChildElement().addChild(self.__create_started_elt(players))
132 self.host.profiles[profile].xmlstream.send(mess) 156 self.host.profiles[profile].xmlstream.send(mess)
133 157
137 if not profile: 161 if not profile:
138 error (_("profile %s is unknown") % profile_key) 162 error (_("profile %s is unknown") % profile_key)
139 return 163 return
140 debug ('new player ready: %s' % profile) 164 debug ('new player ready: %s' % profile)
141 mess = self.createGameElt(jid.JID(referee)) 165 mess = self.createGameElt(jid.JID(referee))
142 mess.firstChildElement().addElement('player_ready', content=user) 166 ready_elt = mess.firstChildElement().addElement('player_ready')
167 ready_elt['user'] = user
168 self.host.profiles[profile].xmlstream.send(mess)
169
170 def contratChoosed(self, user, referee, contrat, profile_key='@DEFAULT@'):
171 """Must be call by player when the contrat is selected
172 @param user: player's name
173 @param referee: arbiter jid
174 @contrat: contrat choosed (must be the exact same string than in the give list options)
175 @profile_key: profile
176 """
177 profile = self.host.memory.getProfileName(profile_key)
178 if not profile:
179 error (_("profile %s is unknown") % profile_key)
180 return
181 debug (_('contrat [%(contrat)s] choosed by %(profile)s') % {'contrat':contrat, 'profile':profile})
182 mess = self.createGameElt(jid.JID(referee))
183 contrat_elt = mess.firstChildElement().addElement(('','contrat_choosed'), content=contrat)
184 contrat_elt['user'] = user
143 self.host.profiles[profile].xmlstream.send(mess) 185 self.host.profiles[profile].xmlstream.send(mess)
144 186
145 187
146 def newGame(self, room_jid): 188 def newGame(self, room_jid):
147 """Launch a new round""" 189 """Launch a new round"""
148 debug (_('new Tarot game')) 190 debug (_('new Tarot game'))
149 deck = self.deck_ordered[:] 191 deck = self.deck_ordered[:]
150 random.shuffle(deck) 192 random.shuffle(deck)
151 profile = self.games[room_jid.userhost()]['profile'] 193 game_data = self.games[room_jid.userhost()]
152 players = self.games[room_jid.userhost()]['players'] 194 referee_profile = game_data['referee_profile']
153 hand = self.games[room_jid.userhost()]['hand'] = {} 195 players = game_data['players']
154 hand_size = self.games[room_jid.userhost()]['hand_size'] 196 players_data = game_data['players_data']
155 chien = self.games[room_jid.userhost()]['chien'] = [] 197 current_player = game_data['current_player']
198 hand = game_data['hand'] = {}
199 hand_size = game_data['hand_size']
200 chien = game_data['chien'] = []
156 for i in range(4): #TODO: distribute according to real Tarot rules (3 by 3 counter-clockwise, 1 card at once to chien) 201 for i in range(4): #TODO: distribute according to real Tarot rules (3 by 3 counter-clockwise, 1 card at once to chien)
157 hand[players[i]] = deck[0:hand_size] 202 hand[players[i]] = deck[0:hand_size]
158 del deck[0:hand_size] 203 del deck[0:hand_size]
159 chien = deck[:] 204 chien = deck[:]
160 del(deck[:]) 205 del(deck[:])
161 206
162 for player in players: 207 for player in players:
163 to_jid = jid.JID(room_jid.userhost()+"/"+player) #FIXME: gof: 208 to_jid = jid.JID(room_jid.userhost()+"/"+player) #FIXME: gof:
164 mess = self.createGameElt(to_jid) 209 mess = self.createGameElt(to_jid)
165 mess.firstChildElement().addChild(self.__hand_to_xml(hand[player])) 210 mess.firstChildElement().addChild(self.__hand_to_xml(hand[player]))
166 self.host.profiles[profile].xmlstream.send(mess) 211 self.host.profiles[referee_profile].xmlstream.send(mess)
212 players_data[player]['contrat'] = None
213
214 pl_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(players) #the player after the dealer start
215 player = players[pl_idx]
216 to_jid = jid.JID(room_jid.userhost()+"/"+player) #FIXME: gof:
217 mess = self.createGameElt(to_jid)
218 mess.firstChildElement().addChild(self.__ask_contrat())
219 self.host.profiles[referee_profile].xmlstream.send(mess)
167 220
168 221
169 def card_game_cmd(self, mess_elt, profile): 222 def card_game_cmd(self, mess_elt, profile):
170 print "\n\nCARD GAME command received (profile=%s): %s" % (profile, mess_elt.toXml()) 223 print "\n\nCARD GAME command received (profile=%s): %s" % (profile, mess_elt.toXml())
171 room_jid = jid.JID(mess_elt['from']) 224 room_jid = jid.JID(mess_elt['from'])
172 game_elt = mess_elt.firstChildElement() 225 game_elt = mess_elt.firstChildElement()
173 for elt in game_elt.elements(): #new game created 226 for elt in game_elt.elements(): #new game created
227
174 if elt.name == 'started': 228 if elt.name == 'started':
175 players = [] 229 players = []
176 for player in elt.elements(): 230 for player in elt.elements():
177 players.append(unicode(player)) 231 players.append(unicode(player))
178 self.host.bridge.tarotGameStarted(room_jid.userhost(), room_jid.full(), players, profile) 232 self.host.bridge.tarotGameStarted(room_jid.userhost(), room_jid.full(), players, profile)
233
179 elif elt.name == 'player_ready': 234 elif elt.name == 'player_ready':
180 player = unicode(elt) 235 player = elt['user']
181 status = self.games[room_jid.userhost()]['status'] 236 status = self.games[room_jid.userhost()]['status']
182 nb_players = len(self.games[room_jid.userhost()]['players']) 237 nb_players = len(self.games[room_jid.userhost()]['players'])
183 status[player] = 'ready' 238 status[player] = 'ready'
184 debug (_('Player %(player)s is ready to start [status: %(status)s]') % {'player':player, 'status':status}) 239 debug (_('Player %(player)s is ready to start [status: %(status)s]') % {'player':player, 'status':status})
185 if status.values().count('ready') == 2: #gof: nb_players: #everybody is ready, we can start the game 240 if status.values().count('ready') == nb_players: #everybody is ready, we can start the game
186 self.newGame(room_jid) 241 self.newGame(room_jid)
187 242
188 elif elt.name == 'hand': #a new hand has been received 243 elif elt.name == 'hand': #a new hand has been received
189 self.host.bridge.tarotGameNew(room_jid.userhost(), self.__xml_to_hand(elt), profile) 244 self.host.bridge.tarotGameNew(room_jid.userhost(), self.__xml_to_hand(elt), profile)
190 245
246 elif elt.name == 'contrat': #it's time to choose contrat
247 form = data_form.Form.fromElement(elt.firstChildElement())
248 xml_data = XMLTools.dataForm2xml(form)
249 self.host.bridge.tarotChooseContrat(room_jid.userhost(), xml_data, profile)
250
251 elif elt.name == 'contrat_choosed': #the player has chooser a contrat
252 #TODO: check we receive the contrat from the right person
253 #TODO: user proper XEP-0004 way for answering form
254 user = elt['user']
255 game_data = self.games[room_jid.userhost()]
256 players_data = game_data['players_data']
257 players_data[user]['contrat'] = unicode(elt)
258 contrats = [players_data[player]['contrat'] for player in game_data['players']]
259 if contrats.count(None):
260 #not everybody has choosed his contrat, it's next one turn
261 player = self.__next_player(game_data)
262 to_jid = jid.JID(room_jid.userhost()+"/"+player) #FIXME: gof:
263 mess = self.createGameElt(to_jid)
264 mess.firstChildElement().addChild(self.__ask_contrat())
265 self.host.profiles[game_data['referee_profile']].xmlstream.send(mess)
266 else:
267 #TODO: manage "everybody pass" case
268 best_contrat = [None, "Passe"]
269 for player in game_data['players']:
270 contrat = players_data[player]['contrat']
271 idx_best = self.contrats.index(best_contrat[1])
272 idx_pl = self.contrats.index(contrat)
273 if idx_pl > idx_best:
274 best_contrat[0] = player
275 best_contrat[1] = contrat
276 debug (_("%(player)s win the bid with %(contrat)s") % {'player':best_contrat[0],'contrat':best_contrat[1]})
277
278
191 279
192 def getHandler(self, profile): 280 def getHandler(self, profile):
193 return CardGameHandler(self) 281 return CardGameHandler(self)
194 282
195 283
200 def __init__(self, plugin_parent): 288 def __init__(self, plugin_parent):
201 self.plugin_parent = plugin_parent 289 self.plugin_parent = plugin_parent
202 self.host = plugin_parent.host 290 self.host = plugin_parent.host
203 291
204 def connectionInitialized(self): 292 def connectionInitialized(self):
205 print "gof: ajout d'observer", CG_REQUEST
206 self.xmlstream.addObserver(CG_REQUEST, self.plugin_parent.card_game_cmd, profile = self.parent.profile) 293 self.xmlstream.addObserver(CG_REQUEST, self.plugin_parent.card_game_cmd, profile = self.parent.profile)
207 294
208 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): 295 def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
209 return [disco.DiscoFeature(NS_CB)] 296 return [disco.DiscoFeature(NS_CB)]
210 297