I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Blackjack strategy

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 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 = startDeck    scores = upCard    if upCard == 1 { // an ace        scores = 11        elevens = 1    }    probs = 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)            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 += 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 += prob // bust            } else {                deck[c]-- // remove card from deck                deck-- // 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    for i := 0; i < 7; i++ {        res[i] /= pnbj    }    res = 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 = 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, dp, dp, dp, dp, dp)    }} // 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)        deck2[c]-- // remove card from deck        deck2-- // 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 = startDeck    scores = card1 + card2    if card1 == 1 || card2 == 1 { // an ace        scores += 10        elevens = 1    }    probs = 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)            if score > 21 && eleven > 0 {                score -= 10 // bust but can demote an ace                eleven--            }            deck[c]-- // remove card from deck            deck-- // 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                         // dealer is bust        eg -= dp + dp + dp + dp // dealer has 18 to 21    case 18:        eg += dp + dp         // dealer has 17 or is bust        eg -= dp + dp + dp // dealer has 19 to 21    case 19:        eg += dp + dp + dp // dealer has 17, 18 or is bust        eg -= dp + dp         // dealer has 20 or 21    case 20:        eg += dp + dp + dp + dp // dealer has 17 to 19 or is bust        eg -= dp                         // dealer has (non-blackjack) 21    case 21:        eg += dp + dp + dp + dp + dp // 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       // dealer is bust        eg -= (1 - dp) // 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) float64 {    deck := NewDeck()    deck[card1]--    deck[card2]--    deck = 50    pscore := card1 + card2 // player score    if card1 == 1 || card2 == 1 {        pscore += 10    }    var egs float64          // results    for uc := 1; uc < 11; uc++ { // dealer's up-card        deck2 := deck        deck2[uc]--        deck2--        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 = 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) float64 {    deck := NewDeck()    deck[card1]--    deck[card2]--    deck = 50    var egs float64          // results    for uc := 1; uc < 11; uc++ { // dealer's up-card        deck2 := deck        deck2[uc]--        deck2 = 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 = 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) 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) float64 {    deck := NewDeck()    deck[card] -= 2 // must be a pair    deck = 50    var egs 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--        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)            deck3 := deck2            deck3[c]--            deck3--            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 = peg * 2 // ditto        }    }    return egs} // Returns the action with the highest expected gain.func bestAction(ags []ActionGain) string {    max := ags.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  = string{} // hard strategy table (round 1)    sTable  = string{}  // soft strategy table (round 1)    pTable  = string{} // pairs strategy table (round 1)    hTable2 = string{} // hard strategy table (round >= 2, no doubling)    sTable2 = 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 + d    aces := 0    if d == 1 || d == 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 == 1 && d == 10) || (d == 10 && d == 1)    pbj := (p == 1 && p == 10) || (p == 10 && p == 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 // 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 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 + p    // get kind of player hand: hard, soft, pair    var kind string    if p == p {        kind = "pair"    } else if p == 1 || p == 1 {        kind = "soft"    } else {        kind = "hard"    }    switch kind {    case "hard":        action = hTable[score-5][uc]    case "soft": // includes one ace        otherCard := p        if otherCard == 1 {            otherCard = p        }        score += 10        aces = 1        action = sTable[otherCard-2][uc]    case "pair":        if p == 1 { // pair of aces            score += 10            aces = 2        }        action = pTable[p-1][uc]    }    switch action {    case "S": // stand        fscores = score    case "H": // hit        h(0)    case "D": // double        h(0)        stake = 2    case "P": // split        for hand := 0; hand < 2; hand++ {            score = p            aces = 0            if score == 1 { // count aces initially as 11                score = 11                aces++            }            h(hand)        }    }    sum := 0.0    if fscores < 22 {        sum += dealerPlay(fscores, &next, cards, d) * stake    } else {        sum -= 1 * stake // this hand is bust    }    if fscores > 0 { // pair        if fscores < 22 {            sum += dealerPlay(fscores, &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 := []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 := 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 := float64{} // if stands    hegs := float64{} // if hits    degs := float64{} // if doubles    for _, tuple := range tuples {        i := tuple + tuple        sg := stand(tuple, tuple)        hg := hit(tuple, tuple, false)        dg := double(tuple, tuple)        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 := float64{} // expected gains if stands    hegs2 := 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[j] += sg4[j]        hegs2[j] += hg4[j]        segs2[j] += sg20[j]        hegs2[j] += hg20[j]        segs2[j] += sg21[j]        hegs2[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 := float64{} // if stands    hegs3 := float64{} // if hits    degs3 := 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 := float64{} // expected gains if stands    hegs4 := 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[j] += sg12[j]        hegs4[j] += hg12[j]        segs4[j] += sg21[j]        hegs4[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 := float64{} // if stands    hegs5 := float64{} // if hits    degs5 := float64{} // if doubles    pegs5 := 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 = startDeck  scores = upCard  if upcard == 1:    # An ace.    scores = 11    elevens = 1   probs = 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 += 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 += 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  for i in 0..6: res[i] /= pnbj   res = 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                                 # Dealer is bust.    result -= dp + dp + dp + dp         # Dealer has 18 to 21.  of 18:    result += dp + dp                         # Dealer has 17 or is bust.    result -= dp + dp + dp                 # Dealer has 19 to 21.  of 19:    result += dp + dp + dp                 # Dealer has 17, 18 or is bust.    result -= dp + dp                         # Dealer has 20 or 21.  of 20:    result += dp + dp + dp + dp         # Dealer has 17 to 19 or is bust.    result -= dp                                 # Dealer has (non-blackjack) 21.  of 21:    result += dp + dp + dp + dp + dp # 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                                 # Dealer is bust.    result -= 1 - dp                             # 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 = startDeck  scores = card1 + card2  if card1 == 1 or card2 == 1:    inc scores, 10    elevens = 1   probs = 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 = 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 = 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 = 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 + d  var aces = 0  if d == 1 or d == 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 == 1 and d == 10 or d == 10 and d == 1  let pbj = p == 1 and p == 10 or p == 10 and p == 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 - 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 + p  # Get kind of player hand: hard, soft, pair.  let kind = if p == p: Pair elif p == 1 or p == 1: Soft else: Hard   case kind  of Hard:    action = hTable[score-5][uc]  of Soft:  # includes one ace.    let othercard = if p == 1: p else: p    inc score, 10    aces = 1    action = sTable[otherCard-2][uc]  of Pair:    if p == 1:      # Pair of aces.      inc score, 10      aces = 2    action = pTable[p-1][uc]   case action  of Stand:    fscores = score  of Hit:    h(0)  of Double:    h(0)    stake = 2  of Split:    for hand in 0..1:      score = p      aces = 0      if score == 1:        # Count aces initially as 11.        score = 11        inc aces      h(hand)   var sum = 0.0  if fscores < 22:    sum += dealerPlay(fscores, next, cards, d) * stake  else:    sum -= 1 * stake  # This hand is bust.  if fscores > 0:    # Pair.    if fscores < 22:      sum += dealerPlay(fscores, 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 + t    let sg = stand(t, t)    let hg = hit(t, t, false)    let dg = double(t, t)    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[j] += sg4[j]    hegs2[j] += hg4[j]    segs2[j] += sg20[j]    hegs2[j] += hg20[j]    segs2[j] += sg21[j]    hegs2[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[j] += sg12[j]    hegs4[j] += hg12[j]    segs4[j] += sg21[j]    hegs4[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 = startDeck
scores = upCard
if upCard == 1 then // an ace
scores = 11
elevens = 1
end if
probs = 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
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 += 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 += prob // bust
else
deck[c] -= 1 // remove card from deck
deck -= 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
for i=1 to 7 do
res[i] /= pnbj
end for
res = 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 = 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 = dp
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                         // dealer is bust
eg -= dp + dp + dp + dp // dealer has 18 to 21
case 18:
eg += dp + dp         // dealer has 17 or is bust
eg -= dp + dp + dp // dealer has 19 to 21
case 19:
eg += dp + dp + dp // dealer has 17, 18 or is bust
eg -= dp + dp         // dealer has 20 or 21
case 20:
eg += dp + dp + dp + dp // dealer has 17 to 19 or is bust
eg -= dp                         // dealer has (non-blackjack) 21
case 21:
eg += dp + dp + dp + dp + dp // 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       // dealer is bust
eg -= (1 - dp) // 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
deck2[c] -= 1 // remove card from deck
deck2 -= 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 = startDeck
scores = card1 + card2
if card1 == 1 or card2 == 1 then // an ace
scores += 10
elevens = 1
end if
probs = 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
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 -= 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 = 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 -= 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 = 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 = 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 = 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 = 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 = 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 -= 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
sequence deck3 := deep_copy(deck2)
deck3[c] -= 1
deck3 -= 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 = 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
integer besti := 1
for i=2 to length(ags) do
if ags[i] > best then
best = ags[i]
besti = i
end if
end for
return ags[besti]
end function

// 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 + d,
aces := 0
if d == 1 or d == 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 and d == 10) or (d == 10 and d == 1),
pbj := (p == 1 and p == 10) or (p == 10 and p == 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 // 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 + p
aces = 0
// get kind of player hand: hard, soft, pair
string kind
if p == p then
kind = "pair"
elsif p == 1 or p == 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
if otherCard == 1 then
otherCard = p
end if
score += 10
aces = 1
action = sTable[otherCard-1][uc]
case "pair":
if p == 1 then // pair of aces
score += 10
aces = 2
end if
action = pTable[p][uc]
end switch
switch action do
case "S": // stand
fscores = score
case "H": // hit
h(1)
case "D": // double
h(1)
stake = 2
case "P": // split
for hand=1 to 2 do
score = p
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 < 22 then
tot += dealerPlay(fscores, d) * stake
else
tot -= 1 * stake // this hand is bust
end if
if fscores > 0 then // pair
if fscores < 22 then
tot += dealerPlay(fscores, 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 + tuple
sequence sg := stand(tuple, tuple)
sequence hg := hit(tuple, tuple, false)
sequence dg := double(tuple, tuple)
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[j] += sg4[j]
hegs2[j] += hg4[j]
segs2[j] += sg20[j]
hegs2[j] += hg20[j]
segs2[j] += sg21[j]
hegs2[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[j] += sg12[j]
hegs4[j] += hg12[j]
segs4[j] += sg21[j]
hegs4[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-trait

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 Randomimport "./array"   for Array, ArrayTypeimport "./dynamic" for Structimport "./fmt"     for Fmtimport "./trait"   for Indexed var Rand = Random.new() // 0: deck size, 1 to 10: number of cards of that denominationvar 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 tablesvar 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    = startDeck.toList        scores   = upCard        if (upCard == 1) {  // an ace            scores = 11            elevens = 1        }        probs = 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                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 = res + 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 = res + prob  // bust                } else {                    deck[c] = deck[c] - 1  // remove card from deck                    deck = deck - 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        for (i in 0..6) res[i] = res[i] / pnbj        res = 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 = 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, dp, dp, dp, dp, dp])        }    }     // 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            deck2[c] = deck2[c] - 1  // remove card from deck            deck2 = deck2 - 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    = startDeck.toList        scores   = card1 + card2        if (card1 == 1 || card2 == 1) {  // an ace            scores = scores + 10            elevens = 1        }        probs = 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                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 = deck - 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                         // dealer is bust            eg = eg - dp - dp - dp - dp // dealer has 18 to 21        } else if (pscore == 18) {            eg = eg + dp + dp          // dealer has 17 or is bust            eg = eg - dp - dp - dp  // dealer has 19 to 21        } else if (pscore == 19) {            eg = eg + dp + dp + dp  // dealer has 17, 18 or is bust            eg = eg - dp - dp          // dealer has 20 or 21        } else if (pscore == 20) {            eg = eg + dp + dp + dp + dp  // dealer has 17 to 19 or is bust            eg = eg - dp                          // dealer has (non-blackjack) 21        } else if (pscore == 21) {            eg = eg + dp + dp + dp + dp + dp  // 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        // dealer is bust            eg = eg - (1 - dp)  // 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 = 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 = deck2 - 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 = 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 = 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 = 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 = 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 = 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  = deck2 - 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                var deck3 = deck2.toList                deck3[c] = deck3[c] - 1                deck3 = deck3 - 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 = peg * 2    // ditto            }        }        return egs    }     // Returns the action with the highest expected gain.    static bestAction(ags) {        var max = ags.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                dailyStake = dailyStake + gs            }            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 + d        var aces = 0        if (d == 1 || d == 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 == 1 && d == 10) || (d == 10 && d == 1)        var pbj = (p == 1 && p == 10) || (p == 10 && p == 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  // 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 + p        // get kind of player hand: hard, soft, pair        var kind        if (p == p) {            kind = "pair"        } else if (p == 1 || p == 1) {            kind = "soft"        } else {            kind = "hard"        }        if (kind == "hard") {            action = HTable[score-5][uc]        } else if (kind == "soft") {  // includes one ace            var otherCard = p            if (otherCard == 1) otherCard = p            score = score + 10            aces = 1            action = STable[otherCard-2][uc]        } else if (kind == "pair") {            if (p == 1) {  // pair of aces                score = score + 10                aces = 2            }            action = PTable[p-1][uc]        }        if (action == "S") {  // stand            fscores = 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                aces = 0                if (score == 1) {  // count aces initially as 11                    score = 11                    aces = aces + 1                }                h.call(hand)            }        }        var sum = 0        if (fscores < 22) {            var res = dealerPlay(fscores, next, cards, d)            sum = sum + res * stake            next = res        } else {            sum = sum - stake  // this hand is bust        }        if (fscores > 0) {  // pair            if (fscores < 22) {                var res = dealerPlay(fscores, next, cards, d)                sum = sum + res                next = res            } 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 + tuple            var sg = stand(tuple, tuple)            var hg = hit(tuple, tuple, false)            var dg = double(tuple, tuple)            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[j]  = segs2[j]  + sg4[j]            hegs2[j]  = hegs2[j]  + hg4[j]            segs2[j] = segs2[j] + sg20[j]            hegs2[j] = hegs2[j] + hg20[j]            segs2[j] = segs2[j] + sg21[j]            hegs2[j] = hegs2[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[j] = segs4[j] + sg12[j]            hegs4[j] = hegs4[j] + hg12[j]            segs4[j] = segs4[j] + sg21[j]            hegs4[j] = hegs4[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
```