Pig the dice game/Player: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
(→‎{{header|REXX}}: included output from the REXX program.)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(48 intermediate revisions by 15 users not shown)
Line 1:
[[Category:Games]]
 
{{task}}
 
__FORCETOC__
;Task:
The task is to create a dice simulator and scorer of [[Pig the dice game]] and add to it the ability to play the game to at least one strategy.
Create a dice simulator and scorer of [[Pig the dice game]] and add to it the ability to play the game to at least one strategy.
* State here the play strategies involved.
* Show play during a game here.
 
 
As a stretch goal:
* Simulate playing the game a number of times with two players of given strategies and report here summary statistics such as, but not restricted to, the influence of going first or which strategy seems stronger.
 
 
;Game Rules:
Line 16 ⟶ 21:
# '''Holding''': The player's score for that round is added to their total and becomes safe from the effects of throwing a one. The player's turn finishes with play passing to the next player.
 
 
;Reference
;References
* [[wp:Pig (dice)|Pig (dice)]]
* [https://youtu.be/ULhRLGzoXQ0 The Math of Being a Pig] and [https://www.youtube.com/watch?v=zD9-V9Idbug Pigs (extra)] - Numberphile videos featuring Ben Sparks.
<br><br>
 
=={{header|Ada}}==
Line 27 ⟶ 35:
The implementation reads five parameters from the command line, in that order: (1) N the number of games to play, (2) the Bound for the first player, (3) the Final_Run for the first player, (4) the Bound for the second player and (5) the Final_Run for the second player. After reading these from the command line (or accepting reasonable defaults), it plays the game N times and counts how often either player wins.
 
<langsyntaxhighlight Adalang="ada">with Pig; with Ada.Text_IO; with Ada.Command_Line;
 
procedure automatic_Pig is
Line 63 ⟶ 71:
Ada.Text_IO.Put_Line(Natural'Image(Win_Count(True)) &
Natural'Image(Win_Count(False)));
end Automatic_Pig;</langsyntaxhighlight>
 
 
Line 80 ⟶ 88:
 
Requires additional file from [[Pig the dice game/Player/AutoHotkey]]
<langsyntaxhighlight lang="autohotkey">#NoEnv
SetBatchLines, -1
#SingleInstance, Force
Line 153 ⟶ 161:
Roll := Optimal[SumMe,TurnSum,SumOpp+1]
Return Roll = "" ? 1 : Roll
}</langsyntaxhighlight>
{{out}}
<table border=1 cellpadding=1 cellspacing=0 width=500 style='table-layout:fixed;width:375pt'>
Line 306 ⟶ 314:
Player 3 always tries to score at least 20 points in a round.<br />
Player 4, just like player 3, always tries to score at least 20 points in a round. But as his round score increases, he gets a little "nervous", what increases the chances that he'll hold.
<langsyntaxhighlight lang="cpp">
#include <windows.h>
#include <iostream>
Line 466 ⟶ 474:
}
//--------------------------------------------------------------------------------------------------
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 630 ⟶ 638:
=={{header|Common Lisp}}==
Just implemented two strategies. One is actually a variable strategy which holds until a specific value is reached and then turns the dice over. The default value is 25. The other is from "Practical Play of the Dice Game Pig" by ToddW. Neller and Clifton G.M. Presser. Their suggested strategy is "If either player’s score is 71 or higher, roll for the goal. Otherwise, hold at 21 + (j - i) / 8" where j is the other player's score and i is the strategizing player's score. The scoring is handled by generic functions on the player type.
<langsyntaxhighlight lang="lisp">(defclass player ()
((score :initform 0 :accessor score)
(name :initarg :name :accessor name)))
Line 690 ⟶ 698:
 
(defun play-pig-player (player1 player2)
(catch 'quit (format t "Hooray! ~A won the game!"</langsyntaxhighlight>
Output:
<syntaxhighlight lang="text">Darrell: Rolled a 4 - Turn: 4 Current Score: 4 Keep rolling (Y, N or Q)?Y
Darrell: Rolled a 3 - Turn: 7 Current Score: 7 Keep rolling (Y, N or Q)?Y
Darrell: Rolled a 3 - Turn: 10 Current Score: 10 Keep rolling (Y, N or Q)?Y
Line 794 ⟶ 802:
Darrell rolls a 3 and WINS!
Hooray! Darrell won the game!
NIL</langsyntaxhighlight>
 
=={{header|D}}==
{{trans|C++}}
<langsyntaxhighlight lang="d">import std.stdio, std.random;
 
enum nPlayers = 4, maxPoints = 100;
Line 924 ⟶ 932:
writeln("Player III (AL20): ", players[2].getCurrScore);
writeln("Player IV (AL20T): ", players[3].getCurrScore, "\n\n");
}</langsyntaxhighlight>
 
The output is similar to the C++ entry.
Line 930 ⟶ 938:
=={{header|Erlang}}==
Four players take turns starting. Their strategy is how long to wait before holding. They aim for 5, 10, 15 and 20 rolls. Player20 managed better than I thought it would.
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( pig_dice_player ).
 
Line 985 ⟶ 993:
Result
end.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 996 ⟶ 1,004:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package pig
 
import (
Line 1,186 ⟶ 1,194:
}
pg.PrintStatus(gameOverSummary)
}</langsyntaxhighlight>
Sample run, player one just tries to keep ahead, while player two always tries to take three rolls, no more.
<pre>
Line 1,388 ⟶ 1,396:
player 1 104
player 2 98
</pre>
 
=={{header|Haskell}}==
 
Implemented 4 strategies:
 
- player1 always rolls until he gets 20 or more
- player2 always rolls four times
- player3 rolls three times until she gets more than 60 points, then she rolls until she gets 20 or more
- player4 rolls 3/4 of the time, 1/4 he holds, but if he gets a score more than 75 he goes for the win
 
