Task

Implement the classic children's game Rock-paper-scissors, as well as a simple predictive   AI   (artificial intelligence)   player.

Rock Paper Scissors is a two player game.

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, the computer will be one of the players.

The operator will select Rock, Paper or Scissors and the computer will keep a record of the choice frequency, and use that information to make a weighted random choice in an attempt to defeat its opponent.



Extra credit

Support additional choices   additional weapons.




 
include random.fs
 
0 value aiwins
0 value plwins
 
10 constant inlim
0  constant rock
1  constant paper
2  constant scissors
 
create rpshistory 0 , 0 , 0 ,
create inversemove 1 , 2 , 0 ,
3 constant historylen
 
: @a ( n array -- )
    swap cells + @ ;
 
: sum-history ( -- n )
    0 historylen 0 ?do
	i rpshistory @a 1+ + loop ;
 
: probable-choice ( -- n ) \ Simple linear search
    sum-history random
    historylen 0 ?do
	i rpshistory @a -
	dup 0< if drop i leave then
    loop inversemove @a ;
 
: rps-print ( addr u -- )
    cr type ;
 
: rpslog. ( -- )
    s"       ROCK    PAPER   SCISSORS  AI/W  PL/W" rps-print cr
    3 0 do i cells rpshistory + @ 9 u.r  loop aiwins 7 u.r plwins 6 u.r cr ;
 
create rpswords ' rock , ' paper , ' scissors , ' quit ,
 
: update-history! ( n -- )
    cells rpshistory + 1 swap +! ;
 
: thrown. ( n -- addr u )
    cells rpswords + @ name>string ;
 
: throws. ( n n -- )
    thrown. s" AI threw:  " 2swap s+ rps-print
    thrown. s" You threw: " 2swap s+ rps-print ;
 
: print-throws ( n n -- )
    rpslog. throws. ;
 
: tie. ( n n -- )
    s" Tie. " rps-print ;
 
: plwin ( n n -- )
    1 +to plwins s" You win. " rps-print ;
 
: aiwin ( n n -- )
    1 +to aiwins s" AI wins. " rps-print ;
 
create rpsstates ' tie. , ' plwin , ' aiwin ,
 
: determine-winner ( n n -- )
    >r abs r> abs - 3 + 3 mod
    cells rpsstates + @  execute ;
 
: rps-validate ( name -- )  ( Rude way of checking for only valid commands )
    4 0 do i cells rpswords + @ over = swap loop drop or or or ;
 
: rps-prompt. ( -- )
    s" Enter choice (rock, paper, scissors or quit):   " rps-print ;
 
: player-choice ( -- n ) recursive
    pad inlim accept pad swap find-name
    dup rps-validate if execute
    else drop rps-prompt. player-choice then ;
 
: update-log ( n n -- )
    update-history! update-history! ;
 
: rps ( -- ) recursive
    rps-prompt. player-choice probable-choice
    2dup update-log 2dup print-throws
    determine-winner rps ; 
 