Rock-paper-scissors

From Rosetta Code
Revision as of 15:25, 4 July 2011 by MikeMol (talk | contribs) (Draft task, first example)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Rock-paper-scissors is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

In this task, the goal is to implement the classic children's game wp:Rock Paper Scissors, as well as a simple predictive AI player.

Rock Paper Scissors has two players. Each player chooses one of rock, paper or scissors, without knowing the other player's choice. The winner is decided by a set of rules:

  • Rock beats scissors
  • Scissors beat paper
  • Paper beats rock.

If both players choose the same thing, there is no winner for that round.

For this task's AI player, keep track of the player's choice frequency, and use that choice frequency to make a weighted random choice to beat the player's likely choice.

Python

<lang python>#!/usr/bin/python from random import randint, random from operator import add from functools import reduce from bisect import bisect_left

WHATBEATS = { 'paper' : 'scissors',

               'scissors' : 'rock',
               'rock' : 'paper'        }

ORDER = ('rock', 'paper', 'scissors')

CHOICEFREQUENCY = {}

def probChoice(choices, probabilities):

   scalefactor = reduce(add, probabilities)
   prob_accumulator = 0
   accumulator = []
   for p in probabilities:
       prob_accumulator += float(p) / scalefactor
       accumulator.append(prob_accumulator)
   r = random()
   bsct = bisect_left(accumulator, r)
   chc = choices[bsct]
   return chc

def buildPair(a, b):

   global ORDER
   # This will loop through ORDER, from the first element to the last. The
   # elements are the order we'll use for sorting. (Particularly important for
   # lookups in our RULES dictionary)
   for higher in ORDER:
       # If this element is in either a or b, then this element should come
       # should come first in the tuple we return.
       if higher == a:
           return (a,b)
       elif higher == b:
           return (b,a)

def checkWinner(a, b):

   global WHATBEATS
   abeater = WHATBEATS[a]
   bbeater = WHATBEATS[b]
   if b == abeater:
       return b
   elif a == bbeater:
       return a
   return None

def sanitizeChoice(a):

   # Drop it to lower-case
   return a.lower()

def registerPlayerChoice(choice):

   global CHOICEFREQUENCY
   if choice in CHOICEFREQUENCY:
       CHOICEFREQUENCY[choice] += 1
   else:
       CHOICEFREQUENCY[choice] = 1

def getRandomChoice():

   global WHATBEATS
   global ORDER
   global CHOICEFREQUENCY
   if len(CHOICEFREQUENCY.keys()) == 0:
       return ORDER[randint(0,len(ORDER)-1)]
   choices = CHOICEFREQUENCY.keys()
   probabilities = CHOICEFREQUENCY.values()
   return WHATBEATS[probChoice(choices, probabilities)]

while True:

   choice = raw_input()
   choice = sanitizeChoice(choice)
   if not choice in ORDER:
       continue
   compChoice = getRandomChoice()
   print "Computer picked", compChoice,
   # Don't register the player choice until after the computer has made
   # its choice.
   registerPlayerChoice(choice)
   winner = checkWinner(choice, compChoice)
   if winner == None:
       winner = "nobody"
   print winner, "wins!"