#!/usr/bin/env python3 # -*- coding: utf-8 -*- import functools import pickle import socket import random import sys import uuid from opale.computer import Computer from opale.game import Game s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: s.bind(("0.0.0.0", 54321)) except socket.error as msg: print('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]) sys.exit() print('Socket bind complete') s.listen(2) print('Socket now listening') try: with open('saved_games.pickle', 'rb') as f: games = pickle.load(f) except: print("Unable to load 'saved_games.pickle'") games = {} def writeSocket(socket, string, *args): if len(args) == 1 and args[0] == None: socket.send(str(string).encode()) elif len(args) > 0: socket.send((string % args).encode() + b"\n") else: socket.send(str(string).encode() + b"\n") def readSocket(socket, string): socket.send(str(string).encode()) s = socket.recv(1024).decode().strip() return s.split("\n")[-1].strip() watchers = [] while True: try: connP1, addrP1 = s.accept() print('Connected with ' + addrP1[0] + ':' + str(addrP1[1])) connP1.send("Hey! Welcome to Opale game. What's your name?\n> ".encode()) print('Asking Player1 name...') nameP1 = connP1.recv(1024).decode().strip() if nameP1 == "watcher": print("new Watcher") watchers.append(connP1) connP1.send(("Welcome! You'll watch futher games. Wait for one... :)\n").encode()) continue else: connP1.send(("Welcome \033[93m%s\033[0m! We are waiting for a second player...\n" % nameP1).encode()) connP1.send("\n\nWould you like to load a saved game? (leave blank and press ENTER to load a new game)\n> ".encode()) connP2, addrP2 = s.accept() print('Connected with ' + addrP2[0] + ':' + str(addrP2[1])) connP2.send("Hey! Welcome to Opale game. What's your name?\n> ".encode()) print('Asking Player2 name...') nameP2 = "" while len(nameP2) == 0 or nameP2 == nameP1: if nameP2 == nameP1: connP2.send("Name conflict! Please choose another name: ".encode()) nameP2 = connP2.recv(1024).decode().strip() connP2.send(("Welcome \033[93m%s\033[0m! We are ready to play. You'll fight against \033[93m%s\033[0m!\n" % (nameP2, nameP1)).encode()) connP1.send(("\nYou'll fight against \033[93m%s\033[0m" % nameP2).encode()) saved_games = [k for k in games.keys() if (games[k].player1.name == nameP1 and games[k].player2.name == nameP2) or (games[k].player1.name == nameP2 and games[k].player2.name == nameP1)] if len(saved_games): connP1.send(("\nHere is a list of saved games together: %s\n" % saved_games).encode()) choice = "sentinel" erchoice = "" while len(choice) != 0 and choice not in games: if choice != "sentinel": erchoice = choice connP1.send(("No game exists with this identifier. Retry (or type the same choice to use it as seed):\n> ").encode()) choice = connP1.recv(1024).decode().strip() if erchoice == choice: break connP1.send((chr(27) + "[2J").encode()) connP2.send((chr(27) + "[2J").encode()) if choice not in games: if len(choice) == 0: choice = str(uuid.uuid1()) random.seed(choice) game = Game(nameP1, nameP2) games[choice] = game connP1.send(("\n\nYou entered a new game.\nSave the id of the room if you loose the connection for any reason: %s\n" % choice).encode()) connP2.send(("\n\nYou entered a new game.\nSave the id of the room if you loose the connection for any reason: %s\n" % choice).encode()) print("Play new game between %s and %s: %s" % (nameP1, nameP2, choice)) else: game = games[choice] if game.player1.name == nameP2 or game.player2.name == nameP1: game.player2,game.player1 = game.player1,game.player2 game.round -= 1 game.player1.name = nameP1 game.player2.name = nameP2 connP1.send(("You entered a saved game (%s); \033[93m%s\033[0m takes the place of \033[94m%s\033[0m, \033[93m%s\033[0m the place of \033[94m%s\033[0m.\n" % (choice, nameP1, game.player1.name, nameP2, game.player2.name)).encode()) connP2.send(("You entered a saved game (%s); \033[93m%s\033[0m takes the place of \033[94m%s\033[0m, \033[93m%s\033[0m the place of \033[94m%s\033[0m.\n" % (choice, nameP1, game.player1.name, nameP2, game.player2.name)).encode()) connP1.send(("\n\nWelcome back! We are at round %d. \033[96m%d citie(s) discovered.\033[0m \033[93m%s\033[0m collected %d cards, you collected %d card(s).\n" % (game.round // 2, game.board.roundCity, game.player2.name, len(game.player2.défausse), len(game.player1.défausse))).encode()) connP2.send(("\n\nWelcome back! We are at round %d. \033[96m%d citie(s) discovered.\033[0m \033[93m%s\033[0m collected %d cards, you collected %d card(s).\n" % (game.round // 2, game.board.roundCity, game.player1.name, len(game.player1.défausse), len(game.player2.défausse))).encode()) game.player1.print = functools.partial(writeSocket, connP1) game.player2.print = functools.partial(writeSocket, connP2) game.player1.input = functools.partial(readSocket, connP1) game.player2.input = functools.partial(readSocket, connP2) def printWatchers(*args): for w in watchers: try: writeSocket(w, *args) except: try: w.close() except: pass watchers.remove(w) def printBoth(*args): game.player1.print(*args) game.player2.print(*args) printWatchers(*args) def play_turn(): printWatchers("\n\033[1mCurrent player:\033[0m \033[93m%s\033[0m \033[95m%s\033[0m" % (game.current_player.name, "DRAGON" if game.current_player.dragonPetrified else "")) game.current_player.print("\n\033[1mCurrent player:\033[0m \033[93m%s\033[0m \033[95m%s\033[0m" % (game.current_player.name, "DRAGON" if game.current_player.dragonPetrified else "")) game.current_partner.print("\n\033[1mCurrent player:\033[0m \033[96m%s\033[0m \033[95m%s\033[0m" % (game.current_player.name, "DRAGON" if game.current_player.dragonPetrified else "")) while True: printBoth(game.board) game.current_player.print("\033[1mHere is your hand currently:\033[0m %s" % {i+1: game.current_player.hand[i] for i in range(len(game.current_player.hand))}) game.current_partner.print("\033[1mHere is your hand currently:\033[0m %s" % {i+1: game.current_partner.hand[i] for i in range(len(game.current_partner.hand))}) game.current_partner.print("\n =============:[ Please wait until \033[1;96m" + game.current_player.name + "\033[0m plays... :-) ]:=============\r",None) printWatchers("\n =============:[ Please wait until \033[1;96m" + game.current_player.name + "\033[0m plays... :-) ]:=============\r",None) icards = game.current_player.input("\nChoose one or more card to play: ") pcards = map(lambda x: int(x), icards.split(" ")) good = True cards = [] for card in pcards: if card <= 0 or card > len(game.current_player.hand): game.current_player.print("\033[91m%s is not a valid card.\033[0m" % card) good = False break else: cards.append(game.current_player.hand[card-1]) if good: try: game.play_round(*cards) return cards except Exception as e: game.current_player.print("\033[91m%s\033[0m" % e) while not game.isFinished(): with open('saved_games.pickle', 'wb') as f: ip1 = game.player1.input del game.player1.input ip2 = game.player2.input del game.player2.input pp1 = game.player1.print del game.player1.print pp2 = game.player2.print del game.player2.print pickle.dump(games, f, pickle.HIGHEST_PROTOCOL) game.player1.input = ip1 game.player2.input = ip2 game.player1.print = pp1 game.player2.print = pp2 curRound = game.board.roundCity hasDragon = game.current_player.dragonPetrified try: cards = play_turn() except BrokenPipeError as e: raise e except Exception as e: raise e game.current_player.print("\033[91mSorry, something goes wrong: '%s'.\033[0m" % e) pass printBoth(chr(27) + "[2J") game.current_player.print("\n\033[93m%s\033[0m plays: %s\n" % (game.current_partner.name, cards)) printWatchers("\n\033[93m%s\033[0m plays: %s\n" % (game.current_partner.name, cards)) game.current_partner.print("\nYou played: %s\n" % (cards)) if game.current_partner.dragonPetrified != hasDragon: game.current_player.print("\n\033[1;93m%s\033[95m takes the petrified dragon!\033[0m\n" % game.current_partner.name) printWatchers("\n\033[1;93m%s\033[95m takes the petrified dragon!\033[0m\n" % game.current_partner.name) game.current_partner.print("\n\033[95mYou take the petrified dragon!\033[0m\n") if curRound != game.board.roundCity and game.board.roundCity < 3: game.current_player.print("\n\033[1;93m%s\033[96m discovers a new lost city! \033[1m%d/%d\033[0m\n" % (game.current_partner.name, game.board.roundCity, 3)) printWatchers("\n\033[1;93m%s\033[96m discovers a new lost city! \033[1m%d/%d\033[0m\n" % (game.current_partner.name, game.board.roundCity, 3)) game.current_partner.print("\n\033[96mYou discover a new lost city! \033[1m%d/%d\033[0m\n" % (game.board.roundCity, 3)) if game.player1.cantpioche: printBoth("\n\033[1;93m%s n'a plus de pioche ! Last round\033[0m" % game.player1.name) elif game.player2.cantpioche: printBoth("\n\033[1;93m%s n'a plus de pioche ! Last round\033[0m" % game.player2.name) else: printBoth("\n\033[1;96mCité sous-marine découverte ! Last round\033[0m") try: play_turn() except BrokenPipeError as e: raise e except Exception as e: game.current_player.print("\033[91mSorry, something goes wrong: '%s'.\033[0m" % e) pass printBoth(game.board) printBoth("\n") printBoth("\033[93m%s\033[0m: \033[1m%d\033[0m pts" % (game.current_player.name, game.current_player.get_score())) printBoth("\033[93m%s\033[0m: \033[1m%d\033[0m pts" % (game.current_partner.name, game.current_partner.get_score())) del games[choice] connP1.send(("\n\nFinished! See you next time " + nameP1 + "!\n\n\n").encode()) connP2.send(("\n\nFinished! See you next time " + nameP2 + "!\n\n\n").encode()) connP1.close() connP2.close() except BrokenPipeError as e: print(e) finally: try: connP1.send(("\nConnection lost with the other player. Save the game id to continuer later (you were player 1): " + choice + "\n").encode()) connP1.close() except: pass try: connP2.send(("\nConnection lost with the other player. Save the game id to continuer later (you were player 2): " + choice + "\n").encode()) connP2.close() except: pass s.close()