game.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. import random
  2. from typing import List, Dict
  3. from color import Color
  4. from cards import Card, shuffle
  5. from option import OptionCode, Option
  6. from player import Player, StateCode, ErrorCode
  7. all_colors = [Color.RED, Color.BLUE, Color.YELLOW, Color.GREEN]
  8. class Game(object):
  9. """description of class"""
  10. players: List[Player]
  11. current_player: Player
  12. current_dealer: Player
  13. stock: List[str]
  14. number_of_cards: int
  15. def __init__(self):
  16. self.stock = []
  17. self.number_of_cards = 0
  18. self.players = []
  19. self.current_player = None
  20. self.current_dealer = None
  21. def join_player(self, name):
  22. player = Player(name=name)
  23. self.players.append(player)
  24. player.state = StateCode.PICK_COLOR
  25. self.set_pick_color_state()
  26. return player
  27. def unjoin_player(self, player):
  28. if player.color is None:
  29. self.players.remove(player)
  30. else:
  31. player.name = None
  32. self.set_pick_color_state()
  33. def pick_color(self, player, color):
  34. color_player = next((p for p in self.players if p.color == color), None)
  35. if color_player is not None:
  36. if color_player.name is None:
  37. # reconnect, merge
  38. player.merge_from(color_player)
  39. self.players.remove(color_player)
  40. else:
  41. # error
  42. player.message = f"Kleur {color} is al gekozen door een andere speler. " + player.message
  43. player.set_error(ErrorCode.COLOR_ALREADY_CHOSEN, color=color)
  44. return
  45. player.color = color
  46. self.set_pick_color_state()
  47. def set_pick_color_state(self):
  48. used_colors = [player.color for player in self.players if player.color is not None and player.name is not None]
  49. available_colors = [color for color in all_colors if color not in used_colors]
  50. for player in self.players:
  51. if player.state == StateCode.PICK_COLOR:
  52. player.options = [Option(OptionCode.PICK_COLOR, str(color), color=color) for color in available_colors]
  53. if len(used_colors) == 4 and player.color is not None:
  54. player.options.append(Option(OptionCode.DEAL, "Delen"))
  55. if player.color is None:
  56. player.message = "Kies een kleur om mee te spelen"
  57. else:
  58. player.message = "Wie begint er met delen?"
  59. player.set_others(self.players)
  60. def deal(self, dealer):
  61. self.current_player = dealer
  62. self.current_dealer = dealer
  63. if self.number_of_cards <= 2:
  64. self.stock = shuffle(2)
  65. self.number_of_cards = 6
  66. else:
  67. self.number_of_cards -= 1
  68. for player in self.players:
  69. if player.color is not None:
  70. player.hand = self.stock[:self.number_of_cards]
  71. self.stock = self.stock[self.number_of_cards:]
  72. player.options = [Option(OptionCode.SWAP_CARD, card.denom, card=card) for card in player.hand]
  73. player.message = "Kies een kaart om te wisselen"
  74. player.state = StateCode.SWAP_CARD
  75. player.swap_card = None
  76. player.card_is_swapped = False
  77. player.passed = False
  78. player.set_current(dealer)
  79. def swap_card(self, player, card):
  80. if player.swap_card is not None:
  81. player.hand.append(player.swap_card)
  82. player.swap_card = None
  83. player.hand.remove(card)
  84. partner = self.partner(player)
  85. if partner.swap_card is None:
  86. player.swap_card = card
  87. player.message = "Wacht op je maat"
  88. player.state = StateCode.SWAP_CARD
  89. player.options = [Option(OptionCode.SWAP_CARD, card.denom, card=card) for card in player.hand]
  90. player.options.append(Option(OptionCode.UNDO_CARD, "Terug"))
  91. return
  92. player.hand.append(partner.swap_card)
  93. partner.swap_card = None
  94. partner.hand.append(card)
  95. player.card_is_swapped = True
  96. partner.card_is_swapped = True
  97. partner.options.clear()
  98. player.options.clear()
  99. player.message = ""
  100. if all(player.card_is_swapped for player in self.players if player.color is not None):
  101. self.next_turn()
  102. else:
  103. player.message = "Wacht op het andere team"
  104. player.state = StateCode.SWAP_CARD_OTHERS
  105. partner.message = "wacht op het andere team"
  106. partner.state = StateCode.SWAP_CARD_OTHERS
  107. def play_card(self, player, card):
  108. if player.play_card is not None:
  109. player.hand.append(player.play_card)
  110. player.play_card = None
  111. player.hand.remove(card)
  112. player.play_card = card
  113. player.options = [Option(OptionCode.UNDO_CARD, "Terug"), Option(OptionCode.READY, "Klaar")]
  114. player.options.extend(Option(OptionCode.PLAY_CARD, card.denom, card=card) for card in self.current_player.hand)
  115. player.message = f"Je speelt {card.denom}"
  116. player.state = StateCode.PLAY_CARD
  117. for other in self.players:
  118. if other.color != player.color:
  119. other.message = f"{player.name} speelt een {card.denom}"
  120. other.state = StateCode.PLAY_CARD_OTHER,
  121. other.play_card = card
  122. def drop_cards(self, player):
  123. player.hand = []
  124. player.options = []
  125. player.passed = True
  126. player.play_card = None
  127. self.next_turn()
  128. def ready(self, player):
  129. player.options.clear()
  130. player.play_card = None
  131. self.next_turn()
  132. def undo_card(self, player):
  133. if player.swap_card is not None:
  134. player.hand.append(player.swap_card)
  135. player.swap_card = None
  136. player.options = [Option(OptionCode.SWAP_CARD, card.denom, card=card) for card in player.hand]
  137. player.message = "Kies een kaart om te wisselen"
  138. player.state = StateCode.SWAP_CARD
  139. else:
  140. player.hand.append(player.play_card)
  141. player.play_card = None
  142. self.turn()
  143. def play_option(self, player, option):
  144. if option.code == OptionCode.PICK_COLOR:
  145. return self.pick_color(player, option.color)
  146. elif option.code == OptionCode.DEAL:
  147. return self.deal(player)
  148. elif option.code == OptionCode.SWAP_CARD:
  149. return self.swap_card(player, option.card)
  150. elif option.code == OptionCode.PLAY_CARD:
  151. return self.play_card(player, option.card)
  152. elif option.code == OptionCode.READY:
  153. return self.ready(player)
  154. elif option.code == OptionCode.UNDO_CARD:
  155. return self.undo_card(player)
  156. elif option.code == OptionCode.PASS:
  157. return self.drop_cards(player)
  158. else:
  159. raise Exception(f"Unknown option {option.code}")
  160. def next_player(self, player):
  161. if player.color == Color.RED:
  162. color = Color.BLUE
  163. elif player.color == Color.BLUE:
  164. color = Color.YELLOW
  165. elif player.color == Color.YELLOW:
  166. color = Color.GREEN
  167. elif player.color == Color.GREEN:
  168. color = Color.RED
  169. else:
  170. raise Exception(f"Unknown color {player.Color}")
  171. return next(player for player in self.players if player.color == color)
  172. def next_turn(self):
  173. if all(len(player.hand) == 0 for player in self.players):
  174. self.next_deal()
  175. else:
  176. self.current_player = self.next_player(self.current_player)
  177. self.current_player.play_card = None
  178. while len(self.current_player.hand) == 0:
  179. self.current_player = self.next_player(self.current_player)
  180. self.turn()
  181. def next_deal(self):
  182. dealer = self.next_player(self.current_dealer)
  183. self.current_player = dealer
  184. dealer.options = [Option(OptionCode.DEAL, "Delen")]
  185. dealer.message = f"Jij bent aan de beurt om te delen."
  186. dealer.state = StateCode.DEAL
  187. for player in self.players:
  188. player.set_current(dealer)
  189. if player.color != dealer.color:
  190. player.message = f"{dealer.name} is aan de beurt om te delen"
  191. player.state= StateCode.DEAL_OTHER
  192. def turn(self):
  193. player = self.current_player
  194. player.options = [Option(OptionCode.PLAY_CARD, card.denom, card=card) for card in player.hand]
  195. player.options.append(Option(OptionCode.PASS, "Pas"))
  196. player.message = "Kies een kaart om te spelen"
  197. player.state = StateCode.PLAY_CARD
  198. player.play_card = None
  199. for player in self.players:
  200. player.set_current(self.current_player)
  201. if player.color != self.current_player.color:
  202. player.message = f"{self.current_player.name} is aan de beurt"
  203. player.state = StateCode.PLAY_CARD_OTHER
  204. def partner(self, player):
  205. if player.color == Color.RED:
  206. color = Color.YELLOW
  207. elif player.color == Color.BLUE:
  208. color = Color.GREEN
  209. elif player.color == Color.YELLOW:
  210. color = Color.RED
  211. elif player.color == Color.GREEN:
  212. color = Color.BLUE
  213. else:
  214. raise Exception(f"Unknown color {player.Color}")
  215. return next(player for player in self.players if player.color == color)
  216. if __name__ == "__main__":
  217. game = Game()
  218. red = game.join_player("Rood")
  219. blue = game.join_player("Blauw")
  220. yellow = game.join_player("Geel")
  221. green = game.join_player("Groen")
  222. olive = game.join_player("Olijf")
  223. players = [blue, yellow, green, red]
  224. game.pick_color(red, Color.RED)
  225. game.pick_color(blue, Color.BLUE)
  226. game.pick_color(yellow, Color.YELLOW)
  227. game.pick_color(green, Color.GREEN)
  228. for round in range(2):
  229. for deal in [6, 5, 4, 3, 2]:
  230. player = players[0]
  231. print(f"{player.name} deals {deal} cards")
  232. game.deal(player)
  233. for player in game.players:
  234. print(player.get_json(), end="\n\n")
  235. game.swap_card(yellow, yellow.hand[deal - 1])
  236. game.swap_card(red, red.hand[1])
  237. if round == 0:
  238. game.swap_card(green, green.hand[0])
  239. else:
  240. game.swap_card(olive, olive.hand[0])
  241. game.swap_card(blue, blue.hand[-1])
  242. players = players[1:] + players[:1]
  243. for turn in range(deal):
  244. for player in players:
  245. card = player.hand[0]
  246. game.play_card(player, card)
  247. print(f"{player.name} plays {card.denom} of {card.suit}")
  248. game.ready(player)
  249. if round == 0:
  250. print(green.get_json(), end="\n\n")
  251. green.name = None
  252. game.pick_color(olive, Color.GREEN)
  253. players = [yellow, olive, red, blue]