Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

blackjack.texi 66KB

před 5 roky
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878
  1. \input texinfo @c -*-texinfo-*-
  2. @c %**start of header
  3. @documentencoding UTF-8
  4. @setfilename blackjack.info
  5. @set UPDATED December 20, 2020
  6. @set VERSION v0.2.4-gafba392
  7. @copying
  8. This manual is for LibreBlackjack (version @value{VERSION}, @value{UPDATED}),
  9. which is a completely free-as-in-freedom blackjack engine designed to
  10. study and analyze the game statistics using different playing strategies
  11. ranging from simple card counting up to other complex algorithms based
  12. on artificial intelligence..
  13. Copyright @copyright{} 2016-2020 Jeremy Theler.
  14. @quotation
  15. Permission is granted to copy, distribute and/or modify this document
  16. under the terms of the GNU Free Documentation License, Version 1.3 or
  17. any later version published by the Free Software Foundation; with no
  18. Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
  19. Texts. A copy of the license is included in the section entitled
  20. ``GNU Free Documentation License''.
  21. @end quotation
  22. @end copying
  23. @ifnottex
  24. @paragraphindent 0
  25. @end ifnottex
  26. @titlepage
  27. @title Libre@ Blackjack
  28. @subtitle A free blackjack back end, v0.2.4-gafba392
  29. @author Jeremy Theler
  30. December 20, 2020
  31. @page
  32. @vskip 0pt plus 1filll
  33. @insertcopying
  34. @end titlepage
  35. @contents
  36. @node Top
  37. @top Libre@ Blackjack
  38. @menu
  39. * Overview::
  40. * Running blackjack::
  41. * Commands::
  42. * Configuration file::
  43. * Example automated players::
  44. @end menu
  45. @node Overview
  46. @chapter Overview
  47. @anchor{#overview}
  48. @quotation
  49. A @uref{https://www.gnu.org/philosophy/free-sw.html,free}
  50. @uref{https://en.wikipedia.org/wiki/Blackjack,Blackjack} back end
  51. inspired by @uref{https://www.gnu.org/software/chess/,GNU Chess}.
  52. @end quotation
  53. @uref{https://www.seamplex.com/blackjack,Libre@ Blackjack} is a
  54. blackjack engine that emulates a dealer, deals (digital) cards and
  55. understands plain-text commands such as @code{hit} or @code{stand}. The
  56. basic idea is that one or more players can talk to Libre@ Blackjack
  57. either in an interactive or in an automated way through
  58. @itemize
  59. @item
  60. the standard input and/or output (optionally using named pipes or TCP
  61. (web)sockets with @code{netcat} or @code{gwsocket}), or
  62. @item
  63. C++ methods (optionally loaded at runtime from shared objects TBD).
  64. @end itemize
  65. These players can be actual human players playing in real-time through a
  66. front end (a GUI application, a web-based interface, a mobile app, etc.)
  67. or robots that implement a certain betting and playing strategy playing
  68. (i.e.@ card counting) as fast as possible to study and analyze game
  69. statistics. There is an internal player that reads the strategy from a
  70. text file and plays accordingly. It can also be used to play interactive
  71. [ASCII blackjack].
  72. @menu
  73. * Why::
  74. * How::
  75. * A note on the C++ implementation::
  76. @end menu
  77. @node Why
  78. @section Why
  79. @anchor{#why}
  80. @quotation
  81. ``I am often surprised that when people drive down two-lane roads, they
  82. will trust complete strangers in the oncoming lane not to swerve into
  83. their lane causing a head-on collision; but they will not trust
  84. mathematicians to create the correct strategy for Blackjack.''
  85. Norman Wattenberger, Modern Blackjack, 2009
  86. @end quotation
  87. With Libre@ Blackjack you do not have to trust other people anymore. You
  88. have a free blackjack engine which you can
  89. @enumerate 0
  90. @item
  91. run as you wish, to see the results of billions of blackjack hands,
  92. @item
  93. study to see how it works and change it if you do not like it,
  94. @item
  95. share it with your friends and colleagues, and
  96. @item
  97. distribute copies of your modified versions.
  98. @end enumerate
  99. If you do not know how to program, you have the @emph{freedom} to hire a
  100. programmer to do it for you. That is why
  101. @uref{https://www.seamplex.com/blackjack,Libre@ Blackjack} is
  102. @uref{https://www.gnu.org/philosophy/free-sw.html,free software}.
  103. @node How
  104. @section How
  105. @anchor{#how}
  106. Once you trust the blackjack engine is fair, you can model and simulate
  107. any blackjack situation you want, playing millions of times a certain
  108. hand (say a sixteen against a ten) in different ways (say hitting or
  109. standing) to obtain you own conclusions. You can even build the
  110. @uref{https://wizardofodds.com/games/blackjack/strategy/4-decks/,basic
  111. strategy charts} from scratch to convince yourself there is no
  112. @uref{https://wizardofodds.com/ask-the-wizard/blackjack/,flaw}.
  113. The main objective is research and optimization of playing and betting
  114. strategies depending on
  115. @itemize
  116. @item
  117. particular table rules (number of decks, hit on soft 17, double after
  118. split, etc.),
  119. @item
  120. card counting strategies
  121. @item
  122. risk of ruin
  123. @item
  124. removal of cards
  125. @item
  126. arranged shoes
  127. @end itemize
  128. These automatic players can range from simple no-bust or
  129. mimic-the-dealer hitters or standers, up to neural-networks trained
  130. players taking into account every card being dealt passing through basic
  131. strategy modified by traditional card counting mechanisms.
  132. @node A note on the C++ implementation
  133. @section A note on the C++ implementation
  134. @anchor{#a-note-on-the-c-implementation}
  135. The first Libre@ Blackjack version (v0.1) was written in C. This version
  136. (v0.2) is a re-implementation of nearly the same functionality but
  137. written completely from scratch in C++. I am not a fan of C++ and still
  138. prefer old plain C for most of my programming projects, but for the
  139. particular case of Libre@ Blackjack these advantages of C++ over C ought
  140. to be noted:
  141. @itemize
  142. @item
  143. the inheritance mechanisms of C++ and virtual methods allows to have
  144. generic dealer and player classes from which particular games (dealers)
  145. and strategies (players) can be instantiated. This way, Blackjack
  146. variations like
  147. @itemize
  148. @item
  149. @uref{https://wizardofodds.com/games/spanish-21/,Spanish 21}
  150. @item
  151. @uref{https://wizardofodds.com/games/down-under-blackjack/,Down under
  152. Blackjack}
  153. @item
  154. @uref{https://wizardofodds.com/games/free-bet-blackjack/,Free Bet
  155. Blackjack}
  156. @item
  157. @uref{https://wizardofodds.com/games/blackjack/switch/,Blackjack Switch}
  158. @end itemize
  159. or even the Spanish ``Siete y medio'' could be also implemented in the
  160. same framework (the card deck should also be changed though). But also
  161. playing variations like a dealer that exposes the hole card a certain
  162. amount of the time (say 1% or 2% of the hands) could also be studied by
  163. extending the base blackjack dealer class.
  164. @item
  165. the private members of the C++ classes allow information to be hidden
  166. between the dealer and the player, so a far better separation of
  167. information can be achieved. This also prevents ``cheating'' in players
  168. by looking at information which is not available for them (such as the
  169. dealer's hole card or the content of the shoe).
  170. @item
  171. the virtual members of derived players and even be linked to other
  172. high-level programming language parsers (such as Python or Julia)
  173. allowing to use the vast variety of AI/ML libraries available for these
  174. languages to implement advanced playing strategies.
  175. @item
  176. the usage of STL containers, methods and algorithms allows for a faster
  177. and cleaner implementation of cards, hands, decks and shoes.
  178. @end itemize
  179. @node Running blackjack
  180. @chapter Running @code{blackjack}
  181. @anchor{#running-blackjack}
  182. @menu
  183. * Invocation::
  184. * Interactive game::
  185. @end menu
  186. @node Invocation
  187. @section Invocation
  188. @anchor{#invocation}
  189. The format for running the @code{blackjack} program is:
  190. @verbatim
  191. blackjack [options] [path_to_conf_file]
  192. @end verbatim
  193. If no configuration file is given, a file named @code{blackjack.conf} in
  194. the current directory is used, provided it exists. With no options and
  195. no configuration file, @code{blackjack} starts in interactive mode and
  196. it is ready to start a blackjack game.
  197. The @code{blackjack} executable supports the following options:
  198. All the options which can be given in the configuration file can be
  199. passed as a command-line argument. For example, running
  200. @verbatim
  201. blackjack --decks=4 --no_insurance=true
  202. @end verbatim
  203. is equivalent to using a configuration file with
  204. @verbatim
  205. decks = 4
  206. no_insurance = true
  207. @end verbatim
  208. @node Interactive game
  209. @section Interactive game
  210. @anchor{#interactive-game}
  211. If @code{blackjack} is attached to an interactive TTY (i.e.@ neither the
  212. standard input nor outputs are redirected), an interactive game is
  213. triggered. First thing the program will do is to ask for a bet:
  214. @verbatim
  215. LibreBlackjack v0.2+Δ
  216. a free & open blackjack engine
  217. Starting new hand #1 with bankroll 0
  218. <-- Bet?
  219. >
  220. @end verbatim
  221. So the user should enter a number, say ``1'' and then press Enter and
  222. then a game will be dealt:
  223. @verbatim
  224. Player's card is Q♥
  225. Dealer's up card is 10♠
  226. Player's card is Q♣
  227. Dealer's hole card is dealt
  228. No blackjacks
  229. -- Dealer's hand: --------
  230. _____ _____
  231. |10 | |#####|
  232. | | |#####|
  233. | ♠ | |#####|
  234. | | |#####|
  235. |___10| |#####|
  236. Value: 10
  237. -- Player's hand --------
  238. _____ _____
  239. |Q | |Q |
  240. | | | |
  241. | ♥ | | ♣ |
  242. | | | |
  243. |____Q| |____Q|
  244. Value: 20
  245. <-- Play? 20 10
  246. >
  247. @end verbatim
  248. A flat-betting game can be played by passing @code{--flat_bet=true}
  249. through the command line.
  250. @node Commands
  251. @chapter Commands
  252. @anchor{#commands}
  253. The dealer (he) and the player (she) ``talk'' through commands, which
  254. are ASCII strings sent through any of the different IPC mechanisms
  255. discussed in [Automated playing through IPC]. In the most basic case, a
  256. human player reads commands from the dealer from @code{blackjack}'s
  257. standard output and writes her commands into the dealer's standard
  258. input. Those commands from the dealer that require a particular action
  259. from the player end with a quotation sign such as @code{bet?},
  260. @code{insurance?} or @code{play?}.
  261. All numerical values such as hand totals or bankrolls are given as
  262. decimal ASCII strings.
  263. @menu
  264. * From the dealer to the player::
  265. * From the player to the dealer::
  266. @end menu
  267. @node From the dealer to the player
  268. @section From the dealer to the player
  269. @anchor{#from-the-dealer-to-the-player}
  270. @node From the player to the dealer
  271. @section From the player to the dealer
  272. @anchor{#from-the-player-to-the-dealer}
  273. The following commands are available for the player for playing her
  274. hand.
  275. The following are general commands in the sense that they can be sent
  276. from the player to the dealer at any moment of the game.
  277. @node Configuration file
  278. @chapter Configuration file
  279. @anchor{#configuration-file}
  280. Libre@ Blackjacks reads a configuration file that contains
  281. @itemize
  282. @item
  283. settings about the rules of the game
  284. @itemize
  285. @item
  286. number of decks,
  287. @item
  288. whether if the dealer has to hit soft seventeen or not,
  289. @item
  290. blackjack payout,
  291. @item
  292. maximum bet allowed,
  293. @item
  294. etc@dots{}
  295. @end itemize
  296. @item
  297. how the player is supposed to play
  298. @itemize
  299. @item
  300. number of hands
  301. @item
  302. whether a flat or variable bet is going to be used,
  303. @item
  304. etc@dots{}
  305. @end itemize
  306. @item
  307. if there are any particular shoe arrangement, i.e.@ a predefined set of
  308. cards dealt in a certain order for instance to play one million hands of
  309. a sixteen against a dealer's ten
  310. @item
  311. what kind of information is shown in the interactive session
  312. @itemize
  313. @item
  314. if ASCII-art cards are supposed to be shown,
  315. @item
  316. a real-time delay to make the game smoother,
  317. @item
  318. etc.
  319. @end itemize
  320. @item
  321. how the automated player communicates with the dealer
  322. @itemize
  323. @item
  324. using standard input/output,
  325. @item
  326. FIFO named pipes,
  327. @item
  328. POSIX message queues,
  329. @item
  330. POSIX shared memory,
  331. @item
  332. etc@dots{}
  333. @end itemize
  334. @end itemize
  335. The location of the configuration file can be given in the command line.
  336. If none is provided, a file named @code{blackjack.conf} in the current
  337. directory is used. If such file does not exists, the defaults values of
  338. each variable are used. Individual variables can be set from the command
  339. line by passing one or more times the option
  340. @code{--}configuration_variable@code{[=}@emph{value}@code{]} in the
  341. @ref{#invocation,invocation}.
  342. Comments can be inserted using either a hash @code{#} or a colon
  343. @code{;}. The following configuration file is the default provided in
  344. the main distribution tarball:
  345. @verbatim
  346. # uncomment the following line to arrange cards
  347. # arranged_cards = 1 5 14 9 27
  348. flat_bet = 1 # do not ask for bets
  349. no_insurance = 1 # do not ask for insurance
  350. decks = 1 # number of decks, negative means infinite
  351. @end verbatim
  352. @menu
  353. * Variables and values::
  354. * Dumb internal player::
  355. @end menu
  356. @node Variables and values
  357. @section Variables and values
  358. @anchor{#variables-and-values}
  359. @node Dumb internal player
  360. @section Dumb internal player
  361. @anchor{#dumb-internal-player}
  362. @node Example automated players
  363. @chapter Example automated players
  364. @anchor{#example-automated-players}
  365. The directory @code{players} contains a few examples of automated
  366. player, which are discussed in the following sections. A script
  367. @code{check.sh} runs some of them and compares the expected value of the
  368. bankroll relative to the number of hands which each player obtains with
  369. the theoretical expected value (according to the game rules and player's
  370. strategy) within an allowed statistical uncertainty. This scripts writes
  371. the following table (actual values might vary depending on the random
  372. nature of the game):
  373. @multitable {Mimic the dealer} {Expected} {-0.0064075} {0.00927449} {Status}
  374. @headitem
  375. Case
  376. @tab Expected
  377. @tab Result
  378. @tab Error
  379. @tab Status
  380. @item
  381. Internal player
  382. @tab -0.004
  383. @tab -0.0064075
  384. @tab 0.00348953
  385. @tab ok
  386. @item
  387. Always stand
  388. @tab -0.150
  389. @tab -0.15539
  390. @tab 0.00940931
  391. @tab ok
  392. @item
  393. No-bust strategy
  394. @tab -0.075
  395. @tab -0.082075
  396. @tab 0.00942851
  397. @tab ok
  398. @item
  399. Mimic the dealer
  400. @tab -0.055
  401. @tab -0.0571
  402. @tab 0.00927449
  403. @tab ok
  404. @end multitable
  405. The columns are
  406. @enumerate
  407. @item
  408. Case name, as discussed below.
  409. @item
  410. Expected theoretical result in absolute units (i.e.@ -0.004 means -0.4%)
  411. @item
  412. Actual result obtained by Libre@ Blackjack in absolute units
  413. @item
  414. Estimated error equal to the standard deviation of the result
  415. @item
  416. Number of played hands per second
  417. @item
  418. Whether the result coincides or not with the theoretical value
  419. @end enumerate
  420. @menu
  421. * Internal player::
  422. * Always stand::
  423. * No-bust strategy::
  424. * Mimic the dealer::
  425. * Derivation of the basic strategy::
  426. @end menu
  427. @node Internal player
  428. @section Internal player
  429. @anchor{#internal-player}
  430. If @code{blackjack} is called with the @code{-i} option, it uses an
  431. @emph{internal} player to play against itself. By default it plays basic
  432. strategy. Run
  433. @verbatim
  434. blackjack -i
  435. @end verbatim
  436. and you will get the following report with the results of playing one
  437. million hands with basic strategy.
  438. @verbatim
  439. ---
  440. result: "(-0.7 ± 0.3) %"
  441. mean: -0.006799
  442. error: 0.00348707
  443. hands: 1e+06
  444. bankroll: -6799
  445. bustsPlayer: 0.139358
  446. bustsDealer: 0.239722
  447. wins: 0.448034
  448. pushes: 0.085913
  449. losses: 0.495532
  450. ...
  451. @end verbatim
  452. @node Always stand
  453. @section Always stand
  454. @anchor{#always-stand}
  455. To play Blackjack as an ``always-stander'' run the following command:
  456. @verbatim
  457. yes stand | blackjack -n1e5 --flat_bet=true --no_insurance=true > /dev/null
  458. @end verbatim
  459. The UNIX command @code{yes stand} writes the string ``stand'' repeteadly
  460. to the standard output, which is piped to the executable
  461. @code{blackjack} (assumed to be installed system-wide). The arguments
  462. tell Libre@ Blackjack to play one hundred thousand hands (@code{-n1e5})
  463. using a flat bet (@code{flat_bet}, it defaults to a unit bet in each
  464. hand) and without asking for insurance if the dealer shows an ace
  465. (@code{no_insurance}). As there is no @code{blackjack.conf} file, the
  466. rules are---as expected---the default ones (see the documentation for
  467. details).
  468. The @code{/dev/null} part is important, otherwise Libre@ Blackjack will
  469. think that there is a human at the other side of the table and will
  470. @enumerate
  471. @item
  472. run slower (it will add explicit time delays to mimic an actual human
  473. dealer), and
  474. @item
  475. give all the details of the dealt hands in the terminal as ASCII
  476. (actually UTF-8) art
  477. @end enumerate
  478. This example is only one-way (i.e.@ the player ignores what the dealer
  479. says) so it is better to redirect the standard output to
  480. @code{/dev/null} to save execution time. The results are written as a
  481. @uref{http://yaml.org/,YAML}-formatted data to @code{stderr} by default
  482. once the hands are over, so they will show up in the terminal
  483. nevertheless. This format is human-friendly (far more than JSON) so it
  484. can be easily parsed, but it also allows complex objects to be
  485. represented (arrays, lists, etc.).
  486. @verbatim
  487. ---
  488. result: "(-15.8 ± 0.9) %"
  489. mean: -0.157675
  490. error: 0.00940803
  491. hands: 100000
  492. bankroll: -15767.5
  493. bustsPlayer: 0
  494. bustsDealer: 0.27344
  495. wins: 0.38585
  496. pushes: 0.04807
  497. losses: 0.56608
  498. ...
  499. @end verbatim
  500. @quotation
  501. @strong{Exercise:} verify that the analytical probability of getting a
  502. natural playing with a single deck (for both the dealer and the player)
  503. is 32/663 = 0.04826546@dots{}
  504. @end quotation
  505. @node No-bust strategy
  506. @section No-bust strategy
  507. @anchor{#no-bust-strategy}
  508. This directory shows how to play a ``no-bust'' strategy, i.e.@ not
  509. hitting any hand higher or equal to hard twelve with Libre@ Blackjack.
  510. The communication between the player and the back end is through
  511. standard input and output. The player reads from its standard input
  512. Libre@ Blackjack's commands and writes to its standard output the
  513. playing commands. In order to do this a FIFO (a.k.a. named pipe) is
  514. needed. So first, we create it (if it is not already created):
  515. @verbatim
  516. mkfifo fifo
  517. @end verbatim
  518. Then we execute @code{blackjack}, piping its output to the player (say
  519. @code{no-bust.pl}) and reading the standard input from @code{fifo},
  520. whilst at the same time we redirect the player's standard output to
  521. @code{fifo}:
  522. @verbatim
  523. rm -f fifo; mkfifo fifo
  524. blackjack -n1e5 < fifo | ./no-bust.pl > fifo
  525. @end verbatim
  526. As this time the player is coded in an interpreted langauge, it is far
  527. smarter than the previous @code{yes}-based player. So the player can
  528. handle bets and insurances, and there is not need to pass the options
  529. @code{--flat_bet} nor @code{--no_insurance} (though they can be passed
  530. anyway). Let us take a look at the Perl implementation:
  531. @verbatim
  532. #!/usr/bin/perl
  533. # this is needed to avoid deadlock with the fifo
  534. STDOUT->autoflush(1);
  535. while ($command ne "bye") {
  536. # do not play more than a number of commands
  537. # if the argument -n was not passed to blackjack
  538. if ($i++ == 1234567) {
  539. print "quit\n";
  540. }
  541. # read and process the commands
  542. chomp($command = <STDIN>);
  543. if ($command eq "bet?") {
  544. print "1\n";
  545. } elsif ($command eq "insurance?") {
  546. print "no\n";
  547. } elsif ($comm eq "play?") {
  548. @tokens = split(/ /, $command);
  549. if ($tokens[1] < 12) {
  550. print "hit\n";
  551. } else {
  552. print "stand\n";
  553. }
  554. }
  555. }
  556. @end verbatim
  557. The very same player may be implemented as a shell script:
  558. @verbatim
  559. #!/bin/sh
  560. i=0
  561. while read command
  562. do
  563. i=$((i+1))
  564. if test ${i} -ge 12345; then
  565. echo "quit"
  566. elif test "${command}" = 'bye'; then
  567. exit
  568. elif test "${command}" = 'bet?'; then
  569. echo 1
  570. elif test "${command}" = 'insurance?'; then
  571. echo "no"
  572. elif test "$(echo ${command} | cut -c-5)" = 'play?'; then
  573. count=$(echo ${command} | cut -f2 -d" ")
  574. if test ${count} -lt 12; then
  575. echo "hit"
  576. else
  577. echo "stand"
  578. fi
  579. fi
  580. done
  581. @end verbatim
  582. To check these two players give the same results, make them play against
  583. Libre@ Blackjack with the same seed (say one) and send the YAML report
  584. to two different files:
  585. @verbatim
  586. blackjack -n1e5 --rng_seed=1 --report_file_path=perl.yml < fifo | ./no-bust.pl > fifo
  587. blackjack -n1e5 --rng_seed=1 --report_file_path=shell.yml < fifo | ./no-bust.awk > fifo
  588. diff perl.yml shell.yml
  589. @end verbatim
  590. As expected, the reports are the same. They just differ in the speed
  591. because the shell script is orders of magnitude slower than its
  592. Perl-based counterpart.
  593. @quotation
  594. @strong{Exercise:} modify the players so they always insure aces and see
  595. if it improves or degrades the result.
  596. @end quotation
  597. @node Mimic the dealer
  598. @section Mimic the dealer
  599. @anchor{#mimic-the-dealer}
  600. This example implements a ``mimic-the-dealer strategy,'' i.e.@ hits if
  601. the hand totals less than seventeen and stands on eighteen or more. The
  602. player stands on hard seventeen but hits on soft seventeen.
  603. This time, the configuration file @code{blackjack.conf} is used. If a
  604. file with this name exists in the directory where @code{blackjack} is
  605. executed, it is read and parsed. The options should be fairly self
  606. descriptive. See the [configuration file] section of the manual for a
  607. detailed explanation of the variables and values that can be entered. In
  608. particular, we ask to play one hundred thousand hands at a six-deck game
  609. where the dealer hits soft seventeens. If the random seed is set to a
  610. fixed value so each execution will lead to the very same sequence of
  611. cards.
  612. Now, there are two options that tell Libre@ Blackjack how the player is
  613. going to talk to the backend: @code{player2dealer} and
  614. @code{dealer2player}. The first one sets the communication mechanism
  615. from the player to the dealer (by default is @code{blackjack}'s standard
  616. input), and the second one sets the mechanism from the dealer to the
  617. player (by default @code{blackjack}'s standard output). In this case,
  618. the configuration file reads:
  619. @verbatim
  620. h17 = true
  621. @end verbatim
  622. This means that two FIFOs (a.k.a. named pipes) are to be used for
  623. communication, @code{player2dealer} from the player to the dealer and
  624. @code{dealer2player} for the dealer to the player. If these FIFOs do not
  625. exist, they are created by @code{blackjack} upon execution.
  626. The player this time is implemented as an awk script, whose input should
  627. be read from @code{dealer2player} and whose output should be written to
  628. @code{player2dealer}. To run the game, execute @code{blackjack} in one
  629. terminal making sure the current directory is where the
  630. @code{blackjack.conf} file exists. It should print a message telling
  631. that it is waiting for someone to be at the other side of the named
  632. pipes:
  633. @verbatim
  634. $ blackjack
  635. [...]
  636. waiting for dealer2player buffered fifo 'dealer2player'...
  637. @end verbatim
  638. In another terminal run the player
  639. @verbatim
  640. $ ./mimic-the-dealer.awk < dealer2player > player2dealer
  641. @end verbatim
  642. Both dealer and player may be run in the same terminal putting the first
  643. one on the background:
  644. @verbatim
  645. rm -f d2p p2d; mkfifo d2p p2d
  646. gawk -f mimic-the-dealer.awk < d2p > p2d &
  647. blackjack -n1e5 > d2p < p2d
  648. @end verbatim
  649. To understand the decisions taken by the player, we have to remember
  650. that when Libre@ Blackjack receives the command @code{count} asking for
  651. the current player's count, it returns a positive number for hard hands
  652. and a negative number for soft hands. The instructions @code{fflush()}
  653. are needed in order to avoid deadlocks on the named pipes:
  654. @verbatim
  655. #!/usr/bin/gawk -f
  656. function abs(x){return ( x >= 0 ) ? x : -x }
  657. /bet\?/ {
  658. print "1";
  659. fflush();
  660. }
  661. /insurance\?/ {
  662. print "no";
  663. fflush();
  664. }
  665. /play\?/ {
  666. # mimic the dealer: hit until 17 (hit soft 17)
  667. if (abs($2) < 17 || $2 == -17) { # soft hands are negative
  668. print "hit";
  669. } else {
  670. print "stand";
  671. }
  672. fflush();
  673. }
  674. /bye/ {
  675. exit;
  676. }
  677. @end verbatim
  678. @verbatim
  679. ---
  680. result: "(-5.7 ± 0.9) %"
  681. mean: -0.05716
  682. error: 0.00926292
  683. hands: 100000
  684. bankroll: -5716
  685. bustsPlayer: 0.27064
  686. bustsDealer: 0.18905
  687. wins: 0.41088
  688. pushes: 0.09888
  689. losses: 0.49024
  690. ...
  691. @end verbatim
  692. @quotation
  693. @strong{Exercise:} modify the player and the configuration file so both
  694. the dealer and the player may stand on soft seventeen. Analyze the four
  695. combinations (player h17 - dealer h17, player h17 - dealer s17, player
  696. s17 - dealer h17, player s17 - dealer s17)
  697. @end quotation
  698. @node Derivation of the basic strategy
  699. @section Derivation of the basic strategy
  700. @anchor{#derivation-of-the-basic-strategy}
  701. @menu
  702. * Quick run::
  703. * Full table with results::
  704. * Detailed explanation::
  705. * Implementation::
  706. @end menu
  707. @node Quick run
  708. @subsection Quick run
  709. @anchor{#quick-run}
  710. Execute the @code{run.sh} script. It should take a few minutes:
  711. @verbatim
  712. $ ./run.sh
  713. h20-2 (10 10) 8.0e+04 +63.23 (1.1) -171.17 (1.1) -85.32 (0.5) stand
  714. h20-3 (10 10) 8.0e+04 +64.54 (1.1) -171.50 (1.1) -85.50 (0.5) stand
  715. h20-4 (10 10) 8.0e+04 +65.55 (1.1) -170.33 (1.1) -85.50 (0.5) stand
  716. h20-5 (10 10) 8.0e+04 +66.65 (1.1) -171.25 (1.1) -85.51 (0.5) stand
  717. h20-6 (10 10) 8.0e+04 +67.80 (1.1) -171.07 (1.1) -85.59 (0.5) stand
  718. h20-7 (10 10) 8.0e+04 +77.44 (1.1) -170.53 (1.1) -85.44 (0.5) stand
  719. h20-8 (10 10) 8.0e+04 +79.11 (1.1) -170.08 (1.1) -85.02 (0.6) stand
  720. h20-9 (10 10) 8.0e+04 +75.77 (1.1) -170.31 (1.1) -84.87 (0.6) stand
  721. [...]
  722. p2-6 8e+04 +24.78 (2.9) +3.07 (1.0) yes
  723. p2-7 8e+04 +1.48 (2.0) -8.90 (1.0) yes
  724. p2-8 8e+04 -17.57 (2.0) -16.33 (1.0) uncertain
  725. p2-8 3e+05 -17.88 (1.0) -16.10 (0.5) no
  726. p2-9 8e+04 -38.73 (2.0) -24.38 (1.0) no
  727. p2-T 8e+04 -54.45 (1.8) -34.92 (0.9) no
  728. p2-A 8e+04 -67.11 (1.5) -51.59 (0.9) no
  729. @end verbatim
  730. A new text file called @code{bs.txt} with the strategy should be created
  731. from scratch:
  732. @verbatim
  733. # 2 3 4 5 6 7 8 9 T A
  734. h20 s s s s s s s s s s
  735. h19 s s s s s s s s s s
  736. h18 s s s s s s s s s s
  737. h17 s s s s s s s s s s
  738. h16 s s s s s h h h h h
  739. h15 s s s s s h h h h h
  740. h14 s s s s s h h h h h
  741. h13 s s s s s h h h h h
  742. h12 h h s s s h h h h h
  743. h11 d d d d d d d d d d
  744. h10 d d d d d d d d h h
  745. h9 h d d d d h h h h h
  746. h8 h h h h h h h h h h
  747. h7 h h h h h h h h h h
  748. h6 h h h h h h h h h h
  749. h5 h h h h h h h h h h
  750. h4 h h h h h h h h h h
  751. # 2 3 4 5 6 7 8 9 T A
  752. s20 s s s s s s s s s s
  753. s19 s s s s d s s s s s
  754. s18 d d d d d s s h h h
  755. s17 h d d d d h h h h h
  756. s16 h h d d d h h h h h
  757. s15 h h d d d h h h h h
  758. s14 h h h d d h h h h h
  759. s13 h h h h d h h h h h
  760. s12 h h h h d h h h h h
  761. # 2 3 4 5 6 7 8 9 T A
  762. pA y y y y y y y y y y
  763. pT n n n n n n n n n n
  764. p9 y y y y y n y y n n
  765. p8 y y y y y y y y y y
  766. p7 y y y y y y n n n n
  767. p6 y y y y y n n n n n
  768. p5 n n n n n n n n n n
  769. p4 n n n y y n n n n n
  770. p3 y y y y y y n n n n
  771. p2 y y y y y y n n n n
  772. @end verbatim
  773. @node Full table with results
  774. @subsection Full table with results
  775. @anchor{#full-table-with-results}
  776. The script computes the expected value of each combination
  777. @enumerate
  778. @item
  779. Player's hand (hard, soft and pair)
  780. @item
  781. Dealer upcard
  782. @item
  783. Hit, double or stand (for hard and soft hands) and splitting or not (for
  784. pairs)
  785. @end enumerate
  786. The results are given as the expected value in percentage with the
  787. uncertainty (one standard deviation) in the last significant digit.
  788. @ Hand | @math{n} | Stand [%] | Double [%] | Hit [%] | Play |@*
  789. h20-2 | 8.0e+04 | +63.23 (1.1) | -85.32 (0.5) | -171.17 (1.1) | stand
  790. |@*
  791. h20-3 | 8.0e+04 | +64.54 (1.1) | -85.50 (0.5) | -171.50 (1.1) | stand
  792. |@*
  793. h20-4 | 8.0e+04 | +65.55 (1.1) | -85.50 (0.5) | -170.33 (1.1) | stand
  794. |@*
  795. h20-5 | 8.0e+04 | +66.65 (1.1) | -85.51 (0.5) | -171.25 (1.1) | stand
  796. |@*
  797. h20-6 | 8.0e+04 | +67.80 (1.1) | -85.59 (0.5) | -171.07 (1.1) | stand
  798. |@*
  799. h20-7 | 8.0e+04 | +77.44 (1.1) | -85.44 (0.5) | -170.53 (1.1) | stand
  800. |@*
  801. h20-8 | 8.0e+04 | +79.11 (1.1) | -85.02 (0.6) | -170.08 (1.1) | stand
  802. |@*
  803. h20-9 | 8.0e+04 | +75.77 (1.1) | -84.87 (0.6) | -170.31 (1.1) | stand
  804. |@*
  805. h20-T | 8.0e+04 | +43.47 (1.1) | -85.86 (0.5) | -164.14 (1.1) | stand
  806. |@*
  807. h20-A | 8.0e+04 | +10.32 (1.0) | -89.73 (0.5) | -149.01 (1.0) | stand
  808. |@*
  809. h19-2 | 8.0e+04 | +37.61 (1.4) | -73.52 (0.7) | -146.58 (1.4) | stand
  810. |@*
  811. h19-3 | 8.0e+04 | +39.34 (1.4) | -72.58 (0.7) | -145.41 (1.4) | stand
  812. |@*
  813. h19-4 | 8.0e+04 | +41.60 (1.4) | -72.88 (0.7) | -145.28 (1.4) | stand
  814. |@*
  815. h19-5 | 8.0e+04 | +43.51 (1.4) | -72.98 (0.7) | -145.12 (1.4) | stand
  816. |@*
  817. h19-6 | 8.0e+04 | +45.41 (1.4) | -72.56 (0.7) | -144.94 (1.4) | stand
  818. |@*
  819. h19-7 | 8.0e+04 | +61.77 (1.5) | -71.07 (0.7) | -142.94 (1.5) | stand
  820. |@*
  821. h19-8 | 8.0e+04 | +59.05 (1.5) | -71.22 (0.7) | -143.04 (1.5) | stand
  822. |@*
  823. h19-9 | 8.0e+04 | +28.52 (1.5) | -71.93 (0.7) | -143.09 (1.5) | stand
  824. |@*
  825. h19-T | 8.0e+04 | -1.96 (1.4) | -75.09 (0.7) | -142.54 (1.4) | stand |@*
  826. h19-A | 8.0e+04 | -17.95 (1.2) | -80.99 (0.6) | -131.78 (1.2) | stand
  827. |@*
  828. h18-2 | 8.0e+04 | +10.97 (1.6) | -61.93 (0.8) | -124.23 (1.6) | stand
  829. |@*
  830. h18-3 | 8.0e+04 | +13.15 (1.6) | -62.50 (0.8) | -124.98 (1.6) | stand
  831. |@*
  832. h18-4 | 8.0e+04 | +16.93 (1.6) | -61.94 (0.8) | -123.60 (1.6) | stand
  833. |@*
  834. h18-5 | 8.0e+04 | +19.25 (1.6) | -62.22 (0.8) | -123.74 (1.6) | stand
  835. |@*
  836. h18-6 | 8.0e+04 | +22.23 (1.6) | -61.47 (0.8) | -122.43 (1.6) | stand
  837. |@*
  838. h18-7 | 8.0e+04 | +39.60 (1.7) | -58.93 (0.8) | -118.77 (1.7) | stand
  839. |@*
  840. h18-8 | 8.0e+04 | +11.02 (1.7) | -59.17 (0.8) | -118.63 (1.7) | stand
  841. |@*
  842. h18-9 | 8.0e+04 | -18.50 (1.6) | -61.67 (0.8) | -122.96 (1.6) | stand
  843. |@*
  844. h18-T | 8.0e+04 | -24.23 (1.5) | -67.40 (0.8) | -126.70 (1.5) | stand
  845. |@*
  846. h18-A | 8.0e+04 | -46.34 (1.3) | -74.66 (0.7) | -118.34 (1.3) | stand
  847. |@*
  848. h17-2 | 8.0e+04 | -16.04 (1.7) | -53.84 (0.9) | -107.43 (1.7) | stand
  849. |@*
  850. h17-3 | 8.0e+04 | -11.84 (1.7) | -53.28 (0.9) | -107.23 (1.7) | stand
  851. |@*
  852. h17-4 | 8.0e+04 | -7.85 (1.8) | -52.66 (0.9) | -105.90 (1.8) | stand |@*
  853. h17-5 | 8.0e+04 | -4.57 (1.8) | -52.56 (0.9) | -103.96 (1.8) | stand |@*
  854. h17-6 | 8.0e+04 | -0.04 (1.8) | -51.63 (0.9) | -104.55 (1.8) | stand |@*
  855. h17-7 | 8.0e+04 | -10.94 (1.8) | -48.70 (0.9) | -96.41 (1.8) | stand |@*
  856. h17-8 | 8.0e+04 | -37.84 (1.8) | -50.88 (0.9) | -101.70 (1.8) | stand
  857. |@*
  858. h17-9 | 8.0e+04 | -42.50 (1.7) | -55.60 (0.8) | -109.70 (1.7) | stand
  859. |@*
  860. h17-T | 8.0e+04 | -46.71 (1.6) | -61.73 (0.8) | -116.13 (1.6) | stand
  861. |@*
  862. h17-A | 8.0e+04 | -66.37 (1.4) | -70.97 (0.7) | -111.14 (1.4) | stand
  863. |@*
  864. h16-2 | 8.0e+04 | -28.77 (1.8) | -47.30 (0.9) | -95.43 (1.8) | stand |@*
  865. h16-3 | 8.0e+04 | -24.29 (1.8) | -46.54 (0.9) | -92.83 (1.8) | stand |@*
  866. h16-4 | 8.0e+04 | -20.04 (1.8) | -46.18 (0.9) | -91.87 (1.8) | stand |@*
  867. h16-5 | 8.0e+04 | -16.86 (1.8) | -45.19 (0.9) | -89.29 (1.8) | stand |@*
  868. h16-6 | 8.0e+04 | -11.67 (1.9) | -44.23 (0.9) | -88.78 (1.9) | stand |@*
  869. h16-7 | 8.0e+04 | -47.23 (1.9) | -41.86 (0.9) | -83.70 (1.9) | hit |@*
  870. h16-8 | 8.0e+04 | -51.20 (1.8) | -46.31 (0.9) | -91.59 (1.8) | hit |@*
  871. h16-9 | 8.0e+04 | -54.18 (1.7) | -51.19 (0.9) | -102.23 (1.7) | hit |@*
  872. h16-T | 2.0e+07 | -57.57 (0) | -57.55 (0) | -107.33 (0) | hit |@*
  873. h16-A | 8.0e+04 | -72.19 (1.4) | -68.30 (0.7) | -105.39 (1.4) | hit |@*
  874. h15-2 | 8.0e+04 | -28.22 (1.9) | -41.63 (0.9) | -82.97 (1.9) | stand |@*
  875. h15-3 | 8.0e+04 | -24.40 (1.9) | -41.04 (0.9) | -80.75 (1.9) | stand |@*
  876. h15-4 | 8.0e+04 | -20.61 (1.9) | -39.80 (0.9) | -79.58 (1.9) | stand |@*
  877. h15-5 | 8.0e+04 | -16.64 (1.9) | -38.18 (1.0) | -76.95 (1.9) | stand |@*
  878. h15-6 | 8.0e+04 | -12.54 (1.9) | -37.21 (1.0) | -75.91 (1.9) | stand |@*
  879. h15-7 | 8.0e+04 | -47.73 (1.9) | -37.35 (0.9) | -73.94 (1.9) | hit |@*
  880. h15-8 | 8.0e+04 | -50.75 (1.9) | -41.05 (0.9) | -84.62 (1.9) | hit |@*
  881. h15-9 | 8.0e+04 | -54.44 (1.8) | -47.05 (0.9) | -95.42 (1.8) | hit |@*
  882. h15-T | 8.0e+04 | -57.26 (1.7) | -54.23 (0.9) | -100.92 (1.7) | hit |@*
  883. h15-A | 8.0e+04 | -72.42 (1.4) | -66.47 (0.8) | -101.91 (1.4) | hit |@*
  884. h14-2 | 8.0e+04 | -28.04 (1.9) | -36.34 (1.0) | -71.61 (1.9) | stand |@*
  885. h14-3 | 8.0e+04 | -24.76 (1.9) | -34.74 (1.0) | -70.47 (1.9) | stand |@*
  886. h14-4 | 8.0e+04 | -20.69 (1.9) | -33.14 (1.0) | -68.04 (1.9) | stand |@*
  887. h14-5 | 8.0e+04 | -16.68 (2.0) | -31.75 (1.0) | -64.69 (2.0) | stand |@*
  888. h14-6 | 8.0e+04 | -12.21 (2.0) | -30.33 (1.0) | -60.55 (2.0) | stand |@*
  889. h14-7 | 8.0e+04 | -47.78 (1.9) | -31.73 (1.0) | -66.56 (1.9) | hit |@*
  890. h14-8 | 8.0e+04 | -50.59 (1.9) | -36.85 (0.9) | -75.91 (1.9) | hit |@*
  891. h14-9 | 8.0e+04 | -54.02 (1.8) | -43.78 (0.9) | -87.29 (1.8) | hit |@*
  892. h14-T | 8.0e+04 | -57.53 (1.7) | -50.98 (0.9) | -94.12 (1.7) | hit |@*
  893. h14-A | 8.0e+04 | -71.95 (1.5) | -63.33 (0.8) | -97.81 (1.5) | hit |@*
  894. h13-2 | 3.2e+05 | -28.71 (1.0) | -30.93 (0.5) | -61.09 (1.0) | stand |@*
  895. h13-3 | 8.0e+04 | -24.71 (2.0) | -29.25 (1.0) | -57.88 (2.0) | stand |@*
  896. h13-4 | 8.0e+04 | -20.47 (2.0) | -27.32 (1.0) | -55.06 (2.0) | stand |@*
  897. h13-5 | 8.0e+04 | -16.25 (2.0) | -25.88 (1.0) | -52.01 (2.0) | stand |@*
  898. h13-6 | 8.0e+04 | -11.78 (2.0) | -24.12 (1.0) | -47.83 (2.0) | stand |@*
  899. h13-7 | 8.0e+04 | -47.69 (2.0) | -26.36 (1.0) | -58.47 (2.0) | hit |@*
  900. h13-8 | 8.0e+04 | -51.19 (1.9) | -32.25 (1.0) | -69.55 (1.9) | hit |@*
  901. h13-9 | 8.0e+04 | -54.03 (1.9) | -38.96 (0.9) | -81.88 (1.9) | hit |@*
  902. h13-T | 8.0e+04 | -57.83 (1.8) | -46.80 (0.9) | -88.48 (1.8) | hit |@*
  903. h13-A | 8.0e+04 | -72.42 (1.5) | -60.37 (0.8) | -93.03 (1.5) | hit |@*
  904. h12-2 | 8.0e+04 | -29.07 (2.0) | -25.61 (1.0) | -49.41 (2.0) | hit |@*
  905. h12-3 | 3.2e+05 | -24.62 (1.0) | -23.31 (0.5) | -47.37 (1.0) | hit |@*
  906. h12-4 | 1.3e+06 | -20.56 (0.5) | -21.52 (0.3) | -42.79 (0.5) | stand |@*
  907. h12-5 | 8.0e+04 | -16.46 (2.0) | -19.95 (1.0) | -38.43 (2.0) | stand |@*
  908. h12-6 | 8.0e+04 | -12.05 (2.0) | -17.28 (1.0) | -33.47 (2.0) | stand |@*
  909. h12-7 | 8.0e+04 | -47.30 (2.0) | -21.83 (1.0) | -50.18 (2.0) | hit |@*
  910. h12-8 | 8.0e+04 | -51.08 (2.0) | -27.00 (1.0) | -61.37 (2.0) | hit |@*
  911. h12-9 | 8.0e+04 | -54.15 (1.9) | -34.39 (0.9) | -73.59 (1.9) | hit |@*
  912. h12-T | 8.0e+04 | -57.87 (1.8) | -42.68 (0.9) | -81.48 (1.8) | hit |@*
  913. h12-A | 8.0e+04 | -72.38 (1.5) | -56.80 (0.8) | -89.31 (1.5) | hit |@*
  914. h11-2 | 8.0e+04 | -28.87 (2.0) | +23.35 (1.0) | +47.39 (2.0) | double
  915. |@*
  916. h11-3 | 8.0e+04 | -24.76 (2.0) | +25.98 (1.0) | +52.29 (2.0) | double
  917. |@*
  918. h11-4 | 8.0e+04 | -20.67 (2.0) | +28.62 (1.0) | +57.21 (2.0) | double
  919. |@*
  920. h11-5 | 8.0e+04 | -16.73 (1.9) | +30.55 (1.0) | +62.32 (1.9) | double
  921. |@*
  922. h11-6 | 8.0e+04 | -11.69 (1.9) | +33.02 (1.0) | +66.25 (1.9) | double
  923. |@*
  924. h11-7 | 8.0e+04 | -47.69 (2.0) | +29.68 (1.0) | +45.78 (2.0) | double
  925. |@*
  926. h11-8 | 8.0e+04 | -52.13 (2.0) | +23.74 (1.0) | +35.93 (2.0) | double
  927. |@*
  928. h11-9 | 8.0e+04 | -54.25 (2.0) | +16.06 (1.0) | +22.66 (2.0) | double
  929. |@*
  930. h11-T | 8.0e+04 | -57.92 (2.0) | +3.19 (1.0) | +9.06 (2.0) | double |@*
  931. h11-A | 8.2e+07 | -72.22 (0) | -23.66 (0) | -23.64 (0) | double |@*
  932. h10-2 | 8.0e+04 | -28.12 (2.0) | +18.19 (1.0) | +36.23 (2.0) | double
  933. |@*
  934. h10-3 | 8.0e+04 | -24.40 (2.0) | +20.90 (1.0) | +40.69 (2.0) | double
  935. |@*
  936. h10-4 | 8.0e+04 | -20.09 (2.0) | +22.58 (1.0) | +46.54 (2.0) | double
  937. |@*
  938. h10-5 | 8.0e+04 | -16.16 (2.0) | +25.57 (1.0) | +49.92 (2.0) | double
  939. |@*
  940. h10-6 | 8.0e+04 | -12.23 (2.0) | +28.35 (1.0) | +56.55 (2.0) | double
  941. |@*
  942. h10-7 | 8.0e+04 | -47.69 (2.0) | +26.37 (1.0) | +39.07 (2.0) | double
  943. |@*
  944. h10-8 | 8.0e+04 | -50.60 (2.0) | +19.50 (1.0) | +27.72 (2.0) | double
  945. |@*
  946. h10-9 | 8.0e+04 | -54.75 (2.0) | +11.43 (1.0) | +15.10 (2.0) | double
  947. |@*
  948. h10-T | 8.0e+04 | -57.90 (1.9) | -5.37 (1.0) | -9.06 (1.9) | hit |@*
  949. h10-A | 8.0e+04 | -71.92 (1.7) | -28.02 (1.0) | -34.12 (1.7) | hit |@*
  950. h9-2 | 3.2e+05 | -28.52 (1.0) | +7.07 (0.5) | +5.21 (1.0) | hit |@*
  951. h9-3 | 3.2e+05 | -24.80 (1.0) | +9.97 (0.5) | +11.98 (1.0) | double |@*
  952. h9-4 | 8.0e+04 | -20.79 (2.0) | +12.80 (1.0) | +18.47 (2.0) | double |@*
  953. h9-5 | 8.0e+04 | -16.32 (2.0) | +15.69 (1.0) | +23.70 (2.0) | double |@*
  954. h9-6 | 8.0e+04 | -12.80 (2.0) | +18.20 (1.0) | +30.52 (2.0) | double |@*
  955. h9-7 | 8.0e+04 | -48.00 (2.0) | +17.03 (1.0) | +10.60 (2.0) | hit |@*
  956. h9-8 | 8.0e+04 | -51.36 (2.0) | +10.40 (1.0) | -1.84 (2.0) | hit |@*
  957. h9-9 | 8.0e+04 | -54.51 (1.9) | -4.82 (1.0) | -29.67 (1.9) | hit |@*
  958. h9-T | 8.0e+04 | -56.87 (1.9) | -22.03 (1.0) | -50.65 (1.9) | hit |@*
  959. h9-A | 8.0e+04 | -72.07 (1.6) | -39.82 (0.9) | -62.20 (1.6) | hit |@*
  960. h8-2 | 8.0e+04 | -28.53 (2.0) | -2.26 (1.0) | -20.42 (2.0) | hit |@*
  961. h8-3 | 8.0e+04 | -24.15 (2.0) | +0.65 (1.0) | -13.16 (2.0) | hit |@*
  962. h8-4 | 8.0e+04 | -20.23 (2.1) | +3.90 (1.0) | -5.21 (2.1) | hit |@*
  963. h8-5 | 8.0e+04 | -16.14 (2.1) | +7.09 (1.0) | -0.54 (2.1) | hit |@*
  964. h8-6 | 3.2e+05 | -12.14 (1.0) | +10.20 (0.5) | +7.84 (1.0) | hit |@*
  965. h8-7 | 8.0e+04 | -47.05 (2.0) | +8.66 (1.0) | -19.70 (2.0) | hit |@*
  966. h8-8 | 8.0e+04 | -50.79 (1.9) | -5.83 (1.0) | -45.53 (1.9) | hit |@*
  967. h8-9 | 8.0e+04 | -54.13 (1.9) | -21.18 (1.0) | -71.69 (1.9) | hit |@*
  968. h8-T | 8.0e+04 | -57.28 (1.8) | -30.79 (1.0) | -76.30 (1.8) | hit |@*
  969. h8-A | 8.0e+04 | -71.71 (1.5) | -49.20 (0.9) | -88.72 (1.5) | hit |@*
  970. h7-2 | 8.0e+04 | -28.98 (2.0) | -10.50 (1.0) | -43.26 (2.0) | hit |@*
  971. h7-3 | 8.0e+04 | -24.01 (2.0) | -7.75 (1.0) | -35.53 (2.0) | hit |@*
  972. h7-4 | 8.0e+04 | -20.99 (2.1) | -3.92 (1.0) | -26.25 (2.1) | hit |@*
  973. h7-5 | 8.0e+04 | -16.47 (2.1) | +0.08 (1.0) | -20.59 (2.1) | hit |@*
  974. h7-6 | 8.0e+04 | -12.61 (2.1) | +2.82 (1.0) | -10.05 (2.1) | hit |@*
  975. h7-7 | 8.0e+04 | -48.34 (1.9) | -6.79 (1.0) | -59.20 (1.9) | hit |@*
  976. h7-8 | 8.0e+04 | -51.35 (1.8) | -21.21 (1.0) | -84.58 (1.8) | hit |@*
  977. h7-9 | 8.0e+04 | -54.69 (1.8) | -28.72 (1.0) | -94.97 (1.8) | hit |@*
  978. h7-T | 8.0e+04 | -57.65 (1.7) | -37.00 (0.9) | -96.37 (1.7) | hit |@*
  979. h7-A | 8.0e+04 | -72.44 (1.4) | -55.11 (0.8) | -106.65 (1.4) | hit |@*
  980. h6-2 | 8.0e+04 | -28.57 (2.0) | -15.43 (1.0) | -54.59 (2.0) | hit |@*
  981. h6-3 | 8.0e+04 | -24.56 (2.0) | -11.04 (1.0) | -47.59 (2.0) | hit |@*
  982. h6-4 | 8.0e+04 | -20.00 (2.1) | -8.47 (1.0) | -38.90 (2.1) | hit |@*
  983. h6-5 | 8.0e+04 | -16.08 (2.1) | -4.01 (1.0) | -31.24 (2.1) | hit |@*
  984. h6-6 | 8.0e+04 | -11.99 (2.1) | -0.87 (1.0) | -21.55 (2.1) | hit |@*
  985. h6-7 | 8.0e+04 | -47.56 (1.9) | -16.78 (1.0) | -89.83 (1.9) | hit |@*
  986. h6-8 | 8.0e+04 | -51.12 (1.8) | -24.33 (1.0) | -99.55 (1.8) | hit |@*
  987. h6-9 | 8.0e+04 | -54.73 (1.8) | -31.31 (1.0) | -106.21 (1.8) | hit |@*
  988. h6-T | 8.0e+04 | -57.42 (1.7) | -41.13 (0.9) | -105.18 (1.7) | hit |@*
  989. h6-A | 8.0e+04 | -72.60 (1.4) | -56.24 (0.8) | -112.72 (1.4) | hit |@*
  990. h5-2 | 8.0e+04 | -29.05 (2.0) | -14.61 (1.0) | -56.03 (2.0) | hit |@*
  991. h5-3 | 8.0e+04 | -24.45 (2.1) | -11.41 (1.0) | -50.65 (2.1) | hit |@*
  992. h5-4 | 8.0e+04 | -20.23 (2.1) | -7.78 (1.0) | -40.43 (2.1) | hit |@*
  993. h5-5 | 8.0e+04 | -16.31 (2.1) | -3.84 (1.0) | -33.26 (2.1) | hit |@*
  994. h5-6 | 8.0e+04 | -11.79 (2.1) | -0.37 (1.0) | -25.05 (2.1) | hit |@*
  995. h5-7 | 8.0e+04 | -47.60 (1.9) | -15.39 (1.0) | -95.71 (1.9) | hit |@*
  996. h5-8 | 8.0e+04 | -51.23 (1.8) | -22.53 (1.0) | -101.98 (1.8) | hit |@*
  997. h5-9 | 8.0e+04 | -54.04 (1.8) | -29.29 (1.0) | -108.81 (1.8) | hit |@*
  998. h5-T | 8.0e+04 | -57.95 (1.7) | -39.00 (0.9) | -107.75 (1.7) | hit |@*
  999. h5-A | 8.0e+04 | -72.13 (1.4) | -54.85 (0.8) | -112.28 (1.4) | hit |@*
  1000. h4-2 | 8.0e+04 | -28.50 (2.0) | -14.23 (1.0) | -56.99 (2.0) | hit |@*
  1001. h4-3 | 8.0e+04 | -24.78 (2.1) | -10.80 (1.0) | -49.65 (2.1) | hit |@*
  1002. h4-4 | 8.0e+04 | -20.49 (2.1) | -6.87 (1.0) | -41.52 (2.1) | hit |@*
  1003. h4-5 | 8.0e+04 | -16.77 (2.1) | -3.61 (1.0) | -32.45 (2.1) | hit |@*
  1004. h4-6 | 8.0e+04 | -11.80 (2.1) | +1.55 (1.0) | -24.32 (2.1) | hit |@*
  1005. h4-7 | 8.0e+04 | -47.75 (1.9) | -13.39 (1.0) | -95.12 (1.9) | hit |@*
  1006. h4-8 | 8.0e+04 | -51.73 (1.8) | -19.55 (1.0) | -101.77 (1.8) | hit |@*
  1007. h4-9 | 8.0e+04 | -54.22 (1.8) | -27.76 (1.0) | -108.31 (1.8) | hit |@*
  1008. h4-T | 8.0e+04 | -58.04 (1.7) | -37.09 (0.9) | -107.42 (1.7) | hit |@*
  1009. h4-A | 8.0e+04 | -72.31 (1.4) | -53.45 (0.9) | -114.02 (1.4) | hit |@*
  1010. s20-2 | 8.0e+04 | +63.62 (2.0) | +18.06 (1.0) | +35.23 (2.0) | stand |@*
  1011. s20-3 | 8.0e+04 | +64.71 (2.0) | +20.31 (1.0) | +39.62 (2.0) | stand |@*
  1012. s20-4 | 8.0e+04 | +65.86 (2.0) | +23.05 (1.0) | +45.11 (2.0) | stand |@*
  1013. s20-5 | 8.0e+04 | +67.00 (2.0) | +25.96 (1.0) | +51.24 (2.0) | stand |@*
  1014. s20-6 | 8.0e+04 | +68.16 (2.0) | +28.27 (1.0) | +55.63 (2.0) | stand |@*
  1015. s20-7 | 8.0e+04 | +77.47 (2.0) | +25.35 (1.0) | +40.40 (2.0) | stand |@*
  1016. s20-8 | 8.0e+04 | +79.10 (2.0) | +20.23 (1.0) | +28.37 (2.0) | stand |@*
  1017. s20-9 | 8.0e+04 | +76.12 (2.0) | +11.22 (1.0) | +14.64 (2.0) | stand |@*
  1018. s20-T | 8.0e+04 | +43.51 (1.9) | -5.46 (1.0) | -8.53 (1.9) | stand |@*
  1019. s20-A | 8.0e+04 | +10.77 (1.7) | -28.26 (1.0) | -33.48 (1.7) | stand |@*
  1020. s19-2 | 8.0e+04 | +38.20 (2.0) | +11.75 (1.0) | +23.54 (2.0) | stand |@*
  1021. s19-3 | 8.0e+04 | +39.82 (2.0) | +15.29 (1.0) | +29.62 (2.0) | stand |@*
  1022. s19-4 | 8.0e+04 | +42.18 (2.0) | +17.78 (1.0) | +35.08 (2.0) | stand |@*
  1023. s19-5 | 3.2e+05 | +43.54 (1.0) | +20.12 (0.5) | +40.89 (1.0) | stand |@*
  1024. s19-6 | 5.1e+06 | +45.35 (0.2) | +23.10 (0.1) | +46.20 (0.2) | double
  1025. |@*
  1026. s19-7 | 8.0e+04 | +61.59 (2.0) | +21.74 (1.0) | +31.70 (2.0) | stand |@*
  1027. s19-8 | 8.0e+04 | +59.31 (2.0) | +15.31 (1.0) | +20.15 (2.0) | stand |@*
  1028. s19-9 | 8.0e+04 | +28.43 (2.0) | +0.63 (1.0) | -8.21 (2.0) | stand |@*
  1029. s19-T | 8.0e+04 | -1.71 (1.9) | -16.07 (1.0) | -28.88 (1.9) | stand |@*
  1030. s19-A | 8.0e+04 | -18.13 (1.7) | -35.40 (0.9) | -46.73 (1.7) | stand |@*
  1031. s18-2 | 2.0e+07 | +11.03 (0) | +5.99 (0) | +11.48 (0) | double |@*
  1032. s18-3 | 3.2e+05 | +13.61 (1.0) | +8.83 (0.5) | +17.60 (1.0) | double |@*
  1033. s18-4 | 8.0e+04 | +16.17 (2.0) | +11.32 (1.0) | +22.57 (2.0) | double
  1034. |@*
  1035. s18-5 | 8.0e+04 | +19.92 (2.0) | +14.49 (1.0) | +28.95 (2.0) | double
  1036. |@*
  1037. s18-6 | 8.0e+04 | +22.64 (2.0) | +15.59 (1.0) | +34.71 (2.0) | double
  1038. |@*
  1039. s18-7 | 8.0e+04 | +39.60 (2.0) | +16.92 (1.0) | +22.37 (2.0) | stand |@*
  1040. s18-8 | 8.0e+04 | +10.50 (2.0) | +4.49 (1.0) | -3.59 (2.0) | stand |@*
  1041. s18-9 | 8.0e+04 | -18.75 (2.0) | -9.78 (1.0) | -29.28 (2.0) | hit |@*
  1042. s18-T | 8.0e+04 | -24.01 (1.9) | -20.91 (1.0) | -38.83 (1.9) | hit |@*
  1043. s18-A | 8.0e+04 | -46.67 (1.7) | -41.65 (0.9) | -59.24 (1.7) | hit |@*
  1044. s17-2 | 2.0e+07 | -15.66 (0) | -0.55 (0) | -0.87 (0) | hit |@*
  1045. s17-3 | 3.2e+05 | -11.98 (1.0) | +2.36 (0.5) | +5.48 (1.0) | double |@*
  1046. s17-4 | 8.0e+04 | -8.31 (2.0) | +5.04 (1.0) | +11.89 (2.0) | double |@*
  1047. s17-5 | 8.0e+04 | -4.91 (2.0) | +8.85 (1.0) | +17.72 (2.0) | double |@*
  1048. s17-6 | 8.0e+04 | -0.74 (2.0) | +10.12 (1.0) | +24.25 (2.0) | double |@*
  1049. s17-7 | 8.0e+04 | -10.35 (2.0) | +5.08 (1.0) | -0.47 (2.0) | hit |@*
  1050. s17-8 | 8.0e+04 | -38.37 (2.0) | -7.07 (1.0) | -26.13 (2.0) | hit |@*
  1051. s17-9 | 8.0e+04 | -41.81 (2.0) | -15.16 (1.0) | -40.21 (2.0) | hit |@*
  1052. s17-T | 8.0e+04 | -45.89 (1.9) | -25.72 (1.0) | -50.87 (1.9) | hit |@*
  1053. s17-A | 8.0e+04 | -66.48 (1.6) | -46.33 (0.9) | -69.24 (1.6) | hit |@*
  1054. s16-2 | 8.0e+04 | -28.80 (2.1) | -2.39 (1.0) | -6.32 (2.1) | hit |@*
  1055. s16-3 | 3.2e+05 | -24.88 (1.0) | +0.60 (0.5) | -0.97 (1.0) | hit |@*
  1056. s16-4 | 8.0e+04 | -21.20 (2.1) | +3.23 (1.0) | +6.64 (2.1) | double |@*
  1057. s16-5 | 8.0e+04 | -15.99 (2.1) | +6.72 (1.0) | +13.54 (2.1) | double |@*
  1058. s16-6 | 8.0e+04 | -12.50 (2.1) | +8.31 (1.0) | +19.84 (2.1) | double |@*
  1059. s16-7 | 8.0e+04 | -47.17 (2.0) | -1.23 (1.0) | -18.63 (2.0) | hit |@*
  1060. s16-8 | 8.0e+04 | -50.91 (2.0) | -6.98 (1.0) | -31.09 (2.0) | hit |@*
  1061. s16-9 | 8.0e+04 | -54.43 (2.0) | -14.67 (1.0) | -46.42 (2.0) | hit |@*
  1062. s16-T | 8.0e+04 | -57.58 (1.9) | -26.70 (1.0) | -55.38 (1.9) | hit |@*
  1063. s16-A | 8.0e+04 | -72.33 (1.6) | -44.35 (0.9) | -71.31 (1.6) | hit |@*
  1064. s15-2 | 8.0e+04 | -29.03 (2.1) | -0.58 (1.0) | -5.65 (2.1) | hit |@*
  1065. s15-3 | 8.0e+04 | -24.71 (2.1) | +3.31 (1.0) | -1.28 (2.1) | hit |@*
  1066. s15-4 | 1.3e+06 | -20.58 (0.5) | +5.60 (0.3) | +6.44 (0.5) | double |@*
  1067. s15-5 | 3.2e+05 | -16.62 (1.0) | +8.86 (0.5) | +12.74 (1.0) | double |@*
  1068. s15-6 | 8.0e+04 | -12.09 (2.1) | +10.13 (1.0) | +19.13 (2.1) | double
  1069. |@*
  1070. s15-7 | 8.0e+04 | -47.61 (2.0) | +4.21 (1.0) | -19.48 (2.0) | hit |@*
  1071. s15-8 | 8.0e+04 | -51.16 (2.0) | -2.81 (1.0) | -30.90 (2.0) | hit |@*
  1072. s15-9 | 8.0e+04 | -54.31 (2.0) | -11.18 (1.0) | -46.93 (2.0) | hit |@*
  1073. s15-T | 8.0e+04 | -57.49 (1.9) | -23.85 (1.0) | -54.93 (1.9) | hit |@*
  1074. s15-A | 8.0e+04 | -71.98 (1.6) | -42.68 (0.9) | -71.58 (1.6) | hit |@*
  1075. s14-2 | 8.0e+04 | -28.59 (2.1) | +1.42 (1.0) | -6.73 (2.1) | hit |@*
  1076. s14-3 | 8.0e+04 | -24.89 (2.1) | +4.04 (1.0) | -0.41 (2.1) | hit |@*
  1077. s14-4 | 8.0e+04 | -20.84 (2.1) | +7.58 (1.0) | +5.13 (2.1) | hit |@*
  1078. s14-5 | 3.2e+05 | -16.36 (1.0) | +10.61 (0.5) | +12.72 (1.0) | double
  1079. |@*
  1080. s14-6 | 8.0e+04 | -12.19 (2.1) | +12.30 (1.0) | +19.62 (2.1) | double
  1081. |@*
  1082. s14-7 | 8.0e+04 | -47.42 (2.1) | +7.66 (1.0) | -18.33 (2.1) | hit |@*
  1083. s14-8 | 8.0e+04 | -50.95 (2.0) | +0.96 (1.0) | -30.90 (2.0) | hit |@*
  1084. s14-9 | 8.0e+04 | -54.73 (2.0) | -7.82 (1.0) | -46.11 (2.0) | hit |@*
  1085. s14-T | 8.0e+04 | -57.51 (1.9) | -21.19 (1.0) | -55.00 (1.9) | hit |@*
  1086. s14-A | 8.0e+04 | -72.28 (1.6) | -40.00 (0.9) | -71.64 (1.6) | hit |@*
  1087. s13-2 | 8.0e+04 | -28.76 (2.1) | +3.98 (1.0) | -7.66 (2.1) | hit |@*
  1088. s13-3 | 8.0e+04 | -25.07 (2.1) | +7.23 (1.0) | -0.04 (2.1) | hit |@*
  1089. s13-4 | 8.0e+04 | -20.02 (2.1) | +9.31 (1.0) | +4.88 (2.1) | hit |@*
  1090. s13-5 | 2.0e+07 | -16.49 (0) | +12.84 (0) | +12.70 (0) | hit |@*
  1091. s13-6 | 8.0e+04 | -12.39 (2.1) | +13.78 (1.0) | +18.69 (2.1) | double
  1092. |@*
  1093. s13-7 | 8.0e+04 | -47.43 (2.1) | +12.59 (1.0) | -18.10 (2.1) | hit |@*
  1094. s13-8 | 8.0e+04 | -50.86 (2.0) | +5.47 (1.0) | -31.53 (2.0) | hit |@*
  1095. s13-9 | 8.0e+04 | -54.25 (2.0) | -4.04 (1.0) | -46.51 (2.0) | hit |@*
  1096. s13-T | 8.0e+04 | -57.70 (1.9) | -16.62 (1.0) | -54.45 (1.9) | hit |@*
  1097. s13-A | 8.0e+04 | -71.53 (1.7) | -37.98 (0.9) | -69.91 (1.7) | hit |@*
  1098. s12-2 | 8.0e+04 | -28.39 (2.1) | +7.36 (1.0) | -6.07 (2.1) | hit |@*
  1099. s12-3 | 8.0e+04 | -25.70 (2.1) | +9.50 (1.0) | -0.03 (2.1) | hit |@*
  1100. s12-4 | 8.0e+04 | -20.48 (2.1) | +12.65 (1.0) | +6.24 (2.1) | hit |@*
  1101. s12-5 | 3.2e+05 | -16.42 (1.0) | +15.18 (0.5) | +13.22 (1.0) | hit |@*
  1102. s12-6 | 8.0e+04 | -11.66 (2.1) | +15.42 (1.0) | +19.62 (2.1) | double
  1103. |@*
  1104. s12-7 | 8.0e+04 | -47.27 (2.1) | +16.31 (1.0) | -16.99 (2.1) | hit |@*
  1105. s12-8 | 8.0e+04 | -51.51 (2.0) | +9.36 (1.0) | -30.70 (2.0) | hit |@*
  1106. s12-9 | 8.0e+04 | -54.23 (2.0) | -0.10 (1.0) | -44.47 (2.0) | hit |@*
  1107. s12-T | 8.0e+04 | -57.77 (1.9) | -14.11 (1.0) | -57.03 (1.9) | hit |@*
  1108. s12-A | 8.0e+04 | -72.70 (1.6) | -34.54 (0.9) | -70.64 (1.6) | hit |
  1109. @ Hand | @math{n} | Yes [%] | No [%] |@*
  1110. pA-2 | 8.0e+04 | +47.20 (1.7) | +6.91 (1.0) | yes |@*
  1111. pA-3 | 8.0e+04 | +53.01 (1.7) | +8.95 (1.0) | yes |@*
  1112. pA-4 | 8.0e+04 | +55.98 (1.7) | +11.49 (1.0) | yes |@*
  1113. pA-5 | 8.0e+04 | +60.89 (1.7) | +14.66 (1.0) | yes |@*
  1114. pA-6 | 8.0e+04 | +66.26 (1.7) | +20.80 (2.1) | yes |@*
  1115. pA-7 | 8.0e+04 | +46.06 (1.6) | +16.94 (1.0) | yes |@*
  1116. pA-8 | 8.0e+04 | +35.38 (1.6) | +9.52 (1.0) | yes |@*
  1117. pA-9 | 8.0e+04 | +22.97 (1.6) | -0.20 (1.0) | yes |@*
  1118. pA-T | 8.0e+04 | +8.41 (1.6) | -14.49 (1.0) | yes |@*
  1119. pA-A | 8.0e+04 | -23.73 (1.5) | -34.77 (0.9) | yes |@*
  1120. pT-2 | 8.0e+04 | -7.22 (3.8) | +63.33 (0.7) | no |@*
  1121. pT-3 | 8.0e+04 | +1.85 (3.8) | +64.34 (0.7) | no |@*
  1122. pT-4 | 8.0e+04 | +15.20 (4.0) | +65.82 (0.7) | no |@*
  1123. pT-5 | 8.0e+04 | +24.91 (4.0) | +66.75 (0.7) | no |@*
  1124. pT-6 | 8.0e+04 | +37.30 (4.0) | +67.83 (0.7) | no |@*
  1125. pT-7 | 8.0e+04 | +9.41 (2.6) | +76.75 (0.6) | no |@*
  1126. pT-8 | 8.0e+04 | -23.72 (2.5) | +79.31 (0.6) | no |@*
  1127. pT-9 | 8.0e+04 | -59.32 (2.6) | +75.92 (0.6) | no |@*
  1128. pT-T | 8.0e+04 | -77.52 (2.6) | +43.30 (0.7) | no |@*
  1129. pT-A | 8.0e+04 | -85.16 (2.2) | +10.82 (1.0) | no |@*
  1130. p9-2 | 8.0e+04 | +20.02 (2.2) | +11.24 (1.0) | yes |@*
  1131. p9-3 | 8.0e+04 | +25.25 (2.2) | +13.40 (1.0) | yes |@*
  1132. p9-4 | 8.0e+04 | +33.27 (2.2) | +16.87 (1.0) | yes |@*
  1133. p9-5 | 8.0e+04 | +39.23 (2.2) | +19.21 (1.0) | yes |@*
  1134. p9-6 | 8.0e+04 | +45.68 (2.2) | +22.91 (1.0) | yes |@*
  1135. p9-7 | 8.0e+04 | +36.00 (1.9) | +40.30 (0.9) | no |@*
  1136. p9-8 | 8.0e+04 | +23.61 (1.9) | +10.59 (0.8) | yes |@*
  1137. p9-9 | 8.0e+04 | -6.82 (1.8) | -18.28 (1.0) | yes |@*
  1138. p9-T | 8.0e+04 | -36.80 (1.9) | -23.83 (1.0) | no |@*
  1139. p9-A | 3.2e+05 | -48.13 (0.8) | -46.28 (0.4) | no |@*
  1140. p8-2 | 8.0e+04 | +5.68 (2.4) | -28.12 (1.0) | yes |@*
  1141. p8-3 | 8.0e+04 | +13.29 (2.4) | -24.45 (1.0) | yes |@*
  1142. p8-4 | 8.0e+04 | +20.18 (2.5) | -20.57 (1.0) | yes |@*
  1143. p8-5 | 8.0e+04 | +28.86 (2.5) | -15.92 (1.0) | yes |@*
  1144. p8-6 | 8.0e+04 | +38.58 (2.7) | -12.18 (1.1) | yes |@*
  1145. p8-7 | 8.0e+04 | +32.62 (2.1) | -41.09 (0.9) | yes |@*
  1146. p8-8 | 8.0e+04 | -1.93 (2.1) | -46.30 (0.9) | yes |@*
  1147. p8-9 | 8.0e+04 | -39.65 (2.2) | -50.97 (0.9) | yes |@*
  1148. p8-T | 8.0e+04 | -51.78 (1.9) | -57.43 (0.8) | yes |@*
  1149. p8-A | 3.2e+05 | -66.56 (0.8) | -68.26 (0.4) | yes |@*
  1150. p7-2 | 8.0e+04 | -14.09 (2.6) | -28.55 (1.0) | yes |@*
  1151. p7-3 | 8.0e+04 | -5.00 (2.8) | -25.59 (1.0) | yes |@*
  1152. p7-4 | 8.0e+04 | +5.68 (2.9) | -20.86 (1.0) | yes |@*
  1153. p7-5 | 8.0e+04 | +15.57 (2.9) | -16.37 (1.0) | yes |@*
  1154. p7-6 | 8.0e+04 | +25.52 (2.9) | -12.25 (1.1) | yes |@*
  1155. p7-7 | 8.0e+04 | -5.23 (2.1) | -31.97 (1.0) | yes |@*
  1156. p7-8 | 3.2e+05 | -39.50 (1.0) | -37.19 (0.5) | no |@*
  1157. p7-9 | 8.0e+04 | -57.79 (2.1) | -42.92 (0.9) | no |@*
  1158. p7-T | 8.0e+04 | -68.47 (1.8) | -50.66 (0.9) | no |@*
  1159. p7-A | 8.0e+04 | -81.50 (1.5) | -63.51 (0.8) | no |@*
  1160. p6-2 | 8.0e+04 | -17.82 (2.5) | -26.09 (1.0) | yes |@*
  1161. p6-3 | 8.0e+04 | -11.19 (2.9) | -23.68 (1.0) | yes |@*
  1162. p6-4 | 8.0e+04 | -0.23 (2.9) | -20.51 (1.0) | yes |@*
  1163. p6-5 | 8.0e+04 | +8.19 (2.9) | -16.81 (1.0) | yes |@*
  1164. p6-6 | 8.0e+04 | +18.21 (2.9) | -12.51 (1.1) | yes |@*
  1165. p6-7 | 8.0e+04 | -26.43 (2.0) | -21.52 (1.0) | no |@*
  1166. p6-8 | 8.0e+04 | -41.81 (2.0) | -27.45 (1.0) | no |@*
  1167. p6-9 | 8.0e+04 | -61.03 (1.9) | -33.82 (1.0) | no |@*
  1168. p6-T | 8.0e+04 | -74.39 (1.7) | -43.03 (0.9) | no |@*
  1169. p6-A | 8.0e+04 | -82.19 (1.4) | -57.43 (0.8) | no |@*
  1170. p5-2 | 8.0e+04 | -28.56 (2.3) | +36.16 (2.0) | no |@*
  1171. p5-3 | 8.0e+04 | -19.64 (2.5) | +40.18 (2.0) | no |@*
  1172. p5-4 | 8.0e+04 | -12.32 (2.8) | +45.78 (2.0) | no |@*
  1173. p5-5 | 8.0e+04 | -5.05 (2.8) | +52.02 (2.0) | no |@*
  1174. p5-6 | 8.0e+04 | +8.49 (2.8) | +57.75 (2.0) | no |@*
  1175. p5-7 | 8.0e+04 | -29.66 (1.8) | +38.20 (2.0) | no |@*
  1176. p5-8 | 8.0e+04 | -45.66 (1.8) | +29.62 (2.0) | no |@*
  1177. p5-9 | 8.0e+04 | -63.47 (1.7) | +14.03 (2.0) | no |@*
  1178. p5-T | 8.0e+04 | -75.39 (1.7) | -5.08 (1.0) | no |@*
  1179. p5-A | 8.0e+04 | -83.27 (1.4) | -28.59 (1.0) | no |@*
  1180. p4-2 | 8.0e+04 | -18.11 (2.5) | -2.44 (1.0) | no |@*
  1181. p4-3 | 8.0e+04 | -11.18 (2.7) | +0.19 (1.0) | no |@*
  1182. p4-4 | 8.0e+04 | -0.79 (2.9) | +3.43 (1.0) | no |@*
  1183. p4-5 | 1.3e+06 | +8.28 (0.7) | +7.07 (0.3) | yes |@*
  1184. p4-6 | 8.0e+04 | +18.98 (3.0) | +8.70 (1.0) | yes |@*
  1185. p4-7 | 8.0e+04 | -16.47 (2.0) | +7.80 (1.0) | no |@*
  1186. p4-8 | 8.0e+04 | -32.77 (2.0) | -6.00 (1.0) | no |@*
  1187. p4-9 | 8.0e+04 | -50.81 (2.0) | -20.81 (1.0) | no |@*
  1188. p4-T | 8.0e+04 | -65.67 (1.7) | -30.72 (1.0) | no |@*
  1189. p4-A | 8.0e+04 | -74.66 (1.5) | -49.18 (0.9) | no |@*
  1190. p3-2 | 2.0e+07 | -13.64 (0) | -13.80 (0) | yes |@*
  1191. p3-3 | 8.0e+04 | -5.32 (2.6) | -10.45 (1.0) | yes |@*
  1192. p3-4 | 8.0e+04 | +4.08 (2.7) | -7.45 (1.0) | yes |@*
  1193. p3-5 | 8.0e+04 | +12.53 (2.9) | -3.04 (1.0) | yes |@*
  1194. p3-6 | 8.0e+04 | +22.61 (2.9) | +0.47 (1.0) | yes |@*
  1195. p3-7 | 8.0e+04 | -4.91 (2.0) | -14.91 (1.0) | yes |@*
  1196. p3-8 | 3.2e+05 | -23.20 (1.0) | -21.69 (0.5) | no |@*
  1197. p3-9 | 8.0e+04 | -43.61 (2.0) | -29.14 (1.0) | no |@*
  1198. p3-T | 8.0e+04 | -58.65 (1.7) | -38.95 (0.9) | no |@*
  1199. p3-A | 8.0e+04 | -70.06 (1.5) | -54.59 (0.8) | no |@*
  1200. p2-2 | 3.2e+05 | -8.69 (1.1) | -11.47 (0.5) | yes |@*
  1201. p2-3 | 8.0e+04 | -1.93 (2.5) | -8.55 (1.0) | yes |@*
  1202. p2-4 | 8.0e+04 | +6.19 (2.7) | -4.95 (1.0) | yes |@*
  1203. p2-5 | 8.0e+04 | +15.78 (2.7) | -1.24 (1.0) | yes |@*
  1204. p2-6 | 8.0e+04 | +24.78 (2.9) | +3.07 (1.0) | yes |@*
  1205. p2-7 | 8.0e+04 | +1.48 (2.0) | -8.90 (1.0) | yes |@*
  1206. p2-8 | 3.2e+05 | -17.88 (1.0) | -16.10 (0.5) | no |@*
  1207. p2-9 | 8.0e+04 | -38.73 (2.0) | -24.38 (1.0) | no |@*
  1208. p2-T | 8.0e+04 | -54.45 (1.8) | -34.92 (0.9) | no |@*
  1209. p2-A | 8.0e+04 | -67.11 (1.5) | -51.59 (0.9) | no |
  1210. @node Detailed explanation
  1211. @subsection Detailed explanation
  1212. @anchor{#detailed-explanation}
  1213. We want to derive the basic strategy from scratch, i.e.@ without making
  1214. any assumption. What we are going to do is to play a large (more on what
  1215. @emph{large} means below) number of hands by fixing our first two cards
  1216. and the dealer upcard and sequentially standing, doubling or hitting the
  1217. first card. Then we will compare the results for the three cases and
  1218. select as the proper strategy the best one of the three possible
  1219. choices.
  1220. Standing and doubling are easy plays, because after we stand or double
  1221. down then the dealer plays accordingly to the rules: she hits until
  1222. seventeen, possibly hitting soft seventeen. But if we hit on our hand,
  1223. we might need to make another decision whether to stand or hit again. As
  1224. we do not want to assume anything, we have to play in such an order that
  1225. if we do need to make another decision, we already know which is the
  1226. best one.
  1227. @menu
  1228. * Hard hands::
  1229. * Soft hands::
  1230. * Pairs::
  1231. * Number of hands::
  1232. @end menu
  1233. @node Hard hands
  1234. @subsubsection Hard hands
  1235. @anchor{#hard-hands}
  1236. So we start by arranging the shoe so that the user gets hard twenty
  1237. (i.e.@ two faces) and the dealer gets successively upcards of two to
  1238. ace. So we play each combination of dealer upcard (ten) three times each
  1239. playing either
  1240. @enumerate
  1241. @item
  1242. always standing
  1243. @item
  1244. always doubling
  1245. @item
  1246. always hitting
  1247. @end enumerate
  1248. In general the first two plays are easy, because the game stops either
  1249. after standing or after receiving only one card. The last one might lead
  1250. to further hitting, but since we are starting with a hard twenty, that
  1251. would either give the player twenty one or a bust. In any case, the game
  1252. also ends. So we play a certain number of hands (say one thousand hands)
  1253. each of these three plays for each of the ten upcard faces and record
  1254. the outcome. The correct play for hard twenty against each of the ten
  1255. upcards is the play that gave the better result, which is of course
  1256. standing.
  1257. Next, we do the same for a hard nineteen. In this case, the hitting play
  1258. might not end after one card is drawn (i.e.@ we hit on nineteen and get
  1259. and ace). But if that was the case, we would already know what the best
  1260. play is from the previous step so we play accordingly and we stand.
  1261. Repeating this procedure down to hard four we can build the basic
  1262. strategy table for any hard total against any dealer upcard.
  1263. @node Soft hands
  1264. @subsubsection Soft hands
  1265. @anchor{#soft-hands}
  1266. We can now switch to analyze soft hands. Starting from soft twenty
  1267. (i.e.@ an ace and a nine) we do the same we did for the hard case. The
  1268. only difference is that when hitting, we might end either in another
  1269. soft hand which we would already analyzed because we start from twenty
  1270. and go down, or in a hard hand, which we also already analyzed so we can
  1271. play accordingly.
  1272. @node Pairs
  1273. @subsubsection Pairs
  1274. @anchor{#pairs}
  1275. When dealing with pairs, we have to decide whether to split or not. When
  1276. we do not split, we end up in one of the already-analyzed cases: either
  1277. a soft twelve of any even hard hand. When we split, we might end in a
  1278. hard or soft hand (already analyzed) or in a new pair. But since the new
  1279. pair can be only the same pair we are analyzing, we have to treat it
  1280. like we treated the first pair: either to split it or not, so we know
  1281. how to deal with it.
  1282. @node Number of hands
  1283. @subsubsection Number of hands
  1284. @anchor{#number-of-hands}
  1285. The output is the expected value@ @math{e} of the bankroll, which is a
  1286. random variable with an associated uncertainty@ @math{\Delta e} (i.e.@ a
  1287. certain numbers of standard deviations). For example, if we received
  1288. only blackjacks, the expected value would be 1.5 (provided blackjacks
  1289. pay@ 3 to@ 2 of course). If we busted all of our hands without doubling
  1290. or splitting, the expected value would be -1. In order to say that the
  1291. best strategy is, let's say stand and not hitting or doubling down, we
  1292. have to make sure that @math{e_h-\Delta e_h > e_s+\Delta e_s} and
  1293. @math{e_h-\Delta e_h > e_d+\Delta e_d}. If there is no play that can
  1294. give a better expected value than the other two taking into account the
  1295. uncertainties, then we have to play more hands in order to reduce the
  1296. random uncertainty.
  1297. @node Implementation
  1298. @subsection Implementation
  1299. @anchor{#implementation}
  1300. The steps above can be written in a
  1301. @uref{https://en.wikipedia.org/wiki/Bash_%28Unix_shell%29,Bash} script
  1302. that
  1303. @itemize
  1304. @item
  1305. loops over hands and upcards,
  1306. @item
  1307. creates a strategy file for each possible play hit, double or stand (or
  1308. split or not),
  1309. @item
  1310. runs @uref{https://www.seamplex.com/blackjack,Libre@ Blackjack},
  1311. @item
  1312. checks the results and picks the best play,
  1313. @item
  1314. updates the strategy file
  1315. @end itemize
  1316. @verbatim
  1317. #!/bin/bash
  1318. n0=80000
  1319. n_max=9000000
  1320. RED="\033[0;31m"
  1321. GREEN="\033[0;32m"
  1322. BROWN="\033[0;33m"
  1323. MAGENTA="\e[0;35m"
  1324. CYAN="\e[0;36m"
  1325. NC="\033[0m" # No Color
  1326. for i in grep awk printf blackjack; do
  1327. if [ -z "$(which $i)" ]; then
  1328. echo "error: $i not installed"
  1329. exit 1
  1330. fi
  1331. done
  1332. debug=0
  1333. declare -A strategy
  1334. declare -A ev
  1335. declare -A min
  1336. min["hard"]=4 # from 20 to 4 in hards
  1337. min["soft"]=12 # from 20 to 12 in softs
  1338. rm -f table.md hard.html soft.html pair.html
  1339. # start with standing
  1340. cp hard-stand.txt hard.txt
  1341. cp soft-stand.txt soft.txt
  1342. cat << EOF >> table.md
  1343. | Hand | \$n\$ | Stand [%] | Double [%] | Hit [%] | Play |
  1344. EOF
  1345. for type in hard soft; do
  1346. for hand in $(seq 20 -1 ${min[${type}]}); do
  1347. # choose two random cards that make up the player's assumed total
  1348. if [ ${type} = "hard" ]; then
  1349. t="h"
  1350. card1=11
  1351. card2=11
  1352. while test $card1 -gt 10 -o $card2 -gt 10; do
  1353. card1=$((${RANDOM} % (${hand}-3) + 2))
  1354. card2=$((${hand} - ${card1}))
  1355. done
  1356. elif [ ${type} = "soft" ]; then
  1357. t="s"
  1358. # one card is an ace
  1359. card1=1
  1360. card2=$((${hand} - 10 - ${card1}))
  1361. fi
  1362. cat << EOF >> ${type}.html
  1363. <tr>
  1364. <td>${t}${hand}</td>
  1365. <td>
  1366. <div class="text-right">s<span class="d-none d-lg-inline">tand</span></div>
  1367. <div class="text-right">h<span class="d-none d-lg-inline">it</span></div>
  1368. <div class="text-right">d<span class="d-none d-lg-inline">ouble</span></div>
  1369. </td>
  1370. EOF
  1371. for upcard in $(seq 2 9) T A; do
  1372. if [ "x$upcard" = "xT" ]; then
  1373. upcard_n=10
  1374. elif [ "x$upcard" = "xA" ]; then
  1375. upcard_n=1
  1376. else
  1377. upcard_n=$(($upcard))
  1378. fi
  1379. n=${n0} # start with n0 hands
  1380. best="x" # x means don't know what to so, so play
  1381. while [ "${best}" = "x" ]; do
  1382. # tell the user which combination we are trying and how many we will play
  1383. echo -ne "${t}${hand}-${upcard} ($card1 $card2)\t"$(printf %.1e ${n})
  1384. for play in s d h; do
  1385. # start with options.conf as a template and add some custom stuff
  1386. cp options.conf blackjack.conf
  1387. cat << EOF >> blackjack.conf
  1388. hands = ${n}
  1389. player = internal
  1390. arranged_cards = ${card1}, $((${upcard_n} + 13)), $((${card2} + 26))
  1391. report = ${t}${hand}-${upcard}-${play}.yaml
  1392. #log = ${t}${hand}-${upcard}-${play}.log
  1393. EOF
  1394. # read the current strategy
  1395. while read w p2 p3 p4 p5 p6 p7 p8 p9 pT pA; do
  1396. # w already has the "h" or the "s"
  1397. strategy[${w},2]=$p2
  1398. strategy[${w},3]=$p3
  1399. strategy[${w},4]=$p4
  1400. strategy[${w},5]=$p5
  1401. strategy[${w},6]=$p6
  1402. strategy[${w},7]=$p7
  1403. strategy[${w},8]=$p8
  1404. strategy[${w},9]=$p9
  1405. strategy[${w},T]=$pT
  1406. strategy[${w},A]=$pA
  1407. done < ${type}.txt
  1408. # override the read strategy with the explicit play: s, d or h
  1409. strategy[${t}${hand},${upcard}]=${play}
  1410. # save the new (temporary) strategy
  1411. rm -f ${type}.txt
  1412. for h in $(seq 20 -1 ${min[${type}]}); do
  1413. echo -n "${t}${h} " >> ${type}.txt
  1414. # extra space if h < 10
  1415. if [ ${h} -lt 10 ]; then
  1416. echo -n " " >> ${type}.txt
  1417. fi
  1418. for u in $(seq 2 9) T A; do
  1419. echo -n "${strategy[${t}${h},${u}]} " >> ${type}.txt
  1420. done
  1421. echo >> ${type}.txt
  1422. done
  1423. # debug, comment for production
  1424. if [ "${debug}" != "0" ]; then
  1425. cp ${type}.txt ${t}${hand}-${upcard}-${play}.str
  1426. fi
  1427. # ensamble the full bs.txt with no pairing
  1428. cat hard.txt soft.txt pair-no.txt > bs.txt
  1429. # play!
  1430. blackjack
  1431. # evaluate the results
  1432. ev[${t}${hand},${upcard},${play}]=$(grep mean ${t}${hand}-${upcard}-${play}.yaml | awk '{printf("%g", $2)}')
  1433. error[${t}${hand},${upcard},${play}]=$(grep error ${t}${hand}-${upcard}-${play}.yaml | awk '{printf("%g", $2)}')
  1434. done
  1435. # choose the best one
  1436. ev_s=$(echo ${ev[${t}${hand},${upcard},s]} | awk '{printf("%+.2f", 100*$1)}')
  1437. ev_d=$(echo ${ev[${t}${hand},${upcard},d]} | awk '{printf("%+.2f", 100*$1)}')
  1438. ev_h=$(echo ${ev[${t}${hand},${upcard},h]} | awk '{printf("%+.2f", 100*$1)}')
  1439. if [ ${n} -le ${n_max} ]; then
  1440. # if we still have room, take into account errors
  1441. error_s=$(echo ${error[${t}${hand},${upcard},s]} | awk '{printf("%.1f", 100*$1)}')
  1442. error_d=$(echo ${error[${t}${hand},${upcard},d]} | awk '{printf("%.1f", 100*$1)}')
  1443. error_h=$(echo ${error[${t}${hand},${upcard},h]} | awk '{printf("%.1f", 100*$1)}')
  1444. else
  1445. # instead of running infinite hands, above a threshold asume errors are zero
  1446. error_s=0
  1447. error_d=0
  1448. error_h=0
  1449. fi
  1450. echo -ne "\t${ev_s}\t(${error_s})"
  1451. echo -ne "\t${ev_d}\t(${error_d})"
  1452. echo -ne "\t${ev_h}\t(${error_h})"
  1453. if (( $(echo ${ev_s} ${error_s} ${ev_d} ${error_d} | awk '{print (($1-$2) > ($3+$4))}') )) &&
  1454. (( $(echo ${ev_s} ${error_s} ${ev_h} ${error_h} | awk '{print (($1-$2) > ($3+$4))}') )); then
  1455. best="s"
  1456. color=${BROWN}
  1457. best_string="stand"
  1458. elif (( $(echo ${ev_d} ${error_d} ${ev_s} ${error_s} | awk '{print (($1-$2) > ($3+$4))}') )) &&
  1459. (( $(echo ${ev_d} ${error_d} ${ev_h} ${error_h} | awk '{print (($1-$2) > ($3+$4))}') )); then
  1460. best="d"
  1461. color=${CYAN}
  1462. best_string="double"
  1463. elif (( $(echo ${ev_h}-${error_h} ${ev_s} ${error_s} | awk '{print (($1-$2) > ($3+$4))}') )) &&
  1464. (( $(echo ${ev_h}-${error_h} ${ev_d} ${error_d} | awk '{print (($1-$2) > ($3+$4))}') )); then
  1465. best="h"
  1466. color=${MAGENTA}
  1467. best_string="hit"
  1468. else
  1469. best="x"
  1470. color=${NC}
  1471. best_string="uncertain"
  1472. n=$((${n} * 4))
  1473. fi
  1474. echo -e ${color}"\t"${best_string}${NC}
  1475. done
  1476. strategy[${t}${hand},${upcard}]=${best}
  1477. echo "| ${t}${hand}-${upcard} | $(printf %.1e ${n}) | ${ev_s} (${error_s}) | ${ev_h} (${error_h}) | ${ev_d} (${error_d}) | ${best_string} | " >> table.md
  1478. echo " <!-- ${upcard} -->" >> ${type}.html
  1479. echo " <td>" >> ${type}.html
  1480. echo ${ev_s} ${error_s} | awk -f html_cell.awk >> ${type}.html
  1481. echo ${ev_h} ${error_h} | awk -f html_cell.awk >> ${type}.html
  1482. echo ${ev_d} ${error_d} | awk -f html_cell.awk >> ${type}.html
  1483. echo " </td>" >> ${type}.html
  1484. # save the strategy again with the best strategy
  1485. rm -f ${type}.txt
  1486. for h in $(seq 20 -1 ${min[${type}]}); do
  1487. echo -n "${t}${h} " >> ${type}.txt
  1488. # extra space if h < 10
  1489. if [ ${h} -lt 10 ]; then
  1490. echo -n " " >> ${type}.txt
  1491. fi
  1492. for u in $(seq 2 9) T A; do
  1493. echo -n "${strategy[${t}${h},${u}]} " >> ${type}.txt
  1494. done
  1495. echo >> ${type}.txt
  1496. done
  1497. done
  1498. # echo "</tr>" >> ${type}.html
  1499. done
  1500. done
  1501. cat << EOF >> table.md
  1502. | Hand | \$n\$ | Yes [%] | No [%] |
  1503. EOF
  1504. # pairs
  1505. type="pair"
  1506. t="p"
  1507. cp pair-no.txt pair.txt
  1508. for hand in A T $(seq 9 -1 2); do
  1509. if [ "${hand}" = "A" ]; then
  1510. pair=1
  1511. elif [ "${hand}" = "T" ]; then
  1512. pair=10
  1513. else
  1514. pair=$((${hand}))
  1515. fi
  1516. # cat << EOF >> ${type}.html
  1517. # <tr>
  1518. # <td>${t}${hand}</td>
  1519. # <td>
  1520. # <div class="text-right">y<span class="d-none d-lg-inline">es</span></div>
  1521. # <div class="text-right">n<span class="d-none d-lg-inline">o</span></div>
  1522. # </td>
  1523. # EOF
  1524. for upcard in $(seq 2 9) T A; do
  1525. if [ "$upcard" = "T" ]; then
  1526. upcard_n=10
  1527. elif [ "$upcard" = "A" ]; then
  1528. upcard_n=1
  1529. else
  1530. upcard_n=$(($upcard))
  1531. fi
  1532. n=${n0} # start with n0 hands
  1533. best="x" # x means don't know what to so, so play
  1534. while [ "${best}" = "x" ]; do
  1535. # tell the user which combination we are trying and how many we will play
  1536. echo -ne "${t}${hand}-${upcard}\t\t$(printf %.0e ${n})"
  1537. for play in y n; do
  1538. # start with options.conf as a template and add some custom stuff
  1539. cp options.conf blackjack.conf
  1540. cat << EOF >> blackjack.conf
  1541. hands = ${n}
  1542. player = internal
  1543. arranged_cards = ${pair}, $((${upcard_n} + 13)), $((${pair} + 26))
  1544. report = ${t}${hand}-${upcard}-${play}.yaml
  1545. # log = ${t}${hand}-${upcard}-${play}.log
  1546. EOF
  1547. # read the current strategy
  1548. while read w p2 p3 p4 p5 p6 p7 p8 p9 pT pA; do
  1549. # w already has the "p"
  1550. strategy[${w},2]=$p2
  1551. strategy[${w},3]=$p3
  1552. strategy[${w},4]=$p4
  1553. strategy[${w},5]=$p5
  1554. strategy[${w},6]=$p6
  1555. strategy[${w},7]=$p7
  1556. strategy[${w},8]=$p8
  1557. strategy[${w},9]=$p9
  1558. strategy[${w},T]=$pT
  1559. strategy[${w},A]=$pA
  1560. done < ${type}.txt
  1561. # override the read strategy with the explicit play: y or n
  1562. strategy[${t}${hand},${upcard}]=${play}
  1563. # save the new (temporary) strategy
  1564. rm -f ${type}.txt
  1565. for h in A T $(seq 9 -1 2); do
  1566. echo -n "${t}${h} " >> ${type}.txt
  1567. for u in $(seq 2 9) T A; do
  1568. echo -n "${strategy[${t}${h},${u}]} " >> ${type}.txt
  1569. done
  1570. echo >> ${type}.txt
  1571. done
  1572. if [ "${debug}" != "0" ]; then
  1573. cp ${type}.txt ${t}${hand}-${upcard}-${play}.str
  1574. fi
  1575. # ensamble the full bs.txt
  1576. cat hard.txt soft.txt pair.txt > bs.txt
  1577. # play!
  1578. blackjack
  1579. # evaluate the results
  1580. ev[${t}${hand},${upcard},${play}]=$(grep mean ${t}${hand}-${upcard}-${play}.yaml | awk '{printf("%g", $2)}')
  1581. error[${t}${hand},${upcard},${play}]=$(grep error ${t}${hand}-${upcard}-${play}.yaml | awk '{printf("%g", $2)}')
  1582. done
  1583. # choose the best one
  1584. ev_y=$(echo ${ev[${t}${hand},${upcard},y]} | awk '{printf("%+.2f", 100*$1)}')
  1585. ev_n=$(echo ${ev[${t}${hand},${upcard},n]} | awk '{printf("%+.2f", 100*$1)}')
  1586. if [ $n -le ${n_max} ]; then
  1587. # if we still have room, take into account errors
  1588. error_y=$(echo ${error[${t}${hand},${upcard},y]} | awk '{printf("%.1f", 100*$1)}')
  1589. error_n=$(echo ${error[${t}${hand},${upcard},n]} | awk '{printf("%.1f", 100*$1)}')
  1590. else
  1591. # instead of running infinite hands, above a threshold asume errors are zero
  1592. error_y=0
  1593. error_n=0
  1594. fi
  1595. echo -ne "\t${ev_y}\t(${error_y})"
  1596. echo -ne "\t${ev_n}\t(${error_n})"
  1597. if (( $(echo ${ev_y} ${error_y} ${ev_n} ${error_n} | awk '{print (($1-$2) > ($3+$4))}') )); then
  1598. best="y"
  1599. color=${GREEN}
  1600. best_string="yes"
  1601. elif (( $(echo ${ev_n} ${error_n} ${ev_y} ${error_y} | awk '{print (($1-$2) > ($3+$4))}') )); then
  1602. best="n"
  1603. color=${RED}
  1604. best_string="no"
  1605. else
  1606. best="x"
  1607. color=${NC}
  1608. best_string="uncertain"
  1609. n=$((${n} * 4))
  1610. fi
  1611. echo -e ${color}"\t"${best_string}${NC}
  1612. done
  1613. echo "| ${t}${hand}-${upcard} | $(printf %.1e ${n}) | ${ev_y} (${error_y}) | ${ev_n} (${error_n}) | ${best_string} | " >> table.md
  1614. echo " <!-- ${upcard} -->" >> ${type}.html
  1615. echo " <td>" >> ${type}.html
  1616. echo ${ev_y} ${error_y} | awk -f html_cell.awk >> ${type}.html
  1617. echo ${ev_n} ${error_n} | awk -f html_cell.awk >> ${type}.html
  1618. echo " </td>" >> ${type}.html
  1619. strategy[${t}${hand},${upcard}]=${best}
  1620. # save the strategy again with the best strategy
  1621. rm -f ${type}.txt
  1622. for h in A T $(seq 9 -1 2); do
  1623. echo -n "${t}${h} " >> ${type}.txt
  1624. for u in $(seq 2 9) T A; do
  1625. echo -n "${strategy[${t}${h},${u}]} " >> ${type}.txt
  1626. done
  1627. echo >> ${type}.txt
  1628. done
  1629. done
  1630. done
  1631. cat header.txt hard.txt header.txt soft.txt header.txt pair.txt > bs.txt
  1632. rm -f hard.txt soft.txt pair.txt blackjack.conf
  1633. if [ "${debug}" == "0" ]; then
  1634. rm -f *.yaml
  1635. rm -f *.str
  1636. rm -f *.log
  1637. fi
  1638. @end verbatim
  1639. @bye