<syntaxhighlight lang="haskell">
{-# LANGUAGE ViewPatterns #-}
 
module Main where
 
import System.Random (randomRIO)
import Text.Printf (printf)
 
data PInfo = PInfo { stack :: Int
, score :: Int
, rolls :: Int
, next :: Bool
, won :: Bool
, name :: String
}
 
type Strategy = [PInfo] -> IO ()
 
roll :: [PInfo] -> IO [PInfo]
roll (pinfo:xs) = do
face <- randomRIO (1, 6)
case (face, face + stack pinfo + score pinfo) of
(1,_) -> do
printf "%s rolled 1 - stack is being resetted\n\n" (name pinfo)
return $ pinfo { stack = 0, rolls = 0, next = True } : xs
(_,x) | x >= 100 -> do
printf "%s rolled %i - stack is now %i + score %i => %i - I won!\n" (name pinfo) face (face + stack pinfo) (score pinfo) x
return $ pinfo { won = True } : xs
(_,_) -> do
printf "%s rolled %i - stack is now %i\n" (name pinfo) face (face + (stack pinfo))
return $ pinfo { stack = face + (stack pinfo), rolls = 1 + (rolls pinfo) } : xs
 
hold :: [PInfo] -> IO [PInfo]
hold (pinfo:xs) = do
let score' = stack pinfo + score pinfo
printf "%s holds - score is now %i\n\n" (name pinfo) score'
return $ pinfo { score = score', stack = 0, rolls = 0, next = True } : xs
 
 
logic :: Strategy -> Strategy -> Strategy
logic _ _ ((won -> True) : xs) = return ()
logic _ strat2 (p@(next -> True) : xs) = strat2 $ xs ++ [p { next = False }]
logic strat1 _ (pinfo : xs) = strat1 (pinfo : xs)
 
strat1 :: Strategy
strat1 (pinfo:xs)
| stack pinfo < 20 = roll (pinfo:xs) >>= logic strat1 strat2
| otherwise = hold (pinfo:xs) >>= logic strat1 strat2
 
strat2 :: Strategy
strat2 (pinfo:xs)
| rolls pinfo < 4 = roll (pinfo:xs) >>= logic strat2 strat3
| otherwise = hold (pinfo:xs) >>= logic strat2 strat3
 
strat3 :: Strategy
strat3 (pinfo:xs)
| rolls pinfo < 3 && score pinfo < 60 = roll (pinfo:xs) >>= logic strat3 strat4
| stack pinfo < 20 = roll (pinfo:xs) >>= logic strat3 strat4
| otherwise = hold (pinfo:xs) >>= logic strat3 strat4
 
strat4 :: Strategy
strat4 (pinfo:xs) | score pinfo > 75 = roll (pinfo:xs) >>= logic strat4 strat1
strat4 (pinfo:xs) = do
chance <- randomRIO (0, 3) :: IO Int
case chance of
0 -> hold (pinfo:xs) >>= logic strat4 strat1
_ -> roll (pinfo:xs) >>= logic strat4 strat1
 
main :: IO ()
main = do
let pInfo = PInfo 0 0 0 False False ""
p1 = pInfo { name = "Peter" }
p2 = pInfo { name = "Mia" }
p3 = pInfo { name = "Liz" }
p4 = pInfo { name = "Stephen" }
strat1 [p1, p2, p3, p4]
</syntaxhighlight>
 
Example output:
<pre>
 
Peter rolled 5 - stack is now 5
Peter rolled 5 - stack is now 10
Peter rolled 4 - stack is now 14
Peter rolled 6 - stack is now 20
Peter holds - score is now 20
 
Mia rolled 4 - stack is now 4
Mia rolled 1 - stack is being resetted
 
Liz rolled 4 - stack is now 4
Liz rolled 6 - stack is now 10
Liz rolled 4 - stack is now 14
Liz rolled 3 - stack is now 17
Liz rolled 3 - stack is now 20
Liz holds - score is now 20
 
Stephen rolled 6 - stack is now 6
Stephen rolled 1 - stack is being resetted
 
Peter rolled 3 - stack is now 3
Peter rolled 6 - stack is now 9
 
...
 
Stephen rolled 1 - stack is being resetted
 
Peter rolled 4 - stack is now 4
Peter rolled 2 - stack is now 6
Peter rolled 5 - stack is now 11
Peter rolled 2 - stack is now 13
Peter rolled 5 - stack is now 18
Peter rolled 6 - stack is now 24
Peter holds - score is now 87
 
Mia rolled 5 - stack is now 5
Mia rolled 1 - stack is being resetted
 
Liz rolled 3 - stack is now 3
Liz rolled 1 - stack is being resetted
 
Stephen rolled 6 - stack is now 6
Stephen rolled 2 - stack is now 8
Stephen rolled 5 - stack is now 13
Stephen rolled 4 - stack is now 17
Stephen holds - score is now 43
 
Peter rolled 4 - stack is now 4
Peter rolled 2 - stack is now 6
Peter rolled 5 - stack is now 11
Peter rolled 6 - stack is now 17 + score 87 => 104 - I won!
</pre>
 
To test the distribution by yourself (in parallel):
 
<syntaxhighlight lang="haskell">
 
-- add this to the top
import Control.Concurrent.ParallelIO.Global (parallel, stopGlobalPool)
import Data.List (sort, group)
 
-- replace "logic _ _ ((won -> True) : xs) = return ()" with
logic _ _ (p@(won -> True) : xs) = return $ name p
 
-- replace strat1 [p1, p2, p3, p4] in main with
let lists = replicate 100000 [p1, p2, p3, p4]
results <- parallel $ map strat1 lists
stopGlobalPool
print $ map length $ group $ sort results
 
-- replace type Strategy = [PInfo] -> IO () with
type Strategy = [PInfo] -> IO String
 
-- comment every printf in "roll" and "hold"
 
-- compile with
-- ghc FILENAME.hs -O2 -threaded -with-rtsopts="-N4" -o dice
 
</syntaxhighlight>
 
Distribution:
 
<pre>
 
Strat1 = 31878 => ~ 32%
Strat2 = 21953 => ~ 22%
Strat3 = 39022 => ~ 39%
Strat4 = 7147 => ~ 7%
 
out of 100 000 tests.
</pre>
 
Line 1,396 ⟶ 1,585:
 
If the expected value is positive, it's probably in the best interest of the player to take the roll. That said, a more sophisticated strategy might play cautiously when a player is sufficiently ahead of the other player(s).
<langsyntaxhighlight lang="j">pigval=:4 :0
(+/%#)(-x),}.(1+i.6)<.100-y+x
)</langsyntaxhighlight>
Examples:
<langsyntaxhighlight lang="j"> 10 pigval 90
_1.66667</langsyntaxhighlight>
If we have 10 points from our current rolls and have 90 permanent points, rolling again is a bad idea.
<langsyntaxhighlight lang="j"> 0 5 10 15 20 pigval"0/60 65 70 75 80 85 90 95 100
3.33333 3.33333 3.33333 3.33333 3.33333 3.33333 3.33333 3.16667 0
2.5 2.5 2.5 2.5 2.5 2.5 2.33333 _0.833333 _5
1.66667 1.66667 1.66667 1.66667 1.66667 1.5 _1.66667 _5.83333 _10
0.833333 0.833333 0.833333 0.833333 0.666667 _2.5 _6.66667 _10.8333 _15
0 0 0 _0.166667 _3.33333 _7.5 _11.6667 _15.8333 _20</langsyntaxhighlight>
If we have 70 permanent points (or less) we should probably re-roll when our uncommitted rolls total to less than 20.
<langsyntaxhighlight lang="j"> (1+i.19) ([,:1+i:~) +/ 0 < pigval"0/~ 1+i.100
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
98 97 96 95 93 92 91 90 89 87 86 85 84 82 81 80 78 77 75</langsyntaxhighlight>
This is a table of decision points. First row represents sum of our current uncommitted rolls. Second row represents the maximum permanent score where you should roll again with that number of uncommitted points, if we are using this estimation mechanism to choose our actions. Note that the first four columns here should have some obvious validity -- for example, if we have 96 permanent points and we have rolled 4 uncommitted points, we have won the game and we gain nothing from rerolling... Note also that this decision mechanism says we should never reroll if we have at least 20 uncommitted points.
 
=={{header|Perl 6Java}}==
This is a full implementation of pig dice with 4 built in bots. Their behavior can easily be modified and additional bots can be added as well.
 
This is the main file, Pigdice.java
This implements a pig player class where you can customize the strategy it uses. Pass a strategy code reference in that will evaluate to a Boolean value. The player will roll the die then decide whether to roll again or lock in its winnings based on its strategy. It will continue to roll until it gets a 1 (bust) or the strategy code reference evaluates to True (finished turn).
<syntaxhighlight lang="java">import java.util.Scanner;
 
public class Pigdice {
Set up as many players as you want, then run it. It will play 100 games (by default) then report the score for each game then the win totals for each player. If you want to play a different number of games, pass the number at the command line as a parameter.
 
public static void main(String[] args) {
Here we have 5 players:
Scanner scan = new Scanner(System.in);
player 0 uses the default strategy, always roll if it can.
int players = 0;
player 1 will roll up to 5 times then lock in whatever it earned.
player 2 will try to get at least 20 points per turn.
//Validate the input
player 3 randomly picks whether to roll again or not biased so that there is a 90% chance that it will.
while(true) {
player 4 randomly chooses to roll again but gets more consrvative as its score get closer to the goal.
//Get the number of players
System.out.println("Hello, welcome to Pig Dice the game! How many players? ");
if(scan.hasNextInt()) {
//Gotta be more than 0
int nextInt = scan.nextInt();
if(nextInt > 0) {
players = nextInt;
break;
}
}
else {
System.out.println("That wasn't an integer. Try again. \n");
scan.next();
}
}
System.out.println("Alright, starting with " + players + " players. \n");
//Start the game
play(players, scan);
scan.close();
}
public static void play(int group, Scanner scan) {
//Set the number of strategies available.
final int STRATEGIES = 5;
//Construct the dice- accepts an int as an arg for number of sides, but defaults to 6.
Dice dice = new Dice();
//Create an array of players and initialize them to defaults.
Player[] players = new Player[group];
for(int count = 0; count < group; count++) {
players[count] = new Player(count);
System.out.println("Player " + players[count].getNumber() + " is alive! ");
}
/*****Print strategy options here. Modify Player.java to add strategies. *****/
System.out.println("Each strategy is numbered 0 - " + (STRATEGIES - 1) + ". They are as follows: ");
System.out.println(">> Enter '0' for a human player. ");
System.out.println(">> Strategy 1 is a basic strategy where the AI rolls until 20+ points and holds unless the current max is 75+.");
System.out.println(">> Strategy 2 is a basic strategy where the AI, after 3 successful rolls, will randomly decide to roll or hold. ");
System.out.println(">> Strategy 3 is similar to strategy 2, except it's a little gutsier and will attempt 5 successful rolls. ");
System.out.println(">> Strategy 4 is like a mix between strategies 1 and 3. After turn points are >= 20 and while max points are still less than 75, it will randomly hold or roll. ");
//Get the strategy for each player
for(Player player : players) {
System.out.println("\nWhat strategy would you like player " + player.getNumber() + " to use? ");
 
//Validate the strategy is a real strategy.
<lang perl6>my $games = @*ARGS ?? (shift @*ARGS) !! 100;
while(true) {
if(scan.hasNextInt()) {
int nextInt = scan.nextInt();
if (nextInt < Strategy.STRATEGIES.length) {
player.setStrategy(Strategy.STRATEGIES[nextInt]);
break;
}
}
else {
System.out.println("That wasn't an option. Try again. ");
scan.next();
}
}
}
//Here is where the rules for the game are programmatically defined.
int max = 0;
while(max < 100) {
//Begin the round
for(Player player : players) {
System.out.println(">> Beginning Player " + player.getNumber() + "'s turn. ");
//Set the points for the turn to 0
player.setTurnPoints(0);
//Determine whether the player chooses to roll or hold.
player.setMax(max);
while(true) {
Move choice = player.choose();
if(choice == Move.ROLL) {
int roll = dice.roll();
System.out.println(" A " + roll + " was rolled. ");
player.setTurnPoints(player.getTurnPoints() + roll);
//Increment the player's built in iterator.
player.incIter();
//If the player rolls a 1, their turn is over and they gain 0 points this round.
if(roll == 1) {
player.setTurnPoints(0);
break;
}
}
//Check if the player held or not.
else {
System.out.println(" The player has held. ");
break;
}
}
//End the turn and add any accumulated points to the player's pool.
player.addPoints(player.getTurnPoints());
System.out.println(" Player " + player.getNumber() + "'s turn is now over. Their total is " + player.getPoints() + ". \n");
//Reset the player's built in iterator.
player.resetIter();
//Update the max score if necessary.
if(max < player.getPoints()) {
max = player.getPoints();
}
//If someone won, stop the game and announce the winner.
if(max >= 100) {
System.out.println("Player " + player.getNumber() + " wins with " + max + " points! End scores: ");
//Announce the final scores.
for(Player p : players) {
System.out.println("Player " + p.getNumber() + " had " + p.getPoints() + " points. ");
}
break;
}
}
}
}
}</syntaxhighlight>
 
This is the Player.java class file.
constant DIE = 1 .. 6;
<syntaxhighlight lang="java">public class Player {
constant GOAL = 100;
 
private int points = 0;
class player {
private int turnPoints = 0;
has $.score is rw = 0;
private Strategy strategy = null;
has $.ante is rw;
private int max = 0;
has $.rolls is rw;
private int number;
has &.strategy is rw = sub { False }; # default, always roll again
private int iter = 0;
public Player(int val) {
number = val;
}
public int getPoints() {
return points;
}
public int getTurnPoints() {
return turnPoints;
}
public int getMax() {
return max;
}
public int getNumber() {
return number;
}
public int getIter() {
return iter;
}
public void addPoints(int val) {
points += val;
}
public void setTurnPoints(int val) {
turnPoints = val;
}
public void setStrategy(Strategy strat) {
strategy = strat;
}
public void setMax(int val) {
max = val;
}
public void setNumber(int val) {
number = val;
}
public void resetIter() {
iter = 0;
}
public void incIter() {
iter++;
}
public void aiIntro() {
System.out.println(" Player " + getNumber() + "'s turn points are " + getTurnPoints() + ". Their total is " + getPoints() + ". ");
System.out.println(" The max points any player currently has is " + getMax() + ". ");
}
public Move choose() {
return strategy.choose(this);
}
 
}</syntaxhighlight>
method turn {
my $done_turn = False;
$.rolls = 0;
$.ante = 0;
repeat {
given DIE.roll {
$.rolls++;
when 1 {
$.ante = 0;
$done_turn = True;
}
when 2..* {
$.ante += $_;
}
}
$done_turn = True if $.score + $.ante >= GOAL or (&.strategy)();
} until $done_turn;
$.score += $.ante;
}
}
 
This is the Move.java class file.
my @players;
<syntaxhighlight lang="java">public enum Move { ROLL, HOLD }</syntaxhighlight>
 
This is the Strategy.java class file.
# default, go-for-broke, always roll again
<syntaxhighlight lang="java">import java.util.Scanner;
@players[0] = player.new;
 
public interface Strategy {
# try to roll 5 times but no more per turn
@players[1] = player.new( strategy => sub { @players[1].rolls >= 5 } );
 
Move choose(Player player);
# try to accumulate at least 20 points per turn
@players[2] = player.new( strategy => sub { @players[2].ante > 20 } );
static final Scanner str = new Scanner(System.in);
static final Dice die = new Dice(2);
static final int ROOF = 75;
static final int FLOOR = 20;
static final int BASEMENT = 10;
/*****MODIFY THIS AREA TO MODIFY THE STRATEGIES*****/
//Determine whether to roll or hold based on the strategy for this player.
public static final Strategy[] STRATEGIES = {
//Strategy 0 is a user-defined strategy
player -> {
System.out.println(" Your turn points are " + player.getTurnPoints() + ". Your total is " + player.getPoints() + ". ");
System.out.println(" The max points any player currently has is " + player.getMax() + ". (H)old or (R)oll?");
System.out.println(" Enter 'h' to hold and 'r' to roll. ");
while(true) {
String input = null;
if(str.hasNextLine()) {
input = str.nextLine();
}
if(input.contains("r")) {
return Move.ROLL;
}
else if(input.contains("h")) {
return Move.HOLD;
}
else {
System.out.println(" Enter an h or an r. \n");
System.out.println(input);
}
}
},
//Strategy 1 is a basic strategy where the AI rolls until 20+ points and holds unless the current max is 75+.
player -> {
player.aiIntro();
if(player.getTurnPoints() < FLOOR || player.getMax() >= ROOF) {
if(player.getTurnPoints() >= (100 - player.getPoints())) {
return Move.HOLD;
}
else {
return Move.ROLL;
}
}
else {
return Move.HOLD;
}
},
//Strategy 2 is a basic strategy where the AI, after 3 successful rolls, will randomly decide to roll or hold.
player -> {
player.aiIntro();
if(player.getPoints() == 0 && player.getTurnPoints() >= (BASEMENT / 2)) {
return Move.HOLD;
}
if(player.getIter() > 3) {
int roll = die.roll();
if(roll == 1) {
return Move.HOLD;
}
else {
return Move.ROLL;
}
}
else {
return Move.ROLL;
}
},
//Strategy 3 is similar to strategy 2, except it's a little gutsier and will attempt 5 successful rolls.
player -> {
player.aiIntro();
if(player.getIter() > 5) {
int roll = die.roll();
if(roll == 1) {
return Move.HOLD;
}
else {
return Move.ROLL;
}
}
else if(player.getPoints() < BASEMENT && player.getTurnPoints() > BASEMENT) {
return Move.HOLD;
}
else {
return Move.ROLL;
}
},
/*Strategy 4 is like a mix between strategies 1 and 3. After turn points are >= 20 and while max points are still less than 75, it will randomly hold or roll.
Unless their total is zero, in which case they'll hold at 10 points. */
player -> {
player.aiIntro();
if(player.getPoints() == 0 && player.getTurnPoints() >= (BASEMENT / 2)) {
return Move.HOLD;
}
else if(player.getTurnPoints() < FLOOR || player.getMax() >= ROOF) {
if(player.getTurnPoints() >= (100 - player.getPoints())) {
return Move.HOLD;
}
else {
return Move.ROLL;
}
}
else if(player.getTurnPoints() > FLOOR && player.getMax() <= ROOF) {
int roll = die.roll();
if(roll == 1) {
return Move.HOLD;
}
else {
return Move.ROLL;
}
}
else {
return Move.HOLD;
}
}
};
 
}</syntaxhighlight>
# random but 90% chance of rolling again
@players[3] = player.new( strategy => sub { 1.rand < .1 } );
 
And finally, this is the Dice.java class file. It's pretty self-explanatory.
# random but more conservative as approaches goal
<syntaxhighlight lang="java">import java.util.Random;
@players[4] = player.new( strategy => sub { 1.rand < ( GOAL - @players[4].score ) * .6 / GOAL } );
 
public class Dice {
my @wins = 0 xx @players;
Random rand = new Random();
int sides;
Dice(int numSides) {
sides = numSides;
}
Dice() {
sides = 6;
}
int roll() {
return rand.nextInt(sides) + 1;
}
}</syntaxhighlight>
 
Here's a small sample output using only bots (even though it fully supports human players too). A full game simulation can obviously be MUCH longer.
for ^ $games {
<pre>
my $player = -1;
Hello, welcome to Pig Dice the game! How many players?
repeat {
4
$player++;
Alright, starting with 4 players.
@players[$player % @players].turn;
} until @players[$player % @players].score >= GOAL;
 
Player 0 is alive!
@wins[$player % @players]++;
Player 1 is alive!
Player 2 is alive!
Player 3 is alive!
Each strategy is numbered 0 - 4. They are as follows:
>> Enter '0' for a human player.
>> Strategy 1 is a basic strategy where the AI rolls until 20+ points and holds unless the current max is 75+.
>> Strategy 2 is a basic strategy where the AI, after 3 successful rolls, will randomly decide to roll or hold.
>> Strategy 3 is similar to strategy 2, except it's a little gutsier and will attempt 5 successful rolls.
>> Strategy 4 is like a mix between strategies 1 and 3. After turn points are >= 20 and while max points are still less than 75, it will randomly hold or roll.
 
What strategy would you like player 0 to use?
say join "\t", @players>>.score;
1
@players[$_].score = 0 for ^@players; # reset scores for next game
What strategy would you like player 1 to use?
}
2
What strategy would you like player 2 to use?
3
What strategy would you like player 3 to use?
4
>> Beginning Player 0's turn.
Player 0's turn points are 0. Their total is 0.
The max points any player currently has is 0.
A 4 was rolled.
Player 0's turn points are 4. Their total is 0.
The max points any player currently has is 0.
A 4 was rolled.
Player 0's turn points are 8. Their total is 0.
The max points any player currently has is 0.
A 1 was rolled.
Player 0's turn is now over. Their total is 0.
 
>> Beginning Player 1's turn.
say "\nSCORES: for $games games";
say join "\t", @wins;</lang>
 
'''Sample output for 10000 games'''
<pre>
0 103 46 5 40
0 100 69 0 48
0 105 22 7 44
0 75 69 19 102
105 21 23 5 17
0 101 85 12 29
0 70 66 103 23
0 0 104 69 20
0 100 44 0 20
0 102 63 75 30
0 56 101 12 40
0 103 71 2 38
0 103 91 21 32
0 18 102 47 28
...
...
*SNIP*
...
...
104 0 69 14 47
Player 3 wins with 102 points! End scores:
0 68 101 13 22
Player 0 had 20 points.
0 99 89 102 31
Player 1 had 73 points.
Player 2 had 66 points.
Player 3 had 102 points.
</pre>
 
=={{header|Julia}}==
SCORES: for 10000 games
<syntaxhighlight lang="julia">mutable struct Player
947 3534 3396 1714 409
score::Int
ante::Int
wins::Int
losses::Int
strategy::Pair{String, Function}
end
 
randomchoicetostop(player, group) = rand(Bool)
variablerandtostop(player, group) = any(x -> x.score > player.score, group) ? rand() < 0.1 : rand(Bool)
overtwentystop(player, group) = player.ante > 20
over20unlesslosingstop(player, group) = player.ante > 20 && all(x -> x.score < 80, group)
 
const strategies = ("random choice to stop" => randomchoicetostop, "variable rand to stop" => variablerandtostop,
"roll to 20" => overtwentystop, "roll to 20 then if not losing stop" => over20unlesslosingstop)
const players = [Player(0, 0, 0, 0, s) for s in strategies]
const dice = collect(1:6)
 
function turn(player, verbose=false)
playernum = findfirst(p -> p == player, players)
scorewin() = for p in players if p == player p.wins += 1 else p.losses += 1 end; p.score = 0 end
player.ante = 0
while (r = rand(dice)) != 1
player.ante += r
verbose && println("Player $playernum rolls a $r.")
if player.score + player.ante >= 100
scorewin()
verbose && println("Player $playernum wins.\n")
return false
elseif player.strategy[2](player, players)
player.score += player.ante
verbose && println("Player $playernum holds and has a new score of $(player.score).")
return true
end
end
verbose && println("Player $playernum rolls a 1, so turn is over.")
true
end
 
function rungames(N)
for i in 1:N
verbose = (i == 3) ? true : false # do verbose if it's game number 3
curplayer = rand(collect(1:length(players)))
while turn(players[curplayer], verbose)
curplayer = curplayer >= length(players) ? 1 : curplayer + 1
end
end
results = sort([(p.wins/(p.wins + p.losses), p.strategy[1]) for p in players], rev=true)
println(" Strategy % of wins (N = $N)")
println("------------------------------------------------------------")
for pair in results
println(lpad(pair[2], 34), lpad(round(pair[1] * 100, digits=1), 18))
end
end
 
rungames(1000000)
</syntaxhighlight>{{out}}
<pre>
Player 3 rolls a 5.
Player 3 rolls a 3.
Player 3 rolls a 1, so turn is over.
Player 4 rolls a 6.
Player 4 rolls a 4.
Player 4 rolls a 3.
Player 4 rolls a 3.
Player 4 rolls a 4.
Player 4 rolls a 4.
Player 4 holds and has a new score of 24.
Player 1 rolls a 6.
Player 1 rolls a 3.
Player 1 holds and has a new score of 9.
Player 2 rolls a 4.
Player 2 rolls a 5.
Player 2 holds and has a new score of 9.
Player 3 rolls a 5.
Player 3 rolls a 5.
Player 3 rolls a 6.
Player 3 rolls a 2.
Player 3 rolls a 3.
Player 3 holds and has a new score of 21.
Player 4 rolls a 6.
Player 4 rolls a 3.
Player 4 rolls a 2.
Player 4 rolls a 5.
Player 4 rolls a 3.
Player 4 rolls a 2.
Player 4 holds and has a new score of 45.
Player 1 rolls a 5.
Player 1 holds and has a new score of 14.
Player 2 rolls a 1, so turn is over.
Player 3 rolls a 2.
Player 3 rolls a 3.
Player 3 rolls a 6.
Player 3 rolls a 5.
Player 3 rolls a 4.
Player 3 rolls a 1, so turn is over.
Player 4 rolls a 6.
Player 4 rolls a 6.
Player 4 rolls a 6.
Player 4 rolls a 4.
Player 4 holds and has a new score of 67.
Player 1 rolls a 1, so turn is over.
Player 2 rolls a 6.
Player 2 rolls a 4.
Player 2 rolls a 1, so turn is over.
Player 3 rolls a 3.
Player 3 rolls a 3.
Player 3 rolls a 3.
Player 3 rolls a 5.
Player 3 rolls a 3.
Player 3 rolls a 6.
Player 3 holds and has a new score of 44.
Player 4 rolls a 5.
Player 4 rolls a 1, so turn is over.
Player 1 rolls a 4.
Player 1 rolls a 5.
Player 1 holds and has a new score of 23.
Player 2 rolls a 6.
Player 2 rolls a 5.
Player 2 rolls a 6.
Player 2 rolls a 4.
Player 2 holds and has a new score of 30.
Player 3 rolls a 4.
Player 3 rolls a 4.
Player 3 rolls a 6.
Player 3 rolls a 6.
Player 3 rolls a 4.
Player 3 holds and has a new score of 68.
Player 4 rolls a 3.
Player 4 rolls a 2.
Player 4 rolls a 2.
Player 4 rolls a 6.
Player 4 rolls a 1, so turn is over.
Player 1 rolls a 5.
Player 1 holds and has a new score of 28.
Player 2 rolls a 2.
Player 2 rolls a 6.
Player 2 rolls a 1, so turn is over.
Player 3 rolls a 1, so turn is over.
Player 4 rolls a 6.
Player 4 rolls a 1, so turn is over.
Player 1 rolls a 2.
Player 1 rolls a 2.
Player 1 holds and has a new score of 32.
Player 2 rolls a 4.
Player 2 rolls a 5.
Player 2 rolls a 6.
Player 2 rolls a 5.
Player 2 rolls a 5.
Player 2 rolls a 2.
Player 2 rolls a 5.
Player 2 rolls a 6.
Player 2 rolls a 6.
Player 2 rolls a 1, so turn is over.
Player 3 rolls a 4.
Player 3 rolls a 1, so turn is over.
Player 4 rolls a 3.
Player 4 rolls a 5.
Player 4 rolls a 6.
Player 4 rolls a 4.
Player 4 rolls a 5.
Player 4 holds and has a new score of 90.
Player 1 rolls a 4.
Player 1 holds and has a new score of 36.
Player 2 rolls a 6.
Player 2 rolls a 1, so turn is over.
Player 3 rolls a 4.
Player 3 rolls a 2.
Player 3 rolls a 3.
Player 3 rolls a 1, so turn is over.
Player 4 rolls a 1, so turn is over.
Player 1 rolls a 6.
Player 1 rolls a 5.
Player 1 holds and has a new score of 47.
Player 2 rolls a 1, so turn is over.
Player 3 rolls a 2.
Player 3 rolls a 1, so turn is over.
Player 4 rolls a 5.
Player 4 rolls a 5.
Player 4 wins.
 
Strategy % of wins (N = 1000000)
------------------------------------------------------------
roll to 20 then if not losing stop 45.8
roll to 20 36.9
variable rand to stop 15.8
random choice to stop 1.5
</pre>
 
=={{header|RacketM2000 Interpreter}}==
Strategy like ADA, look if get 8 or more points and then look if other sum is lower from 100 from a min difference, and if it is true the choose Hold, else continue until win or dice=1.
{{output?|Racket}}
Same as [[Pig_the_dice_game#Racket]], with three strategy makers, and
simulation code for trying out strategies.
<lang racket>
#lang racket
 
This is version 2.
(define (pig-the-dice #:print? [print? #t] . players)
(define prn (if print? (λ xs (apply printf xs) (flush-output)) void))
(define names (for/list ([p players] [n (in-naturals 1)]) n))
(define points (for/list ([p players]) (box 0)))
(with-handlers ([(negate exn?) identity])
(for ([nm (in-cycle names)] [tp (in-cycle points)] [pl (in-cycle players)])
(prn (string-join (for/list ([n names] [p points])
(format "Player ~a, ~a points" n (unbox p)))
"; " #:before-first "Status: " #:after-last ".\n"))
(let turn ([p 0] [n 0])
(prn "Player ~a, round #~a, [R]oll or [P]ass? " nm (+ 1 n))
(define roll? (pl (unbox tp) p n))
(unless (eq? pl human) (prn "~a\n" (if roll? 'R 'P)))
(if (not roll?) (set-box! tp (+ (unbox tp) p))
(let ([r (+ 1 (random 6))])
(prn " Dice roll: ~s => " r)
(if (= r 1) (prn "turn lost\n")
(let ([p (+ p r)]) (prn "~a points\n" p) (turn p (+ 1 n)))))))
(prn "--------------------\n")
(when (<= 100 (unbox tp)) (prn "Player ~a wins!\n" nm) (raise nm)))))
 
We play the same strategy pair two times, second in reverse
(define (human total-points turn-points round#)
Even for 20+20 games strategy 12, 20 wins 8, 10
(case (string->symbol (car (regexp-match #px"[A-Za-z]?" (read-line))))
[(R r) #t] [(P p) #f] [else (human total-points turn-points round#)]))
 
<syntaxhighlight lang="m2000 interpreter">
;; Always do N rolls
Module GamePig (games, strategy1, strategy2) {
(define ((n-rounds n) total-points turn-points round#) (< round# n))
;; Roll until a given number Print "Game of pointsPig"
win1=0
(define ((n-points n) total-points turn-points round#) (< turn-points n))
win2=0
;; Random decision
While games {
(define ((n-random n) total-points turn-points round#) (zero? (random n)))
games--
dice=-1
res$=""
Player1points=0
Player1sum=0
Player2points=0
Player2sum=0
HaveWin=False
score()
\\ for simulation
simulate$=String$("R", 500)
Keyboard simulate$
\\ end simulation
while res$<>"Q" {
Print "Player 1 turn"
PlayerTurn(&Player1points, &player1sum, player2sum, ! strategy1)
if res$="Q" then exit
Player1sum+=Player1points
Score()
Print "Player 2 turn"
PlayerTurn(&Player2points,&player2sum, player1sum, ! strategy2)
if res$="Q" then exit
Player2sum+=Player2points
Score()
}
If HaveWin then {
Score()
If Player1Sum>Player2sum then {
Print "Player 1 Win"
win1++
} Else Print "Player 2 Win" : win2++
}
}
\\ use stack as FIFO
If win1>win2 Then {
Data "Player 1 Win", win1,win2, array(strategy1,0), array(strategy1,1)
} Else {
Data "Player 2 Win", win2,win1, array(strategy2,0), array(strategy2,1)
}
Sub Rolling()
dice=random(1,6)
Print "dice=";dice
End Sub
Sub PlayOrQuit()
Print "R - Roling Q-Quit"
Repeat {
res$=Ucase$(Key$)
} Until Instr("RQ", res$)>0
End Sub
Sub PlayAgain()
Print "R - Roling H - Hold Q-Quit"
Repeat {
res$=Ucase$(Key$)
} Until Instr("RHQ", res$)>0
End Sub
Sub PlayerTurn(&playerpoints, &sum, othersum, Max_Points, Min_difference)
PlayOrQuit()
If res$="Q" then Exit Sub
playerpoints=0
Rolling()
While dice<>1 and res$="R" {
playerpoints+=dice
if dice>1 and playerpoints+sum>100 then {
sum+=playerpoints
HaveWin=True
res$="Q"
} Else {
if playerpoints>=Max_Points Then If 100-othersum>Min_difference Then res$="H" : exit
PlayAgain()
if res$="R" then Rolling()
}
}
if dice=1 then playerpoints=0
End Sub
Sub Score()
Print "Player1 points="; Player1sum
Print "Player2 points="; Player2sum
End Sub
}
Flush
GamePig 20, (8,10), (12, 20)
GamePig 20, (12, 20), (8,10)
Print "Results"
While not Empty {
Read WhoWin$, winA,winb, Max_Points, Min_difference
Print WhoWin$, winA;">";winb, Max_Points, Min_difference
}
 
(define (n-runs n . players)
(define v (make-vector (length players) 0))
(for ([i n])
(define p (sub1 (apply pig-the-dice #:print? #f players)))
(vector-set! v p (add1 (vector-ref v p))))
(for ([wins v] [i (in-naturals 1)])
(printf "Player ~a: ~a%\n" i (round (/ wins n 1/100)))))
 
</syntaxhighlight>
;; Things to try
 
;; (n-runs 1000 (n-random 2) (n-random 3) (n-random 4))
=={{header|Nim}}==
;; (n-runs 1000 (n-rounds 5) (n-points 24))
{{trans|D}}
;; (n-runs 1000 (n-rounds 5) (n-random 2))
We use the same strategies as D (and C++) but the code is somewhat different. To represent the players with their different strategies, we don’t use a player base class with subclasses for each strategy but a single player object with a “strategy” field. To dispatch, we use a "case" statement rather than method overriding. This is only a matter of preference as Nim allows inheritance and method overriding.
</lang>
 
We also describe the list of players as a linked ring of player objects. The code is somewhat more pleasant this way.
 
Except for some small differences in the formatting, the output is similar to that of D (or C++) implementation.
 
<syntaxhighlight lang="nim">import random, strformat
 
const MaxPoints = 100
 
type
 
Move {.pure.} = enum Roll, Hold
Strategy {.pure.} = enum Rand, Q2Win, AL20, AL20T
 
# Player description.
Player = ref object
num: Natural
currentScore: Natural
roundScore: Natural
strategy: Strategy
next: Player
 
# Player list managed as a singly linked ring.
PlayerList = object
count: Natural
head, tail: Player
 
 
proc addPlayer(playerList: var PlayerList; strategy: Strategy) =
## Add a player with given strategy.
inc playerList.count
let newPlayer = Player(num: playerList.count, strategy: strategy)
if playerList.head.isNil:
playerList.head = newPlayer
else:
playerList.tail.next = newPlayer
playerList.tail = newPlayer
newPlayer.next = playerList.head
 
 
iterator items(playerList: PlayerList): Player =
## Yield the successive players of a player list.
var player = playerList.head
yield player
while player != playerList.tail:
player = player.next
yield player
 
 
proc getMove(player: Player): Move =
## Get the move for the given player.
 
if player.roundScore + player.currentScore >= MaxPoints: return Hold
 
case player.strategy
 
of Strategy.Rand:
result = if rand(1) == 0: Roll
elif player.roundScore > 0: Hold
else: Roll
 
of Strategy.Q2Win:
let q = MaxPoints - player.currentScore
result = if q < 6 or player.roundScore < q div 4: Roll
else: Hold
 
of Strategy.AL20:
result = if player.roundScore < 20: Roll
else: Hold
 
of Strategy.AL20T:
let d = 5 * player.roundScore
result = if player.roundScore < 20 and d < rand(99): Roll
else: Hold
 
 
randomize()
 
# Create player list.
var playerList = PlayerList()
for strategy in Strategy.low..Strategy.high:
playerList.addPlayer(strategy)
 
var endGame = false
var player = playerList.head
 
while not endGame:
case player.getMove()
 
of Roll:
let die = rand(1..6)
if die == 1:
echo &"Player {player.num} rolled {die} Current score: {player.currentScore:3}\n"
player.roundScore = 0
player = player.next
continue
inc player.roundScore, die
echo &"Player {player.num} rolled {die} Round score: {player.roundScore:3}"
 
of Hold:
inc player.currentScore, player.roundScore
echo &"Player {player.num} holds Current score: {player.currentScore:3}\n"
if player.currentScore >= MaxPoints:
endGame = true
else:
player.roundScore = 0
player = player.next
 
for player in playerList:
let stratStr = &"({player.strategy}):"
echo &"Player {player.num} {stratStr:8} {player.currentScore:3}"</syntaxhighlight>
 
{{out}}
<pre>Player 1 rolled 2 Round score: 2
Player 1 rolled 5 Round score: 7
Player 1 holds Current score: 7
 
Player 2 rolled 2 Round score: 2
Player 2 rolled 6 Round score: 8
Player 2 rolled 4 Round score: 12
Player 2 rolled 4 Round score: 16
Player 2 rolled 4 Round score: 20
Player 2 rolled 1 Current score: 0
 
Player 3 rolled 3 Round score: 3
Player 3 rolled 1 Current score: 0
 
Player 4 rolled 6 Round score: 6
Player 4 holds Current score: 6
 
Player 1 rolled 1 Current score: 7
 
Player 2 rolled 6 Round score: 6
Player 2 rolled 6 Round score: 12
Player 2 rolled 1 Current score: 0
 
Player 3 rolled 3 Round score: 3
Player 3 rolled 5 Round score: 8
Player 3 rolled 2 Round score: 10
Player 3 rolled 4 Round score: 14
Player 3 rolled 2 Round score: 16
Player 3 rolled 4 Round score: 20
Player 3 holds Current score: 20
 
Player 4 rolled 1 Current score: 6
 
Player 1 rolled 4 Round score: 4
Player 1 rolled 3 Round score: 7
Player 1 holds Current score: 14
 
Player 2 rolled 3 Round score: 3
Player 2 rolled 4 Round score: 7
Player 2 rolled 3 Round score: 10
Player 2 rolled 2 Round score: 12
Player 2 rolled 6 Round score: 18
Player 2 rolled 4 Round score: 22
Player 2 rolled 5 Round score: 27
Player 2 holds Current score: 27
 
Player 3 rolled 3 Round score: 3
Player 3 rolled 4 Round score: 7
Player 3 rolled 1 Current score: 20
 
Player 4 rolled 5 Round score: 5
Player 4 rolled 5 Round score: 10
Player 4 rolled 1 Current score: 6
 
Player 1 rolled 2 Round score: 2
Player 1 rolled 3 Round score: 5
Player 1 holds Current score: 19
 
Player 2 rolled 2 Round score: 2
Player 2 rolled 2 Round score: 4
Player 2 rolled 3 Round score: 7
Player 2 rolled 2 Round score: 9
Player 2 rolled 5 Round score: 14
Player 2 rolled 4 Round score: 18
Player 2 holds Current score: 45
 
Player 3 rolled 3 Round score: 3
Player 3 rolled 5 Round score: 8
Player 3 rolled 4 Round score: 12
Player 3 rolled 4 Round score: 16
Player 3 rolled 3 Round score: 19
Player 3 rolled 1 Current score: 20
 
Player 4 rolled 3 Round score: 3
Player 4 rolled 6 Round score: 9
Player 4 holds Current score: 15
 
Player 1 rolled 6 Round score: 6
Player 1 holds Current score: 25
 
Player 2 rolled 6 Round score: 6
Player 2 rolled 3 Round score: 9
Player 2 rolled 3 Round score: 12
Player 2 rolled 6 Round score: 18
Player 2 holds Current score: 63
 
Player 3 rolled 2 Round score: 2
Player 3 rolled 4 Round score: 6
Player 3 rolled 1 Current score: 20
 
Player 4 rolled 4 Round score: 4
Player 4 rolled 4 Round score: 8
Player 4 holds Current score: 23
 
Player 1 rolled 4 Round score: 4
Player 1 holds Current score: 29
 
Player 2 rolled 3 Round score: 3
Player 2 rolled 6 Round score: 9
Player 2 holds Current score: 72
 
Player 3 rolled 5 Round score: 5
Player 3 rolled 5 Round score: 10
Player 3 rolled 6 Round score: 16
Player 3 rolled 1 Current score: 20
 
Player 4 rolled 2 Round score: 2
Player 4 rolled 3 Round score: 5
Player 4 rolled 2 Round score: 7
Player 4 holds Current score: 30
 
Player 1 rolled 4 Round score: 4
Player 1 holds Current score: 33
 
Player 2 rolled 1 Current score: 72
 
Player 3 rolled 6 Round score: 6
Player 3 rolled 1 Current score: 20
 
Player 4 rolled 2 Round score: 2
Player 4 rolled 1 Current score: 30
 
Player 1 rolled 3 Round score: 3
Player 1 rolled 3 Round score: 6
Player 1 rolled 5 Round score: 11
Player 1 rolled 5 Round score: 16
Player 1 holds Current score: 49
 
Player 2 rolled 2 Round score: 2
Player 2 rolled 4 Round score: 6
Player 2 rolled 4 Round score: 10
Player 2 holds Current score: 82
 
Player 3 rolled 2 Round score: 2
Player 3 rolled 6 Round score: 8
Player 3 rolled 1 Current score: 20
 
Player 4 rolled 6 Round score: 6
Player 4 holds Current score: 36
 
Player 1 rolled 2 Round score: 2
Player 1 holds Current score: 51
 
Player 2 rolled 5 Round score: 5
Player 2 holds Current score: 87
 
Player 3 rolled 1 Current score: 20
 
Player 4 rolled 6 Round score: 6
Player 4 rolled 3 Round score: 9
Player 4 holds Current score: 45
 
Player 1 rolled 5 Round score: 5
Player 1 holds Current score: 56
 
Player 2 rolled 2 Round score: 2
Player 2 rolled 1 Current score: 87
 
Player 3 rolled 2 Round score: 2
Player 3 rolled 5 Round score: 7
Player 3 rolled 5 Round score: 12
Player 3 rolled 3 Round score: 15
Player 3 rolled 5 Round score: 20
Player 3 holds Current score: 40
 
Player 4 rolled 5 Round score: 5
Player 4 rolled 6 Round score: 11
Player 4 rolled 2 Round score: 13
Player 4 rolled 4 Round score: 17
Player 4 rolled 3 Round score: 20
Player 4 holds Current score: 65
 
Player 1 rolled 6 Round score: 6
Player 1 holds Current score: 62
 
Player 2 rolled 4 Round score: 4
Player 2 holds Current score: 91
 
Player 3 rolled 5 Round score: 5
Player 3 rolled 5 Round score: 10
Player 3 rolled 4 Round score: 14
Player 3 rolled 6 Round score: 20
Player 3 holds Current score: 60
 
Player 4 rolled 4 Round score: 4
Player 4 rolled 4 Round score: 8
Player 4 holds Current score: 73
 
Player 1 rolled 3 Round score: 3
Player 1 rolled 2 Round score: 5
Player 1 rolled 6 Round score: 11
Player 1 rolled 6 Round score: 17
Player 1 holds Current score: 79
 
Player 2 rolled 5 Round score: 5
Player 2 holds Current score: 96
 
Player 3 rolled 4 Round score: 4
Player 3 rolled 6 Round score: 10
Player 3 rolled 4 Round score: 14
Player 3 rolled 2 Round score: 16
Player 3 rolled 3 Round score: 19
Player 3 rolled 4 Round score: 23
Player 3 holds Current score: 83
 
Player 4 rolled 3 Round score: 3
Player 4 rolled 4 Round score: 7
Player 4 rolled 2 Round score: 9
Player 4 holds Current score: 82
 
Player 1 rolled 1 Current score: 79
 
Player 2 rolled 3 Round score: 3
Player 2 rolled 1 Current score: 96
 
Player 3 rolled 1 Current score: 83
 
Player 4 rolled 6 Round score: 6
Player 4 holds Current score: 88
 
Player 1 rolled 4 Round score: 4
Player 1 rolled 3 Round score: 7
Player 1 holds Current score: 86
 
Player 2 rolled 2 Round score: 2
Player 2 rolled 1 Current score: 96
 
Player 3 rolled 2 Round score: 2
Player 3 rolled 2 Round score: 4
Player 3 rolled 3 Round score: 7
Player 3 rolled 4 Round score: 11
Player 3 rolled 1 Current score: 83
 
Player 4 rolled 1 Current score: 88
 
Player 1 rolled 6 Round score: 6
Player 1 holds Current score: 92
 
Player 2 rolled 4 Round score: 4
Player 2 holds Current score: 100
 
Player 1 (Rand): 92
Player 2 (Q2Win): 100
Player 3 (AL20): 83
Player 4 (AL20T): 88</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang="perl">my $GOAL = 100;
 
package Player;
 
sub new {
my ($class,$strategy) = @_;
my $self = {
score => 0,
rolls => 0,
ante => 0,
strategy => $strategy || sub { 0 } # as fallback, always roll again
};
return bless($self, $class);
}
 
sub turn {
my ($P) = @_;
$P->{rolls} = 0;
$P->{ante} = 0;
my $done = 0;
do {
my $v = 1 + int rand 6;
$P->{rolls}++;
if ($v == 1) {
$P->{ante} = 0;
$done = 1;
} else {
$P->{ante} += $v;
}
$done = 1 if $P->{score} + $P->{ante} >= $GOAL or $P->{strategy}();
} until $done;
$P->{score} += $P->{ante};
}
 
package Main;
 
# default, go-for-broke, always roll again
$players[0] = Player->new;
 
# try to roll 5 times but no more per turn
$players[1] = Player->new( sub { $players[1]->{rolls} >= 5 } );
 
# try to accumulate at least 20 points per turn
@players[2] = Player->new( sub { $players[2]->{ante} > 20 } );
 
# random but 90% chance of rolling again
$players[3] = Player->new( sub { rand() < 0.1 } );
 
# random but more conservative as approaches goal
$players[4] = Player->new( sub { rand() < ( $GOAL - $players[4]->{score} ) * .6 / $GOAL } );
 
for (1 .. shift || 100) {
my $player = -1;
do {
$player++;
@players[$player % @players]->turn;
} until $players[$player % @players]->{score} >= $GOAL;
 
$wins[$player % @players]++;
 
printf "%5d", $players[$_]->{score} for 0..$#players; print "\n";
$players[$_]->{score} = 0 for 0..$#players; # reset scores for next game
}
 
print ' ----' x @players, "\n";
printf "%5d", $_ for @wins; print "\n";</syntaxhighlight>
Distribution of wins after 10000 games:
{{out}}
<pre>929 3518 3462 1715 376</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">maxScore</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">100</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">one_game</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">strategies</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">numPlayers</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strategies</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- points accumulated in current turn, 0=swap turn</span>
<span style="color: #000000;">rolls</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- number of rolls</span>
<span style="color: #000000;">player</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">numPlayers</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- start with a random player</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">scores</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">numPlayers</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">roll</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">6</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">roll</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- swap turn</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">points</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">roll</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">points</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">maxScore</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">rolls</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">play</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strategies</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">play</span><span style="color: #0000FF;">(</span><span style="color: #000000;">scores</span><span style="color: #0000FF;">,</span><span style="color: #000000;">player</span><span style="color: #0000FF;">,</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rolls</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">points</span>
<span style="color: #000000;">points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- swap turn</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">points</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">player</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">player</span><span style="color: #0000FF;">,</span><span style="color: #000000;">numPlayers</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">rolls</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">player</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">-- each strategy returns true to roll, false to hold.</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">strategy1</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000080;font-style:italic;">/*scores*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*player*/</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">points</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">/*rolls*/</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">points</span><span style="color: #0000FF;"><</span><span style="color: #000000;">20</span> <span style="color: #000080;font-style:italic;">-- roll until 20 or more</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">strategy2</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000080;font-style:italic;">/*scores*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*player*/</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">/*points*/</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rolls</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">rolls</span><span style="color: #0000FF;"><</span><span style="color: #000000;">4</span> <span style="color: #000080;font-style:italic;">-- roll 4 times</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">strategy3</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">player</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">points</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">/*rolls*/</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- roll until 20 or score&gt;80</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">points</span><span style="color: #0000FF;"><</span><span style="color: #000000;">20</span> <span style="color: #008080;">or</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">player</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">points</span><span style="color: #0000FF;">></span><span style="color: #000000;">80</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">strategy4</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">player</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">points</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">/*rolls*/</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- roll until 20 or any player has &gt;71</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">scores</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]></span><span style="color: #000000;">71</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">true</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">points</span><span style="color: #0000FF;"><</span><span style="color: #000000;">20</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">strategies</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">strategy1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">strategy2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">strategy3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">strategy4</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">numStrategies</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strategies</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">numOpponents</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">numStrategies</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #000080;font-style:italic;">-- play each strategy 1000 times against all combinations of other strategies</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">numStrategies</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">strategy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strategies</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">mask</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">numOpponents</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">wins</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">opponents</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strategies</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">opponents</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">..</span><span style="color: #000000;">s</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- (ie all others only)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">mask</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (all possible bit settings, bar 0, eg/ie 1..7)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">game</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">strategy</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">numOpponents</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">game</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">opponents</span><span style="color: #0000FF;">[</span><span style="color: #000000;">g</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1000</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">wins</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">one_game</span><span style="color: #0000FF;">(</span><span style="color: #000000;">game</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"strategy %d: %d wins\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">wins</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
strategy 1: 2784 wins
strategy 2: 2065 wins
strategy 3: 2885 wins
strategy 4: 3135 wins
</pre>
Setting player to 1 at the start of one_game shows the advantage of going first,
which (not surprisingly) appears to apply fairly evenly to all strategies.
<pre>
strategy 1: 3053 wins
strategy 2: 2293 wins
strategy 3: 3170 wins
strategy 4: 3457 wins
</pre>
 
=={{header|Python}}==
Line 1,587 ⟶ 2,848:
Notice how Pythons Counter class from the standard library is used to collate the winning statistics near the end of the program without much additional code.
 
<langsyntaxhighlight lang="python">#!/usr/bin/python3
 
'''
Line 1,713 ⟶ 2,974:
for i in range(maxgames))
print(' Players(position) winning on left; occurrences on right:\n %s'
% ',\n '.join(str(w) for w in winners.most_common()))</langsyntaxhighlight>
{{out}}
First is shown the game data for a single game with reduced maxscore then statistics on multiple games.
Line 1,756 ⟶ 3,017:
 
Note: ''('(RollTo20(1), RandPlay(0))', 25063)'' means that the algorithm RollTo20 playing as the second player, (1) wins against algorithm RandPlay of the first player, (0) and wins 25063 times. (Zero based indexing so the first player is player(0)).
 
=={{header|Racket}}==
 
Same as [[Pig_the_dice_game#Racket]], with three strategy makers, and
simulation code for trying out strategies.
<syntaxhighlight lang="racket">#lang racket
 
(define (pig-the-dice #:print? [print? #t] . players)
(define prn (if print? (λ xs (apply printf xs) (flush-output)) void))
(define names (for/list ([p players] [n (in-naturals 1)]) n))
(define points (for/list ([p players]) (box 0)))
(with-handlers ([(negate exn?) identity])
(for ([nm (in-cycle names)] [tp (in-cycle points)] [pl (in-cycle players)])
(prn (string-join (for/list ([n names] [p points])
(format "Player ~a, ~a points" n (unbox p)))
"; " #:before-first "Status: " #:after-last ".\n"))
(let turn ([p 0] [n 0])
(prn "Player ~a, round #~a, [R]oll or [P]ass? " nm (+ 1 n))
(define roll? (pl (unbox tp) p n))
(unless (eq? pl human) (prn "~a\n" (if roll? 'R 'P)))
(if (not roll?) (set-box! tp (+ (unbox tp) p))
(let ([r (+ 1 (random 6))])
(prn " Dice roll: ~s => " r)
(if (= r 1) (prn "turn lost\n")
(let ([p (+ p r)]) (prn "~a points\n" p) (turn p (+ 1 n)))))))
(prn "--------------------\n")
(when (<= 100 (unbox tp)) (prn "Player ~a wins!\n" nm) (raise nm)))))
 
(define (human total-points turn-points round#)
(case (string->symbol (car (regexp-match #px"[A-Za-z]?" (read-line))))
[(R r) #t] [(P p) #f] [else (human total-points turn-points round#)]))
 
;; Always do N rolls
(define ((n-rounds n) total-points turn-points round#) (< round# n))
;; Roll until a given number of points
(define ((n-points n) total-points turn-points round#) (< turn-points n))
;; Random decision
(define ((n-random n) total-points turn-points round#) (zero? (random n)))
 
(define (n-runs n . players)
(define v (make-vector (length players) 0))
(for ([i n])
(define p (sub1 (apply pig-the-dice #:print? #f players)))
(vector-set! v p (add1 (vector-ref v p))))
(for ([wins v] [i (in-naturals 1)])
(printf "Player ~a: ~a%\n" i (round (/ wins n 1/100)))))
 
;; Things to try
;; (n-runs 1000 (n-random 2) (n-random 3) (n-random 4))
;; (n-runs 1000 (n-rounds 5) (n-points 24))
;; (n-runs 1000 (n-rounds 5) (n-random 2))</syntaxhighlight>
The following example run demonstrates the output from
<syntaxhighlight lang="racket">(pig-the-dice #:print? #t (n-points 12) (n-rounds 4))</syntaxhighlight>
Where <code>n-points</code> is a strategy where the user continues to roll until the specified number of points is gained and <code>n-rounds</code> is a strategy where the users rolls the specified number of times each round.
<pre>
Status: Player 1, 0 points; Player 2, 0 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 4 => 4 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 5 => 9 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 2 => 11 points
Player 1, round #4, [R]oll or [P]ass? R
Dice roll: 5 => 16 points
Player 1, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 16 points; Player 2, 0 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 6 => 6 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 6 => 12 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 3 => 15 points
Player 2, round #4, [R]oll or [P]ass? R
Dice roll: 5 => 20 points
Player 2, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 16 points; Player 2, 20 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 2 => 2 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 2 => 4 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 6 => 10 points
Player 1, round #4, [R]oll or [P]ass? R
Dice roll: 6 => 16 points
Player 1, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 32 points; Player 2, 20 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 5 => 5 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 2 => 7 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 2 => 9 points
Player 2, round #4, [R]oll or [P]ass? R
Dice roll: 3 => 12 points
Player 2, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 32 points; Player 2, 32 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 6 => 6 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 5 => 11 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 2 => 13 points
Player 1, round #4, [R]oll or [P]ass? P
--------------------
Status: Player 1, 45 points; Player 2, 32 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 3 => 3 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 32 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 2 => 2 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 4 => 6 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 32 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 5 => 5 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 2 => 7 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 6 => 13 points
Player 2, round #4, [R]oll or [P]ass? R
Dice roll: 2 => 15 points
Player 2, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 45 points; Player 2, 47 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 47 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 47 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 2 => 2 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 5 => 7 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 47 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 5 => 5 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 6 => 11 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 6 => 17 points
Player 2, round #4, [R]oll or [P]ass? R
Dice roll: 3 => 20 points
Player 2, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 45 points; Player 2, 67 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 4 => 4 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 67 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 3 => 3 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 3 => 6 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 2 => 8 points
Player 2, round #4, [R]oll or [P]ass? R
Dice roll: 3 => 11 points
Player 2, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 45 points; Player 2, 78 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 3 => 3 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 4 => 7 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 4 => 11 points
Player 1, round #4, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 78 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 2 => 2 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 5 => 7 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 78 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 3 => 3 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 78 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 45 points; Player 2, 78 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 5 => 5 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 4 => 9 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 2 => 11 points
Player 1, round #4, [R]oll or [P]ass? R
Dice roll: 5 => 16 points
Player 1, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 61 points; Player 2, 78 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 4 => 4 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 2 => 6 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 3 => 9 points
Player 2, round #4, [R]oll or [P]ass? R
Dice roll: 6 => 15 points
Player 2, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 61 points; Player 2, 93 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 5 => 5 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 3 => 8 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 2 => 10 points
Player 1, round #4, [R]oll or [P]ass? R
Dice roll: 2 => 12 points
Player 1, round #5, [R]oll or [P]ass? P
--------------------
Status: Player 1, 73 points; Player 2, 93 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 6 => 6 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 4 => 10 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 4 => 14 points
Player 2, round #4, [R]oll or [P]ass? R
Dice roll: 1 => turn lost
--------------------
Status: Player 1, 73 points; Player 2, 93 points.
Player 1, round #1, [R]oll or [P]ass? R
Dice roll: 3 => 3 points
Player 1, round #2, [R]oll or [P]ass? R
Dice roll: 4 => 7 points
Player 1, round #3, [R]oll or [P]ass? R
Dice roll: 6 => 13 points
Player 1, round #4, [R]oll or [P]ass? P
--------------------
Status: Player 1, 86 points; Player 2, 93 points.
Player 2, round #1, [R]oll or [P]ass? R
Dice roll: 2 => 2 points
Player 2, round #2, [R]oll or [P]ass? R
Dice roll: 6 => 8 points
Player 2, round #3, [R]oll or [P]ass? R
Dice roll: 4 => 12 points
Player 2, round #4, [R]oll or [P]ass? R
Dice roll: 5 => 17 points
Player 2, round #5, [R]oll or [P]ass? P
--------------------
Player 2 wins!
2
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
 
This implements a pig player class where you can customize the strategy it uses. Pass a strategy code reference in that will evaluate to a Boolean value. The player will roll the die then decide whether to roll again or lock in its winnings based on its strategy. It will continue to roll until it gets a 1 (bust) or the strategy code reference evaluates to True (finished turn).
 
Set up as many players as you want, then run it. It will play 100 games (by default) then report the score for each game then the win totals for each player. If you want to play a different number of games, pass the number at the command line as a parameter.
 
Here we have 5 players:
player 0 uses the default strategy, always roll if it can.
player 1 will roll up to 5 times then lock in whatever it earned.
player 2 will try to get at least 20 points per turn.
player 3 randomly picks whether to roll again or not biased so that there is a 90% chance that it will.
player 4 randomly chooses to roll again but gets more consrvative as its score get closer to the goal.
 
<syntaxhighlight lang="raku" line>my $games = @*ARGS ?? (shift @*ARGS) !! 100;
 
constant DIE = 1 .. 6;
constant GOAL = 100;
 
class player {
has $.score is rw = 0;
has $.ante is rw;
has $.rolls is rw;
has &.strategy is rw = sub { False }; # default, always roll again
 
method turn {
my $done_turn = False;
$.rolls = 0;
$.ante = 0;
repeat {
given DIE.roll {
$.rolls++;
when 1 {
$.ante = 0;
$done_turn = True;
}
when 2..* {
$.ante += $_;
}
}
$done_turn = True if $.score + $.ante >= GOAL or (&.strategy)();
} until $done_turn;
$.score += $.ante;
}
}
 
my @players;
 
# default, go-for-broke, always roll again
@players[0] = player.new;
 
# try to roll 5 times but no more per turn
@players[1] = player.new( strategy => sub { @players[1].rolls >= 5 } );
 
# try to accumulate at least 20 points per turn
@players[2] = player.new( strategy => sub { @players[2].ante > 20 } );
 
# random but 90% chance of rolling again
@players[3] = player.new( strategy => sub { 1.rand < .1 } );
 
# random but more conservative as approaches goal
@players[4] = player.new( strategy => sub { 1.rand < ( GOAL - @players[4].score ) * .6 / GOAL } );
 
my @wins = 0 xx @players;
 
for ^ $games {
my $player = -1;
repeat {
$player++;
@players[$player % @players].turn;
} until @players[$player % @players].score >= GOAL;
 
@wins[$player % @players]++;
 
say join "\t", @players>>.score;
@players[$_].score = 0 for ^@players; # reset scores for next game
}
 
say "\nSCORES: for $games games";
say join "\t", @wins;</syntaxhighlight>
 
'''Sample output for 10000 games'''
<pre>
0 103 46 5 40
0 100 69 0 48
0 105 22 7 44
0 75 69 19 102
105 21 23 5 17
0 101 85 12 29
0 70 66 103 23
0 0 104 69 20
0 100 44 0 20
0 102 63 75 30
0 56 101 12 40
0 103 71 2 38
0 103 91 21 32
0 18 102 47 28
...
...
...
104 0 69 14 47
0 68 101 13 22
0 99 89 102 31
 
SCORES: for 10000 games
947 3534 3396 1714 409
 
</pre>
 
=={{header|REXX}}==
Line 1,761 ⟶ 3,402:
 
The (somewhat aggressive) "quarter" strategy was chosen to give the advantage to a human (it was presumed that this dice game would be played with a CBLF).
<langsyntaxhighlight lang="rexx">/*REXX program plays "pig the dice game" (any #number of CBLFs and/or silicons or HALs).*/
sw= linesize() - 1 /*get the width of the terminal screen,*/
signal on syntax; signal on novalue /*handle REXX program errors. */
sw=linesize()-1 parse arg hp cp win die _ . '(' names ")" /*getobtain theoptional widtharguments offrom the terminal. CL*/
/*names with blanks should use an _ */
parse arg hp cp win die _ . '(' names ")" /*obtain optional arguments.*/
/*names with blanks should use _ */
if _\=='' then call err 'too many arguments were specified: ' _
@nhp = 'number of human players' ; hp = scrutinize( hp, @nhp , 0, 0, 0)
@ncp = 'number of computer players'; cp = scrutinize( cp, @ncp , 0, 0, 2)
@sn2w = 'score needed to win' ; win= scrutinize(win, @sn2w, 1, 1e6, 60)
@nsid = 'number of sides in die' ; die= scrutinize(die, @nsid, 2, 999, 6)
if hp==0 & cp==0 then cp= 2 /*if both counts are zero, 2two HALs. */
if hp==1 & cp==0 then cp= 1 /*if one human, then use 1one HAL. */
name.= /*nullify all names (to a blank). */
L= 0 /*maximum length of a player name. */
do i=1 for hp+cp /*get the player's names, ... maybe. */
if i>hp then @= 'HAL_'i"_the_computer" /*use this for default name. */
else @= 'player_'i /* " " " " " */
name.i = translate( word( strip( word( names, i) ) @, 1), , '_')
L= max(L, length( name.i) ) /*use L for nice name formatting. */
end /*i*/ /*underscores are changed─►blankschanged ──► blanks. */
 
hpn=hp; if hpn==0 then hpn= 'no' /*use normal English for the display. */
cpn=cp; if cpn==0 then cpn=" 'no"' /* " " " " " " */
say 'Pig (the dice game) is being played with:' /*introduction to pig.*/
if cpn\==0 then say right(cpn,9) 'computer player's(cp)
if hpn\==0 then say right(hpn,9) 'human player's(hp)
say 'and the' @sn2w "is: " win ' (or greater).'
!.=; dieNames='ace deuce trey square nickle boxcar' /*die face names.*/
/*note: snake eyes is for 2 aces.*/
!w=0; do i=1 for die; !.i=' ['word(dieNames,i)"]"
!w=max(!w, length(!.i)) /*!w ──► maximum length die name.*/
end /*i*/
s.=0 /*set all player's scores to zero*/
!w=!w+length(die)+3 /*pad the die number and die name*/
@=copies('─',9) /*an eyecatcher (for prompting). */
@jra='just rolled a '; @ati='and the inning' /*nice literals to have.*/
/*──────────────────────────────────────────────────let's play some pig.*/
do game=1; in.=0 /*set each inning's score to zero*/
say; say copies('█',sw) /*display a fence for da eyeballs*/
 
say 'Pig (the dice game) is being played with:' /*the introduction to pig-the-dice-game*/
do k=1 for hp+cp /*display the scores (as a recap)*/
say 'The score for ' left(name.k,L) " is " right(s.k,length(win))'.'
end /*k*/
 
say copies('█',sw) if cpn\==0 then say right(cpn, 9) /*display'computer a fence for da eyeballs*/player's(cp)
if hpn\==0 then say right(hpn, 9) 'human player's(hp)
!.=
say 'and the' @sn2w "is: " win ' (or greater).'
dieNames= 'ace deuce trey square nickle boxcar' /*some slangy vernacular die─face names*/
!w=0 /*note: snake eyes is for two aces. */
do i=1 for die /*assign the vernacular die─face names.*/
!.i= ' ['word(dieNames,i)"]" /*pick a word from die─face name lists.*/
!w= max(!w, length(!.i) ) /*!w ──► maximum length die─face name. */
end /*i*/
s.= 0 /*set all player's scores to zero. */
!w= !w + length(die) + 3 /*pad the die number and die names. */
@= copies('─', 9) /*eyecatcher (for the prompting text). */
@jra= 'just rolled a ' /*a nice literal to have laying 'round.*/
@ati= 'and the inning' /*" " " " " " " */
/*═══════════════════════════════════════════════════let's play some pig.*/
do game=1; in.= 0; call score /*set each inning's score to 0; display*/
 
do j=1 for hp+cp; say /*let each player roll their dice. */
say; say copies('─', sw); /*display a fence for da ole eyeballs. */
it= name.j
say it', your total score (so far) in this pig game is: ' s.j"."
 
do until stopped /*keep prompting/rolling 'til notstopped. */
r= random(1, die) /*get a random die face (number). */
!= left(space(r !.r','), !w) /*for color, use a die-facedie─face name. */
in.j= in.j + r /*add die-facedie─face number to the inning. */
 
if r==1 then do; say it @jra ! || @ati "is a bust."; leave; end
if r==1 then do; say it @jra ! || @ati "is a bust."; leave; end
say it @jra ! || @ati "total is: " in.j
 
stopped=what2do(j) /*determine|ask to stop rolling.*/
ifstopped= what2do(j>hp) & stopped then say ' and' name.j "elected /*determine or ask to stop rolling." */
if j>hp & stopped then say ' and' name.j "elected to stop rolling."
end /*until stopped*/
 
if r\==1 then s.j= s.j + in.j /*if not a bust, then add to the inning.*/
if s.j>=win then leave game /*we have a winner, so the game ends. */
end /*j*/ /*that's the end of the players. */
end /*game*/
 
call score; say; say; say; say; say center(''name.j "won! ", sw, '═'); say; say; exit
exit say; say; exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────S subroutine────────────────────────*/
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1) /*plural?pluralizer.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────SCRUTINIZE subroutine───────────────*/
score: say; say copies('█', sw) /*display a fence for da ole eyeballs. */
scrutinize: parse arg ?,what,min,max /*? is the number, or maybe not. */
do k=1 for hp+cp /*display the scores (as a recap). */
if ?=='' | ?==',' then return arg(5)
say 'The score for ' left(name.k, L) " is " right(s.k, length(win) ).
if \datatype(?,'N') then call err what "isn't numeric: " ?; ?=?/1
end /*k*/
if \datatype(?,'W') then call err what "isn't an integer: " ?
say copies('█', sw); return /*display a fence for da ole eyeballs. */
if ?==0 & min>0 then call err what "can't be zero."
/*──────────────────────────────────────────────────────────────────────────────────────*/
if ?<min then call err what "can't be less than" min': ' ?
scrutinize: parse arg ?,what,min,max /*? is the number, ... or maybe not. */
if ?==0 & max>0 then call err what "can't be zero."
if ?=='' | ?==',' then return arg(5)
if ?>max & max\==0 then call err what "can't be greater than" max': ' ?
if \datatype(?, 'N') then call err what "isn't numeric: " ?; ?=?/1
return ?
if \datatype(?, 'W') then call err what "isn't an integer: " ?
/*──────────────────────────────────what2do subroutine──────────────────*/
what2do: parse arg who if ?==0 & min>0 /*"who" is athen humancall orerr awhat computer"can't be zero.*/"
if j>hp?<min & s.j+in.j>=win then call err what return"can't 1be less than" /*an easy choicemin': ' for HAL.*/?
if j>hp & in.j> if ?==win%40 then& max>0 return 1 /*athen call err simplewhat stategy"can't forbe HALzero.*/"
if j>hp if ?>max & max\==0 then call returnerr 0what "can't be greater /*HALthan" says, keepmax': truckin'! */ ?
return ?
say @ name.who', what do you want to do? (a QUIT will stop the game),'
/*──────────────────────────────────────────────────────────────────────────────────────*/
say @ 'press ENTER to roll again, or anything else to STOP rolling.'
what2do: parse arg who /*"who" is a human or a computer.*/
pull action; action=space(action) /*remove any superfluous blanks. */
if j>hp & s.j+in.j>=win then return 1 /*an easy choice for HAL. */
if \abbrev('QUIT',action,1) then return action\==''
if j>hp & in.j>=win%4 then return 1 /*a simple strategy for HAL. */
say; say; say; say center(' quitting. ',sw,'─'); say; say; say; exit
if j>hp then return 0 /*HAL says, keep truckin'! */
/*───────────────────────────────error handling subroutines and others.─*/
say @ name.who', what do you want to do? (a QUIT will stop the game),'
err: say; say; say center(' error! ',max(40,linesize()%2),"*"); say
say @ 'press ENTER to roll again, or anything else to STOP rolling.'
do j=1 for arg(); say arg(j); say; end; say; exit 13
pull action; action=space(action) /*remove any superfluous blanks. */
 
if \abbrev('QUIT', action, 1) then return action\==''
novalue: syntax: call err 'REXX program' condition('C') "error",
say; say; say ,conditioncenter('D quitting. '), sw, 'REXX─'); source statement (line' sigl"):",say; say; exit
/*──────────────────────────────────────────────────────────────────────────────────────*/
,sourceline(sigl)</lang>
err: say; say; say center(' error! ', max(40, linesize() % 2), "*"); say
<br><br>The &nbsp; '''$T''' &nbsp; REXX program makes use of &nbsp; '''LINESIZE''' &nbsp; BIF &nbsp; which returns the terminals width (linesize).
do j=1 for arg(); say arg(j); say; end; say; exit 13</syntaxhighlight>
<br>Some REXXes doen't have a &nbsp; '''LINESIZE''' &nbsp; BIF, so one is included here &nbsp; ──► &nbsp; [[LINESIZE.REX]].
This REXX program makes use of &nbsp; '''LINESIZE''' &nbsp; BIF &nbsp; which returns the terminals width (linesize).
<br>Some REXXes don't have a &nbsp; '''LINESIZE''' &nbsp; BIF, so one is included here &nbsp; ──► &nbsp; [[LINESIZE.REX]].
<br><br>
 
Line 1,987 ⟶ 3,629:
 
═══════════════════════════HAL 2 the computer won! ════════════════════════════
</pre>
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">
def player1(sum,sm)
for i in 1..100
puts "player1 rolled"
a=gets.chomp().to_i
if (a>1 && a<7)
sum+=a
if sum>=100
puts "player1 wins"
break
end
else
 
goto player2(sum,sm)
end
i+=1
end
end
 
def player2(sum,sm)
for j in 1..100
puts "player2 rolled"
b=gets.chomp().to_i
if(b>1 && b<7)
sm+=b
if sm>=100
puts "player2 wins"
break
end
else
 
player1(sum,sm)
end
j+=1
end
end
i=0
j=0
sum=0
sm=0
player1(sum,sm)
return</syntaxhighlight>
 
=={{header|Sidef}}==
{{trans|Raku}}
<syntaxhighlight lang="ruby">var (games=100) = ARGV.map{.to_i}...
 
define DIE = 1..6
define GOAL = 100
 
class Player(score=0, ante=0, rolls=0, strategy={false}) {
method turn {
rolls = 0
ante = 0
loop {
rolls++
given (DIE.rand) { |roll|
when (1) {
ante = 0
break
}
case (roll > 1) {
ante += roll
}
}
((score + ante >= GOAL) || strategy) && break
}
score += ante
}
}
 
var players = []
 
# default, go-for-broke, always roll again
players[0] = Player()
 
# try to roll 5 times but no more per turn
players[1] = Player( strategy: { players[1].rolls >= 5 } )
 
# try to accumulate at least 20 points per turn
players[2] = Player( strategy: { players[2].ante > 20 } )
 
# random but 90% chance of rolling again
players[3] = Player( strategy: { 1.rand < 0.1 } )
 
# random but more conservative as approaches goal
players[4] = Player( strategy: { 1.rand < ((GOAL - players[4].score) * 0.6 / GOAL) } )
 
var wins = players.len.of(0)
 
games.times {
var player = -1
loop {
player++
var p = players[player % players.len]
p.turn
p.score >= GOAL && break
}
wins[player % players.len]++
players.map{.score}.join("\t").say
players.each { |p| p.score = 0 }
}
 
say "\nSCORES: for #{games} games"
say wins.join("\t")</syntaxhighlight>
{{out}}
<pre>
0 0 67 101 19
0 88 100 9 14
0 81 66 100 24
0 56 103 8 27
0 102 70 17 27
0 79 101 29 36
0 100 71 56 31
0 62 104 28 34
103 19 24 6 5
0 49 101 24 19
0 60 22 101 0
0 20 101 30 34
...
...
...
0 101 69 26 91
0 87 101 30 54
0 84 100 17 64
0 52 24 102 17
 
SCORES: for 100 games
6 28 40 22 4
</pre>
 
Line 1,992 ⟶ 3,766:
<table><tr><td>{{works with|Tcl|8.6}}</td><td>or alternatively with Tcl 8.5 and</td><td>{{libheader|TclOO}}</td></tr></table><!-- dirty trick! -->
First the structure of the game (from [[Pig the dice game#Tcl|the parent page]]):
<langsyntaxhighlight lang="tcl">package require TclOO
 
oo::class create Player {
Line 2,098 ⟶ 3,872:
rotateList scores
}
}</langsyntaxhighlight>
Then the classes that create the various implemented strategies:
<langsyntaxhighlight lang="tcl">oo::class create RoboPlayer {
superclass Player
variable me
Line 2,160 ⟶ 3,934:
dict set scores $who $score
}
}</langsyntaxhighlight>
Demonstration, pitting the three of them against each other:
<langsyntaxhighlight lang="tcl">pig [RandomPlayer new] [To20Player new] [Desperate new]</langsyntaxhighlight>
{{out}}
<pre>
Line 2,259 ⟶ 4,033:
Desperate® has (66,31)... roll
Desperate® has won! (Score: 101)
</pre>
 
=={{header|Wren}}==
{{trans|Sidef}}
<syntaxhighlight lang="wren">import "random" for Random
import "os" for Process
 
var args = Process.arguments
var games = (args.count == 0) ? 100 : Num.fromString(args[0])
 
var Rand = Random.new()
var Die = 1..6
var Goal = 100
 
class Player {
construct new(strategy) {
_score = 0
_ante = 0
_rolls = 0
_strategy = strategy
}
 
score { _score }
rolls { _rolls }
ante { _ante }
 
score=(s) { _score = s }
 
turn() {
_rolls = 0
_ante = 0
while (true) {
_rolls = _rolls + 1
var roll = Rand.int(Die.from, Die.to + 1)
if (roll == 1) {
_ante = 0
break
}
_ante = _ante + roll
if (_score + _ante >= Goal || _strategy.call()) break
}
_score = _score + _ante
}
}
 
var numPlayers = 5
var players = List.filled(numPlayers, null)
 
// default, go-for-broke, always roll again
players[0] = Player.new { false }
 
// try to roll 5 times but no more per turn
players[1] = Player.new { players[1].rolls >= 5 }
 
// try to accumulate at least 20 points per turn
players[2] = Player.new { players[2].ante > 20 }
 
// random but 90% chance of rolling again
players[3] = Player.new { Rand.float() < 0.1 }
 
// random but more conservative as approaches goal
players[4] = Player.new { Rand.float() < (Goal - players[4].score) * 0.6 / Goal }
 
var wins = List.filled(numPlayers, 0)
 
for (i in 0...games) {
var player = -1
while (true) {
player = player + 1
var p = players[player % numPlayers]
p.turn()
if (p.score >= Goal) break
}
wins[player % numPlayers] = wins[player % numPlayers] + 1
System.print(players.map { |p| p.score }.join("\t"))
players.each { |p| p.score = 0 }
}
 
System.print("\nSCORES: for %(games) games")
System.print(wins.join("\t"))</syntaxhighlight>
 
{{out}}
Sample output for 10000 games:
<pre>
0 89 88 102 33
0 21 45 101 16
0 84 104 11 29
0 101 46 20 22
0 102 24 0 36
0 42 100 49 13
0 103 92 34 65
0 82 100 34 34
0 95 100 60 41
0 105 69 53 82
0 35 101 65 66
0 19 102 83 27
0 40 101 24 30
0 101 71 15 67
...
0 101 23 31 34
0 81 45 103 24
102 66 68 82 36
0 101 42 49 49
0 86 103 29 22
0 100 91 82 32
 
SCORES: for 10000 games
938 3581 3426 1656 399
</pre>
9,482

edits