#: c11:PaperScissorsRock2.py
# Multiple dispatching using a table
from __future__ import generators
import random

class Outcome:
  def __init__(self, value, name): 
    self.value = value
    self.name = name
  def __str__(self): return self.name 
  def __eq__(self, other):
      return self.value == other.value

Outcome.WIN = Outcome(0, "win")
Outcome.LOSE = Outcome(1, "lose")
Outcome.DRAW = Outcome(2, "draw")

class Item(object):
  def compete(self, item):
    # Use a tuple for table lookup:
    return outcome[self.__class__, item.__class__]
  def __str__(self): 
    return self.__class__.__name__ 

class Paper(Item): pass
class Scissors(Item): pass
class Rock(Item): pass

outcome = {
  (Paper, Rock): Outcome.WIN,
  (Paper, Scissors): Outcome.LOSE,
  (Paper, Paper): Outcome.DRAW,
  (Scissors, Paper): Outcome.WIN,
  (Scissors, Rock): Outcome.LOSE,
  (Scissors, Scissors): Outcome.DRAW,
  (Rock, Scissors): Outcome.WIN,
  (Rock, Paper): Outcome.LOSE,
  (Rock, Rock): Outcome.DRAW,
}

def match(item1, item2):
  print "%s <--> %s : %s" % (
    item1, item2, item1.compete(item2))

# Generate the items:
def itemPairGen(n):
  # Create a list of instances of all Items:
  Items = Item.__subclasses__()
  for i in range(n):
    yield (random.choice(Items)(), 
           random.choice(Items)())

for item1, item2 in itemPairGen(20):
  match(item1, item2)
#:~