Rock-paper-scissors: Difference between revisions

From Rosetta Code
Content added Content deleted
(Whups. buildPair was for an older revision of my code.)
(Added Ada version)
Line 10: Line 10:


For this task's AI player, keep track of the player's choice frequency, and use that choice frequency to make a [[Probabilistic choice|weighted random choice]] to beat the player's likely choice.
For this task's AI player, keep track of the player's choice frequency, and use that choice frequency to make a [[Probabilistic choice|weighted random choice]] to beat the player's likely choice.
=={{header|Ada}}==

<lang Ada>with Ada.Text_IO; with Ada.Numerics.Float_Random;

procedure Rock_Paper_Scissors is

package Rand renames Ada.Numerics.Float_Random;
Gen: Rand.Generator;

type Choice is (Rock, Paper, Scissors);

Cnt: array (Choice) of Natural := (1, 1, 1);
-- pretend that each of R., P., and S., has been played once by the human

function Computer_Choice return Choice is
Random_Number: Natural :=
Integer(Rand.Random(Gen)
* (Float(Cnt(Rock)) + Float(Cnt(Paper)) + Float(Cnt(Scissors))));
begin
if Random_Number < Cnt(Rock) then
-- guess the human will choose Rock
return Paper;
elsif Random_Number - Cnt(Rock) < Cnt(Paper) then
-- guess the human will choose Paper
return Scissors;
else -- guess the human will choose Scissors
return Rock;
end if;
end Computer_Choice;

Finish_The_Game: exception;

function Human_Choice return Choice is
Done: Boolean := False;
T: constant String
:= "enter ""r"" for Rock, ""p"" for Paper, or ""s"" for Scissors""!";
U: constant String
:= "or enter ""q"" to Quit the game";
Result: Choice;
begin
Ada.Text_IO.Put_Line(T);
Ada.Text_IO.Put_Line(U);
while not Done loop
Done := True;
declare
S: String := Ada.Text_IO.Get_Line;
begin
if S="r" or S="R" then
Result := Rock;
elsif S="p" or S = "P" then
Result := Paper;
elsif S="s" or S="S" then
Result := Scissors;
elsif S="q" or S="Q" then
raise Finish_The_Game;
else
Done := False;
end if;
end;
end loop;
return Result;
end Human_Choice;

type Result is (Human_Wins, Draw, Computer_Wins);

function "<" (X, Y: Choice) return Boolean is
-- X < Y if X looses against Y
begin
case X is
when Rock => return (Y = Paper);
when Paper => return (Y = Scissors);
when Scissors => return (Y = Rock);
end case;
end "<";

Score: array(Result) of Natural := (0, 0, 0);

C,H: Choice;

Res: Result;

