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.
This commit is contained in:
parent
851faff0e3
commit
e337d590e3
3 changed files with 126 additions and 4 deletions
|
|
@ -55,6 +55,7 @@ class QuickApp():
|
|||
self.bridge.register("tarotGameYourTurn", self.tarotMyTurn)
|
||||
self.bridge.register("tarotGameScore", self.tarotScore)
|
||||
self.bridge.register("tarotGameCardsPlayed", self.tarotCardsPlayed)
|
||||
self.bridge.register("tarotGameInvalidCards", self.tarotInvalidCards)
|
||||
self.bridge.register("subscribe", self.subscribe)
|
||||
self.bridge.register("paramUpdate", self.paramUpdate)
|
||||
self.bridge.register("contactDeleted", self.contactDeleted)
|
||||
|
|
@ -324,6 +325,13 @@ class QuickApp():
|
|||
if self.chat_wins.has_key(room_jid):
|
||||
self.chat_wins[room_jid].getGame("Tarot").cardsPlayed(player, cards)
|
||||
|
||||
def tarotInvalidCards(self, room_jid, phase, played_cards, invalid_cards, profile):
|
||||
if not self.__check_profile(profile):
|
||||
return
|
||||
debug (_("Cards played are not valid: %s") % invalid_cards)
|
||||
if self.chat_wins.has_key(room_jid):
|
||||
self.chat_wins[room_jid].getGame("Tarot").invalidCards(phase, played_cards, invalid_cards)
|
||||
|
||||
def subscribe(self, type, raw_jid, profile):
|
||||
"""Called when a subsciption management signal is received"""
|
||||
if not self.__check_profile(profile):
|
||||
|
|
|
|||
|
|
@ -193,6 +193,29 @@ class CardPanel(wx.Panel):
|
|||
self.played[player] = pl_cards[0]
|
||||
self.Refresh()
|
||||
|
||||
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._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"""
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ class Tarot():
|
|||
host.bridge.addSignal("tarotGameCardsPlayed", ".communication", signature='ssa(ss)s') #args: room_jid, player, type ["chien", "poignée",...], cards, data[dict], profile
|
||||
host.bridge.addSignal("tarotGameYourTurn", ".communication", signature='ss') #args: room_jid, profile
|
||||
host.bridge.addSignal("tarotGameScore", ".communication", signature='ssasass') #args: room_jid, xml_data, winners (list of nicks), loosers (list of nicks), profile
|
||||
host.bridge.addSignal("tarotGameInvalidCards", ".communication", signature='ssa(ss)a(ss)s') #args: room_jid, game phase, played_cards, invalid_cards, profile
|
||||
self.deck_ordered = []
|
||||
for value in ['excuse']+map(str,range(1,22)):
|
||||
self.deck_ordered.append(Card(("atout",value)))
|
||||
|
|
@ -207,6 +208,19 @@ class Tarot():
|
|||
score_elt.addChild(looser_elt)
|
||||
return score_elt
|
||||
|
||||
def __invalid_cards_elt(self, played_cards, invalid_cards, game_phase):
|
||||
"""Create a element for invalid_cards error
|
||||
@param list_cards: list of Card
|
||||
@param game_phase: phase of the game ['ecart', 'play']"""
|
||||
error_elt = domish.Element(('','error'))
|
||||
played_elt = self.__card_list_to_xml(played_cards, 'played')
|
||||
invalid_elt = self.__card_list_to_xml(invalid_cards, 'invalid')
|
||||
error_elt['type'] = 'invalid_cards'
|
||||
error_elt['phase'] = game_phase
|
||||
error_elt.addChild(played_elt)
|
||||
error_elt.addChild(invalid_elt)
|
||||
return error_elt
|
||||
|
||||
def __next_player(self, game_data, next_pl = None):
|
||||
"""Increment player number & return player name
|
||||
@param next_pl: if given, then next_player is forced to this one
|
||||
|
|
@ -325,8 +339,6 @@ class Tarot():
|
|||
if game_data['contrat'] == "Garde Contre":
|
||||
for card in game_data['chien']:
|
||||
check_score+=card.points
|
||||
if ( score + check_score != 91 ):
|
||||
pdb.set_trace()
|
||||
assert (score + check_score == 91)
|
||||
|
||||
point_limit = None
|
||||
|
|
@ -373,6 +385,63 @@ class Tarot():
|
|||
|
||||
return (scores_str, winners, loosers)
|
||||
|
||||
def __invalid_cards(self, game_data, cards):
|
||||
"""Checks that the player has the right to play what he wants to
|
||||
@param game_data: Game data
|
||||
@param cards: cards the player want to play
|
||||
@return forbidden_cards cards or empty list if cards are ok"""
|
||||
forbidden_cards = []
|
||||
if game_data['stage'] == 'ecart':
|
||||
for card in cards:
|
||||
if card.bout or card.value=="roi":
|
||||
forbidden_cards.append(card)
|
||||
#TODO: manage case where atouts (trumps) are in the dog
|
||||
elif game_data['stage'] == 'play':
|
||||
biggest_atout = None
|
||||
suit_asked = None
|
||||
players = game_data['players']
|
||||
players_data = game_data['players_data']
|
||||
idx = players.index(game_data['first_player'])
|
||||
current_idx = game_data['current_player']
|
||||
current_player = players[current_idx]
|
||||
if idx == current_idx:
|
||||
#the player is the first to play, he can play what he wants
|
||||
return forbidden_cards
|
||||
while (idx != current_idx):
|
||||
player = players[idx]
|
||||
played_card = players_data[player]['played']
|
||||
if not suit_asked and played_card.value != "excuse":
|
||||
suit_asked = played_card.suit
|
||||
if played_card.suit == "atout" and played_card > biggest_atout:
|
||||
biggest_atout = played_card
|
||||
idx = (idx + 1) % len(players)
|
||||
has_suit = False #True if there is one card of the asked suit in the hand of the player
|
||||
has_atout = False
|
||||
biggest_hand_atout = None
|
||||
|
||||
for hand_card in game_data['hand'][current_player]:
|
||||
if hand_card.suit == suit_asked:
|
||||
has_suit = True
|
||||
if hand_card.suit == "atout":
|
||||
has_atout = True
|
||||
if hand_card.suit == "atout" and hand_card > biggest_hand_atout:
|
||||
biggest_hand_atout = hand_card
|
||||
|
||||
assert len(cards) == 1
|
||||
card = cards[0]
|
||||
if card.suit != suit_asked and has_suit and card.value != "excuse":
|
||||
forbidden_cards.append(card)
|
||||
return forbidden_cards
|
||||
if card.suit != suit_asked and card.suit != "atout" and has_atout:
|
||||
forbidden_cards.append(card)
|
||||
return forbidden_cards
|
||||
if card.suit == "atout" and card < biggest_atout and biggest_hand_atout > biggest_atout and card.value != "excuse":
|
||||
forbidden_cards.append(card)
|
||||
else:
|
||||
error(_('Internal error: unmanaged game stage'))
|
||||
return forbidden_cards
|
||||
|
||||
|
||||
def __start_play(self, room_jid, game_data, profile):
|
||||
"""Start the game (tell to the first player after dealer to play"""
|
||||
game_data['stage'] = "play"
|
||||
|
|
@ -584,10 +653,17 @@ class Tarot():
|
|||
|
||||
elif elt.name == 'cards_played':
|
||||
if game_data['stage'] == "ecart":
|
||||
#TODO: check validity of écart (no king, no oulder, cards must be in player hand)
|
||||
#TODO: show atouts (trumps) if player put some in écart
|
||||
assert (game_data['attaquant'] == elt['player']) #TODO: throw an xml error here
|
||||
list_cards = Card.from_tuples(self.__xml_to_list(elt))
|
||||
#we now check validity of card
|
||||
invalid_cards = self.__invalid_cards(game_data, list_cards)
|
||||
if invalid_cards:
|
||||
mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+elt['player']))
|
||||
mess.firstChildElement().addChild(self.__invalid_cards_elt(list_cards, invalid_cards, game_data['stage']))
|
||||
self.host.profiles[profile].xmlstream.send(mess)
|
||||
return
|
||||
|
||||
#FIXME: gof: manage Garde Sans & Garde Contre cases
|
||||
players_data[elt['player']]['levees'].extend(list_cards) #we add the chien to attaquant's levées
|
||||
for card in list_cards:
|
||||
|
|
@ -602,7 +678,13 @@ class Tarot():
|
|||
if mess_elt['type'] == 'groupchat':
|
||||
self.host.bridge.tarotGameCardsPlayed(room_jid.userhost(), elt['player'], self.__xml_to_list(elt), profile)
|
||||
else:
|
||||
#TODO: check card validity and send error mess if necessary
|
||||
#we first check validity of card
|
||||
invalid_cards = self.__invalid_cards(game_data, cards)
|
||||
if invalid_cards:
|
||||
mess = self.createGameElt(jid.JID(room_jid.userhost()+'/'+current_player))
|
||||
mess.firstChildElement().addChild(self.__invalid_cards_elt(cards, invalid_cards, game_data['stage']))
|
||||
self.host.profiles[profile].xmlstream.send(mess)
|
||||
return
|
||||
#the card played is ok, we forward it to everybody
|
||||
#first we remove it from the hand and put in on the table
|
||||
game_data['hand'][current_player].remove(cards[0])
|
||||
|
|
@ -657,6 +739,15 @@ class Tarot():
|
|||
form = data_form.Form.fromElement(form_elt)
|
||||
xml_data = XMLTools.dataForm2xml(form)
|
||||
self.host.bridge.tarotGameScore(room_jid.userhost(), xml_data, winners, loosers, profile)
|
||||
elif elt.name == 'error':
|
||||
if elt['type'] == 'invalid_cards':
|
||||
played_cards = self.__xml_to_list(elt.elements(name='played',uri='').next())
|
||||
invalid_cards = self.__xml_to_list(elt.elements(name='invalid',uri='').next())
|
||||
self.host.bridge.tarotGameInvalidCards(room_jid.userhost(), elt['phase'], played_cards, invalid_cards, profile)
|
||||
else:
|
||||
error (_('Unmanaged error type: %s') % elt['type'])
|
||||
else:
|
||||
error (_('Unmanaged card game element: %s') % elt.name)
|
||||
|
||||
def getHandler(self, profile):
|
||||
return CardGameHandler(self)
|
||||
|
|
|
|||
Loading…
Reference in a new issue