#!/usr/bin/env python

from __future__ import print_function
from sys import argv, exit
import random

class Player:
    def __init__(self, name, strategy):
        self.name = name
        self.strategy = strategy
    def __str__(self):
        return self.name
    def __repr__(self):
        if hasattr(self, 'card'):
            return "Player(%s, %s, %d)" % (self.name, self.card, self.strategy)
        else:
            return "Player(%s, %d)" % (self.name, self.strategy)

    def guess(self, otherCards):
        parity = getParity(otherCards)
        guess = (self.strategy - parity) % divisor
        return suits[guess]

player_names = ['Alice', 'Bob', 'Cathy', 'Dave']
suits   = ['Clubs', 'Diamonds', 'Hearts', 'Spades']
suitValues = { suits[i]:i for i in range(0, len(suits)) }
players = [ Player(player_names[i], i) for i in range(0, len(suits)) ]
divisor = len(suits)
runs    = 10
fails   = 0
passes  = 0

def main():
    # Number of runs given on command-line?
    global runs
    if len(argv) > 1: runs = int(argv[1])

    for i in range(0, runs):
        oneRun(i)

    print()
    print("--------------------")
    print("Total runs: %d" % runs)
    print("Total passed: %d" % passes)
    print("Total failed: %d" % fails)
    print()
    print("End.")

def oneRun(run):
    global fails, passes

    print()
    print("Run %d:" % run)

    for p in players:
        p.card = random.choice(suits)
    print("Table: %s" % repr(players))

    success = False
    for p in players:
        others = getOtherPlayers(p)
        print("Player %s sees %s" % (str(p), [o.card for o in others]))
        cards = [ x.card for x in others ]
        guess = p.guess(cards)
        print("Player guesses %s, which is %s." % (guess,
            ('RIGHT' if guess == p.card else 'WRONG')))
        if guess == p.card: success = True
    if success:
        print("Players WIN!!")
        passes = passes + 1
    else:
        print("Players LOSE!!!!!!!!\a\a\a")
        fails = fails + 1
        sys.exit(1)

def getOtherPlayers(player):
    return [ x for x in players if x is not player ]

def getParity(cards):
    parity = 0
    for c in cards:
        parity = parity + suitValues[c]
    return parity

if __name__ == '__main__':
    main()