begin
-- play the game
loop
C := Computer_Choice; -- computer choice made first
H := Human_Choice; -- now as the player for his/her choice
Cnt(H) := Cnt(H) + 1; -- update the counts for the AI
if C < H then
Res := Human_Wins;
elsif H < C then
Res := Computer_Wins;
else
Res := Draw;
end if;
Ada.Text_IO.Put_Line("COMPUTER'S CHOICE: " & Choice'Image(C)
& " RESULT: " & Result'Image(Res));
Ada.Text_IO.New_Line;
Score(Res) := Score(Res) + 1;
end loop;

exception
when Finish_The_Game =>
Ada.Text_IO.New_Line;
for R in Score'Range loop
Ada.Text_IO.Put_Line(Result'Image(R) & Natural'Image(Score(R)));
end loop;
end Rock_Paper_Scissors;</lang>

First and last few lines of the output of a game, where the human did permanently choose Rock:

<pre>./rock_paper_scissors
enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: SCISSORS RESULT: HUMAN_WINS

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: ROCK RESULT: DRAW

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: SCISSORS RESULT: HUMAN_WINS

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: ROCK RESULT: DRAW


[...]


enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: ROCK RESULT: DRAW

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: PAPER RESULT: COMPUTER_WINS

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
q

HUMAN_WINS 2
DRAW 5
COMPUTER_WINS 21</pre>


=={{header|Python}}==
=={{header|Python}}==

Revision as of 10:00, 5 July 2011

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 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.

Ada

<lang Ada>with Ada.Text_IO; with Ada.Numerics.Float_Random;

procedure Rock_Paper_Scissors is

  package Rand renames Ada.Numerics.Float_Random;
  Gen: Rand.Generator;
  type Choice is (Rock, Paper, Scissors);
  Cnt: array (Choice) of Natural := (1, 1, 1);
    -- pretend that each of R., P., and S., has been played once by the human
  function Computer_Choice return Choice is
     Random_Number: Natural :=
       Integer(Rand.Random(Gen)
         * (Float(Cnt(Rock)) + Float(Cnt(Paper)) + Float(Cnt(Scissors))));
  begin
     if Random_Number < Cnt(Rock) then
        -- guess the human will choose Rock
        return Paper;
     elsif Random_Number - Cnt(Rock) < Cnt(Paper) then
        -- guess the human will choose Paper
        return Scissors;
     else -- guess the human will choose Scissors
        return Rock;
     end if;
  end Computer_Choice;
  Finish_The_Game: exception;
  function Human_Choice return Choice is
     Done: Boolean := False;
     T: constant String
       := "enter ""r"" for Rock, ""p"" for Paper, or ""s"" for Scissors""!";
     U: constant String
       := "or enter ""q"" to Quit the game";
     Result: Choice;
  begin
     Ada.Text_IO.Put_Line(T);
     Ada.Text_IO.Put_Line(U);
     while not Done loop
        Done := True;
        declare
           S: String := Ada.Text_IO.Get_Line;
        begin
           if S="r" or S="R" then
              Result := Rock;
           elsif S="p" or S = "P" then
              Result := Paper;
           elsif S="s" or S="S" then
              Result := Scissors;
           elsif S="q" or S="Q" then
              raise Finish_The_Game;
           else
              Done := False;
           end if;
        end;
     end loop;
     return Result;
  end Human_Choice;
  type Result is (Human_Wins, Draw, Computer_Wins);
  function "<" (X, Y: Choice) return Boolean is
     -- X < Y if X looses against Y
  begin
     case X is
        when Rock => return  (Y = Paper);
        when Paper => return (Y = Scissors);
        when Scissors => return (Y = Rock);
     end case;
  end "<";
  Score: array(Result) of Natural := (0, 0, 0);
  C,H: Choice;
  Res: Result;

begin

  -- play the game
  loop
     C := Computer_Choice;  -- computer choice made first
     H := Human_Choice;     -- now as the player for his/her choice
     Cnt(H) := Cnt(H) + 1;  -- update the counts for the AI
     if C < H then
        Res := Human_Wins;
     elsif H < C then
        Res := Computer_Wins;
     else
        Res := Draw;
     end if;
     Ada.Text_IO.Put_Line("COMPUTER'S CHOICE: " & Choice'Image(C)
                            & "       RESULT: " & Result'Image(Res));
     Ada.Text_IO.New_Line;
     Score(Res) := Score(Res) + 1;
  end loop;

exception

  when Finish_The_Game =>
     Ada.Text_IO.New_Line;
     for R in Score'Range loop
        Ada.Text_IO.Put_Line(Result'Image(R) & Natural'Image(Score(R)));
     end loop;

end Rock_Paper_Scissors;</lang>

First and last few lines of the output of a game, where the human did permanently choose Rock:

./rock_paper_scissors 
enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: SCISSORS       RESULT: HUMAN_WINS

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: ROCK       RESULT: DRAW

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: SCISSORS       RESULT: HUMAN_WINS

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: ROCK       RESULT: DRAW


[...]


enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: ROCK       RESULT: DRAW

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
r
COMPUTER'S CHOICE: PAPER       RESULT: COMPUTER_WINS

enter "r" for Rock, "p" for Paper, or "s" for Scissors"!
or enter "q" to Quit the game
q

HUMAN_WINS 2
DRAW 5
COMPUTER_WINS 21

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 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!"