Mercurial > libervia-backend
comparison plugins/plugin_misc_tarot.py @ 99:63c9067a1499
Tarot game: invalid cards management
- tarot plugin: card validity check, new signal tarotGameInvalidCards
- wix: when an invalid cards signal is received, the cards are back in the hand, and the state change so the player as to play again.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 18 Jun 2010 15:19:32 +0800 |
parents | dd556233a1b1 |
children | 783e9d6980ec |
comparison
equal
deleted
inserted
replaced
98:dd556233a1b1 | 99:63c9067a1499 |
---|---|
130 host.bridge.addSignal("tarotGameChooseContrat", ".communication", signature='sss') #args: room_jid, xml_data, profile | 130 host.bridge.addSignal("tarotGameChooseContrat", ".communication", signature='sss') #args: room_jid, xml_data, profile |
131 host.bridge.addSignal("tarotGameShowCards", ".communication", signature='ssa(ss)a{ss}s') #args: room_jid, type ["chien", "poignée",...], cards, data[dict], profile | 131 host.bridge.addSignal("tarotGameShowCards", ".communication", signature='ssa(ss)a{ss}s') #args: room_jid, type ["chien", "poignée",...], cards, data[dict], profile |
132 host.bridge.addSignal("tarotGameCardsPlayed", ".communication", signature='ssa(ss)s') #args: room_jid, player, type ["chien", "poignée",...], cards, data[dict], profile | 132 host.bridge.addSignal("tarotGameCardsPlayed", ".communication", signature='ssa(ss)s') #args: room_jid, player, type ["chien", "poignée",...], cards, data[dict], profile |
133 host.bridge.addSignal("tarotGameYourTurn", ".communication", signature='ss') #args: room_jid, profile | 133 host.bridge.addSignal("tarotGameYourTurn", ".communication", signature='ss') #args: room_jid, profile |
134 host.bridge.addSignal("tarotGameScore", ".communication", signature='ssasass') #args: room_jid, xml_data, winners (list of nicks), loosers (list of nicks), profile | 134 host.bridge.addSignal("tarotGameScore", ".communication", signature='ssasass') #args: room_jid, xml_data, winners (list of nicks), loosers (list of nicks), profile |
135 host.bridge.addSignal("tarotGameInvalidCards", ".communication", signature='ssa(ss)a(ss)s') #args: room_jid, game phase, played_cards, invalid_cards, profile | |
135 self.deck_ordered = [] | 136 self.deck_ordered = [] |
136 for value in ['excuse']+map(str,range(1,22)): | 137 for value in ['excuse']+map(str,range(1,22)): |
137 self.deck_ordered.append(Card(("atout",value))) | 138 self.deck_ordered.append(Card(("atout",value))) |
138 for suit in ["pique", "coeur", "carreau", "trefle"]: | 139 for suit in ["pique", "coeur", "carreau", "trefle"]: |
139 for value in map(str,range(1,11))+["valet","cavalier","dame","roi"]: | 140 for value in map(str,range(1,11))+["valet","cavalier","dame","roi"]: |
205 looser_elt = domish.Element(('','looser')) | 206 looser_elt = domish.Element(('','looser')) |
206 looser_elt.addContent(looser) | 207 looser_elt.addContent(looser) |
207 score_elt.addChild(looser_elt) | 208 score_elt.addChild(looser_elt) |
208 return score_elt | 209 return score_elt |
209 | 210 |
211 def __invalid_cards_elt(self, played_cards, invalid_cards, game_phase): | |
212 """Create a element for invalid_cards error | |
213 @param list_cards: list of Card | |
214 @param game_phase: phase of the game ['ecart', 'play']""" | |
215 error_elt = domish.Element(('','error')) | |
216 played_elt = self.__card_list_to_xml(played_cards, 'played') | |
217 invalid_elt = self.__card_list_to_xml(invalid_cards, 'invalid') | |
218 error_elt['type'] = 'invalid_cards' | |
219 error_elt['phase'] = game_phase | |
220 error_elt.addChild(played_elt) | |
221 error_elt.addChild(invalid_elt) | |
222 return error_elt | |
223 | |
210 def __next_player(self, game_data, next_pl = None): | 224 def __next_player(self, game_data, next_pl = None): |
211 """Increment player number & return player name | 225 """Increment player number & return player name |
212 @param next_pl: if given, then next_player is forced to this one | 226 @param next_pl: if given, then next_player is forced to this one |
213 """ | 227 """ |
214 if next_pl: | 228 if next_pl: |
323 for card in players_data[defenseur]['levees']: | 337 for card in players_data[defenseur]['levees']: |
324 check_score+=card.points | 338 check_score+=card.points |
325 if game_data['contrat'] == "Garde Contre": | 339 if game_data['contrat'] == "Garde Contre": |
326 for card in game_data['chien']: | 340 for card in game_data['chien']: |
327 check_score+=card.points | 341 check_score+=card.points |
328 if ( score + check_score != 91 ): | |
329 pdb.set_trace() | |
330 assert (score + check_score == 91) | 342 assert (score + check_score == 91) |
331 | 343 |
332 point_limit = None | 344 point_limit = None |
333 if nb_bouts == 3: | 345 if nb_bouts == 3: |
334 point_limit = 36 | 346 point_limit = 36 |
370 for player in game_data['players']: | 382 for player in game_data['players']: |
371 scores_str+=_("\n--\n%(player)s:\nscore for this game ==> %(score_game)i\ntotal score ==> %(total_score)i") % {'player':player, 'score_game':player_score[player], 'total_score': players_data[player]['score']} | 383 scores_str+=_("\n--\n%(player)s:\nscore for this game ==> %(score_game)i\ntotal score ==> %(total_score)i") % {'player':player, 'score_game':player_score[player], 'total_score': players_data[player]['score']} |
372 debug(scores_str) | 384 debug(scores_str) |
373 | 385 |
374 return (scores_str, winners, loosers) | 386 return (scores_str, winners, loosers) |
387 | |
388 def __invalid_cards(self, game_data, cards): | |
389 """Checks that the player has the right to play what he wants to | |
390 @param game_data: Game data | |
391 @param cards: cards the player want to play | |
392 @return forbidden_cards cards or empty list if cards are ok""" | |
393 forbidden_cards = [] | |
394 if game_data['stage'] == 'ecart': | |
395 for card in cards: | |
396 if card.bout or card.value=="roi": | |
397 forbidden_cards.append(card) | |
398 #TODO: manage case where atouts (trumps) are in the dog | |
399 elif game_data['stage'] == 'play': | |
400 biggest_atout = None | |
401 suit_asked = None | |
402 players = game_data['players'] | |
403 players_data = game_data['players_data'] | |
404 idx = players.index(game_data['first_player']) | |
405 current_idx = game_data['current_player'] | |
406 current_player = players[current_idx] | |
407 if idx == current_idx: | |
408 #the player is the first to play, he can play what he wants | |
409 return forbidden_cards | |
410 while (idx != current_idx): | |
411 player = players[idx] | |
412 played_card = players_data[player]['played'] | |
413 if not suit_asked and played_card.value != "excuse": | |
414 suit_asked = played_card.suit | |
415 if played_card.suit == "atout" and played_card > biggest_atout: | |
416 biggest_atout = played_card | |
417 idx = (idx + 1) % len(players) | |
418 has_suit = False #True if there is one card of the asked suit in the hand of the player | |
419 has_atout = False | |
420 biggest_hand_atout = None | |
421 | |
422 for hand_card in game_data['hand'][current_player]: | |
423 if hand_card.suit == suit_asked: | |
424 has_suit = True | |
425 if hand_card.suit == "atout": | |
426 has_atout = True | |
427 if hand_card.suit == "atout" and hand_card > biggest_hand_atout: | |
428 biggest_hand_atout = hand_card | |
429 | |
430 assert len(cards) == 1 | |
431 card = cards[0] | |
432 if card.suit != suit_asked and has_suit and card.value != "excuse": | |
433 forbidden_cards.append(card) | |
434 return forbidden_cards | |
435 if card.suit != suit_asked and card.suit != "atout" and has_atout: | |
436 forbidden_cards.append(card) | |
437 return forbidden_cards | |
438 if card.suit == "atout" and card < biggest_atout and biggest_hand_atout > biggest_atout and card.value != "excuse": | |
439 forbidden_cards.append(card) | |
440 else: | |
441 error(_('Internal error: unmanaged game stage')) | |
442 return forbidden_cards | |
443 | |
375 | 444 |
376 def __start_play(self, room_jid, game_data, profile): | 445 def __start_play(self, room_jid, game_data, profile): |
377 """Start the game (tell to the first player after dealer to play""" | 446 """Start the game (tell to the first player after dealer to play""" |
378 game_data['stage'] = "play" | 447 game_data['stage'] = "play" |
379 next_player_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(game_data['players']) #the player after the dealer start | 448 next_player_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(game_data['players']) #the player after the dealer start |
582 game_data['attaquant'] = elt['attaquant'] | 651 game_data['attaquant'] = elt['attaquant'] |
583 self.host.bridge.tarotGameShowCards(room_jid.userhost(), "chien", self.__xml_to_list(elt), data, profile) | 652 self.host.bridge.tarotGameShowCards(room_jid.userhost(), "chien", self.__xml_to_list(elt), data, profile) |
584 | 653 |
585 elif elt.name == 'cards_played': | 654 elif elt.name == 'cards_played': |
586 if game_data['stage'] == "ecart": | 655 if game_data['stage'] == "ecart": |
587 #TODO: check validity of écart (no king, no oulder, cards must be in player hand) | |
588 #TODO: show atouts (trumps) if player put some in écart | 656 #TODO: show atouts (trumps) if player put some in écart |
589 assert (game_data['attaquant'] == elt['player']) #TODO: throw an xml error here | 657 assert (game_data['attaquant'] == elt['player']) #TODO: throw an xml error here |
590 list_cards = Card.from_tuples(self.__xml_to_list(elt)) | 658 list_cards = Card.from_tuples(self.__xml_to_list(elt)) |
659 #we now check validity of card | |
660 invalid_cards = self.__invalid_cards(game_data, list_cards) | |
661 if invalid_cards: | |
662 mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+elt['player'])) | |
663 mess.firstChildElement().addChild(self.__invalid_cards_elt(list_cards, invalid_cards, game_data['stage'])) | |
664 self.host.profiles[profile].xmlstream.send(mess) | |
665 return | |
666 | |
591 #FIXME: gof: manage Garde Sans & Garde Contre cases | 667 #FIXME: gof: manage Garde Sans & Garde Contre cases |
592 players_data[elt['player']]['levees'].extend(list_cards) #we add the chien to attaquant's levées | 668 players_data[elt['player']]['levees'].extend(list_cards) #we add the chien to attaquant's levées |
593 for card in list_cards: | 669 for card in list_cards: |
594 game_data['hand'][elt['player']].remove(card) | 670 game_data['hand'][elt['player']].remove(card) |
595 | 671 |
600 cards = Card.from_tuples(self.__xml_to_list(elt)) | 676 cards = Card.from_tuples(self.__xml_to_list(elt)) |
601 | 677 |
602 if mess_elt['type'] == 'groupchat': | 678 if mess_elt['type'] == 'groupchat': |
603 self.host.bridge.tarotGameCardsPlayed(room_jid.userhost(), elt['player'], self.__xml_to_list(elt), profile) | 679 self.host.bridge.tarotGameCardsPlayed(room_jid.userhost(), elt['player'], self.__xml_to_list(elt), profile) |
604 else: | 680 else: |
605 #TODO: check card validity and send error mess if necessary | 681 #we first check validity of card |
682 invalid_cards = self.__invalid_cards(game_data, cards) | |
683 if invalid_cards: | |
684 mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+current_player)) | |
685 mess.firstChildElement().addChild(self.__invalid_cards_elt(cards, invalid_cards, game_data['stage'])) | |
686 self.host.profiles[profile].xmlstream.send(mess) | |
687 return | |
606 #the card played is ok, we forward it to everybody | 688 #the card played is ok, we forward it to everybody |
607 #first we remove it from the hand and put in on the table | 689 #first we remove it from the hand and put in on the table |
608 game_data['hand'][current_player].remove(cards[0]) | 690 game_data['hand'][current_player].remove(cards[0]) |
609 players_data[current_player]['played'] = cards[0] | 691 players_data[current_player]['played'] = cards[0] |
610 | 692 |
655 for looser in elt.elements(name='looser', uri=''): | 737 for looser in elt.elements(name='looser', uri=''): |
656 loosers.append(unicode(looser)) | 738 loosers.append(unicode(looser)) |
657 form = data_form.Form.fromElement(form_elt) | 739 form = data_form.Form.fromElement(form_elt) |
658 xml_data = XMLTools.dataForm2xml(form) | 740 xml_data = XMLTools.dataForm2xml(form) |
659 self.host.bridge.tarotGameScore(room_jid.userhost(), xml_data, winners, loosers, profile) | 741 self.host.bridge.tarotGameScore(room_jid.userhost(), xml_data, winners, loosers, profile) |
742 elif elt.name == 'error': | |
743 if elt['type'] == 'invalid_cards': | |
744 played_cards = self.__xml_to_list(elt.elements(name='played',uri='').next()) | |
745 invalid_cards = self.__xml_to_list(elt.elements(name='invalid',uri='').next()) | |
746 self.host.bridge.tarotGameInvalidCards(room_jid.userhost(), elt['phase'], played_cards, invalid_cards, profile) | |
747 else: | |
748 error (_('Unmanaged error type: %s') % elt['type']) | |
749 else: | |
750 error (_('Unmanaged card game element: %s') % elt.name) | |
660 | 751 |
661 def getHandler(self, profile): | 752 def getHandler(self, profile): |
662 return CardGameHandler(self) | 753 return CardGameHandler(self) |
663 | 754 |
664 class CardGameHandler (XMPPHandler): | 755 class CardGameHandler (XMPPHandler): |