\input texinfo @c -*-texinfo-*- @c %**start of header @documentencoding UTF-8 @setfilename blackjack.info @set UPDATED December 20, 2020 @set VERSION v0.2.5-g9c5893b @copying This manual is for LibreBlackjack (version @value{VERSION}, @value{UPDATED}), which is a completely free-as-in-freedom blackjack engine designed to study and analyze the game statistics using different playing strategies ranging from simple card counting up to other complex algorithms based on artificial intelligence.. Copyright @copyright{} 2016-2020 Jeremy Theler. @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end quotation @end copying @ifnottex @paragraphindent 0 @end ifnottex @titlepage @title Libre@ Blackjack @subtitle A free blackjack back end, v0.2.5-g9c5893b @author Jeremy Theler December 20, 2020 @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @node Top @top Libre@ Blackjack @menu * Overview:: * Running blackjack:: * Commands:: * Configuration file:: * Example automated players:: @end menu @node Overview @chapter Overview @anchor{#overview} Libre@ Blackjack is a blackjack engine that emulates a dealer, deals (digital) cards and understands plain-text commands such as @code{hit} or @code{stand}. It's inspired by GNU@ Chess. The basic idea is that one or more players can talk to Libre@ Blackjack either in an interactive or in an automated way through @itemize @item the standard input/output (optionally using named pipes or TCP (web)sockets with @code{netcat} or @code{gwsocket}), or @item C++ methods (optionally loaded at runtime from shared objects---TBD). @end itemize These players can be actual human players playing in real-time through a front end (a GUI application, a web-based interface, a mobile app, etc.) or robots that implement a certain betting and playing strategy playing (i.e.@ card counting) as fast as possible to study and analyze game statistics. There is an internal player that reads the strategy from a text file and plays accordingly. Libre@ Blackjack can also be used to play interactive ASCII blackjack. @menu * Background:: * A note on the C++ implementation:: @end menu @node Background @section Background @anchor{#background} The casino game known as Blackjack has converged to the current mainstream rules since the beginning of the 20th century. Assuming the cards are infinite, the best strategy for the player yields approximately a house edge which is in the order of@ 0.5%. This is a remarkable result, because the rules of the game are not trivial and the overall combination gives a very little margin for the dealer, more than five times smaller than standard single-zero roulette. In 1963, Edward Thorp published his seminal book @emph{Beat the dealer} where he showed---with the help of the mainframes available at that time---that it is possible to flip the margin to the player's side by taking into account that the chances of dealing the next card of a finite shoe depends on the cards that were already dealt. This was the beginning of the card counting era, and a lot of mathematicians have devoted to the analysis of probabilities in the Blackjack game---and its variations. @quotation ``I am often surprised that when people drive down two-lane roads, they will trust complete strangers in the oncoming lane not to swerve into their lane causing a head-on collision; but they will not trust mathematicians to create the correct strategy for Blackjack.'' Norman Wattenberger, Modern Blackjack, 2009 @end quotation With Libre@ Blackjack you do not have to trust other people anymore. You have a free blackjack engine which you can @enumerate 0 @item run as you wish, to see the results of billions of blackjack hands, @item study to see how it works and change it if you do not like it, @item share it with your friends and colleagues, and @item distribute copies of your modified versions. @end enumerate If you do not know how to program, you have the @emph{freedom} to hire a programmer to do it for you. That is why Libre@ Blackjack is @emph{free software}. Once you trust the blackjack engine is fair, you can model and simulate any blackjack situation you want, playing millions of times a certain hand (say a sixteen against a ten) in different ways (say hitting or standing) with different rules (does the dealer have to hit soft seventeens?) to obtain you own conclusions. You can even build the basic strategy charts from scratch to convince yourself there is no ``flaw.'' The main objective is research and optimization of playing and betting strategies depending on @itemize @item particular table rules (number of decks, hit on soft 17, double after split, etc.), @item card counting strategies @item risk of ruin @item removal of cards @item arranged shoes @end itemize These automatic players can range from simple no-bust or mimic-the-dealer hitters or standers, up to neural-networks trained players taking into account every card being dealt passing through basic strategy modified by traditional card counting mechanisms. @node A note on the C++ implementation @section A note on the C++ implementation @anchor{#a-note-on-the-c-implementation} The first Libre@ Blackjack version (v0.1) was written in C. This version (v0.2) is a re-implementation of nearly the same functionality but written completely from scratch in C++. I am not a fan of C++ and still prefer old plain C for most of my programming projects, but for the particular case of Libre@ Blackjack these advantages of C++ over C ought to be noted: @itemize @item the inheritance mechanisms of C++ and virtual methods allows to have generic dealer and player classes from which particular games (dealers) and strategies (players) can be instantiated. This way, Blackjack variations like @itemize @item Spanish 21 @item Down under Blackjack @item Free Bet Blackjack @item Blackjack Switch @end itemize or even the Spanish ``Siete y medio'' could be also implemented in the same framework (the card deck should also be changed though). But also playing variations like a dealer that exposes the hole card a certain amount of the time (say 1% or 2% of the hands) could also be studied by extending the base blackjack dealer class. @item the private members of the C++ classes allow information to be hidden between the dealer and the player, so a far better separation of information can be achieved. This also prevents ``cheating'' in players by looking at information which is not available for them (such as the dealer's hole card or the content of the shoe). @item the virtual members of derived players and even be linked to other high-level programming language parsers (such as Python or Julia) allowing to use the vast variety of AI/ML libraries available for these languages to implement advanced playing strategies. @item the usage of STL containers, methods and algorithms allows for a faster and cleaner implementation of cards, hands, decks and shoes. @end itemize @node Running blackjack @chapter Running @code{blackjack} @anchor{#running-blackjack} @menu * Invocation:: * Interactive game:: @end menu @node Invocation @section Invocation @anchor{#invocation} The format for running the @code{blackjack} program is: @verbatim blackjack [options] [path_to_conf_file] @end verbatim If no configuration file is given, a file named @code{blackjack.conf} in the current directory is used, provided it exists. With no options and no configuration file, @code{blackjack} starts in interactive mode and it is ready to start a blackjack game. The @code{blackjack} executable supports the following options: All the options which can be given in the configuration file can be passed as a command-line argument. For example, running @verbatim blackjack --decks=4 --no_insurance=true @end verbatim is equivalent to using a configuration file with @verbatim decks = 4 no_insurance = true @end verbatim @node Interactive game @section Interactive game @anchor{#interactive-game} If @code{blackjack} is attached to an interactive TTY (i.e.@ neither the standard input nor outputs are redirected), an interactive game is triggered. First thing the program will do is to ask for a bet: @verbatim LibreBlackjack v0.2+Δ a free & open blackjack engine Starting new hand #1 with bankroll 0 <-- Bet? > @end verbatim So the user should enter a number, say ``1'' and then press Enter and then a game will be dealt: @verbatim Player's card is Q♥ Dealer's up card is 10♠ Player's card is Q♣ Dealer's hole card is dealt No blackjacks -- Dealer's hand: -------- _____ _____ |10 | |#####| | | |#####| | ♠ | |#####| | | |#####| |___10| |#####| Value: 10 -- Player's hand -------- _____ _____ |Q | |Q | | | | | | ♥ | | ♣ | | | | | |____Q| |____Q| Value: 20 <-- Play? 20 10 > @end verbatim A flat-betting game can be played by passing @code{--flat_bet=true} through the command line. @node Commands @chapter Commands @anchor{#commands} The dealer (he) and the player (she) ``talk'' through commands, which are ASCII strings sent through any of the different IPC mechanisms discussed in [Automated playing through IPC]. In the most basic case, a human player reads commands from the dealer from @code{blackjack}'s standard output and writes her commands into the dealer's standard input. Those commands from the dealer that require a particular action from the player end with a quotation sign such as @code{bet?}, @code{insurance?} or @code{play?}. All numerical values such as hand totals or bankrolls are given as decimal ASCII strings. @menu * From the dealer to the player:: * From the player to the dealer:: @end menu @node From the dealer to the player @section From the dealer to the player @anchor{#from-the-dealer-to-the-player} @node From the player to the dealer @section From the player to the dealer @anchor{#from-the-player-to-the-dealer} The following commands are available for the player for playing her hand. The following are general commands in the sense that they can be sent from the player to the dealer at any moment of the game. @node Configuration file @chapter Configuration file @anchor{#configuration-file} Libre@ Blackjacks reads a configuration file that contains @itemize @item settings about the rules of the game @itemize @item number of decks, @item whether if the dealer has to hit soft seventeen or not, @item blackjack payout, @item maximum bet allowed, @item etc@dots{} @end itemize @item how the player is supposed to play @itemize @item number of hands @item whether a flat or variable bet is going to be used, @item etc@dots{} @end itemize @item if there are any particular shoe arrangement, i.e.@ a predefined set of cards dealt in a certain order for instance to play one million hands of a sixteen against a dealer's ten @item what kind of information is shown in the interactive session @itemize @item if ASCII-art cards are supposed to be shown, @item a real-time delay to make the game smoother, @item etc. @end itemize @item how the automated player communicates with the dealer @itemize @item using standard input/output, @item FIFO named pipes, @item POSIX message queues, @item POSIX shared memory, @item etc@dots{} @end itemize @end itemize The location of the configuration file can be given in the command line. If none is provided, a file named @code{blackjack.conf} in the current directory is used. If such file does not exists, the defaults values of each variable are used. Individual variables can be set from the command line by passing one or more times the option @code{--}configuration_variable@code{[=}@emph{value}@code{]} in the @ref{#invocation,invocation}. Comments can be inserted using either a hash @code{#} or a colon @code{;}. The following configuration file is the default provided in the main distribution tarball: @verbatim # uncomment the following line to arrange cards # arranged_cards = 1 5 14 9 27 flat_bet = 1 # do not ask for bets no_insurance = 1 # do not ask for insurance decks = 1 # number of decks, negative means infinite @end verbatim @menu * Variables and values:: * Dumb internal player:: @end menu @node Variables and values @section Variables and values @anchor{#variables-and-values} @node Dumb internal player @section Dumb internal player @anchor{#dumb-internal-player} @node Example automated players @chapter Example automated players @anchor{#example-automated-players} The directory @code{players} contains a few examples of automated player, which are discussed in the following sections. A script @code{check.sh} runs some of them and compares the expected value of the bankroll relative to the number of hands which each player obtains with the theoretical expected value (according to the game rules and player's strategy) within an allowed statistical uncertainty. This scripts writes the following table (actual values might vary depending on the random nature of the game): @multitable {Mimic the dealer} {Expected} {-0.0075415} {0.00926715} {Status} @headitem Case @tab Expected @tab Result @tab Error @tab Status @item Internal player @tab -0.0065 @tab -0.0075415 @tab 0.00348656 @tab ok @item Always stand @tab -0.150 @tab -0.15393 @tab 0.00941969 @tab ok @item No-bust strategy @tab -0.075 @tab -0.077645 @tab 0.00944109 @tab ok @item Mimic the dealer @tab -0.055 @tab -0.063785 @tab 0.00926715 @tab ok @end multitable The columns are @enumerate @item Case name, as discussed below. @item Expected theoretical result in absolute units (i.e.@ -0.01 means -1%) @item Actual result obtained by Libre@ Blackjack in absolute units @item Estimated error equal to the standard deviation of the result @item Whether the result coincides or not with the theoretical value @end enumerate @menu * Internal player:: * Always stand:: * No-bust strategy:: * Mimic the dealer:: * Derivation of the basic strategy:: @end menu @node Internal player @section Internal player @anchor{#internal-player} If @code{blackjack} is called with the @code{-i} option, it uses an @emph{internal} player to play against itself. By default it plays basic strategy. Run @verbatim blackjack -i @end verbatim and you will get the following report with the results of playing one million hands with basic strategy. @verbatim result: "(-0.7 ± 0.3) %" mean: -0.006799 error: 0.00348707 hands: 1e+06 bankroll: -6799 bustsPlayer: 0.139358 bustsDealer: 0.239722 wins: 0.448034 pushes: 0.085913 losses: 0.495532 @end verbatim @node Always stand @section Always stand @anchor{#always-stand} To play Blackjack as an ``always-stander'' run the following command: @verbatim yes stand | blackjack -n1e5 --flat_bet=true --no_insurance=true > /dev/null @end verbatim The UNIX command @code{yes stand} writes the string ``stand'' repeteadly to the standard output, which is piped to the executable @code{blackjack} (assumed to be installed system-wide). The arguments tell Libre@ Blackjack to play one hundred thousand hands (@code{-n1e5}) using a flat bet (@code{flat_bet}, it defaults to a unit bet in each hand) and without asking for insurance if the dealer shows an ace (@code{no_insurance}). As there is no @code{blackjack.conf} file, the rules are---as expected---the default ones (see the documentation for details). The @code{/dev/null} part is important, otherwise Libre@ Blackjack will think that there is a human at the other side of the table and will @enumerate @item run slower (it will add explicit time delays to mimic an actual human dealer), and @item give all the details of the dealt hands in the terminal as ASCII (actually UTF-8) art @end enumerate This example is only one-way (i.e.@ the player ignores what the dealer says) so it is better to redirect the standard output to @code{/dev/null} to save execution time. The results are written as a @uref{http://yaml.org/,YAML}-formatted data to @code{stderr} by default once the hands are over, so they will show up in the terminal nevertheless. This format is human-friendly (far more than JSON) so it can be easily parsed, but it also allows complex objects to be represented (arrays, lists, etc.). @verbatim result: "(-15.8 ± 0.9) %" mean: -0.157675 error: 0.00940803 hands: 100000 bankroll: -15767.5 bustsPlayer: 0 bustsDealer: 0.27344 wins: 0.38585 pushes: 0.04807 losses: 0.56608 @end verbatim @quotation @strong{Exercise:} verify that the analytical probability of getting a natural playing with a single deck (for both the dealer and the player) is 32/663 = 0.04826546@dots{} @end quotation @node No-bust strategy @section No-bust strategy @anchor{#no-bust-strategy} This directory shows how to play a ``no-bust'' strategy, i.e.@ not hitting any hand higher or equal to hard twelve with Libre@ Blackjack. The communication between the player and the back end is through standard input and output. The player reads from its standard input Libre@ Blackjack's commands and writes to its standard output the playing commands. In order to do this a FIFO (a.k.a. named pipe) is needed. So first, we create it (if it is not already created): @verbatim mkfifo fifo @end verbatim Then we execute @code{blackjack}, piping its output to the player (say @code{no-bust.pl}) and reading the standard input from @code{fifo}, whilst at the same time we redirect the player's standard output to @code{fifo}: @verbatim rm -f fifo; mkfifo fifo blackjack -n1e5 < fifo | ./no-bust.pl > fifo @end verbatim As this time the player is coded in an interpreted langauge, it is far smarter than the previous @code{yes}-based player. So the player can handle bets and insurances, and there is not need to pass the options @code{--flat_bet} nor @code{--no_insurance} (though they can be passed anyway). Let us take a look at the Perl implementation: @verbatim ##!/usr/bin/perl ## this is needed to avoid deadlock with the fifo STDOUT->autoflush(1); while ($command ne "bye") { ## do not play more than a number of commands ## if the argument -n was not passed to blackjack if ($i++ == 1234567) { print "quit\n"; } ## read and process the commands chomp($command = ); if ($command eq "bet?") { print "1\n"; } elsif ($command eq "insurance?") { print "no\n"; } elsif ($comm eq "play?") { @tokens = split(/ /, $command); if ($tokens[1] < 12) { print "hit\n"; } else { print "stand\n"; } } } @end verbatim The very same player may be implemented as a shell script: @verbatim ##!/bin/sh i=0 while read command do i=$((i+1)) if test ${i} -ge 12345; then echo "quit" elif test "${command}" = 'bye'; then exit elif test "${command}" = 'bet?'; then echo 1 elif test "${command}" = 'insurance?'; then echo "no" elif test "$(echo ${command} | cut -c-5)" = 'play?'; then count=$(echo ${command} | cut -f2 -d" ") if test ${count} -lt 12; then echo "hit" else echo "stand" fi fi done @end verbatim To check these two players give the same results, make them play against Libre@ Blackjack with the same seed (say one) and send the YAML report to two different files: @verbatim blackjack -n1e5 --rng_seed=1 --report_file_path=perl.yml < fifo | ./no-bust.pl > fifo blackjack -n1e5 --rng_seed=1 --report_file_path=shell.yml < fifo | ./no-bust.awk > fifo diff perl.yml shell.yml @end verbatim As expected, the reports are the same. They just differ in the speed because the shell script is orders of magnitude slower than its Perl-based counterpart. @quotation @strong{Exercise:} modify the players so they always insure aces and see if it improves or degrades the result. @end quotation @node Mimic the dealer @section Mimic the dealer @anchor{#mimic-the-dealer} This example implements a ``mimic-the-dealer strategy,'' i.e.@ hits if the hand totals less than seventeen and stands on eighteen or more. The player stands on hard seventeen but hits on soft seventeen. This time, the configuration file @code{blackjack.conf} is used. If a file with this name exists in the directory where @code{blackjack} is executed, it is read and parsed. The options should be fairly self descriptive. See the @ref{#configuration-file,configuration file} section of the manual for a detailed explanation of the variables and values that can be entered. In particular, we ask to play one hundred thousand hands at a six-deck game where the dealer hits soft seventeens. If the random seed is set to a fixed value so each execution will lead to the very same sequence of cards. Now, there are two options that tell Libre@ Blackjack how the player is going to talk to the backend: @code{player2dealer} and @code{dealer2player}. The first one sets the communication mechanism from the player to the dealer (by default is @code{blackjack}'s standard input), and the second one sets the mechanism from the dealer to the player (by default @code{blackjack}'s standard output). In this case, the configuration file reads: @verbatim h17 = true @end verbatim This means that two FIFOs (a.k.a. named pipes) are to be used for communication, @code{player2dealer} from the player to the dealer and @code{dealer2player} for the dealer to the player. If these FIFOs do not exist, they are created by @code{blackjack} upon execution. The player this time is implemented as an awk script, whose input should be read from @code{dealer2player} and whose output should be written to @code{player2dealer}. To run the game, execute @code{blackjack} in one terminal making sure the current directory is where the @code{blackjack.conf} file exists. It should print a message telling that it is waiting for someone to be at the other side of the named pipes: @verbatim $ blackjack @end verbatim In another terminal run the player @verbatim $ ./mimic-the-dealer.awk < dealer2player > player2dealer @end verbatim Both dealer and player may be run in the same terminal putting the first one on the background: @verbatim rm -f d2p p2d; mkfifo d2p p2d gawk -f mimic-the-dealer.awk < d2p > p2d & blackjack -n1e5 > d2p < p2d @end verbatim To understand the decisions taken by the player, we have to remember that when Libre@ Blackjack receives the command @code{count} asking for the current player's count, it returns a positive number for hard hands and a negative number for soft hands. The instructions @code{fflush()} are needed in order to avoid deadlocks on the named pipes: @verbatim ##!/usr/bin/gawk -f function abs(x){return ( x >= 0 ) ? x : -x } /bet\?/ { print "1"; fflush(); } /insurance\?/ { print "no"; fflush(); } /play\?/ { ## mimic the dealer: hit until 17 (hit soft 17) if (abs($2) < 17 || $2 == -17) { ## soft hands are negative print "hit"; } else { print "stand"; } fflush(); } /bye/ { exit; } @end verbatim @verbatim result: "(-5.7 ± 0.9) %" mean: -0.05716 error: 0.00926292 hands: 100000 bankroll: -5716 bustsPlayer: 0.27064 bustsDealer: 0.18905 wins: 0.41088 pushes: 0.09888 losses: 0.49024 @end verbatim @quotation @strong{Exercise:} modify the player and the configuration file so both the dealer and the player may stand on soft seventeen. Analyze the four combinations (player h17 - dealer h17, player h17 - dealer s17, player s17 - dealer h17, player s17 - dealer s17) @end quotation @node Derivation of the basic strategy @section Derivation of the basic strategy @anchor{#derivation-of-the-basic-strategy} @menu * Quick run:: * Full table with results:: * Detailed explanation:: * Implementation:: @end menu @node Quick run @subsection Quick run @anchor{#quick-run} Execute the @code{run.sh} script. It should take a few minutes: @verbatim $ ./run.sh h20-2 (10 10) 8.0e+04 +63.23 (1.1) -171.17 (1.1) -85.32 (0.5) stand h20-3 (10 10) 8.0e+04 +64.54 (1.1) -171.50 (1.1) -85.50 (0.5) stand h20-4 (10 10) 8.0e+04 +65.55 (1.1) -170.33 (1.1) -85.50 (0.5) stand h20-5 (10 10) 8.0e+04 +66.65 (1.1) -171.25 (1.1) -85.51 (0.5) stand h20-6 (10 10) 8.0e+04 +67.80 (1.1) -171.07 (1.1) -85.59 (0.5) stand h20-7 (10 10) 8.0e+04 +77.44 (1.1) -170.53 (1.1) -85.44 (0.5) stand h20-8 (10 10) 8.0e+04 +79.11 (1.1) -170.08 (1.1) -85.02 (0.6) stand h20-9 (10 10) 8.0e+04 +75.77 (1.1) -170.31 (1.1) -84.87 (0.6) stand p2-6 8e+04 +24.78 (2.9) +3.07 (1.0) yes p2-7 8e+04 +1.48 (2.0) -8.90 (1.0) yes p2-8 8e+04 -17.57 (2.0) -16.33 (1.0) uncertain p2-8 3e+05 -17.88 (1.0) -16.10 (0.5) no p2-9 8e+04 -38.73 (2.0) -24.38 (1.0) no p2-T 8e+04 -54.45 (1.8) -34.92 (0.9) no p2-A 8e+04 -67.11 (1.5) -51.59 (0.9) no @end verbatim A new text file called @code{bs.txt} with the strategy should be created from scratch: @verbatim ## 2 3 4 5 6 7 8 9 T A h20 s s s s s s s s s s h19 s s s s s s s s s s h18 s s s s s s s s s s h17 s s s s s s s s s s h16 s s s s s h h h h h h15 s s s s s h h h h h h14 s s s s s h h h h h h13 s s s s s h h h h h h12 h h s s s h h h h h h11 d d d d d d d d d d h10 d d d d d d d d h h h9 h d d d d h h h h h h8 h h h h h h h h h h h7 h h h h h h h h h h h6 h h h h h h h h h h h5 h h h h h h h h h h h4 h h h h h h h h h h ## 2 3 4 5 6 7 8 9 T A s20 s s s s s s s s s s s19 s s s s d s s s s s s18 d d d d d s s h h h s17 h d d d d h h h h h s16 h h d d d h h h h h s15 h h d d d h h h h h s14 h h h d d h h h h h s13 h h h h d h h h h h s12 h h h h d h h h h h ## 2 3 4 5 6 7 8 9 T A pA y y y y y y y y y y pT n n n n n n n n n n p9 y y y y y n y y n n p8 y y y y y y y y y y p7 y y y y y y n n n n p6 y y y y y n n n n n p5 n n n n n n n n n n p4 n n n y y n n n n n p3 y y y y y y n n n n p2 y y y y y y n n n n @end verbatim @node Full table with results @subsection Full table with results @anchor{#full-table-with-results} The script computes the expected value of each combination @enumerate @item Player's hand (hard, soft and pair) @item Dealer upcard @item Hit, double or stand (for hard and soft hands) and splitting or not (for pairs) @end enumerate The results are given as the expected value in percentage with the uncertainty (one standard deviation) in the last significant digit. @multitable {s12-A} {Hands needed} {-72.15 (1.6)} {-35.17 (0.9)} {-113.22 (1.4)} {double} @headitem Hand @tab Hands needed @tab Stand [%] @tab Double [%] @tab Hit [%] @tab Play @item h20-2 @tab 8.0e+04 @tab +63.55 (1.1) @tab -85.62 (0.5) @tab -171.16 (1.1) @tab stand @item h20-3 @tab 8.0e+04 @tab +64.58 (1.1) @tab -85.56 (0.5) @tab -170.56 (1.1) @tab stand @item h20-4 @tab 8.0e+04 @tab +65.30 (1.1) @tab -85.70 (0.5) @tab -171.10 (1.1) @tab stand @item h20-5 @tab 8.0e+04 @tab +67.04 (1.1) @tab -85.52 (0.5) @tab -171.34 (1.1) @tab stand @item h20-6 @tab 8.0e+04 @tab +67.81 (1.1) @tab -85.17 (0.5) @tab -170.61 (1.1) @tab stand @item h20-7 @tab 8.0e+04 @tab +77.12 (1.1) @tab -85.13 (0.6) @tab -170.32 (1.1) @tab stand @item h20-8 @tab 8.0e+04 @tab +79.14 (1.1) @tab -84.99 (0.6) @tab -170.46 (1.1) @tab stand @item h20-9 @tab 8.0e+04 @tab +75.94 (1.1) @tab -85.00 (0.6) @tab -169.53 (1.1) @tab stand @item h20-T @tab 8.0e+04 @tab +43.51 (1.1) @tab -86.06 (0.5) @tab -164.02 (1.1) @tab stand @item h20-A @tab 8.0e+04 @tab +10.86 (1.0) @tab -89.62 (0.5) @tab -149.06 (1.0) @tab stand @item h19-2 @tab 8.0e+04 @tab +37.41 (1.4) @tab -73.09 (0.7) @tab -146.25 (1.4) @tab stand @item h19-3 @tab 8.0e+04 @tab +40.09 (1.4) @tab -72.96 (0.7) @tab -145.29 (1.4) @tab stand @item h19-4 @tab 8.0e+04 @tab +41.38 (1.4) @tab -72.80 (0.7) @tab -146.07 (1.4) @tab stand @item h19-5 @tab 8.0e+04 @tab +43.76 (1.4) @tab -72.76 (0.7) @tab -144.19 (1.4) @tab stand @item h19-6 @tab 8.0e+04 @tab +45.80 (1.4) @tab -72.62 (0.7) @tab -145.14 (1.4) @tab stand @item h19-7 @tab 8.0e+04 @tab +61.39 (1.5) @tab -71.50 (0.7) @tab -143.39 (1.5) @tab stand @item h19-8 @tab 8.0e+04 @tab +59.58 (1.5) @tab -71.36 (0.7) @tab -143.03 (1.5) @tab stand @item h19-9 @tab 8.0e+04 @tab +28.15 (1.5) @tab -71.59 (0.7) @tab -143.42 (1.5) @tab stand @item h19-T @tab 8.0e+04 @tab -2.00 (1.3) @tab -74.91 (0.7) @tab -142.88 (1.3) @tab stand @item h19-A @tab 8.0e+04 @tab -18.04 (1.2) @tab -81.43 (0.6) @tab -131.46 (1.2) @tab stand @item h18-2 @tab 8.0e+04 @tab +11.02 (1.6) @tab -62.22 (0.8) @tab -123.71 (1.6) @tab stand @item h18-3 @tab 8.0e+04 @tab +13.20 (1.6) @tab -61.53 (0.8) @tab -124.35 (1.6) @tab stand @item h18-4 @tab 8.0e+04 @tab +16.92 (1.6) @tab -61.80 (0.8) @tab -123.86 (1.6) @tab stand @item h18-5 @tab 8.0e+04 @tab +19.35 (1.6) @tab -61.38 (0.8) @tab -123.62 (1.6) @tab stand @item h18-6 @tab 8.0e+04 @tab +22.36 (1.6) @tab -61.35 (0.8) @tab -121.85 (1.6) @tab stand @item h18-7 @tab 8.0e+04 @tab +39.35 (1.7) @tab -59.36 (0.8) @tab -118.48 (1.7) @tab stand @item h18-8 @tab 8.0e+04 @tab +10.34 (1.7) @tab -58.35 (0.8) @tab -117.43 (1.7) @tab stand @item h18-9 @tab 8.0e+04 @tab -18.74 (1.6) @tab -61.52 (0.8) @tab -123.34 (1.6) @tab stand @item h18-T @tab 8.0e+04 @tab -23.84 (1.5) @tab -67.55 (0.8) @tab -127.96 (1.5) @tab stand @item h18-A @tab 8.0e+04 @tab -46.97 (1.3) @tab -74.64 (0.7) @tab -118.63 (1.3) @tab stand @item h17-2 @tab 8.0e+04 @tab -15.44 (1.7) @tab -53.93 (0.9) @tab -108.61 (1.7) @tab stand @item h17-3 @tab 8.0e+04 @tab -12.18 (1.8) @tab -53.57 (0.9) @tab -105.83 (1.8) @tab stand @item h17-4 @tab 8.0e+04 @tab -8.33 (1.8) @tab -52.86 (0.9) @tab -105.69 (1.8) @tab stand @item h17-5 @tab 8.0e+04 @tab -4.55 (1.8) @tab -51.66 (0.9) @tab -105.34 (1.8) @tab stand @item h17-6 @tab 8.0e+04 @tab -1.15 (1.8) @tab -51.94 (0.9) @tab -104.07 (1.8) @tab stand @item h17-7 @tab 8.0e+04 @tab -10.79 (1.8) @tab -48.10 (0.9) @tab -96.43 (1.8) @tab stand @item h17-8 @tab 8.0e+04 @tab -38.74 (1.8) @tab -50.44 (0.9) @tab -101.03 (1.8) @tab stand @item h17-9 @tab 8.0e+04 @tab -42.54 (1.7) @tab -55.42 (0.8) @tab -111.46 (1.7) @tab stand @item h17-T @tab 8.0e+04 @tab -46.12 (1.6) @tab -61.91 (0.8) @tab -115.53 (1.6) @tab stand @item h17-A @tab 8.0e+04 @tab -66.10 (1.4) @tab -70.80 (0.7) @tab -110.62 (1.4) @tab stand @item h16-2 @tab 8.0e+04 @tab -28.62 (1.8) @tab -47.46 (0.9) @tab -95.12 (1.8) @tab stand @item h16-3 @tab 8.0e+04 @tab -24.81 (1.8) @tab -46.52 (0.9) @tab -93.95 (1.8) @tab stand @item h16-4 @tab 8.0e+04 @tab -20.67 (1.8) @tab -45.46 (0.9) @tab -91.92 (1.8) @tab stand @item h16-5 @tab 8.0e+04 @tab -16.48 (1.8) @tab -45.18 (0.9) @tab -89.56 (1.8) @tab stand @item h16-6 @tab 8.0e+04 @tab -11.55 (1.9) @tab -44.39 (0.9) @tab -87.64 (1.9) @tab stand @item h16-7 @tab 8.0e+04 @tab -47.14 (1.9) @tab -41.27 (0.9) @tab -84.33 (1.9) @tab hit @item h16-8 @tab 8.0e+04 @tab -50.94 (1.8) @tab -45.95 (0.9) @tab -92.12 (1.8) @tab hit @item h16-9 @tab 8.0e+04 @tab -54.50 (1.7) @tab -50.71 (0.9) @tab -102.58 (1.7) @tab hit @item h16-T @tab 2.0e+07 @tab -57.57 (0) @tab -57.53 (0) @tab -107.34 (0) @tab hit @item h16-A @tab 8.0e+04 @tab -72.39 (1.4) @tab -68.19 (0.7) @tab -105.24 (1.4) @tab hit @item h15-2 @tab 8.0e+04 @tab -28.36 (1.9) @tab -41.53 (0.9) @tab -83.65 (1.9) @tab stand @item h15-3 @tab 8.0e+04 @tab -25.21 (1.9) @tab -40.72 (0.9) @tab -81.48 (1.9) @tab stand @item h15-4 @tab 8.0e+04 @tab -20.66 (1.9) @tab -39.38 (0.9) @tab -78.86 (1.9) @tab stand @item h15-5 @tab 8.0e+04 @tab -16.55 (1.9) @tab -38.38 (1.0) @tab -77.57 (1.9) @tab stand @item h15-6 @tab 8.0e+04 @tab -11.88 (1.9) @tab -37.86 (1.0) @tab -75.22 (1.9) @tab stand @item h15-7 @tab 8.0e+04 @tab -48.09 (1.9) @tab -37.04 (0.9) @tab -75.35 (1.9) @tab hit @item h15-8 @tab 8.0e+04 @tab -50.84 (1.9) @tab -41.53 (0.9) @tab -83.94 (1.9) @tab hit @item h15-9 @tab 8.0e+04 @tab -54.38 (1.8) @tab -47.30 (0.9) @tab -95.06 (1.8) @tab hit @item h15-T @tab 8.0e+04 @tab -57.73 (1.7) @tab -54.62 (0.9) @tab -99.81 (1.7) @tab hit @item h15-A @tab 8.0e+04 @tab -72.00 (1.5) @tab -65.80 (0.8) @tab -101.33 (1.5) @tab hit @item h14-2 @tab 8.0e+04 @tab -28.56 (1.9) @tab -36.62 (1.0) @tab -72.17 (1.9) @tab stand @item h14-3 @tab 8.0e+04 @tab -24.12 (1.9) @tab -34.63 (1.0) @tab -70.90 (1.9) @tab stand @item h14-4 @tab 8.0e+04 @tab -20.48 (1.9) @tab -33.73 (1.0) @tab -68.97 (1.9) @tab stand @item h14-5 @tab 8.0e+04 @tab -16.54 (2.0) @tab -31.93 (1.0) @tab -64.39 (2.0) @tab stand @item h14-6 @tab 8.0e+04 @tab -12.19 (2.0) @tab -30.64 (1.0) @tab -60.75 (2.0) @tab stand @item h14-7 @tab 8.0e+04 @tab -47.85 (1.9) @tab -32.25 (1.0) @tab -66.44 (1.9) @tab hit @item h14-8 @tab 8.0e+04 @tab -51.09 (1.9) @tab -37.59 (0.9) @tab -76.59 (1.9) @tab hit @item h14-9 @tab 8.0e+04 @tab -54.41 (1.8) @tab -43.27 (0.9) @tab -87.80 (1.8) @tab hit @item h14-T @tab 8.0e+04 @tab -57.74 (1.7) @tab -50.71 (0.9) @tab -94.55 (1.7) @tab hit @item h14-A @tab 8.0e+04 @tab -72.11 (1.5) @tab -62.81 (0.8) @tab -97.57 (1.5) @tab hit @item h13-2 @tab 3.2e+05 @tab -28.58 (1.0) @tab -30.97 (0.5) @tab -61.58 (1.0) @tab stand @item h13-3 @tab 8.0e+04 @tab -24.61 (2.0) @tab -29.17 (1.0) @tab -58.99 (2.0) @tab stand @item h13-4 @tab 8.0e+04 @tab -21.15 (2.0) @tab -27.05 (1.0) @tab -55.31 (2.0) @tab stand @item h13-5 @tab 8.0e+04 @tab -16.88 (2.0) @tab -26.15 (1.0) @tab -50.31 (2.0) @tab stand @item h13-6 @tab 8.0e+04 @tab -12.35 (2.0) @tab -24.12 (1.0) @tab -47.91 (2.0) @tab stand @item h13-7 @tab 8.0e+04 @tab -47.50 (2.0) @tab -26.69 (1.0) @tab -58.47 (2.0) @tab hit @item h13-8 @tab 8.0e+04 @tab -51.33 (1.9) @tab -32.22 (1.0) @tab -70.19 (1.9) @tab hit @item h13-9 @tab 8.0e+04 @tab -54.31 (1.9) @tab -38.57 (0.9) @tab -80.97 (1.9) @tab hit @item h13-T @tab 8.0e+04 @tab -56.99 (1.8) @tab -46.49 (0.9) @tab -87.36 (1.8) @tab hit @item h13-A @tab 8.0e+04 @tab -72.39 (1.5) @tab -60.33 (0.8) @tab -92.36 (1.5) @tab hit @item h12-2 @tab 8.0e+04 @tab -28.53 (2.0) @tab -25.26 (1.0) @tab -50.10 (2.0) @tab hit @item h12-3 @tab 3.2e+05 @tab -24.74 (1.0) @tab -23.20 (0.5) @tab -47.17 (1.0) @tab hit @item h12-4 @tab 5.1e+06 @tab -20.50 (0.3) @tab -21.34 (0.1) @tab -42.80 (0.3) @tab stand @item h12-5 @tab 3.2e+05 @tab -16.67 (1.0) @tab -19.49 (0.5) @tab -38.59 (1.0) @tab stand @item h12-6 @tab 8.0e+04 @tab -11.57 (2.0) @tab -17.45 (1.0) @tab -34.91 (2.0) @tab stand @item h12-7 @tab 8.0e+04 @tab -47.16 (2.0) @tab -21.22 (1.0) @tab -49.56 (2.0) @tab hit @item h12-8 @tab 8.0e+04 @tab -51.23 (2.0) @tab -26.82 (1.0) @tab -61.96 (2.0) @tab hit @item h12-9 @tab 8.0e+04 @tab -54.02 (1.9) @tab -33.93 (1.0) @tab -74.10 (1.9) @tab hit @item h12-T @tab 8.0e+04 @tab -58.14 (1.8) @tab -43.03 (0.9) @tab -82.21 (1.8) @tab hit @item h12-A @tab 8.0e+04 @tab -72.60 (1.5) @tab -57.38 (0.8) @tab -88.89 (1.5) @tab hit @item h11-2 @tab 8.0e+04 @tab -27.73 (2.0) @tab +23.74 (1.0) @tab +46.68 (2.0) @tab double @item h11-3 @tab 8.0e+04 @tab -24.81 (2.0) @tab +26.30 (1.0) @tab +50.86 (2.0) @tab double @item h11-4 @tab 8.0e+04 @tab -20.28 (2.0) @tab +28.91 (1.0) @tab +56.46 (2.0) @tab double @item h11-5 @tab 8.0e+04 @tab -16.10 (1.9) @tab +31.08 (1.0) @tab +60.58 (1.9) @tab double @item h11-6 @tab 8.0e+04 @tab -12.18 (1.9) @tab +33.16 (1.0) @tab +67.19 (1.9) @tab double @item h11-7 @tab 8.0e+04 @tab -47.49 (2.0) @tab +29.49 (1.0) @tab +46.09 (2.0) @tab double @item h11-8 @tab 8.0e+04 @tab -51.29 (2.0) @tab +22.39 (1.0) @tab +34.94 (2.0) @tab double @item h11-9 @tab 8.0e+04 @tab -54.41 (2.0) @tab +15.62 (1.0) @tab +23.72 (2.0) @tab double @item h11-T @tab 8.0e+04 @tab -57.70 (2.0) @tab +3.21 (1.0) @tab +9.84 (2.0) @tab double @item h11-A @tab 2.0e+07 @tab -72.22 (0) @tab -23.67 (0) @tab -23.56 (0) @tab double @item h10-2 @tab 8.0e+04 @tab -28.45 (2.0) @tab +18.25 (1.0) @tab +35.73 (2.0) @tab double @item h10-3 @tab 8.0e+04 @tab -23.99 (2.0) @tab +20.70 (1.0) @tab +40.59 (2.0) @tab double @item h10-4 @tab 8.0e+04 @tab -21.31 (2.0) @tab +23.14 (1.0) @tab +46.54 (2.0) @tab double @item h10-5 @tab 8.0e+04 @tab -16.23 (2.0) @tab +25.77 (1.0) @tab +51.66 (2.0) @tab double @item h10-6 @tab 8.0e+04 @tab -12.01 (2.0) @tab +28.63 (1.0) @tab +56.36 (2.0) @tab double @item h10-7 @tab 8.0e+04 @tab -47.40 (2.0) @tab +25.23 (1.0) @tab +38.38 (2.0) @tab double @item h10-8 @tab 8.0e+04 @tab -51.35 (2.0) @tab +20.43 (1.0) @tab +28.63 (2.0) @tab double @item h10-9 @tab 3.2e+05 @tab -54.13 (1.0) @tab +11.81 (0.5) @tab +15.23 (1.0) @tab double @item h10-T @tab 8.0e+04 @tab -58.04 (1.9) @tab -5.84 (1.0) @tab -7.94 (1.9) @tab hit @item h10-A @tab 8.0e+04 @tab -72.46 (1.7) @tab -28.90 (1.0) @tab -33.54 (1.7) @tab hit @item h9-2 @tab 3.2e+05 @tab -28.82 (1.0) @tab +7.62 (0.5) @tab +5.95 (1.0) @tab hit @item h9-3 @tab 3.2e+05 @tab -24.59 (1.0) @tab +9.93 (0.5) @tab +11.94 (1.0) @tab double @item h9-4 @tab 8.0e+04 @tab -20.79 (2.0) @tab +12.15 (1.0) @tab +17.76 (2.0) @tab double @item h9-5 @tab 8.0e+04 @tab -16.50 (2.0) @tab +15.92 (1.0) @tab +23.51 (2.0) @tab double @item h9-6 @tab 8.0e+04 @tab -12.35 (2.0) @tab +19.57 (1.0) @tab +30.65 (2.0) @tab double @item h9-7 @tab 8.0e+04 @tab -47.62 (2.0) @tab +17.20 (1.0) @tab +10.00 (2.0) @tab hit @item h9-8 @tab 8.0e+04 @tab -50.97 (2.0) @tab +10.15 (1.0) @tab -2.38 (2.0) @tab hit @item h9-9 @tab 8.0e+04 @tab -53.95 (1.9) @tab -4.61 (1.0) @tab -29.84 (1.9) @tab hit @item h9-T @tab 8.0e+04 @tab -57.78 (1.9) @tab -21.96 (1.0) @tab -52.36 (1.9) @tab hit @item h9-A @tab 8.0e+04 @tab -72.33 (1.7) @tab -38.77 (0.9) @tab -61.26 (1.7) @tab hit @item h8-2 @tab 8.0e+04 @tab -29.03 (2.0) @tab -1.76 (1.0) @tab -19.15 (2.0) @tab hit @item h8-3 @tab 8.0e+04 @tab -25.61 (2.1) @tab +0.33 (1.0) @tab -13.68 (2.1) @tab hit @item h8-4 @tab 8.0e+04 @tab -20.69 (2.1) @tab +3.82 (1.0) @tab -7.66 (2.1) @tab hit @item h8-5 @tab 8.0e+04 @tab -16.06 (2.1) @tab +7.53 (1.0) @tab +0.32 (2.1) @tab hit @item h8-6 @tab 3.2e+05 @tab -12.16 (1.0) @tab +10.49 (0.5) @tab +7.43 (1.0) @tab hit @item h8-7 @tab 8.0e+04 @tab -47.34 (2.0) @tab +8.56 (1.0) @tab -16.64 (2.0) @tab hit @item h8-8 @tab 8.0e+04 @tab -51.56 (1.9) @tab -6.18 (1.0) @tab -46.07 (1.9) @tab hit @item h8-9 @tab 8.0e+04 @tab -54.44 (1.9) @tab -21.65 (1.0) @tab -71.64 (1.9) @tab hit @item h8-T @tab 8.0e+04 @tab -57.15 (1.8) @tab -30.78 (1.0) @tab -76.35 (1.8) @tab hit @item h8-A @tab 8.0e+04 @tab -72.01 (1.5) @tab -49.02 (0.9) @tab -88.47 (1.5) @tab hit @item h7-2 @tab 8.0e+04 @tab -29.15 (2.0) @tab -11.08 (1.0) @tab -42.53 (2.0) @tab hit @item h7-3 @tab 8.0e+04 @tab -24.37 (2.0) @tab -7.51 (1.0) @tab -34.68 (2.0) @tab hit @item h7-4 @tab 8.0e+04 @tab -19.40 (2.1) @tab -3.90 (1.0) @tab -27.57 (2.1) @tab hit @item h7-5 @tab 8.0e+04 @tab -16.84 (2.1) @tab -0.53 (1.0) @tab -20.59 (2.1) @tab hit @item h7-6 @tab 8.0e+04 @tab -11.93 (2.1) @tab +2.53 (1.0) @tab -10.66 (2.1) @tab hit @item h7-7 @tab 8.0e+04 @tab -47.22 (1.9) @tab -7.33 (1.0) @tab -59.71 (1.9) @tab hit @item h7-8 @tab 8.0e+04 @tab -50.71 (1.8) @tab -20.35 (1.0) @tab -85.02 (1.8) @tab hit @item h7-9 @tab 8.0e+04 @tab -54.12 (1.8) @tab -29.11 (1.0) @tab -96.16 (1.8) @tab hit @item h7-T @tab 8.0e+04 @tab -57.52 (1.7) @tab -37.06 (0.9) @tab -95.95 (1.7) @tab hit @item h7-A @tab 8.0e+04 @tab -72.23 (1.4) @tab -55.54 (0.8) @tab -104.99 (1.4) @tab hit @item h6-2 @tab 8.0e+04 @tab -28.38 (2.0) @tab -15.59 (1.0) @tab -56.44 (2.0) @tab hit @item h6-3 @tab 8.0e+04 @tab -24.34 (2.1) @tab -11.56 (1.0) @tab -46.62 (2.1) @tab hit @item h6-4 @tab 8.0e+04 @tab -21.46 (2.1) @tab -8.03 (1.0) @tab -39.24 (2.1) @tab hit @item h6-5 @tab 8.0e+04 @tab -16.68 (2.1) @tab -4.95 (1.0) @tab -31.10 (2.1) @tab hit @item h6-6 @tab 8.0e+04 @tab -12.40 (2.1) @tab -0.76 (1.0) @tab -22.49 (2.1) @tab hit @item h6-7 @tab 8.0e+04 @tab -47.58 (1.9) @tab -16.43 (1.0) @tab -89.56 (1.9) @tab hit @item h6-8 @tab 8.0e+04 @tab -50.72 (1.8) @tab -24.13 (1.0) @tab -98.62 (1.8) @tab hit @item h6-9 @tab 8.0e+04 @tab -54.32 (1.8) @tab -31.34 (1.0) @tab -107.41 (1.8) @tab hit @item h6-T @tab 8.0e+04 @tab -57.56 (1.7) @tab -40.02 (0.9) @tab -105.28 (1.7) @tab hit @item h6-A @tab 8.0e+04 @tab -72.04 (1.4) @tab -56.31 (0.8) @tab -112.37 (1.4) @tab hit @item h5-2 @tab 8.0e+04 @tab -28.46 (2.0) @tab -14.09 (1.0) @tab -56.05 (2.0) @tab hit @item h5-3 @tab 8.0e+04 @tab -24.73 (2.1) @tab -11.80 (1.0) @tab -49.48 (2.1) @tab hit @item h5-4 @tab 8.0e+04 @tab -20.62 (2.1) @tab -8.01 (1.0) @tab -42.69 (2.1) @tab hit @item h5-5 @tab 8.0e+04 @tab -16.47 (2.1) @tab -4.45 (1.0) @tab -32.88 (2.1) @tab hit @item h5-6 @tab 8.0e+04 @tab -12.29 (2.1) @tab -0.24 (1.0) @tab -24.41 (2.1) @tab hit @item h5-7 @tab 8.0e+04 @tab -47.07 (1.9) @tab -16.19 (1.0) @tab -94.28 (1.9) @tab hit @item h5-8 @tab 8.0e+04 @tab -51.00 (1.8) @tab -22.25 (1.0) @tab -101.66 (1.8) @tab hit @item h5-9 @tab 8.0e+04 @tab -54.20 (1.8) @tab -29.74 (1.0) @tab -107.96 (1.8) @tab hit @item h5-T @tab 8.0e+04 @tab -57.42 (1.7) @tab -38.76 (0.9) @tab -107.09 (1.7) @tab hit @item h5-A @tab 8.0e+04 @tab -72.39 (1.4) @tab -54.71 (0.8) @tab -114.03 (1.4) @tab hit @item h4-2 @tab 8.0e+04 @tab -28.76 (2.0) @tab -12.93 (1.0) @tab -57.47 (2.0) @tab hit @item h4-3 @tab 8.0e+04 @tab -24.68 (2.1) @tab -10.48 (1.0) @tab -49.92 (2.1) @tab hit @item h4-4 @tab 8.0e+04 @tab -20.67 (2.1) @tab -7.36 (1.0) @tab -41.23 (2.1) @tab hit @item h4-5 @tab 8.0e+04 @tab -16.91 (2.1) @tab -3.43 (1.0) @tab -32.59 (2.1) @tab hit @item h4-6 @tab 8.0e+04 @tab -12.25 (2.1) @tab +0.40 (1.0) @tab -23.57 (2.1) @tab hit @item h4-7 @tab 8.0e+04 @tab -47.75 (1.9) @tab -12.72 (1.0) @tab -94.73 (1.9) @tab hit @item h4-8 @tab 8.0e+04 @tab -50.76 (1.8) @tab -19.63 (1.0) @tab -103.23 (1.8) @tab hit @item h4-9 @tab 8.0e+04 @tab -54.06 (1.8) @tab -28.13 (1.0) @tab -108.57 (1.8) @tab hit @item h4-T @tab 8.0e+04 @tab -56.86 (1.7) @tab -36.62 (0.9) @tab -107.18 (1.7) @tab hit @item h4-A @tab 8.0e+04 @tab -72.38 (1.4) @tab -53.76 (0.9) @tab -113.22 (1.4) @tab hit @item s20-2 @tab 8.0e+04 @tab +63.48 (2.0) @tab +18.05 (1.0) @tab +36.30 (2.0) @tab stand @item s20-3 @tab 8.0e+04 @tab +64.51 (2.0) @tab +19.96 (1.0) @tab +41.60 (2.0) @tab stand @item s20-4 @tab 8.0e+04 @tab +65.47 (2.0) @tab +22.51 (1.0) @tab +45.96 (2.0) @tab stand @item s20-5 @tab 8.0e+04 @tab +66.59 (2.0) @tab +26.19 (1.0) @tab +50.69 (2.0) @tab stand @item s20-6 @tab 8.0e+04 @tab +68.22 (2.0) @tab +28.20 (1.0) @tab +56.57 (2.0) @tab stand @item s20-7 @tab 8.0e+04 @tab +77.45 (2.0) @tab +26.05 (1.0) @tab +40.16 (2.0) @tab stand @item s20-8 @tab 8.0e+04 @tab +79.03 (2.0) @tab +19.32 (1.0) @tab +28.44 (2.0) @tab stand @item s20-9 @tab 8.0e+04 @tab +76.09 (2.0) @tab +11.81 (1.0) @tab +15.62 (2.0) @tab stand @item s20-T @tab 8.0e+04 @tab +43.83 (1.9) @tab -5.43 (1.0) @tab -8.42 (1.9) @tab stand @item s20-A @tab 8.0e+04 @tab +10.71 (1.7) @tab -28.46 (1.0) @tab -34.57 (1.7) @tab stand @item s19-2 @tab 8.0e+04 @tab +37.55 (2.0) @tab +12.16 (1.0) @tab +23.28 (2.0) @tab stand @item s19-3 @tab 8.0e+04 @tab +39.32 (2.0) @tab +14.45 (1.0) @tab +28.76 (2.0) @tab stand @item s19-4 @tab 8.0e+04 @tab +41.67 (2.0) @tab +17.97 (1.0) @tab +34.49 (2.0) @tab stand @item s19-5 @tab 3.2e+05 @tab +43.87 (1.0) @tab +20.25 (0.5) @tab +39.76 (1.0) @tab stand @item s19-6 @tab 5.1e+06 @tab +45.30 (0.2) @tab +23.06 (0.1) @tab +46.24 (0.2) @tab double @item s19-7 @tab 8.0e+04 @tab +62.00 (2.0) @tab +22.80 (1.0) @tab +32.42 (2.0) @tab stand @item s19-8 @tab 8.0e+04 @tab +59.68 (2.0) @tab +15.07 (1.0) @tab +20.09 (2.0) @tab stand @item s19-9 @tab 8.0e+04 @tab +28.83 (2.0) @tab +1.29 (1.0) @tab -7.06 (2.0) @tab stand @item s19-T @tab 8.0e+04 @tab -1.88 (1.9) @tab -15.44 (1.0) @tab -29.40 (1.9) @tab stand @item s19-A @tab 8.0e+04 @tab -17.63 (1.7) @tab -34.41 (0.9) @tab -46.94 (1.7) @tab stand @item s18-2 @tab 2.0e+07 @tab +11.01 (0) @tab +6.00 (0) @tab +11.43 (0) @tab double @item s18-3 @tab 3.2e+05 @tab +13.74 (1.0) @tab +8.81 (0.5) @tab +17.70 (1.0) @tab double @item s18-4 @tab 8.0e+04 @tab +16.38 (2.0) @tab +12.04 (1.0) @tab +22.38 (2.0) @tab double @item s18-5 @tab 8.0e+04 @tab +19.67 (2.0) @tab +14.12 (1.0) @tab +29.11 (2.0) @tab double @item s18-6 @tab 8.0e+04 @tab +22.24 (2.0) @tab +15.83 (1.0) @tab +35.89 (2.0) @tab double @item s18-7 @tab 8.0e+04 @tab +39.95 (2.0) @tab +17.00 (1.0) @tab +21.63 (2.0) @tab stand @item s18-8 @tab 8.0e+04 @tab +10.59 (2.0) @tab +3.79 (1.0) @tab -2.20 (2.0) @tab stand @item s18-9 @tab 8.0e+04 @tab -18.25 (2.0) @tab -10.19 (1.0) @tab -27.83 (2.0) @tab hit @item s18-T @tab 8.0e+04 @tab -23.79 (1.9) @tab -20.45 (1.0) @tab -38.84 (1.9) @tab hit @item s18-A @tab 8.0e+04 @tab -46.31 (1.7) @tab -41.64 (0.9) @tab -59.63 (1.7) @tab hit @item s17-2 @tab 2.0e+07 @tab -15.67 (0) @tab -0.59 (0) @tab -0.88 (0) @tab hit @item s17-3 @tab 3.2e+05 @tab -12.35 (1.0) @tab +2.42 (0.5) @tab +5.90 (1.0) @tab double @item s17-4 @tab 8.0e+04 @tab -8.13 (2.0) @tab +5.14 (1.0) @tab +11.54 (2.0) @tab double @item s17-5 @tab 8.0e+04 @tab -4.49 (2.0) @tab +9.23 (1.0) @tab +18.59 (2.0) @tab double @item s17-6 @tab 8.0e+04 @tab -0.39 (2.0) @tab +10.43 (1.0) @tab +25.67 (2.0) @tab double @item s17-7 @tab 8.0e+04 @tab -10.70 (2.0) @tab +5.76 (1.0) @tab -2.08 (2.0) @tab hit @item s17-8 @tab 8.0e+04 @tab -37.98 (2.0) @tab -7.55 (1.0) @tab -24.83 (2.0) @tab hit @item s17-9 @tab 8.0e+04 @tab -42.52 (2.0) @tab -14.14 (1.0) @tab -39.49 (2.0) @tab hit @item s17-T @tab 8.0e+04 @tab -46.49 (1.9) @tab -25.88 (1.0) @tab -50.28 (1.9) @tab hit @item s17-A @tab 8.0e+04 @tab -66.85 (1.6) @tab -46.56 (0.9) @tab -68.92 (1.6) @tab hit @item s16-2 @tab 8.0e+04 @tab -28.87 (2.1) @tab -1.93 (1.0) @tab -7.79 (2.1) @tab hit @item s16-3 @tab 3.2e+05 @tab -24.68 (1.0) @tab +0.27 (0.5) @tab -1.15 (1.0) @tab hit @item s16-4 @tab 3.2e+05 @tab -20.67 (1.0) @tab +3.56 (0.5) @tab +5.67 (1.0) @tab double @item s16-5 @tab 8.0e+04 @tab -16.41 (2.1) @tab +6.62 (1.0) @tab +13.59 (2.1) @tab double @item s16-6 @tab 8.0e+04 @tab -12.54 (2.1) @tab +8.47 (1.0) @tab +19.52 (2.1) @tab double @item s16-7 @tab 8.0e+04 @tab -47.66 (2.1) @tab -0.28 (1.0) @tab -17.54 (2.1) @tab hit @item s16-8 @tab 8.0e+04 @tab -51.11 (2.0) @tab -6.82 (1.0) @tab -31.42 (2.0) @tab hit @item s16-9 @tab 8.0e+04 @tab -54.37 (2.0) @tab -14.60 (1.0) @tab -45.25 (2.0) @tab hit @item s16-T @tab 8.0e+04 @tab -57.80 (1.9) @tab -26.81 (1.0) @tab -55.92 (1.9) @tab hit @item s16-A @tab 8.0e+04 @tab -72.59 (1.6) @tab -44.41 (0.9) @tab -71.66 (1.6) @tab hit @item s15-2 @tab 8.0e+04 @tab -28.34 (2.1) @tab -0.67 (1.0) @tab -7.00 (2.1) @tab hit @item s15-3 @tab 8.0e+04 @tab -24.95 (2.1) @tab +2.82 (1.0) @tab -0.19 (2.1) @tab hit @item s15-4 @tab 5.1e+06 @tab -20.55 (0.3) @tab +5.57 (0.1) @tab +6.16 (0.3) @tab double @item s15-5 @tab 8.0e+04 @tab -16.27 (2.1) @tab +8.83 (1.0) @tab +13.72 (2.1) @tab double @item s15-6 @tab 8.0e+04 @tab -12.97 (2.1) @tab +9.96 (1.0) @tab +20.24 (2.1) @tab double @item s15-7 @tab 8.0e+04 @tab -47.65 (2.1) @tab +3.09 (1.0) @tab -18.41 (2.1) @tab hit @item s15-8 @tab 8.0e+04 @tab -51.20 (2.0) @tab -2.86 (1.0) @tab -31.79 (2.0) @tab hit @item s15-9 @tab 8.0e+04 @tab -55.02 (2.0) @tab -11.42 (1.0) @tab -46.42 (2.0) @tab hit @item s15-T @tab 8.0e+04 @tab -57.45 (1.9) @tab -23.91 (1.0) @tab -54.95 (1.9) @tab hit @item s15-A @tab 8.0e+04 @tab -72.00 (1.6) @tab -42.42 (0.9) @tab -72.09 (1.6) @tab hit @item s14-2 @tab 8.0e+04 @tab -28.06 (2.1) @tab +1.78 (1.0) @tab -6.21 (2.1) @tab hit @item s14-3 @tab 8.0e+04 @tab -24.41 (2.1) @tab +4.42 (1.0) @tab -0.62 (2.1) @tab hit @item s14-4 @tab 8.0e+04 @tab -20.41 (2.1) @tab +8.31 (1.0) @tab +5.82 (2.1) @tab hit @item s14-5 @tab 3.2e+05 @tab -16.31 (1.0) @tab +10.82 (0.5) @tab +12.34 (1.0) @tab double @item s14-6 @tab 8.0e+04 @tab -12.35 (2.1) @tab +11.90 (1.0) @tab +19.57 (2.1) @tab double @item s14-7 @tab 8.0e+04 @tab -47.52 (2.0) @tab +7.95 (1.0) @tab -18.64 (2.0) @tab hit @item s14-8 @tab 8.0e+04 @tab -51.41 (2.0) @tab +2.01 (1.0) @tab -32.23 (2.0) @tab hit @item s14-9 @tab 8.0e+04 @tab -54.26 (2.0) @tab -7.57 (1.0) @tab -45.45 (2.0) @tab hit @item s14-T @tab 8.0e+04 @tab -57.20 (1.9) @tab -20.14 (1.0) @tab -56.20 (1.9) @tab hit @item s14-A @tab 8.0e+04 @tab -72.41 (1.6) @tab -39.75 (0.9) @tab -70.94 (1.6) @tab hit @item s13-2 @tab 8.0e+04 @tab -28.79 (2.1) @tab +4.29 (1.0) @tab -7.07 (2.1) @tab hit @item s13-3 @tab 8.0e+04 @tab -24.39 (2.1) @tab +7.00 (1.0) @tab -0.33 (2.1) @tab hit @item s13-4 @tab 8.0e+04 @tab -20.39 (2.1) @tab +10.23 (1.0) @tab +5.20 (2.1) @tab hit @item s13-5 @tab 2.0e+07 @tab -16.46 (0) @tab +12.88 (0) @tab +12.73 (0) @tab hit @item s13-6 @tab 8.0e+04 @tab -12.67 (2.1) @tab +13.75 (1.0) @tab +18.93 (2.1) @tab double @item s13-7 @tab 8.0e+04 @tab -47.64 (2.1) @tab +12.41 (1.0) @tab -18.59 (2.1) @tab hit @item s13-8 @tab 8.0e+04 @tab -51.47 (2.0) @tab +5.50 (1.0) @tab -32.61 (2.0) @tab hit @item s13-9 @tab 8.0e+04 @tab -54.33 (2.0) @tab -3.30 (1.0) @tab -45.89 (2.0) @tab hit @item s13-T @tab 8.0e+04 @tab -57.17 (1.9) @tab -17.29 (1.0) @tab -55.28 (1.9) @tab hit @item s13-A @tab 8.0e+04 @tab -71.95 (1.6) @tab -37.21 (0.9) @tab -72.33 (1.6) @tab hit @item s12-2 @tab 8.0e+04 @tab -28.81 (2.1) @tab +7.24 (1.0) @tab -5.99 (2.1) @tab hit @item s12-3 @tab 8.0e+04 @tab -24.61 (2.1) @tab +9.89 (1.0) @tab -0.34 (2.1) @tab hit @item s12-4 @tab 8.0e+04 @tab -20.33 (2.1) @tab +12.28 (1.0) @tab +6.36 (2.1) @tab hit @item s12-5 @tab 8.0e+04 @tab -16.22 (2.1) @tab +15.13 (1.0) @tab +12.78 (2.1) @tab hit @item s12-6 @tab 8.0e+04 @tab -12.16 (2.1) @tab +15.30 (1.0) @tab +21.02 (2.1) @tab double @item s12-7 @tab 8.0e+04 @tab -46.97 (2.1) @tab +16.64 (1.0) @tab -18.22 (2.1) @tab hit @item s12-8 @tab 8.0e+04 @tab -50.98 (2.0) @tab +9.38 (1.0) @tab -31.23 (2.0) @tab hit @item s12-9 @tab 8.0e+04 @tab -54.01 (2.0) @tab +0.31 (1.0) @tab -45.30 (2.0) @tab hit @item s12-T @tab 8.0e+04 @tab -58.03 (1.9) @tab -14.72 (1.0) @tab -56.96 (1.9) @tab hit @item s12-A @tab 8.0e+04 @tab -72.15 (1.6) @tab -35.17 (0.9) @tab -72.39 (1.6) @tab hit @end multitable @multitable {p2-A} {Hands needed} {-67.42 (1.5)} {-51.15 (0.9)} @headitem Hand @tab Hands needed @tab Yes [%] @tab No [%] @item pA-2 @tab 8.0e+04 @tab +47.79 (1.7) @tab +7.70 (1.0) @item pA-3 @tab 8.0e+04 @tab +51.89 (1.7) @tab +9.80 (1.0) @item pA-4 @tab 8.0e+04 @tab +56.73 (1.7) @tab +11.81 (1.0) @item pA-5 @tab 8.0e+04 @tab +61.10 (1.7) @tab +15.76 (1.0) @item pA-6 @tab 8.0e+04 @tab +66.09 (1.7) @tab +20.40 (2.1) @item pA-7 @tab 8.0e+04 @tab +46.61 (1.6) @tab +15.82 (1.0) @item pA-8 @tab 8.0e+04 @tab +35.34 (1.6) @tab +9.87 (1.0) @item pA-9 @tab 8.0e+04 @tab +23.05 (1.6) @tab -0.13 (1.0) @item pA-T @tab 8.0e+04 @tab +8.79 (1.6) @tab -14.01 (1.0) @item pA-A @tab 8.0e+04 @tab -24.16 (1.5) @tab -35.35 (0.9) @item pT-2 @tab 8.0e+04 @tab -4.29 (3.7) @tab +63.29 (0.7) @item pT-3 @tab 8.0e+04 @tab +4.76 (3.8) @tab +64.28 (0.7) @item pT-4 @tab 8.0e+04 @tab +15.42 (4.0) @tab +65.64 (0.7) @item pT-5 @tab 8.0e+04 @tab +27.51 (4.1) @tab +66.77 (0.7) @item pT-6 @tab 8.0e+04 @tab +37.88 (4.1) @tab +67.89 (0.7) @item pT-7 @tab 8.0e+04 @tab +8.98 (2.6) @tab +77.52 (0.6) @item pT-8 @tab 8.0e+04 @tab -22.83 (2.5) @tab +79.04 (0.6) @item pT-9 @tab 8.0e+04 @tab -61.33 (2.6) @tab +76.23 (0.6) @item pT-T @tab 8.0e+04 @tab -76.47 (2.7) @tab +43.58 (0.7) @item pT-A @tab 8.0e+04 @tab -85.74 (2.2) @tab +11.11 (1.0) @item p9-2 @tab 8.0e+04 @tab +20.25 (2.2) @tab +10.96 (1.0) @item p9-3 @tab 8.0e+04 @tab +25.62 (2.2) @tab +13.70 (1.0) @item p9-4 @tab 8.0e+04 @tab +32.53 (2.2) @tab +16.16 (1.0) @item p9-5 @tab 8.0e+04 @tab +39.22 (2.2) @tab +19.08 (1.0) @item p9-6 @tab 8.0e+04 @tab +47.19 (2.2) @tab +22.75 (1.0) @item p9-7 @tab 3.2e+05 @tab +36.59 (0.9) @tab +40.03 (0.4) @item p9-8 @tab 8.0e+04 @tab +23.50 (1.9) @tab +10.05 (0.8) @item p9-9 @tab 8.0e+04 @tab -8.46 (1.8) @tab -18.37 (1.0) @item p9-T @tab 8.0e+04 @tab -36.82 (1.9) @tab -23.97 (1.0) @item p9-A @tab 3.2e+05 @tab -48.36 (0.8) @tab -46.75 (0.4) @item p8-2 @tab 8.0e+04 @tab +7.89 (2.4) @tab -29.06 (1.0) @item p8-3 @tab 8.0e+04 @tab +14.84 (2.4) @tab -23.82 (1.0) @item p8-4 @tab 8.0e+04 @tab +21.02 (2.5) @tab -20.67 (1.0) @item p8-5 @tab 8.0e+04 @tab +29.77 (2.5) @tab -16.36 (1.0) @item p8-6 @tab 8.0e+04 @tab +39.44 (2.7) @tab -11.93 (1.1) @item p8-7 @tab 8.0e+04 @tab +31.80 (2.1) @tab -41.83 (0.9) @item p8-8 @tab 8.0e+04 @tab -2.54 (2.1) @tab -45.57 (0.9) @item p8-9 @tab 8.0e+04 @tab -39.27 (2.2) @tab -50.67 (0.9) @item p8-T @tab 8.0e+04 @tab -51.15 (1.9) @tab -57.31 (0.8) @item p8-A @tab 3.2e+05 @tab -66.55 (0.8) @tab -68.39 (0.4) @item p7-2 @tab 8.0e+04 @tab -12.93 (2.6) @tab -28.38 (1.0) @item p7-3 @tab 8.0e+04 @tab -5.76 (2.8) @tab -24.45 (1.0) @item p7-4 @tab 8.0e+04 @tab +7.32 (2.9) @tab -21.06 (1.0) @item p7-5 @tab 8.0e+04 @tab +16.33 (2.9) @tab -16.50 (1.0) @item p7-6 @tab 8.0e+04 @tab +24.66 (2.9) @tab -12.31 (1.1) @item p7-7 @tab 8.0e+04 @tab -4.49 (2.1) @tab -31.70 (1.0) @item p7-8 @tab 3.2e+05 @tab -39.47 (1.0) @tab -36.94 (0.5) @item p7-9 @tab 8.0e+04 @tab -57.27 (2.1) @tab -43.25 (0.9) @item p7-T @tab 8.0e+04 @tab -68.16 (1.8) @tab -51.02 (0.9) @item p7-A @tab 8.0e+04 @tab -81.66 (1.6) @tab -62.96 (0.8) @item p6-2 @tab 8.0e+04 @tab -20.02 (2.5) @tab -24.94 (1.0) @item p6-3 @tab 8.0e+04 @tab -13.43 (2.9) @tab -22.86 (1.0) @item p6-4 @tab 8.0e+04 @tab -1.32 (2.9) @tab -20.97 (1.0) @item p6-5 @tab 8.0e+04 @tab +8.77 (2.9) @tab -16.47 (1.0) @item p6-6 @tab 8.0e+04 @tab +18.02 (2.9) @tab -11.89 (1.1) @item p6-7 @tab 8.0e+04 @tab -25.77 (2.0) @tab -21.03 (1.0) @item p6-8 @tab 8.0e+04 @tab -42.37 (2.0) @tab -26.97 (1.0) @item p6-9 @tab 8.0e+04 @tab -61.32 (1.9) @tab -33.82 (1.0) @item p6-T @tab 8.0e+04 @tab -73.60 (1.7) @tab -42.98 (0.9) @item p6-A @tab 8.0e+04 @tab -81.35 (1.5) @tab -57.46 (0.8) @item p5-2 @tab 8.0e+04 @tab -29.29 (2.3) @tab +35.74 (2.0) @item p5-3 @tab 8.0e+04 @tab -21.10 (2.5) @tab +40.83 (2.0) @item p5-4 @tab 8.0e+04 @tab -14.02 (2.8) @tab +46.13 (2.0) @item p5-5 @tab 8.0e+04 @tab -2.07 (2.8) @tab +51.38 (2.0) @item p5-6 @tab 8.0e+04 @tab +7.69 (2.8) @tab +55.49 (2.0) @item p5-7 @tab 8.0e+04 @tab -29.78 (1.8) @tab +38.74 (2.0) @item p5-8 @tab 8.0e+04 @tab -45.59 (1.8) @tab +29.74 (2.0) @item p5-9 @tab 8.0e+04 @tab -63.38 (1.7) @tab +15.31 (2.0) @item p5-T @tab 8.0e+04 @tab -75.56 (1.7) @tab -5.45 (1.0) @item p5-A @tab 8.0e+04 @tab -83.48 (1.4) @tab -28.71 (1.0) @item p4-2 @tab 8.0e+04 @tab -18.34 (2.4) @tab -2.08 (1.0) @item p4-3 @tab 8.0e+04 @tab -10.15 (2.7) @tab -0.10 (1.0) @item p4-4 @tab 8.0e+04 @tab -1.53 (2.9) @tab +4.20 (1.0) @item p4-5 @tab 1.3e+06 @tab +8.32 (0.7) @tab +6.94 (0.3) @item p4-6 @tab 8.0e+04 @tab +18.54 (2.9) @tab +9.10 (1.0) @item p4-7 @tab 8.0e+04 @tab -17.13 (2.0) @tab +8.29 (1.0) @item p4-8 @tab 8.0e+04 @tab -32.41 (2.0) @tab -5.80 (1.0) @item p4-9 @tab 8.0e+04 @tab -52.03 (2.0) @tab -21.40 (1.0) @item p4-T @tab 8.0e+04 @tab -65.35 (1.7) @tab -30.80 (1.0) @item p4-A @tab 8.0e+04 @tab -75.64 (1.5) @tab -48.85 (0.9) @item p3-2 @tab 2.0e+07 @tab -13.55 (0) @tab -13.84 (0) @item p3-3 @tab 3.2e+05 @tab -4.62 (1.3) @tab -10.55 (0.5) @item p3-4 @tab 8.0e+04 @tab +4.29 (2.7) @tab -7.50 (1.0) @item p3-5 @tab 8.0e+04 @tab +12.98 (2.9) @tab -2.79 (1.0) @item p3-6 @tab 8.0e+04 @tab +22.13 (2.9) @tab +0.27 (1.0) @item p3-7 @tab 8.0e+04 @tab -5.64 (2.0) @tab -14.75 (1.0) @item p3-8 @tab 3.2e+05 @tab -23.16 (1.0) @tab -21.60 (0.5) @item p3-9 @tab 8.0e+04 @tab -43.38 (2.0) @tab -29.61 (1.0) @item p3-T @tab 8.0e+04 @tab -59.02 (1.7) @tab -38.86 (0.9) @item p3-A @tab 8.0e+04 @tab -70.21 (1.5) @tab -54.10 (0.9) @item p2-2 @tab 8.0e+04 @tab -7.83 (2.3) @tab -11.55 (1.0) @item p2-3 @tab 8.0e+04 @tab -1.63 (2.5) @tab -8.20 (1.0) @item p2-4 @tab 8.0e+04 @tab +5.17 (2.7) @tab -4.49 (1.0) @item p2-5 @tab 8.0e+04 @tab +16.51 (2.7) @tab -1.33 (1.0) @item p2-6 @tab 8.0e+04 @tab +25.65 (2.9) @tab +2.57 (1.0) @item p2-7 @tab 8.0e+04 @tab +0.70 (2.0) @tab -8.63 (1.0) @item p2-8 @tab 1.3e+06 @tab -17.84 (0.5) @tab -15.96 (0.2) @item p2-9 @tab 8.0e+04 @tab -40.15 (2.0) @tab -23.95 (1.0) @item p2-T @tab 8.0e+04 @tab -53.36 (1.8) @tab -34.25 (0.9) @item p2-A @tab 8.0e+04 @tab -67.42 (1.5) @tab -51.15 (0.9) @end multitable @node Detailed explanation @subsection Detailed explanation @anchor{#detailed-explanation} We want to derive the basic strategy from scratch, i.e.@ without making any assumption. What we are going to do is to play a large (more on what @emph{large} means below) number of hands by fixing our first two cards and the dealer upcard and sequentially standing, doubling or hitting the first card. Then we will compare the results for the three cases and select as the proper strategy the best one of the three possible choices. Standing and doubling are easy plays, because after we stand or double down then the dealer plays accordingly to the rules: she hits until seventeen, possibly hitting soft seventeen. But if we hit on our hand, we might need to make another decision whether to stand or hit again. As we do not want to assume anything, we have to play in such an order that if we do need to make another decision, we already know which is the best one. @menu * Hard hands:: * Soft hands:: * Pairs:: * Number of hands:: @end menu @node Hard hands @subsubsection Hard hands @anchor{#hard-hands} So we start by arranging the shoe so that the user gets hard twenty (i.e.@ two faces) and the dealer gets successively upcards of two to ace. So we play each combination of dealer upcard (ten) three times each playing either @enumerate @item always standing @item always doubling @item always hitting @end enumerate In general the first two plays are easy, because the game stops either after standing or after receiving only one card. The last one might lead to further hitting, but since we are starting with a hard twenty, that would either give the player twenty one or a bust. In any case, the game also ends. So we play a certain number of hands (say one thousand hands) each of these three plays for each of the ten upcard faces and record the outcome. The correct play for hard twenty against each of the ten upcards is the play that gave the better result, which is of course standing. Next, we do the same for a hard nineteen. In this case, the hitting play might not end after one card is drawn (i.e.@ we hit on nineteen and get and ace). But if that was the case, we would already know what the best play is from the previous step so we play accordingly and we stand. Repeating this procedure down to hard four we can build the basic strategy table for any hard total against any dealer upcard. @node Soft hands @subsubsection Soft hands @anchor{#soft-hands} We can now switch to analyze soft hands. Starting from soft twenty (i.e.@ an ace and a nine) we do the same we did for the hard case. The only difference is that when hitting, we might end either in another soft hand which we would already analyzed because we start from twenty and go down, or in a hard hand, which we also already analyzed so we can play accordingly. @node Pairs @subsubsection Pairs @anchor{#pairs} When dealing with pairs, we have to decide whether to split or not. When we do not split, we end up in one of the already-analyzed cases: either a soft twelve of any even hard hand. When we split, we might end in a hard or soft hand (already analyzed) or in a new pair. But since the new pair can be only the same pair we are analyzing, we have to treat it like we treated the first pair: either to split it or not, so we know how to deal with it. @node Number of hands @subsubsection Number of hands @anchor{#number-of-hands} The output is the expected value@ @math{e} of the bankroll, which is a random variable with an associated uncertainty@ @math{\Delta e} (i.e.@ a certain numbers of standard deviations). For example, if we received only blackjacks, the expected value would be 1.5 (provided blackjacks pay@ 3 to@ 2 of course). If we busted all of our hands without doubling or splitting, the expected value would be -1. In order to say that the best strategy is, let's say stand and not hitting or doubling down, we have to make sure that @math{e_h-\Delta e_h > e_s+\Delta e_s} and @math{e_h-\Delta e_h > e_d+\Delta e_d}. If there is no play that can give a better expected value than the other two taking into account the uncertainties, then we have to play more hands in order to reduce the random uncertainty. @node Implementation @subsection Implementation @anchor{#implementation} The steps above can be written in a @uref{https://en.wikipedia.org/wiki/Bash_%28Unix_shell%29,Bash} script that @itemize @item loops over hands and upcards, @item creates a strategy file for each possible play hit, double or stand (or split or not), @item runs @uref{https://www.seamplex.com/blackjack,Libre@ Blackjack}, @item checks the results and picks the best play, @item updates the strategy file @end itemize @verbatim ##!/bin/bash n0=80000 n_max=9000000 RED="\033[0;31m" GREEN="\033[0;32m" BROWN="\033[0;33m" MAGENTA="\e[0;35m" CYAN="\e[0;36m" NC="\033[0m" ## No Color for i in grep awk printf blackjack; do if [ -z "$(which $i)" ]; then echo "error: $i not installed" exit 1 fi done debug=0 declare -A strategy declare -A ev declare -A min min["hard"]=4 ## from 20 to 4 in hards min["soft"]=12 ## from 20 to 12 in softs rm -f table.md hard.html soft.html pair.html ## -------------------------------------------------------------- ## start with standing cp hard-stand.txt hard.txt cp soft-stand.txt soft.txt cat << EOF >> table.md | Hand | \$n\$ | Stand [%] | Double [%] | Hit [%] | Play | |:------:|:-----:|:-----------:|:------------:|:--------:|:---------:| EOF for type in hard soft; do for hand in $(seq 20 -1 ${min[${type}]}); do ## choose two random cards that make up the player's assumed total if [ ${type} = "hard" ]; then t="h" card1=11 card2=11 while test $card1 -gt 10 -o $card2 -gt 10; do card1=$((${RANDOM} % (${hand}-3) + 2)) card2=$((${hand} - ${card1})) done elif [ ${type} = "soft" ]; then t="s" ## one card is an ace card1=1 card2=$((${hand} - 10 - ${card1})) fi cat << EOF >> ${type}.html ${t}${hand}
stand
hit
double
EOF for upcard in $(seq 2 9) T A; do if [ "x$upcard" = "xT" ]; then upcard_n=10 elif [ "x$upcard" = "xA" ]; then upcard_n=1 else upcard_n=$(($upcard)) fi n=${n0} ## start with n0 hands best="x" ## x means don't know what to so, so play while [ "${best}" = "x" ]; do ## tell the user which combination we are trying and how many we will play echo -ne "${t}${hand}-${upcard} ($card1 $card2)\t"$(printf %.1e ${n}) for play in s d h; do ## start with options.conf as a template and add some custom stuff cp options.conf blackjack.conf cat << EOF >> blackjack.conf hands = ${n} player = internal arranged_cards = ${card1}, $((${upcard_n} + 13)), $((${card2} + 26)) report = ${t}${hand}-${upcard}-${play}.yaml ##log = ${t}${hand}-${upcard}-${play}.log EOF ## read the current strategy while read w p2 p3 p4 p5 p6 p7 p8 p9 pT pA; do ## w already has the "h" or the "s" strategy[${w},2]=$p2 strategy[${w},3]=$p3 strategy[${w},4]=$p4 strategy[${w},5]=$p5 strategy[${w},6]=$p6 strategy[${w},7]=$p7 strategy[${w},8]=$p8 strategy[${w},9]=$p9 strategy[${w},T]=$pT strategy[${w},A]=$pA done < ${type}.txt ## override the read strategy with the explicit play: s, d or h strategy[${t}${hand},${upcard}]=${play} ## save the new (temporary) strategy rm -f ${type}.txt for h in $(seq 20 -1 ${min[${type}]}); do echo -n "${t}${h} " >> ${type}.txt ## extra space if h < 10 if [ ${h} -lt 10 ]; then echo -n " " >> ${type}.txt fi for u in $(seq 2 9) T A; do echo -n "${strategy[${t}${h},${u}]} " >> ${type}.txt done echo >> ${type}.txt done ## debug, comment for production if [ "${debug}" != "0" ]; then cp ${type}.txt ${t}${hand}-${upcard}-${play}.str fi ## ensamble the full bs.txt with no pairing cat hard.txt soft.txt pair-no.txt > bs.txt ## play! blackjack ## evaluate the results ev[${t}${hand},${upcard},${play}]=$(grep mean ${t}${hand}-${upcard}-${play}.yaml | awk '{printf("%g", $2)}') error[${t}${hand},${upcard},${play}]=$(grep error ${t}${hand}-${upcard}-${play}.yaml | awk '{printf("%g", $2)}') done ## choose the best one ev_s=$(echo ${ev[${t}${hand},${upcard},s]} | awk '{printf("%+.2f", 100*$1)}') ev_d=$(echo ${ev[${t}${hand},${upcard},d]} | awk '{printf("%+.2f", 100*$1)}') ev_h=$(echo ${ev[${t}${hand},${upcard},h]} | awk '{printf("%+.2f", 100*$1)}') if [ ${n} -le ${n_max} ]; then ## if we still have room, take into account errors error_s=$(echo ${error[${t}${hand},${upcard},s]} | awk '{printf("%.1f", 100*$1)}') error_d=$(echo ${error[${t}${hand},${upcard},d]} | awk '{printf("%.1f", 100*$1)}') error_h=$(echo ${error[${t}${hand},${upcard},h]} | awk '{printf("%.1f", 100*$1)}') else ## instead of running infinite hands, above a threshold asume errors are zero error_s=0 error_d=0 error_h=0 fi echo -ne "\t${ev_s}\t(${error_s})" echo -ne "\t${ev_d}\t(${error_d})" echo -ne "\t${ev_h}\t(${error_h})" if (( $(echo ${ev_s} ${error_s} ${ev_d} ${error_d} | awk '{print (($1-$2) > ($3+$4))}') )) && (( $(echo ${ev_s} ${error_s} ${ev_h} ${error_h} | awk '{print (($1-$2) > ($3+$4))}') )); then best="s" color=${BROWN} best_string="stand" elif (( $(echo ${ev_d} ${error_d} ${ev_s} ${error_s} | awk '{print (($1-$2) > ($3+$4))}') )) && (( $(echo ${ev_d} ${error_d} ${ev_h} ${error_h} | awk '{print (($1-$2) > ($3+$4))}') )); then best="d" color=${CYAN} best_string="double" elif (( $(echo ${ev_h}-${error_h} ${ev_s} ${error_s} | awk '{print (($1-$2) > ($3+$4))}') )) && (( $(echo ${ev_h}-${error_h} ${ev_d} ${error_d} | awk '{print (($1-$2) > ($3+$4))}') )); then best="h" color=${MAGENTA} best_string="hit" else best="x" color=${NC} best_string="uncertain" n=$((${n} * 4)) fi echo -e ${color}"\t"${best_string}${NC} done strategy[${t}${hand},${upcard}]=${best} echo "| ${t}${hand}-${upcard} | $(printf %.1e ${n}) | ${ev_s} (${error_s}) | ${ev_h} (${error_h}) | ${ev_d} (${error_d}) | ${best_string} | " >> table.md echo " " >> ${type}.html echo " " >> ${type}.html echo ${ev_s} ${error_s} | awk -f html_cell.awk >> ${type}.html echo ${ev_h} ${error_h} | awk -f html_cell.awk >> ${type}.html echo ${ev_d} ${error_d} | awk -f html_cell.awk >> ${type}.html echo " " >> ${type}.html ## save the strategy again with the best strategy rm -f ${type}.txt for h in $(seq 20 -1 ${min[${type}]}); do echo -n "${t}${h} " >> ${type}.txt ## extra space if h < 10 if [ ${h} -lt 10 ]; then echo -n " " >> ${type}.txt fi for u in $(seq 2 9) T A; do echo -n "${strategy[${t}${h},${u}]} " >> ${type}.txt done echo >> ${type}.txt done done ## echo "" >> ${type}.html done done cat << EOF >> table.md | Hand | \$n\$ | Yes [%] | No [%] | |:------:|:-------:|:----------:|:----------:| EOF ## -------------------------------------------------------------------- ## pairs type="pair" t="p" cp pair-no.txt pair.txt for hand in A T $(seq 9 -1 2); do if [ "${hand}" = "A" ]; then pair=1 elif [ "${hand}" = "T" ]; then pair=10 else pair=$((${hand})) fi ## cat << EOF >> ${type}.html ## ## ${t}${hand} ## ##
yes
##
no
## ## EOF for upcard in $(seq 2 9) T A; do if [ "$upcard" = "T" ]; then upcard_n=10 elif [ "$upcard" = "A" ]; then upcard_n=1 else upcard_n=$(($upcard)) fi n=${n0} ## start with n0 hands best="x" ## x means don't know what to so, so play while [ "${best}" = "x" ]; do ## tell the user which combination we are trying and how many we will play echo -ne "${t}${hand}-${upcard}\t\t$(printf %.0e ${n})" for play in y n; do ## start with options.conf as a template and add some custom stuff cp options.conf blackjack.conf cat << EOF >> blackjack.conf hands = ${n} player = internal arranged_cards = ${pair}, $((${upcard_n} + 13)), $((${pair} + 26)) report = ${t}${hand}-${upcard}-${play}.yaml ## log = ${t}${hand}-${upcard}-${play}.log EOF ## read the current strategy while read w p2 p3 p4 p5 p6 p7 p8 p9 pT pA; do ## w already has the "p" strategy[${w},2]=$p2 strategy[${w},3]=$p3 strategy[${w},4]=$p4 strategy[${w},5]=$p5 strategy[${w},6]=$p6 strategy[${w},7]=$p7 strategy[${w},8]=$p8 strategy[${w},9]=$p9 strategy[${w},T]=$pT strategy[${w},A]=$pA done < ${type}.txt ## override the read strategy with the explicit play: y or n strategy[${t}${hand},${upcard}]=${play} ## save the new (temporary) strategy rm -f ${type}.txt for h in A T $(seq 9 -1 2); do echo -n "${t}${h} " >> ${type}.txt for u in $(seq 2 9) T A; do echo -n "${strategy[${t}${h},${u}]} " >> ${type}.txt done echo >> ${type}.txt done if [ "${debug}" != "0" ]; then cp ${type}.txt ${t}${hand}-${upcard}-${play}.str fi ## ensamble the full bs.txt cat hard.txt soft.txt pair.txt > bs.txt ## play! blackjack ## evaluate the results ev[${t}${hand},${upcard},${play}]=$(grep mean ${t}${hand}-${upcard}-${play}.yaml | awk '{printf("%g", $2)}') error[${t}${hand},${upcard},${play}]=$(grep error ${t}${hand}-${upcard}-${play}.yaml | awk '{printf("%g", $2)}') done ## choose the best one ev_y=$(echo ${ev[${t}${hand},${upcard},y]} | awk '{printf("%+.2f", 100*$1)}') ev_n=$(echo ${ev[${t}${hand},${upcard},n]} | awk '{printf("%+.2f", 100*$1)}') if [ $n -le ${n_max} ]; then ## if we still have room, take into account errors error_y=$(echo ${error[${t}${hand},${upcard},y]} | awk '{printf("%.1f", 100*$1)}') error_n=$(echo ${error[${t}${hand},${upcard},n]} | awk '{printf("%.1f", 100*$1)}') else ## instead of running infinite hands, above a threshold asume errors are zero error_y=0 error_n=0 fi echo -ne "\t${ev_y}\t(${error_y})" echo -ne "\t${ev_n}\t(${error_n})" if (( $(echo ${ev_y} ${error_y} ${ev_n} ${error_n} | awk '{print (($1-$2) > ($3+$4))}') )); then best="y" color=${GREEN} best_string="yes" elif (( $(echo ${ev_n} ${error_n} ${ev_y} ${error_y} | awk '{print (($1-$2) > ($3+$4))}') )); then best="n" color=${RED} best_string="no" else best="x" color=${NC} best_string="uncertain" n=$((${n} * 4)) fi echo -e ${color}"\t"${best_string}${NC} done echo "| ${t}${hand}-${upcard} | $(printf %.1e ${n}) | ${ev_y} (${error_y}) | ${ev_n} (${error_n}) | ${best_string} | " >> table.md echo " " >> ${type}.html echo " " >> ${type}.html echo ${ev_y} ${error_y} | awk -f html_cell.awk >> ${type}.html echo ${ev_n} ${error_n} | awk -f html_cell.awk >> ${type}.html echo " " >> ${type}.html strategy[${t}${hand},${upcard}]=${best} ## save the strategy again with the best strategy rm -f ${type}.txt for h in A T $(seq 9 -1 2); do echo -n "${t}${h} " >> ${type}.txt for u in $(seq 2 9) T A; do echo -n "${strategy[${t}${h},${u}]} " >> ${type}.txt done echo >> ${type}.txt done done done cat header.txt hard.txt header.txt soft.txt header.txt pair.txt > bs.txt rm -f hard.txt soft.txt pair.txt blackjack.conf if [ "${debug}" == "0" ]; then rm -f *.yaml rm -f *.str rm -f *.log fi @end verbatim @bye