Blackjack strategy: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(15 intermediate revisions by 8 users not shown)
Line 1: Line 1:
[[Category:Games]]
{{task}}
The objective of this task is to recreate and explore the following [http://www.blackjacktactics.com/blackjack/strategy/charts/single-deck/ Strategy charts].
{{draft task}} The objective of this task is to recreate and explore the following [https://web.archive.org/web/20130625120019/http://www.blackjacktactics.com/blackjack/strategy/charts/single-deck/ strategy charts] for the game of [[wp:Blackjack|blackjack]] (which is known by many other names as well).


Assume that my casino:
Assume that my casino:
: Uses a single deck;
* uses a single deck,
: Does not allow Double after split.
* does not allow Double after split,
* pays out 3 to 2 for Blackjack, and
: [http://www.blackjacktactics.com/blackjack/how-to-play/ Uses these rules]
* uses [https://web.archive.org/web/20140822052840/http://www.blackjacktactics.com/blackjack/how-to-play// these rules].


Begin by assuming the player's dealt hand contains no aces and is not a pair.
Begin by assuming the player's dealt hand contains no aces and is not a pair. Create functions which given the players dealt cards and the dealers exposed card returns the number of wins and losses for all possible continuations when the player either sticks or hits. Gather the results together, set a threshold at which you consider it wise to Double the bet and reconstruct the Hard Totals Table enhanced with precise probabilities.
Create functions which given the players dealt cards and the dealers exposed card returns the number of wins and losses for all possible continuations when the player either sticks or hits.
Gather the results together, set a threshold at which you consider it wise to Double the bet and reconstruct the Hard Totals Table enhanced with precise probabilities.


Enhance your analysis by considering the case when the player's hand contains an Ace. Again by considering all continuations recreate the Soft Totals Table again enhanced with precise probabilities.
Enhance your analysis by considering the case when the player's hand contains an Ace. Again by considering all continuations recreate the Soft Totals Table again enhanced with precise probabilities.


Finally complete your analysis by considering the case when the player's hand contains a pair. Again by considering all continuations recreate the Pair Splitting Table again enhanced with precise probabilities.
Finally complete your analysis by considering the case when the player's hand contains a pair.
Again by considering all continuations recreate the Pair Splitting Table again enhanced with precise probabilities.


You should now create a function which randomly deals hands. Assuming I play 50 hands at a visit and visit everyday for a year applying the strategy defined by the tables you have created answer the following questions:
You should now create a function which randomly deals hands.
Assuming I play 50 hands at a visit and visit everyday for a year,
: How many days will I win/lose?
applying the strategy defined by the tables you have created,
: What will be my biggest win?
answer the following questions:
: What will be my biggest loss?
: What will I win/lose over the year?
* How many days can I expect to win/lose?
* What can I expect to be my biggest win?
* What can I expect to be my biggest loss?
* What can I expect to win/lose over the year?
=={{header|Go}}==
As the dealer plays automatically, the first thing I did was to write a function which calculates the probabilities of the dealer ending up with various scores according to the Rules. I then checked the resulting table against a similar one on an 'active' online gambling site (which I'd better not link to here) and the results agreed to 6 decimal places.

The task asks us to calculate precise probabilities for all possible continuations after the player stands, hits, doubles or splits but this is impossible if the player 'hits' or 'splits' as we don't know what decisions (s)he will make subsequently. To be reasonably realistic, I decided to anticipate some further strategy tables I've computed for rounds after the initial deal and to assume that further decisions (to hit or stand) will be made in accordance with these tables.

The criterion I've used for doubling down is that this gives a better expected gain (positive or negative) than the other alternatives, taking into account the doubled stake.

Using these assumptions, I've been able to reproduce the 'hard' strategy table exactly and my 'soft' strategy table only differs in one case (A7/A) where I have 'stand' rather than 'hit' though the underlying figures are quite close.

The trickiest part of this task is dealing with the splitting of pairs (I've assumed re-splitting is not allowed though the Rules aren't explicit on this). The criterion used again is that this gives a better expected gain than the alternatives, taking into account the doubled stake.

I decided, given the other uncertainties, to make the simplifying assumption that, after calculating the expected gain for the first split hand as if the second one isn't completed, the expected gain for the second hand will then be exactly the same. This, of course, is not quite right since both hands need to be completed and the probabilities for the second hand will depend on what cards have been drawn for the first hand and the dealer's probabilities will depend on what cards have been drawn for both hands, a very complicated calculation.

However, the 'true' figures are unlikely to be much different from the figures I've actually used which is borne out by my 'pairs' strategy table only differing from the original in 4 cases out of 100 (33/3, 55/A, 77/T and 88/T). Of these, 2 cases have nothing to do with splitting, 1 case (55/A) is extremely marginal and the other 3 are quite close too.

Finally, I've done 10 years of simulations as the basic statistics can vary quite a bit from year to year. However, it will be seen that % loss varies over a narrower range - between about 0.3 and 1.8% for this particular run - which seems reasonable given the casino's edge even after basic strategy is utilized.
<syntaxhighlight lang="go">package main

import (
"fmt"
"math/rand"
"time"
)

type Deck [11]int // 0:deck size, 1 to 10: number of cards of that denomination

type ActionGain struct {
action string
gain float64
}

func NewDeck() Deck {
return Deck{52, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16}
}

// Returns probabilities of dealer eventually getting:
// 0: 17, 1: 18, 2: 19, 3: 20, 4: 21 (non-blackjack), 5: blackjack (nil), 6: bust.
// It is assumed that the dealer has already checked for blackjack, that one deck is used
// and that the dealer stands on 'soft' 17.
func dealerProbs(upCard int, startDeck Deck) []float64 {
res := make([]float64, 7) // results
decks := make([]Deck, 9) // decks for each level
scores := make([]int, 9) // scores for each level
elevens := make([]int, 9) // number of aces for each level scored as 11
probs := make([]float64, 9) // probs for each level
decks[0] = startDeck
scores[0] = upCard
if upCard == 1 { // an ace
scores[0] = 11
elevens[0] = 1
}
probs[0] = 1.0
var f func(lev int) // recursive closure
f = func(lev int) {
for c := 1; c < 11; c++ {
if decks[lev][c] == 0 {
continue // card no longer present in deck
}
// temporary variables for current level
deck, score, eleven, prob := decks[lev], scores[lev], elevens[lev], probs[lev]
score += c // add card to score
if c == 1 { // score all aces initially as 11
score += 10
eleven++
}
prob *= float64(deck[c]) / float64(deck[0])
if score > 21 && eleven > 0 {
score -= 10 // bust but can demote an ace
eleven--
}
if lev == 0 && ((upCard == 1 && c == 10) || (upCard == 10 && c == 1)) {
res[5] += prob // blackjack, allow for now
} else if score >= 17 && score <= 21 {
res[score-17] += prob // 17 to (non-blackjack) 21
} else if score > 21 && eleven == 0 {
res[6] += prob // bust
} else {
deck[c]-- // remove card from deck
deck[0]-- // decrement deck size
lev2 := lev + 1
decks[lev2], scores[lev2], elevens[lev2], probs[lev2] = deck, score, eleven, prob
f(lev2) // get another card
}
}
}
f(0)
// but can't have blackjack, so adjust probabilities accordingly
pnbj := 1 - res[5]
for i := 0; i < 7; i++ {
res[i] /= pnbj
}
res[5] = 0
return res
}

// Prints chart of dealer probabilities (as a check against an external source).
func dealerChart() {
fmt.Println("Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules")
fmt.Println("Up Card 17 18 19 20 21 Bust")
fmt.Println("-------------------------------------------------------------------")
deck := NewDeck()
deck[0] = 51
for uc := 1; uc < 11; uc++ {
deck2 := deck
deck2[uc]--
dp := dealerProbs(uc, deck2)
if uc > 1 {
fmt.Printf("%3d ", uc)
} else {
fmt.Print("Ace ")
}
fmt.Printf("%f %f %f %f %f %f\n", dp[0], dp[1], dp[2], dp[3], dp[4], dp[6])
}
}

// Returns player's expected gain per unit staked after hitting once and then standing.
func playerGain(card1, card2, uc int, startDeck Deck) float64 {
eg := 0.0
deck := startDeck
score := card1 + card2
eleven := false
if card1 == 1 || card2 == 1 { // an ace
score += 10
eleven = true
}
for c := 1; c < 11; c++ { // get another card
if deck[c] == 0 {
continue // card no longer present in deck
}
// temporary variables for current card
deck2, score2, eleven2 := deck, score, eleven
score2 += c // add card to score
if c == 1 { // score all aces initially as 11
score2 += 10
eleven2 = true
}
prob := float64(deck2[c]) / float64(deck2[0])
deck2[c]-- // remove card from deck
deck2[0]-- // decrement deck size
if score2 > 21 && eleven2 {
score2 -= 10 // bust but can demote an ace
}
if score2 <= 21 {
dp := dealerProbs(uc, deck2)
eg += calcGain(score2, dp) * prob
} else { // bust
eg -= prob
}
}
return eg
}

// Returns player's expected gain per unit staked after hitting once and then continuing in accordance
// with the tables for rounds >= 2.
func playerGain2(card1, card2, uc int, startDeck Deck) float64 {
eg := 0.0 // result
decks := make([]Deck, 9) // decks for each level
scores := make([]int, 9) // scores for each level
elevens := make([]int, 9) // number of aces for each level scored as 11
probs := make([]float64, 9) // probs for each level
decks[0] = startDeck
scores[0] = card1 + card2
if card1 == 1 || card2 == 1 { // an ace
scores[0] += 10
elevens[0] = 1
}
probs[0] = 1.0
var f func(lev int) // recursive closure
f = func(lev int) {
for c := 1; c < 11; c++ {
if decks[lev][c] == 0 {
continue // card no longer present in deck
}
// temporary variables for current level
deck, score, eleven, prob := decks[lev], scores[lev], elevens[lev], probs[lev]
score += c // add card to score
if c == 1 { // score all aces initially as 11
score += 10
eleven++
}
prob *= float64(deck[c]) / float64(deck[0])
if score > 21 && eleven > 0 {
score -= 10 // bust but can demote an ace
eleven--
}
deck[c]-- // remove card from deck
deck[0]-- // decrement deck size
if (eleven == 0 && (score >= 17 || (score >= 13 && uc < 7)) ||
(eleven == 0 && score == 12 && uc >= 4 && uc <= 6) ||
(eleven > 0 && score == 18 && uc != 9 && uc != 10) ||
(eleven > 0 && score >= 19)) && score <= 21 {
dp := dealerProbs(uc, deck)
eg += calcGain(score, dp) * prob
} else if score > 21 && eleven == 0 { // bust
eg -= prob
} else {
lev2 := lev + 1
decks[lev2], scores[lev2], elevens[lev2], probs[lev2] = deck, score, eleven, prob
f(lev2) // get another card
}
}
}
f(0)
return eg
}

// Calculates gain per unit staked for a given scenario (helper function).
func calcGain(pscore int, dp []float64) float64 {
eg := 0.0
switch pscore {
case 17:
eg += dp[6] // dealer is bust
eg -= dp[1] + dp[2] + dp[3] + dp[4] // dealer has 18 to 21
case 18:
eg += dp[0] + dp[6] // dealer has 17 or is bust
eg -= dp[2] + dp[3] + dp[4] // dealer has 19 to 21
case 19:
eg += dp[0] + dp[1] + dp[6] // dealer has 17, 18 or is bust
eg -= dp[3] + dp[4] // dealer has 20 or 21
case 20:
eg += dp[0] + dp[1] + dp[2] + dp[6] // dealer has 17 to 19 or is bust
eg -= dp[4] // dealer has (non-blackjack) 21
case 21:
eg += dp[0] + dp[1] + dp[2] + dp[3] + dp[6] // dealer has 17 to 20 or is bust
case 22: // notional
eg += 1.5 // player blackjack
case 23: // notional
eg -= 1 // player bust, loses stake irrespective of what dealer has
default: // player has less than 17
eg += dp[6] // dealer is bust
eg -= (1 - dp[6]) // dealer isn't bust
}
return eg
}

// Returns player's expected gains per unit staked, for each dealer up-card, after standing.
func stand(card1, card2 int) [10]float64 {
deck := NewDeck()
deck[card1]--
deck[card2]--
deck[0] = 50
pscore := card1 + card2 // player score
if card1 == 1 || card2 == 1 {
pscore += 10
}
var egs [10]float64 // results
for uc := 1; uc < 11; uc++ { // dealer's up-card
deck2 := deck
deck2[uc]--
deck2[0]--
dp := dealerProbs(uc, deck2)
eg := calcGain(pscore, dp) // expected gain for this up-card
if uc > 1 {
egs[uc-2] = eg
} else { // dealer has Ace
egs[9] = eg // ace comes last in tables
}
}
return egs
}

// Returns player's expected gains per unit staked, for each dealer up-card, after hitting once and
// then either standing (once == true) or continuing as per the round >= 2 tables (once == false).
func hit(card1, card2 int, once bool) [10]float64 {
deck := NewDeck()
deck[card1]--
deck[card2]--
deck[0] = 50
var egs [10]float64 // results
for uc := 1; uc < 11; uc++ { // dealer's up-card
deck2 := deck
deck2[uc]--
deck2[0] = 49
var peg float64 // player's expected gain for this up-card
if once {
peg = playerGain(card1, card2, uc, deck2)
} else {
peg = playerGain2(card1, card2, uc, deck2)
}
if uc > 1 {
egs[uc-2] = peg
} else { // dealer has Ace
egs[9] = peg
}
}
return egs
}

// Returns player's expected gains per unit oiginally staked, for each dealer up-card, after
// doubling i.e. hitting once and then standing with a doubled stake.
func double(card1, card2 int) [10]float64 {
egs := hit(card1, card2, true) // hit once and then stand
for i := 0; i < 10; i++ {
egs[i] *= 2
}
return egs
}

// Returns player's expected gains per unit originally staked, for each dealer up-card, after
// splitting a pair and doubling the stake, getting a second card for each hand and then continuing
// in accordace with the rounds >= 2 tables. It is assumed that a player cannot double or re-split
// following a split. It is also assumed (in the interests of simplicity) that the expected gains
// for each split hand (after calculating the gains for the first hand as though the second hand
// is not completed) are exactly the same.
func split(card int) [10]float64 {
deck := NewDeck()
deck[card] -= 2 // must be a pair
deck[0] = 50
var egs [10]float64 // overall results

// now play a single hand
score := card
eleven := 0
if card == 1 { // an ace
score = 11
eleven = 1
}
for uc := 1; uc < 11; uc++ { // collect results for each dealer up-card
if deck[uc] == 0 {
continue // card no longer present in deck
}
deck2 := deck
deck2[uc]--
deck2[0]--
ix := uc - 2
if ix == -1 {
ix = 9 // in tables ace comes last
}
var peg float64 // player expected gain for this up-card
// get second player card
for c := 1; c < 11; c++ {
if deck2[c] == 0 {
continue // card no longer present in deck
}
prob := float64(deck2[c]) / float64(deck2[0])
deck3 := deck2
deck3[c]--
deck3[0]--
score2 := score + c
eleven2 := eleven
if c == 1 { // score all aces initially as 11
score2 += 10
eleven2++
}
if score2 == 21 { // player has blackjack & we know dealer hasn't
peg += 1.5 * prob
continue
}
if score2 > 21 && eleven2 > 0 {
score2 -= 10 // bust but can demote an ace
eleven2--
}
var action string
if eleven2 > 0 {
action = sTable2[score2-12][ix] // use soft strategy table, no doubling
} else { // including pairs as no re-splitting
action = hTable2[score2-4][ix] // use hard strategy table, no doubling
}
var peg2 float64
if action == "S" {
dp := dealerProbs(uc, deck3)
peg2 = calcGain(score2, dp)
} else {
peg2 = playerGain2(card, c, uc, deck3)
}
peg += peg2 * prob
}
if uc > 1 {
egs[uc-2] = peg * 2 // allow for both hands in overall results
} else {
egs[9] = peg * 2 // ditto
}
}
return egs
}

// Returns the action with the highest expected gain.
func bestAction(ags []ActionGain) string {
max := ags[0].gain
maxi := 0
for i := 1; i < len(ags); i++ {
if ags[i].gain > max {
max = ags[i].gain
maxi = i
}
}
return ags[maxi].action
}

// Prints title and header for a given chart.
func printHeader(title string) {
fmt.Println(title)
fmt.Println("P/D 2 3 4 5 6 7 8 9 T A")
fmt.Println("--------------------------------------------------------------------------")
}

// Prints header for a pair of cards.
func printPair(c int) {
if c == 1 {
fmt.Print("AA ")
} else if c == 10 {
fmt.Print("TT ")
} else {
fmt.Printf("%d%d ", c, c)
}
}

// Computed strategy tables.
var (
hTable = [15][10]string{} // hard strategy table (round 1)
sTable = [8][10]string{} // soft strategy table (round 1)
pTable = [10][10]string{} // pairs strategy table (round 1)
hTable2 = [18][10]string{} // hard strategy table (round >= 2, no doubling)
sTable2 = [10][10]string{} // soft strategy table (round >= 2, no doubling)
)

// Simulates 'perDay' blackjack games for 'days' days.
func simulate(perDay, days int) {
winDays, loseDays, evenDays := 0, 0, 0
bigWin, bigLoss := 0.0, 0.0
totalGain, totalStake := 0.0, 0.0
for d := 1; d <= days; d++ {
dailyGain, dailyStake := 0.0, 0.0
for p := 1; p <= perDay; p++ {
gain, stake := playerPlay()
dailyGain += gain
dailyStake += stake
}
if dailyGain > 0 {
winDays++
} else if dailyGain < 0 {
loseDays++
} else {
evenDays++
}
if dailyGain > bigWin {
bigWin = dailyGain
} else if -dailyGain > bigLoss {
bigLoss = -dailyGain
}
totalGain += dailyGain
totalStake += dailyStake
}
fmt.Printf("\nAfter playing %d times a day for %d days:\n", perDay, days)
fmt.Println("Winning days :", winDays)
fmt.Println("Losing days :", loseDays)
fmt.Println("Breakeven days :", evenDays)
fmt.Println("Biggest win :", bigWin)
fmt.Println("Biggest loss :", bigLoss)
if totalGain < 0 {
fmt.Println("Total loss :", -totalGain)
fmt.Println("Total staked :", totalStake)
fmt.Printf("Loss %% staked : %0.3f\n", -totalGain/totalStake*100)
} else {
fmt.Println("Total win :", totalGain)
fmt.Println("Total staked :", totalStake)
fmt.Printf("Win %% staked : %0.3f\n", totalGain/totalStake*100)
}
}

// Simulates a dealer's play for a given player's hand and state of deck.
// Returns the player's gain (positive or negative) per unit staked.
func dealerPlay(pscore int, next *int, cards, d []int) float64 {
dscore := d[0] + d[1]
aces := 0
if d[0] == 1 || d[1] == 1 { // dealer has an ace
dscore += 10
aces++
}
for {
if dscore > 21 && aces > 0 {
dscore -= 10 // bust but we can demote an ace
aces--
}
if dscore > 21 {
return 1 // dealer is bust and player gains stake
}
if dscore >= 17 { // dealer must stick on 17 or above, hard or not
if dscore > pscore {
return -1 // dealer wins and player loses stake
} else if dscore == pscore {
break // player breaks even
} else {
return 1 // dealer loses and player gains stake
}
}
nc := cards[*next] // get new card from pack
*next++
dscore += nc
if nc == 1 { // count aces initially as 11
dscore += 10
aces++
}
}
return 0
}

// Simulates the playing of a random player's hand according to the strategy tables.
// Returns both the gain (positive or negative) and the stake (1 or 2).
func playerPlay() (float64, float64) {
perm := rand.Perm(52) // randomizes integers from 0 to 51 inclusive
cards := make([]int, 52)
for i, r := range perm {
card := r/4 + 1
if card > 10 {
card = 10
}
cards[i] = card
}
var p, d []int // player and dealer hands
// initial deal
for i, card := range cards[0:4] {
if i < 2 {
p = append(p, card)
} else {
d = append(d, card)
}
}
next := 4 // index of next card to be dealt

// check if dealer and/or player have blackjack
dbj := (d[0] == 1 && d[1] == 10) || (d[0] == 10 && d[1] == 1)
pbj := (p[0] == 1 && p[1] == 10) || (p[0] == 10 && p[1] == 1)
if dbj {
if pbj {
return 0.0, 1.0 // player neither wins nor loses
}
return -1.0, 1.0 // player loses stake
}
if pbj {
return 1.5, 1.0 // player wins 1.5 x stake
}

uc := d[0] // dealer's up-card for accessing tables
if uc == 0 {
uc = 9 // move ace to last place
} else {
uc-- // move others down 1
}
stake := 1.0 // player's initial stake
var fscores [2]int // final player scores (one or, after split, two hands)
var action string
var score, aces int

h := func(hand int) { // processes a 'hit'
for {
nc := cards[next] // get new card from pack
next++
score += nc
if nc == 1 { // count aces initially as 11
score += 10
aces++
}
if score > 21 && aces > 0 {
score -= 10 // bust but we can demote an ace
aces--
}
if score > 21 {
fscores[hand] = 22 // player is bust and loses stake
return
}
if action == "D" {
fscores[hand] = score
return
}
// get further strategy and act accordingly
if aces == 0 {
action = hTable2[score-4][uc]
} else {
action = sTable2[score-12][uc]
}
if action == "S" { // stand
fscores[hand] = score
return
}
}
}

score = p[0] + p[1]
// get kind of player hand: hard, soft, pair
var kind string
if p[0] == p[1] {
kind = "pair"
} else if p[0] == 1 || p[1] == 1 {
kind = "soft"
} else {
kind = "hard"
}
switch kind {
case "hard":
action = hTable[score-5][uc]
case "soft": // includes one ace
otherCard := p[0]
if otherCard == 1 {
otherCard = p[1]
}
score += 10
aces = 1
action = sTable[otherCard-2][uc]
case "pair":
if p[0] == 1 { // pair of aces
score += 10
aces = 2
}
action = pTable[p[0]-1][uc]
}
switch action {
case "S": // stand
fscores[0] = score
case "H": // hit
h(0)
case "D": // double
h(0)
stake = 2
case "P": // split
for hand := 0; hand < 2; hand++ {
score = p[0]
aces = 0
if score == 1 { // count aces initially as 11
score = 11
aces++
}
h(hand)
}
}
sum := 0.0
if fscores[0] < 22 {
sum += dealerPlay(fscores[0], &next, cards, d) * stake
} else {
sum -= 1 * stake // this hand is bust
}
if fscores[1] > 0 { // pair
if fscores[1] < 22 {
sum += dealerPlay(fscores[1], &next, cards, d)
} else {
sum -= 1 // this hand is bust
}
stake = 2
}
return sum, stake
}

func main() {
// print dealer probabilities chart
dealerChart()

// for hard scores (i.e. different cards, no aces)
tuples := [][2]int{
{2, 3},
{2, 4},
{2, 5}, {3, 4},
{2, 6}, {3, 5},
{2, 7}, {3, 6}, {4, 5},
{2, 8}, {3, 7}, {4, 6},
{2, 9}, {3, 8}, {4, 7}, {5, 6},
{2, 10}, {3, 9}, {4, 8}, {5, 7},
{3, 10}, {4, 9}, {5, 8}, {6, 7},
{4, 10}, {5, 9}, {6, 8},
{5, 10}, {6, 9}, {7, 8},
{6, 10}, {7, 9},
{7, 10}, {8, 9},
{8, 10},
{9, 10},
}
// number of tuples for each player score from 5 to 19
counts := [15]float64{1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1}
// expected gains for each player score & for each dealer up-card
segs := [15][10]float64{} // if stands
hegs := [15][10]float64{} // if hits
degs := [15][10]float64{} // if doubles
for _, tuple := range tuples {
i := tuple[0] + tuple[1]
sg := stand(tuple[0], tuple[1])
hg := hit(tuple[0], tuple[1], false)
dg := double(tuple[0], tuple[1])
for j := 0; j < 10; j++ {
segs[i-5][j] += sg[j]
hegs[i-5][j] += hg[j]
degs[i-5][j] += dg[j]
}
}
// calculate the average per tuple for each score
for i := 0; i < 15; i++ {
for j := 0; j < 10; j++ {
segs[i][j] /= counts[i]
hegs[i][j] /= counts[i]
degs[i][j] /= counts[i]
}
}

printHeader("\nHard Chart - Player Expected Gains per unit (Stand)")
for i := 5; i < 20; i++ {
fmt.Printf("%2d ", i)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", segs[i-5][j])
}
fmt.Println()
}

printHeader("\nHard Chart - Player Expected Gains per unit (Hit)")
for i := 5; i < 20; i++ {
fmt.Printf("%2d ", i)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", hegs[i-5][j])
}
fmt.Println()
}

printHeader("\nHard Chart - Player Expected Gains per original unit (Double)")
for i := 5; i < 20; i++ {
fmt.Printf("%2d ", i)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", degs[i-5][j])
}
fmt.Println()
}

printHeader("\nHard Chart - Player Strategy (Round 1)")
for i := 5; i < 20; i++ {
fmt.Printf("%2d ", i)
for j := 0; j < 10; j++ {
ags := []ActionGain{{"S", segs[i-5][j]}, {"H", hegs[i-5][j]}, {"D", degs[i-5][j]}}
action := bestAction(ags)
hTable[i-5][j] = action
fmt.Printf("%4s ", action)
}
fmt.Println()
}

// for hard scores (no aces) - after round 1 (no doubling or splitting)
// based on hard table figures (round 1) with scores of 4, 20, and 21 added
segs2 := [18][10]float64{} // expected gains if stands
hegs2 := [18][10]float64{} // expected gains if hits
for i := 5; i < 20; i++ {
segs2[i-4] = segs[i-5]
hegs2[i-4] = hegs[i-5]
}
sg4, hg4 := stand(2, 2), hit(2, 2, false)
sg20, hg20 := stand(10, 10), hit(10, 10, false)
sg21, hg21 := stand(1, 10), hit(1, 10, false)
for j := 0; j < 10; j++ {
segs2[0][j] += sg4[j]
hegs2[0][j] += hg4[j]
segs2[16][j] += sg20[j]
hegs2[16][j] += hg20[j]
segs2[17][j] += sg21[j]
hegs2[17][j] += hg21[j]
}

printHeader("\nHard Chart - Player Strategy (Round >= 2, No Doubling)")
for i := 4; i < 22; i++ {
fmt.Printf("%2d ", i)
for j := 0; j < 10; j++ {
action := "S"
if hegs2[i-4][j] > segs2[i-4][j] {
action = "H"
}
hTable2[i-4][j] = action
fmt.Printf("%4s ", action)
}
fmt.Println()
}

// for soft scores (i.e. including exactly one ace)

// expected gains for each player second card (2 to 9) & for each dealer up-card
segs3 := [8][10]float64{} // if stands
hegs3 := [8][10]float64{} // if hits
degs3 := [8][10]float64{} // if doubles
for c := 2; c < 10; c++ {
sg := stand(1, c)
hg := hit(1, c, false)
dg := double(1, c)
for j := 0; j < 10; j++ {
segs3[c-2][j] += sg[j]
hegs3[c-2][j] += hg[j]
degs3[c-2][j] += dg[j]
}
}

printHeader("\nSoft Chart - Player Expected Gains per unit (Stand)")
for c := 2; c < 10; c++ {
fmt.Printf("A%d ", c)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", segs3[c-2][j])
}
fmt.Println()
}

printHeader("\nSoft Chart - Player Expected Gains per unit (Hit)")
for c := 2; c < 10; c++ {
fmt.Printf("A%d ", c)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", hegs3[c-2][j])
}
fmt.Println()
}

printHeader("\nSoft Chart - Player Expected Gains per original unit (Double)")
for c := 2; c < 10; c++ {
fmt.Printf("A%d ", c)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", degs3[c-2][j])
}
fmt.Println()
}

printHeader("\nSoft Chart - Player Strategy (Round 1)")
for c := 2; c < 10; c++ {
fmt.Printf("A%d ", c)
for j := 0; j < 10; j++ {
ags := []ActionGain{{"S", segs3[c-2][j]}, {"H", hegs3[c-2][j]}, {"D", degs3[c-2][j]}}
action := bestAction(ags)
sTable[c-2][j] = action
fmt.Printf("%4s ", action)
}
fmt.Println()
}

// for soft scores (at least one ace) - after round 1 (no doubling or splitting)
// based on soft table figures (round 1) with scores of 12 and 21 added
// assumes one ace counted as 11
segs4 := [10][10]float64{} // expected gains if stands
hegs4 := [10][10]float64{} // expected gains if hits
for i := 1; i < 9; i++ {
segs4[i] = segs3[i-1]
hegs4[i] = hegs3[i-1]
}
sg12, hg12 := stand(1, 1), hit(1, 1, false)
for j := 0; j < 10; j++ {
segs4[0][j] += sg12[j]
hegs4[0][j] += hg12[j]
segs4[9][j] += sg21[j]
hegs4[9][j] += hg21[j]
}

printHeader("\nSoft Chart - Player Strategy (Round >= 2, No Doubling)")
for i := 12; i < 22; i++ {
fmt.Printf("%2d ", i)
for j := 0; j < 10; j++ {
action := "S"
if hegs4[i-12][j] > segs4[i-12][j] {
action = "H"
}
sTable2[i-12][j] = action
fmt.Printf("%4s ", action)
}
fmt.Println()
}

// for pairs

// expected gains for each pair (A to 10) & for each dealer up-card
segs5 := [10][10]float64{} // if stands
hegs5 := [10][10]float64{} // if hits
degs5 := [10][10]float64{} // if doubles
pegs5 := [10][10]float64{} // if splits
for c := 1; c < 11; c++ {
sg := stand(c, c)
hg := hit(c, c, false)
dg := double(c, c)
pg := split(c)
for j := 0; j < 10; j++ {
segs5[c-1][j] += sg[j]
hegs5[c-1][j] += hg[j]
degs5[c-1][j] += dg[j]
pegs5[c-1][j] += pg[j]
}
}

printHeader("\nPairs Chart - Player Expected Gains per unit (Stand)")
for c := 1; c < 11; c++ {
printPair(c)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", segs5[c-1][j])
}
fmt.Println()
}

printHeader("\nPairs Chart - Player Expected Gains per unit (Hit)")
for c := 1; c < 11; c++ {
printPair(c)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", hegs5[c-1][j])
}
fmt.Println()
}

printHeader("\nPairs Chart - Player Expected Gains per original unit (Double)")
for c := 1; c < 11; c++ {
printPair(c)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", degs5[c-1][j])
}
fmt.Println()
}

printHeader("\nPairs Chart - Player Expected Gains per original unit (Split)")
for c := 1; c < 11; c++ {
printPair(c)
for j := 0; j < 10; j++ {
fmt.Printf("% 0.3f ", pegs5[c-1][j])
}
fmt.Println()
}

printHeader("\nPairs Chart - Player Strategy (Round 1)")
for c := 1; c < 11; c++ {
printPair(c)
for j := 0; j < 10; j++ {
ags := []ActionGain{{"S", segs5[c-1][j]}, {"H", hegs5[c-1][j]}, {"D", degs5[c-1][j]},
{"P", pegs5[c-1][j]}}
action := bestAction(ags)
pTable[c-1][j] = action
fmt.Printf("%4s ", action)
}
fmt.Println()
}
rand.Seed(time.Now().UnixNano())
// do 10 years of simulations
for i := 1; i <= 10; i++ {
fmt.Printf("\nSimulation for Year %d:\n", i)
simulate(50, 365)
}
}</syntaxhighlight>

{{out}}
<pre>
Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules
Up Card 17 18 19 20 21 Bust
-------------------------------------------------------------------
Ace 0.183786 0.190890 0.188680 0.191692 0.075137 0.169815
2 0.138976 0.131762 0.131815 0.123948 0.120526 0.352973
3 0.130313 0.130946 0.123761 0.123345 0.116047 0.375588
4 0.130973 0.114163 0.120679 0.116286 0.115096 0.402803
5 0.119687 0.123483 0.116909 0.104694 0.106321 0.428905
6 0.166948 0.106454 0.107192 0.100705 0.097878 0.420823
7 0.372345 0.138583 0.077334 0.078897 0.072987 0.259854
8 0.130857 0.362989 0.129445 0.068290 0.069791 0.238627
9 0.121886 0.103921 0.357391 0.122250 0.061109 0.233442
10 0.124156 0.122486 0.124421 0.356869 0.039570 0.232499

Hard Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.293 -0.248 -0.176 -0.104 -0.122 -0.469 -0.513 -0.533 -0.546 -0.659
6 -0.291 -0.232 -0.172 -0.101 -0.119 -0.467 -0.522 -0.533 -0.547 -0.659
7 -0.283 -0.229 -0.163 -0.098 -0.117 -0.471 -0.521 -0.537 -0.547 -0.658
8 -0.276 -0.229 -0.162 -0.100 -0.130 -0.478 -0.523 -0.539 -0.549 -0.648
9 -0.277 -0.224 -0.160 -0.108 -0.134 -0.480 -0.528 -0.543 -0.542 -0.646
10 -0.279 -0.227 -0.172 -0.120 -0.146 -0.484 -0.531 -0.539 -0.537 -0.644
11 -0.277 -0.231 -0.175 -0.123 -0.147 -0.488 -0.529 -0.537 -0.537 -0.646
12 -0.286 -0.241 -0.185 -0.134 -0.151 -0.485 -0.526 -0.535 -0.533 -0.655
13 -0.282 -0.236 -0.181 -0.133 -0.156 -0.488 -0.529 -0.537 -0.534 -0.649
14 -0.282 -0.238 -0.188 -0.134 -0.159 -0.489 -0.529 -0.533 -0.536 -0.651
15 -0.280 -0.239 -0.190 -0.144 -0.169 -0.494 -0.531 -0.536 -0.531 -0.648
16 -0.287 -0.250 -0.194 -0.152 -0.179 -0.495 -0.526 -0.540 -0.530 -0.648
17 -0.147 -0.120 -0.074 -0.044 -0.011 -0.122 -0.405 -0.414 -0.402 -0.459
18 0.119 0.144 0.164 0.202 0.268 0.389 0.096 -0.196 -0.155 -0.082
19 0.385 0.384 0.404 0.448 0.484 0.610 0.577 0.264 0.103 0.308

Hard Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.131 -0.098 -0.041 0.022 0.019 -0.119 -0.181 -0.262 -0.309 -0.417
6 -0.151 -0.107 -0.055 0.009 0.014 -0.164 -0.234 -0.305 -0.349 -0.443
7 -0.111 -0.072 -0.013 0.053 0.064 -0.069 -0.223 -0.295 -0.332 -0.401
8 -0.015 0.021 0.084 0.136 0.148 0.092 -0.056 -0.213 -0.253 -0.275
9 0.090 0.137 0.181 0.226 0.235 0.194 0.111 -0.052 -0.148 -0.128
10 0.215 0.246 0.277 0.314 0.319 0.277 0.211 0.119 0.030 0.030
11 0.272 0.296 0.327 0.361 0.362 0.293 0.222 0.146 0.107 0.113
12 -0.256 -0.232 -0.206 -0.181 -0.179 -0.241 -0.308 -0.380 -0.378 -0.413
13 -0.315 -0.293 -0.270 -0.252 -0.251 -0.301 -0.362 -0.389 -0.423 -0.440
14 -0.363 -0.353 -0.337 -0.315 -0.313 -0.346 -0.366 -0.426 -0.455 -0.460
15 -0.419 -0.414 -0.406 -0.392 -0.383 -0.351 -0.406 -0.466 -0.496 -0.487
16 -0.461 -0.460 -0.454 -0.448 -0.397 -0.376 -0.426 -0.481 -0.510 -0.497
17 -0.534 -0.536 -0.538 -0.493 -0.484 -0.450 -0.475 -0.529 -0.558 -0.546
18 -0.633 -0.634 -0.597 -0.591 -0.586 -0.567 -0.565 -0.593 -0.624 -0.630
19 -0.750 -0.713 -0.712 -0.709 -0.707 -0.699 -0.697 -0.698 -0.712 -0.740

Hard Chart - Player Expected Gains per original unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.587 -0.497 -0.352 -0.209 -0.244 -0.938 -1.025 -1.066 -1.093 -1.318
6 -0.560 -0.446 -0.324 -0.186 -0.215 -0.870 -1.023 -1.045 -1.074 -1.295
7 -0.415 -0.317 -0.186 -0.066 -0.059 -0.555 -0.851 -0.936 -0.956 -1.127
8 -0.165 -0.081 0.032 0.143 0.157 -0.140 -0.433 -0.697 -0.743 -0.802
9 0.114 0.193 0.286 0.380 0.393 0.175 0.007 -0.281 -0.442 -0.409
10 0.428 0.492 0.554 0.628 0.638 0.446 0.313 0.164 0.007 0.025
11 0.542 0.592 0.654 0.722 0.724 0.479 0.341 0.223 0.164 0.198
12 -0.511 -0.463 -0.413 -0.362 -0.358 -0.556 -0.690 -0.811 -0.789 -0.827
13 -0.630 -0.587 -0.541 -0.503 -0.503 -0.651 -0.775 -0.807 -0.862 -0.880
14 -0.727 -0.706 -0.673 -0.630 -0.627 -0.723 -0.759 -0.862 -0.915 -0.921
15 -0.838 -0.829 -0.812 -0.783 -0.767 -0.716 -0.826 -0.937 -0.992 -0.973
16 -0.921 -0.920 -0.908 -0.896 -0.793 -0.751 -0.853 -0.961 -1.019 -0.995
17 -1.069 -1.072 -1.076 -0.985 -0.967 -0.901 -0.949 -1.058 -1.116 -1.092
18 -1.265 -1.267 -1.195 -1.182 -1.172 -1.135 -1.130 -1.186 -1.248 -1.260
19 -1.499 -1.425 -1.423 -1.417 -1.414 -1.397 -1.395 -1.396 -1.425 -1.481

Hard Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 H H H H H H H H H H
6 H H H H H H H H H H
7 H H H H H H H H H H
8 H H H D D H H H H H
9 D D D D D H H H H H
10 D D D D D D D D H H
11 D D D D D D D D D D
12 H H S S S H H H H H
13 S S S S S H H H H H
14 S S S S S H H H H H
15 S S S S S H H H H H
16 S S S S S H H H H H
17 S S S S S S S S S S
18 S S S S S S S S S S
19 S S S S S S S S S S

Hard Chart - Player Strategy (Round >= 2, No Doubling)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
4 H H H H H H H H H H
5 H H H H H H H H H H
6 H H H H H H H H H H
7 H H H H H H H H H H
8 H H H H H H H H H H
9 H H H H H H H H H H
10 H H H H H H H H H H
11 H H H H H H H H H H
12 H H S S S H H H H H
13 S S S S S H H H H H
14 S S S S S H H H H H
15 S S S S S H H H H H
16 S S S S S H H H H H
17 S S S S S S S S S S
18 S S S S S S S S S S
19 S S S S S S S S S S
20 S S S S S S S S S S
21 S S S S S S S S S S

Soft Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 -0.283 -0.241 -0.186 -0.119 -0.114 -0.462 -0.508 -0.517 -0.539 -0.662
A3 -0.284 -0.240 -0.170 -0.116 -0.112 -0.460 -0.505 -0.527 -0.538 -0.661
A4 -0.283 -0.224 -0.166 -0.113 -0.109 -0.458 -0.514 -0.526 -0.538 -0.659
A5 -0.266 -0.221 -0.164 -0.111 -0.108 -0.468 -0.515 -0.525 -0.537 -0.659
A6 -0.132 -0.093 -0.037 0.005 0.010 -0.090 -0.385 -0.407 -0.418 -0.483
A7 0.136 0.167 0.204 0.222 0.262 0.412 0.121 -0.179 -0.186 -0.101
A8 0.402 0.420 0.415 0.461 0.482 0.615 0.608 0.288 0.064 0.290
A9 0.656 0.644 0.654 0.682 0.694 0.773 0.785 0.766 0.555 0.681

Soft Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 0.039 0.071 0.110 0.159 0.168 0.107 0.039 -0.014 -0.090 -0.184
A3 0.017 0.044 0.091 0.137 0.147 0.060 0.035 -0.060 -0.124 -0.216
A4 -0.012 0.022 0.061 0.108 0.120 0.034 -0.035 -0.114 -0.172 -0.256
A5 -0.032 -0.003 0.038 0.082 0.116 -0.024 -0.084 -0.167 -0.229 -0.296
A6 0.007 0.036 0.077 0.140 0.133 0.060 -0.065 -0.135 -0.189 -0.242
A7 0.065 0.093 0.156 0.175 0.192 0.175 0.047 -0.087 -0.140 -0.160
A8 0.120 0.173 0.187 0.227 0.241 0.222 0.158 0.005 -0.087 -0.081
A9 0.191 0.196 0.230 0.268 0.280 0.243 0.172 0.096 0.007 -0.008

Soft Chart - Player Expected Gains per original unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 -0.042 0.028 0.115 0.212 0.230 -0.157 -0.312 -0.373 -0.478 -0.586
A3 -0.047 0.011 0.109 0.204 0.222 -0.175 -0.254 -0.394 -0.479 -0.588
A4 -0.070 0.003 0.085 0.175 0.201 -0.141 -0.314 -0.422 -0.495 -0.613
A5 -0.082 -0.019 0.063 0.148 0.217 -0.189 -0.333 -0.452 -0.536 -0.649
A6 0.013 0.074 0.155 0.280 0.266 0.014 -0.230 -0.345 -0.433 -0.522
A7 0.128 0.189 0.313 0.349 0.385 0.240 -0.015 -0.254 -0.322 -0.359
A8 0.237 0.346 0.373 0.453 0.483 0.325 0.190 -0.060 -0.226 -0.200
A9 0.380 0.392 0.459 0.536 0.560 0.351 0.230 0.111 -0.055 -0.055

Soft Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 H H D D D H H H H H
A3 H H D D D H H H H H
A4 H H D D D H H H H H
A5 H H D D D H H H H H
A6 D D D D D H H H H H
A7 S D D D D S S H H S
A8 S S S S D S S S S S
A9 S S S S S S S S S S

Soft Chart - Player Strategy (Round >= 2, No Doubling)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
12 H H H H H H H H H H
13 H H H H H H H H H H
14 H H H H H H H H H H
15 H H H H H H H H H H
16 H H H H H H H H H H
17 H H H H H H H H H H
18 S S S S S S S H H S
19 S S S S S S S S S S
20 S S S S S S S S S S
21 S S S S S S S S S S

Pairs Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA -0.274 -0.232 -0.178 -0.130 -0.104 -0.452 -0.500 -0.511 -0.531 -0.663
22 -0.291 -0.251 -0.192 -0.107 -0.125 -0.471 -0.515 -0.523 -0.547 -0.660
33 -0.295 -0.246 -0.160 -0.101 -0.119 -0.467 -0.510 -0.542 -0.546 -0.660
44 -0.290 -0.214 -0.152 -0.095 -0.114 -0.463 -0.529 -0.543 -0.547 -0.656
55 -0.256 -0.206 -0.146 -0.090 -0.112 -0.484 -0.531 -0.541 -0.545 -0.653
66 -0.262 -0.211 -0.152 -0.102 -0.165 -0.493 -0.536 -0.549 -0.552 -0.617
77 -0.268 -0.219 -0.164 -0.156 -0.174 -0.502 -0.539 -0.555 -0.510 -0.631
88 -0.275 -0.228 -0.215 -0.165 -0.178 -0.503 -0.551 -0.516 -0.518 -0.644
99 0.137 0.123 0.167 0.203 0.265 0.401 0.065 -0.196 -0.133 -0.055
TT 0.627 0.636 0.645 0.674 0.697 0.765 0.783 0.744 0.583 0.650

Pairs Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA 0.095 0.120 0.142 0.182 0.200 0.158 0.093 -0.003 -0.048 -0.075
22 -0.113 -0.082 -0.035 0.036 0.032 -0.092 -0.141 -0.222 -0.277 -0.395
33 -0.153 -0.118 -0.047 0.008 0.014 -0.164 -0.231 -0.310 -0.346 -0.444
44 -0.013 0.028 0.098 0.154 0.175 0.111 -0.055 -0.206 -0.246 -0.268
55 0.224 0.254 0.295 0.347 0.362 0.279 0.207 0.119 0.032 0.042
66 -0.253 -0.222 -0.190 -0.162 -0.194 -0.265 -0.322 -0.386 -0.386 -0.411
77 -0.406 -0.388 -0.369 -0.370 -0.367 -0.389 -0.408 -0.475 -0.516 -0.510
88 -0.454 -0.450 -0.461 -0.453 -0.397 -0.374 -0.426 -0.487 -0.512 -0.490
99 -0.627 -0.638 -0.597 -0.590 -0.587 -0.566 -0.566 -0.595 -0.626 -0.621
TT -0.847 -0.846 -0.846 -0.846 -0.845 -0.843 -0.843 -0.842 -0.840 -0.882

Pairs Chart - Player Expected Gains per original unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA -0.019 0.055 0.137 0.216 0.248 -0.137 -0.296 -0.421 -0.468 -0.591
22 -0.582 -0.501 -0.384 -0.214 -0.249 -0.942 -1.030 -1.047 -1.094 -1.320
33 -0.567 -0.472 -0.302 -0.184 -0.215 -0.871 -1.000 -1.065 -1.072 -1.298
44 -0.185 -0.082 0.044 0.162 0.193 -0.108 -0.447 -0.701 -0.741 -0.802
55 0.446 0.510 0.590 0.695 0.724 0.466 0.323 0.175 0.014 0.042
66 -0.505 -0.444 -0.380 -0.325 -0.387 -0.599 -0.711 -0.817 -0.803 -0.823
77 -0.813 -0.777 -0.738 -0.741 -0.734 -0.823 -0.858 -0.978 -1.035 -1.019
88 -0.908 -0.900 -0.922 -0.906 -0.793 -0.747 -0.853 -0.974 -1.024 -0.980
99 -1.255 -1.277 -1.194 -1.181 -1.173 -1.132 -1.133 -1.189 -1.252 -1.242
TT -1.693 -1.693 -1.693 -1.691 -1.690 -1.686 -1.685 -1.684 -1.681 -1.764

Pairs Chart - Player Expected Gains per original unit (Split)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA 1.192 1.223 1.265 1.321 1.344 1.308 1.201 1.039 0.860 0.921
22 -0.128 -0.070 -0.007 0.128 0.126 -0.054 -0.213 -0.383 -0.463 -0.566
33 -0.202 -0.128 0.009 0.117 0.112 -0.115 -0.265 -0.418 -0.509 -0.579
44 -0.236 -0.127 -0.013 0.095 0.083 -0.223 -0.343 -0.493 -0.580 -0.623
55 -0.232 -0.150 -0.038 0.068 0.056 -0.299 -0.448 -0.608 -0.685 -0.695
66 -0.219 -0.135 -0.028 0.068 -0.011 -0.270 -0.413 -0.570 -0.652 -0.660
77 -0.163 -0.084 0.016 0.039 0.053 -0.123 -0.423 -0.564 -0.634 -0.635
88 0.017 0.077 0.106 0.188 0.234 0.202 -0.100 -0.430 -0.464 -0.378
99 0.170 0.170 0.253 0.339 0.359 0.341 0.179 -0.112 -0.268 -0.109
TT 0.412 0.465 0.518 0.596 0.619 0.576 0.447 0.276 0.146 0.140

Pairs Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA P P P P P P P P P P
22 H P P P P P H H H H
33 H H P P P P H H H H
44 H H H D D H H H H H
55 D D D D D D D D H D
66 P P P P P H H H H H
77 P P P P P P H H S H
88 P P P P P P P P P P
99 P P P P P S P P S S
TT S S S S S S S S S S

Simulation for Year 1:

After playing 50 times a day for 365 days:
Winning days : 170
Losing days : 185
Breakeven days : 10
Biggest win : 20
Biggest loss : 20.5
Total loss : 263
Total staked : 20498
Loss % staked : 1.283

Simulation for Year 2:

After playing 50 times a day for 365 days:
Winning days : 171
Losing days : 184
Breakeven days : 10
Biggest win : 18.5
Biggest loss : 22.5
Total loss : 332.5
Total staked : 20515
Loss % staked : 1.621

Simulation for Year 3:

After playing 50 times a day for 365 days:
Winning days : 154
Losing days : 204
Breakeven days : 7
Biggest win : 28
Biggest loss : 24
Total loss : 339.5
Total staked : 20461
Loss % staked : 1.659

Simulation for Year 4:

After playing 50 times a day for 365 days:
Winning days : 164
Losing days : 191
Breakeven days : 10
Biggest win : 26.5
Biggest loss : 26.5
Total loss : 211.5
Total staked : 20587
Loss % staked : 1.027

Simulation for Year 5:

After playing 50 times a day for 365 days:
Winning days : 175
Losing days : 186
Breakeven days : 4
Biggest win : 18
Biggest loss : 21.5
Total loss : 162
Total staked : 20493
Loss % staked : 0.791

Simulation for Year 6:

After playing 50 times a day for 365 days:
Winning days : 179
Losing days : 177
Breakeven days : 9
Biggest win : 25.5
Biggest loss : 26
Total win : 55.5
Total staked : 20495
Win % staked : 0.271

Simulation for Year 7:

After playing 50 times a day for 365 days:
Winning days : 162
Losing days : 190
Breakeven days : 13
Biggest win : 26.5
Biggest loss : 27
Total loss : 274
Total staked : 20545
Loss % staked : 1.334

Simulation for Year 8:

After playing 50 times a day for 365 days:
Winning days : 165
Losing days : 192
Breakeven days : 8
Biggest win : 21
Biggest loss : 25.5
Total loss : 329
Total staked : 20536
Loss % staked : 1.602

Simulation for Year 9:

After playing 50 times a day for 365 days:
Winning days : 169
Losing days : 186
Breakeven days : 10
Biggest win : 18.5
Biggest loss : 26.5
Total loss : 241
Total staked : 20549
Loss % staked : 1.173

Simulation for Year 10:

After playing 50 times a day for 365 days:
Winning days : 173
Losing days : 183
Breakeven days : 9
Biggest win : 23
Biggest loss : 19
Total loss : 370
Total staked : 20541
Loss % staked : 1.801
</pre>
=={{header|Nim}}==
{{trans|Go}}
<syntaxhighlight lang="nim">import random, sequtils, strformat, strutils

type

Card = 1..10

Deck = object
size: int
cards: array[Card, int]

HandKind {.pure.} = enum Hard, Soft, Pair

Action {.pure.} = enum Stand, Hit, Double, Split

ActionGain = tuple[action: Action; gain: float]


var

# Computed strategy tables.
hTable: array[15, array[10, Action]] # Hard strategy table (round 1).
sTable: array[8, array[10, Action]] # Soft strategy table (round 1).
pTable: array[10, array[10, Action]] # Pairs strategy table (round 1).
hTable2: array[18, array[10, Action]] # Hard strategy table (round >= 2, no doubling).
sTable2: array[10, array[10, Action]] # Soft strategy table (round >= 2, no doubling).



func initDeck(): Deck =
Deck(size: 52, cards: [4, 4, 4, 4, 4, 4, 4, 4, 4, 16])


func `<`(ag1, ag2: ActionGain): bool = ag1.gain < ag2.gain


func dealerProbs(upcard: Card; startDeck: Deck): array[7, float] =
## Returns probabilities of dealer eventually getting:
## 0: 17, 1: 18, 2: 19, 3: 20, 4: 21 (non-blackjack), 5: blackjack (nil), 6: bust.
## It is assumed that the dealer has already checked for blackjack, that one deck is used
## and that the dealer stands on 'soft' 17.

var
res: array[7, float] # Results.
decks: array[9, Deck] # Decks for each level.
scores: array[9, int] # Scores for each level.
elevens: array[9, int] # Number of aces for each level scored as 11.
probs: array[9, float] # Probabilities for each level.

decks[0] = startDeck
scores[0] = upCard
if upcard == 1:
# An ace.
scores[0] = 11
elevens[0] = 1

probs[0] = 1.0

proc drawCard(lev: Natural) =
## Recursive closure.
for c in Card.low..Card.high:
if decks[lev].cards[c] == 0: continue # Card no longer present in deck.

# Temporary variables for current level.
var
deck = decks[lev]
score = scores[lev]
eleven = elevens[lev]
prob = probs[lev]

inc score, c # Add card to score.
if c == 1:
# Score all aces initially as 11.
inc score, 10
inc eleven

prob *= deck.cards[c] / deck.size
if score > 21 and eleven > 0:
dec score, 10 # Bust but can demote an ace.
dec eleven

if lev == 0 and (upCard == 1 and c == 10 or upCard == 10 and c == 1):
res[5] += prob # Blackjack, allow for now.
elif score in 17..21:
res[score-17] += prob # 17 to (non-blackjack) 21.
elif score > 21 and eleven == 0:
res[6] += prob # Bust.
else:
dec deck.cards[c] # Remove card from deck.
dec deck.size
let lev = lev + 1
decks[lev] = deck
scores[lev] = score
elevens[lev] = eleven
probs[lev] = prob
drawCard(lev)

drawCard(0)
# But can't have blackjack, so adjust probabilities accordingly.
let pnbj = 1 - res[5]
for i in 0..6: res[i] /= pnbj

res[5] = 0
result = res


proc dealerChart =
## Print chart of dealer probabilities (as a check against an external source).
echo "Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules"
echo "Up Card 17 18 19 20 21 Bust"
echo "———————————————————————————————————————————————————————————————————"
var deck = initDeck()
deck.size = 51
for uc in Card.low..Card.high:
var deck2 = deck
dec deck2.cards[uc]
let dp = dealerProbs(uc, deck2)
stdout.write if uc > 1: &"{uc:3} " else: "Ace "
for i in [0, 1, 2, 3, 4, 6]: stdout.write &" {dp[i]:.6f}"
echo()


func calcGain(pscore: int; dp: openArray[float]): float =
## Calculates gain per unit staked for a given scenario (helper function).
case pscore
of 17:
result += dp[6] # Dealer is bust.
result -= dp[1] + dp[2] + dp[3] + dp[4] # Dealer has 18 to 21.
of 18:
result += dp[0] + dp[6] # Dealer has 17 or is bust.
result -= dp[2] + dp[3] + dp[4] # Dealer has 19 to 21.
of 19:
result += dp[0] + dp[1] + dp[6] # Dealer has 17, 18 or is bust.
result -= dp[3] + dp[4] # Dealer has 20 or 21.
of 20:
result += dp[0] + dp[1] + dp[2] + dp[6] # Dealer has 17 to 19 or is bust.
result -= dp[4] # Dealer has (non-blackjack) 21.
of 21:
result += dp[0] + dp[1] + dp[2] + dp[3] + dp[6] # Dealer has 17 to 20 or is bust.
of 22: # Notional.
result += 1.5 # Player blackjack.
of 23: # Notional.
result -= 1 # Player bust, loses stake irrespective of what dealer has.
else: # Player has less than 17
result += dp[6] # Dealer is bust.
result -= 1 - dp[6] # Dealer isn't bust.


func playerGain(card1, card2, uc: Card; startDeck: Deck): float =
## Returns player's expected gain per unit staked after hitting once and then standing.
let deck = startDeck
var
score = card1 + card2
eleven = false
if card1 == 1 or card2 == 1:
inc score, 10
eleven = true

for c in Card.low..Card.high:
# Get another card.
if deck.cards[c] == 0: continue # Card no longer present in deck.
# Temporary variables for current card.
var
deck2 = deck
score2 = score
eleven2 = eleven

inc score2, c # Add card to score.
if c == 1:
# Score all aces initially as 11.
inc score2, 10
eleven2 = true

let prob = deck2.cards[c] / deck2.size
dec deck2.cards[c]
dec deck2.size
if score2 > 21 and eleven2:
dec score2, 10 # Bust but can demote an ace.
if score2 <= 21:
let dp = dealerProbs(uc, deck2)
result += calcGain(score2, dp) * prob
else:
# Bust.
result -= prob


func playerGain2(card1, card2, uc: Card; startDeck: Deck): float =
## Return player's expected gain per unit staked after hitting once
## and then continuing in accordance with the tables for rounds >= 2.

var
eg = 0.0 # Result.
decks: array[9, Deck] # Decks for each level.
scores: array[9, int] # Scores for each level.
elevens: array[9, int] # Number of aces for each level scored as 11.
probs: array[9, float] # Probabilities for each level.
decks[0] = startDeck
scores[0] = card1 + card2
if card1 == 1 or card2 == 1:
inc scores[0], 10
elevens[0] = 1

probs[0] = 1.0

proc drawCard(lev: Natural) =
## Recursive closure.
for c in Card.low..Card.high:
if decks[lev].cards[c] == 0: continue # Card no longer present in deck.

# Temporary variables for current level.
var
deck = decks[lev]
score = scores[lev]
eleven = elevens[lev]
prob = probs[lev]

inc score, c # Add card to score.
if c == 1:
# Score all aces initially as 11.
inc score, 10
inc eleven

prob *= deck.cards[c] / deck.size
if score > 21 and eleven > 0:
dec score, 10 # Bust but can demote an ace.
dec eleven

dec deck.cards[c] # Remove card from deck.
dec deck.size

if (eleven == 0 and (score >= 17 or score >= 13 and uc < 7) or
eleven == 0 and score == 12 and uc >= 4 and uc <= 6 or
eleven > 0 and score == 18 and uc != 9 and uc != 10 or
eleven > 0 and score >= 19) and score <= 21:
let dp = dealerProbs(uc, deck)
eg += calcGain(score, dp) * prob
elif score > 21 and eleven == 0:
# Bust.
eg -= prob
else:
let lev = lev + 1
decks[lev] = deck
scores[lev] = score
elevens[lev] = eleven
probs[lev] = prob
drawCard(lev)

drawCard(0)
result = eg


func stand(card1, card2: Card): array[10, float] =
## Return player's expected gains per unit staked, for each dealer up-card, after standing.

var deck = initDeck()
dec deck.cards[card1]
dec deck.cards[card2]
deck.size = 50
var pscore = card1 + card2 # Player score.
if card1 == 1 or card2 == 1:
inc pscore, 10

for uc in Card.low..Card.high: # Dealer's up-card.
var deck2 = deck
dec deck2.cards[uc]
dec deck2.size
let dp = dealerProbs(uc, deck2)
let eg = calcGain(pscore, dp) # Expected gain for this up-card.
if uc > 1:
result[uc-2] = eg
else: # Dealer has Ace.
result[9] = eg # Ace comes last in tables.


func hit(card1, card2: Card; once: bool): array[10, float] =
## Return player's expected gains per unit staked, for each dealer
## up-card, after hitting once and then either standing (once == true)
## or continuing as per the round >= 2 tables (once == false).
var deck = initDeck()
dec deck.cards[card1]
dec deck.cards[card2]
deck.size = 50
for uc in Card.low..Card.high: # Dealer's up-card.
var deck2 = deck
dec deck2.cards[uc]
deck2.size = 49
# Player's expected gain for this up-card.
let peg = if once: playerGain(card1, card2, uc, deck2)
else: playerGain2(card1, card2, uc, deck2)
if uc > 1:
result[uc-2] = peg
else: # Dealer has Ace.
result[9] = peg


func double(card1, card2: Card): array[10, float] =
## Return player's expected gains per unit originally staked,
## for each dealer up-card, after doubling i.e. hitting once
## and then standing with a doubled stake.
result = hit(card1, card2, true) # Hit once and then stand.
for item in result.mitems:
item *= 2


proc split(card: Card): array[10, float] =
## Return player's expected gains per unit originally staked, for each dealer up-card, after
## splitting a pair and doubling the stake, getting a second card for each hand and then
## continuing in accordance with the rounds >= 2 tables. It is assumed that a player cannot
## double or re-split following a split. It is also assumed (in the interests of simplicity)
## that the expected gains for each split hand (after calculating the gains for the first hand
## as though the second hand is not completed) are exactly the same.
var deck = initDeck()
dec deck.cards[card], 2 # Must be a pair.
deck.size = 50

# Now play a single hand.
var score: int = card
var eleven = 0
if card == 1:
score = 11
eleven = 1

for uc in Card.low..Card.high: # Collect results for each dealer up-card.
if deck.cards[uc] == 0: continue # Card no longer present in deck.

var deck2 = deck
dec deck2.cards[uc]
dec deck2.size
var ix = uc - 2
if ix == -1: ix = 9 # In tables ace comes last.
var peg: float # Player expected gain for this up-card.
# Get second player card.
for c in Card.low..Card.high:
if deck2.cards[c] == 0: continue # Card no longer present in deck.

let prob = deck2.cards[c] / deck2.size
var deck3 = deck2
dec deck3.cards[c]
dec deck3.size
var score2 = score + c
var eleven2 = eleven
if c == 1:
# Score all aces initially as 11.
inc score2, 10
inc eleven2

if score2 == 21:
# Player has blackjack & we know dealer hasn't.
peg += 1.5 * prob
continue

if score2 > 21 and eleven2 > 0:
dec score2, 10 # Bust but can demote an ace.
dec eleven2

let action = if eleven2 > 0: sTable2[score2-12][ix] # Use soft strategy table, no doubling.
else: hTable2[score2-4][ix] # Use hard strategy table, no doubling
let peg2 = if action == Stand: calcGain(score2, dealerProbs(uc, deck3))
else: playerGain2(card, c, uc, deck3)
peg += peg2 * prob

if uc > 1:
result[uc-2] = peg * 2 # Allow for both hands in overall results.
else:
result[9] = peg * 2 # Ditto.


func bestAction(ags: openArray[ActionGain]): Action =
## Return the action with the highest expected gain.
ags[ags.maxIndex()].action


proc printHeader(title: string) =
## Print title and header for a given chart.
echo title
echo "P/D 2 3 4 5 6 7 8 9 T A"
echo "——————————————————————————————————————————————————————————————————————————"


proc printPair(c: Card) =
## Print header for a pair of cards.
stdout.write if c == 1: "AA " elif c == 10: "TT " else: &"{c}{c} "


func dealerPlay(pscore: int, next: var int; cards, d: openArray[Card]): float =
## Simulate a dealer's play for a given player's hand and state of deck.
## Return the player's gain (positive or negative) per unit staked.
var dscore = d[0] + d[1]
var aces = 0
if d[0] == 1 or d[1] == 1:
# Dealer has an ace.
inc dscore, 10
inc aces

while true:
if dscore > 21 and aces > 0:
dec dscore, 10 # Bust but we can demote an ace.
dec aces
if dscore > 21:
return 1 # Dealer is bust and player gains stake.

if dscore >= 17:
# Dealer must stick on 17 or above, hard or not.
if dscore > pscore:
return -1 # Dealer wins and player loses stake.
if dscore == pscore:
break # Player breaks even.
return 1 # Dealer loses and player gains stake.

let nc = cards[next] # Get new card from pack.
inc next
inc dscore, nc
if nc == 1:
# Count aces initially as 11.
inc dscore, 10
inc aces


proc playerPlay(): (float, float) =
## Simulate the playing of a random player's hand according to the strategy tables.
## Return both the gain (positive or negative) and the stake (1 or 2).

var perm = toSeq(0..51)
perm.shuffle()
var cards: array[52, Card]
for i, r in perm:
var card = r div 4 + 1
if card > 10: card = 10
cards[i] = card

var p, d: seq[Card] # Player and dealer hands.
# Initial deal.
p.add cards[0..1]
d.add cards[2..3]
var next = 4 # Index of next card to be dealt.

# Check if dealer and/or player have blackjack.
let dbj = d[0] == 1 and d[1] == 10 or d[0] == 10 and d[1] == 1
let pbj = p[0] == 1 and p[1] == 10 or p[0] == 10 and p[1] == 1
if dbj:
if pbj: return (0.0, 1.0) # Player neither wins nor loses.
else: return (-1.0, 1.0) # Player loses stake.
if pbj: return (1.5, 1.0) # Player wins 1.5 x stake.

var uc = d[0] - 2 # Dealer's up-card as index to access tables.
if uc < 0: uc = 9 # Ace is at last place in tables.

var stake = 1.0 # Player's initial stake.
var fscores: array[2, int] # Final player scores (one or, after split, two hands).
var action: Action
var score, aces: int

proc h(hand: int) =
## Process a hit.
while true:
let nc = cards[next] # Get new card from pack.
inc next
inc score, nc
if nc == 1:
# Count aces initially as 11.
inc score, 10
inc aces
if score > 21 and aces > 0:
dec score, 10 # Bust but we can demote an ace.
dec aces
if score > 21:
fscores[hand] = 22 # Player is bust and loses stake.
break
if action == Double:
fscores[hand] = score
break
# Get further strategy and act accordingly.
action = if aces == 0: hTable2[score-4][uc] else: sTable2[score-12][uc]
if action == Stand:
fscores[hand] = score
break

score = p[0] + p[1]
# Get kind of player hand: hard, soft, pair.
let kind = if p[0] == p[1]: Pair elif p[0] == 1 or p[1] == 1: Soft else: Hard

case kind
of Hard:
action = hTable[score-5][uc]
of Soft: # includes one ace.
let othercard = if p[0] == 1: p[1] else: p[0]
inc score, 10
aces = 1
action = sTable[otherCard-2][uc]
of Pair:
if p[0] == 1:
# Pair of aces.
inc score, 10
aces = 2
action = pTable[p[0]-1][uc]

case action
of Stand:
fscores[0] = score
of Hit:
h(0)
of Double:
h(0)
stake = 2
of Split:
for hand in 0..1:
score = p[0]
aces = 0
if score == 1:
# Count aces initially as 11.
score = 11
inc aces
h(hand)

var sum = 0.0
if fscores[0] < 22:
sum += dealerPlay(fscores[0], next, cards, d) * stake
else:
sum -= 1 * stake # This hand is bust.
if fscores[1] > 0:
# Pair.
if fscores[1] < 22:
sum += dealerPlay(fscores[1], next, cards, d)
else:
sum -= 1
stake = 2

result = (sum, stake)


proc simulate(perDay, days: int) =
## Simulate "perDay" blackjack games for "days" days.

var
winDays, loseDays, evenDays = 0
bigWin, bigLoss = 0.0
totalGain, totalStake = 0.0

for d in 1..days:
var dailyGain, dailyStake = 0.0
for p in 1..perDay:
let (gain, stake) = playerPlay()
dailyGain += gain
dailyStake += stake

if dailyGain > 0: inc winDays
elif dailyGain < 0: inc loseDays
else: inc evenDays

if dailyGain > bigWin: bigWin = dailyGain
elif -dailyGain > bigLoss: bigLoss = -dailyGain

totalGain += dailyGain
totalStake += dailyStake

echo &"\nAfter playing {perDay} times a day for {days} days:"
echo "Winning days: ", winDays
echo "Losing days: ", loseDays
echo "Breakeven days: ", evenDays
echo "Biggest win: ", bigWin
echo "Biggest loss: ", bigLoss
if totalGain < 0:
echo "Total loss: ", -totalGain
echo "Total staked: ", totalStake
echo &"Loss % staked: {-totalGain/totalStake*100:0.3f}\n"
else:
echo "Total win: ", totalGain
echo "Total staked: ", totalStake
echo &"Win % staked: {totalGain/totalStake*100:0.3f}\n"


proc main() =

# Print dealer probabilities chart.
dealerChart()

# For hard scores (i.e. different cards, no aces).
const Tuples = [(2, 3),
(2, 4),
(2, 5), (3, 4),
(2, 6), (3, 5),
(2, 7), (3, 6), (4, 5),
(2, 8), (3, 7), (4, 6),
(2, 9), (3, 8), (4, 7), (5, 6),
(2, 10), (3, 9), (4, 8), (5, 7),
(3, 10), (4, 9), (5, 8), (6, 7),
(4, 10), (5, 9), (6, 8),
(5, 10), (6, 9), (7, 8),
(6, 10), (7, 9),
(7, 10), (8, 9),
(8, 10),
(9, 10)]

# Number of tuples for each player score from 5 to 19.
const Counts = [float 1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1]

# Expected gains for each player score & for each dealer up-card.
var
segs: array[15, array[10, float]] # if stands.
hegs: array[15, array[10, float]] # if hits.
degs: array[15, array[10, float]] # if doubles.

for t in Tuples:
let i = t[0] + t[1]
let sg = stand(t[0], t[1])
let hg = hit(t[0], t[1], false)
let dg = double(t[0], t[1])
for j in 0..9:
segs[i-5][j] += sg[j]
hegs[i-5][j] += hg[j]
degs[i-5][j] += dg[j]

# Calculate the average per tuple for each score.
for i in 0..14:
for j in 0..9:
segs[i][j] /= Counts[i]
hegs[i][j] /= Counts[i]
degs[i][j] /= Counts[i]

printHeader("\nHard Chart - Player Expected Gains per unit (Stand)")
for i in 5..19:
stdout.write &"{i:2} "
for j in 0..9:
stdout.write &"{segs[i-5][j]: 0.3f} "
echo()

printHeader("\nHard Chart - Player Expected Gains per unit (Hit)")
for i in 5..19:
stdout.write &"{i:2} "
for j in 0..9:
stdout.write &"{hegs[i-5][j]: 0.3f} "
echo()

printHeader("\nHard Chart - Player Expected Gains per unit (Double)")
for i in 5..19:
stdout.write &"{i:2} "
for j in 0..9:
stdout.write &"{degs[i-5][j]: 0.3f} "
echo()

printHeader("\nHard Chart - Player Strategy (Round 1)")
for i in 5..19:
stdout.write &"{i:2} "
for j in 0..9:
let ags = [(Stand, segs[i-5][j]), (Hit, hegs[i-5][j]), (Double, degs[i-5][j])]
let action = bestAction(ags)
hTable[i-5][j] = action
stdout.write &"{action:^6} "
echo()

# For hard scores (no aces) - after round 1 (no doubling or splitting).
# Based on hard table figures (round 1) with scores of 4, 20, and 21 added.
var
segs2: array[18, array[10, float]] # Expected gains if stands.
hegs2: array[18, array[10, float]] # Expected gains if hits.
for i in 5..19:
segs2[i-4] = segs[i-5]
hegs2[i-4] = hegs[i-5]

let sg4 = stand(2, 2)
let hg4 = hit(2, 2, false)
let sg20 = stand(10, 10)
let hg20 = hit(10, 10, false)
let sg21 = stand(1, 10)
let hg21 = hit(1, 10, false)
for j in 0..9:
segs2[0][j] += sg4[j]
hegs2[0][j] += hg4[j]
segs2[16][j] += sg20[j]
hegs2[16][j] += hg20[j]
segs2[17][j] += sg21[j]
hegs2[17][j] += hg21[j]

printHeader("\nHard Chart - Player Strategy (Round >= 2, No Doubling)")
for i in 4..21:
stdout.write &"{i:2} "
for j in 0..9:
var action = Stand
if hegs2[i-4][j] > segs2[i-4][j]: action = Hit
hTable2[i-4][j] = action
stdout.write &"{action:^6} "
echo()

# For soft scores (i.e. including exactly one ace).

# Expected gains for each player second card (2 to 9) & for each dealer up-card.
var
segs3: array[8, array[10, float]] # if stands.
hegs3: array[8, array[10, float]] # if hits.
degs3: array[8, array[10, float]] # if doubles.
for c in 2..9:
let sg = stand(1, c)
let hg = hit(1, c, false)
let dg = double(1, c)
for j in 0..9:
segs3[c-2][j] += sg[j]
hegs3[c-2][j] += hg[j]
degs3[c-2][j] += dg[j]

printHeader("\nSoft Chart - Player Expected Gains per unit (Stand)")
for c in 2..9:
stdout.write &"A{c} "
for j in 0..9:
stdout.write &"{segs3[c-2][j]: 0.3f} "
echo()


printHeader("\nSoft Chart - Player Expected Gains per unit (Hit)")
for c in 2..9:
stdout.write &"A{c} "
for j in 0..9:
stdout.write &"{hegs3[c-2][j]: 0.3f} "
echo()


printHeader("\nSoft Chart - Player Expected Gains per unit (Double)")
for c in 2..9:
stdout.write &"A{c} "
for j in 0..9:
stdout.write &"{degs3[c-2][j]: 0.3f} "
echo()


printHeader("\nSoft Chart - Player Strategy (Round 1)")
for c in 2..9:
stdout.write &"A{c} "
for j in 0..9:
let ags = [(Stand, segs3[c-2][j]), (Hit, hegs3[c-2][j]), (Double, degs3[c-2][j])]
let action = bestAction(ags)
sTable[c-2][j] = action
stdout.write &"{action:^6} "
echo()


# For soft scores (at least one ace) - after round 1 (no doubling or splitting).
# Based on soft table figures (round 1) with scores of 12 and 21 added.
# Assumes one ace counted as 11.
var
segs4: array[10, array[10, float]] # Expected gains if stands.
hegs4: array[10, array[10, float]] # Expected gains if hits.
for i in 1..8:
segs4[i] = segs3[i-1]
hegs4[i] = hegs3[i-1]

let sg12 = stand(1, 1)
let hg12 = hit(1, 1, false)
for j in 0..9:
segs4[0][j] += sg12[j]
hegs4[0][j] += hg12[j]
segs4[9][j] += sg21[j]
hegs4[9][j] += hg21[j]

printHeader("\nSoft Chart - Player Strategy (Round >= 2, No Doubling)")
for i in 12..21:
stdout.write &"{i:2} "
for j in 0..9:
var action = Stand
if hegs4[i-12][j] > segs4[i-12][j]: action = Hit
sTable2[i-12][j] = action
stdout.write &"{action:^6} "
echo()


# For pairs.

# Expected gains for each pair (A to 10) & for each dealer up-card.
var
segs5: array[10, array[10, float]] # if stands.
hegs5: array[10, array[10, float]] # if hits.
degs5: array[10, array[10, float]] # if double.
pegs5: array[10, array[10, float]] # if split.
for c in 1..10:
let
sg = stand(c, c)
hg = hit(c, c, false)
dg = double(c, c)
pg = split(c)
for j in 0..9:
segs5[c-1][j] += sg[j]
hegs5[c-1][j] += hg[j]
degs5[c-1][j] += dg[j]
pegs5[c-1][j] += pg[j]

printHeader("\nPairs Chart - Player Expected Gains per unit (Stand)")
for c in 1..10:
printPair(c)
for j in 0..9:
stdout.write &"{segs5[c-1][j]: 0.3f} "
echo()

printHeader("\nPairs Chart - Player Expected Gains per unit (Hit)")
for c in 1..10:
printPair(c)
for j in 0..9:
stdout.write &"{hegs5[c-1][j]: 0.3f} "
echo()

printHeader("\nPairs Chart - Player Expected Gains per unit (Double)")
for c in 1..10:
printPair(c)
for j in 0..9:
stdout.write &"{degs5[c-1][j]: 0.3f} "
echo()

printHeader("\nPairs Chart - Player Expected Gains per unit (Split)")
for c in 1..10:
printPair(c)
for j in 0..9:
stdout.write &"{pegs5[c-1][j]: 0.3f} "
echo()

printHeader("\nPairs Chart - Player Strategy (Round 1)")
for c in 1..10:
printPair(c)
for j in 0..9:
let ags = [(Stand, segs5[c-1][j]), (Hit, hegs5[c-1][j]),
(Double, degs5[c-1][j]), (Split, pegs5[c-1][j])]
let action = bestAction(ags)
pTable[c-1][j] = action
stdout.write &"{action:^6} "
echo()

randomize()

# Do 10 years of simulation.
for i in 1..10:
echo &"Simulation for year {i}:"
simulate(50, 365)

main()</syntaxhighlight>

{{out}}
<pre>Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules
Up Card 17 18 19 20 21 Bust
———————————————————————————————————————————————————————————————————
Ace 0.183786 0.190890 0.188680 0.191692 0.075137 0.169815
2 0.138976 0.131762 0.131815 0.123948 0.120526 0.352973
3 0.130313 0.130946 0.123761 0.123345 0.116047 0.375588
4 0.130973 0.114163 0.120679 0.116286 0.115096 0.402803
5 0.119687 0.123483 0.116909 0.104694 0.106321 0.428905
6 0.166948 0.106454 0.107192 0.100705 0.097878 0.420823
7 0.372345 0.138583 0.077334 0.078897 0.072987 0.259854
8 0.130857 0.362989 0.129445 0.068290 0.069791 0.238627
9 0.121886 0.103921 0.357391 0.122250 0.061109 0.233442
10 0.124156 0.122486 0.124421 0.356869 0.039570 0.232499

Hard Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
5 -0.293 -0.248 -0.176 -0.104 -0.122 -0.469 -0.513 -0.533 -0.546 -0.659
6 -0.291 -0.232 -0.172 -0.101 -0.119 -0.467 -0.522 -0.533 -0.547 -0.659
7 -0.283 -0.229 -0.163 -0.098 -0.117 -0.471 -0.521 -0.537 -0.547 -0.658
8 -0.276 -0.229 -0.162 -0.100 -0.130 -0.478 -0.523 -0.539 -0.549 -0.648
9 -0.277 -0.224 -0.160 -0.108 -0.134 -0.480 -0.528 -0.543 -0.542 -0.646
10 -0.279 -0.227 -0.172 -0.120 -0.146 -0.484 -0.531 -0.539 -0.537 -0.644
11 -0.277 -0.231 -0.175 -0.123 -0.147 -0.488 -0.529 -0.537 -0.537 -0.646
12 -0.286 -0.241 -0.185 -0.134 -0.151 -0.485 -0.526 -0.535 -0.533 -0.655
13 -0.282 -0.236 -0.181 -0.133 -0.156 -0.488 -0.529 -0.537 -0.534 -0.649
14 -0.282 -0.238 -0.188 -0.134 -0.159 -0.489 -0.529 -0.533 -0.536 -0.651
15 -0.280 -0.239 -0.190 -0.144 -0.169 -0.494 -0.531 -0.536 -0.531 -0.648
16 -0.287 -0.250 -0.194 -0.152 -0.179 -0.495 -0.526 -0.540 -0.530 -0.648
17 -0.147 -0.120 -0.074 -0.044 -0.011 -0.122 -0.405 -0.414 -0.402 -0.459
18 0.119 0.144 0.164 0.202 0.268 0.389 0.096 -0.196 -0.155 -0.082
19 0.385 0.384 0.404 0.448 0.484 0.610 0.577 0.264 0.103 0.308

Hard Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
5 -0.131 -0.098 -0.041 0.022 0.019 -0.119 -0.181 -0.262 -0.309 -0.417
6 -0.151 -0.107 -0.055 0.009 0.014 -0.164 -0.234 -0.305 -0.349 -0.443
7 -0.111 -0.072 -0.013 0.053 0.064 -0.069 -0.223 -0.295 -0.332 -0.401
8 -0.015 0.021 0.084 0.136 0.148 0.092 -0.056 -0.213 -0.253 -0.275
9 0.090 0.137 0.181 0.226 0.235 0.194 0.111 -0.052 -0.148 -0.128
10 0.215 0.246 0.277 0.314 0.319 0.277 0.211 0.119 0.030 0.030
11 0.272 0.296 0.327 0.361 0.362 0.293 0.222 0.146 0.107 0.113
12 -0.256 -0.232 -0.206 -0.181 -0.179 -0.241 -0.308 -0.380 -0.378 -0.413
13 -0.315 -0.293 -0.270 -0.252 -0.251 -0.301 -0.362 -0.389 -0.423 -0.440
14 -0.363 -0.353 -0.337 -0.315 -0.313 -0.346 -0.366 -0.426 -0.455 -0.460
15 -0.419 -0.414 -0.406 -0.392 -0.383 -0.351 -0.406 -0.466 -0.496 -0.487
16 -0.461 -0.460 -0.454 -0.448 -0.397 -0.376 -0.426 -0.481 -0.510 -0.497
17 -0.534 -0.536 -0.538 -0.493 -0.484 -0.450 -0.475 -0.529 -0.558 -0.546
18 -0.633 -0.634 -0.597 -0.591 -0.586 -0.567 -0.565 -0.593 -0.624 -0.630
19 -0.750 -0.713 -0.712 -0.709 -0.707 -0.699 -0.697 -0.698 -0.712 -0.740

Hard Chart - Player Expected Gains per unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
5 -0.587 -0.497 -0.352 -0.209 -0.244 -0.938 -1.025 -1.066 -1.093 -1.318
6 -0.560 -0.446 -0.324 -0.186 -0.215 -0.870 -1.023 -1.045 -1.074 -1.295
7 -0.415 -0.317 -0.186 -0.066 -0.059 -0.555 -0.851 -0.936 -0.956 -1.127
8 -0.165 -0.081 0.032 0.143 0.157 -0.140 -0.433 -0.697 -0.743 -0.802
9 0.114 0.193 0.286 0.380 0.393 0.175 0.007 -0.281 -0.442 -0.409
10 0.428 0.492 0.554 0.628 0.638 0.446 0.313 0.164 0.007 0.025
11 0.542 0.592 0.654 0.722 0.724 0.479 0.341 0.223 0.164 0.198
12 -0.511 -0.463 -0.413 -0.362 -0.358 -0.556 -0.690 -0.811 -0.789 -0.827
13 -0.630 -0.587 -0.541 -0.503 -0.503 -0.651 -0.775 -0.807 -0.862 -0.880
14 -0.727 -0.706 -0.673 -0.630 -0.627 -0.723 -0.759 -0.862 -0.915 -0.921
15 -0.838 -0.829 -0.812 -0.783 -0.767 -0.716 -0.826 -0.937 -0.992 -0.973
16 -0.921 -0.920 -0.908 -0.896 -0.793 -0.751 -0.853 -0.961 -1.019 -0.995
17 -1.069 -1.072 -1.076 -0.985 -0.967 -0.901 -0.949 -1.058 -1.116 -1.092
18 -1.265 -1.267 -1.195 -1.182 -1.172 -1.135 -1.130 -1.186 -1.248 -1.260
19 -1.499 -1.425 -1.423 -1.417 -1.414 -1.397 -1.395 -1.396 -1.425 -1.481

Hard Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
5 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
6 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
7 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
8 Hit Hit Hit Double Double Hit Hit Hit Hit Hit
9 Double Double Double Double Double Hit Hit Hit Hit Hit
10 Double Double Double Double Double Double Double Double Hit Hit
11 Double Double Double Double Double Double Double Double Double Double
12 Hit Hit Stand Stand Stand Hit Hit Hit Hit Hit
13 Stand Stand Stand Stand Stand Hit Hit Hit Hit Hit
14 Stand Stand Stand Stand Stand Hit Hit Hit Hit Hit
15 Stand Stand Stand Stand Stand Hit Hit Hit Hit Hit
16 Stand Stand Stand Stand Stand Hit Hit Hit Hit Hit
17 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
18 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
19 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand

Hard Chart - Player Strategy (Round >= 2, No Doubling)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
4 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
5 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
6 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
7 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
8 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
9 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
10 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
11 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
12 Hit Hit Stand Stand Stand Hit Hit Hit Hit Hit
13 Stand Stand Stand Stand Stand Hit Hit Hit Hit Hit
14 Stand Stand Stand Stand Stand Hit Hit Hit Hit Hit
15 Stand Stand Stand Stand Stand Hit Hit Hit Hit Hit
16 Stand Stand Stand Stand Stand Hit Hit Hit Hit Hit
17 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
18 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
19 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
20 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
21 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand

Soft Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
A2 -0.283 -0.241 -0.186 -0.119 -0.114 -0.462 -0.508 -0.517 -0.539 -0.662
A3 -0.284 -0.240 -0.170 -0.116 -0.112 -0.460 -0.505 -0.527 -0.538 -0.661
A4 -0.283 -0.224 -0.166 -0.113 -0.109 -0.458 -0.514 -0.526 -0.538 -0.659
A5 -0.266 -0.221 -0.164 -0.111 -0.108 -0.468 -0.515 -0.525 -0.537 -0.659
A6 -0.132 -0.093 -0.037 0.005 0.010 -0.090 -0.385 -0.407 -0.418 -0.483
A7 0.136 0.167 0.204 0.222 0.262 0.412 0.121 -0.179 -0.186 -0.101
A8 0.402 0.420 0.415 0.461 0.482 0.615 0.608 0.288 0.064 0.290
A9 0.656 0.644 0.654 0.682 0.694 0.773 0.785 0.766 0.555 0.681

Soft Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
A2 0.039 0.071 0.110 0.159 0.168 0.107 0.039 -0.014 -0.090 -0.184
A3 0.017 0.044 0.091 0.137 0.147 0.060 0.035 -0.060 -0.124 -0.216
A4 -0.012 0.022 0.061 0.108 0.120 0.034 -0.035 -0.114 -0.172 -0.256
A5 -0.032 -0.003 0.038 0.082 0.116 -0.024 -0.084 -0.167 -0.229 -0.296
A6 0.007 0.036 0.077 0.140 0.133 0.060 -0.065 -0.135 -0.189 -0.242
A7 0.065 0.093 0.156 0.175 0.192 0.175 0.047 -0.087 -0.140 -0.160
A8 0.120 0.173 0.187 0.227 0.241 0.222 0.158 0.005 -0.087 -0.081
A9 0.191 0.196 0.230 0.268 0.280 0.243 0.172 0.096 0.007 -0.008

Soft Chart - Player Expected Gains per unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
A2 -0.042 0.028 0.115 0.212 0.230 -0.157 -0.312 -0.373 -0.478 -0.586
A3 -0.047 0.011 0.109 0.204 0.222 -0.175 -0.254 -0.394 -0.479 -0.588
A4 -0.070 0.003 0.085 0.175 0.201 -0.141 -0.314 -0.422 -0.495 -0.613
A5 -0.082 -0.019 0.063 0.148 0.217 -0.189 -0.333 -0.452 -0.536 -0.649
A6 0.013 0.074 0.155 0.280 0.266 0.014 -0.230 -0.345 -0.433 -0.522
A7 0.128 0.189 0.313 0.349 0.385 0.240 -0.015 -0.254 -0.322 -0.359
A8 0.237 0.346 0.373 0.453 0.483 0.325 0.190 -0.060 -0.226 -0.200
A9 0.380 0.392 0.459 0.536 0.560 0.351 0.230 0.111 -0.055 -0.055

Soft Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
A2 Hit Hit Double Double Double Hit Hit Hit Hit Hit
A3 Hit Hit Double Double Double Hit Hit Hit Hit Hit
A4 Hit Hit Double Double Double Hit Hit Hit Hit Hit
A5 Hit Hit Double Double Double Hit Hit Hit Hit Hit
A6 Double Double Double Double Double Hit Hit Hit Hit Hit
A7 Stand Double Double Double Double Stand Stand Hit Hit Stand
A8 Stand Stand Stand Stand Double Stand Stand Stand Stand Stand
A9 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand

Soft Chart - Player Strategy (Round >= 2, No Doubling)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
12 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
13 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
14 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
15 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
16 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
17 Hit Hit Hit Hit Hit Hit Hit Hit Hit Hit
18 Stand Stand Stand Stand Stand Stand Stand Hit Hit Stand
19 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
20 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
21 Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand

Pairs Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
AA -0.274 -0.232 -0.178 -0.130 -0.104 -0.452 -0.500 -0.511 -0.531 -0.663
22 -0.291 -0.251 -0.192 -0.107 -0.125 -0.471 -0.515 -0.523 -0.547 -0.660
33 -0.295 -0.246 -0.160 -0.101 -0.119 -0.467 -0.510 -0.542 -0.546 -0.660
44 -0.290 -0.214 -0.152 -0.095 -0.114 -0.463 -0.529 -0.543 -0.547 -0.656
55 -0.256 -0.206 -0.146 -0.090 -0.112 -0.484 -0.531 -0.541 -0.545 -0.653
66 -0.262 -0.211 -0.152 -0.102 -0.165 -0.493 -0.536 -0.549 -0.552 -0.617
77 -0.268 -0.219 -0.164 -0.156 -0.174 -0.502 -0.539 -0.555 -0.510 -0.631
88 -0.275 -0.228 -0.215 -0.165 -0.178 -0.503 -0.551 -0.516 -0.518 -0.644
99 0.137 0.123 0.167 0.203 0.265 0.401 0.065 -0.196 -0.133 -0.055
TT 0.627 0.636 0.645 0.674 0.697 0.765 0.783 0.744 0.583 0.650

Pairs Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
AA 0.095 0.120 0.142 0.182 0.200 0.158 0.093 -0.003 -0.048 -0.075
22 -0.113 -0.082 -0.035 0.036 0.032 -0.092 -0.141 -0.222 -0.277 -0.395
33 -0.153 -0.118 -0.047 0.008 0.014 -0.164 -0.231 -0.310 -0.346 -0.444
44 -0.013 0.028 0.098 0.154 0.175 0.111 -0.055 -0.206 -0.246 -0.268
55 0.224 0.254 0.295 0.347 0.362 0.279 0.207 0.119 0.032 0.042
66 -0.253 -0.222 -0.190 -0.162 -0.194 -0.265 -0.322 -0.386 -0.386 -0.411
77 -0.406 -0.388 -0.369 -0.370 -0.367 -0.389 -0.408 -0.475 -0.516 -0.510
88 -0.454 -0.450 -0.461 -0.453 -0.397 -0.374 -0.426 -0.487 -0.512 -0.490
99 -0.627 -0.638 -0.597 -0.590 -0.587 -0.566 -0.566 -0.595 -0.626 -0.621
TT -0.847 -0.846 -0.846 -0.846 -0.845 -0.843 -0.843 -0.842 -0.840 -0.882

Pairs Chart - Player Expected Gains per unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
AA -0.019 0.055 0.137 0.216 0.248 -0.137 -0.296 -0.421 -0.468 -0.591
22 -0.582 -0.501 -0.384 -0.214 -0.249 -0.942 -1.030 -1.047 -1.094 -1.320
33 -0.567 -0.472 -0.302 -0.184 -0.215 -0.871 -1.000 -1.065 -1.072 -1.298
44 -0.185 -0.082 0.044 0.162 0.193 -0.108 -0.447 -0.701 -0.741 -0.802
55 0.446 0.510 0.590 0.695 0.724 0.466 0.323 0.175 0.014 0.042
66 -0.505 -0.444 -0.380 -0.325 -0.387 -0.599 -0.711 -0.817 -0.803 -0.823
77 -0.813 -0.777 -0.738 -0.741 -0.734 -0.823 -0.858 -0.978 -1.035 -1.019
88 -0.908 -0.900 -0.922 -0.906 -0.793 -0.747 -0.853 -0.974 -1.024 -0.980
99 -1.255 -1.277 -1.194 -1.181 -1.173 -1.132 -1.133 -1.189 -1.252 -1.242
TT -1.693 -1.693 -1.693 -1.691 -1.690 -1.686 -1.685 -1.684 -1.681 -1.764

Pairs Chart - Player Expected Gains per unit (Split)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
AA 1.192 1.223 1.265 1.321 1.344 1.308 1.201 1.039 0.860 0.921
22 -0.128 -0.070 -0.007 0.128 0.126 -0.054 -0.213 -0.383 -0.463 -0.566
33 -0.202 -0.128 0.009 0.117 0.112 -0.115 -0.265 -0.418 -0.509 -0.579
44 -0.236 -0.127 -0.013 0.095 0.083 -0.223 -0.343 -0.493 -0.580 -0.623
55 -0.232 -0.150 -0.038 0.068 0.056 -0.299 -0.448 -0.608 -0.685 -0.695
66 -0.219 -0.135 -0.028 0.068 -0.011 -0.270 -0.413 -0.570 -0.652 -0.660
77 -0.163 -0.084 0.016 0.039 0.053 -0.123 -0.423 -0.564 -0.634 -0.635
88 0.017 0.077 0.106 0.188 0.234 0.202 -0.100 -0.430 -0.464 -0.378
99 0.170 0.170 0.253 0.339 0.359 0.341 0.179 -0.112 -0.268 -0.109
TT 0.412 0.465 0.518 0.596 0.619 0.576 0.447 0.276 0.146 0.140

Pairs Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
——————————————————————————————————————————————————————————————————————————
AA Split Split Split Split Split Split Split Split Split Split
22 Hit Split Split Split Split Split Hit Hit Hit Hit
33 Hit Hit Split Split Split Split Hit Hit Hit Hit
44 Hit Hit Hit Double Double Hit Hit Hit Hit Hit
55 Double Double Double Double Double Double Double Double Hit Double
66 Split Split Split Split Split Hit Hit Hit Hit Hit
77 Split Split Split Split Split Split Hit Hit Stand Hit
88 Split Split Split Split Split Split Split Split Split Split
99 Split Split Split Split Split Stand Split Split Stand Stand
TT Stand Stand Stand Stand Stand Stand Stand Stand Stand Stand
Simulation for year 1:

After playing 50 times a day for 365 days:
Winning days: 179
Losing days: 180
Breakeven days: 6
Biggest win: 33.0
Biggest loss: 22.5
Total win: 144.0
Total staked: 20623.0
Win % staked: 0.698

Simulation for year 2:

After playing 50 times a day for 365 days:
Winning days: 168
Losing days: 184
Breakeven days: 13
Biggest win: 25.5
Biggest loss: 25.0
Total loss: 233.0
Total staked: 20553.0
Loss % staked: 1.134

Simulation for year 3:

After playing 50 times a day for 365 days:
Winning days: 177
Losing days: 176
Breakeven days: 12
Biggest win: 25.5
Biggest loss: 22.0
Total loss: 18.5
Total staked: 20646.0
Loss % staked: 0.090

Simulation for year 4:

After playing 50 times a day for 365 days:
Winning days: 193
Losing days: 164
Breakeven days: 8
Biggest win: 26.5
Biggest loss: 22.0
Total win: 210.5
Total staked: 20635.0
Win % staked: 1.020

Simulation for year 5:

After playing 50 times a day for 365 days:
Winning days: 161
Losing days: 191
Breakeven days: 13
Biggest win: 25.0
Biggest loss: 31.0
Total loss: 270.0
Total staked: 20502.0
Loss % staked: 1.317

Simulation for year 6:

After playing 50 times a day for 365 days:
Winning days: 182
Losing days: 175
Breakeven days: 8
Biggest win: 23.0
Biggest loss: 26.0
Total win: 104.0
Total staked: 20610.0
Win % staked: 0.505

Simulation for year 7:

After playing 50 times a day for 365 days:
Winning days: 178
Losing days: 181
Breakeven days: 6
Biggest win: 19.0
Biggest loss: 21.5
Total loss: 86.0
Total staked: 20546.0
Loss % staked: 0.419

Simulation for year 8:

After playing 50 times a day for 365 days:
Winning days: 178
Losing days: 177
Breakeven days: 10
Biggest win: 26.5
Biggest loss: 21.0
Total loss: 127.5
Total staked: 20522.0
Loss % staked: 0.621

Simulation for year 9:

After playing 50 times a day for 365 days:
Winning days: 173
Losing days: 184
Breakeven days: 8
Biggest win: 25.0
Biggest loss: 24.0
Total loss: 14.5
Total staked: 20551.0
Loss % staked: 0.071

Simulation for year 10:

After playing 50 times a day for 365 days:
Winning days: 170
Losing days: 178
Breakeven days: 17
Biggest win: 20.0
Biggest loss: 21.5
Total loss: 93.0
Total staked: 20516.0
Loss % staked: 0.453</pre>
=={{header|Phix}}==
{{trans|Go}}
<!--<syntaxhighlight lang="phix">-->
<span style="color: #000080;font-style:italic;">-- demo/rosetta/blackjack.exw</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">NewDeck</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">52</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">dealerProbs</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">upCard</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">startDeck</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Returns probabilities of dealer eventually getting:
-- 1: 17, 2: 18, 3: 19, 4: 20, 5: 21 (non-blackjack), 6: blackjack (nil), 7: bust.
-- It is assumed that the dealer has already checked for blackjack, that one deck is used
-- and that the dealer stands on 'soft' 17.
--</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// results</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">decks</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// decks for each level</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;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// scores for each level</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">elevens</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;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// number of aces for each level scored as 11</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">probs</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// probs for each level</span>
<span style="color: #000000;">decks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">startDeck</span>
<span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">upCard</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">upCard</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// an ace</span>
<span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">11</span>
<span style="color: #000000;">elevens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">probs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1.0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cs</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;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">lev</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">></span><span style="color: #000000;">10</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">lev</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">decks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">][</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- card still present in deck
// temporary variables for current level</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">decks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">])</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">eleven</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">elevens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">prob</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">probs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span> <span style="color: #000080;font-style:italic;">// add card to score</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// score all aces initially as 11</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">eleven</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">prob</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]/</span><span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">and</span> <span style="color: #000000;">eleven</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">// bust but can demote an ace</span>
<span style="color: #000000;">eleven</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">lev</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">upCard</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">upCard</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">10</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c</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;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">6</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">prob</span> <span style="color: #000080;font-style:italic;">// blackjack, allow for now</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">>=</span> <span style="color: #000000;">17</span> <span style="color: #008080;">and</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">21</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">score</span><span style="color: #0000FF;">-</span><span style="color: #000000;">16</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">prob</span> <span style="color: #000080;font-style:italic;">// 17 to (non-blackjack) 21</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">and</span> <span style="color: #000000;">eleven</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">prob</span> <span style="color: #000080;font-style:italic;">// bust</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// remove card from deck</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// decrement deck size</span>
<span style="color: #000000;">lev</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">decks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deck</span>
<span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span>
<span style="color: #000000;">elevens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eleven</span>
<span style="color: #000000;">probs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">prob</span>
<span style="color: #000080;font-style:italic;">-- get another card:</span>
<span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</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;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000080;font-style:italic;">// but can't have blackjack, so adjust probabilities accordingly</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">pnbj</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">6</span><span style="color: #0000FF;">]</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: #000000;">7</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">pnbj</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">6</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">dealerChart</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">// Prints chart of dealer probabilities (as a check against an external source).</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;">"Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules\n"</span><span style="color: #0000FF;">)</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;">"Up Card 17 18 19 20 21 Bust\n"</span><span style="color: #0000FF;">)</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;">"-------------------------------------------------------------------\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">NewDeck</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">51</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck2</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deck</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dp</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">dealerProbs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</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;">"%3d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</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;">"Ace "</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">6</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</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;">"%f %f %f %f %f %f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000080;font-style:italic;">// Calculates gain per unit staked for a given scenario (helper function).</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">calcGain</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">pscore</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">eg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0.0</span>
<span style="color: #008080;">switch</span> <span style="color: #000000;">pscore</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">17</span><span style="color: #0000FF;">:</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer is bust</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer has 18 to 21</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">18</span><span style="color: #0000FF;">:</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer has 17 or is bust</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer has 19 to 21</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">:</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer has 17, 18 or is bust</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer has 20 or 21</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">:</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer has 17 to 19 or is bust</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer has (non-blackjack) 21</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">21</span><span style="color: #0000FF;">:</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer has 17 to 20 or is bust</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">22</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">// notional</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1.5</span> <span style="color: #000080;font-style:italic;">// player blackjack</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">23</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">// notional</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// player bust, loses stake irrespective of what dealer has</span>
<span style="color: #008080;">default</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">// player has less than 17</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer is bust</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">-=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">1</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">])</span> <span style="color: #000080;font-style:italic;">// dealer isn't bust</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">eg</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">playerGain</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">card1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">card2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">startDeck</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Returns player's expected gain per unit staked after hitting once and then standing.</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">eg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0.0</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">startDeck</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">card1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">card2</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">eleven</span> <span style="color: #0000FF;">:=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">card1</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">card2</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// an ace</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">eleven</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// get another card</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">!=</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// card still present in deck
// temporary variables for current card</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck2</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deck</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">score2</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">score</span>
<span style="color: #000080;font-style:italic;">--DEV shouldn't this be false?</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">eleven2</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">eleven</span>
<span style="color: #000000;">score2</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span> <span style="color: #000080;font-style:italic;">// add card to score</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// score all aces initially as 11</span>
<span style="color: #000000;">score2</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">eleven2</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">prob</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// remove card from deck</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// decrement deck size</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score2</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">and</span> <span style="color: #000000;">eleven2</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">score2</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">// bust but can demote an ace</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score2</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">21</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dp</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">dealerProbs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">calcGain</span><span style="color: #0000FF;">(</span><span style="color: #000000;">score2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">prob</span>
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">// bust</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">prob</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;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">eg</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">playerGain2</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">card1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">card2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">startDeck</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Returns player's expected gain per unit staked after hitting once and then continuing in accordance
// with the tables for rounds &gt;= 2.</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">eg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0.0</span> <span style="color: #000080;font-style:italic;">// result</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">decks</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// decks for each level</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;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// scores for each level</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">elevens</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;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// number of aces for each level scored as 11</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">probs</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// probs for each level</span>
<span style="color: #000000;">decks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">startDeck</span>
<span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">card1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">card2</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">card1</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">card2</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// an ace</span>
<span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">elevens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">probs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1.0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cs</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;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">lev</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">></span><span style="color: #000000;">10</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">lev</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">decks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">][</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- card still present in deck
// temporary variables for current level</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">decks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">])</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">eleven</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">elevens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">prob</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">probs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span> <span style="color: #000080;font-style:italic;">// add card to score</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// score all aces initially as 11</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">eleven</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">prob</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">and</span> <span style="color: #000000;">eleven</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">// bust but can demote an ace</span>
<span style="color: #000000;">eleven</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// remove card from deck</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// decrement deck size</span>
<span style="color: #008080;">if</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">eleven</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">score</span> <span style="color: #0000FF;">>=</span> <span style="color: #000000;">17</span> <span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">score</span> <span style="color: #0000FF;">>=</span> <span style="color: #000000;">13</span> <span style="color: #008080;">and</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">)))</span> <span style="color: #008080;">or</span>
<span style="color: #0000FF;">(</span><span style="color: #000000;">eleven</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">12</span> <span style="color: #008080;">and</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">>=</span> <span style="color: #000000;">4</span> <span style="color: #008080;">and</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span>
<span style="color: #0000FF;">(</span><span style="color: #000000;">eleven</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">18</span> <span style="color: #008080;">and</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">!=</span> <span style="color: #000000;">9</span> <span style="color: #008080;">and</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">!=</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span>
<span style="color: #0000FF;">(</span><span style="color: #000000;">eleven</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">>=</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">and</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">21</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dp</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">dealerProbs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">calcGain</span><span style="color: #0000FF;">(</span><span style="color: #000000;">score</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">prob</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">and</span> <span style="color: #000000;">eleven</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// bust</span>
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">prob</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">lev</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">decks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deck</span>
<span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span>
<span style="color: #000000;">elevens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eleven</span>
<span style="color: #000000;">probs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">prob</span>
<span style="color: #000080;font-style:italic;">// get another card:</span>
<span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lev</span><span style="color: #0000FF;">]</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;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">eg</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">stand</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">card1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">card2</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Returns player's expected gains per unit staked, for each dealer up-card, after standing.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">NewDeck</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">card1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">card2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">50</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">pscore</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">card1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">card2</span> <span style="color: #000080;font-style:italic;">// player score</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">card1</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">card2</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">pscore</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">egs</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;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// results</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// dealer's up-card</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck2</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deck</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dp</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">dealerProbs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">eg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">calcGain</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pscore</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// expected gain for this up-card</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">egs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eg</span>
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">// dealer has Ace</span>
<span style="color: #000000;">egs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eg</span> <span style="color: #000080;font-style:italic;">// ace comes last in tables</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;">egs</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">card1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">card2</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">once</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Returns player's expected gains per unit staked, for each dealer up-card, after hitting once and
// then either standing (once == true) or continuing as per the round &gt;= 2 tables (once == false).</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">NewDeck</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">card1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">card2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">50</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">egs</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;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// results</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// dealer's up-card</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck2</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deck</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">49</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">peg</span> <span style="color: #000080;font-style:italic;">// player's expected gain for this up-card</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">once</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">peg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">playerGain</span><span style="color: #0000FF;">(</span><span style="color: #000000;">card1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">card2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">peg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">playerGain2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">card1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">card2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">egs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">peg</span>
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">// dealer has Ace</span>
<span style="color: #000000;">egs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">peg</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;">egs</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">double</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">card1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">card2</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Returns player's expected gains per unit oiginally staked, for each dealer up-card, after
// doubling i.e. hitting once and then standing with a doubled stake.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">egs</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">card1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">card2</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">true</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// hit once and then stand</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: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">egs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">egs</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">// Computed strategy tables.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hTable</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">15</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// hard strategy table (round 1)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sTable</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// soft strategy table (round 1)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pTable</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// pairs strategy table (round 1)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hTable2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">18</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// hard strategy table (round &gt;= 2, no doubling)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sTable2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// soft strategy table (round &gt;= 2, no doubling)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">splitt</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">card</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Returns player's expected gains per unit originally staked, for each dealer up-card, after
// splitting a pair and doubling the stake, getting a second card for each hand and then continuing
// in accordace with the rounds &gt;= 2 tables. It is assumed that a player cannot double or re-split
// following a split. It is also assumed (in the interests of simplicity) that the expected gains
// for each split hand (after calculating the gains for the first hand as though the second hand
// is not completed) are exactly the same.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">NewDeck</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">card</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">// must be a pair</span>
<span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">50</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">egs</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;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// overall results
// now play a single hand</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">card</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">eleven</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">card</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// an ace</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">11</span>
<span style="color: #000000;">eleven</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// collect results for each dealer up-card</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">!=</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// card still present in deck</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck2</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deck</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ix</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ix</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">ix</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">// in tables ace comes last</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">peg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">// player expected gain for this up-card
// get second player card</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">!=</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// card still present in deck</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">prob</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">deck2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck3</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deck2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">deck3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">deck3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">score2</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">eleven2</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">eleven</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// score all aces initially as 11</span>
<span style="color: #000000;">score2</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">eleven2</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score2</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">21</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// player has blackjack & we know dealer hasn't</span>
<span style="color: #000000;">peg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1.5</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">prob</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score2</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">and</span> <span style="color: #000000;">eleven2</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">score2</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">// bust but can demote an ace</span>
<span style="color: #000000;">eleven2</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">action</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">eleven2</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sTable2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">score2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ix</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// use soft strategy table, no doubling</span>
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">// including pairs as no re-splitting</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hTable2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">score2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ix</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// use hard strategy table, no doubling</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">peg2</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">action</span> <span style="color: #0000FF;">==</span> <span style="color: #008000;">"S"</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dp</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">dealerProbs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">deck3</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">peg2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">calcGain</span><span style="color: #0000FF;">(</span><span style="color: #000000;">score2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dp</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">peg2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">playerGain2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">card</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">uc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">deck3</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">peg</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">peg2</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">prob</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;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">egs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">peg</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">// allow for both hands in overall results</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">egs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">peg</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">// ditto</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;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">egs</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">bestAction</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">ags</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Returns the action with the highest expected gain.</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">best</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">ags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">besti</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ags</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">best</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">best</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">besti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</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;">ags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">besti</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">title</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Prints title and header for a given chart.</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;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">title</span><span style="color: #0000FF;">)</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;">"P/D 2 3 4 5 6 7 8 9 T A\n"</span><span style="color: #0000FF;">)</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;">"--------------------------------------------------------------------------\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">printPair</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Prints header for a pair of cards.</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"A23456789T"</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</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;">"%c%c "</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cards</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fscores</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">next</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">aces</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">uc</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">action</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">dealerPlay</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">pscore</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Simulates a dealer's play for a given player's hand and state of deck.
// Returns the player's gain (positive or negative) per unit staked.</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dscore</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// dealer has an ace</span>
<span style="color: #000000;">dscore</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dscore</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">and</span> <span style="color: #000000;">aces</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">dscore</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">// bust but we can demote an ace</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dscore</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// dealer is bust and player gains stake</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dscore</span> <span style="color: #0000FF;">>=</span> <span style="color: #000000;">17</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// dealer must stick on 17 or above, hard or not</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dscore</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">pscore</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// dealer wins and player loses stake</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">dscore</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">pscore</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">exit</span> <span style="color: #000080;font-style:italic;">// player breaks even</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// dealer loses and player gains stake</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: #004080;">integer</span> <span style="color: #000000;">nc</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">cards</span><span style="color: #0000FF;">[</span><span style="color: #000000;">next</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// get new card from pack</span>
<span style="color: #000000;">next</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">dscore</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">nc</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">nc</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// count aces initially as 11</span>
<span style="color: #000000;">dscore</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</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;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">hand</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// simulate a 'hit'</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;">nc</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">cards</span><span style="color: #0000FF;">[</span><span style="color: #000000;">next</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// get new card from pack</span>
<span style="color: #000000;">next</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">nc</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">nc</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// count aces initially as 11</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">and</span> <span style="color: #000000;">aces</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">// bust but we can demote an ace</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">21</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">22</span> <span style="color: #000080;font-style:italic;">// player is bust and loses stake</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">action</span> <span style="color: #0000FF;">==</span> <span style="color: #008000;">"D"</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">// get further strategy and act accordingly</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">aces</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hTable2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">score</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">][</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sTable2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">score</span><span style="color: #0000FF;">-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">][</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">action</span> <span style="color: #0000FF;">==</span> <span style="color: #008000;">"S"</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// stand</span>
<span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span>
<span style="color: #008080;">return</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;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">playerPlay</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">// Simulates the playing of a random player's hand according to the strategy tables.
// Returns both the gain (positive or negative) and the stake (1 or 2).</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">perm</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">52</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">// randomizes integers from 1 to 52 inclusive</span>
<span style="color: #000000;">cards</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;">52</span><span style="color: #0000FF;">)</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;">perm</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">card</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">r</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">card</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">10</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">card</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">cards</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">card</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">// player and dealer hands
// initial deal</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: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cards</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cards</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</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: #000000;">next</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">5</span> <span style="color: #000080;font-style:italic;">// index of next card to be dealt
// check if dealer and/or player have blackjack</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">dbj</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">10</span> <span style="color: #008080;">and</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">pbj</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">10</span> <span style="color: #008080;">and</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dbj</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pbj</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1.0</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">// player neither wins nor loses</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">1.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1.0</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">// player loses stake</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pbj</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1.5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1.0</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">// player wins 1.5 x stake</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">uc</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">// dealer's up-card for accessing tables</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">uc</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">uc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">// move ace to last place</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">uc</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// move others down 1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">stake</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">1.0</span> <span style="color: #000080;font-style:italic;">// player's initial stake</span>
<span style="color: #000000;">fscores</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">// final player scores (one or, after split, two hands)</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000080;font-style:italic;">// get kind of player hand: hard, soft, pair</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">kind</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">kind</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"pair"</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">kind</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"soft"</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">kind</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"hard"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">switch</span> <span style="color: #000000;">kind</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"hard"</span><span style="color: #0000FF;">:</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hTable</span><span style="color: #0000FF;">[</span><span style="color: #000000;">score</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"soft"</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">// includes one ace</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">otherCard</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">otherCard</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">otherCard</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sTable</span><span style="color: #0000FF;">[</span><span style="color: #000000;">otherCard</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"pair"</span><span style="color: #0000FF;">:</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// pair of aces</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">10</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pTable</span><span style="color: #0000FF;">[</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]][</span><span style="color: #000000;">uc</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #008080;">switch</span> <span style="color: #000000;">action</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"S"</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">// stand</span>
<span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"H"</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">// hit</span>
<span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"D"</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">// double</span>
<span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">stake</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"P"</span><span style="color: #0000FF;">:</span> <span style="color: #000080;font-style:italic;">// split</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">hand</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">score</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// count aces initially as 11</span>
<span style="color: #000000;">score</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">11</span>
<span style="color: #000000;">aces</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">tot</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0.0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">22</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dealerPlay</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">stake</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">stake</span> <span style="color: #000080;font-style:italic;">// this hand is bust</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// pair</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">22</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dealerPlay</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fscores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// this hand is bust</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">stake</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tot</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">stake</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">simulate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">perDay</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">days</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// Simulates 'perDay' blackjack games for 'days' days.</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">winDays</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">loseDays</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">evenDays</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">bigWin</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bigLoss</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">totalGain</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">totalStake</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">days</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">dailyGain</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dailyStake</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0.0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">perDay</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">gain</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">stake</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">playerPlay</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">dailyGain</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">gain</span>
<span style="color: #000000;">dailyStake</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">stake</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dailyGain</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">winDays</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">dailyGain</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">loseDays</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">evenDays</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dailyGain</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">bigWin</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">bigWin</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dailyGain</span>
<span style="color: #008080;">elsif</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">dailyGain</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">bigLoss</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">bigLoss</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">dailyGain</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">totalGain</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dailyGain</span>
<span style="color: #000000;">totalStake</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dailyStake</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;">"\nAfter playing %d times a day for %d days:\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">perDay</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">days</span><span style="color: #0000FF;">})</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;">"Winning days :%d\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">winDays</span><span style="color: #0000FF;">)</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;">"Losing days :%d\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">loseDays</span><span style="color: #0000FF;">)</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;">"Breakeven days :%d\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">evenDays</span><span style="color: #0000FF;">)</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;">"Biggest win :%.2f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bigWin</span><span style="color: #0000FF;">)</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;">"Biggest loss :%.2f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bigLoss</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">totalGain</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</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;">"Total loss :%.2f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">totalGain</span><span style="color: #0000FF;">)</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;">"Total staked :%.2f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">totalStake</span><span style="color: #0000FF;">)</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;">"Loss %% staked : %0.3f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">totalGain</span><span style="color: #0000FF;">/</span><span style="color: #000000;">totalStake</span><span style="color: #0000FF;">*</span><span style="color: #000000;">100</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</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;">"Total win :%.2f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">totalGain</span><span style="color: #0000FF;">)</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;">"Total staked :%.2f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">totalStake</span><span style="color: #0000FF;">)</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;">"Win %% staked : %0.3f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">totalGain</span><span style="color: #0000FF;">/</span><span style="color: #000000;">totalStake</span><span style="color: #0000FF;">*</span><span style="color: #000000;">100</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;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">// print dealer probabilities chart</span>
<span style="color: #000000;">dealerChart</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">// for hard scores (i.e. different cards, no aces)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tuples</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">{</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">}</span>
<span style="color: #000080;font-style:italic;">// number of tuples for each player score from 5 to 19</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">counts</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">}</span>
<span style="color: #000080;font-style:italic;">// expected gains for each player score & for each dealer up-card</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">segs</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">15</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// if stands</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hegs</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">15</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// if hits</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">degs</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">15</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// if doubles</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">t</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;">tuples</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d/%d\r"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tuples</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tuple</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">tuples</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">tuple</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">tuple</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">stand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tuple</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">tuple</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tuple</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">tuple</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">double</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tuple</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">tuple</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">segs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">hg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">degs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</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: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">// calculate the average per tuple for each score</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: #000000;">15</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">segs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">degs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</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: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nHard Chart - Player Expected Gains per unit (Stand)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</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;">"%2d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">segs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nHard Chart - Player Expected Gains per unit (Hit)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</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;">"%2d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hegs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nHard Chart - Player Expected Gains per original unit (Double)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</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;">"%2d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nHard Chart - Player Strategy (Round 1)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</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;">"%2d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ags</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"S"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">segs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"H"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hegs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"D"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}}</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">action</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">bestAction</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ags</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">hTable</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">action</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;">"%4s "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">action</span><span style="color: #0000FF;">)</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">// for hard scores (no aces) - after round 1 (no doubling or splitting)
// based on hard table figures (round 1) with scores of 4, 20, and 21 added</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">segs2</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">18</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// expected gains if stands</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hegs2</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">18</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// expected gains if hits</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">segs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">segs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hegs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sg4</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">hg4</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">sg20</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">hg20</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">sg21</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">hg21</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">segs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sg4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">hg4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">segs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">17</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sg20</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">17</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">hg20</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">segs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">18</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sg21</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">18</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">hg21</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nHard Chart - Player Strategy (Round &gt;= 2, No Doubling)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">to</span> <span style="color: #000000;">21</span> <span style="color: #008080;">do</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;">"%2d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">action</span> <span style="color: #0000FF;">:=</span> <span style="color: #008000;">"S"</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">hegs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">segs2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"H"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">hTable2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">action</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;">"%4s "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">action</span><span style="color: #0000FF;">)</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">// for soft scores (i.e. including exactly one ace)
// expected gains for each player second card (2 to 9) & for each dealer up-card</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">segs3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">8</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">// if stands</span>
<span style="color: #000000;">hegs3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">8</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">// if hits</span>
<span style="color: #000000;">degs3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// if doubles</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">stand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">hg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">dg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">double</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">segs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">hg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">degs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</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: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nSoft Chart - Player Expected Gains per unit (Stand)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</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;">"A%d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">segs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nSoft Chart - Player Expected Gains per unit (Hit)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</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;">"A%d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hegs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nSoft Chart - Player Expected Gains per original unit (Double)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</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;">"A%d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nSoft Chart - Player Strategy (Round 1)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</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;">"A%d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ags</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"S"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">segs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"H"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hegs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"D"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}}</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">action</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">bestAction</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ags</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">sTable</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">action</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;">"%4s "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">action</span><span style="color: #0000FF;">)</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">// for soft scores (at least one ace) - after round 1 (no doubling or splitting)
// based on soft table figures (round 1) with scores of 12 and 21 added
// assumes one ace counted as 11</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">segs4</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">// expected gains if stands</span>
<span style="color: #000000;">hegs4</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// expected gains if hits</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">segs4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">segs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hegs3</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sg12</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">hg12</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">segs4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sg12</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">hg12</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">segs4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sg21</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">hg21</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nSoft Chart - Player Strategy (Round &gt;= 2, No Doubling)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">12</span> <span style="color: #008080;">to</span> <span style="color: #000000;">21</span> <span style="color: #008080;">do</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;">"%2d "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">action</span> <span style="color: #0000FF;">:=</span> <span style="color: #008000;">"S"</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">hegs4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">segs4</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">action</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"H"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">sTable2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">action</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;">"%4s "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">action</span><span style="color: #0000FF;">)</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">// for pairs
// expected gains for each pair (A to 10) & for each dealer up-card</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">segs5</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">// if stands</span>
<span style="color: #000000;">hegs5</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">// if hits</span>
<span style="color: #000000;">degs5</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">// if doubles</span>
<span style="color: #000000;">pegs5</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">repeat</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;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">// if splits</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d/10"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">stand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">hg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">hit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">dg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">double</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">pg</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">splitt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">segs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">sg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">hegs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">hg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">degs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">pegs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">pg</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</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: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nPairs Chart - Player Expected Gains per unit (Stand)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">printPair</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">segs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nPairs Chart - Player Expected Gains per unit (Hit)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">printPair</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hegs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nPairs Chart - Player Expected Gains per original unit (Double)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">printPair</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nPairs Chart - Player Expected Gains per original unit (Split)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">printPair</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</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;">"%6.3f "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pegs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">printHeader</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\nPairs Chart - Player Strategy (Round 1)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">printPair</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ags</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"S"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">segs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"H"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hegs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"D"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">degs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]},</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"P"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pegs5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}}</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">action</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">bestAction</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ags</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">pTable</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">action</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;">"%4s "</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">action</span><span style="color: #0000FF;">)</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;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">// do 10 years of simulations</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: #000000;">10</span> <span style="color: #008080;">do</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;">"\nSimulation for Year %d:\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">simulate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">365</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<span style="color: #0000FF;">?</span><span style="color: #008000;">"done"</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>

Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules
Up Card 17 18 19 20 21 Bust
-------------------------------------------------------------------
Ace 0.183786 0.190890 0.188680 0.191692 0.075137 0.169815
2 0.138976 0.131762 0.131815 0.123948 0.120526 0.352973
3 0.130313 0.130946 0.123761 0.123345 0.116047 0.375588
4 0.130973 0.114163 0.120679 0.116286 0.115096 0.402803
5 0.119687 0.123483 0.116909 0.104694 0.106321 0.428905
6 0.166948 0.106454 0.107192 0.100705 0.097878 0.420823
7 0.372345 0.138583 0.077334 0.078897 0.072987 0.259854
8 0.130857 0.362989 0.129445 0.068290 0.069791 0.238627
9 0.121886 0.103921 0.357391 0.122250 0.061109 0.233442
10 0.124156 0.122486 0.124421 0.356869 0.039570 0.232499

Hard Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.293 -0.248 -0.176 -0.104 -0.122 -0.469 -0.513 -0.533 -0.546 -0.659
6 -0.291 -0.232 -0.172 -0.101 -0.119 -0.467 -0.522 -0.533 -0.547 -0.659
7 -0.283 -0.229 -0.163 -0.098 -0.117 -0.471 -0.521 -0.537 -0.547 -0.658
8 -0.276 -0.229 -0.162 -0.100 -0.130 -0.478 -0.523 -0.539 -0.549 -0.648
9 -0.277 -0.224 -0.160 -0.108 -0.134 -0.480 -0.528 -0.543 -0.542 -0.646
10 -0.279 -0.227 -0.172 -0.120 -0.146 -0.484 -0.531 -0.539 -0.537 -0.644
11 -0.277 -0.231 -0.175 -0.123 -0.147 -0.488 -0.529 -0.537 -0.537 -0.646
12 -0.286 -0.241 -0.185 -0.134 -0.151 -0.485 -0.526 -0.535 -0.533 -0.655
13 -0.282 -0.236 -0.181 -0.133 -0.156 -0.488 -0.529 -0.537 -0.534 -0.649
14 -0.282 -0.238 -0.188 -0.134 -0.159 -0.489 -0.529 -0.533 -0.536 -0.651
15 -0.280 -0.239 -0.190 -0.144 -0.169 -0.494 -0.531 -0.536 -0.531 -0.648
16 -0.287 -0.250 -0.194 -0.152 -0.179 -0.495 -0.526 -0.540 -0.530 -0.648
17 -0.147 -0.120 -0.074 -0.044 -0.011 -0.122 -0.405 -0.414 -0.402 -0.459
18 0.119 0.144 0.164 0.202 0.268 0.389 0.096 -0.196 -0.155 -0.082
19 0.385 0.384 0.404 0.448 0.484 0.610 0.577 0.264 0.103 0.308

Hard Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.131 -0.098 -0.041 0.022 0.019 -0.119 -0.181 -0.262 -0.309 -0.417
6 -0.151 -0.107 -0.055 0.009 0.014 -0.164 -0.234 -0.305 -0.349 -0.443
7 -0.111 -0.072 -0.013 0.053 0.064 -0.069 -0.223 -0.295 -0.332 -0.401
8 -0.015 0.021 0.084 0.136 0.148 0.092 -0.056 -0.213 -0.253 -0.275
9 0.090 0.137 0.181 0.226 0.235 0.194 0.111 -0.052 -0.148 -0.128
10 0.215 0.246 0.277 0.314 0.319 0.277 0.211 0.119 0.030 0.030
11 0.272 0.296 0.327 0.361 0.362 0.293 0.222 0.146 0.107 0.113
12 -0.256 -0.232 -0.206 -0.181 -0.179 -0.241 -0.308 -0.380 -0.378 -0.413
13 -0.315 -0.293 -0.270 -0.252 -0.251 -0.301 -0.362 -0.389 -0.423 -0.440
14 -0.363 -0.353 -0.337 -0.315 -0.313 -0.346 -0.366 -0.426 -0.455 -0.460
15 -0.419 -0.414 -0.406 -0.392 -0.383 -0.351 -0.406 -0.466 -0.496 -0.487
16 -0.461 -0.460 -0.454 -0.448 -0.397 -0.376 -0.426 -0.481 -0.510 -0.497
17 -0.534 -0.536 -0.538 -0.493 -0.484 -0.450 -0.475 -0.529 -0.558 -0.546
18 -0.633 -0.634 -0.597 -0.591 -0.586 -0.567 -0.565 -0.593 -0.624 -0.630
19 -0.750 -0.713 -0.712 -0.709 -0.707 -0.699 -0.697 -0.698 -0.712 -0.740

Hard Chart - Player Expected Gains per original unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.587 -0.497 -0.352 -0.209 -0.244 -0.938 -1.025 -1.066 -1.093 -1.318
6 -0.560 -0.446 -0.324 -0.186 -0.215 -0.870 -1.023 -1.045 -1.074 -1.295
7 -0.415 -0.317 -0.186 -0.066 -0.059 -0.555 -0.851 -0.936 -0.956 -1.127
8 -0.165 -0.081 0.032 0.143 0.157 -0.140 -0.433 -0.697 -0.743 -0.802
9 0.114 0.193 0.286 0.380 0.393 0.175 0.007 -0.281 -0.442 -0.409
10 0.428 0.492 0.554 0.628 0.638 0.446 0.313 0.164 0.007 0.025
11 0.542 0.592 0.654 0.722 0.724 0.479 0.341 0.223 0.164 0.198
12 -0.511 -0.463 -0.413 -0.362 -0.358 -0.556 -0.690 -0.811 -0.789 -0.827
13 -0.630 -0.587 -0.541 -0.503 -0.503 -0.651 -0.775 -0.807 -0.862 -0.880
14 -0.727 -0.706 -0.673 -0.630 -0.627 -0.723 -0.759 -0.862 -0.915 -0.921
15 -0.838 -0.829 -0.812 -0.783 -0.767 -0.716 -0.826 -0.937 -0.992 -0.973
16 -0.921 -0.920 -0.908 -0.896 -0.793 -0.751 -0.853 -0.961 -1.019 -0.995
17 -1.069 -1.072 -1.076 -0.985 -0.967 -0.901 -0.949 -1.058 -1.116 -1.092
18 -1.265 -1.267 -1.195 -1.182 -1.172 -1.135 -1.130 -1.186 -1.248 -1.260
19 -1.499 -1.425 -1.423 -1.417 -1.414 -1.397 -1.395 -1.396 -1.425 -1.481

Hard Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 H H H H H H H H H H
6 H H H H H H H H H H
7 H H H H H H H H H H
8 H H H D D H H H H H
9 D D D D D H H H H H
10 D D D D D D D D H H
11 D D D D D D D D D D
12 H H S S S H H H H H
13 S S S S S H H H H H
14 S S S S S H H H H H
15 S S S S S H H H H H
16 S S S S S H H H H H
17 S S S S S S S S S S
18 S S S S S S S S S S
19 S S S S S S S S S S

Hard Chart - Player Strategy (Round >= 2, No Doubling)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
4 H H H H H H H H H H
5 H H H H H H H H H H
6 H H H H H H H H H H
7 H H H H H H H H H H
8 H H H H H H H H H H
9 H H H H H H H H H H
10 H H H H H H H H H H
11 H H H H H H H H H H
12 H H S S S H H H H H
13 S S S S S H H H H H
14 S S S S S H H H H H
15 S S S S S H H H H H
16 S S S S S H H H H H
17 S S S S S S S S S S
18 S S S S S S S S S S
19 S S S S S S S S S S
20 S S S S S S S S S S
21 S S S S S S S S S S

Soft Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 -0.283 -0.241 -0.186 -0.119 -0.114 -0.462 -0.508 -0.517 -0.539 -0.662
A3 -0.284 -0.240 -0.170 -0.116 -0.112 -0.460 -0.505 -0.527 -0.538 -0.661
A4 -0.283 -0.224 -0.166 -0.113 -0.109 -0.458 -0.514 -0.526 -0.538 -0.659
A5 -0.266 -0.221 -0.164 -0.111 -0.108 -0.468 -0.515 -0.525 -0.537 -0.659
A6 -0.132 -0.093 -0.037 0.005 0.010 -0.090 -0.385 -0.407 -0.418 -0.483
A7 0.136 0.167 0.204 0.222 0.262 0.412 0.121 -0.179 -0.186 -0.101
A8 0.402 0.420 0.415 0.461 0.482 0.615 0.608 0.288 0.064 0.290
A9 0.656 0.644 0.654 0.682 0.694 0.773 0.785 0.766 0.555 0.681

Soft Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 0.039 0.071 0.110 0.159 0.168 0.107 0.039 -0.014 -0.090 -0.184
A3 0.017 0.044 0.091 0.137 0.147 0.060 0.035 -0.060 -0.124 -0.216
A4 -0.012 0.022 0.061 0.108 0.120 0.034 -0.035 -0.114 -0.172 -0.256
A5 -0.032 -0.003 0.038 0.082 0.116 -0.024 -0.084 -0.167 -0.229 -0.296
A6 0.007 0.036 0.077 0.140 0.133 0.060 -0.065 -0.135 -0.189 -0.242
A7 0.065 0.093 0.156 0.175 0.192 0.175 0.047 -0.087 -0.140 -0.160
A8 0.120 0.173 0.187 0.227 0.241 0.222 0.158 0.005 -0.087 -0.081
A9 0.191 0.196 0.230 0.268 0.280 0.243 0.172 0.096 0.007 -0.008

Soft Chart - Player Expected Gains per original unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 -0.042 0.028 0.115 0.212 0.230 -0.157 -0.312 -0.373 -0.478 -0.586
A3 -0.047 0.011 0.109 0.204 0.222 -0.175 -0.254 -0.394 -0.479 -0.588
A4 -0.070 0.003 0.085 0.175 0.201 -0.141 -0.314 -0.422 -0.495 -0.613
A5 -0.082 -0.019 0.063 0.148 0.217 -0.189 -0.333 -0.452 -0.536 -0.649
A6 0.013 0.074 0.155 0.280 0.266 0.014 -0.230 -0.345 -0.433 -0.522
A7 0.128 0.189 0.313 0.349 0.385 0.240 -0.015 -0.254 -0.322 -0.359
A8 0.237 0.346 0.373 0.453 0.483 0.325 0.190 -0.060 -0.226 -0.200
A9 0.380 0.392 0.459 0.536 0.560 0.351 0.230 0.111 -0.055 -0.055

Soft Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 H H D D D H H H H H
A3 H H D D D H H H H H
A4 H H D D D H H H H H
A5 H H D D D H H H H H
A6 D D D D D H H H H H
A7 S D D D D S S H H S
A8 S S S S D S S S S S
A9 S S S S S S S S S S

Soft Chart - Player Strategy (Round >= 2, No Doubling)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
12 H H H H H H H H H H
13 H H H H H H H H H H
14 H H H H H H H H H H
15 H H H H H H H H H H
16 H H H H H H H H H H
17 H H H H H H H H H H
18 S S S S S S S H H S
19 S S S S S S S S S S
20 S S S S S S S S S S
21 S S S S S S S S S S

Pairs Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA -0.274 -0.232 -0.178 -0.130 -0.104 -0.452 -0.500 -0.511 -0.531 -0.663
22 -0.291 -0.251 -0.192 -0.107 -0.125 -0.471 -0.515 -0.523 -0.547 -0.660
33 -0.295 -0.246 -0.160 -0.101 -0.119 -0.467 -0.510 -0.542 -0.546 -0.660
44 -0.290 -0.214 -0.152 -0.095 -0.114 -0.463 -0.529 -0.543 -0.547 -0.656
55 -0.256 -0.206 -0.146 -0.090 -0.112 -0.484 -0.531 -0.541 -0.545 -0.653
66 -0.262 -0.211 -0.152 -0.102 -0.165 -0.493 -0.536 -0.549 -0.552 -0.617
77 -0.268 -0.219 -0.164 -0.156 -0.174 -0.502 -0.539 -0.555 -0.510 -0.631
88 -0.275 -0.228 -0.215 -0.165 -0.178 -0.503 -0.551 -0.516 -0.518 -0.644
99 0.137 0.123 0.167 0.203 0.265 0.401 0.065 -0.196 -0.133 -0.055
TT 0.627 0.636 0.645 0.674 0.697 0.765 0.783 0.744 0.583 0.650

Pairs Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA 0.095 0.120 0.142 0.182 0.200 0.158 0.093 -0.003 -0.048 -0.075
22 -0.113 -0.082 -0.035 0.036 0.032 -0.092 -0.141 -0.222 -0.277 -0.395
33 -0.153 -0.118 -0.047 0.008 0.014 -0.164 -0.231 -0.310 -0.346 -0.444
44 -0.013 0.028 0.098 0.154 0.175 0.111 -0.055 -0.206 -0.246 -0.268
55 0.224 0.254 0.295 0.347 0.362 0.279 0.207 0.119 0.032 0.042
66 -0.253 -0.222 -0.190 -0.162 -0.194 -0.265 -0.322 -0.386 -0.386 -0.411
77 -0.406 -0.388 -0.369 -0.370 -0.367 -0.389 -0.408 -0.475 -0.516 -0.510
88 -0.454 -0.450 -0.461 -0.453 -0.397 -0.374 -0.426 -0.487 -0.512 -0.490
99 -0.627 -0.638 -0.597 -0.590 -0.587 -0.566 -0.566 -0.595 -0.626 -0.621
TT -0.847 -0.846 -0.846 -0.846 -0.845 -0.843 -0.843 -0.842 -0.840 -0.882

Pairs Chart - Player Expected Gains per original unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA -0.019 0.055 0.137 0.216 0.248 -0.137 -0.296 -0.421 -0.468 -0.591
22 -0.582 -0.501 -0.384 -0.214 -0.249 -0.942 -1.030 -1.047 -1.094 -1.320
33 -0.567 -0.472 -0.302 -0.184 -0.215 -0.871 -1.000 -1.065 -1.072 -1.298
44 -0.185 -0.082 0.044 0.162 0.193 -0.108 -0.447 -0.701 -0.741 -0.802
55 0.446 0.510 0.590 0.695 0.724 0.466 0.323 0.175 0.014 0.042
66 -0.505 -0.444 -0.380 -0.325 -0.387 -0.599 -0.711 -0.817 -0.803 -0.823
77 -0.813 -0.777 -0.738 -0.741 -0.734 -0.823 -0.858 -0.978 -1.035 -1.019
88 -0.908 -0.900 -0.922 -0.906 -0.793 -0.747 -0.853 -0.974 -1.024 -0.980
99 -1.255 -1.277 -1.194 -1.181 -1.173 -1.132 -1.133 -1.189 -1.252 -1.242
TT -1.693 -1.693 -1.693 -1.691 -1.690 -1.686 -1.685 -1.684 -1.681 -1.764

Pairs Chart - Player Expected Gains per original unit (Split)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA 1.192 1.223 1.265 1.321 1.344 1.308 1.201 1.039 0.860 0.921
22 -0.128 -0.070 -0.007 0.128 0.126 -0.054 -0.213 -0.383 -0.463 -0.566
33 -0.202 -0.128 0.009 0.117 0.112 -0.115 -0.265 -0.418 -0.509 -0.579
44 -0.236 -0.127 -0.013 0.095 0.083 -0.223 -0.343 -0.493 -0.580 -0.623
55 -0.232 -0.150 -0.038 0.068 0.056 -0.299 -0.448 -0.608 -0.685 -0.695
66 -0.219 -0.135 -0.028 0.068 -0.011 -0.270 -0.413 -0.570 -0.652 -0.660
77 -0.163 -0.084 0.016 0.039 0.053 -0.123 -0.423 -0.564 -0.634 -0.635
88 0.017 0.077 0.106 0.188 0.234 0.202 -0.100 -0.430 -0.464 -0.378
99 0.170 0.170 0.253 0.339 0.359 0.341 0.179 -0.112 -0.268 -0.109
TT 0.412 0.465 0.518 0.596 0.619 0.576 0.447 0.276 0.146 0.140

Pairs Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA P P P P P P P P P P
22 H P P P P P H H H H
33 H H P P P P H H H H
44 H H H D D H H H H H
55 D D D D D D D D H D
66 P P P P P H H H H H
77 P P P P P P H H S H
88 P P P P P P P P P P
99 P P P P P S P P S S
TT S S S S S S S S S S

Simulation for Year 1:

After playing 50 times a day for 365 days:
Winning days :186
Losing days :171
Breakeven days :8
Biggest win :25.00
Biggest loss :26.00
Total win :211.00
Total staked :20546.00
Win % staked : 1.027

Simulation for Year 2:

After playing 50 times a day for 365 days:
Winning days :174
Losing days :181
Breakeven days :10
Biggest win :25.50
Biggest loss :22.50
Total loss :213.00
Total staked :20536.00
Loss % staked : 1.037

Simulation for Year 3:

After playing 50 times a day for 365 days:
Winning days :174
Losing days :182
Breakeven days :9
Biggest win :23.00
Biggest loss :26.50
Total loss :204.50
Total staked :20542.00
Loss % staked : 0.996

Simulation for Year 4:

After playing 50 times a day for 365 days:
Winning days :181
Losing days :176
Breakeven days :8
Biggest win :25.50
Biggest loss :22.00
Total win :122.50
Total staked :20555.00
Win % staked : 0.596

Simulation for Year 5:

After playing 50 times a day for 365 days:
Winning days :164
Losing days :187
Breakeven days :14
Biggest win :25.50
Biggest loss :21.50
Total loss :87.00
Total staked :20566.00
Loss % staked : 0.423

Simulation for Year 6:

After playing 50 times a day for 365 days:
Winning days :180
Losing days :175
Breakeven days :10
Biggest win :22.50
Biggest loss :26.00
Total win :23.50
Total staked :20524.00
Win % staked : 0.115

Simulation for Year 7:

After playing 50 times a day for 365 days:
Winning days :175
Losing days :181
Breakeven days :9
Biggest win :21.50
Biggest loss :19.00
Total win :15.00
Total staked :20552.00
Win % staked : 0.073

Simulation for Year 8:

After playing 50 times a day for 365 days:
Winning days :185
Losing days :173
Breakeven days :7
Biggest win :20.00
Biggest loss :22.00
Total win :80.00
Total staked :20623.00
Win % staked : 0.388

Simulation for Year 9:

After playing 50 times a day for 365 days:
Winning days :172
Losing days :180
Breakeven days :13
Biggest win :20.50
Biggest loss :19.00
Total loss :1.50
Total staked :20589.00
Loss % staked : 0.007

Simulation for Year 10:

After playing 50 times a day for 365 days:
Winning days :172
Losing days :186
Breakeven days :7
Biggest win :24.50
Biggest loss :25.50
Total loss :15.00
Total staked :20436.00
Loss % staked : 0.073
</pre>
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-array}}
{{libheader|Wren-dynamic}}
{{libheader|Wren-fmt}}
{{libheader|Wren-iterate}}
<br>
This runs OK but takes a long time to do so - 6 minutes 21 seconds compared to less than 3 seconds for the Go example. As I also wrote the latter I'm confident it's a faithful translation.

The bottleneck seems to be the ''dealerProbs'' method which is called around 300,000 times during the course of the program and contains several arrays (heap allocated in Wren) plus a recursive closure and so is not cheap to run. Making the arrays global and resetting them each time the method is called doesn't help and memoization is out of the question as there are just too many parameter combinations.

So interpreted languages such as Wren are probably stuck with slow times for this task.
<syntaxhighlight lang="wren">import "random" for Random
import "./array" for Array, ArrayType
import "./dynamic" for Struct
import "./fmt" for Fmt
import "./iterate" for Indexed

var Rand = Random.new()

// 0: deck size, 1 to 10: number of cards of that denomination
var Deck = ArrayType.create("Deck", 11, 0)

var ActionGain = Struct.create("ActionGain", ["action", "gain"])

var NewDeck = Fn.new { Deck.fit([52, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16]) }

// Computed strategy tables
var HTable = List.filled(15, null) // hard strategy table (round 1)
var STable = List.filled( 8, null) // soft strategy table (round 1)
var PTable = List.filled(10, null) // pairs strategy table (round 1)
var HTable2 = List.filled(18, null) // hard strategy table (round >= 2, no doubling)
var STable2 = List.filled(10, null) // soft strategy table (round >= 2, no doubling)

for (i in 0..14) HTable[i] = List.filled(10, null)
for (i in 0..7) STable[i] = List.filled(10, null)
for (i in 0..9) PTable[i] = List.filled(10, null)
for (i in 0..17) HTable2[i] = List.filled(10, null)
for (i in 0..9) STable2[i] = List.filled(10, null)

class Blackjack {
// Returns probabilities of dealer eventually getting:
// 0: 17, 1: 18, 2: 19, 3: 20, 4: 21 (non-blackjack), 5: blackjack (nil), 6: bust.
// It is assumed that the dealer has already checked for blackjack, that one deck is used
// and that the dealer stands on 'soft' 17.
static dealerProbs(upCard, startDeck) {
var res = List.filled(7, 0) // results
var decks = List.filled(9, null) // decks for each level
var scores = List.filled(9, 0) // scores for each level
var elevens = List.filled(9, 0) // number of aces for each level scored as 11
var probs = List.filled(9, 0) // probs for each level
decks[0] = startDeck.toList
scores[0] = upCard
if (upCard == 1) { // an ace
scores[0] = 11
elevens[0] = 1
}
probs[0] = 1
var f // recursive closure
f = Fn.new { |lev|
for (c in 1..10) {
if (decks[lev][c] == 0) continue // card no longer present in deck
// temporary variables for current level
var deck = decks[lev].toList
var score = scores[lev]
var eleven = elevens[lev]
var prob = probs[lev]
score = score + c // add card to score
if (c == 1) { // score all aces initially as 11
score = score + 10
eleven = eleven + 1
}
prob = prob * deck[c] / deck[0]
if (score > 21 && eleven > 0) {
score = score - 10 // bust but can demote an ace
eleven = eleven - 1
}
if (lev == 0 && ((upCard == 1 && c == 10) || (upCard == 10 && c == 1))) {
res[5] = res[5] + prob // blackjack, allow for now
} else if (score >= 17 && score <= 21) {
res[score-17] = res[score-17] + prob // 17 to (non-blackjack) 21
} else if (score > 21 && eleven == 0) {
res[6] = res[6] + prob // bust
} else {
deck[c] = deck[c] - 1 // remove card from deck
deck[0] = deck[0] - 1 // decrement deck size
var lev2 = lev + 1
decks[lev2] = deck
scores[lev2] = score
elevens[lev2] = eleven
probs[lev2] = prob
f.call(lev2) // get another card
}
}
}
f.call(0)
// but can't have blackjack, so adjust probabilities accordingly
var pnbj = 1 - res[5]
for (i in 0..6) res[i] = res[i] / pnbj
res[5] = 0
return res
}

// Prints chart of dealer probabilities (as a check against an external source).
static dealerChart() {
System.print("Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules")
System.print("Up Card 17 18 19 20 21 Bust")
System.print("-------------------------------------------------------------------")
var deck = NewDeck.call()
deck[0] = 51
for (uc in 1..10) {
var deck2 = deck.toList
deck2[uc] = deck2[uc] - 1
var dp = dealerProbs(uc, deck2)
if (uc > 1) {
Fmt.write("$3d ", uc)
} else {
System.write("Ace ")
}
Fmt.lprint("$f $f $f $f $f $f", [dp[0], dp[1], dp[2], dp[3], dp[4], dp[6]])
}
}

// Returns player's expected gain per unit staked after hitting once and then standing.
static playerGain(card1, card2, uc, startDeck) {
var eg = 0
var deck = startDeck.toList
var score = card1 + card2
var eleven = false
if (card1 == 1 || card2 == 1) { // an ace
score = score + 10
eleven = true
}
for (c in 1..10) { // get another card
if (deck[c] == 0) continue // card no longer present in deck
// temporary variables for current card
var deck2 = deck.toList
var score2 = score
var eleven2 = eleven
score2 = score2 + c // add card to score
if (c == 1) { // score all aces initially as 11
score2 = score2 + 10
eleven2 = true
}
var prob = deck2[c] / deck2[0]
deck2[c] = deck2[c] - 1 // remove card from deck
deck2[0] = deck2[0] - 1 // decrement deck size
if (score2 > 21 && eleven2) {
score2 = score2 - 10 // bust but can demote an ace
}
if (score2 <= 21) {
var dp = dealerProbs(uc, deck2)
eg = eg + calcGain(score2, dp) * prob
} else { // bust
eg = eg - prob
}
}
return eg
}

// Returns player's expected gain per unit staked after hitting once and then continuing
// in accordance with the tables for rounds >= 2.
static playerGain2(card1, card2, uc, startDeck) {
var eg = 0 // result
var decks = List.filled(9, null) // decks for each level
var scores = List.filled(9, 0) // scores for each level
var elevens = List.filled(9, 0) // number of aces for each level scored as 11
var probs = List.filled(9, 0) // probs for each level
decks[0] = startDeck.toList
scores[0] = card1 + card2
if (card1 == 1 || card2 == 1) { // an ace
scores[0] = scores[0] + 10
elevens[0] = 1
}
probs[0] = 1
var f // recursive closure
f = Fn.new { |lev|
for (c in 1..10) {
if (decks[lev][c] == 0) continue // card no longer present in deck
// temporary variables for current level
var deck = decks[lev].toList
var score = scores[lev]
var eleven = elevens[lev]
var prob = probs[lev]
score = score + c // add card to score
if (c == 1) { // score all aces initially as 11
score = score + 10
eleven = eleven + 1
}
prob = prob * deck[c] / deck[0]
if (score > 21 && eleven > 0) {
score = score - 10 // bust but can demote an ace
eleven = eleven - 1
}
deck[c] = deck[c] - 1 // remove card from deck
deck[0] = deck[0] - 1 // decrement deck size
if ((eleven == 0 && (score >= 17 || (score >= 13 && uc < 7)) ||
(eleven == 0 && score == 12 && uc >= 4 && uc <= 6) ||
(eleven > 0 && score == 18 && uc != 9 && uc != 10) ||
(eleven > 0 && score >= 19)) && score <= 21) {
var dp = dealerProbs(uc, deck)
eg = eg + calcGain(score, dp) * prob
} else if (score > 21 && eleven == 0) { // bust
eg = eg - prob
} else {
var lev2 = lev + 1
decks[lev2] = deck
scores[lev2] = score
elevens[lev2] = eleven
probs[lev2] = prob
f.call(lev2) // get another card
}
}
}
f.call(0)
return eg
}

// Calculates gain per unit staked for a given scenario (helper function).
static calcGain(pscore, dp) {
var eg = 0
if (pscore == 17) {
eg = eg + dp[6] // dealer is bust
eg = eg - dp[1] - dp[2] - dp[3] - dp[4] // dealer has 18 to 21
} else if (pscore == 18) {
eg = eg + dp[0] + dp[6] // dealer has 17 or is bust
eg = eg - dp[2] - dp[3] - dp[4] // dealer has 19 to 21
} else if (pscore == 19) {
eg = eg + dp[0] + dp[1] + dp[6] // dealer has 17, 18 or is bust
eg = eg - dp[3] - dp[4] // dealer has 20 or 21
} else if (pscore == 20) {
eg = eg + dp[0] + dp[1] + dp[2] + dp[6] // dealer has 17 to 19 or is bust
eg = eg - dp[4] // dealer has (non-blackjack) 21
} else if (pscore == 21) {
eg = eg + dp[0] + dp[1] + dp[2] + dp[3] + dp[6] // dealer has 17 to 20 or is bust
} else if (pscore == 22) { // notional
eg = eg + 1.5 // player blackjack
} else if (pscore == 23) { // notional
eg = eg - 1 // player bust, loses stake irrespective of what dealer has
} else { // player has less than 17
eg = eg + dp[6] // dealer is bust
eg = eg - (1 - dp[6]) // dealer isn't bust
}
return eg
}

// Returns player's expected gains per unit staked, for each dealer up-card, after standing.
static stand(card1, card2) {
var deck = NewDeck.call()
deck[card1] = deck[card1] - 1
deck[card2] = deck[card2] - 1
deck[0] = 50
var pscore = card1 + card2 // player score
if (card1 == 1 || card2 == 1) pscore = pscore + 10
var egs = List.filled(10, 0) // results
for (uc in 1..10) { // dealer's up-card
var deck2 = deck.toList
deck2[uc] = deck2[uc] - 1
deck2[0] = deck2[0] - 1
var dp = dealerProbs(uc, deck2)
var eg = calcGain(pscore, dp) // expected gain for this up-card
if (uc > 1) {
egs[uc-2] = eg
} else { // dealer has Ace
egs[9] = eg // ace comes last in tables
}
}
return egs
}

// Returns player's expected gains per unit staked, for each dealer up-card, after
// hitting once and then either standing (once == true) or continuing
// as per the round >= 2 tables (once == false).
static hit(card1, card2, once) {
var deck = NewDeck.call()
deck[card1] = deck[card1] - 1
deck[card2] = deck[card2] - 1
deck[0] = 50
var egs = List.filled(10, 0) // results
for (uc in 1..10) { // dealer's up-card
var deck2 = deck.toList
deck2[uc] = deck2[uc] - 1
deck2[0] = 49
var peg = once ? playerGain (card1, card2, uc, deck2) :
playerGain2(card1, card2, uc, deck2)
if (uc > 1) {
egs[uc-2] = peg
} else { // dealer has Ace
egs[9] = peg
}
}
return egs
}

// Returns player's expected gains per unit oiginally staked, for each dealer up-card,
// after doubling i.e. hitting once and then standing with a doubled stake.
static double(card1, card2) {
var egs = hit(card1, card2, true) // hit once and then stand
for (i in 0..9) egs[i] = egs[i] * 2
return egs
}

// Returns player's expected gains per unit originally staked, for each dealer up-card,
// after splitting a pair and doubling the stake, getting a second card for each hand
// and then continuing in accordance with the rounds >= 2 tables. It is assumed that a
// player cannot double or re-split following a split. It is also assumed
// (in the interests of simplicity) that the expected gains for each split hand (after
// calculating the gains for the first hand as though the second hand is not completed)
// are exactly the same.
static split(card) {
var deck = NewDeck.call()
deck[card] = deck[card] - 2 // must be a pair
deck[0] = 50
var egs = List.filled(10, 0) // overall results

// now play a single hand
var score = card
var eleven = 0
if (card == 1) { // an ace
score = 11
eleven = 1
}
for (uc in 1..10) { // collect results for each dealer up-card
if (deck[uc] == 0) continue // card no longer present in deck
var deck2 = deck.toList
deck2[uc] = deck2[uc] - 1
deck2[0] = deck2[0] - 1
var ix = uc - 2
if (ix == -1) ix = 9 // in tables ace comes last
var peg = 0 // player expected gain for this up-card
// get second player card
for (c in 1..10) {
if (deck2[c] == 0) continue // card no longer present in deck
var prob = deck2[c] / deck2[0]
var deck3 = deck2.toList
deck3[c] = deck3[c] - 1
deck3[0] = deck3[0] - 1
var score2 = score + c
var eleven2 = eleven
if (c == 1) { // score all aces initially as 11
score2 = score2 + 10
eleven2 = eleven2 + 1
}
if (score2 == 21) { // player has blackjack & we know dealer hasn't
peg = peg + 1.5 * prob
continue
}
if (score2 > 21 && eleven2 > 0) {
score2 = score2 - 10 // bust but can demote an ace
eleven2 = eleven2 - 1
}
var action
if (eleven2 > 0) {
action = STable2[score2-12][ix] // use soft strategy table, no doubling
} else { // including pairs as no re-splitting
action = HTable2[score2-4][ix] // use hard strategy table, no doubling
}
var peg2
if (action == "S") {
var dp = dealerProbs(uc, deck3)
peg2 = calcGain(score2, dp)
} else {
peg2 = playerGain2(card, c, uc, deck3)
}
peg = peg + peg2 * prob
}
if (uc > 1) {
egs[uc-2] = peg * 2 // allow for both hands in overall results
} else {
egs[9] = peg * 2 // ditto
}
}
return egs
}

// Returns the action with the highest expected gain.
static bestAction(ags) {
var max = ags[0].gain
var maxi = 0
for (i in 1...ags.count) {
if (ags[i].gain > max) {
max = ags[i].gain
maxi = i
}
}
return ags[maxi].action
}

// Prints title and header for a given chart.
static printHeader(title) {
System.print(title)
System.print("P/D 2 3 4 5 6 7 8 9 T A")
System.print("--------------------------------------------------------------------------")
}

// Prints header for a pair of cards.
static printPair(c) {
if (c == 1) {
System.write("AA ")
} else if (c == 10) {
System.write("TT ")
} else {
Fmt.write("$d$d ", c, c)
}
}

// Simulates 'perDay' blackjack games for 'days' days.
static simulate(perDay, days) {
var winDays = 0
var loseDays = 0
var evenDays = 0
var bigWin = 0
var bigLoss = 0
var totGain = 0
var totStake = 0
for (d in 1..days) {
var dailyGain = 0
var dailyStake = 0
for (p in 1..perDay) {
var gs = playerPlay()
dailyGain = dailyGain + gs[0]
dailyStake = dailyStake + gs[1]
}
if (dailyGain > 0) {
winDays = winDays + 1
} else if (dailyGain < 0) {
loseDays = loseDays + 1
} else {
evenDays = evenDays + 1
}
if (dailyGain > bigWin) {
bigWin = dailyGain
} else if (-dailyGain > bigLoss) {
bigLoss = -dailyGain
}
totGain = totGain + dailyGain
totStake = totStake + dailyStake
}
Fmt.print("\nAfter playing $d times a day for $d days:", perDay, days)
Fmt.print("Winning days : $d", winDays)
Fmt.print("Losing days : $d", loseDays)
Fmt.print("Breakeven days : $d", evenDays)
Fmt.print("Biggest win : $h", bigWin)
Fmt.print("Biggest loss : $h", bigLoss)
if (totGain < 0) {
Fmt.print("Total loss : $h", -totGain)
Fmt.print("Total staked : $h", totStake)
Fmt.print("Loss \% staked : $0.3f", -totGain/totStake*100)
} else {
Fmt.print("Total win : $h", totGain)
Fmt.print("Total staked : $h", totStake)
Fmt.print("Win \% staked : $0.3f", totGain/totStake*100)
}
}

// Simulates a dealer's play for a given player's hand and state of deck.
// Returns the player's gain (positive or negative) per unit staked.
static dealerPlay(pscore, next, cards, d) {
var dscore = d[0] + d[1]
var aces = 0
if (d[0] == 1 || d[1] == 1) { // dealer has an ace
dscore = dscore + 10
aces = aces + 1
}
while (true) {
if (dscore > 21 && aces > 0) {
dscore = dscore - 10 // bust but we can demote an ace
aces = aces - 1
}
if (dscore > 21) {
return [1, next] // dealer is bust and player gains stake
}
if (dscore >= 17) { // dealer must stick on 17 or above, hard or not
if (dscore > pscore) {
return [-1, next] // dealer wins and player loses stake
} else if (dscore == pscore) {
break // player breaks even
} else {
return [1, next] // dealer loses and player gains stake
}
}
var nc = cards[next] // get new card from pack
next = next + 1
dscore = dscore + nc
if (nc == 1) { // count aces initially as 11
dscore = dscore + 10
aces = aces + 1
}
}
return [0, next]
}

// Simulates the playing of a random player's hand according to the strategy tables.
// Returns both the gain (positive or negative) and the stake (1 or 2).
static playerPlay() {
var perm = (0..51).toList
Rand.shuffle(perm) // randomizes integers from 0 to 51 inclusive
var cards = List.filled(52, 0)
for (se in Indexed.new(perm)) {
var card = (se.value/4).floor + 1
if (card > 10) card = 10
cards[se.index] = card
}
var p = [] // player hand
var d = [] // dealer hand
// initial deal
for (se in Indexed.new(cards[0..3])) {
if (se.index < 2) {
p.add(se.value)
} else {
d.add(se.value)
}
}
var next = 4 // index of next card to be dealt

// check if dealer and/or player have blackjack
var dbj = (d[0] == 1 && d[1] == 10) || (d[0] == 10 && d[1] == 1)
var pbj = (p[0] == 1 && p[1] == 10) || (p[0] == 10 && p[1] == 1)
if (dbj) {
if (pbj) return [0, 1] // player neither wins nor loses
return [-1, 1] // player loses stake
}
if (pbj) return [1.5, 1] // player wins 1.5 x stake
var uc = d[0] // dealer's up-card for accessing tables
if (uc == 0) {
uc = 9 // move ace to last place
} else {
uc = uc - 1 // move others down 1
}
var stake = 1 // player's initial stake
var fscores = List.filled(2, 0) // final player scores (one or, after split, two hands)
var action = ""
var score = 0
var aces = 0

var h = Fn.new { |hand| // processes a 'hit'
while (true) {
var nc = cards[next] // get new card from pack
next = next + 1
score = score + nc
if (nc == 1) { // count aces initially as 11
score = score + 10
aces= aces + 1
}
if (score > 21 && aces > 0) {
score = score - 10 // bust but we can demote an ace
aces = aces - 1
}
if (score > 21) {
fscores[hand] = 22 // player is bust and loses stake
return
}
if (action == "D") {
fscores[hand] = score
return
}
// get further strategy and act accordingly
if (aces == 0) {
action = HTable2[score-4][uc]
} else {
action = STable2[score-12][uc]
}
if (action == "S") { // stand
fscores[hand] = score
return
}
}
}

score = p[0] + p[1]
// get kind of player hand: hard, soft, pair
var kind
if (p[0] == p[1]) {
kind = "pair"
} else if (p[0] == 1 || p[1] == 1) {
kind = "soft"
} else {
kind = "hard"
}
if (kind == "hard") {
action = HTable[score-5][uc]
} else if (kind == "soft") { // includes one ace
var otherCard = p[0]
if (otherCard == 1) otherCard = p[1]
score = score + 10
aces = 1
action = STable[otherCard-2][uc]
} else if (kind == "pair") {
if (p[0] == 1) { // pair of aces
score = score + 10
aces = 2
}
action = PTable[p[0]-1][uc]
}
if (action == "S") { // stand
fscores[0] = score
} else if (action == "H") { // hit
h.call(0)
} else if (action == "D") { // double
h.call(0)
stake = 2
} else if (action == "P") { // split
for (hand in 0..1) {
score = p[0]
aces = 0
if (score == 1) { // count aces initially as 11
score = 11
aces = aces + 1
}
h.call(hand)
}
}
var sum = 0
if (fscores[0] < 22) {
var res = dealerPlay(fscores[0], next, cards, d)
sum = sum + res[0] * stake
next = res[1]
} else {
sum = sum - stake // this hand is bust
}
if (fscores[1] > 0) { // pair
if (fscores[1] < 22) {
var res = dealerPlay(fscores[1], next, cards, d)
sum = sum + res[0]
next = res[1]
} else {
sum = sum - 1 // this hand is bust
}
stake = 2
}
return [sum, stake]
}

static main() {
// print dealer probabilities chart
dealerChart()

// for hard scores (i.e. different cards, no aces)
var tuples = [
[2, 3],
[2, 4],
[2, 5], [3, 4],
[2, 6], [3, 5],
[2, 7], [3, 6], [4, 5],
[2, 8], [3, 7], [4, 6],
[2, 9], [3, 8], [4, 7], [5, 6],
[2, 10], [3, 9], [4, 8], [5, 7],
[3, 10], [4, 9], [5, 8], [6, 7],
[4, 10], [5, 9], [6, 8],
[5, 10], [6, 9], [7, 8],
[6, 10], [7, 9],
[7, 10], [8, 9],
[8, 10],
[9, 10]
]

// number of tuples for each player score from 5 to 19
var counts = Array.from([1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1])
// expected gains for each player score & for each dealer up-card
var segs = List.filled(15, null) // if stands
var hegs = List.filled(15, null) // if hits
var degs = List.filled(15, null) // if doubles
for (i in 0..14) {
segs[i] = List.filled(10, 0)
hegs[i] = List.filled(10, 0)
degs[i] = List.filled(10, 0)
}
for (tuple in tuples) {
var i = tuple[0] + tuple[1]
var sg = stand(tuple[0], tuple[1])
var hg = hit(tuple[0], tuple[1], false)
var dg = double(tuple[0], tuple[1])
for (j in 0..9) {
segs[i-5][j] = segs[i-5][j] + sg[j]
hegs[i-5][j] = hegs[i-5][j] + hg[j]
degs[i-5][j] = degs[i-5][j] + dg[j]
}
}

// calculate the average per tuple for each score
for (i in 0..14) {
for (j in 0..9) {
segs[i][j] = segs[i][j] / counts[i]
hegs[i][j] = hegs[i][j] / counts[i]
degs[i][j] = degs[i][j] / counts[i]
}
}

printHeader("\nHard Chart - Player Expected Gains per unit (Stand)")
for (i in 5..19) {
Fmt.write("$2d ", i)
for (j in 0..9) Fmt.write("$6.3f ", segs[i-5][j])
System.print()
}

printHeader("\nHard Chart - Player Expected Gains per unit (Hit)")
for (i in 5..19) {
Fmt.write("$2d ", i)
for (j in 0..9) Fmt.write("$6.3f ", hegs[i-5][j])
System.print()
}

printHeader("\nHard Chart - Player Expected Gains per original unit (Double)")
for (i in 5..19) {
Fmt.write("$2d ", i)
for (j in 0..9) Fmt.write("$6.3f ", degs[i-5][j])
System.print()
}

printHeader("\nHard Chart - Player Strategy (Round 1)")
for (i in 5..19) {
Fmt.write("$2d ", i)
for (j in 0..9) {
var ags = [
ActionGain.new("S", segs[i-5][j]),
ActionGain.new("H", hegs[i-5][j]),
ActionGain.new("D", degs[i-5][j])
]
var action = bestAction(ags)
HTable[i-5][j] = action
Fmt.write("$4s ", action)
}
System.print()
}

// for hard scores (no aces) - after round 1 (no doubling or splitting)
// based on hard table figures (round 1) with scores of 4, 20, and 21 added
var segs2 = List.filled(18, null) // expected gains if stands
var hegs2 = List.filled(18, null) // expected gains if hits
for (i in 0..17) {
segs2[i] = List.filled(10, 0)
hegs2[i] = List.filled(10, 0)
}
for (i in 5..19) {
segs2[i-4] = segs[i-5]
hegs2[i-4] = hegs[i-5]
}
var sg4 = stand(2, 2)
var hg4 = hit(2, 2, false)
var sg20 = stand(10, 10)
var hg20 = hit(10, 10, false)
var sg21 = stand(1, 10)
var hg21 = hit(1, 10, false)
for (j in 0..9) {
segs2[0][j] = segs2[0][j] + sg4[j]
hegs2[0][j] = hegs2[0][j] + hg4[j]
segs2[16][j] = segs2[16][j] + sg20[j]
hegs2[16][j] = hegs2[16][j] + hg20[j]
segs2[17][j] = segs2[17][j] + sg21[j]
hegs2[17][j] = hegs2[17][j] + hg21[j]
}

printHeader("\nHard Chart - Player Strategy (Round >= 2, No Doubling)")
for (i in 4..21) {
Fmt.write("$2d ", i)
for (j in 0..9) {
var action = "S"
if (hegs2[i-4][j] > segs2[i-4][j]) action = "H"
HTable2[i-4][j] = action
Fmt.write("$4s ", action)
}
System.print()
}

/* for soft scores (i.e. including exactly one ace) */

// expected gains for each player second card (2 to 9) & for each dealer up-card
var segs3 = List.filled(8, null) // if stands
var hegs3 = List.filled(8, null) // if hits
var degs3 = List.filled(8, null) // if doubles
for (i in 0..7) {
segs3[i] = List.filled(10, 0)
hegs3[i] = List.filled(10, 0)
degs3[i] = List.filled(10, 0)
}
for (c in 2..9) {
var sg = stand(1, c)
var hg = hit(1, c, false)
var dg = double(1, c)
for (j in 0..9) {
segs3[c-2][j] = segs3[c-2][j] + sg[j]
hegs3[c-2][j] = hegs3[c-2][j] + hg[j]
degs3[c-2][j] = degs3[c-2][j] + dg[j]
}
}

printHeader("\nSoft Chart - Player Expected Gains per unit (Stand)")
for (c in 2..9) {
Fmt.write("A$d ", c)
for (j in 0..9) Fmt.write("$6.3f ", segs3[c-2][j])
System.print()
}

printHeader("\nSoft Chart - Player Expected Gains per unit (Hit)")
for (c in 2..9) {
Fmt.write("A$d ", c)
for (j in 0..9) Fmt.write("$6.3f ", hegs3[c-2][j])
System.print()
}

printHeader("\nSoft Chart - Player Expected Gains per unit (Double)")
for (c in 2..9) {
Fmt.write("A$d ", c)
for (j in 0..9) Fmt.write("$6.3f ", degs3[c-2][j])
System.print()
}

printHeader("\nSoft Chart - Player Strategy (Round 1)")
for (c in 2..9) {
Fmt.write("A$d ", c)
for (j in 0..9) {
var ags = [
ActionGain.new("S", segs3[c-2][j]),
ActionGain.new("H", hegs3[c-2][j]),
ActionGain.new("D", degs3[c-2][j])
]
var action = bestAction(ags)
STable[c-2][j] = action
Fmt.write("$4s ", action)
}
System.print()
}

// for soft scores (at least one ace) - after round 1 (no doubling or splitting)
// based on soft table figures (round 1) with scores of 12 and 21 added
// assumes one ace counted as 11
var segs4 = List.filled(10, null) // expected gains if stands
var hegs4 = List.filled(10, null) // expected gains if hits
for (i in 0..9) {
segs4[i] = List.filled(10, 0)
hegs4[i] = List.filled(10, 0)
}
for (i in 1..8) {
segs4[i] = segs3[i-1]
hegs4[i] = hegs3[i-1]
}
var sg12 = stand(1, 1)
var hg12 = hit(1, 1, false)
for (j in 0..9) {
segs4[0][j] = segs4[0][j] + sg12[j]
hegs4[0][j] = hegs4[0][j] + hg12[j]
segs4[9][j] = segs4[9][j] + sg21[j]
hegs4[9][j] = hegs4[9][j] + hg21[j]
}

printHeader("\nSoft Chart - Player Strategy (Round >= 2, No Doubling)")
for (i in 12..21) {
Fmt.write("$2d ", i)
for (j in 0..9) {
var action = "S"
if (hegs4[i-12][j] > segs4[i-12][j]) action = "H"
STable2[i-12][j] = action
Fmt.write("$4s ", action)
}
System.print()
}

/* for pairs */

// expected gains for each pair (A to 10) & for each dealer up-card
var segs5 = List.filled(10, null) // if stands
var hegs5 = List.filled(10, null) // if hits
var degs5 = List.filled(10, null) // if doubles
var pegs5 = List.filled(10, null) // if splits
for (i in 0..9) {
segs5[i] = List.filled(10, 0)
hegs5[i] = List.filled(10, 0)
degs5[i] = List.filled(10, 0)
pegs5[i] = List.filled(10, 0)
}
for (c in 1..10) {
var sg = stand(c, c)
var hg = hit(c, c, false)
var dg = double(c, c)
var pg = split(c)
for (j in 0..9) {
segs5[c-1][j] = segs5[c-1][j] + sg[j]
hegs5[c-1][j] = hegs5[c-1][j] + hg[j]
degs5[c-1][j] = degs5[c-1][j] + dg[j]
pegs5[c-1][j] = pegs5[c-1][j] + pg[j]
}
}

printHeader("\nPairs Chart - Player Expected Gains per unit (Stand)")
for (c in 1..10) {
printPair(c)
for (j in 0..9) Fmt.write("$6.3f ", segs5[c-1][j])
System.print()
}

printHeader("\nPairs Chart - Player Expected Gains per unit (Hit)")
for (c in 1..10) {
printPair(c)
for (j in 0..9) Fmt.write("$6.3f ", hegs5[c-1][j])
System.print()
}

printHeader("\nPairs Chart - Player Expected Gains per unit (Double)")
for (c in 1..10) {
printPair(c)
for (j in 0..9) Fmt.write("$6.3f ", degs5[c-1][j])
System.print()
}

printHeader("\nPairs Chart - Player Expected Gains per unit (Split)")
for (c in 1..10) {
printPair(c)
for (j in 0..9) Fmt.write("$6.3f ", pegs5[c-1][j])
System.print()
}

printHeader("\nPairs Chart - Player Strategy (Round 1)")
for (c in 1..10) {
printPair(c)
for (j in 0..9) {
var ags = [
ActionGain.new("S", segs5[c-1][j]),
ActionGain.new("H", hegs5[c-1][j]),
ActionGain.new("D", degs5[c-1][j]),
ActionGain.new("P", pegs5[c-1][j]),
]
var action = bestAction(ags)
PTable[c-1][j] = action
Fmt.write("$4s ", action)
}
System.print()
}

// do 10 years of simulations
for (i in 1..10) {
Fmt.print("\nSimulation for Year $d:", i)
simulate(50, 365)
}
}
}

Blackjack.main()</syntaxhighlight>

{{out}}
<pre>
Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules
Up Card 17 18 19 20 21 Bust
-------------------------------------------------------------------
Ace 0.183786 0.190890 0.188680 0.191692 0.075137 0.169815
2 0.138976 0.131762 0.131815 0.123948 0.120526 0.352973
3 0.130313 0.130946 0.123761 0.123345 0.116047 0.375588
4 0.130973 0.114163 0.120679 0.116286 0.115096 0.402803
5 0.119687 0.123483 0.116909 0.104694 0.106321 0.428905
6 0.166948 0.106454 0.107192 0.100705 0.097878 0.420823
7 0.372345 0.138583 0.077334 0.078897 0.072987 0.259854
8 0.130857 0.362989 0.129445 0.068290 0.069791 0.238627
9 0.121886 0.103921 0.357391 0.122250 0.061109 0.233442
10 0.124156 0.122486 0.124421 0.356869 0.039570 0.232499

Hard Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.293 -0.248 -0.176 -0.104 -0.122 -0.469 -0.513 -0.533 -0.546 -0.659
6 -0.291 -0.232 -0.172 -0.101 -0.119 -0.467 -0.522 -0.533 -0.547 -0.659
7 -0.283 -0.229 -0.163 -0.098 -0.117 -0.471 -0.521 -0.537 -0.547 -0.658
8 -0.276 -0.229 -0.162 -0.100 -0.130 -0.478 -0.523 -0.539 -0.549 -0.648
9 -0.277 -0.224 -0.160 -0.108 -0.134 -0.480 -0.528 -0.543 -0.542 -0.646
10 -0.279 -0.227 -0.172 -0.120 -0.146 -0.484 -0.531 -0.539 -0.537 -0.644
11 -0.277 -0.231 -0.175 -0.123 -0.147 -0.488 -0.529 -0.537 -0.537 -0.646
12 -0.286 -0.241 -0.185 -0.134 -0.151 -0.485 -0.526 -0.535 -0.533 -0.655
13 -0.282 -0.236 -0.181 -0.133 -0.156 -0.488 -0.529 -0.537 -0.534 -0.649
14 -0.282 -0.238 -0.188 -0.134 -0.159 -0.489 -0.529 -0.533 -0.536 -0.651
15 -0.280 -0.239 -0.190 -0.144 -0.169 -0.494 -0.531 -0.536 -0.531 -0.648
16 -0.287 -0.250 -0.194 -0.152 -0.179 -0.495 -0.526 -0.540 -0.530 -0.648
17 -0.147 -0.120 -0.074 -0.044 -0.011 -0.122 -0.405 -0.414 -0.402 -0.459
18 0.119 0.144 0.164 0.202 0.268 0.389 0.096 -0.196 -0.155 -0.082
19 0.385 0.384 0.404 0.448 0.484 0.610 0.577 0.264 0.103 0.308

Hard Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.131 -0.098 -0.041 0.022 0.019 -0.119 -0.181 -0.262 -0.309 -0.417
6 -0.151 -0.107 -0.055 0.009 0.014 -0.164 -0.234 -0.305 -0.349 -0.443
7 -0.111 -0.072 -0.013 0.053 0.064 -0.069 -0.223 -0.295 -0.332 -0.401
8 -0.015 0.021 0.084 0.136 0.148 0.092 -0.056 -0.213 -0.253 -0.275
9 0.090 0.137 0.181 0.226 0.235 0.194 0.111 -0.052 -0.148 -0.128
10 0.215 0.246 0.277 0.314 0.319 0.277 0.211 0.119 0.030 0.030
11 0.272 0.296 0.327 0.361 0.362 0.293 0.222 0.146 0.107 0.113
12 -0.256 -0.232 -0.206 -0.181 -0.179 -0.241 -0.308 -0.380 -0.378 -0.413
13 -0.315 -0.293 -0.270 -0.252 -0.251 -0.301 -0.362 -0.389 -0.423 -0.440
14 -0.363 -0.353 -0.337 -0.315 -0.313 -0.346 -0.366 -0.426 -0.455 -0.460
15 -0.419 -0.414 -0.406 -0.392 -0.383 -0.351 -0.406 -0.466 -0.496 -0.487
16 -0.461 -0.460 -0.454 -0.448 -0.397 -0.376 -0.426 -0.481 -0.510 -0.497
17 -0.534 -0.536 -0.538 -0.493 -0.484 -0.450 -0.475 -0.529 -0.558 -0.546
18 -0.633 -0.634 -0.597 -0.591 -0.586 -0.567 -0.565 -0.593 -0.624 -0.630
19 -0.750 -0.713 -0.712 -0.709 -0.707 -0.699 -0.697 -0.698 -0.712 -0.740

Hard Chart - Player Expected Gains per original unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 -0.587 -0.497 -0.352 -0.209 -0.244 -0.938 -1.025 -1.066 -1.093 -1.318
6 -0.560 -0.446 -0.324 -0.186 -0.215 -0.870 -1.023 -1.045 -1.074 -1.295
7 -0.415 -0.317 -0.186 -0.066 -0.059 -0.555 -0.851 -0.936 -0.956 -1.127
8 -0.165 -0.081 0.032 0.143 0.157 -0.140 -0.433 -0.697 -0.743 -0.802
9 0.114 0.193 0.286 0.380 0.393 0.175 0.007 -0.281 -0.442 -0.409
10 0.428 0.492 0.554 0.628 0.638 0.446 0.313 0.164 0.007 0.025
11 0.542 0.592 0.654 0.722 0.724 0.479 0.341 0.223 0.164 0.198
12 -0.511 -0.463 -0.413 -0.362 -0.358 -0.556 -0.690 -0.811 -0.789 -0.827
13 -0.630 -0.587 -0.541 -0.503 -0.503 -0.651 -0.775 -0.807 -0.862 -0.880
14 -0.727 -0.706 -0.673 -0.630 -0.627 -0.723 -0.759 -0.862 -0.915 -0.921
15 -0.838 -0.829 -0.812 -0.783 -0.767 -0.716 -0.826 -0.937 -0.992 -0.973
16 -0.921 -0.920 -0.908 -0.896 -0.793 -0.751 -0.853 -0.961 -1.019 -0.995
17 -1.069 -1.072 -1.076 -0.985 -0.967 -0.901 -0.949 -1.058 -1.116 -1.092
18 -1.265 -1.267 -1.195 -1.182 -1.172 -1.135 -1.130 -1.186 -1.248 -1.260
19 -1.499 -1.425 -1.423 -1.417 -1.414 -1.397 -1.395 -1.396 -1.425 -1.481

Hard Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
5 H H H H H H H H H H
6 H H H H H H H H H H
7 H H H H H H H H H H
8 H H H D D H H H H H
9 D D D D D H H H H H
10 D D D D D D D D H H
11 D D D D D D D D D D
12 H H S S S H H H H H
13 S S S S S H H H H H
14 S S S S S H H H H H
15 S S S S S H H H H H
16 S S S S S H H H H H
17 S S S S S S S S S S
18 S S S S S S S S S S
19 S S S S S S S S S S

Hard Chart - Player Strategy (Round >= 2, No Doubling)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
4 H H H H H H H H H H
5 H H H H H H H H H H
6 H H H H H H H H H H
7 H H H H H H H H H H
8 H H H H H H H H H H
9 H H H H H H H H H H
10 H H H H H H H H H H
11 H H H H H H H H H H
12 H H S S S H H H H H
13 S S S S S H H H H H
14 S S S S S H H H H H
15 S S S S S H H H H H
16 S S S S S H H H H H
17 S S S S S S S S S S
18 S S S S S S S S S S
19 S S S S S S S S S S
20 S S S S S S S S S S
21 S S S S S S S S S S

Soft Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 -0.283 -0.241 -0.186 -0.119 -0.114 -0.462 -0.508 -0.517 -0.539 -0.662
A3 -0.284 -0.240 -0.170 -0.116 -0.112 -0.460 -0.505 -0.527 -0.538 -0.661
A4 -0.283 -0.224 -0.166 -0.113 -0.109 -0.458 -0.514 -0.526 -0.538 -0.659
A5 -0.266 -0.221 -0.164 -0.111 -0.108 -0.468 -0.515 -0.525 -0.537 -0.659
A6 -0.132 -0.093 -0.037 0.005 0.010 -0.090 -0.385 -0.407 -0.418 -0.483
A7 0.136 0.167 0.204 0.222 0.262 0.412 0.121 -0.179 -0.186 -0.101
A8 0.402 0.420 0.415 0.461 0.482 0.615 0.608 0.288 0.064 0.290
A9 0.656 0.644 0.654 0.682 0.694 0.773 0.785 0.766 0.555 0.681

Soft Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 0.039 0.071 0.110 0.159 0.168 0.107 0.039 -0.014 -0.090 -0.184
A3 0.017 0.044 0.091 0.137 0.147 0.060 0.035 -0.060 -0.124 -0.216
A4 -0.012 0.022 0.061 0.108 0.120 0.034 -0.035 -0.114 -0.172 -0.256
A5 -0.032 -0.003 0.038 0.082 0.116 -0.024 -0.084 -0.167 -0.229 -0.296
A6 0.007 0.036 0.077 0.140 0.133 0.060 -0.065 -0.135 -0.189 -0.242
A7 0.065 0.093 0.156 0.175 0.192 0.175 0.047 -0.087 -0.140 -0.160
A8 0.120 0.173 0.187 0.227 0.241 0.222 0.158 0.005 -0.087 -0.081
A9 0.191 0.196 0.230 0.268 0.280 0.243 0.172 0.096 0.007 -0.008

Soft Chart - Player Expected Gains per unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 -0.042 0.028 0.115 0.212 0.230 -0.157 -0.312 -0.373 -0.478 -0.586
A3 -0.047 0.011 0.109 0.204 0.222 -0.175 -0.254 -0.394 -0.479 -0.588
A4 -0.070 0.003 0.085 0.175 0.201 -0.141 -0.314 -0.422 -0.495 -0.613
A5 -0.082 -0.019 0.063 0.148 0.217 -0.189 -0.333 -0.452 -0.536 -0.649
A6 0.013 0.074 0.155 0.280 0.266 0.014 -0.230 -0.345 -0.433 -0.522
A7 0.128 0.189 0.313 0.349 0.385 0.240 -0.015 -0.254 -0.322 -0.359
A8 0.237 0.346 0.373 0.453 0.483 0.325 0.190 -0.060 -0.226 -0.200
A9 0.380 0.392 0.459 0.536 0.560 0.351 0.230 0.111 -0.055 -0.055

Soft Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
A2 H H D D D H H H H H
A3 H H D D D H H H H H
A4 H H D D D H H H H H
A5 H H D D D H H H H H
A6 D D D D D H H H H H
A7 S D D D D S S H H S
A8 S S S S D S S S S S
A9 S S S S S S S S S S

Soft Chart - Player Strategy (Round >= 2, No Doubling)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
12 H H H H H H H H H H
13 H H H H H H H H H H
14 H H H H H H H H H H
15 H H H H H H H H H H
16 H H H H H H H H H H
17 H H H H H H H H H H
18 S S S S S S S H H S
19 S S S S S S S S S S
20 S S S S S S S S S S
21 S S S S S S S S S S

Pairs Chart - Player Expected Gains per unit (Stand)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA -0.274 -0.232 -0.178 -0.130 -0.104 -0.452 -0.500 -0.511 -0.531 -0.663
22 -0.291 -0.251 -0.192 -0.107 -0.125 -0.471 -0.515 -0.523 -0.547 -0.660
33 -0.295 -0.246 -0.160 -0.101 -0.119 -0.467 -0.510 -0.542 -0.546 -0.660
44 -0.290 -0.214 -0.152 -0.095 -0.114 -0.463 -0.529 -0.543 -0.547 -0.656
55 -0.256 -0.206 -0.146 -0.090 -0.112 -0.484 -0.531 -0.541 -0.545 -0.653
66 -0.262 -0.211 -0.152 -0.102 -0.165 -0.493 -0.536 -0.549 -0.552 -0.617
77 -0.268 -0.219 -0.164 -0.156 -0.174 -0.502 -0.539 -0.555 -0.510 -0.631
88 -0.275 -0.228 -0.215 -0.165 -0.178 -0.503 -0.551 -0.516 -0.518 -0.644
99 0.137 0.123 0.167 0.203 0.265 0.401 0.065 -0.196 -0.133 -0.055
TT 0.627 0.636 0.645 0.674 0.697 0.765 0.783 0.744 0.583 0.650

Pairs Chart - Player Expected Gains per unit (Hit)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA 0.095 0.120 0.142 0.182 0.200 0.158 0.093 -0.003 -0.048 -0.075
22 -0.113 -0.082 -0.035 0.036 0.032 -0.092 -0.141 -0.222 -0.277 -0.395
33 -0.153 -0.118 -0.047 0.008 0.014 -0.164 -0.231 -0.310 -0.346 -0.444
44 -0.013 0.028 0.098 0.154 0.175 0.111 -0.055 -0.206 -0.246 -0.268
55 0.224 0.254 0.295 0.347 0.362 0.279 0.207 0.119 0.032 0.042
66 -0.253 -0.222 -0.190 -0.162 -0.194 -0.265 -0.322 -0.386 -0.386 -0.411
77 -0.406 -0.388 -0.369 -0.370 -0.367 -0.389 -0.408 -0.475 -0.516 -0.510
88 -0.454 -0.450 -0.461 -0.453 -0.397 -0.374 -0.426 -0.487 -0.512 -0.490
99 -0.627 -0.638 -0.597 -0.590 -0.587 -0.566 -0.566 -0.595 -0.626 -0.621
TT -0.847 -0.846 -0.846 -0.846 -0.845 -0.843 -0.843 -0.842 -0.840 -0.882

Pairs Chart - Player Expected Gains per unit (Double)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA -0.019 0.055 0.137 0.216 0.248 -0.137 -0.296 -0.421 -0.468 -0.591
22 -0.582 -0.501 -0.384 -0.214 -0.249 -0.942 -1.030 -1.047 -1.094 -1.320
33 -0.567 -0.472 -0.302 -0.184 -0.215 -0.871 -1.000 -1.065 -1.072 -1.298
44 -0.185 -0.082 0.044 0.162 0.193 -0.108 -0.447 -0.701 -0.741 -0.802
55 0.446 0.510 0.590 0.695 0.724 0.466 0.323 0.175 0.014 0.042
66 -0.505 -0.444 -0.380 -0.325 -0.387 -0.599 -0.711 -0.817 -0.803 -0.823
77 -0.813 -0.777 -0.738 -0.741 -0.734 -0.823 -0.858 -0.978 -1.035 -1.019
88 -0.908 -0.900 -0.922 -0.906 -0.793 -0.747 -0.853 -0.974 -1.024 -0.980
99 -1.255 -1.277 -1.194 -1.181 -1.173 -1.132 -1.133 -1.189 -1.252 -1.242
TT -1.693 -1.693 -1.693 -1.691 -1.690 -1.686 -1.685 -1.684 -1.681 -1.764

Pairs Chart - Player Expected Gains per unit (Split)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA 1.192 1.223 1.265 1.321 1.344 1.308 1.201 1.039 0.860 0.921
22 -0.128 -0.070 -0.007 0.128 0.126 -0.054 -0.213 -0.383 -0.463 -0.566
33 -0.202 -0.128 0.009 0.117 0.112 -0.115 -0.265 -0.418 -0.509 -0.579
44 -0.236 -0.127 -0.013 0.095 0.083 -0.223 -0.343 -0.493 -0.580 -0.623
55 -0.232 -0.150 -0.038 0.068 0.056 -0.299 -0.448 -0.608 -0.685 -0.695
66 -0.219 -0.135 -0.028 0.068 -0.011 -0.270 -0.413 -0.570 -0.652 -0.660
77 -0.163 -0.084 0.016 0.039 0.053 -0.123 -0.423 -0.564 -0.634 -0.635
88 0.017 0.077 0.106 0.188 0.234 0.202 -0.100 -0.430 -0.464 -0.378
99 0.170 0.170 0.253 0.339 0.359 0.341 0.179 -0.112 -0.268 -0.109
TT 0.412 0.465 0.518 0.596 0.619 0.576 0.447 0.276 0.146 0.140

Pairs Chart - Player Strategy (Round 1)
P/D 2 3 4 5 6 7 8 9 T A
--------------------------------------------------------------------------
AA P P P P P P P P P P
22 H P P P P P H H H H
33 H H P P P P H H H H
44 H H H D D H H H H H
55 D D D D D D D D H D
66 P P P P P H H H H H
77 P P P P P P H H S H
88 P P P P P P P P P P
99 P P P P P S P P S S
TT S S S S S S S S S S

Simulation for Year 1:

After playing 50 times a day for 365 days:
Winning days : 180
Losing days : 176
Breakeven days : 9
Biggest win : 23.5
Biggest loss : 24.5
Total loss : 263
Total staked : 20482
Loss % staked : 1.284

Simulation for Year 2:

After playing 50 times a day for 365 days:
Winning days : 176
Losing days : 174
Breakeven days : 15
Biggest win : 20.5
Biggest loss : 20
Total loss : 60.5
Total staked : 20514
Loss % staked : 0.295

Simulation for Year 3:

After playing 50 times a day for 365 days:
Winning days : 163
Losing days : 195
Breakeven days : 7
Biggest win : 20.5
Biggest loss : 26
Total loss : 297
Total staked : 20501
Loss % staked : 1.449

Simulation for Year 4:

After playing 50 times a day for 365 days:
Winning days : 163
Losing days : 190
Breakeven days : 12
Biggest win : 21.5
Biggest loss : 20.5
Total loss : 144.5
Total staked : 20507
Loss % staked : 0.705

Simulation for Year 5:

After playing 50 times a day for 365 days:
Winning days : 153
Losing days : 203
Breakeven days : 9
Biggest win : 19
Biggest loss : 24.5
Total loss : 485.5
Total staked : 20501
Loss % staked : 2.368

Simulation for Year 6:

After playing 50 times a day for 365 days:
Winning days : 176
Losing days : 177
Breakeven days : 12
Biggest win : 21
Biggest loss : 29.5
Total loss : 4
Total staked : 20536
Loss % staked : 0.019

Simulation for Year 7:

After playing 50 times a day for 365 days:
Winning days : 161
Losing days : 195
Breakeven days : 9
Biggest win : 25.5
Biggest loss : 24.5
Total loss : 316.5
Total staked : 20568
Loss % staked : 1.539

Simulation for Year 8:

After playing 50 times a day for 365 days:
Winning days : 168
Losing days : 189
Breakeven days : 8
Biggest win : 21
Biggest loss : 28
Total loss : 240
Total staked : 20524
Loss % staked : 1.169

Simulation for Year 9:

After playing 50 times a day for 365 days:
Winning days : 181
Losing days : 174
Breakeven days : 10
Biggest win : 22
Biggest loss : 26
Total loss : 17
Total staked : 20494
Loss % staked : 0.083

Simulation for Year 10:

After playing 50 times a day for 365 days:
Winning days : 156
Losing days : 198
Breakeven days : 11
Biggest win : 22
Biggest loss : 21
Total loss : 346.5
Total staked : 20438
Loss % staked : 1.695
</pre>

Latest revision as of 16:21, 9 November 2023

Blackjack strategy is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

The objective of this task is to recreate and explore the following strategy charts for the game of blackjack (which is known by many other names as well).

Assume that my casino:

  • uses a single deck,
  • does not allow Double after split,
  • pays out 3 to 2 for Blackjack, and
  • uses these rules.

Begin by assuming the player's dealt hand contains no aces and is not a pair. Create functions which given the players dealt cards and the dealers exposed card returns the number of wins and losses for all possible continuations when the player either sticks or hits. Gather the results together, set a threshold at which you consider it wise to Double the bet and reconstruct the Hard Totals Table enhanced with precise probabilities.

Enhance your analysis by considering the case when the player's hand contains an Ace. Again by considering all continuations recreate the Soft Totals Table again enhanced with precise probabilities.

Finally complete your analysis by considering the case when the player's hand contains a pair. Again by considering all continuations recreate the Pair Splitting Table again enhanced with precise probabilities.

You should now create a function which randomly deals hands. Assuming I play 50 hands at a visit and visit everyday for a year, applying the strategy defined by the tables you have created, answer the following questions:

  • How many days can I expect to win/lose?
  • What can I expect to be my biggest win?
  • What can I expect to be my biggest loss?
  • What can I expect to win/lose over the year?

Go

As the dealer plays automatically, the first thing I did was to write a function which calculates the probabilities of the dealer ending up with various scores according to the Rules. I then checked the resulting table against a similar one on an 'active' online gambling site (which I'd better not link to here) and the results agreed to 6 decimal places.

The task asks us to calculate precise probabilities for all possible continuations after the player stands, hits, doubles or splits but this is impossible if the player 'hits' or 'splits' as we don't know what decisions (s)he will make subsequently. To be reasonably realistic, I decided to anticipate some further strategy tables I've computed for rounds after the initial deal and to assume that further decisions (to hit or stand) will be made in accordance with these tables.

The criterion I've used for doubling down is that this gives a better expected gain (positive or negative) than the other alternatives, taking into account the doubled stake.

Using these assumptions, I've been able to reproduce the 'hard' strategy table exactly and my 'soft' strategy table only differs in one case (A7/A) where I have 'stand' rather than 'hit' though the underlying figures are quite close.

The trickiest part of this task is dealing with the splitting of pairs (I've assumed re-splitting is not allowed though the Rules aren't explicit on this). The criterion used again is that this gives a better expected gain than the alternatives, taking into account the doubled stake.

I decided, given the other uncertainties, to make the simplifying assumption that, after calculating the expected gain for the first split hand as if the second one isn't completed, the expected gain for the second hand will then be exactly the same. This, of course, is not quite right since both hands need to be completed and the probabilities for the second hand will depend on what cards have been drawn for the first hand and the dealer's probabilities will depend on what cards have been drawn for both hands, a very complicated calculation.

However, the 'true' figures are unlikely to be much different from the figures I've actually used which is borne out by my 'pairs' strategy table only differing from the original in 4 cases out of 100 (33/3, 55/A, 77/T and 88/T). Of these, 2 cases have nothing to do with splitting, 1 case (55/A) is extremely marginal and the other 3 are quite close too.

Finally, I've done 10 years of simulations as the basic statistics can vary quite a bit from year to year. However, it will be seen that % loss varies over a narrower range - between about 0.3 and 1.8% for this particular run - which seems reasonable given the casino's edge even after basic strategy is utilized.

package main

import (
    "fmt"
    "math/rand"
    "time"
)

type Deck [11]int // 0:deck size, 1 to 10: number of cards of that denomination

type ActionGain struct {
    action string
    gain   float64
}

func NewDeck() Deck {
    return Deck{52, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16}
}

// Returns probabilities of dealer eventually getting:
// 0: 17, 1: 18, 2: 19, 3: 20, 4: 21 (non-blackjack), 5: blackjack (nil), 6: bust.
// It is assumed that the dealer has already checked for blackjack, that one deck is used
// and that the dealer stands on 'soft' 17.
func dealerProbs(upCard int, startDeck Deck) []float64 {
    res := make([]float64, 7)   // results
    decks := make([]Deck, 9)    // decks for each level
    scores := make([]int, 9)    // scores for each level
    elevens := make([]int, 9)   // number of aces for each level scored as 11
    probs := make([]float64, 9) // probs for each level
    decks[0] = startDeck
    scores[0] = upCard
    if upCard == 1 { // an ace
        scores[0] = 11
        elevens[0] = 1
    }
    probs[0] = 1.0
    var f func(lev int) // recursive closure
    f = func(lev int) {
        for c := 1; c < 11; c++ {
            if decks[lev][c] == 0 {
                continue // card no longer present in deck
            }
            // temporary variables for current level
            deck, score, eleven, prob := decks[lev], scores[lev], elevens[lev], probs[lev]
            score += c  // add card to score
            if c == 1 { // score all aces initially as 11
                score += 10
                eleven++
            }
            prob *= float64(deck[c]) / float64(deck[0])
            if score > 21 && eleven > 0 {
                score -= 10 // bust but can demote an ace
                eleven--
            }
            if lev == 0 && ((upCard == 1 && c == 10) || (upCard == 10 && c == 1)) {
                res[5] += prob // blackjack, allow for now
            } else if score >= 17 && score <= 21 {
                res[score-17] += prob // 17 to (non-blackjack) 21
            } else if score > 21 && eleven == 0 {
                res[6] += prob // bust
            } else {
                deck[c]-- // remove card from deck
                deck[0]-- // decrement deck size
                lev2 := lev + 1
                decks[lev2], scores[lev2], elevens[lev2], probs[lev2] = deck, score, eleven, prob
                f(lev2) // get another card
            }
        }
    }
    f(0)
    // but can't have blackjack, so adjust probabilities accordingly
    pnbj := 1 - res[5]
    for i := 0; i < 7; i++ {
        res[i] /= pnbj
    }
    res[5] = 0
    return res
}

// Prints chart of dealer probabilities (as a check against an external source).
func dealerChart() {
    fmt.Println("Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules")
    fmt.Println("Up Card     17        18        19        20        21       Bust")
    fmt.Println("-------------------------------------------------------------------")
    deck := NewDeck()
    deck[0] = 51
    for uc := 1; uc < 11; uc++ {
        deck2 := deck
        deck2[uc]--
        dp := dealerProbs(uc, deck2)
        if uc > 1 {
            fmt.Printf("%3d      ", uc)
        } else {
            fmt.Print("Ace      ")
        }
        fmt.Printf("%f  %f  %f  %f  %f  %f\n", dp[0], dp[1], dp[2], dp[3], dp[4], dp[6])
    }
}

// Returns player's expected gain per unit staked after hitting once and then standing.
func playerGain(card1, card2, uc int, startDeck Deck) float64 {
    eg := 0.0
    deck := startDeck
    score := card1 + card2
    eleven := false
    if card1 == 1 || card2 == 1 { // an ace
        score += 10
        eleven = true
    }
    for c := 1; c < 11; c++ { // get another card
        if deck[c] == 0 {
            continue // card no longer present in deck
        }
        // temporary variables for current card
        deck2, score2, eleven2 := deck, score, eleven
        score2 += c // add card to score
        if c == 1 { // score all aces initially as 11
            score2 += 10
            eleven2 = true
        }
        prob := float64(deck2[c]) / float64(deck2[0])
        deck2[c]-- // remove card from deck
        deck2[0]-- // decrement deck size
        if score2 > 21 && eleven2 {
            score2 -= 10 // bust but can demote an ace
        }
        if score2 <= 21 {
            dp := dealerProbs(uc, deck2)
            eg += calcGain(score2, dp) * prob
        } else { // bust
            eg -= prob
        }
    }
    return eg
}

// Returns player's expected gain per unit staked after hitting once and then continuing in accordance
// with the tables for rounds >= 2.
func playerGain2(card1, card2, uc int, startDeck Deck) float64 {
    eg := 0.0                   // result
    decks := make([]Deck, 9)    // decks for each level
    scores := make([]int, 9)    // scores for each level
    elevens := make([]int, 9)   // number of aces for each level scored as 11
    probs := make([]float64, 9) // probs for each level
    decks[0] = startDeck
    scores[0] = card1 + card2
    if card1 == 1 || card2 == 1 { // an ace
        scores[0] += 10
        elevens[0] = 1
    }
    probs[0] = 1.0
    var f func(lev int) // recursive closure
    f = func(lev int) {
        for c := 1; c < 11; c++ {
            if decks[lev][c] == 0 {
                continue // card no longer present in deck
            }
            // temporary variables for current level
            deck, score, eleven, prob := decks[lev], scores[lev], elevens[lev], probs[lev]
            score += c  // add card to score
            if c == 1 { // score all aces initially as 11
                score += 10
                eleven++
            }
            prob *= float64(deck[c]) / float64(deck[0])
            if score > 21 && eleven > 0 {
                score -= 10 // bust but can demote an ace
                eleven--
            }
            deck[c]-- // remove card from deck
            deck[0]-- // decrement deck size
            if (eleven == 0 && (score >= 17 || (score >= 13 && uc < 7)) ||
                (eleven == 0 && score == 12 && uc >= 4 && uc <= 6) ||
                (eleven > 0 && score == 18 && uc != 9 && uc != 10) ||
                (eleven > 0 && score >= 19)) && score <= 21 {
                dp := dealerProbs(uc, deck)
                eg += calcGain(score, dp) * prob
            } else if score > 21 && eleven == 0 { // bust
                eg -= prob
            } else {
                lev2 := lev + 1
                decks[lev2], scores[lev2], elevens[lev2], probs[lev2] = deck, score, eleven, prob
                f(lev2) // get another card
            }
        }
    }
    f(0)
    return eg
}

// Calculates gain per unit staked for a given scenario (helper function).
func calcGain(pscore int, dp []float64) float64 {
    eg := 0.0
    switch pscore {
    case 17:
        eg += dp[6]                         // dealer is bust
        eg -= dp[1] + dp[2] + dp[3] + dp[4] // dealer has 18 to 21
    case 18:
        eg += dp[0] + dp[6]         // dealer has 17 or is bust
        eg -= dp[2] + dp[3] + dp[4] // dealer has 19 to 21
    case 19:
        eg += dp[0] + dp[1] + dp[6] // dealer has 17, 18 or is bust
        eg -= dp[3] + dp[4]         // dealer has 20 or 21
    case 20:
        eg += dp[0] + dp[1] + dp[2] + dp[6] // dealer has 17 to 19 or is bust
        eg -= dp[4]                         // dealer has (non-blackjack) 21
    case 21:
        eg += dp[0] + dp[1] + dp[2] + dp[3] + dp[6] // dealer has 17 to 20 or is bust
    case 22: // notional
        eg += 1.5 // player blackjack
    case 23: // notional
        eg -= 1 // player bust, loses stake irrespective of what dealer has
    default: // player has less than 17
        eg += dp[6]       // dealer is bust
        eg -= (1 - dp[6]) // dealer isn't bust
    }
    return eg
}

// Returns player's expected gains per unit staked, for each dealer up-card, after standing.
func stand(card1, card2 int) [10]float64 {
    deck := NewDeck()
    deck[card1]--
    deck[card2]--
    deck[0] = 50
    pscore := card1 + card2 // player score
    if card1 == 1 || card2 == 1 {
        pscore += 10
    }
    var egs [10]float64          // results
    for uc := 1; uc < 11; uc++ { // dealer's up-card
        deck2 := deck
        deck2[uc]--
        deck2[0]--
        dp := dealerProbs(uc, deck2)
        eg := calcGain(pscore, dp) // expected gain for this up-card
        if uc > 1 {
            egs[uc-2] = eg
        } else { // dealer has Ace
            egs[9] = eg // ace comes last in tables
        }
    }
    return egs
}

// Returns player's expected gains per unit staked, for each dealer up-card, after hitting once and
// then either standing (once == true) or continuing as per the round >= 2 tables (once == false).
func hit(card1, card2 int, once bool) [10]float64 {
    deck := NewDeck()
    deck[card1]--
    deck[card2]--
    deck[0] = 50
    var egs [10]float64          // results
    for uc := 1; uc < 11; uc++ { // dealer's up-card
        deck2 := deck
        deck2[uc]--
        deck2[0] = 49
        var peg float64 // player's expected gain for this up-card
        if once {
            peg = playerGain(card1, card2, uc, deck2)
        } else {
            peg = playerGain2(card1, card2, uc, deck2)
        }
        if uc > 1 {
            egs[uc-2] = peg
        } else { // dealer has Ace
            egs[9] = peg
        }
    }
    return egs
}

// Returns player's expected gains per unit oiginally staked, for each dealer up-card, after
// doubling i.e. hitting once and then standing with a doubled stake.
func double(card1, card2 int) [10]float64 {
    egs := hit(card1, card2, true) // hit once and then stand
    for i := 0; i < 10; i++ {
        egs[i] *= 2
    }
    return egs
}

// Returns player's expected gains per unit originally staked, for each dealer up-card, after
// splitting a pair and doubling the stake, getting a second card for each hand  and then continuing
// in accordace with the rounds >= 2 tables. It is assumed that a player cannot double or re-split
// following a split. It is also assumed (in the interests of simplicity) that the expected gains
// for each split hand (after calculating the gains for the first hand as though the second hand
// is not completed) are exactly the same.
func split(card int) [10]float64 {
    deck := NewDeck()
    deck[card] -= 2 // must be a pair
    deck[0] = 50
    var egs [10]float64 // overall results

    // now play a single hand
    score := card
    eleven := 0
    if card == 1 { // an ace
        score = 11
        eleven = 1
    }
    for uc := 1; uc < 11; uc++ { // collect results for each dealer up-card
        if deck[uc] == 0 {
            continue // card no longer present in deck
        }
        deck2 := deck
        deck2[uc]--
        deck2[0]--
        ix := uc - 2
        if ix == -1 {
            ix = 9 // in tables ace comes last
        }
        var peg float64 // player expected gain for this up-card
        // get second player card
        for c := 1; c < 11; c++ {
            if deck2[c] == 0 {
                continue // card no longer present in deck
            }
            prob := float64(deck2[c]) / float64(deck2[0])
            deck3 := deck2
            deck3[c]--
            deck3[0]--
            score2 := score + c
            eleven2 := eleven
            if c == 1 { // score all aces initially as 11
                score2 += 10
                eleven2++
            }
            if score2 == 21 { // player has blackjack & we know dealer hasn't
                peg += 1.5 * prob
                continue
            }
            if score2 > 21 && eleven2 > 0 {
                score2 -= 10 // bust but can demote an ace
                eleven2--
            }
            var action string
            if eleven2 > 0 {
                action = sTable2[score2-12][ix] // use soft strategy table, no doubling
            } else { // including pairs as no re-splitting
                action = hTable2[score2-4][ix] // use hard strategy table, no doubling
            }
            var peg2 float64
            if action == "S" {
                dp := dealerProbs(uc, deck3)
                peg2 = calcGain(score2, dp)
            } else {
                peg2 = playerGain2(card, c, uc, deck3)
            }
            peg += peg2 * prob
        }
        if uc > 1 {
            egs[uc-2] = peg * 2 // allow for both hands in overall results
        } else {
            egs[9] = peg * 2 // ditto
        }
    }
    return egs
}

// Returns the action with the highest expected gain.
func bestAction(ags []ActionGain) string {
    max := ags[0].gain
    maxi := 0
    for i := 1; i < len(ags); i++ {
        if ags[i].gain > max {
            max = ags[i].gain
            maxi = i
        }
    }
    return ags[maxi].action
}

// Prints title and header for a given chart.
func printHeader(title string) {
    fmt.Println(title)
    fmt.Println("P/D     2      3      4      5      6      7      8      9      T      A")
    fmt.Println("--------------------------------------------------------------------------")
}

// Prints header for a pair of cards.
func printPair(c int) {
    if c == 1 {
        fmt.Print("AA   ")
    } else if c == 10 {
        fmt.Print("TT   ")
    } else {
        fmt.Printf("%d%d   ", c, c)
    }
}

// Computed strategy tables.
var (
    hTable  = [15][10]string{} // hard strategy table (round 1)
    sTable  = [8][10]string{}  // soft strategy table (round 1)
    pTable  = [10][10]string{} // pairs strategy table (round 1)
    hTable2 = [18][10]string{} // hard strategy table (round >= 2, no doubling)
    sTable2 = [10][10]string{} // soft strategy table (round >= 2, no doubling)
)

// Simulates 'perDay' blackjack games for 'days' days.
func simulate(perDay, days int) {
    winDays, loseDays, evenDays := 0, 0, 0
    bigWin, bigLoss := 0.0, 0.0
    totalGain, totalStake := 0.0, 0.0
    for d := 1; d <= days; d++ {
        dailyGain, dailyStake := 0.0, 0.0
        for p := 1; p <= perDay; p++ {
            gain, stake := playerPlay()
            dailyGain += gain
            dailyStake += stake
        }
        if dailyGain > 0 {
            winDays++
        } else if dailyGain < 0 {
            loseDays++
        } else {
            evenDays++
        }
        if dailyGain > bigWin {
            bigWin = dailyGain
        } else if -dailyGain > bigLoss {
            bigLoss = -dailyGain
        }
        totalGain += dailyGain
        totalStake += dailyStake
    }
    fmt.Printf("\nAfter playing %d times a day for %d days:\n", perDay, days)
    fmt.Println("Winning days   :", winDays)
    fmt.Println("Losing days    :", loseDays)
    fmt.Println("Breakeven days :", evenDays)
    fmt.Println("Biggest win    :", bigWin)
    fmt.Println("Biggest loss   :", bigLoss)
    if totalGain < 0 {
        fmt.Println("Total loss     :", -totalGain)
        fmt.Println("Total staked   :", totalStake)
        fmt.Printf("Loss %% staked  : %0.3f\n", -totalGain/totalStake*100)
    } else {
        fmt.Println("Total win      :", totalGain)
        fmt.Println("Total staked   :", totalStake)
        fmt.Printf("Win %% staked   : %0.3f\n", totalGain/totalStake*100)
    }
}

// Simulates a dealer's play for a given player's hand and state of deck.
// Returns the player's gain (positive or negative) per unit staked.
func dealerPlay(pscore int, next *int, cards, d []int) float64 {
    dscore := d[0] + d[1]
    aces := 0
    if d[0] == 1 || d[1] == 1 { // dealer has an ace
        dscore += 10
        aces++
    }
    for {
        if dscore > 21 && aces > 0 {
            dscore -= 10 // bust but we can demote an ace
            aces--
        }
        if dscore > 21 {
            return 1 // dealer is bust and player gains stake
        }
        if dscore >= 17 { // dealer must stick on 17 or above, hard or not
            if dscore > pscore {
                return -1 // dealer wins and player loses stake
            } else if dscore == pscore {
                break // player breaks even
            } else {
                return 1 // dealer loses and player gains stake
            }
        }
        nc := cards[*next] // get new card from pack
        *next++
        dscore += nc
        if nc == 1 { // count aces initially as 11
            dscore += 10
            aces++
        }
    }
    return 0
}

// Simulates the playing of a random player's hand according to the strategy tables.
// Returns both the gain (positive or negative) and the stake (1 or 2).
func playerPlay() (float64, float64) {
    perm := rand.Perm(52) // randomizes integers from 0 to 51 inclusive
    cards := make([]int, 52)
    for i, r := range perm {
        card := r/4 + 1
        if card > 10 {
            card = 10
        }
        cards[i] = card
    }
    var p, d []int // player and dealer hands
    // initial deal
    for i, card := range cards[0:4] {
        if i < 2 {
            p = append(p, card)
        } else {
            d = append(d, card)
        }
    }
    next := 4 // index of next card to be dealt

    // check if dealer and/or player have blackjack
    dbj := (d[0] == 1 && d[1] == 10) || (d[0] == 10 && d[1] == 1)
    pbj := (p[0] == 1 && p[1] == 10) || (p[0] == 10 && p[1] == 1)
    if dbj {
        if pbj {
            return 0.0, 1.0 // player neither wins nor loses
        }
        return -1.0, 1.0 // player loses stake
    }
    if pbj {
        return 1.5, 1.0 // player wins 1.5 x stake
    }

    uc := d[0] // dealer's up-card for accessing tables
    if uc == 0 {
        uc = 9 // move ace to last place
    } else {
        uc-- // move others down 1
    }
    stake := 1.0       // player's initial stake
    var fscores [2]int // final player scores (one or, after split, two hands)
    var action string
    var score, aces int

    h := func(hand int) { // processes a 'hit'
        for {
            nc := cards[next] // get new card from pack
            next++
            score += nc
            if nc == 1 { // count aces initially as 11
                score += 10
                aces++
            }
            if score > 21 && aces > 0 {
                score -= 10 // bust but we can demote an ace
                aces--
            }
            if score > 21 {
                fscores[hand] = 22 // player is bust and loses stake
                return
            }
            if action == "D" {
                fscores[hand] = score
                return
            }
            // get further strategy and act accordingly
            if aces == 0 {
                action = hTable2[score-4][uc]
            } else {
                action = sTable2[score-12][uc]
            }
            if action == "S" { // stand
                fscores[hand] = score
                return
            }
        }
    }

    score = p[0] + p[1]
    // get kind of player hand: hard, soft, pair
    var kind string
    if p[0] == p[1] {
        kind = "pair"
    } else if p[0] == 1 || p[1] == 1 {
        kind = "soft"
    } else {
        kind = "hard"
    }
    switch kind {
    case "hard":
        action = hTable[score-5][uc]
    case "soft": // includes one ace
        otherCard := p[0]
        if otherCard == 1 {
            otherCard = p[1]
        }
        score += 10
        aces = 1
        action = sTable[otherCard-2][uc]
    case "pair":
        if p[0] == 1 { // pair of aces
            score += 10
            aces = 2
        }
        action = pTable[p[0]-1][uc]
    }
    switch action {
    case "S": // stand
        fscores[0] = score
    case "H": // hit
        h(0)
    case "D": // double
        h(0)
        stake = 2
    case "P": // split
        for hand := 0; hand < 2; hand++ {
            score = p[0]
            aces = 0
            if score == 1 { // count aces initially as 11
                score = 11
                aces++
            }
            h(hand)
        }
    }
    sum := 0.0
    if fscores[0] < 22 {
        sum += dealerPlay(fscores[0], &next, cards, d) * stake
    } else {
        sum -= 1 * stake // this hand is bust
    }
    if fscores[1] > 0 { // pair
        if fscores[1] < 22 {
            sum += dealerPlay(fscores[1], &next, cards, d)
        } else {
            sum -= 1 // this hand is bust
        }
        stake = 2
    }
    return sum, stake
}

func main() {
    // print dealer probabilities chart
    dealerChart()

    // for hard scores (i.e. different cards, no aces)
    tuples := [][2]int{
        {2, 3},
        {2, 4},
        {2, 5}, {3, 4},
        {2, 6}, {3, 5},
        {2, 7}, {3, 6}, {4, 5},
        {2, 8}, {3, 7}, {4, 6},
        {2, 9}, {3, 8}, {4, 7}, {5, 6},
        {2, 10}, {3, 9}, {4, 8}, {5, 7},
        {3, 10}, {4, 9}, {5, 8}, {6, 7},
        {4, 10}, {5, 9}, {6, 8},
        {5, 10}, {6, 9}, {7, 8},
        {6, 10}, {7, 9},
        {7, 10}, {8, 9},
        {8, 10},
        {9, 10},
    }
    // number of tuples for each player score from 5 to 19
    counts := [15]float64{1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1}
    // expected gains for each player score & for each dealer up-card
    segs := [15][10]float64{} // if stands
    hegs := [15][10]float64{} // if hits
    degs := [15][10]float64{} // if doubles
    for _, tuple := range tuples {
        i := tuple[0] + tuple[1]
        sg := stand(tuple[0], tuple[1])
        hg := hit(tuple[0], tuple[1], false)
        dg := double(tuple[0], tuple[1])
        for j := 0; j < 10; j++ {
            segs[i-5][j] += sg[j]
            hegs[i-5][j] += hg[j]
            degs[i-5][j] += dg[j]
        }
    }
    // calculate the average per tuple for each score
    for i := 0; i < 15; i++ {
        for j := 0; j < 10; j++ {
            segs[i][j] /= counts[i]
            hegs[i][j] /= counts[i]
            degs[i][j] /= counts[i]
        }
    }

    printHeader("\nHard Chart - Player Expected Gains per unit (Stand)")
    for i := 5; i < 20; i++ {
        fmt.Printf("%2d   ", i)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", segs[i-5][j])
        }
        fmt.Println()
    }

    printHeader("\nHard Chart - Player Expected Gains per unit (Hit)")
    for i := 5; i < 20; i++ {
        fmt.Printf("%2d   ", i)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", hegs[i-5][j])
        }
        fmt.Println()
    }

    printHeader("\nHard Chart - Player Expected Gains per original unit (Double)")
    for i := 5; i < 20; i++ {
        fmt.Printf("%2d   ", i)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", degs[i-5][j])
        }
        fmt.Println()
    }

    printHeader("\nHard Chart - Player Strategy (Round 1)")
    for i := 5; i < 20; i++ {
        fmt.Printf("%2d   ", i)
        for j := 0; j < 10; j++ {
            ags := []ActionGain{{"S", segs[i-5][j]}, {"H", hegs[i-5][j]}, {"D", degs[i-5][j]}}
            action := bestAction(ags)
            hTable[i-5][j] = action
            fmt.Printf("%4s   ", action)
        }
        fmt.Println()
    }

    // for hard scores (no aces) - after round 1 (no doubling or splitting)
    // based on hard table figures (round 1) with scores of 4, 20, and 21 added
    segs2 := [18][10]float64{} // expected gains if stands
    hegs2 := [18][10]float64{} // expected gains if hits
    for i := 5; i < 20; i++ {
        segs2[i-4] = segs[i-5]
        hegs2[i-4] = hegs[i-5]
    }
    sg4, hg4 := stand(2, 2), hit(2, 2, false)
    sg20, hg20 := stand(10, 10), hit(10, 10, false)
    sg21, hg21 := stand(1, 10), hit(1, 10, false)
    for j := 0; j < 10; j++ {
        segs2[0][j] += sg4[j]
        hegs2[0][j] += hg4[j]
        segs2[16][j] += sg20[j]
        hegs2[16][j] += hg20[j]
        segs2[17][j] += sg21[j]
        hegs2[17][j] += hg21[j]
    }

    printHeader("\nHard Chart - Player Strategy (Round >= 2, No Doubling)")
    for i := 4; i < 22; i++ {
        fmt.Printf("%2d   ", i)
        for j := 0; j < 10; j++ {
            action := "S"
            if hegs2[i-4][j] > segs2[i-4][j] {
                action = "H"
            }
            hTable2[i-4][j] = action
            fmt.Printf("%4s   ", action)
        }
        fmt.Println()
    }

    // for soft scores (i.e. including exactly one ace)

    // expected gains for each player second card (2 to 9) & for each dealer up-card
    segs3 := [8][10]float64{} // if stands
    hegs3 := [8][10]float64{} // if hits
    degs3 := [8][10]float64{} // if doubles
    for c := 2; c < 10; c++ {
        sg := stand(1, c)
        hg := hit(1, c, false)
        dg := double(1, c)
        for j := 0; j < 10; j++ {
            segs3[c-2][j] += sg[j]
            hegs3[c-2][j] += hg[j]
            degs3[c-2][j] += dg[j]
        }
    }

    printHeader("\nSoft Chart - Player Expected Gains per unit (Stand)")
    for c := 2; c < 10; c++ {
        fmt.Printf("A%d   ", c)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", segs3[c-2][j])
        }
        fmt.Println()
    }

    printHeader("\nSoft Chart - Player Expected Gains per unit (Hit)")
    for c := 2; c < 10; c++ {
        fmt.Printf("A%d   ", c)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", hegs3[c-2][j])
        }
        fmt.Println()
    }

    printHeader("\nSoft Chart - Player Expected Gains per original unit (Double)")
    for c := 2; c < 10; c++ {
        fmt.Printf("A%d   ", c)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", degs3[c-2][j])
        }
        fmt.Println()
    }

    printHeader("\nSoft Chart - Player Strategy (Round 1)")
    for c := 2; c < 10; c++ {
        fmt.Printf("A%d   ", c)
        for j := 0; j < 10; j++ {
            ags := []ActionGain{{"S", segs3[c-2][j]}, {"H", hegs3[c-2][j]}, {"D", degs3[c-2][j]}}
            action := bestAction(ags)
            sTable[c-2][j] = action
            fmt.Printf("%4s   ", action)
        }
        fmt.Println()
    }

    // for soft scores (at least one ace) - after round 1 (no doubling or splitting)
    // based on soft table figures (round 1) with scores of 12 and 21 added
    // assumes one ace counted as 11
    segs4 := [10][10]float64{} // expected gains if stands
    hegs4 := [10][10]float64{} // expected gains if hits
    for i := 1; i < 9; i++ {
        segs4[i] = segs3[i-1]
        hegs4[i] = hegs3[i-1]
    }
    sg12, hg12 := stand(1, 1), hit(1, 1, false)
    for j := 0; j < 10; j++ {
        segs4[0][j] += sg12[j]
        hegs4[0][j] += hg12[j]
        segs4[9][j] += sg21[j]
        hegs4[9][j] += hg21[j]
    }

    printHeader("\nSoft Chart - Player Strategy (Round >= 2, No Doubling)")
    for i := 12; i < 22; i++ {
        fmt.Printf("%2d   ", i)
        for j := 0; j < 10; j++ {
            action := "S"
            if hegs4[i-12][j] > segs4[i-12][j] {
                action = "H"
            }
            sTable2[i-12][j] = action
            fmt.Printf("%4s   ", action)
        }
        fmt.Println()
    }

    // for pairs

    // expected gains for each pair (A to 10) & for each dealer up-card
    segs5 := [10][10]float64{} // if stands
    hegs5 := [10][10]float64{} // if hits
    degs5 := [10][10]float64{} // if doubles
    pegs5 := [10][10]float64{} // if splits
    for c := 1; c < 11; c++ {
        sg := stand(c, c)
        hg := hit(c, c, false)
        dg := double(c, c)
        pg := split(c)
        for j := 0; j < 10; j++ {
            segs5[c-1][j] += sg[j]
            hegs5[c-1][j] += hg[j]
            degs5[c-1][j] += dg[j]
            pegs5[c-1][j] += pg[j]
        }
    }

    printHeader("\nPairs Chart - Player Expected Gains per unit (Stand)")
    for c := 1; c < 11; c++ {
        printPair(c)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", segs5[c-1][j])
        }
        fmt.Println()
    }

    printHeader("\nPairs Chart - Player Expected Gains per unit (Hit)")
    for c := 1; c < 11; c++ {
        printPair(c)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", hegs5[c-1][j])
        }
        fmt.Println()
    }

    printHeader("\nPairs Chart - Player Expected Gains per original unit (Double)")
    for c := 1; c < 11; c++ {
        printPair(c)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", degs5[c-1][j])
        }
        fmt.Println()
    }

    printHeader("\nPairs Chart - Player Expected Gains per original unit (Split)")
    for c := 1; c < 11; c++ {
        printPair(c)
        for j := 0; j < 10; j++ {
            fmt.Printf("% 0.3f ", pegs5[c-1][j])
        }
        fmt.Println()
    }

    printHeader("\nPairs Chart - Player Strategy (Round 1)")
    for c := 1; c < 11; c++ {
        printPair(c)
        for j := 0; j < 10; j++ {
            ags := []ActionGain{{"S", segs5[c-1][j]}, {"H", hegs5[c-1][j]}, {"D", degs5[c-1][j]},
                {"P", pegs5[c-1][j]}}
            action := bestAction(ags)
            pTable[c-1][j] = action
            fmt.Printf("%4s   ", action)
        }
        fmt.Println()
    }
    rand.Seed(time.Now().UnixNano())
    // do 10 years of simulations
    for i := 1; i <= 10; i++ {
        fmt.Printf("\nSimulation for Year %d:\n", i)
        simulate(50, 365)
    }
}
Output:
Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules
Up Card     17        18        19        20        21       Bust
-------------------------------------------------------------------
Ace      0.183786  0.190890  0.188680  0.191692  0.075137  0.169815
  2      0.138976  0.131762  0.131815  0.123948  0.120526  0.352973
  3      0.130313  0.130946  0.123761  0.123345  0.116047  0.375588
  4      0.130973  0.114163  0.120679  0.116286  0.115096  0.402803
  5      0.119687  0.123483  0.116909  0.104694  0.106321  0.428905
  6      0.166948  0.106454  0.107192  0.100705  0.097878  0.420823
  7      0.372345  0.138583  0.077334  0.078897  0.072987  0.259854
  8      0.130857  0.362989  0.129445  0.068290  0.069791  0.238627
  9      0.121886  0.103921  0.357391  0.122250  0.061109  0.233442
 10      0.124156  0.122486  0.124421  0.356869  0.039570  0.232499

Hard Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.293 -0.248 -0.176 -0.104 -0.122 -0.469 -0.513 -0.533 -0.546 -0.659 
 6   -0.291 -0.232 -0.172 -0.101 -0.119 -0.467 -0.522 -0.533 -0.547 -0.659 
 7   -0.283 -0.229 -0.163 -0.098 -0.117 -0.471 -0.521 -0.537 -0.547 -0.658 
 8   -0.276 -0.229 -0.162 -0.100 -0.130 -0.478 -0.523 -0.539 -0.549 -0.648 
 9   -0.277 -0.224 -0.160 -0.108 -0.134 -0.480 -0.528 -0.543 -0.542 -0.646 
10   -0.279 -0.227 -0.172 -0.120 -0.146 -0.484 -0.531 -0.539 -0.537 -0.644 
11   -0.277 -0.231 -0.175 -0.123 -0.147 -0.488 -0.529 -0.537 -0.537 -0.646 
12   -0.286 -0.241 -0.185 -0.134 -0.151 -0.485 -0.526 -0.535 -0.533 -0.655 
13   -0.282 -0.236 -0.181 -0.133 -0.156 -0.488 -0.529 -0.537 -0.534 -0.649 
14   -0.282 -0.238 -0.188 -0.134 -0.159 -0.489 -0.529 -0.533 -0.536 -0.651 
15   -0.280 -0.239 -0.190 -0.144 -0.169 -0.494 -0.531 -0.536 -0.531 -0.648 
16   -0.287 -0.250 -0.194 -0.152 -0.179 -0.495 -0.526 -0.540 -0.530 -0.648 
17   -0.147 -0.120 -0.074 -0.044 -0.011 -0.122 -0.405 -0.414 -0.402 -0.459 
18    0.119  0.144  0.164  0.202  0.268  0.389  0.096 -0.196 -0.155 -0.082 
19    0.385  0.384  0.404  0.448  0.484  0.610  0.577  0.264  0.103  0.308 

Hard Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.131 -0.098 -0.041  0.022  0.019 -0.119 -0.181 -0.262 -0.309 -0.417 
 6   -0.151 -0.107 -0.055  0.009  0.014 -0.164 -0.234 -0.305 -0.349 -0.443 
 7   -0.111 -0.072 -0.013  0.053  0.064 -0.069 -0.223 -0.295 -0.332 -0.401 
 8   -0.015  0.021  0.084  0.136  0.148  0.092 -0.056 -0.213 -0.253 -0.275 
 9    0.090  0.137  0.181  0.226  0.235  0.194  0.111 -0.052 -0.148 -0.128 
10    0.215  0.246  0.277  0.314  0.319  0.277  0.211  0.119  0.030  0.030 
11    0.272  0.296  0.327  0.361  0.362  0.293  0.222  0.146  0.107  0.113 
12   -0.256 -0.232 -0.206 -0.181 -0.179 -0.241 -0.308 -0.380 -0.378 -0.413 
13   -0.315 -0.293 -0.270 -0.252 -0.251 -0.301 -0.362 -0.389 -0.423 -0.440 
14   -0.363 -0.353 -0.337 -0.315 -0.313 -0.346 -0.366 -0.426 -0.455 -0.460 
15   -0.419 -0.414 -0.406 -0.392 -0.383 -0.351 -0.406 -0.466 -0.496 -0.487 
16   -0.461 -0.460 -0.454 -0.448 -0.397 -0.376 -0.426 -0.481 -0.510 -0.497 
17   -0.534 -0.536 -0.538 -0.493 -0.484 -0.450 -0.475 -0.529 -0.558 -0.546 
18   -0.633 -0.634 -0.597 -0.591 -0.586 -0.567 -0.565 -0.593 -0.624 -0.630 
19   -0.750 -0.713 -0.712 -0.709 -0.707 -0.699 -0.697 -0.698 -0.712 -0.740 

Hard Chart - Player Expected Gains per original unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.587 -0.497 -0.352 -0.209 -0.244 -0.938 -1.025 -1.066 -1.093 -1.318 
 6   -0.560 -0.446 -0.324 -0.186 -0.215 -0.870 -1.023 -1.045 -1.074 -1.295 
 7   -0.415 -0.317 -0.186 -0.066 -0.059 -0.555 -0.851 -0.936 -0.956 -1.127 
 8   -0.165 -0.081  0.032  0.143  0.157 -0.140 -0.433 -0.697 -0.743 -0.802 
 9    0.114  0.193  0.286  0.380  0.393  0.175  0.007 -0.281 -0.442 -0.409 
10    0.428  0.492  0.554  0.628  0.638  0.446  0.313  0.164  0.007  0.025 
11    0.542  0.592  0.654  0.722  0.724  0.479  0.341  0.223  0.164  0.198 
12   -0.511 -0.463 -0.413 -0.362 -0.358 -0.556 -0.690 -0.811 -0.789 -0.827 
13   -0.630 -0.587 -0.541 -0.503 -0.503 -0.651 -0.775 -0.807 -0.862 -0.880 
14   -0.727 -0.706 -0.673 -0.630 -0.627 -0.723 -0.759 -0.862 -0.915 -0.921 
15   -0.838 -0.829 -0.812 -0.783 -0.767 -0.716 -0.826 -0.937 -0.992 -0.973 
16   -0.921 -0.920 -0.908 -0.896 -0.793 -0.751 -0.853 -0.961 -1.019 -0.995 
17   -1.069 -1.072 -1.076 -0.985 -0.967 -0.901 -0.949 -1.058 -1.116 -1.092 
18   -1.265 -1.267 -1.195 -1.182 -1.172 -1.135 -1.130 -1.186 -1.248 -1.260 
19   -1.499 -1.425 -1.423 -1.417 -1.414 -1.397 -1.395 -1.396 -1.425 -1.481 

Hard Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5      H      H      H      H      H      H      H      H      H      H   
 6      H      H      H      H      H      H      H      H      H      H   
 7      H      H      H      H      H      H      H      H      H      H   
 8      H      H      H      D      D      H      H      H      H      H   
 9      D      D      D      D      D      H      H      H      H      H   
10      D      D      D      D      D      D      D      D      H      H   
11      D      D      D      D      D      D      D      D      D      D   
12      H      H      S      S      S      H      H      H      H      H   
13      S      S      S      S      S      H      H      H      H      H   
14      S      S      S      S      S      H      H      H      H      H   
15      S      S      S      S      S      H      H      H      H      H   
16      S      S      S      S      S      H      H      H      H      H   
17      S      S      S      S      S      S      S      S      S      S   
18      S      S      S      S      S      S      S      S      S      S   
19      S      S      S      S      S      S      S      S      S      S   

Hard Chart - Player Strategy (Round >= 2, No Doubling)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 4      H      H      H      H      H      H      H      H      H      H   
 5      H      H      H      H      H      H      H      H      H      H   
 6      H      H      H      H      H      H      H      H      H      H   
 7      H      H      H      H      H      H      H      H      H      H   
 8      H      H      H      H      H      H      H      H      H      H   
 9      H      H      H      H      H      H      H      H      H      H   
10      H      H      H      H      H      H      H      H      H      H   
11      H      H      H      H      H      H      H      H      H      H   
12      H      H      S      S      S      H      H      H      H      H   
13      S      S      S      S      S      H      H      H      H      H   
14      S      S      S      S      S      H      H      H      H      H   
15      S      S      S      S      S      H      H      H      H      H   
16      S      S      S      S      S      H      H      H      H      H   
17      S      S      S      S      S      S      S      S      S      S   
18      S      S      S      S      S      S      S      S      S      S   
19      S      S      S      S      S      S      S      S      S      S   
20      S      S      S      S      S      S      S      S      S      S   
21      S      S      S      S      S      S      S      S      S      S   

Soft Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2   -0.283 -0.241 -0.186 -0.119 -0.114 -0.462 -0.508 -0.517 -0.539 -0.662 
A3   -0.284 -0.240 -0.170 -0.116 -0.112 -0.460 -0.505 -0.527 -0.538 -0.661 
A4   -0.283 -0.224 -0.166 -0.113 -0.109 -0.458 -0.514 -0.526 -0.538 -0.659 
A5   -0.266 -0.221 -0.164 -0.111 -0.108 -0.468 -0.515 -0.525 -0.537 -0.659 
A6   -0.132 -0.093 -0.037  0.005  0.010 -0.090 -0.385 -0.407 -0.418 -0.483 
A7    0.136  0.167  0.204  0.222  0.262  0.412  0.121 -0.179 -0.186 -0.101 
A8    0.402  0.420  0.415  0.461  0.482  0.615  0.608  0.288  0.064  0.290 
A9    0.656  0.644  0.654  0.682  0.694  0.773  0.785  0.766  0.555  0.681 

Soft Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2    0.039  0.071  0.110  0.159  0.168  0.107  0.039 -0.014 -0.090 -0.184 
A3    0.017  0.044  0.091  0.137  0.147  0.060  0.035 -0.060 -0.124 -0.216 
A4   -0.012  0.022  0.061  0.108  0.120  0.034 -0.035 -0.114 -0.172 -0.256 
A5   -0.032 -0.003  0.038  0.082  0.116 -0.024 -0.084 -0.167 -0.229 -0.296 
A6    0.007  0.036  0.077  0.140  0.133  0.060 -0.065 -0.135 -0.189 -0.242 
A7    0.065  0.093  0.156  0.175  0.192  0.175  0.047 -0.087 -0.140 -0.160 
A8    0.120  0.173  0.187  0.227  0.241  0.222  0.158  0.005 -0.087 -0.081 
A9    0.191  0.196  0.230  0.268  0.280  0.243  0.172  0.096  0.007 -0.008 

Soft Chart - Player Expected Gains per original unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2   -0.042  0.028  0.115  0.212  0.230 -0.157 -0.312 -0.373 -0.478 -0.586 
A3   -0.047  0.011  0.109  0.204  0.222 -0.175 -0.254 -0.394 -0.479 -0.588 
A4   -0.070  0.003  0.085  0.175  0.201 -0.141 -0.314 -0.422 -0.495 -0.613 
A5   -0.082 -0.019  0.063  0.148  0.217 -0.189 -0.333 -0.452 -0.536 -0.649 
A6    0.013  0.074  0.155  0.280  0.266  0.014 -0.230 -0.345 -0.433 -0.522 
A7    0.128  0.189  0.313  0.349  0.385  0.240 -0.015 -0.254 -0.322 -0.359 
A8    0.237  0.346  0.373  0.453  0.483  0.325  0.190 -0.060 -0.226 -0.200 
A9    0.380  0.392  0.459  0.536  0.560  0.351  0.230  0.111 -0.055 -0.055 

Soft Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2      H      H      D      D      D      H      H      H      H      H   
A3      H      H      D      D      D      H      H      H      H      H   
A4      H      H      D      D      D      H      H      H      H      H   
A5      H      H      D      D      D      H      H      H      H      H   
A6      D      D      D      D      D      H      H      H      H      H   
A7      S      D      D      D      D      S      S      H      H      S   
A8      S      S      S      S      D      S      S      S      S      S   
A9      S      S      S      S      S      S      S      S      S      S   

Soft Chart - Player Strategy (Round >= 2, No Doubling)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
12      H      H      H      H      H      H      H      H      H      H   
13      H      H      H      H      H      H      H      H      H      H   
14      H      H      H      H      H      H      H      H      H      H   
15      H      H      H      H      H      H      H      H      H      H   
16      H      H      H      H      H      H      H      H      H      H   
17      H      H      H      H      H      H      H      H      H      H   
18      S      S      S      S      S      S      S      H      H      S   
19      S      S      S      S      S      S      S      S      S      S   
20      S      S      S      S      S      S      S      S      S      S   
21      S      S      S      S      S      S      S      S      S      S   

Pairs Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA   -0.274 -0.232 -0.178 -0.130 -0.104 -0.452 -0.500 -0.511 -0.531 -0.663 
22   -0.291 -0.251 -0.192 -0.107 -0.125 -0.471 -0.515 -0.523 -0.547 -0.660 
33   -0.295 -0.246 -0.160 -0.101 -0.119 -0.467 -0.510 -0.542 -0.546 -0.660 
44   -0.290 -0.214 -0.152 -0.095 -0.114 -0.463 -0.529 -0.543 -0.547 -0.656 
55   -0.256 -0.206 -0.146 -0.090 -0.112 -0.484 -0.531 -0.541 -0.545 -0.653 
66   -0.262 -0.211 -0.152 -0.102 -0.165 -0.493 -0.536 -0.549 -0.552 -0.617 
77   -0.268 -0.219 -0.164 -0.156 -0.174 -0.502 -0.539 -0.555 -0.510 -0.631 
88   -0.275 -0.228 -0.215 -0.165 -0.178 -0.503 -0.551 -0.516 -0.518 -0.644 
99    0.137  0.123  0.167  0.203  0.265  0.401  0.065 -0.196 -0.133 -0.055 
TT    0.627  0.636  0.645  0.674  0.697  0.765  0.783  0.744  0.583  0.650 

Pairs Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA    0.095  0.120  0.142  0.182  0.200  0.158  0.093 -0.003 -0.048 -0.075 
22   -0.113 -0.082 -0.035  0.036  0.032 -0.092 -0.141 -0.222 -0.277 -0.395 
33   -0.153 -0.118 -0.047  0.008  0.014 -0.164 -0.231 -0.310 -0.346 -0.444 
44   -0.013  0.028  0.098  0.154  0.175  0.111 -0.055 -0.206 -0.246 -0.268 
55    0.224  0.254  0.295  0.347  0.362  0.279  0.207  0.119  0.032  0.042 
66   -0.253 -0.222 -0.190 -0.162 -0.194 -0.265 -0.322 -0.386 -0.386 -0.411 
77   -0.406 -0.388 -0.369 -0.370 -0.367 -0.389 -0.408 -0.475 -0.516 -0.510 
88   -0.454 -0.450 -0.461 -0.453 -0.397 -0.374 -0.426 -0.487 -0.512 -0.490 
99   -0.627 -0.638 -0.597 -0.590 -0.587 -0.566 -0.566 -0.595 -0.626 -0.621 
TT   -0.847 -0.846 -0.846 -0.846 -0.845 -0.843 -0.843 -0.842 -0.840 -0.882 

Pairs Chart - Player Expected Gains per original unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA   -0.019  0.055  0.137  0.216  0.248 -0.137 -0.296 -0.421 -0.468 -0.591 
22   -0.582 -0.501 -0.384 -0.214 -0.249 -0.942 -1.030 -1.047 -1.094 -1.320 
33   -0.567 -0.472 -0.302 -0.184 -0.215 -0.871 -1.000 -1.065 -1.072 -1.298 
44   -0.185 -0.082  0.044  0.162  0.193 -0.108 -0.447 -0.701 -0.741 -0.802 
55    0.446  0.510  0.590  0.695  0.724  0.466  0.323  0.175  0.014  0.042 
66   -0.505 -0.444 -0.380 -0.325 -0.387 -0.599 -0.711 -0.817 -0.803 -0.823 
77   -0.813 -0.777 -0.738 -0.741 -0.734 -0.823 -0.858 -0.978 -1.035 -1.019 
88   -0.908 -0.900 -0.922 -0.906 -0.793 -0.747 -0.853 -0.974 -1.024 -0.980 
99   -1.255 -1.277 -1.194 -1.181 -1.173 -1.132 -1.133 -1.189 -1.252 -1.242 
TT   -1.693 -1.693 -1.693 -1.691 -1.690 -1.686 -1.685 -1.684 -1.681 -1.764 

Pairs Chart - Player Expected Gains per original unit (Split)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA    1.192  1.223  1.265  1.321  1.344  1.308  1.201  1.039  0.860  0.921 
22   -0.128 -0.070 -0.007  0.128  0.126 -0.054 -0.213 -0.383 -0.463 -0.566 
33   -0.202 -0.128  0.009  0.117  0.112 -0.115 -0.265 -0.418 -0.509 -0.579 
44   -0.236 -0.127 -0.013  0.095  0.083 -0.223 -0.343 -0.493 -0.580 -0.623 
55   -0.232 -0.150 -0.038  0.068  0.056 -0.299 -0.448 -0.608 -0.685 -0.695 
66   -0.219 -0.135 -0.028  0.068 -0.011 -0.270 -0.413 -0.570 -0.652 -0.660 
77   -0.163 -0.084  0.016  0.039  0.053 -0.123 -0.423 -0.564 -0.634 -0.635 
88    0.017  0.077  0.106  0.188  0.234  0.202 -0.100 -0.430 -0.464 -0.378 
99    0.170  0.170  0.253  0.339  0.359  0.341  0.179 -0.112 -0.268 -0.109 
TT    0.412  0.465  0.518  0.596  0.619  0.576  0.447  0.276  0.146  0.140 

Pairs Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA      P      P      P      P      P      P      P      P      P      P   
22      H      P      P      P      P      P      H      H      H      H   
33      H      H      P      P      P      P      H      H      H      H   
44      H      H      H      D      D      H      H      H      H      H   
55      D      D      D      D      D      D      D      D      H      D   
66      P      P      P      P      P      H      H      H      H      H   
77      P      P      P      P      P      P      H      H      S      H   
88      P      P      P      P      P      P      P      P      P      P   
99      P      P      P      P      P      S      P      P      S      S   
TT      S      S      S      S      S      S      S      S      S      S   

Simulation for Year 1:

After playing 50 times a day for 365 days:
Winning days   : 170
Losing days    : 185
Breakeven days : 10
Biggest win    : 20
Biggest loss   : 20.5
Total loss     : 263
Total staked   : 20498
Loss % staked  : 1.283

Simulation for Year 2:

After playing 50 times a day for 365 days:
Winning days   : 171
Losing days    : 184
Breakeven days : 10
Biggest win    : 18.5
Biggest loss   : 22.5
Total loss     : 332.5
Total staked   : 20515
Loss % staked  : 1.621

Simulation for Year 3:

After playing 50 times a day for 365 days:
Winning days   : 154
Losing days    : 204
Breakeven days : 7
Biggest win    : 28
Biggest loss   : 24
Total loss     : 339.5
Total staked   : 20461
Loss % staked  : 1.659

Simulation for Year 4:

After playing 50 times a day for 365 days:
Winning days   : 164
Losing days    : 191
Breakeven days : 10
Biggest win    : 26.5
Biggest loss   : 26.5
Total loss     : 211.5
Total staked   : 20587
Loss % staked  : 1.027

Simulation for Year 5:

After playing 50 times a day for 365 days:
Winning days   : 175
Losing days    : 186
Breakeven days : 4
Biggest win    : 18
Biggest loss   : 21.5
Total loss     : 162
Total staked   : 20493
Loss % staked  : 0.791

Simulation for Year 6:

After playing 50 times a day for 365 days:
Winning days   : 179
Losing days    : 177
Breakeven days : 9
Biggest win    : 25.5
Biggest loss   : 26
Total win      : 55.5
Total staked   : 20495
Win % staked   : 0.271

Simulation for Year 7:

After playing 50 times a day for 365 days:
Winning days   : 162
Losing days    : 190
Breakeven days : 13
Biggest win    : 26.5
Biggest loss   : 27
Total loss     : 274
Total staked   : 20545
Loss % staked  : 1.334

Simulation for Year 8:

After playing 50 times a day for 365 days:
Winning days   : 165
Losing days    : 192
Breakeven days : 8
Biggest win    : 21
Biggest loss   : 25.5
Total loss     : 329
Total staked   : 20536
Loss % staked  : 1.602

Simulation for Year 9:

After playing 50 times a day for 365 days:
Winning days   : 169
Losing days    : 186
Breakeven days : 10
Biggest win    : 18.5
Biggest loss   : 26.5
Total loss     : 241
Total staked   : 20549
Loss % staked  : 1.173

Simulation for Year 10:

After playing 50 times a day for 365 days:
Winning days   : 173
Losing days    : 183
Breakeven days : 9
Biggest win    : 23
Biggest loss   : 19
Total loss     : 370
Total staked   : 20541
Loss % staked  : 1.801

Nim

Translation of: Go
import random, sequtils, strformat, strutils

type

  Card = 1..10

  Deck = object
    size: int
    cards: array[Card, int]

  HandKind {.pure.} = enum Hard, Soft, Pair

  Action {.pure.} = enum Stand, Hit, Double, Split

  ActionGain = tuple[action: Action; gain: float]


var

  # Computed strategy tables.
  hTable: array[15, array[10, Action]]    # Hard strategy table (round 1).
  sTable: array[8, array[10, Action]]     # Soft strategy table (round 1).
  pTable: array[10, array[10, Action]]    # Pairs strategy table (round 1).
  hTable2: array[18, array[10, Action]]   # Hard strategy table (round >= 2, no doubling).
  sTable2: array[10, array[10, Action]]   # Soft strategy table (round >= 2, no doubling).



func initDeck(): Deck =
  Deck(size: 52, cards: [4, 4, 4, 4, 4, 4, 4, 4, 4, 16])


func `<`(ag1, ag2: ActionGain): bool = ag1.gain < ag2.gain


func dealerProbs(upcard: Card; startDeck: Deck): array[7, float] =
  ## Returns probabilities of dealer eventually getting:
  ## 0: 17, 1: 18, 2: 19, 3: 20, 4: 21 (non-blackjack), 5: blackjack (nil), 6: bust.
  ## It is assumed that the dealer has already checked for blackjack, that one deck is used
  ## and that the dealer stands on 'soft' 17.

  var
    res: array[7, float]    # Results.
    decks: array[9, Deck]   # Decks for each level.
    scores: array[9, int]   # Scores for each level.
    elevens: array[9, int]  # Number of aces for each level scored as 11.
    probs: array[9, float]  # Probabilities for each level.

  decks[0] = startDeck
  scores[0] = upCard
  if upcard == 1:
    # An ace.
    scores[0] = 11
    elevens[0] = 1

  probs[0] = 1.0

  proc drawCard(lev: Natural) =
    ## Recursive closure.
    for c in Card.low..Card.high:
      if decks[lev].cards[c] == 0: continue   # Card no longer present in deck.

      # Temporary variables for current level.
      var
        deck = decks[lev]
        score = scores[lev]
        eleven = elevens[lev]
        prob = probs[lev]

      inc score, c  # Add card to score.
      if c == 1:
        # Score all aces initially as 11.
        inc score, 10
        inc eleven

      prob *= deck.cards[c] / deck.size
      if score > 21 and eleven > 0:
        dec score, 10   # Bust but can demote an ace.
        dec eleven

      if lev == 0 and (upCard == 1 and c == 10 or upCard == 10 and c == 1):
        res[5] += prob          # Blackjack, allow for now.
      elif score in 17..21:
        res[score-17] += prob   # 17 to (non-blackjack) 21.
      elif score > 21 and eleven == 0:
        res[6] += prob          # Bust.
      else:
        dec deck.cards[c]   # Remove card from deck.
        dec deck.size
        let lev = lev + 1
        decks[lev] = deck
        scores[lev] = score
        elevens[lev] = eleven
        probs[lev] = prob
        drawCard(lev)

  drawCard(0)
  # But can't have blackjack, so adjust probabilities accordingly.
  let pnbj = 1 - res[5]
  for i in 0..6: res[i] /= pnbj

  res[5] = 0
  result = res


proc dealerChart =
  ## Print chart of dealer probabilities (as a check against an external source).
  echo "Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules"
  echo "Up Card     17        18        19        20        21       Bust"
  echo "———————————————————————————————————————————————————————————————————"
  var deck = initDeck()
  deck.size = 51
  for uc in Card.low..Card.high:
    var deck2 = deck
    dec deck2.cards[uc]
    let dp = dealerProbs(uc, deck2)
    stdout.write if uc > 1: &"{uc:3}    " else: "Ace    "
    for i in [0, 1, 2, 3, 4, 6]: stdout.write &"  {dp[i]:.6f}"
    echo()


func calcGain(pscore: int; dp: openArray[float]): float =
  ## Calculates gain per unit staked for a given scenario (helper function).
  case pscore
  of 17:
    result += dp[6]                                 # Dealer is bust.
    result -= dp[1] + dp[2] + dp[3] + dp[4]         # Dealer has 18 to 21.
  of 18:
    result += dp[0] + dp[6]                         # Dealer has 17 or is bust.
    result -= dp[2] + dp[3] + dp[4]                 # Dealer has 19 to 21.
  of 19:
    result += dp[0] + dp[1] + dp[6]                 # Dealer has 17, 18 or is bust.
    result -= dp[3] + dp[4]                         # Dealer has 20 or 21.
  of 20:
    result += dp[0] + dp[1] + dp[2] + dp[6]         # Dealer has 17 to 19 or is bust.
    result -= dp[4]                                 # Dealer has (non-blackjack) 21.
  of 21:
    result += dp[0] + dp[1] + dp[2] + dp[3] + dp[6] # Dealer has 17 to 20 or is bust.
  of 22: # Notional.
    result += 1.5                                   # Player blackjack.
  of 23: # Notional.
    result -= 1       # Player bust, loses stake irrespective of what dealer has.
  else: # Player has less than 17
    result += dp[6]                                 # Dealer is bust.
    result -= 1 - dp[6]                             # Dealer isn't bust.


func playerGain(card1, card2, uc: Card; startDeck: Deck): float =
  ## Returns player's expected gain per unit staked after hitting once and then standing.
  let deck = startDeck
  var
    score = card1 + card2
    eleven = false
  if card1 == 1 or card2 == 1:
    inc score, 10
    eleven = true

  for c in Card.low..Card.high:
    # Get another card.
    if deck.cards[c] == 0: continue   # Card no longer present in deck.
    # Temporary variables for current card.
    var
      deck2 = deck
      score2 = score
      eleven2 = eleven

    inc score2, c   # Add card to score.
    if c == 1:
      # Score all aces initially as 11.
      inc score2, 10
      eleven2 = true

    let prob = deck2.cards[c] / deck2.size
    dec deck2.cards[c]
    dec deck2.size
    if score2 > 21 and eleven2:
      dec score2, 10  # Bust but can demote an ace.
    if score2 <= 21:
      let dp = dealerProbs(uc, deck2)
      result += calcGain(score2, dp) * prob
    else:
      # Bust.
      result -= prob


func playerGain2(card1, card2, uc: Card; startDeck: Deck): float =
  ## Return player's expected gain per unit staked after hitting once
  ## and then continuing in accordance with the tables for rounds >= 2.

  var
    eg = 0.0                # Result.
    decks: array[9, Deck]   # Decks for each level.
    scores: array[9, int]   # Scores for each level.
    elevens: array[9, int]  # Number of aces for each level scored as 11.
    probs: array[9, float]  # Probabilities for each level.
  decks[0] = startDeck
  scores[0] = card1 + card2
  if card1 == 1 or card2 == 1:
    inc scores[0], 10
    elevens[0] = 1

  probs[0] = 1.0

  proc drawCard(lev: Natural) =
    ## Recursive closure.
    for c in Card.low..Card.high:
      if decks[lev].cards[c] == 0: continue   # Card no longer present in deck.

      # Temporary variables for current level.
      var
        deck = decks[lev]
        score = scores[lev]
        eleven = elevens[lev]
        prob = probs[lev]

      inc score, c  # Add card to score.
      if c == 1:
        # Score all aces initially as 11.
        inc score, 10
        inc eleven

      prob *= deck.cards[c] / deck.size
      if score > 21 and eleven > 0:
        dec score, 10   # Bust but can demote an ace.
        dec eleven

      dec deck.cards[c] # Remove card from deck.
      dec deck.size

      if (eleven == 0 and (score >= 17 or score >= 13 and uc < 7) or
          eleven == 0 and score == 12 and uc >= 4 and  uc <= 6 or
          eleven > 0 and score == 18 and uc != 9 and  uc != 10 or
          eleven > 0 and score >= 19) and score <= 21:
          let dp = dealerProbs(uc, deck)
          eg += calcGain(score, dp) * prob
      elif score > 21 and eleven == 0:
        # Bust.
        eg -= prob
      else:
        let lev = lev + 1
        decks[lev] = deck
        scores[lev] = score
        elevens[lev] = eleven
        probs[lev] = prob
        drawCard(lev)

  drawCard(0)
  result = eg


func stand(card1, card2: Card): array[10, float] =
  ## Return player's expected gains per unit staked, for each dealer up-card, after standing.

  var deck = initDeck()
  dec deck.cards[card1]
  dec deck.cards[card2]
  deck.size = 50
  var pscore = card1 + card2    # Player score.
  if card1 == 1 or card2 == 1:
    inc pscore, 10

  for uc in Card.low..Card.high:  # Dealer's up-card.
    var deck2 = deck
    dec deck2.cards[uc]
    dec deck2.size
    let dp = dealerProbs(uc, deck2)
    let eg = calcGain(pscore, dp)   # Expected gain for this up-card.
    if uc > 1:
      result[uc-2] = eg
    else: # Dealer has Ace.
      result[9] = eg  # Ace comes last in tables.


func hit(card1, card2: Card; once: bool): array[10, float] =
  ## Return player's expected gains per unit staked, for each dealer
  ## up-card, after hitting once and then either standing (once == true)
  ## or continuing as per the round >= 2 tables (once == false).
  var deck = initDeck()
  dec deck.cards[card1]
  dec deck.cards[card2]
  deck.size = 50
  for uc in Card.low..Card.high:  # Dealer's up-card.
    var deck2 = deck
    dec deck2.cards[uc]
    deck2.size = 49
    # Player's expected gain for this up-card.
    let peg = if once: playerGain(card1, card2, uc, deck2)
              else: playerGain2(card1, card2, uc, deck2)
    if uc > 1:
      result[uc-2] = peg
    else: # Dealer has Ace.
      result[9] = peg


func double(card1, card2: Card): array[10, float] =
  ## Return player's expected gains per unit originally staked,
  ## for each dealer up-card, after doubling i.e. hitting once
  ## and then standing with a doubled stake.
  result = hit(card1, card2, true)   # Hit once and then stand.
  for item in result.mitems:
    item *= 2


proc split(card: Card): array[10, float] =
  ## Return player's expected gains per unit originally staked, for each dealer up-card, after
  ## splitting a pair and doubling the stake, getting a second card for each hand and then
  ## continuing in accordance with the rounds >= 2 tables. It is assumed that a player cannot
  ## double or re-split following a split. It is also assumed (in the interests of simplicity)
  ## that the expected gains for each split hand (after calculating the gains for the first hand
  ## as though the second hand is not completed) are exactly the same.
  var deck = initDeck()
  dec deck.cards[card], 2   # Must be a pair.
  deck.size = 50

  # Now play a single hand.
  var score: int = card
  var eleven = 0
  if card == 1:
    score = 11
    eleven = 1

  for uc in Card.low..Card.high:  # Collect results for each dealer up-card.
    if deck.cards[uc] == 0: continue   # Card no longer present in deck.

    var deck2 = deck
    dec deck2.cards[uc]
    dec deck2.size
    var ix = uc - 2
    if ix == -1: ix = 9   # In tables ace comes last.
    var peg: float  # Player expected gain for this up-card.
    # Get second player card.
    for c in Card.low..Card.high:
      if deck2.cards[c] == 0: continue   # Card no longer present in deck.

      let prob = deck2.cards[c] / deck2.size
      var deck3 = deck2
      dec deck3.cards[c]
      dec deck3.size
      var score2 = score + c
      var eleven2 = eleven
      if c == 1:
        # Score all aces initially as 11.
        inc score2, 10
        inc eleven2

      if score2 == 21:
        # Player has blackjack & we know dealer hasn't.
        peg += 1.5 * prob
        continue

      if score2 > 21 and eleven2 > 0:
        dec score2, 10  # Bust but can demote an ace.
        dec eleven2

      let action = if eleven2 > 0: sTable2[score2-12][ix] # Use soft strategy table, no doubling.
                   else:  hTable2[score2-4][ix]           # Use hard strategy table, no doubling
      let peg2 =  if action == Stand: calcGain(score2, dealerProbs(uc, deck3))
                  else: playerGain2(card, c, uc, deck3)
      peg += peg2 * prob

    if uc > 1:
      result[uc-2] = peg * 2    # Allow for both hands in overall results.
    else:
      result[9] = peg * 2       # Ditto.


func bestAction(ags: openArray[ActionGain]): Action =
  ## Return the action with the highest expected gain.
  ags[ags.maxIndex()].action


proc printHeader(title: string) =
  ## Print title and header for a given chart.
  echo title
  echo "P/D     2      3      4      5      6      7      8      9      T      A"
  echo "——————————————————————————————————————————————————————————————————————————"


proc printPair(c: Card) =
  ## Print header for a pair of cards.
  stdout.write if c == 1: "AA   " elif c == 10: "TT   " else: &"{c}{c}   "


func dealerPlay(pscore: int, next: var int; cards, d: openArray[Card]): float =
  ## Simulate a dealer's play for a given player's hand and state of deck.
  ## Return the player's gain (positive or negative) per unit staked.
  var dscore = d[0] + d[1]
  var aces = 0
  if d[0] == 1 or d[1] == 1:
    # Dealer has an ace.
    inc dscore, 10
    inc aces

  while true:
    if dscore > 21 and aces > 0:
      dec dscore, 10    # Bust but we can demote an ace.
      dec aces
    if dscore > 21:
      return 1      # Dealer is bust and player gains stake.

    if dscore >= 17:
      # Dealer must stick on 17 or above, hard or not.
      if dscore > pscore:
        return -1   # Dealer wins and player loses stake.
      if dscore == pscore:
        break       # Player breaks even.
      return 1      # Dealer loses and player gains stake.

    let nc = cards[next]  # Get new card from pack.
    inc next
    inc dscore, nc
    if nc == 1:
      # Count aces initially as 11.
      inc dscore, 10
      inc aces


proc playerPlay(): (float, float) =
  ## Simulate the playing of a random player's hand according to the strategy tables.
  ## Return both the gain (positive or negative) and the stake (1 or 2).

  var perm = toSeq(0..51)
  perm.shuffle()
  var cards: array[52, Card]
  for i, r in perm:
    var card = r div 4 + 1
    if card > 10: card = 10
    cards[i] = card

  var p, d: seq[Card]   # Player and dealer hands.
  # Initial deal.
  p.add cards[0..1]
  d.add cards[2..3]
  var next = 4    # Index of next card to be dealt.

  # Check if dealer and/or player have blackjack.
  let dbj = d[0] == 1 and d[1] == 10 or d[0] == 10 and d[1] == 1
  let pbj = p[0] == 1 and p[1] == 10 or p[0] == 10 and p[1] == 1
  if dbj:
    if pbj: return (0.0, 1.0) # Player neither wins nor loses.
    else: return (-1.0, 1.0)  # Player loses stake.
  if pbj: return (1.5, 1.0)   # Player wins 1.5 x stake.

  var uc = d[0] - 2       # Dealer's up-card as index to access tables.
  if uc < 0: uc = 9       # Ace is at last place in tables.

  var stake = 1.0             # Player's initial stake.
  var fscores: array[2, int]  # Final player scores (one or, after split, two hands).
  var action: Action
  var score, aces: int

  proc h(hand: int) =
    ## Process a hit.
    while true:
      let nc = cards[next]  # Get new card from pack.
      inc next
      inc score, nc
      if nc == 1:
        # Count aces initially as 11.
        inc score, 10
        inc aces
      if score > 21 and aces > 0:
        dec score, 10   # Bust but we can demote an ace.
        dec aces
      if score > 21:
        fscores[hand] = 22  # Player is bust and loses stake.
        break
      if action == Double:
        fscores[hand] = score
        break
      # Get further strategy and act accordingly.
      action = if aces == 0: hTable2[score-4][uc] else: sTable2[score-12][uc]
      if action == Stand:
        fscores[hand] = score
        break

  score = p[0] + p[1]
  # Get kind of player hand: hard, soft, pair.
  let kind = if p[0] == p[1]: Pair elif p[0] == 1 or p[1] == 1: Soft else: Hard

  case kind
  of Hard:
    action = hTable[score-5][uc]
  of Soft:  # includes one ace.
    let othercard = if p[0] == 1: p[1] else: p[0]
    inc score, 10
    aces = 1
    action = sTable[otherCard-2][uc]
  of Pair:
    if p[0] == 1:
      # Pair of aces.
      inc score, 10
      aces = 2
    action = pTable[p[0]-1][uc]

  case action
  of Stand:
    fscores[0] = score
  of Hit:
    h(0)
  of Double:
    h(0)
    stake = 2
  of Split:
    for hand in 0..1:
      score = p[0]
      aces = 0
      if score == 1:
        # Count aces initially as 11.
        score = 11
        inc aces
      h(hand)

  var sum = 0.0
  if fscores[0] < 22:
    sum += dealerPlay(fscores[0], next, cards, d) * stake
  else:
    sum -= 1 * stake  # This hand is bust.
  if fscores[1] > 0:
    # Pair.
    if fscores[1] < 22:
      sum += dealerPlay(fscores[1], next, cards, d)
    else:
      sum -= 1
    stake = 2

  result = (sum, stake)


proc simulate(perDay, days: int) =
  ## Simulate "perDay" blackjack games for "days" days.

  var
    winDays, loseDays, evenDays = 0
    bigWin, bigLoss = 0.0
    totalGain, totalStake = 0.0

  for d in 1..days:
    var dailyGain, dailyStake = 0.0
    for p in 1..perDay:
      let (gain, stake) = playerPlay()
      dailyGain += gain
      dailyStake += stake

    if dailyGain > 0: inc winDays
    elif dailyGain < 0: inc loseDays
    else: inc evenDays

    if dailyGain > bigWin: bigWin = dailyGain
    elif -dailyGain > bigLoss: bigLoss = -dailyGain

    totalGain += dailyGain
    totalStake += dailyStake

  echo &"\nAfter playing {perDay} times a day for {days} days:"
  echo "Winning days:   ", winDays
  echo "Losing days:    ", loseDays
  echo "Breakeven days: ", evenDays
  echo "Biggest win:    ", bigWin
  echo "Biggest loss:   ", bigLoss
  if totalGain < 0:
    echo "Total loss:     ", -totalGain
    echo "Total staked:   ", totalStake
    echo &"Loss % staked:  {-totalGain/totalStake*100:0.3f}\n"
  else:
    echo "Total win:      ", totalGain
    echo "Total staked:   ", totalStake
    echo &"Win % staked:  {totalGain/totalStake*100:0.3f}\n"


proc main() =

  # Print dealer probabilities chart.
  dealerChart()

  # For hard scores (i.e. different cards, no aces).
  const Tuples = [(2, 3),
                  (2, 4),
                  (2, 5), (3, 4),
                  (2, 6), (3, 5),
                  (2, 7), (3, 6), (4, 5),
                  (2, 8), (3, 7), (4, 6),
                  (2, 9), (3, 8), (4, 7), (5, 6),
                  (2, 10), (3, 9), (4, 8), (5, 7),
                  (3, 10), (4, 9), (5, 8), (6, 7),
                  (4, 10), (5, 9), (6, 8),
                  (5, 10), (6, 9), (7, 8),
                  (6, 10), (7, 9),
                  (7, 10), (8, 9),
                  (8, 10),
                  (9, 10)]

  # Number of tuples for each player score from 5 to 19.
  const Counts = [float 1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1]

  # Expected gains for each player score & for each dealer up-card.
  var
    segs: array[15, array[10, float]]  # if stands.
    hegs: array[15, array[10, float]]  # if hits.
    degs: array[15, array[10, float]]  # if doubles.

  for t in Tuples:
    let i = t[0] + t[1]
    let sg = stand(t[0], t[1])
    let hg = hit(t[0], t[1], false)
    let dg = double(t[0], t[1])
    for j in 0..9:
      segs[i-5][j] += sg[j]
      hegs[i-5][j] += hg[j]
      degs[i-5][j] += dg[j]

  # Calculate the average per tuple for each score.
  for i in 0..14:
    for j in 0..9:
      segs[i][j] /= Counts[i]
      hegs[i][j] /= Counts[i]
      degs[i][j] /= Counts[i]

  printHeader("\nHard Chart - Player Expected Gains per unit (Stand)")
  for i in 5..19:
    stdout.write &"{i:2}   "
    for j in 0..9:
      stdout.write &"{segs[i-5][j]: 0.3f} "
    echo()

  printHeader("\nHard Chart - Player Expected Gains per unit (Hit)")
  for i in 5..19:
    stdout.write &"{i:2}   "
    for j in 0..9:
      stdout.write &"{hegs[i-5][j]: 0.3f} "
    echo()

  printHeader("\nHard Chart - Player Expected Gains per unit (Double)")
  for i in 5..19:
    stdout.write &"{i:2}   "
    for j in 0..9:
      stdout.write &"{degs[i-5][j]: 0.3f} "
    echo()

  printHeader("\nHard Chart - Player Strategy (Round 1)")
  for i in 5..19:
    stdout.write &"{i:2}   "
    for j in 0..9:
      let ags = [(Stand, segs[i-5][j]), (Hit, hegs[i-5][j]), (Double, degs[i-5][j])]
      let action = bestAction(ags)
      hTable[i-5][j] = action
      stdout.write &"{action:^6} "
    echo()

  # For hard scores (no aces) - after round 1 (no doubling or splitting).
  # Based on hard table figures (round 1) with scores of 4, 20, and 21 added.
  var
    segs2: array[18, array[10, float]]   # Expected gains if stands.
    hegs2: array[18, array[10, float]]   # Expected gains if hits.
  for i in 5..19:
    segs2[i-4] = segs[i-5]
    hegs2[i-4] = hegs[i-5]

  let sg4 = stand(2, 2)
  let hg4 = hit(2, 2, false)
  let sg20 = stand(10, 10)
  let hg20 = hit(10, 10, false)
  let sg21 = stand(1, 10)
  let hg21 = hit(1, 10, false)
  for j in 0..9:
    segs2[0][j] += sg4[j]
    hegs2[0][j] += hg4[j]
    segs2[16][j] += sg20[j]
    hegs2[16][j] += hg20[j]
    segs2[17][j] += sg21[j]
    hegs2[17][j] += hg21[j]

  printHeader("\nHard Chart - Player Strategy (Round >= 2, No Doubling)")
  for i in 4..21:
    stdout.write &"{i:2}   "
    for j in 0..9:
      var action = Stand
      if hegs2[i-4][j] > segs2[i-4][j]: action = Hit
      hTable2[i-4][j] = action
      stdout.write &"{action:^6} "
    echo()

  # For soft scores (i.e. including exactly one ace).

  # Expected gains for each player second card (2 to 9) & for each dealer up-card.
  var
    segs3: array[8, array[10, float]]   # if stands.
    hegs3: array[8, array[10, float]]   # if hits.
    degs3: array[8, array[10, float]]   # if doubles.
  for c in 2..9:
    let sg = stand(1, c)
    let hg = hit(1, c, false)
    let dg = double(1, c)
    for j in 0..9:
      segs3[c-2][j] += sg[j]
      hegs3[c-2][j] += hg[j]
      degs3[c-2][j] += dg[j]

  printHeader("\nSoft Chart - Player Expected Gains per unit (Stand)")
  for c in 2..9:
    stdout.write &"A{c}   "
    for j in 0..9:
      stdout.write &"{segs3[c-2][j]: 0.3f} "
    echo()


  printHeader("\nSoft Chart - Player Expected Gains per unit (Hit)")
  for c in 2..9:
    stdout.write &"A{c}   "
    for j in 0..9:
      stdout.write &"{hegs3[c-2][j]: 0.3f} "
    echo()


  printHeader("\nSoft Chart - Player Expected Gains per unit (Double)")
  for c in 2..9:
    stdout.write &"A{c}   "
    for j in 0..9:
      stdout.write &"{degs3[c-2][j]: 0.3f} "
    echo()


  printHeader("\nSoft Chart - Player Strategy (Round 1)")
  for c in 2..9:
    stdout.write &"A{c}   "
    for j in 0..9:
      let ags = [(Stand, segs3[c-2][j]), (Hit, hegs3[c-2][j]), (Double, degs3[c-2][j])]
      let action = bestAction(ags)
      sTable[c-2][j] = action
      stdout.write &"{action:^6} "
    echo()


  # For soft scores (at least one ace) - after round 1 (no doubling or splitting).
  # Based on soft table figures (round 1) with scores of 12 and 21 added.
  # Assumes one ace counted as 11.
  var
    segs4: array[10, array[10, float]]  # Expected gains if stands.
    hegs4: array[10, array[10, float]]  # Expected gains if hits.
  for i in 1..8:
    segs4[i] = segs3[i-1]
    hegs4[i] = hegs3[i-1]

  let sg12 = stand(1, 1)
  let hg12 = hit(1, 1, false)
  for j in 0..9:
    segs4[0][j] += sg12[j]
    hegs4[0][j] += hg12[j]
    segs4[9][j] += sg21[j]
    hegs4[9][j] += hg21[j]

  printHeader("\nSoft Chart - Player Strategy (Round >= 2, No Doubling)")
  for i in 12..21:
    stdout.write &"{i:2}   "
    for j in 0..9:
      var action = Stand
      if hegs4[i-12][j] > segs4[i-12][j]: action = Hit
      sTable2[i-12][j] = action
      stdout.write &"{action:^6} "
    echo()


  # For pairs.

  # Expected gains for each pair (A to 10) & for each dealer up-card.
  var
    segs5: array[10, array[10, float]]  # if stands.
    hegs5: array[10, array[10, float]]  # if hits.
    degs5: array[10, array[10, float]]  # if double.
    pegs5: array[10, array[10, float]]  # if split.
  for c in 1..10:
    let
      sg = stand(c, c)
      hg = hit(c, c, false)
      dg = double(c, c)
      pg = split(c)
    for j in 0..9:
      segs5[c-1][j] += sg[j]
      hegs5[c-1][j] += hg[j]
      degs5[c-1][j] += dg[j]
      pegs5[c-1][j] += pg[j]

  printHeader("\nPairs Chart - Player Expected Gains per unit (Stand)")
  for c in 1..10:
    printPair(c)
    for j in 0..9:
      stdout.write &"{segs5[c-1][j]: 0.3f} "
    echo()

  printHeader("\nPairs Chart - Player Expected Gains per unit (Hit)")
  for c in 1..10:
    printPair(c)
    for j in 0..9:
      stdout.write &"{hegs5[c-1][j]: 0.3f} "
    echo()

  printHeader("\nPairs Chart - Player Expected Gains per unit (Double)")
  for c in 1..10:
    printPair(c)
    for j in 0..9:
      stdout.write &"{degs5[c-1][j]: 0.3f} "
    echo()

  printHeader("\nPairs Chart - Player Expected Gains per unit (Split)")
  for c in 1..10:
    printPair(c)
    for j in 0..9:
      stdout.write &"{pegs5[c-1][j]: 0.3f} "
    echo()

  printHeader("\nPairs Chart - Player Strategy (Round 1)")
  for c in 1..10:
    printPair(c)
    for j in 0..9:
      let ags = [(Stand, segs5[c-1][j]), (Hit, hegs5[c-1][j]),
                 (Double, degs5[c-1][j]), (Split, pegs5[c-1][j])]
      let action = bestAction(ags)
      pTable[c-1][j] = action
      stdout.write &"{action:^6} "
    echo()

  randomize()

  # Do 10 years of simulation.
  for i in 1..10:
    echo &"Simulation for year {i}:"
    simulate(50, 365)

main()
Output:
Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules
Up Card     17        18        19        20        21       Bust
———————————————————————————————————————————————————————————————————
Ace      0.183786  0.190890  0.188680  0.191692  0.075137  0.169815
  2      0.138976  0.131762  0.131815  0.123948  0.120526  0.352973
  3      0.130313  0.130946  0.123761  0.123345  0.116047  0.375588
  4      0.130973  0.114163  0.120679  0.116286  0.115096  0.402803
  5      0.119687  0.123483  0.116909  0.104694  0.106321  0.428905
  6      0.166948  0.106454  0.107192  0.100705  0.097878  0.420823
  7      0.372345  0.138583  0.077334  0.078897  0.072987  0.259854
  8      0.130857  0.362989  0.129445  0.068290  0.069791  0.238627
  9      0.121886  0.103921  0.357391  0.122250  0.061109  0.233442
 10      0.124156  0.122486  0.124421  0.356869  0.039570  0.232499

Hard Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
 5   -0.293 -0.248 -0.176 -0.104 -0.122 -0.469 -0.513 -0.533 -0.546 -0.659 
 6   -0.291 -0.232 -0.172 -0.101 -0.119 -0.467 -0.522 -0.533 -0.547 -0.659 
 7   -0.283 -0.229 -0.163 -0.098 -0.117 -0.471 -0.521 -0.537 -0.547 -0.658 
 8   -0.276 -0.229 -0.162 -0.100 -0.130 -0.478 -0.523 -0.539 -0.549 -0.648 
 9   -0.277 -0.224 -0.160 -0.108 -0.134 -0.480 -0.528 -0.543 -0.542 -0.646 
10   -0.279 -0.227 -0.172 -0.120 -0.146 -0.484 -0.531 -0.539 -0.537 -0.644 
11   -0.277 -0.231 -0.175 -0.123 -0.147 -0.488 -0.529 -0.537 -0.537 -0.646 
12   -0.286 -0.241 -0.185 -0.134 -0.151 -0.485 -0.526 -0.535 -0.533 -0.655 
13   -0.282 -0.236 -0.181 -0.133 -0.156 -0.488 -0.529 -0.537 -0.534 -0.649 
14   -0.282 -0.238 -0.188 -0.134 -0.159 -0.489 -0.529 -0.533 -0.536 -0.651 
15   -0.280 -0.239 -0.190 -0.144 -0.169 -0.494 -0.531 -0.536 -0.531 -0.648 
16   -0.287 -0.250 -0.194 -0.152 -0.179 -0.495 -0.526 -0.540 -0.530 -0.648 
17   -0.147 -0.120 -0.074 -0.044 -0.011 -0.122 -0.405 -0.414 -0.402 -0.459 
18    0.119  0.144  0.164  0.202  0.268  0.389  0.096 -0.196 -0.155 -0.082 
19    0.385  0.384  0.404  0.448  0.484  0.610  0.577  0.264  0.103  0.308 

Hard Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
 5   -0.131 -0.098 -0.041  0.022  0.019 -0.119 -0.181 -0.262 -0.309 -0.417 
 6   -0.151 -0.107 -0.055  0.009  0.014 -0.164 -0.234 -0.305 -0.349 -0.443 
 7   -0.111 -0.072 -0.013  0.053  0.064 -0.069 -0.223 -0.295 -0.332 -0.401 
 8   -0.015  0.021  0.084  0.136  0.148  0.092 -0.056 -0.213 -0.253 -0.275 
 9    0.090  0.137  0.181  0.226  0.235  0.194  0.111 -0.052 -0.148 -0.128 
10    0.215  0.246  0.277  0.314  0.319  0.277  0.211  0.119  0.030  0.030 
11    0.272  0.296  0.327  0.361  0.362  0.293  0.222  0.146  0.107  0.113 
12   -0.256 -0.232 -0.206 -0.181 -0.179 -0.241 -0.308 -0.380 -0.378 -0.413 
13   -0.315 -0.293 -0.270 -0.252 -0.251 -0.301 -0.362 -0.389 -0.423 -0.440 
14   -0.363 -0.353 -0.337 -0.315 -0.313 -0.346 -0.366 -0.426 -0.455 -0.460 
15   -0.419 -0.414 -0.406 -0.392 -0.383 -0.351 -0.406 -0.466 -0.496 -0.487 
16   -0.461 -0.460 -0.454 -0.448 -0.397 -0.376 -0.426 -0.481 -0.510 -0.497 
17   -0.534 -0.536 -0.538 -0.493 -0.484 -0.450 -0.475 -0.529 -0.558 -0.546 
18   -0.633 -0.634 -0.597 -0.591 -0.586 -0.567 -0.565 -0.593 -0.624 -0.630 
19   -0.750 -0.713 -0.712 -0.709 -0.707 -0.699 -0.697 -0.698 -0.712 -0.740 

Hard Chart - Player Expected Gains per unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
 5   -0.587 -0.497 -0.352 -0.209 -0.244 -0.938 -1.025 -1.066 -1.093 -1.318 
 6   -0.560 -0.446 -0.324 -0.186 -0.215 -0.870 -1.023 -1.045 -1.074 -1.295 
 7   -0.415 -0.317 -0.186 -0.066 -0.059 -0.555 -0.851 -0.936 -0.956 -1.127 
 8   -0.165 -0.081  0.032  0.143  0.157 -0.140 -0.433 -0.697 -0.743 -0.802 
 9    0.114  0.193  0.286  0.380  0.393  0.175  0.007 -0.281 -0.442 -0.409 
10    0.428  0.492  0.554  0.628  0.638  0.446  0.313  0.164  0.007  0.025 
11    0.542  0.592  0.654  0.722  0.724  0.479  0.341  0.223  0.164  0.198 
12   -0.511 -0.463 -0.413 -0.362 -0.358 -0.556 -0.690 -0.811 -0.789 -0.827 
13   -0.630 -0.587 -0.541 -0.503 -0.503 -0.651 -0.775 -0.807 -0.862 -0.880 
14   -0.727 -0.706 -0.673 -0.630 -0.627 -0.723 -0.759 -0.862 -0.915 -0.921 
15   -0.838 -0.829 -0.812 -0.783 -0.767 -0.716 -0.826 -0.937 -0.992 -0.973 
16   -0.921 -0.920 -0.908 -0.896 -0.793 -0.751 -0.853 -0.961 -1.019 -0.995 
17   -1.069 -1.072 -1.076 -0.985 -0.967 -0.901 -0.949 -1.058 -1.116 -1.092 
18   -1.265 -1.267 -1.195 -1.182 -1.172 -1.135 -1.130 -1.186 -1.248 -1.260 
19   -1.499 -1.425 -1.423 -1.417 -1.414 -1.397 -1.395 -1.396 -1.425 -1.481 

Hard Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
 5    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
 6    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
 7    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
 8    Hit    Hit    Hit   Double Double  Hit    Hit    Hit    Hit    Hit   
 9   Double Double Double Double Double  Hit    Hit    Hit    Hit    Hit   
10   Double Double Double Double Double Double Double Double  Hit    Hit   
11   Double Double Double Double Double Double Double Double Double Double 
12    Hit    Hit   Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
13   Stand  Stand  Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
14   Stand  Stand  Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
15   Stand  Stand  Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
16   Stand  Stand  Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
17   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
18   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
19   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  

Hard Chart - Player Strategy (Round >= 2, No Doubling)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
 4    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
 5    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
 6    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
 7    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
 8    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
 9    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
10    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
11    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
12    Hit    Hit   Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
13   Stand  Stand  Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
14   Stand  Stand  Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
15   Stand  Stand  Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
16   Stand  Stand  Stand  Stand  Stand   Hit    Hit    Hit    Hit    Hit   
17   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
18   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
19   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
20   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
21   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  

Soft Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
A2   -0.283 -0.241 -0.186 -0.119 -0.114 -0.462 -0.508 -0.517 -0.539 -0.662 
A3   -0.284 -0.240 -0.170 -0.116 -0.112 -0.460 -0.505 -0.527 -0.538 -0.661 
A4   -0.283 -0.224 -0.166 -0.113 -0.109 -0.458 -0.514 -0.526 -0.538 -0.659 
A5   -0.266 -0.221 -0.164 -0.111 -0.108 -0.468 -0.515 -0.525 -0.537 -0.659 
A6   -0.132 -0.093 -0.037  0.005  0.010 -0.090 -0.385 -0.407 -0.418 -0.483 
A7    0.136  0.167  0.204  0.222  0.262  0.412  0.121 -0.179 -0.186 -0.101 
A8    0.402  0.420  0.415  0.461  0.482  0.615  0.608  0.288  0.064  0.290 
A9    0.656  0.644  0.654  0.682  0.694  0.773  0.785  0.766  0.555  0.681 

Soft Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
A2    0.039  0.071  0.110  0.159  0.168  0.107  0.039 -0.014 -0.090 -0.184 
A3    0.017  0.044  0.091  0.137  0.147  0.060  0.035 -0.060 -0.124 -0.216 
A4   -0.012  0.022  0.061  0.108  0.120  0.034 -0.035 -0.114 -0.172 -0.256 
A5   -0.032 -0.003  0.038  0.082  0.116 -0.024 -0.084 -0.167 -0.229 -0.296 
A6    0.007  0.036  0.077  0.140  0.133  0.060 -0.065 -0.135 -0.189 -0.242 
A7    0.065  0.093  0.156  0.175  0.192  0.175  0.047 -0.087 -0.140 -0.160 
A8    0.120  0.173  0.187  0.227  0.241  0.222  0.158  0.005 -0.087 -0.081 
A9    0.191  0.196  0.230  0.268  0.280  0.243  0.172  0.096  0.007 -0.008 

Soft Chart - Player Expected Gains per unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
A2   -0.042  0.028  0.115  0.212  0.230 -0.157 -0.312 -0.373 -0.478 -0.586 
A3   -0.047  0.011  0.109  0.204  0.222 -0.175 -0.254 -0.394 -0.479 -0.588 
A4   -0.070  0.003  0.085  0.175  0.201 -0.141 -0.314 -0.422 -0.495 -0.613 
A5   -0.082 -0.019  0.063  0.148  0.217 -0.189 -0.333 -0.452 -0.536 -0.649 
A6    0.013  0.074  0.155  0.280  0.266  0.014 -0.230 -0.345 -0.433 -0.522 
A7    0.128  0.189  0.313  0.349  0.385  0.240 -0.015 -0.254 -0.322 -0.359 
A8    0.237  0.346  0.373  0.453  0.483  0.325  0.190 -0.060 -0.226 -0.200 
A9    0.380  0.392  0.459  0.536  0.560  0.351  0.230  0.111 -0.055 -0.055 

Soft Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
A2    Hit    Hit   Double Double Double  Hit    Hit    Hit    Hit    Hit   
A3    Hit    Hit   Double Double Double  Hit    Hit    Hit    Hit    Hit   
A4    Hit    Hit   Double Double Double  Hit    Hit    Hit    Hit    Hit   
A5    Hit    Hit   Double Double Double  Hit    Hit    Hit    Hit    Hit   
A6   Double Double Double Double Double  Hit    Hit    Hit    Hit    Hit   
A7   Stand  Double Double Double Double Stand  Stand   Hit    Hit   Stand  
A8   Stand  Stand  Stand  Stand  Double Stand  Stand  Stand  Stand  Stand  
A9   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  

Soft Chart - Player Strategy (Round >= 2, No Doubling)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
12    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
13    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
14    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
15    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
16    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
17    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit    Hit   
18   Stand  Stand  Stand  Stand  Stand  Stand  Stand   Hit    Hit   Stand  
19   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
20   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
21   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  

Pairs Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
AA   -0.274 -0.232 -0.178 -0.130 -0.104 -0.452 -0.500 -0.511 -0.531 -0.663 
22   -0.291 -0.251 -0.192 -0.107 -0.125 -0.471 -0.515 -0.523 -0.547 -0.660 
33   -0.295 -0.246 -0.160 -0.101 -0.119 -0.467 -0.510 -0.542 -0.546 -0.660 
44   -0.290 -0.214 -0.152 -0.095 -0.114 -0.463 -0.529 -0.543 -0.547 -0.656 
55   -0.256 -0.206 -0.146 -0.090 -0.112 -0.484 -0.531 -0.541 -0.545 -0.653 
66   -0.262 -0.211 -0.152 -0.102 -0.165 -0.493 -0.536 -0.549 -0.552 -0.617 
77   -0.268 -0.219 -0.164 -0.156 -0.174 -0.502 -0.539 -0.555 -0.510 -0.631 
88   -0.275 -0.228 -0.215 -0.165 -0.178 -0.503 -0.551 -0.516 -0.518 -0.644 
99    0.137  0.123  0.167  0.203  0.265  0.401  0.065 -0.196 -0.133 -0.055 
TT    0.627  0.636  0.645  0.674  0.697  0.765  0.783  0.744  0.583  0.650 

Pairs Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
AA    0.095  0.120  0.142  0.182  0.200  0.158  0.093 -0.003 -0.048 -0.075 
22   -0.113 -0.082 -0.035  0.036  0.032 -0.092 -0.141 -0.222 -0.277 -0.395 
33   -0.153 -0.118 -0.047  0.008  0.014 -0.164 -0.231 -0.310 -0.346 -0.444 
44   -0.013  0.028  0.098  0.154  0.175  0.111 -0.055 -0.206 -0.246 -0.268 
55    0.224  0.254  0.295  0.347  0.362  0.279  0.207  0.119  0.032  0.042 
66   -0.253 -0.222 -0.190 -0.162 -0.194 -0.265 -0.322 -0.386 -0.386 -0.411 
77   -0.406 -0.388 -0.369 -0.370 -0.367 -0.389 -0.408 -0.475 -0.516 -0.510 
88   -0.454 -0.450 -0.461 -0.453 -0.397 -0.374 -0.426 -0.487 -0.512 -0.490 
99   -0.627 -0.638 -0.597 -0.590 -0.587 -0.566 -0.566 -0.595 -0.626 -0.621 
TT   -0.847 -0.846 -0.846 -0.846 -0.845 -0.843 -0.843 -0.842 -0.840 -0.882 

Pairs Chart - Player Expected Gains per unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
AA   -0.019  0.055  0.137  0.216  0.248 -0.137 -0.296 -0.421 -0.468 -0.591 
22   -0.582 -0.501 -0.384 -0.214 -0.249 -0.942 -1.030 -1.047 -1.094 -1.320 
33   -0.567 -0.472 -0.302 -0.184 -0.215 -0.871 -1.000 -1.065 -1.072 -1.298 
44   -0.185 -0.082  0.044  0.162  0.193 -0.108 -0.447 -0.701 -0.741 -0.802 
55    0.446  0.510  0.590  0.695  0.724  0.466  0.323  0.175  0.014  0.042 
66   -0.505 -0.444 -0.380 -0.325 -0.387 -0.599 -0.711 -0.817 -0.803 -0.823 
77   -0.813 -0.777 -0.738 -0.741 -0.734 -0.823 -0.858 -0.978 -1.035 -1.019 
88   -0.908 -0.900 -0.922 -0.906 -0.793 -0.747 -0.853 -0.974 -1.024 -0.980 
99   -1.255 -1.277 -1.194 -1.181 -1.173 -1.132 -1.133 -1.189 -1.252 -1.242 
TT   -1.693 -1.693 -1.693 -1.691 -1.690 -1.686 -1.685 -1.684 -1.681 -1.764 

Pairs Chart - Player Expected Gains per unit (Split)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
AA    1.192  1.223  1.265  1.321  1.344  1.308  1.201  1.039  0.860  0.921 
22   -0.128 -0.070 -0.007  0.128  0.126 -0.054 -0.213 -0.383 -0.463 -0.566 
33   -0.202 -0.128  0.009  0.117  0.112 -0.115 -0.265 -0.418 -0.509 -0.579 
44   -0.236 -0.127 -0.013  0.095  0.083 -0.223 -0.343 -0.493 -0.580 -0.623 
55   -0.232 -0.150 -0.038  0.068  0.056 -0.299 -0.448 -0.608 -0.685 -0.695 
66   -0.219 -0.135 -0.028  0.068 -0.011 -0.270 -0.413 -0.570 -0.652 -0.660 
77   -0.163 -0.084  0.016  0.039  0.053 -0.123 -0.423 -0.564 -0.634 -0.635 
88    0.017  0.077  0.106  0.188  0.234  0.202 -0.100 -0.430 -0.464 -0.378 
99    0.170  0.170  0.253  0.339  0.359  0.341  0.179 -0.112 -0.268 -0.109 
TT    0.412  0.465  0.518  0.596  0.619  0.576  0.447  0.276  0.146  0.140 

Pairs Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
——————————————————————————————————————————————————————————————————————————
AA   Split  Split  Split  Split  Split  Split  Split  Split  Split  Split  
22    Hit   Split  Split  Split  Split  Split   Hit    Hit    Hit    Hit   
33    Hit    Hit   Split  Split  Split  Split   Hit    Hit    Hit    Hit   
44    Hit    Hit    Hit   Double Double  Hit    Hit    Hit    Hit    Hit   
55   Double Double Double Double Double Double Double Double  Hit   Double 
66   Split  Split  Split  Split  Split   Hit    Hit    Hit    Hit    Hit   
77   Split  Split  Split  Split  Split  Split   Hit    Hit   Stand   Hit   
88   Split  Split  Split  Split  Split  Split  Split  Split  Split  Split  
99   Split  Split  Split  Split  Split  Stand  Split  Split  Stand  Stand  
TT   Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  Stand  
Simulation for year 1:

After playing 50 times a day for 365 days:
Winning days:   179
Losing days:    180
Breakeven days: 6
Biggest win:    33.0
Biggest loss:   22.5
Total win:      144.0
Total staked:   20623.0
Win % staked:  0.698

Simulation for year 2:

After playing 50 times a day for 365 days:
Winning days:   168
Losing days:    184
Breakeven days: 13
Biggest win:    25.5
Biggest loss:   25.0
Total loss:     233.0
Total staked:   20553.0
Loss % staked:  1.134

Simulation for year 3:

After playing 50 times a day for 365 days:
Winning days:   177
Losing days:    176
Breakeven days: 12
Biggest win:    25.5
Biggest loss:   22.0
Total loss:     18.5
Total staked:   20646.0
Loss % staked:  0.090

Simulation for year 4:

After playing 50 times a day for 365 days:
Winning days:   193
Losing days:    164
Breakeven days: 8
Biggest win:    26.5
Biggest loss:   22.0
Total win:      210.5
Total staked:   20635.0
Win % staked:  1.020

Simulation for year 5:

After playing 50 times a day for 365 days:
Winning days:   161
Losing days:    191
Breakeven days: 13
Biggest win:    25.0
Biggest loss:   31.0
Total loss:     270.0
Total staked:   20502.0
Loss % staked:  1.317

Simulation for year 6:

After playing 50 times a day for 365 days:
Winning days:   182
Losing days:    175
Breakeven days: 8
Biggest win:    23.0
Biggest loss:   26.0
Total win:      104.0
Total staked:   20610.0
Win % staked:  0.505

Simulation for year 7:

After playing 50 times a day for 365 days:
Winning days:   178
Losing days:    181
Breakeven days: 6
Biggest win:    19.0
Biggest loss:   21.5
Total loss:     86.0
Total staked:   20546.0
Loss % staked:  0.419

Simulation for year 8:

After playing 50 times a day for 365 days:
Winning days:   178
Losing days:    177
Breakeven days: 10
Biggest win:    26.5
Biggest loss:   21.0
Total loss:     127.5
Total staked:   20522.0
Loss % staked:  0.621

Simulation for year 9:

After playing 50 times a day for 365 days:
Winning days:   173
Losing days:    184
Breakeven days: 8
Biggest win:    25.0
Biggest loss:   24.0
Total loss:     14.5
Total staked:   20551.0
Loss % staked:  0.071

Simulation for year 10:

After playing 50 times a day for 365 days:
Winning days:   170
Losing days:    178
Breakeven days: 17
Biggest win:    20.0
Biggest loss:   21.5
Total loss:     93.0
Total staked:   20516.0
Loss % staked:  0.453

Phix

Translation of: Go
-- demo/rosetta/blackjack.exw
with javascript_semantics
 
function NewDeck()
    return {4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 52}
end function
 
function dealerProbs(integer upCard, sequence startDeck)
--
-- Returns probabilities of dealer eventually getting:
-- 1: 17, 2: 18, 3: 19, 4: 20, 5: 21 (non-blackjack), 6: blackjack (nil), 7: bust.
-- It is assumed that the dealer has already checked for blackjack, that one deck is used
-- and that the dealer stands on 'soft' 17.
--
    sequence res := repeat(0.0, 7)  // results
    sequence decks := repeat({}, 9) // decks for each level
    sequence scores := repeat(0, 9) // scores for each level
    sequence elevens := repeat(0, 9)    // number of aces for each level scored as 11
    sequence probs := repeat(0.0, 9) // probs for each level
    decks[1] = startDeck
    scores[1] = upCard
    if upCard == 1 then // an ace
        scores[1] = 11
        elevens[1] = 1
    end if
    probs[1] = 1.0
    integer lev = 1
    sequence cs = repeat(0,9)
    while lev do
        cs[lev] += 1
        integer c = cs[lev]
        if c>10 then
            lev -= 1
        elsif decks[lev][c]!=0 then -- card still present in deck
            // temporary variables for current level
            sequence deck := deep_copy(decks[lev])
            integer score := scores[lev]
            integer eleven := elevens[lev]
            atom prob := probs[lev]
            score += c  // add card to score
            if c == 1 then // score all aces initially as 11
                score += 10
                eleven += 1
            end if
            prob *= deck[c]/deck[11]
            if score > 21 and eleven > 0 then
                score -= 10 // bust but can demote an ace
                eleven -= 1
            end if
            if lev == 1 and ((upCard == 1 and c == 10) or (upCard == 10 and c == 1)) then
                res[6] += prob // blackjack, allow for now
            elsif score >= 17 and score <= 21 then
                res[score-16] += prob // 17 to (non-blackjack) 21
            elsif score > 21 and eleven == 0 then
                res[7] += prob // bust
            else
                deck[c] -= 1 // remove card from deck
                deck[11] -= 1 // decrement deck size
                lev += 1
                decks[lev] = deck
                scores[lev] = score
                elevens[lev] = eleven
                probs[lev] = prob
                -- get another card:
                cs[lev] = 0
            end if
        end if
    end while
    // but can't have blackjack, so adjust probabilities accordingly
    atom pnbj := 1 - res[6]
    for i=1 to 7 do 
        res[i] /= pnbj
    end for
    res[6] = 0
    return res
end function

procedure dealerChart()
    // Prints chart of dealer probabilities (as a check against an external source).
    printf(1,"Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules\n")
    printf(1,"Up Card     17        18        19        20        21       Bust\n")
    printf(1,"-------------------------------------------------------------------\n")
    sequence deck := NewDeck()
    deck[11] = 51
    for uc=1 to 10 do
        sequence deck2 := deep_copy(deck)
        deck2[uc] -= 1
        sequence dp := dealerProbs(uc, deck2)
        if uc > 1 then
            printf(1,"%3d      ", uc)
        else
            printf(1,"Ace      ")
        end if
        dp[6] = dp[7]
        printf(1,"%f  %f  %f  %f  %f  %f\n", dp)
    end for
end procedure
 
// Calculates gain per unit staked for a given scenario (helper function).
function calcGain(integer pscore, sequence dp)
    atom eg := 0.0
    switch pscore do
    case 17:
        eg += dp[7]                         // dealer is bust
        eg -= dp[2] + dp[3] + dp[4] + dp[5] // dealer has 18 to 21
    case 18:
        eg += dp[1] + dp[7]         // dealer has 17 or is bust
        eg -= dp[3] + dp[4] + dp[5] // dealer has 19 to 21
    case 19:
        eg += dp[1] + dp[2] + dp[7] // dealer has 17, 18 or is bust
        eg -= dp[4] + dp[5]         // dealer has 20 or 21
    case 20:
        eg += dp[1] + dp[2] + dp[3] + dp[7] // dealer has 17 to 19 or is bust
        eg -= dp[5]                         // dealer has (non-blackjack) 21
    case 21:
        eg += dp[1] + dp[2] + dp[3] + dp[4] + dp[7] // dealer has 17 to 20 or is bust
    case 22: // notional
        eg += 1.5 // player blackjack
    case 23: // notional
        eg -= 1 // player bust, loses stake irrespective of what dealer has
    default: // player has less than 17
        eg += dp[7]       // dealer is bust
        eg -= (1 - dp[7]) // dealer isn't bust
    end switch
    return eg
end function
 
function playerGain(integer card1, card2, uc, sequence startDeck)
// Returns player's expected gain per unit staked after hitting once and then standing.
    atom eg := 0.0
    sequence deck := startDeck
    integer score := card1 + card2
    bool eleven := false
    if card1 == 1 or card2 == 1 then // an ace
        score += 10
        eleven = true
    end if
    for c=1 to 10 do // get another card
        if deck[c] != 0 then // card still present in deck
            // temporary variables for current card
            sequence deck2 := deep_copy(deck)
            integer score2 := score
--DEV shouldn't this be false?
            bool eleven2 := eleven
            score2 += c // add card to score
            if c == 1 then // score all aces initially as 11
                score2 += 10
                eleven2 = true
            end if
            atom prob := deck2[c] / deck2[11]
            deck2[c] -= 1 // remove card from deck
            deck2[11] -= 1 // decrement deck size
            if score2 > 21 and eleven2 then
                score2 -= 10 // bust but can demote an ace
            end if
            if score2 <= 21 then
                sequence dp := dealerProbs(uc, deck2)
                eg += calcGain(score2, dp) * prob
            else  // bust
                eg -= prob
            end if
        end if
    end for
    return eg
end function
 
function playerGain2(integer card1, card2, uc, sequence startDeck)
// Returns player's expected gain per unit staked after hitting once and then continuing in accordance
// with the tables for rounds >= 2.
    atom eg := 0.0                  // result
    sequence decks := repeat({}, 9) // decks for each level
    sequence scores := repeat(0, 9) // scores for each level
    sequence elevens := repeat(0, 9)    // number of aces for each level scored as 11
    sequence probs := repeat(0.0, 9) // probs for each level
    decks[1] = startDeck
    scores[1] = card1 + card2
    if card1 == 1 or card2 == 1 then // an ace
        scores[1] += 10
        elevens[1] = 1
    end if
    probs[1] = 1.0
    integer lev = 1
    sequence cs = repeat(0,9)
    while lev do
        cs[lev] += 1
        integer c = cs[lev]
        if c>10 then
            lev -= 1
        elsif decks[lev][c]!=0 then -- card still present in deck
            // temporary variables for current level
            sequence deck := deep_copy(decks[lev])
            integer score := scores[lev]
            integer eleven := elevens[lev]
            atom prob := probs[lev]
            score += c  // add card to score
            if c == 1 then // score all aces initially as 11
                score += 10
                eleven += 1
            end if
            prob *= deck[c] / deck[11]
            if score > 21 and eleven > 0 then
                score -= 10 // bust but can demote an ace
                eleven -= 1
            end if
            deck[c] -= 1 // remove card from deck
            deck[11] -= 1 // decrement deck size
            if ((eleven == 0 and (score >= 17 or (score >= 13 and uc < 7))) or
                (eleven == 0 and score == 12 and uc >= 4 and uc <= 6) or
                (eleven > 0 and score == 18 and uc != 9 and uc != 10) or
                (eleven > 0 and score >= 19)) and score <= 21 then
                sequence dp := dealerProbs(uc, deck)
                eg += calcGain(score, dp) * prob
            elsif score > 21 and eleven == 0 then // bust
                eg -= prob
            else
                lev += 1
                decks[lev] = deck
                scores[lev] = score
                elevens[lev] = eleven
                probs[lev] = prob
                // get another card:
                cs[lev] = 0
            end if
        end if
    end while
    return eg
end function
 
function stand(integer card1, card2)
// Returns player's expected gains per unit staked, for each dealer up-card, after standing.
    sequence deck := NewDeck()
    deck[card1] -= 1
    deck[card2] -= 1
    deck[11] = 50
    integer pscore := card1 + card2 // player score
    if card1 == 1 or card2 == 1 then
        pscore += 10
    end if
    sequence egs = repeat(0,10)          // results
    for uc=1 to 10 do // dealer's up-card
        sequence deck2 := deep_copy(deck)
        deck2[uc] -= 1
        deck2[11] -= 1
        sequence dp := dealerProbs(uc, deck2)
        atom eg := calcGain(pscore, dp) // expected gain for this up-card
        if uc > 1 then
            egs[uc-1] = eg
        else  // dealer has Ace
            egs[10] = eg // ace comes last in tables
        end if
    end for
    return egs
end function
 
function hit(integer card1, card2, bool once)
// Returns player's expected gains per unit staked, for each dealer up-card, after hitting once and
// then either standing (once == true) or continuing as per the round >= 2 tables (once == false).
    sequence deck := NewDeck()
    deck[card1] -= 1
    deck[card2] -= 1
    deck[11] = 50
    sequence egs =repeat(0,10)       // results
    for uc=1 to 10 do // dealer's up-card
        sequence deck2 := deep_copy(deck)
        deck2[uc] -= 1
        deck2[11] = 49
        atom peg // player's expected gain for this up-card
        if once then
            peg = playerGain(card1, card2, uc, deck2)
        else
            peg = playerGain2(card1, card2, uc, deck2)
        end if
        if uc > 1 then
            egs[uc-1] = peg
        else  // dealer has Ace
            egs[10] = peg
        end if
    end for
    return egs
end function
 
function double(integer card1, card2)
// Returns player's expected gains per unit oiginally staked, for each dealer up-card, after
// doubling i.e. hitting once and then standing with a doubled stake.
    sequence egs := hit(card1, card2, true) // hit once and then stand
    for i=1 to 10 do
        egs[i] *= 2
    end for
    return egs
end function

// Computed strategy tables.
sequence hTable = repeat(repeat("",10),15) // hard strategy table (round 1)
sequence sTable = repeat(repeat("",10),8)  // soft strategy table (round 1)
sequence pTable = repeat(repeat("",10),10) // pairs strategy table (round 1)
sequence hTable2 = repeat(repeat("",10),18) // hard strategy table (round >= 2, no doubling)
sequence sTable2 = repeat(repeat("",10),10) // soft strategy table (round >= 2, no doubling)
 
function splitt(integer card)
// Returns player's expected gains per unit originally staked, for each dealer up-card, after
// splitting a pair and doubling the stake, getting a second card for each hand  and then continuing
// in accordace with the rounds >= 2 tables. It is assumed that a player cannot double or re-split
// following a split. It is also assumed (in the interests of simplicity) that the expected gains
// for each split hand (after calculating the gains for the first hand as though the second hand
// is not completed) are exactly the same.
    sequence deck := NewDeck()
    deck[card] -= 2 // must be a pair
    deck[11] = 50
    sequence egs = repeat(0,10) // overall results
 
    // now play a single hand
    integer score := card,
            eleven := 0
    if card == 1 then // an ace
        score = 11
        eleven = 1
    end if
    for uc=1 to 10 do // collect results for each dealer up-card
        if deck[uc] != 0 then // card still present in deck
            sequence deck2 := deep_copy(deck)
            deck2[uc] -= 1
            deck2[11] -= 1
            integer ix := uc - 1
            if ix == 0 then
                ix = 10 // in tables ace comes last
            end if
            atom peg = 0 // player expected gain for this up-card
            // get second player card
            for c=1 to 10 do
                if deck2[c] != 0 then // card still present in deck
                    atom prob := deck2[c] / deck2[11]
                    sequence deck3 := deep_copy(deck2)
                    deck3[c] -= 1
                    deck3[11] -= 1
                    integer score2 := score + c,
                            eleven2 := eleven
                    if c == 1 then // score all aces initially as 11
                        score2 += 10
                        eleven2 += 1
                    end if
                    if score2 == 21 then // player has blackjack & we know dealer hasn't
                        peg += 1.5 * prob
                    else
                        if score2 > 21 and eleven2 > 0 then
                            score2 -= 10 // bust but can demote an ace
                            eleven2 -= 1
                        end if
                        string action
                        if eleven2 > 0 then
                            action = sTable2[score2-11][ix] // use soft strategy table, no doubling
                        else  // including pairs as no re-splitting
                            action = hTable2[score2-3][ix] // use hard strategy table, no doubling
                        end if
                        atom peg2
                        if action == "S" then
                            sequence dp := dealerProbs(uc, deck3)
                            peg2 = calcGain(score2, dp)
                        else
                            peg2 = playerGain2(card, c, uc, deck3)
                        end if
                        peg += peg2 * prob
                    end if
                end if
            end for
            if uc > 1 then
                egs[uc-1] = peg * 2 // allow for both hands in overall results
            else
                egs[10] = peg * 2 // ditto
            end if
        end if
    end for
    return egs
end function

function bestAction(sequence ags)
// Returns the action with the highest expected gain.
    atom best := ags[1][2]
    integer besti := 1
    for i=2 to length(ags) do
        if ags[i][2] > best then
            best = ags[i][2]
            besti = i
        end if
    end for
    return ags[besti][1]
end function
 
procedure printHeader(string title)
// Prints title and header for a given chart.
    printf(1,"%s\n",title)
    printf(1,"P/D     2      3      4      5      6      7      8      9      T      A\n")
    printf(1,"--------------------------------------------------------------------------\n")
end procedure
 
procedure printPair(integer c)
// Prints header for a pair of cards.
    c = "A23456789T"[c]
    printf(1,"%c%c   ",c)
end procedure

sequence cards, fscores
integer next, score, aces, uc
string action

function dealerPlay(integer pscore, sequence d)
// Simulates a dealer's play for a given player's hand and state of deck.
// Returns the player's gain (positive or negative) per unit staked.
    integer dscore := d[1] + d[2],
            aces := 0
    if d[1] == 1 or d[2] == 1 then // dealer has an ace
        dscore += 10
        aces += 1
    end if
    while true do
        if dscore > 21 and aces > 0 then
            dscore -= 10 // bust but we can demote an ace
            aces -= 1
        end if
        if dscore > 21 then
            return 1 // dealer is bust and player gains stake
        end if
        if dscore >= 17 then // dealer must stick on 17 or above, hard or not
            if dscore > pscore then
                return -1 // dealer wins and player loses stake
            elsif dscore == pscore then
                exit // player breaks even
            else
                return 1 // dealer loses and player gains stake
            end if
        end if
        integer nc := cards[next] // get new card from pack
        next += 1
        dscore += nc
        if nc == 1 then // count aces initially as 11
            dscore += 10
            aces += 1
        end if
    end while
    return 0
end function


procedure h(integer hand)
    // simulate a 'hit'
    while true do
        integer nc := cards[next] // get new card from pack
        next += 1
        score += nc
        if nc == 1 then // count aces initially as 11
            score += 10
            aces += 1
        end if
        if score > 21 and aces > 0 then
            score -= 10 // bust but we can demote an ace
            aces -= 1
        end if
        if score > 21 then
            fscores[hand] = 22 // player is bust and loses stake
            return
        end if
        if action == "D" then
            fscores[hand] = score
            return
        end if
        // get further strategy and act accordingly
        if aces == 0 then
            action = hTable2[score-3][uc]
        else
            action = sTable2[score-11][uc]
        end if
        if action == "S" then // stand
            fscores[hand] = score
            return
        end if
    end while
end procedure

function playerPlay()
// Simulates the playing of a random player's hand according to the strategy tables.
// Returns both the gain (positive or negative) and the stake (1 or 2).
    sequence perm = shuffle(tagset(52)) // randomizes integers from 1 to 52 inclusive
    cards := repeat(0,52)
    for i=1 to length(perm) do
        integer r = perm[i]
        integer card := floor((r-1)/4) + 1
        if card > 10 then
            card = 10
        end if
        cards[i] = card
    end for
    sequence p = {}, d = {} // player and dealer hands
    // initial deal
    for i=1 to 4 do
        if i <= 2 then
            p = append(p, cards[i])
        else
            d = append(d, cards[i])
        end if
    end for
    next := 5 // index of next card to be dealt
 
    // check if dealer and/or player have blackjack
    bool dbj := (d[1] == 1 and d[2] == 10) or (d[1] == 10 and d[2] == 1),
         pbj := (p[1] == 1 and p[2] == 10) or (p[1] == 10 and p[2] == 1)
    if dbj then
        if pbj then
            return {0.0, 1.0} // player neither wins nor loses
        end if
        return {-1.0, 1.0} // player loses stake
    end if
    if pbj then
        return {1.5, 1.0} // player wins 1.5 x stake
    end if
 
    uc := d[1] // dealer's up-card for accessing tables
    if uc == 1 then
        uc = 10 // move ace to last place
    else
        uc -= 1 // move others down 1
    end if
    atom stake := 1.0      // player's initial stake
    fscores = {0,0} // final player scores (one or, after split, two hands)
 
    score = p[1] + p[2]
    aces = 0
    // get kind of player hand: hard, soft, pair
    string kind
    if p[1] == p[2] then
        kind = "pair"
    elsif p[1] == 1 or p[2] == 1 then
        kind = "soft"
    else
        kind = "hard"
    end if
    switch kind do
    case "hard":
        action = hTable[score-4][uc]
    case "soft": // includes one ace
        integer otherCard := p[1]
        if otherCard == 1 then
            otherCard = p[2]
        end if
        score += 10
        aces = 1
        action = sTable[otherCard-1][uc]
    case "pair":
        if p[1] == 1 then // pair of aces
            score += 10
            aces = 2
        end if
        action = pTable[p[1]][uc]
    end switch
    switch action do
    case "S": // stand
        fscores[1] = score
    case "H": // hit
        h(1)
    case "D": // double
        h(1)
        stake = 2
    case "P": // split
        for hand=1 to 2 do
            score = p[1]
            aces = 0
            if score == 1 then // count aces initially as 11
                score = 11
                aces += 1
            end if
            h(hand)
        end for
    end switch
    atom tot := 0.0
    if fscores[1] < 22 then
        tot += dealerPlay(fscores[1], d) * stake
    else
        tot -= 1 * stake // this hand is bust
    end if
    if fscores[2] > 0 then // pair
        if fscores[1] < 22 then
            tot += dealerPlay(fscores[2], d)
        else
            tot -= 1 // this hand is bust
        end if
        stake = 2
    end if
    return {tot, stake}
end function
 
procedure simulate(integer perDay, days)
// Simulates 'perDay' blackjack games for 'days' days.
    integer winDays = 0, loseDays = 0, evenDays = 0
    atom bigWin = 0.0, bigLoss = 0.0,
         totalGain = 0.0, totalStake = 0.0
    for d=1 to days do
        atom dailyGain = 0.0, dailyStake = 0.0
        for p=1 to perDay do
            atom {gain, stake} := playerPlay()
            dailyGain += gain
            dailyStake += stake
        end for
        if dailyGain > 0 then
            winDays += 1
        elsif dailyGain < 0 then
            loseDays += 1
        else
            evenDays += 1
        end if
        if dailyGain > bigWin then
            bigWin = dailyGain
        elsif -dailyGain > bigLoss then
            bigLoss = -dailyGain
        end if
        totalGain += dailyGain
        totalStake += dailyStake
    end for
    printf(1,"\nAfter playing %d times a day for %d days:\n", {perDay, days})
    printf(1,"Winning days   :%d\n", winDays)
    printf(1,"Losing days    :%d\n", loseDays)
    printf(1,"Breakeven days :%d\n", evenDays)
    printf(1,"Biggest win    :%.2f\n", bigWin)
    printf(1,"Biggest loss   :%.2f\n", bigLoss)
    if totalGain < 0 then
        printf(1,"Total loss     :%.2f\n", -totalGain)
        printf(1,"Total staked   :%.2f\n", totalStake)
        printf(1,"Loss %% staked  : %0.3f\n", -totalGain/totalStake*100)
    else
        printf(1,"Total win      :%.2f\n", totalGain)
        printf(1,"Total staked   :%.2f\n", totalStake)
        printf(1,"Win %% staked   : %0.3f\n", totalGain/totalStake*100)
    end if
end procedure
 
procedure main()
    // print dealer probabilities chart
    dealerChart()
 
    // for hard scores (i.e. different cards, no aces)
    sequence tuples := {
        {2, 3},
        {2, 4},
        {2, 5}, {3, 4},
        {2, 6}, {3, 5},
        {2, 7}, {3, 6}, {4, 5},
        {2, 8}, {3, 7}, {4, 6},
        {2, 9}, {3, 8}, {4, 7}, {5, 6},
        {2, 10}, {3, 9}, {4, 8}, {5, 7},
        {3, 10}, {4, 9}, {5, 8}, {6, 7},
        {4, 10}, {5, 9}, {6, 8},
        {5, 10}, {6, 9}, {7, 8},
        {6, 10}, {7, 9},
        {7, 10}, {8, 9},
        {8, 10},
        {9, 10},
    }
    // number of tuples for each player score from 5 to 19
    sequence counts := {1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1}
    // expected gains for each player score & for each dealer up-card
    sequence segs := repeat(repeat(0,10),15) // if stands
    sequence hegs := repeat(repeat(0,10),15) // if hits
    sequence degs := repeat(repeat(0,10),15) // if doubles
    for t = 1 to length(tuples) do
        if platform()!=JS then
            progress("%d/%d\r",{t,length(tuples)})
        end if
        sequence tuple := tuples[t]
        integer i := tuple[1] + tuple[2]
        sequence sg := stand(tuple[1], tuple[2])
        sequence hg := hit(tuple[1], tuple[2], false)
        sequence dg := double(tuple[1], tuple[2])
        for j=1 to 10 do
            segs[i-4][j] += sg[j]
            hegs[i-4][j] += hg[j]
            degs[i-4][j] += dg[j]
        end for
    end for
    if platform()!=JS then
        progress("")
    end if
    // calculate the average per tuple for each score
    for i=1 to 15 do
        for j=1 to 10 do
            segs[i][j] /= counts[i]
            hegs[i][j] /= counts[i]
            degs[i][j] /= counts[i]
        end for
    end for
 
    printHeader("\nHard Chart - Player Expected Gains per unit (Stand)")
    for i=5 to 19 do
        printf(1,"%2d   ", i)
        for j=1 to 10 do
            printf(1,"%6.3f ", segs[i-4][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nHard Chart - Player Expected Gains per unit (Hit)")
    for i=5 to 19 do
        printf(1,"%2d   ", i)
        for j=1 to 10 do
            printf(1,"%6.3f ", hegs[i-4][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nHard Chart - Player Expected Gains per original unit (Double)")
    for i=5 to 19 do
        printf(1,"%2d   ", i)
        for j=1 to 10 do
            printf(1,"%6.3f ", degs[i-4][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nHard Chart - Player Strategy (Round 1)")
    for i=5 to 19 do
        printf(1,"%2d   ", i)
        for j=1 to 10 do
            sequence ags := {{"S", segs[i-4][j]}, {"H", hegs[i-4][j]}, {"D", degs[i-4][j]}}
            string action := bestAction(ags)
            hTable[i-4][j] = action
            printf(1,"%4s   ", action)
        end for
        printf(1,"\n")
    end for
 
    // for hard scores (no aces) - after round 1 (no doubling or splitting)
    // based on hard table figures (round 1) with scores of 4, 20, and 21 added
    sequence segs2 := repeat(repeat(0,10),18) // expected gains if stands
    sequence hegs2 := repeat(repeat(0,10),18) // expected gains if hits
    for i=5 to 19 do
        segs2[i-3] = segs[i-4]
        hegs2[i-3] = hegs[i-4]
    end for
    sequence sg4 = stand(2, 2), hg4 = hit(2, 2, false),
             sg20 = stand(10, 10), hg20 = hit(10, 10, false),
             sg21 = stand(1, 10), hg21 = hit(1, 10, false)
    for j=1 to 10 do
        segs2[1][j] += sg4[j]
        hegs2[1][j] += hg4[j]
        segs2[17][j] += sg20[j]
        hegs2[17][j] += hg20[j]
        segs2[18][j] += sg21[j]
        hegs2[18][j] += hg21[j]
    end for
 
    printHeader("\nHard Chart - Player Strategy (Round >= 2, No Doubling)")
    for i=4 to 21 do
        printf(1,"%2d   ", i)
        for j=1 to 10 do
            string action := "S"
            if hegs2[i-3][j] > segs2[i-3][j] then
                action = "H"
            end if
            hTable2[i-3][j] = action
            printf(1,"%4s   ", action)
        end for
        printf(1,"\n")
    end for
 
    // for soft scores (i.e. including exactly one ace)
 
    // expected gains for each player second card (2 to 9) & for each dealer up-card
    sequence segs3 = repeat(repeat(0,10),8), // if stands
             hegs3 = repeat(repeat(0,10),8), // if hits
             degs3 = repeat(repeat(0,10),8)  // if doubles
    for c=2 to 9 do
        sequence sg := stand(1, c),
                 hg := hit(1, c, false),
                 dg := double(1, c)
        for j=1 to 10 do
            segs3[c-1][j] += sg[j]
            hegs3[c-1][j] += hg[j]
            degs3[c-1][j] += dg[j]
        end for
    end for
 
    printHeader("\nSoft Chart - Player Expected Gains per unit (Stand)")
    for c=2 to 9 do
        printf(1,"A%d   ", c)
        for j=1 to 10 do
            printf(1,"%6.3f ", segs3[c-1][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nSoft Chart - Player Expected Gains per unit (Hit)")
    for c=2 to 9 do
        printf(1,"A%d   ", c)
        for j=1 to 10 do
            printf(1,"%6.3f ", hegs3[c-1][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nSoft Chart - Player Expected Gains per original unit (Double)")
    for c=2 to 9 do
        printf(1,"A%d   ", c)
        for j=1 to 10 do
            printf(1,"%6.3f ", degs3[c-1][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nSoft Chart - Player Strategy (Round 1)")
    for c=2 to 9 do
        printf(1,"A%d   ", c)
        for j=1 to 10 do
            sequence ags := {{"S", segs3[c-1][j]}, {"H", hegs3[c-1][j]}, {"D", degs3[c-1][j]}}
            string action := bestAction(ags)
            sTable[c-1][j] = action
            printf(1,"%4s   ", action)
        end for
        printf(1,"\n")
    end for
 
    // for soft scores (at least one ace) - after round 1 (no doubling or splitting)
    // based on soft table figures (round 1) with scores of 12 and 21 added
    // assumes one ace counted as 11
    sequence segs4 := repeat(repeat(0,10),10), // expected gains if stands
             hegs4 := repeat(repeat(0,10),10)  // expected gains if hits
    for i=2 to 9 do
        segs4[i] = segs3[i-1]
        hegs4[i] = hegs3[i-1]
    end for
    sequence sg12 = stand(1, 1), hg12 = hit(1, 1, false)
    for j=1 to 10 do
        segs4[1][j] += sg12[j]
        hegs4[1][j] += hg12[j]
        segs4[10][j] += sg21[j]
        hegs4[10][j] += hg21[j]
    end for
 
    printHeader("\nSoft Chart - Player Strategy (Round >= 2, No Doubling)")
    for i=12 to 21 do
        printf(1,"%2d   ", i)
        for j=1 to 10 do
            string action := "S"
            if hegs4[i-11][j] > segs4[i-11][j] then
                action = "H"
            end if
            sTable2[i-11][j] = action
            printf(1,"%4s   ", action)
        end for
        printf(1,"\n")
    end for
 
    // for pairs
 
    // expected gains for each pair (A to 10) & for each dealer up-card
    sequence segs5 := repeat(repeat(0,10),10), // if stands
             hegs5 := repeat(repeat(0,10),10), // if hits
             degs5 := repeat(repeat(0,10),10), // if doubles
             pegs5 := repeat(repeat(0,10),10)  // if splits
    for c=1 to 10 do
        if platform()!=JS then
            progress("%d/10",{c})
        end if
        sequence sg := stand(c, c),
                 hg := hit(c, c, false),
                 dg := double(c, c),
                 pg := splitt(c)
        for j=1 to 10 do
            segs5[c][j] += sg[j]
            hegs5[c][j] += hg[j]
            degs5[c][j] += dg[j]
            pegs5[c][j] += pg[j]
        end for
    end for
    if platform()!=JS then
        progress("")
    end if 

    printHeader("\nPairs Chart - Player Expected Gains per unit (Stand)")
    for c=1 to 10 do
        printPair(c)
        for j=1 to 10 do
            printf(1,"%6.3f ", segs5[c][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nPairs Chart - Player Expected Gains per unit (Hit)")
    for c=1 to 10 do
        printPair(c)
        for j=1 to 10 do
            printf(1,"%6.3f ", hegs5[c][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nPairs Chart - Player Expected Gains per original unit (Double)")
    for c=1 to 10 do
        printPair(c)
        for j=1 to 10 do
            printf(1,"%6.3f ", degs5[c][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nPairs Chart - Player Expected Gains per original unit (Split)")
    for c=1 to 10 do
        printPair(c)
        for j=1 to 10 do
            printf(1,"%6.3f ", pegs5[c][j])
        end for
        printf(1,"\n")
    end for
 
    printHeader("\nPairs Chart - Player Strategy (Round 1)")
    for c=1 to 10 do
        printPair(c)
        for j=1 to 10 do
            sequence ags := {{"S", segs5[c][j]}, {"H", hegs5[c][j]}, {"D", degs5[c][j]}, {"P", pegs5[c][j]}}
            string action := bestAction(ags)
            pTable[c][j] = action
            printf(1,"%4s   ", action)
        end for
        printf(1,"\n")
    end for

    // do 10 years of simulations
    for i=1 to 10 do
        printf(1,"\nSimulation for Year %d:\n", i)
        simulate(50, 365)
    end for
end procedure
main()
?"done"
{} = wait_key()
Output:

Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules
Up Card     17        18        19        20        21       Bust
-------------------------------------------------------------------
Ace      0.183786  0.190890  0.188680  0.191692  0.075137  0.169815
  2      0.138976  0.131762  0.131815  0.123948  0.120526  0.352973
  3      0.130313  0.130946  0.123761  0.123345  0.116047  0.375588
  4      0.130973  0.114163  0.120679  0.116286  0.115096  0.402803
  5      0.119687  0.123483  0.116909  0.104694  0.106321  0.428905
  6      0.166948  0.106454  0.107192  0.100705  0.097878  0.420823
  7      0.372345  0.138583  0.077334  0.078897  0.072987  0.259854
  8      0.130857  0.362989  0.129445  0.068290  0.069791  0.238627
  9      0.121886  0.103921  0.357391  0.122250  0.061109  0.233442
 10      0.124156  0.122486  0.124421  0.356869  0.039570  0.232499

Hard Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.293 -0.248 -0.176 -0.104 -0.122 -0.469 -0.513 -0.533 -0.546 -0.659
 6   -0.291 -0.232 -0.172 -0.101 -0.119 -0.467 -0.522 -0.533 -0.547 -0.659
 7   -0.283 -0.229 -0.163 -0.098 -0.117 -0.471 -0.521 -0.537 -0.547 -0.658
 8   -0.276 -0.229 -0.162 -0.100 -0.130 -0.478 -0.523 -0.539 -0.549 -0.648
 9   -0.277 -0.224 -0.160 -0.108 -0.134 -0.480 -0.528 -0.543 -0.542 -0.646
10   -0.279 -0.227 -0.172 -0.120 -0.146 -0.484 -0.531 -0.539 -0.537 -0.644
11   -0.277 -0.231 -0.175 -0.123 -0.147 -0.488 -0.529 -0.537 -0.537 -0.646
12   -0.286 -0.241 -0.185 -0.134 -0.151 -0.485 -0.526 -0.535 -0.533 -0.655
13   -0.282 -0.236 -0.181 -0.133 -0.156 -0.488 -0.529 -0.537 -0.534 -0.649
14   -0.282 -0.238 -0.188 -0.134 -0.159 -0.489 -0.529 -0.533 -0.536 -0.651
15   -0.280 -0.239 -0.190 -0.144 -0.169 -0.494 -0.531 -0.536 -0.531 -0.648
16   -0.287 -0.250 -0.194 -0.152 -0.179 -0.495 -0.526 -0.540 -0.530 -0.648
17   -0.147 -0.120 -0.074 -0.044 -0.011 -0.122 -0.405 -0.414 -0.402 -0.459
18    0.119  0.144  0.164  0.202  0.268  0.389  0.096 -0.196 -0.155 -0.082
19    0.385  0.384  0.404  0.448  0.484  0.610  0.577  0.264  0.103  0.308

Hard Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.131 -0.098 -0.041  0.022  0.019 -0.119 -0.181 -0.262 -0.309 -0.417
 6   -0.151 -0.107 -0.055  0.009  0.014 -0.164 -0.234 -0.305 -0.349 -0.443
 7   -0.111 -0.072 -0.013  0.053  0.064 -0.069 -0.223 -0.295 -0.332 -0.401
 8   -0.015  0.021  0.084  0.136  0.148  0.092 -0.056 -0.213 -0.253 -0.275
 9    0.090  0.137  0.181  0.226  0.235  0.194  0.111 -0.052 -0.148 -0.128
10    0.215  0.246  0.277  0.314  0.319  0.277  0.211  0.119  0.030  0.030
11    0.272  0.296  0.327  0.361  0.362  0.293  0.222  0.146  0.107  0.113
12   -0.256 -0.232 -0.206 -0.181 -0.179 -0.241 -0.308 -0.380 -0.378 -0.413
13   -0.315 -0.293 -0.270 -0.252 -0.251 -0.301 -0.362 -0.389 -0.423 -0.440
14   -0.363 -0.353 -0.337 -0.315 -0.313 -0.346 -0.366 -0.426 -0.455 -0.460
15   -0.419 -0.414 -0.406 -0.392 -0.383 -0.351 -0.406 -0.466 -0.496 -0.487
16   -0.461 -0.460 -0.454 -0.448 -0.397 -0.376 -0.426 -0.481 -0.510 -0.497
17   -0.534 -0.536 -0.538 -0.493 -0.484 -0.450 -0.475 -0.529 -0.558 -0.546
18   -0.633 -0.634 -0.597 -0.591 -0.586 -0.567 -0.565 -0.593 -0.624 -0.630
19   -0.750 -0.713 -0.712 -0.709 -0.707 -0.699 -0.697 -0.698 -0.712 -0.740

Hard Chart - Player Expected Gains per original unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.587 -0.497 -0.352 -0.209 -0.244 -0.938 -1.025 -1.066 -1.093 -1.318
 6   -0.560 -0.446 -0.324 -0.186 -0.215 -0.870 -1.023 -1.045 -1.074 -1.295
 7   -0.415 -0.317 -0.186 -0.066 -0.059 -0.555 -0.851 -0.936 -0.956 -1.127
 8   -0.165 -0.081  0.032  0.143  0.157 -0.140 -0.433 -0.697 -0.743 -0.802
 9    0.114  0.193  0.286  0.380  0.393  0.175  0.007 -0.281 -0.442 -0.409
10    0.428  0.492  0.554  0.628  0.638  0.446  0.313  0.164  0.007  0.025
11    0.542  0.592  0.654  0.722  0.724  0.479  0.341  0.223  0.164  0.198
12   -0.511 -0.463 -0.413 -0.362 -0.358 -0.556 -0.690 -0.811 -0.789 -0.827
13   -0.630 -0.587 -0.541 -0.503 -0.503 -0.651 -0.775 -0.807 -0.862 -0.880
14   -0.727 -0.706 -0.673 -0.630 -0.627 -0.723 -0.759 -0.862 -0.915 -0.921
15   -0.838 -0.829 -0.812 -0.783 -0.767 -0.716 -0.826 -0.937 -0.992 -0.973
16   -0.921 -0.920 -0.908 -0.896 -0.793 -0.751 -0.853 -0.961 -1.019 -0.995
17   -1.069 -1.072 -1.076 -0.985 -0.967 -0.901 -0.949 -1.058 -1.116 -1.092
18   -1.265 -1.267 -1.195 -1.182 -1.172 -1.135 -1.130 -1.186 -1.248 -1.260
19   -1.499 -1.425 -1.423 -1.417 -1.414 -1.397 -1.395 -1.396 -1.425 -1.481

Hard Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5      H      H      H      H      H      H      H      H      H      H
 6      H      H      H      H      H      H      H      H      H      H
 7      H      H      H      H      H      H      H      H      H      H
 8      H      H      H      D      D      H      H      H      H      H
 9      D      D      D      D      D      H      H      H      H      H
10      D      D      D      D      D      D      D      D      H      H
11      D      D      D      D      D      D      D      D      D      D
12      H      H      S      S      S      H      H      H      H      H
13      S      S      S      S      S      H      H      H      H      H
14      S      S      S      S      S      H      H      H      H      H
15      S      S      S      S      S      H      H      H      H      H
16      S      S      S      S      S      H      H      H      H      H
17      S      S      S      S      S      S      S      S      S      S
18      S      S      S      S      S      S      S      S      S      S
19      S      S      S      S      S      S      S      S      S      S

Hard Chart - Player Strategy (Round >= 2, No Doubling)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 4      H      H      H      H      H      H      H      H      H      H
 5      H      H      H      H      H      H      H      H      H      H
 6      H      H      H      H      H      H      H      H      H      H
 7      H      H      H      H      H      H      H      H      H      H
 8      H      H      H      H      H      H      H      H      H      H
 9      H      H      H      H      H      H      H      H      H      H
10      H      H      H      H      H      H      H      H      H      H
11      H      H      H      H      H      H      H      H      H      H
12      H      H      S      S      S      H      H      H      H      H
13      S      S      S      S      S      H      H      H      H      H
14      S      S      S      S      S      H      H      H      H      H
15      S      S      S      S      S      H      H      H      H      H
16      S      S      S      S      S      H      H      H      H      H
17      S      S      S      S      S      S      S      S      S      S
18      S      S      S      S      S      S      S      S      S      S
19      S      S      S      S      S      S      S      S      S      S
20      S      S      S      S      S      S      S      S      S      S
21      S      S      S      S      S      S      S      S      S      S

Soft Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2   -0.283 -0.241 -0.186 -0.119 -0.114 -0.462 -0.508 -0.517 -0.539 -0.662
A3   -0.284 -0.240 -0.170 -0.116 -0.112 -0.460 -0.505 -0.527 -0.538 -0.661
A4   -0.283 -0.224 -0.166 -0.113 -0.109 -0.458 -0.514 -0.526 -0.538 -0.659
A5   -0.266 -0.221 -0.164 -0.111 -0.108 -0.468 -0.515 -0.525 -0.537 -0.659
A6   -0.132 -0.093 -0.037  0.005  0.010 -0.090 -0.385 -0.407 -0.418 -0.483
A7    0.136  0.167  0.204  0.222  0.262  0.412  0.121 -0.179 -0.186 -0.101
A8    0.402  0.420  0.415  0.461  0.482  0.615  0.608  0.288  0.064  0.290
A9    0.656  0.644  0.654  0.682  0.694  0.773  0.785  0.766  0.555  0.681

Soft Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2    0.039  0.071  0.110  0.159  0.168  0.107  0.039 -0.014 -0.090 -0.184
A3    0.017  0.044  0.091  0.137  0.147  0.060  0.035 -0.060 -0.124 -0.216
A4   -0.012  0.022  0.061  0.108  0.120  0.034 -0.035 -0.114 -0.172 -0.256
A5   -0.032 -0.003  0.038  0.082  0.116 -0.024 -0.084 -0.167 -0.229 -0.296
A6    0.007  0.036  0.077  0.140  0.133  0.060 -0.065 -0.135 -0.189 -0.242
A7    0.065  0.093  0.156  0.175  0.192  0.175  0.047 -0.087 -0.140 -0.160
A8    0.120  0.173  0.187  0.227  0.241  0.222  0.158  0.005 -0.087 -0.081
A9    0.191  0.196  0.230  0.268  0.280  0.243  0.172  0.096  0.007 -0.008

Soft Chart - Player Expected Gains per original unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2   -0.042  0.028  0.115  0.212  0.230 -0.157 -0.312 -0.373 -0.478 -0.586
A3   -0.047  0.011  0.109  0.204  0.222 -0.175 -0.254 -0.394 -0.479 -0.588
A4   -0.070  0.003  0.085  0.175  0.201 -0.141 -0.314 -0.422 -0.495 -0.613
A5   -0.082 -0.019  0.063  0.148  0.217 -0.189 -0.333 -0.452 -0.536 -0.649
A6    0.013  0.074  0.155  0.280  0.266  0.014 -0.230 -0.345 -0.433 -0.522
A7    0.128  0.189  0.313  0.349  0.385  0.240 -0.015 -0.254 -0.322 -0.359
A8    0.237  0.346  0.373  0.453  0.483  0.325  0.190 -0.060 -0.226 -0.200
A9    0.380  0.392  0.459  0.536  0.560  0.351  0.230  0.111 -0.055 -0.055

Soft Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2      H      H      D      D      D      H      H      H      H      H
A3      H      H      D      D      D      H      H      H      H      H
A4      H      H      D      D      D      H      H      H      H      H
A5      H      H      D      D      D      H      H      H      H      H
A6      D      D      D      D      D      H      H      H      H      H
A7      S      D      D      D      D      S      S      H      H      S
A8      S      S      S      S      D      S      S      S      S      S
A9      S      S      S      S      S      S      S      S      S      S

Soft Chart - Player Strategy (Round >= 2, No Doubling)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
12      H      H      H      H      H      H      H      H      H      H
13      H      H      H      H      H      H      H      H      H      H
14      H      H      H      H      H      H      H      H      H      H
15      H      H      H      H      H      H      H      H      H      H
16      H      H      H      H      H      H      H      H      H      H
17      H      H      H      H      H      H      H      H      H      H
18      S      S      S      S      S      S      S      H      H      S
19      S      S      S      S      S      S      S      S      S      S
20      S      S      S      S      S      S      S      S      S      S
21      S      S      S      S      S      S      S      S      S      S

Pairs Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA   -0.274 -0.232 -0.178 -0.130 -0.104 -0.452 -0.500 -0.511 -0.531 -0.663
22   -0.291 -0.251 -0.192 -0.107 -0.125 -0.471 -0.515 -0.523 -0.547 -0.660
33   -0.295 -0.246 -0.160 -0.101 -0.119 -0.467 -0.510 -0.542 -0.546 -0.660
44   -0.290 -0.214 -0.152 -0.095 -0.114 -0.463 -0.529 -0.543 -0.547 -0.656
55   -0.256 -0.206 -0.146 -0.090 -0.112 -0.484 -0.531 -0.541 -0.545 -0.653
66   -0.262 -0.211 -0.152 -0.102 -0.165 -0.493 -0.536 -0.549 -0.552 -0.617
77   -0.268 -0.219 -0.164 -0.156 -0.174 -0.502 -0.539 -0.555 -0.510 -0.631
88   -0.275 -0.228 -0.215 -0.165 -0.178 -0.503 -0.551 -0.516 -0.518 -0.644
99    0.137  0.123  0.167  0.203  0.265  0.401  0.065 -0.196 -0.133 -0.055
TT    0.627  0.636  0.645  0.674  0.697  0.765  0.783  0.744  0.583  0.650

Pairs Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA    0.095  0.120  0.142  0.182  0.200  0.158  0.093 -0.003 -0.048 -0.075
22   -0.113 -0.082 -0.035  0.036  0.032 -0.092 -0.141 -0.222 -0.277 -0.395
33   -0.153 -0.118 -0.047  0.008  0.014 -0.164 -0.231 -0.310 -0.346 -0.444
44   -0.013  0.028  0.098  0.154  0.175  0.111 -0.055 -0.206 -0.246 -0.268
55    0.224  0.254  0.295  0.347  0.362  0.279  0.207  0.119  0.032  0.042
66   -0.253 -0.222 -0.190 -0.162 -0.194 -0.265 -0.322 -0.386 -0.386 -0.411
77   -0.406 -0.388 -0.369 -0.370 -0.367 -0.389 -0.408 -0.475 -0.516 -0.510
88   -0.454 -0.450 -0.461 -0.453 -0.397 -0.374 -0.426 -0.487 -0.512 -0.490
99   -0.627 -0.638 -0.597 -0.590 -0.587 -0.566 -0.566 -0.595 -0.626 -0.621
TT   -0.847 -0.846 -0.846 -0.846 -0.845 -0.843 -0.843 -0.842 -0.840 -0.882

Pairs Chart - Player Expected Gains per original unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA   -0.019  0.055  0.137  0.216  0.248 -0.137 -0.296 -0.421 -0.468 -0.591
22   -0.582 -0.501 -0.384 -0.214 -0.249 -0.942 -1.030 -1.047 -1.094 -1.320
33   -0.567 -0.472 -0.302 -0.184 -0.215 -0.871 -1.000 -1.065 -1.072 -1.298
44   -0.185 -0.082  0.044  0.162  0.193 -0.108 -0.447 -0.701 -0.741 -0.802
55    0.446  0.510  0.590  0.695  0.724  0.466  0.323  0.175  0.014  0.042
66   -0.505 -0.444 -0.380 -0.325 -0.387 -0.599 -0.711 -0.817 -0.803 -0.823
77   -0.813 -0.777 -0.738 -0.741 -0.734 -0.823 -0.858 -0.978 -1.035 -1.019
88   -0.908 -0.900 -0.922 -0.906 -0.793 -0.747 -0.853 -0.974 -1.024 -0.980
99   -1.255 -1.277 -1.194 -1.181 -1.173 -1.132 -1.133 -1.189 -1.252 -1.242
TT   -1.693 -1.693 -1.693 -1.691 -1.690 -1.686 -1.685 -1.684 -1.681 -1.764

Pairs Chart - Player Expected Gains per original unit (Split)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA    1.192  1.223  1.265  1.321  1.344  1.308  1.201  1.039  0.860  0.921
22   -0.128 -0.070 -0.007  0.128  0.126 -0.054 -0.213 -0.383 -0.463 -0.566
33   -0.202 -0.128  0.009  0.117  0.112 -0.115 -0.265 -0.418 -0.509 -0.579
44   -0.236 -0.127 -0.013  0.095  0.083 -0.223 -0.343 -0.493 -0.580 -0.623
55   -0.232 -0.150 -0.038  0.068  0.056 -0.299 -0.448 -0.608 -0.685 -0.695
66   -0.219 -0.135 -0.028  0.068 -0.011 -0.270 -0.413 -0.570 -0.652 -0.660
77   -0.163 -0.084  0.016  0.039  0.053 -0.123 -0.423 -0.564 -0.634 -0.635
88    0.017  0.077  0.106  0.188  0.234  0.202 -0.100 -0.430 -0.464 -0.378
99    0.170  0.170  0.253  0.339  0.359  0.341  0.179 -0.112 -0.268 -0.109
TT    0.412  0.465  0.518  0.596  0.619  0.576  0.447  0.276  0.146  0.140

Pairs Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA      P      P      P      P      P      P      P      P      P      P
22      H      P      P      P      P      P      H      H      H      H
33      H      H      P      P      P      P      H      H      H      H
44      H      H      H      D      D      H      H      H      H      H
55      D      D      D      D      D      D      D      D      H      D
66      P      P      P      P      P      H      H      H      H      H
77      P      P      P      P      P      P      H      H      S      H
88      P      P      P      P      P      P      P      P      P      P
99      P      P      P      P      P      S      P      P      S      S
TT      S      S      S      S      S      S      S      S      S      S

Simulation for Year 1:

After playing 50 times a day for 365 days:
Winning days   :186
Losing days    :171
Breakeven days :8
Biggest win    :25.00
Biggest loss   :26.00
Total win      :211.00
Total staked   :20546.00
Win % staked   : 1.027

Simulation for Year 2:

After playing 50 times a day for 365 days:
Winning days   :174
Losing days    :181
Breakeven days :10
Biggest win    :25.50
Biggest loss   :22.50
Total loss     :213.00
Total staked   :20536.00
Loss % staked  : 1.037

Simulation for Year 3:

After playing 50 times a day for 365 days:
Winning days   :174
Losing days    :182
Breakeven days :9
Biggest win    :23.00
Biggest loss   :26.50
Total loss     :204.50
Total staked   :20542.00
Loss % staked  : 0.996

Simulation for Year 4:

After playing 50 times a day for 365 days:
Winning days   :181
Losing days    :176
Breakeven days :8
Biggest win    :25.50
Biggest loss   :22.00
Total win      :122.50
Total staked   :20555.00
Win % staked   : 0.596

Simulation for Year 5:

After playing 50 times a day for 365 days:
Winning days   :164
Losing days    :187
Breakeven days :14
Biggest win    :25.50
Biggest loss   :21.50
Total loss     :87.00
Total staked   :20566.00
Loss % staked  : 0.423

Simulation for Year 6:

After playing 50 times a day for 365 days:
Winning days   :180
Losing days    :175
Breakeven days :10
Biggest win    :22.50
Biggest loss   :26.00
Total win      :23.50
Total staked   :20524.00
Win % staked   : 0.115

Simulation for Year 7:

After playing 50 times a day for 365 days:
Winning days   :175
Losing days    :181
Breakeven days :9
Biggest win    :21.50
Biggest loss   :19.00
Total win      :15.00
Total staked   :20552.00
Win % staked   : 0.073

Simulation for Year 8:

After playing 50 times a day for 365 days:
Winning days   :185
Losing days    :173
Breakeven days :7
Biggest win    :20.00
Biggest loss   :22.00
Total win      :80.00
Total staked   :20623.00
Win % staked   : 0.388

Simulation for Year 9:

After playing 50 times a day for 365 days:
Winning days   :172
Losing days    :180
Breakeven days :13
Biggest win    :20.50
Biggest loss   :19.00
Total loss     :1.50
Total staked   :20589.00
Loss % staked  : 0.007

Simulation for Year 10:

After playing 50 times a day for 365 days:
Winning days   :172
Losing days    :186
Breakeven days :7
Biggest win    :24.50
Biggest loss   :25.50
Total loss     :15.00
Total staked   :20436.00
Loss % staked  : 0.073

Wren

Translation of: Go
Library: Wren-array
Library: Wren-dynamic
Library: Wren-fmt
Library: Wren-iterate


This runs OK but takes a long time to do so - 6 minutes 21 seconds compared to less than 3 seconds for the Go example. As I also wrote the latter I'm confident it's a faithful translation.

The bottleneck seems to be the dealerProbs method which is called around 300,000 times during the course of the program and contains several arrays (heap allocated in Wren) plus a recursive closure and so is not cheap to run. Making the arrays global and resetting them each time the method is called doesn't help and memoization is out of the question as there are just too many parameter combinations.

So interpreted languages such as Wren are probably stuck with slow times for this task.

import "random"    for Random
import "./array"   for Array, ArrayType
import "./dynamic" for Struct
import "./fmt"     for Fmt
import "./iterate"   for Indexed

var Rand = Random.new()

// 0: deck size, 1 to 10: number of cards of that denomination
var Deck = ArrayType.create("Deck", 11, 0)

var ActionGain = Struct.create("ActionGain", ["action", "gain"])

var NewDeck = Fn.new { Deck.fit([52, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16]) }

// Computed strategy tables
var HTable  = List.filled(15, null)  // hard strategy table (round 1)
var STable  = List.filled( 8, null)  // soft strategy table (round 1)
var PTable  = List.filled(10, null)  // pairs strategy table (round 1)
var HTable2 = List.filled(18, null)  // hard strategy table (round >= 2, no doubling)
var STable2 = List.filled(10, null)  // soft strategy table (round >= 2, no doubling)

for (i in 0..14) HTable[i]  = List.filled(10, null)
for (i in 0..7)  STable[i]  = List.filled(10, null)
for (i in 0..9)  PTable[i]  = List.filled(10, null)
for (i in 0..17) HTable2[i] = List.filled(10, null)
for (i in 0..9)  STable2[i] = List.filled(10, null)

class Blackjack {
    // Returns probabilities of dealer eventually getting:
    // 0: 17, 1: 18, 2: 19, 3: 20, 4: 21 (non-blackjack), 5: blackjack (nil), 6: bust.
    // It is assumed that the dealer has already checked for blackjack, that one deck is used
    // and that the dealer stands on 'soft' 17.
    static dealerProbs(upCard, startDeck) {
        var res     = List.filled(7, 0)     // results
        var decks   = List.filled(9, null)  // decks for each level
        var scores  = List.filled(9, 0)     // scores for each level
        var elevens = List.filled(9, 0)     // number of aces for each level scored as 11
        var probs   = List.filled(9, 0)     // probs for each level
        decks[0]    = startDeck.toList
        scores[0]   = upCard
        if (upCard == 1) {  // an ace
            scores[0] = 11
            elevens[0] = 1
        }
        probs[0] = 1
        var f  // recursive closure
        f = Fn.new { |lev|
            for (c in 1..10) {
                if (decks[lev][c] == 0) continue  // card no longer present in deck
                // temporary variables for current level
                var deck   = decks[lev].toList
                var score  = scores[lev]
                var eleven = elevens[lev]
                var prob   = probs[lev]
                score = score + c  // add card to score
                if (c == 1) {  // score all aces initially as 11
                    score = score + 10
                    eleven = eleven + 1
                }
                prob = prob * deck[c] / deck[0]
                if (score > 21 && eleven > 0) {
                    score = score - 10  // bust but can demote an ace
                    eleven = eleven - 1
                }
                if (lev == 0 && ((upCard == 1 && c == 10) || (upCard == 10 && c == 1))) {
                    res[5] = res[5] + prob  // blackjack, allow for now
                } else if (score >= 17 && score <= 21) {
                    res[score-17] = res[score-17] + prob  // 17 to (non-blackjack) 21
                } else if (score > 21 && eleven == 0) {
                    res[6] = res[6] + prob  // bust
                } else {
                    deck[c] = deck[c] - 1  // remove card from deck
                    deck[0] = deck[0] - 1  // decrement deck size
                    var lev2 = lev + 1
                    decks[lev2]   = deck
                    scores[lev2]  = score
                    elevens[lev2] = eleven
                    probs[lev2]   = prob
                    f.call(lev2)  // get another card
                }
            }
        }
        f.call(0)
        // but can't have blackjack, so adjust probabilities accordingly
        var pnbj = 1 - res[5]
        for (i in 0..6) res[i] = res[i] / pnbj
        res[5] = 0
        return res
    }

    // Prints chart of dealer probabilities (as a check against an external source).
    static dealerChart() {
        System.print("Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules")
        System.print("Up Card     17        18        19        20        21       Bust")
        System.print("-------------------------------------------------------------------")
        var deck = NewDeck.call()
        deck[0] = 51
        for (uc in 1..10) {
            var deck2 = deck.toList
            deck2[uc] = deck2[uc] - 1
            var dp = dealerProbs(uc, deck2)
            if (uc > 1) {
                Fmt.write("$3d      ", uc)
            } else {
               System.write("Ace      ")
            }
            Fmt.lprint("$f  $f  $f  $f  $f  $f", [dp[0], dp[1], dp[2], dp[3], dp[4], dp[6]])
        }
    }

    // Returns player's expected gain per unit staked after hitting once and then standing.
    static playerGain(card1, card2, uc, startDeck) {
        var eg = 0
        var deck = startDeck.toList
        var score = card1 + card2
        var eleven = false
        if (card1 == 1 || card2 == 1) {  // an ace
            score = score + 10
            eleven = true
        }
        for (c in 1..10) {  // get another card
            if (deck[c] == 0) continue  // card no longer present in deck
            // temporary variables for current card
            var deck2   = deck.toList
            var score2  = score
            var eleven2 = eleven
            score2 = score2 + c  // add card to score
            if (c == 1) {  // score all aces initially as 11
                score2 = score2 + 10
                eleven2 = true
            }
            var prob = deck2[c] / deck2[0]
            deck2[c] = deck2[c] - 1  // remove card from deck
            deck2[0] = deck2[0] - 1  // decrement deck size
            if (score2 > 21 && eleven2) {
                score2 = score2 - 10  // bust but can demote an ace
            }
            if (score2 <= 21) {
                var dp = dealerProbs(uc, deck2)
                eg = eg + calcGain(score2, dp) * prob
            } else {  // bust
                eg = eg - prob
            }
        }
        return eg
    }

    // Returns player's expected gain per unit staked after hitting once and then continuing
    // in accordance with the tables for rounds >= 2.
    static playerGain2(card1, card2, uc, startDeck) {
        var eg      = 0                     // result
        var decks   = List.filled(9, null)  // decks for each level
        var scores  = List.filled(9, 0)     // scores for each level
        var elevens = List.filled(9, 0)     // number of aces for each level scored as 11
        var probs   = List.filled(9, 0)     // probs for each level
        decks[0]    = startDeck.toList
        scores[0]   = card1 + card2
        if (card1 == 1 || card2 == 1) {  // an ace
            scores[0] = scores[0] + 10
            elevens[0] = 1
        }
        probs[0] = 1
        var f  // recursive closure
        f = Fn.new { |lev|
            for (c in 1..10) {
                if (decks[lev][c] == 0) continue  // card no longer present in deck
                // temporary variables for current level
                var deck   = decks[lev].toList
                var score  = scores[lev]
                var eleven = elevens[lev]
                var prob   = probs[lev]
                score = score + c  // add card to score
                if (c == 1) {  // score all aces initially as 11
                    score = score + 10
                    eleven = eleven + 1
                }
                prob = prob * deck[c] / deck[0]
                if (score > 21 && eleven > 0) {
                    score = score - 10  // bust but can demote an ace
                    eleven = eleven - 1
                }
                deck[c] = deck[c] - 1  // remove card from deck
                deck[0] = deck[0] - 1  // decrement deck size
                if ((eleven == 0 && (score >= 17 || (score >= 13 && uc < 7)) ||
                    (eleven == 0 && score == 12 && uc >= 4 && uc <= 6) ||
                    (eleven > 0 && score == 18 && uc != 9 && uc != 10) ||
                    (eleven > 0 && score >= 19)) && score <= 21) {
                        var dp = dealerProbs(uc, deck)
                        eg = eg + calcGain(score, dp) * prob
                } else if (score > 21 && eleven == 0) {  // bust
                    eg = eg - prob
                } else {
                    var lev2 = lev + 1
                    decks[lev2]   = deck
                    scores[lev2]  = score
                    elevens[lev2] = eleven
                    probs[lev2]   = prob
                    f.call(lev2)  // get another card
                }
            }
        }
        f.call(0)
        return eg
    }

    // Calculates gain per unit staked for a given scenario (helper function).
    static calcGain(pscore, dp) {
        var eg = 0
        if (pscore == 17) {
            eg = eg + dp[6]                         // dealer is bust
            eg = eg - dp[1] - dp[2] - dp[3] - dp[4] // dealer has 18 to 21
        } else if (pscore == 18) {
            eg = eg + dp[0] + dp[6]          // dealer has 17 or is bust
            eg = eg - dp[2] - dp[3] - dp[4]  // dealer has 19 to 21
        } else if (pscore == 19) {
            eg = eg + dp[0] + dp[1] + dp[6]  // dealer has 17, 18 or is bust
            eg = eg - dp[3] - dp[4]          // dealer has 20 or 21
        } else if (pscore == 20) {
            eg = eg + dp[0] + dp[1] + dp[2] + dp[6]  // dealer has 17 to 19 or is bust
            eg = eg - dp[4]                          // dealer has (non-blackjack) 21
        } else if (pscore == 21) {
            eg = eg + dp[0] + dp[1] + dp[2] + dp[3] + dp[6]  // dealer has 17 to 20 or is bust
        } else if (pscore == 22) {  // notional
            eg = eg + 1.5  // player blackjack
        } else if (pscore == 23) {  // notional
            eg = eg - 1  // player bust, loses stake irrespective of what dealer has
        } else {  // player has less than 17
            eg = eg + dp[6]        // dealer is bust
            eg = eg - (1 - dp[6])  // dealer isn't bust
        }
        return eg
    }

    // Returns player's expected gains per unit staked, for each dealer up-card, after standing.
    static stand(card1, card2) {
        var deck = NewDeck.call()
        deck[card1] = deck[card1] - 1
        deck[card2] = deck[card2] - 1
        deck[0] = 50
        var pscore = card1 + card2  // player score
        if (card1 == 1 || card2 == 1) pscore = pscore + 10
        var egs = List.filled(10, 0)  // results
        for (uc in 1..10) {         // dealer's up-card
            var deck2 = deck.toList
            deck2[uc] = deck2[uc] - 1
            deck2[0] = deck2[0] - 1
            var dp = dealerProbs(uc, deck2)
            var eg = calcGain(pscore, dp)  // expected gain for this up-card
            if (uc > 1) {
                egs[uc-2] = eg
            } else {  // dealer has Ace
                egs[9] = eg  // ace comes last in tables
            }
        }
        return egs
    }

    // Returns player's expected gains per unit staked, for each dealer up-card, after
    // hitting once and then either standing (once == true) or continuing
    // as per the round >= 2 tables (once == false).
    static hit(card1, card2, once) {
        var deck = NewDeck.call()
        deck[card1] = deck[card1] - 1
        deck[card2] = deck[card2] - 1
        deck[0] = 50
        var egs = List.filled(10, 0)  // results
        for (uc in 1..10) {           // dealer's up-card
            var deck2 = deck.toList
            deck2[uc] = deck2[uc] - 1
            deck2[0] = 49
            var peg = once ? playerGain (card1, card2, uc, deck2) :
                             playerGain2(card1, card2, uc, deck2)
            if (uc > 1) {
                egs[uc-2] = peg
            } else {  // dealer has Ace
                egs[9] = peg
            }
        }
        return egs
    }

    // Returns player's expected gains per unit oiginally staked, for each dealer up-card,
    // after doubling i.e. hitting once and then standing with a doubled stake.
    static double(card1, card2) {
        var egs = hit(card1, card2, true)  // hit once and then stand
        for (i in 0..9) egs[i] = egs[i] * 2
        return egs
    }

    // Returns player's expected gains per unit originally staked, for each dealer up-card,
    // after splitting a pair and doubling the stake, getting a second card for each hand
    // and then continuing in accordance with the rounds >= 2 tables. It is assumed that a
    // player cannot double or re-split following a split. It is also assumed
    // (in the interests of simplicity) that the expected gains for each split hand (after
    // calculating the gains for the first hand as though the second hand is not completed)
    // are exactly the same.
    static split(card) {
        var deck = NewDeck.call()
        deck[card] = deck[card] - 2  // must be a pair
        deck[0] = 50
        var egs = List.filled(10, 0)  // overall results

        // now play a single hand
        var score = card
        var eleven = 0
        if (card == 1) {  // an ace
            score = 11
            eleven = 1
        }
        for (uc in 1..10) {  // collect results for each dealer up-card
            if (deck[uc] == 0) continue  // card no longer present in deck
            var deck2 = deck.toList
            deck2[uc] = deck2[uc] - 1
            deck2[0]  = deck2[0] - 1
            var ix = uc - 2
            if (ix  == -1) ix = 9  // in tables ace comes last
            var peg = 0  // player expected gain for this up-card
            // get second player card
            for (c in 1..10) {
                if (deck2[c] == 0) continue  // card no longer present in deck
                var prob = deck2[c] / deck2[0]
                var deck3 = deck2.toList
                deck3[c] = deck3[c] - 1
                deck3[0] = deck3[0] - 1
                var score2 = score + c
                var eleven2 = eleven
                if (c == 1) {  // score all aces initially as 11
                    score2 = score2 + 10
                    eleven2 = eleven2 + 1
                }
                if (score2 == 21) {  // player has blackjack & we know dealer hasn't
                    peg = peg + 1.5 * prob
                    continue
                }
                if (score2 > 21 && eleven2 > 0) {
                    score2 = score2 - 10  // bust but can demote an ace
                    eleven2 = eleven2 - 1
                }
                var action
                if (eleven2 > 0) {
                    action = STable2[score2-12][ix]  // use soft strategy table, no doubling
                } else {  // including pairs as no re-splitting
                    action = HTable2[score2-4][ix]   // use hard strategy table, no doubling
                }
                var peg2
                if (action == "S") {
                    var dp = dealerProbs(uc, deck3)
                    peg2 = calcGain(score2, dp)
                } else {
                    peg2 = playerGain2(card, c, uc, deck3)
                }
                peg = peg + peg2 * prob
            }
            if (uc > 1) {
                egs[uc-2] = peg * 2 // allow for both hands in overall results
            } else {
                egs[9] = peg * 2    // ditto
            }
        }
        return egs
    }

    // Returns the action with the highest expected gain.
    static bestAction(ags) {
        var max = ags[0].gain
        var maxi = 0
        for (i in 1...ags.count) {
            if (ags[i].gain > max) {
                max = ags[i].gain
                maxi = i
            }
        }
        return ags[maxi].action
    }

    // Prints title and header for a given chart.
    static printHeader(title) {
        System.print(title)
        System.print("P/D     2      3      4      5      6      7      8      9      T      A")
        System.print("--------------------------------------------------------------------------")
    }

    // Prints header for a pair of cards.
    static printPair(c) {
        if (c == 1) {
            System.write("AA   ")
        } else if (c == 10) {
            System.write("TT   ")
        } else {
            Fmt.write("$d$d   ", c, c)
        }
    }

    // Simulates 'perDay' blackjack games for 'days' days.
    static simulate(perDay, days) {
        var winDays  = 0
        var loseDays = 0
        var evenDays = 0
        var bigWin   = 0
        var bigLoss  = 0
        var totGain  = 0
        var totStake = 0
        for (d in 1..days) {
            var dailyGain  = 0
            var dailyStake = 0
            for (p in 1..perDay) {
                var gs = playerPlay()
                dailyGain  = dailyGain + gs[0]
                dailyStake = dailyStake + gs[1]
            }
            if (dailyGain > 0) {
                winDays = winDays + 1
            } else if (dailyGain < 0) {
                loseDays = loseDays + 1
            } else {
                evenDays = evenDays + 1
            }
            if (dailyGain > bigWin) {
                bigWin = dailyGain
            } else if (-dailyGain > bigLoss) {
                bigLoss = -dailyGain
            }
            totGain  = totGain + dailyGain
            totStake = totStake + dailyStake
        }
        Fmt.print("\nAfter playing $d times a day for $d days:", perDay, days)
        Fmt.print("Winning days   : $d", winDays)
        Fmt.print("Losing days    : $d", loseDays)
        Fmt.print("Breakeven days : $d", evenDays)
        Fmt.print("Biggest win    : $h", bigWin)
        Fmt.print("Biggest loss   : $h", bigLoss)
        if (totGain < 0) {
            Fmt.print("Total loss     : $h", -totGain)
            Fmt.print("Total staked   : $h", totStake)
            Fmt.print("Loss \% staked  : $0.3f", -totGain/totStake*100)
        } else {
            Fmt.print("Total win      : $h", totGain)
            Fmt.print("Total staked   : $h", totStake)
            Fmt.print("Win \% staked   : $0.3f", totGain/totStake*100)
        }
    }

    // Simulates a dealer's play for a given player's hand and state of deck.
    // Returns the player's gain (positive or negative) per unit staked.
    static dealerPlay(pscore, next, cards, d) {
        var dscore = d[0] + d[1]
        var aces = 0
        if (d[0] == 1 || d[1] == 1) { // dealer has an ace
            dscore = dscore + 10
            aces = aces + 1
        }
        while (true) {
            if (dscore > 21 && aces > 0) {
                dscore = dscore - 10  // bust but we can demote an ace
                aces = aces - 1
            }
            if (dscore > 21) {
                return [1, next]  // dealer is bust and player gains stake
            }
            if (dscore >= 17) {  // dealer must stick on 17 or above, hard or not
                if (dscore > pscore) {
                    return [-1, next]  // dealer wins and player loses stake
                } else if (dscore == pscore) {
                    break  // player breaks even
                } else {
                    return [1, next]  // dealer loses and player gains stake
                }
            }
            var nc = cards[next] // get new card from pack
            next = next + 1
            dscore = dscore + nc
            if (nc == 1) {  // count aces initially as 11
                dscore = dscore + 10
                aces = aces + 1
            }
        }
        return [0, next]
    }

    // Simulates the playing of a random player's hand according to the strategy tables.
    // Returns both the gain (positive or negative) and the stake (1 or 2).
    static playerPlay() {
        var perm = (0..51).toList
        Rand.shuffle(perm) // randomizes integers from 0 to 51 inclusive
        var cards = List.filled(52, 0)
        for (se in Indexed.new(perm)) {
            var card = (se.value/4).floor + 1
            if (card > 10) card = 10
            cards[se.index] = card
        }
        var p = []  // player hand
        var d = []  // dealer hand
        // initial deal
        for (se in Indexed.new(cards[0..3])) {
            if (se.index < 2) {
                p.add(se.value)
            } else {
                d.add(se.value)
            }
        }
        var next = 4  // index of next card to be dealt

        // check if dealer and/or player have blackjack
        var dbj = (d[0] == 1 && d[1] == 10) || (d[0] == 10 && d[1] == 1)
        var pbj = (p[0] == 1 && p[1] == 10) || (p[0] == 10 && p[1] == 1)
        if (dbj) {
            if (pbj) return [0, 1]  // player neither wins nor loses
            return [-1, 1]  // player loses stake
        }
        if (pbj) return [1.5, 1]  // player wins 1.5 x stake
        var uc = d[0]  // dealer's up-card for accessing tables
        if (uc == 0) {
            uc = 9  // move ace to last place
        } else {
            uc = uc - 1  // move others down 1
        }
        var stake = 1      // player's initial stake
        var fscores = List.filled(2, 0)  // final player scores (one or, after split, two hands)
        var action = ""
        var score = 0 
        var aces  = 0

        var h = Fn.new { |hand|  // processes a 'hit'
            while (true) {
                var nc = cards[next]  // get new card from pack
                next = next + 1
                score = score + nc
                if (nc == 1) {  // count aces initially as 11
                    score = score + 10
                    aces= aces + 1
                }
                if (score > 21 && aces > 0) {
                    score = score - 10  // bust but we can demote an ace
                    aces = aces - 1
                }
                if (score > 21) {
                    fscores[hand] = 22 // player is bust and loses stake
                    return
                }
                if (action == "D") {
                    fscores[hand] = score
                    return
                }
                // get further strategy and act accordingly
                if (aces == 0) {
                    action = HTable2[score-4][uc]
                } else {
                    action = STable2[score-12][uc]
                }
                if (action == "S") {  // stand
                    fscores[hand] = score
                    return
                }
            }
        }

        score = p[0] + p[1]
        // get kind of player hand: hard, soft, pair
        var kind
        if (p[0] == p[1]) {
            kind = "pair"
        } else if (p[0] == 1 || p[1] == 1) {
            kind = "soft"
        } else {
            kind = "hard"
        }
        if (kind == "hard") {
            action = HTable[score-5][uc]
        } else if (kind == "soft") {  // includes one ace
            var otherCard = p[0]
            if (otherCard == 1) otherCard = p[1]
            score = score + 10
            aces = 1
            action = STable[otherCard-2][uc]
        } else if (kind == "pair") {
            if (p[0] == 1) {  // pair of aces
                score = score + 10
                aces = 2
            }
            action = PTable[p[0]-1][uc]
        }
        if (action == "S") {  // stand
            fscores[0] = score
        } else if (action == "H") {  // hit
            h.call(0)
        } else if (action == "D") {  // double
            h.call(0)
            stake = 2
        } else if (action == "P") {  // split
            for (hand in 0..1) {
                score = p[0]
                aces = 0
                if (score == 1) {  // count aces initially as 11
                    score = 11
                    aces = aces + 1
                }
                h.call(hand)
            }
        }
        var sum = 0
        if (fscores[0] < 22) {
            var res = dealerPlay(fscores[0], next, cards, d)
            sum = sum + res[0] * stake
            next = res[1]
        } else {
            sum = sum - stake  // this hand is bust
        }
        if (fscores[1] > 0) {  // pair
            if (fscores[1] < 22) {
                var res = dealerPlay(fscores[1], next, cards, d)
                sum = sum + res[0]
                next = res[1]
            } else {
                sum = sum - 1 // this hand is bust
            }
            stake = 2
        }
        return [sum, stake]
    }

    static main() {
        // print dealer probabilities chart
        dealerChart()

        // for hard scores (i.e. different cards, no aces)
        var tuples = [
            [2,  3],
            [2,  4],
            [2,  5], [3, 4],
            [2,  6], [3, 5],
            [2,  7], [3, 6], [4, 5],
            [2,  8], [3, 7], [4, 6],
            [2,  9], [3, 8], [4, 7], [5, 6],
            [2, 10], [3, 9], [4, 8], [5, 7],
            [3, 10], [4, 9], [5, 8], [6, 7],
            [4, 10], [5, 9], [6, 8],
            [5, 10], [6, 9], [7, 8],
            [6, 10], [7, 9],
            [7, 10], [8, 9],
            [8, 10],
            [9, 10]
        ]

        // number of tuples for each player score from 5 to 19
        var counts = Array.from([1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1])
        // expected gains for each player score & for each dealer up-card
        var segs = List.filled(15, null)  // if stands
        var hegs = List.filled(15, null)  // if hits
        var degs = List.filled(15, null)  // if doubles
        for (i in 0..14) {
            segs[i] = List.filled(10, 0)
            hegs[i] = List.filled(10, 0)
            degs[i] = List.filled(10, 0)
        }
        for (tuple in tuples) {
            var i  = tuple[0] + tuple[1]
            var sg = stand(tuple[0], tuple[1])
            var hg = hit(tuple[0], tuple[1], false)
            var dg = double(tuple[0], tuple[1])
            for (j in 0..9) {
                segs[i-5][j] = segs[i-5][j] + sg[j]
                hegs[i-5][j] = hegs[i-5][j] + hg[j]
                degs[i-5][j] = degs[i-5][j] + dg[j]
            }
        }

        // calculate the average per tuple for each score
        for (i in 0..14) {
            for (j in 0..9) {
                segs[i][j] = segs[i][j] / counts[i]
                hegs[i][j] = hegs[i][j] / counts[i]
                degs[i][j] = degs[i][j] / counts[i]
            }
        }

        printHeader("\nHard Chart - Player Expected Gains per unit (Stand)")
        for (i in 5..19) {
            Fmt.write("$2d   ", i)
            for (j in 0..9) Fmt.write("$6.3f ", segs[i-5][j])
            System.print()
        }

        printHeader("\nHard Chart - Player Expected Gains per unit (Hit)")
        for (i in 5..19) {
            Fmt.write("$2d   ", i)
            for (j in 0..9) Fmt.write("$6.3f ", hegs[i-5][j])
            System.print()
        }

        printHeader("\nHard Chart - Player Expected Gains per original unit (Double)")
        for (i in 5..19) {
            Fmt.write("$2d   ", i)
            for (j in 0..9) Fmt.write("$6.3f ", degs[i-5][j])
            System.print()
        }

        printHeader("\nHard Chart - Player Strategy (Round 1)")
        for (i in 5..19) {
            Fmt.write("$2d   ", i)
            for (j in 0..9) {
                var ags = [
                    ActionGain.new("S", segs[i-5][j]),
                    ActionGain.new("H", hegs[i-5][j]),
                    ActionGain.new("D", degs[i-5][j])
                ]
                var action = bestAction(ags)
                HTable[i-5][j] = action
                Fmt.write("$4s   ", action)
            }
            System.print()
        }

        // for hard scores (no aces) - after round 1 (no doubling or splitting)
        // based on hard table figures (round 1) with scores of 4, 20, and 21 added
        var segs2 = List.filled(18, null)  // expected gains if stands
        var hegs2 = List.filled(18, null)  // expected gains if hits
        for (i in 0..17) {
            segs2[i] = List.filled(10, 0)
            hegs2[i] = List.filled(10, 0)
        }
        for (i in 5..19) {
            segs2[i-4] = segs[i-5]
            hegs2[i-4] = hegs[i-5]
        }
        var sg4  = stand(2, 2)
        var hg4  = hit(2, 2, false)
        var sg20 = stand(10, 10)
        var hg20 = hit(10, 10, false)
        var sg21 = stand(1, 10)
        var hg21 = hit(1, 10, false)
        for (j in 0..9) {
            segs2[0][j]  = segs2[0][j]  + sg4[j]
            hegs2[0][j]  = hegs2[0][j]  + hg4[j]
            segs2[16][j] = segs2[16][j] + sg20[j]
            hegs2[16][j] = hegs2[16][j] + hg20[j]
            segs2[17][j] = segs2[17][j] + sg21[j]
            hegs2[17][j] = hegs2[17][j] + hg21[j]
        }

        printHeader("\nHard Chart - Player Strategy (Round >= 2, No Doubling)")
        for (i in 4..21) {
            Fmt.write("$2d   ", i)
            for (j in 0..9) {
                var action = "S"
                if (hegs2[i-4][j] > segs2[i-4][j]) action = "H"
                HTable2[i-4][j] = action
                Fmt.write("$4s   ", action)
            }
            System.print()
        }

        /* for soft scores (i.e. including exactly one ace) */

        // expected gains for each player second card (2 to 9) & for each dealer up-card
        var segs3 = List.filled(8, null)  // if stands
        var hegs3 = List.filled(8, null)  // if hits
        var degs3 = List.filled(8, null)  // if doubles
        for (i in 0..7) {
            segs3[i] = List.filled(10, 0)
            hegs3[i] = List.filled(10, 0)
            degs3[i] = List.filled(10, 0)
        }
        for (c in 2..9) {
            var sg = stand(1, c)
            var hg = hit(1, c, false)
            var dg = double(1, c)
            for (j in 0..9) {
                segs3[c-2][j] = segs3[c-2][j] + sg[j]
                hegs3[c-2][j] = hegs3[c-2][j] + hg[j]
                degs3[c-2][j] = degs3[c-2][j] + dg[j]
            }
        }

        printHeader("\nSoft Chart - Player Expected Gains per unit (Stand)")
        for (c in 2..9) {
            Fmt.write("A$d   ", c)
            for (j in 0..9) Fmt.write("$6.3f ", segs3[c-2][j])
            System.print()
        }

        printHeader("\nSoft Chart - Player Expected Gains per unit (Hit)")
        for (c in 2..9) {
            Fmt.write("A$d   ", c)
            for (j in 0..9) Fmt.write("$6.3f ", hegs3[c-2][j])
            System.print()
        }

        printHeader("\nSoft Chart - Player Expected Gains per unit (Double)")
        for (c in 2..9) {
            Fmt.write("A$d   ", c)
            for (j in 0..9) Fmt.write("$6.3f ", degs3[c-2][j])
            System.print()
        }

        printHeader("\nSoft Chart - Player Strategy (Round 1)")
        for (c in 2..9) {
            Fmt.write("A$d   ", c)
            for (j in 0..9) {
                var ags = [
                    ActionGain.new("S", segs3[c-2][j]),
                    ActionGain.new("H", hegs3[c-2][j]),
                    ActionGain.new("D", degs3[c-2][j])
                ]
                var action = bestAction(ags)
                STable[c-2][j] = action
                Fmt.write("$4s   ", action)
            }
            System.print()
        }

        // for soft scores (at least one ace) - after round 1 (no doubling or splitting)
        // based on soft table figures (round 1) with scores of 12 and 21 added
        // assumes one ace counted as 11
        var segs4 = List.filled(10, null)  // expected gains if stands
        var hegs4 = List.filled(10, null)  // expected gains if hits
        for (i in 0..9) {
            segs4[i] = List.filled(10, 0)
            hegs4[i] = List.filled(10, 0)
        }
        for (i in 1..8) {
            segs4[i] = segs3[i-1]
            hegs4[i] = hegs3[i-1]
        }
        var sg12 = stand(1, 1)
        var hg12 = hit(1, 1, false)
        for (j in 0..9) {
            segs4[0][j] = segs4[0][j] + sg12[j]
            hegs4[0][j] = hegs4[0][j] + hg12[j]
            segs4[9][j] = segs4[9][j] + sg21[j]
            hegs4[9][j] = hegs4[9][j] + hg21[j]
        }

        printHeader("\nSoft Chart - Player Strategy (Round >= 2, No Doubling)")
        for (i in 12..21) {
            Fmt.write("$2d   ", i)
            for (j in 0..9) {
                var action = "S"
                if (hegs4[i-12][j] > segs4[i-12][j]) action = "H"
                STable2[i-12][j] = action
                Fmt.write("$4s   ", action)
            }
            System.print()
        }

        /* for pairs */

        // expected gains for each pair (A to 10) & for each dealer up-card
        var segs5 = List.filled(10, null)  // if stands
        var hegs5 = List.filled(10, null)  // if hits
        var degs5 = List.filled(10, null)  // if doubles
        var pegs5 = List.filled(10, null)  // if splits
        for (i in 0..9) {
            segs5[i] = List.filled(10, 0)
            hegs5[i] = List.filled(10, 0)
            degs5[i] = List.filled(10, 0)
            pegs5[i] = List.filled(10, 0)
        }
        for (c in 1..10) {
            var sg = stand(c, c)
            var hg = hit(c, c, false)
            var dg = double(c, c)
            var pg = split(c)
            for (j in 0..9) {
                segs5[c-1][j] = segs5[c-1][j] + sg[j]
                hegs5[c-1][j] = hegs5[c-1][j] + hg[j]
                degs5[c-1][j] = degs5[c-1][j] + dg[j]
                pegs5[c-1][j] = pegs5[c-1][j] + pg[j]
            }
        }

        printHeader("\nPairs Chart - Player Expected Gains per unit (Stand)")
        for (c in 1..10) {
            printPair(c)
            for (j in 0..9) Fmt.write("$6.3f ", segs5[c-1][j])
            System.print()
        }

        printHeader("\nPairs Chart - Player Expected Gains per unit (Hit)")
        for (c in 1..10) {
            printPair(c)
            for (j in 0..9) Fmt.write("$6.3f ", hegs5[c-1][j])
            System.print()
        }

        printHeader("\nPairs Chart - Player Expected Gains per unit (Double)")
        for (c in 1..10) {
            printPair(c)
            for (j in 0..9) Fmt.write("$6.3f ", degs5[c-1][j])
            System.print()
        }

        printHeader("\nPairs Chart - Player Expected Gains per unit (Split)")
        for (c in 1..10) {
            printPair(c)
            for (j in 0..9) Fmt.write("$6.3f ", pegs5[c-1][j])
            System.print()
        }

        printHeader("\nPairs Chart - Player Strategy (Round 1)")
        for (c in 1..10) {
            printPair(c)
            for (j in 0..9) {
                var ags = [
                    ActionGain.new("S", segs5[c-1][j]),
                    ActionGain.new("H", hegs5[c-1][j]),
                    ActionGain.new("D", degs5[c-1][j]),
                    ActionGain.new("P", pegs5[c-1][j]),
                ]
                var action = bestAction(ags)
                PTable[c-1][j] = action
                Fmt.write("$4s   ", action)
            }
            System.print()
        }

        // do 10 years of simulations
        for (i in 1..10) {
            Fmt.print("\nSimulation for Year $d:", i)
            simulate(50, 365)
        }
    }
}

Blackjack.main()
Output:
Dealer Probabilities, Stands on Soft 17, 1 Deck, U.S Rules
Up Card     17        18        19        20        21       Bust
-------------------------------------------------------------------
Ace      0.183786  0.190890  0.188680  0.191692  0.075137  0.169815
  2      0.138976  0.131762  0.131815  0.123948  0.120526  0.352973
  3      0.130313  0.130946  0.123761  0.123345  0.116047  0.375588
  4      0.130973  0.114163  0.120679  0.116286  0.115096  0.402803
  5      0.119687  0.123483  0.116909  0.104694  0.106321  0.428905
  6      0.166948  0.106454  0.107192  0.100705  0.097878  0.420823
  7      0.372345  0.138583  0.077334  0.078897  0.072987  0.259854
  8      0.130857  0.362989  0.129445  0.068290  0.069791  0.238627
  9      0.121886  0.103921  0.357391  0.122250  0.061109  0.233442
 10      0.124156  0.122486  0.124421  0.356869  0.039570  0.232499

Hard Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.293 -0.248 -0.176 -0.104 -0.122 -0.469 -0.513 -0.533 -0.546 -0.659 
 6   -0.291 -0.232 -0.172 -0.101 -0.119 -0.467 -0.522 -0.533 -0.547 -0.659 
 7   -0.283 -0.229 -0.163 -0.098 -0.117 -0.471 -0.521 -0.537 -0.547 -0.658 
 8   -0.276 -0.229 -0.162 -0.100 -0.130 -0.478 -0.523 -0.539 -0.549 -0.648 
 9   -0.277 -0.224 -0.160 -0.108 -0.134 -0.480 -0.528 -0.543 -0.542 -0.646 
10   -0.279 -0.227 -0.172 -0.120 -0.146 -0.484 -0.531 -0.539 -0.537 -0.644 
11   -0.277 -0.231 -0.175 -0.123 -0.147 -0.488 -0.529 -0.537 -0.537 -0.646 
12   -0.286 -0.241 -0.185 -0.134 -0.151 -0.485 -0.526 -0.535 -0.533 -0.655 
13   -0.282 -0.236 -0.181 -0.133 -0.156 -0.488 -0.529 -0.537 -0.534 -0.649 
14   -0.282 -0.238 -0.188 -0.134 -0.159 -0.489 -0.529 -0.533 -0.536 -0.651 
15   -0.280 -0.239 -0.190 -0.144 -0.169 -0.494 -0.531 -0.536 -0.531 -0.648 
16   -0.287 -0.250 -0.194 -0.152 -0.179 -0.495 -0.526 -0.540 -0.530 -0.648 
17   -0.147 -0.120 -0.074 -0.044 -0.011 -0.122 -0.405 -0.414 -0.402 -0.459 
18    0.119  0.144  0.164  0.202  0.268  0.389  0.096 -0.196 -0.155 -0.082 
19    0.385  0.384  0.404  0.448  0.484  0.610  0.577  0.264  0.103  0.308 

Hard Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.131 -0.098 -0.041  0.022  0.019 -0.119 -0.181 -0.262 -0.309 -0.417 
 6   -0.151 -0.107 -0.055  0.009  0.014 -0.164 -0.234 -0.305 -0.349 -0.443 
 7   -0.111 -0.072 -0.013  0.053  0.064 -0.069 -0.223 -0.295 -0.332 -0.401 
 8   -0.015  0.021  0.084  0.136  0.148  0.092 -0.056 -0.213 -0.253 -0.275 
 9    0.090  0.137  0.181  0.226  0.235  0.194  0.111 -0.052 -0.148 -0.128 
10    0.215  0.246  0.277  0.314  0.319  0.277  0.211  0.119  0.030  0.030 
11    0.272  0.296  0.327  0.361  0.362  0.293  0.222  0.146  0.107  0.113 
12   -0.256 -0.232 -0.206 -0.181 -0.179 -0.241 -0.308 -0.380 -0.378 -0.413 
13   -0.315 -0.293 -0.270 -0.252 -0.251 -0.301 -0.362 -0.389 -0.423 -0.440 
14   -0.363 -0.353 -0.337 -0.315 -0.313 -0.346 -0.366 -0.426 -0.455 -0.460 
15   -0.419 -0.414 -0.406 -0.392 -0.383 -0.351 -0.406 -0.466 -0.496 -0.487 
16   -0.461 -0.460 -0.454 -0.448 -0.397 -0.376 -0.426 -0.481 -0.510 -0.497 
17   -0.534 -0.536 -0.538 -0.493 -0.484 -0.450 -0.475 -0.529 -0.558 -0.546 
18   -0.633 -0.634 -0.597 -0.591 -0.586 -0.567 -0.565 -0.593 -0.624 -0.630 
19   -0.750 -0.713 -0.712 -0.709 -0.707 -0.699 -0.697 -0.698 -0.712 -0.740 

Hard Chart - Player Expected Gains per original unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5   -0.587 -0.497 -0.352 -0.209 -0.244 -0.938 -1.025 -1.066 -1.093 -1.318 
 6   -0.560 -0.446 -0.324 -0.186 -0.215 -0.870 -1.023 -1.045 -1.074 -1.295 
 7   -0.415 -0.317 -0.186 -0.066 -0.059 -0.555 -0.851 -0.936 -0.956 -1.127 
 8   -0.165 -0.081  0.032  0.143  0.157 -0.140 -0.433 -0.697 -0.743 -0.802 
 9    0.114  0.193  0.286  0.380  0.393  0.175  0.007 -0.281 -0.442 -0.409 
10    0.428  0.492  0.554  0.628  0.638  0.446  0.313  0.164  0.007  0.025 
11    0.542  0.592  0.654  0.722  0.724  0.479  0.341  0.223  0.164  0.198 
12   -0.511 -0.463 -0.413 -0.362 -0.358 -0.556 -0.690 -0.811 -0.789 -0.827 
13   -0.630 -0.587 -0.541 -0.503 -0.503 -0.651 -0.775 -0.807 -0.862 -0.880 
14   -0.727 -0.706 -0.673 -0.630 -0.627 -0.723 -0.759 -0.862 -0.915 -0.921 
15   -0.838 -0.829 -0.812 -0.783 -0.767 -0.716 -0.826 -0.937 -0.992 -0.973 
16   -0.921 -0.920 -0.908 -0.896 -0.793 -0.751 -0.853 -0.961 -1.019 -0.995 
17   -1.069 -1.072 -1.076 -0.985 -0.967 -0.901 -0.949 -1.058 -1.116 -1.092 
18   -1.265 -1.267 -1.195 -1.182 -1.172 -1.135 -1.130 -1.186 -1.248 -1.260 
19   -1.499 -1.425 -1.423 -1.417 -1.414 -1.397 -1.395 -1.396 -1.425 -1.481 

Hard Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 5      H      H      H      H      H      H      H      H      H      H   
 6      H      H      H      H      H      H      H      H      H      H   
 7      H      H      H      H      H      H      H      H      H      H   
 8      H      H      H      D      D      H      H      H      H      H   
 9      D      D      D      D      D      H      H      H      H      H   
10      D      D      D      D      D      D      D      D      H      H   
11      D      D      D      D      D      D      D      D      D      D   
12      H      H      S      S      S      H      H      H      H      H   
13      S      S      S      S      S      H      H      H      H      H   
14      S      S      S      S      S      H      H      H      H      H   
15      S      S      S      S      S      H      H      H      H      H   
16      S      S      S      S      S      H      H      H      H      H   
17      S      S      S      S      S      S      S      S      S      S   
18      S      S      S      S      S      S      S      S      S      S   
19      S      S      S      S      S      S      S      S      S      S   

Hard Chart - Player Strategy (Round >= 2, No Doubling)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
 4      H      H      H      H      H      H      H      H      H      H   
 5      H      H      H      H      H      H      H      H      H      H   
 6      H      H      H      H      H      H      H      H      H      H   
 7      H      H      H      H      H      H      H      H      H      H   
 8      H      H      H      H      H      H      H      H      H      H   
 9      H      H      H      H      H      H      H      H      H      H   
10      H      H      H      H      H      H      H      H      H      H   
11      H      H      H      H      H      H      H      H      H      H   
12      H      H      S      S      S      H      H      H      H      H   
13      S      S      S      S      S      H      H      H      H      H   
14      S      S      S      S      S      H      H      H      H      H   
15      S      S      S      S      S      H      H      H      H      H   
16      S      S      S      S      S      H      H      H      H      H   
17      S      S      S      S      S      S      S      S      S      S   
18      S      S      S      S      S      S      S      S      S      S   
19      S      S      S      S      S      S      S      S      S      S   
20      S      S      S      S      S      S      S      S      S      S   
21      S      S      S      S      S      S      S      S      S      S   

Soft Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2   -0.283 -0.241 -0.186 -0.119 -0.114 -0.462 -0.508 -0.517 -0.539 -0.662 
A3   -0.284 -0.240 -0.170 -0.116 -0.112 -0.460 -0.505 -0.527 -0.538 -0.661 
A4   -0.283 -0.224 -0.166 -0.113 -0.109 -0.458 -0.514 -0.526 -0.538 -0.659 
A5   -0.266 -0.221 -0.164 -0.111 -0.108 -0.468 -0.515 -0.525 -0.537 -0.659 
A6   -0.132 -0.093 -0.037  0.005  0.010 -0.090 -0.385 -0.407 -0.418 -0.483 
A7    0.136  0.167  0.204  0.222  0.262  0.412  0.121 -0.179 -0.186 -0.101 
A8    0.402  0.420  0.415  0.461  0.482  0.615  0.608  0.288  0.064  0.290 
A9    0.656  0.644  0.654  0.682  0.694  0.773  0.785  0.766  0.555  0.681 

Soft Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2    0.039  0.071  0.110  0.159  0.168  0.107  0.039 -0.014 -0.090 -0.184 
A3    0.017  0.044  0.091  0.137  0.147  0.060  0.035 -0.060 -0.124 -0.216 
A4   -0.012  0.022  0.061  0.108  0.120  0.034 -0.035 -0.114 -0.172 -0.256 
A5   -0.032 -0.003  0.038  0.082  0.116 -0.024 -0.084 -0.167 -0.229 -0.296 
A6    0.007  0.036  0.077  0.140  0.133  0.060 -0.065 -0.135 -0.189 -0.242 
A7    0.065  0.093  0.156  0.175  0.192  0.175  0.047 -0.087 -0.140 -0.160 
A8    0.120  0.173  0.187  0.227  0.241  0.222  0.158  0.005 -0.087 -0.081 
A9    0.191  0.196  0.230  0.268  0.280  0.243  0.172  0.096  0.007 -0.008 

Soft Chart - Player Expected Gains per unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2   -0.042  0.028  0.115  0.212  0.230 -0.157 -0.312 -0.373 -0.478 -0.586 
A3   -0.047  0.011  0.109  0.204  0.222 -0.175 -0.254 -0.394 -0.479 -0.588 
A4   -0.070  0.003  0.085  0.175  0.201 -0.141 -0.314 -0.422 -0.495 -0.613 
A5   -0.082 -0.019  0.063  0.148  0.217 -0.189 -0.333 -0.452 -0.536 -0.649 
A6    0.013  0.074  0.155  0.280  0.266  0.014 -0.230 -0.345 -0.433 -0.522 
A7    0.128  0.189  0.313  0.349  0.385  0.240 -0.015 -0.254 -0.322 -0.359 
A8    0.237  0.346  0.373  0.453  0.483  0.325  0.190 -0.060 -0.226 -0.200 
A9    0.380  0.392  0.459  0.536  0.560  0.351  0.230  0.111 -0.055 -0.055 

Soft Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
A2      H      H      D      D      D      H      H      H      H      H   
A3      H      H      D      D      D      H      H      H      H      H   
A4      H      H      D      D      D      H      H      H      H      H   
A5      H      H      D      D      D      H      H      H      H      H   
A6      D      D      D      D      D      H      H      H      H      H   
A7      S      D      D      D      D      S      S      H      H      S   
A8      S      S      S      S      D      S      S      S      S      S   
A9      S      S      S      S      S      S      S      S      S      S   

Soft Chart - Player Strategy (Round >= 2, No Doubling)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
12      H      H      H      H      H      H      H      H      H      H   
13      H      H      H      H      H      H      H      H      H      H   
14      H      H      H      H      H      H      H      H      H      H   
15      H      H      H      H      H      H      H      H      H      H   
16      H      H      H      H      H      H      H      H      H      H   
17      H      H      H      H      H      H      H      H      H      H   
18      S      S      S      S      S      S      S      H      H      S   
19      S      S      S      S      S      S      S      S      S      S   
20      S      S      S      S      S      S      S      S      S      S   
21      S      S      S      S      S      S      S      S      S      S   

Pairs Chart - Player Expected Gains per unit (Stand)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA   -0.274 -0.232 -0.178 -0.130 -0.104 -0.452 -0.500 -0.511 -0.531 -0.663 
22   -0.291 -0.251 -0.192 -0.107 -0.125 -0.471 -0.515 -0.523 -0.547 -0.660 
33   -0.295 -0.246 -0.160 -0.101 -0.119 -0.467 -0.510 -0.542 -0.546 -0.660 
44   -0.290 -0.214 -0.152 -0.095 -0.114 -0.463 -0.529 -0.543 -0.547 -0.656 
55   -0.256 -0.206 -0.146 -0.090 -0.112 -0.484 -0.531 -0.541 -0.545 -0.653 
66   -0.262 -0.211 -0.152 -0.102 -0.165 -0.493 -0.536 -0.549 -0.552 -0.617 
77   -0.268 -0.219 -0.164 -0.156 -0.174 -0.502 -0.539 -0.555 -0.510 -0.631 
88   -0.275 -0.228 -0.215 -0.165 -0.178 -0.503 -0.551 -0.516 -0.518 -0.644 
99    0.137  0.123  0.167  0.203  0.265  0.401  0.065 -0.196 -0.133 -0.055 
TT    0.627  0.636  0.645  0.674  0.697  0.765  0.783  0.744  0.583  0.650 

Pairs Chart - Player Expected Gains per unit (Hit)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA    0.095  0.120  0.142  0.182  0.200  0.158  0.093 -0.003 -0.048 -0.075 
22   -0.113 -0.082 -0.035  0.036  0.032 -0.092 -0.141 -0.222 -0.277 -0.395 
33   -0.153 -0.118 -0.047  0.008  0.014 -0.164 -0.231 -0.310 -0.346 -0.444 
44   -0.013  0.028  0.098  0.154  0.175  0.111 -0.055 -0.206 -0.246 -0.268 
55    0.224  0.254  0.295  0.347  0.362  0.279  0.207  0.119  0.032  0.042 
66   -0.253 -0.222 -0.190 -0.162 -0.194 -0.265 -0.322 -0.386 -0.386 -0.411 
77   -0.406 -0.388 -0.369 -0.370 -0.367 -0.389 -0.408 -0.475 -0.516 -0.510 
88   -0.454 -0.450 -0.461 -0.453 -0.397 -0.374 -0.426 -0.487 -0.512 -0.490 
99   -0.627 -0.638 -0.597 -0.590 -0.587 -0.566 -0.566 -0.595 -0.626 -0.621 
TT   -0.847 -0.846 -0.846 -0.846 -0.845 -0.843 -0.843 -0.842 -0.840 -0.882 

Pairs Chart - Player Expected Gains per unit (Double)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA   -0.019  0.055  0.137  0.216  0.248 -0.137 -0.296 -0.421 -0.468 -0.591 
22   -0.582 -0.501 -0.384 -0.214 -0.249 -0.942 -1.030 -1.047 -1.094 -1.320 
33   -0.567 -0.472 -0.302 -0.184 -0.215 -0.871 -1.000 -1.065 -1.072 -1.298 
44   -0.185 -0.082  0.044  0.162  0.193 -0.108 -0.447 -0.701 -0.741 -0.802 
55    0.446  0.510  0.590  0.695  0.724  0.466  0.323  0.175  0.014  0.042 
66   -0.505 -0.444 -0.380 -0.325 -0.387 -0.599 -0.711 -0.817 -0.803 -0.823 
77   -0.813 -0.777 -0.738 -0.741 -0.734 -0.823 -0.858 -0.978 -1.035 -1.019 
88   -0.908 -0.900 -0.922 -0.906 -0.793 -0.747 -0.853 -0.974 -1.024 -0.980 
99   -1.255 -1.277 -1.194 -1.181 -1.173 -1.132 -1.133 -1.189 -1.252 -1.242 
TT   -1.693 -1.693 -1.693 -1.691 -1.690 -1.686 -1.685 -1.684 -1.681 -1.764 

Pairs Chart - Player Expected Gains per unit (Split)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA    1.192  1.223  1.265  1.321  1.344  1.308  1.201  1.039  0.860  0.921 
22   -0.128 -0.070 -0.007  0.128  0.126 -0.054 -0.213 -0.383 -0.463 -0.566 
33   -0.202 -0.128  0.009  0.117  0.112 -0.115 -0.265 -0.418 -0.509 -0.579 
44   -0.236 -0.127 -0.013  0.095  0.083 -0.223 -0.343 -0.493 -0.580 -0.623 
55   -0.232 -0.150 -0.038  0.068  0.056 -0.299 -0.448 -0.608 -0.685 -0.695 
66   -0.219 -0.135 -0.028  0.068 -0.011 -0.270 -0.413 -0.570 -0.652 -0.660 
77   -0.163 -0.084  0.016  0.039  0.053 -0.123 -0.423 -0.564 -0.634 -0.635 
88    0.017  0.077  0.106  0.188  0.234  0.202 -0.100 -0.430 -0.464 -0.378 
99    0.170  0.170  0.253  0.339  0.359  0.341  0.179 -0.112 -0.268 -0.109 
TT    0.412  0.465  0.518  0.596  0.619  0.576  0.447  0.276  0.146  0.140 

Pairs Chart - Player Strategy (Round 1)
P/D     2      3      4      5      6      7      8      9      T      A
--------------------------------------------------------------------------
AA      P      P      P      P      P      P      P      P      P      P   
22      H      P      P      P      P      P      H      H      H      H   
33      H      H      P      P      P      P      H      H      H      H   
44      H      H      H      D      D      H      H      H      H      H   
55      D      D      D      D      D      D      D      D      H      D   
66      P      P      P      P      P      H      H      H      H      H   
77      P      P      P      P      P      P      H      H      S      H   
88      P      P      P      P      P      P      P      P      P      P   
99      P      P      P      P      P      S      P      P      S      S   
TT      S      S      S      S      S      S      S      S      S      S   

Simulation for Year 1:

After playing 50 times a day for 365 days:
Winning days   : 180
Losing days    : 176
Breakeven days : 9
Biggest win    : 23.5     
Biggest loss   : 24.5     
Total loss     : 263       
Total staked   : 20482       
Loss % staked  : 1.284

Simulation for Year 2:

After playing 50 times a day for 365 days:
Winning days   : 176
Losing days    : 174
Breakeven days : 15
Biggest win    : 20.5     
Biggest loss   : 20       
Total loss     : 60.5     
Total staked   : 20514       
Loss % staked  : 0.295

Simulation for Year 3:

After playing 50 times a day for 365 days:
Winning days   : 163
Losing days    : 195
Breakeven days : 7
Biggest win    : 20.5     
Biggest loss   : 26       
Total loss     : 297       
Total staked   : 20501       
Loss % staked  : 1.449

Simulation for Year 4:

After playing 50 times a day for 365 days:
Winning days   : 163
Losing days    : 190
Breakeven days : 12
Biggest win    : 21.5     
Biggest loss   : 20.5     
Total loss     : 144.5     
Total staked   : 20507       
Loss % staked  : 0.705

Simulation for Year 5:

After playing 50 times a day for 365 days:
Winning days   : 153
Losing days    : 203
Breakeven days : 9
Biggest win    : 19       
Biggest loss   : 24.5     
Total loss     : 485.5     
Total staked   : 20501       
Loss % staked  : 2.368

Simulation for Year 6:

After playing 50 times a day for 365 days:
Winning days   : 176
Losing days    : 177
Breakeven days : 12
Biggest win    : 21       
Biggest loss   : 29.5     
Total loss     : 4       
Total staked   : 20536       
Loss % staked  : 0.019

Simulation for Year 7:

After playing 50 times a day for 365 days:
Winning days   : 161
Losing days    : 195
Breakeven days : 9
Biggest win    : 25.5     
Biggest loss   : 24.5     
Total loss     : 316.5     
Total staked   : 20568       
Loss % staked  : 1.539

Simulation for Year 8:

After playing 50 times a day for 365 days:
Winning days   : 168
Losing days    : 189
Breakeven days : 8
Biggest win    : 21       
Biggest loss   : 28       
Total loss     : 240       
Total staked   : 20524       
Loss % staked  : 1.169

Simulation for Year 9:

After playing 50 times a day for 365 days:
Winning days   : 181
Losing days    : 174
Breakeven days : 10
Biggest win    : 22       
Biggest loss   : 26       
Total loss     : 17       
Total staked   : 20494       
Loss % staked  : 0.083

Simulation for Year 10:

After playing 50 times a day for 365 days:
Winning days   : 156
Losing days    : 198
Breakeven days : 11
Biggest win    : 22       
Biggest loss   : 21       
Total loss     : 346.5     
Total staked   : 20438       
Loss % staked  : 1.695