#!/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