Skip to content

Instantly share code, notes, and snippets.

@dabd
Created February 4, 2013 00:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dabd/4704396 to your computer and use it in GitHub Desktop.
Save dabd/4704396 to your computer and use it in GitHub Desktop.
shove, minr/shove game
let equities_file = "preflop_equities.dat"
let combos_file = "preflop_combos.dat"
let num_hands = 169
let sb_minr_range = Array.make num_hands 0.5
let sb_shove_range = Array.make num_hands 0.5
let sb_call_range = Array.make num_hands 0.5
let bb_call_range = Array.make num_hands 0.5
let bb_shove_range = Array.make num_hands 0.5
(* All equities between hand i and j *)
let pf_equities = Array.make_matrix num_hands num_hands 0.0
(* pf_combos is a matrix m where m(i,j) = #non-conflicting combos when matching i against j, i.e. how many combos of j there are after removing the conflicting cards in i.
Ex: m(0,1) = 6 because i=22 and j=32o and when matching 22 against 32o there are only 6 combos of 32o after removing the two deuces in 22. *)
let pf_combos = Array.make_matrix num_hands num_hands 0.0
let preflop_hands = [|"22";"32o";"42o";"52o";"62o";"72o";"82o";"92o";"T2o";"J2o";"Q2o";"K2o";"A2o";"32s";"33";"43o";"53o";"63o";"73o";"83o";"93o";"T3o";"J3o";"Q3o";"K3o";"A3o";"42s";"43s";"44";"54o";"64o";"74o";"84o";"94o";"T4o";"J4o";"Q4o";"K4o";"A4o";"52s";"53s";"54s";"55";"65o";"75o";"85o";"95o";"T5o";"J5o";"Q5o";"K5o";"A5o";"62s";"63s";"64s";"65s";"66";"76o";"86o";"96o";"T6o";"J6o";"Q6o";"K6o";"A6o";"72s";"73s";"74s";"75s";"76s";"77";"87o";"97o";"T7o";"J7o";"Q7o";"K7o";"A7o";"82s";"83s";"84s";"85s";"86s";"87s";"88";"98o";"T8o";"J8o";"Q8o";"K8o";"A8o";"92s";"93s";"94s";"95s";"96s";"97s";"98s";"99";"T9o";"J9o";"Q9o";"K9o";"A9o";"T2s";"T3s";"T4s";"T5s";"T6s";"T7s";"T8s";"T9s";"TT";"JTo";"QTo";"KTo";"ATo";"J2s";"J3s";"J4s";"J5s";"J6s";"J7s";"J8s";"J9s";"JTs";"JJ";"QJo";"KJo";"AJo";"Q2s";"Q3s";"Q4s";"Q5s";"Q6s";"Q7s";"Q8s";"Q9s";"QTs";"QJs";"QQ";"KQo";"AQo";"K2s";"K3s";"K4s";"K5s";"K6s";"K7s";"K8s";"K9s";"KTs";"KJs";"KQs";"KK";"AKo";"A2s";"A3s";"A4s";"A5s";"A6s";"A7s";"A8s";"A9s";"ATs";"AJs";"AQs";"AKs";"AA"|]
let read_pf_data file matrix =
let ic = open_in file in
try
for i=0 to num_hands-1 do
for j=0 to num_hands-1 do
let line = input_line ic in
matrix.(i).(j) <- float_of_string line
done
done;
close_in ic (* close the input channel *)
with e -> (* some unexpected exception occurs *)
close_in_noerr ic; (* emergency closing *)
raise e (* exit with error: files are closed but
channels are not flushed *)
;;
let print_range r =
print_string "{";
for i=0 to num_hands-1 do
print_string preflop_hands.(i);
print_string ":";
print_float r.(i);
if i < num_hands-1
then
print_string ",";
done;
print_string "}"
;;
let update_strategy range new_range iter =
let mix_factor = 1.0 /. ( (float_of_int iter) +. 1.0) in
for i=0 to num_hands-1 do
range.(i) <- mix_factor *. new_range.(i) +. (1.0 -. mix_factor) *. range.(i)
done
;;
let get_equity hand range =
let eq_sum = ref 0.0 in
let sum = ref 0.0 in
for i=0 to num_hands-1 do
eq_sum.contents <- !eq_sum +. pf_combos.(hand).(i) *. range.(i) *. pf_equities.(hand).(i);
sum.contents <- !sum +. pf_combos.(hand).(i) *. range.(i)
done;
!eq_sum /. !sum
;;
let get_frac_of_all_hands_without_conflict hand range =
let total_combos_dont_confl = ref 0.0 in
let sum = ref 0.0 in
for i=0 to num_hands-1 do
total_combos_dont_confl.contents <- !total_combos_dont_confl +. pf_combos.(hand).(i);
sum.contents <- !sum +. range.(i) *. pf_combos.(hand).(i)
done;
!sum /. !total_combos_dont_confl
;;
let get_sb_best_response new_sb_minr_range new_sb_shove_range new_sb_call_range bb_call_range bb_shove_range stack_size =
let total_ev = ref 0.0 in
for i=0 to num_hands-1 do
let ev_fold_vs_shove = stack_size -. 2.0 in
let eq_i_vs_shove_range = get_equity i bb_shove_range in
let ev_call = 2.0 *. stack_size *. eq_i_vs_shove_range in
let bb_shove_freq = get_frac_of_all_hands_without_conflict i bb_shove_range in
let ev_open_fold = stack_size -. 0.5 in
let ev_minr = (1.0 -. bb_shove_freq) *. (stack_size +. 1.0) +. bb_shove_freq *. max ev_fold_vs_shove ev_call in
let eq_i_vs_call_range = get_equity i bb_call_range in
let bb_call_freq = get_frac_of_all_hands_without_conflict i bb_call_range in
let ev_shove = bb_call_freq *. eq_i_vs_call_range *. 2.0 *. stack_size +. (1.0 -. bb_call_freq) *. (stack_size +. 1.0) in
let ev = max ev_open_fold (max ev_shove ev_minr) in
total_ev.contents <- !total_ev +. ev;
match (ev_minr > ev_shove, ev_minr > ev_open_fold, ev_shove > ev_open_fold) with
(true, true, _) ->
(* ev_minr is max *)
begin
new_sb_minr_range.(i) <- 1.0;
new_sb_shove_range.(i) <- 0.0;
if ev_call > ev_fold_vs_shove
then new_sb_call_range.(i) <- 1.0
else new_sb_call_range.(i) <- 0.0
end
| (true, false, true) -> ()
| (_, false, false) ->
(* ev_open_fold is max *)
begin
new_sb_minr_range.(i) <- 0.0;
new_sb_shove_range.(i) <- 0.0;
new_sb_call_range.(i) <- 0.0
end
| (false, _, true) ->
(* ev_shove is max *)
begin
new_sb_shove_range.(i) <- 1.0;
new_sb_minr_range.(i) <- 0.0;
new_sb_call_range.(i) <- 0.0
end
| (false, true, false) -> ()
done;
!total_ev
;;
let get_bb_best_response new_bb_shove_range new_bb_call_range sb_minr_range sb_shove_range sb_call_range stack_size =
for i=0 to num_hands-1 do
let ev_fold = stack_size -. 1.0 in
let eq_i_vs_call_range = get_equity i sb_call_range in
let sb_minr_freq = get_frac_of_all_hands_without_conflict i sb_minr_range in
let sb_call_freq = get_frac_of_all_hands_without_conflict i sb_call_range in
let ev_shove = (1.0 -. sb_call_freq /. sb_minr_freq) *. (stack_size +. 2.0) +. sb_call_freq /. sb_minr_freq *. eq_i_vs_call_range *. 2.0 *. stack_size in
let eq_i_vs_shove_range = get_equity i sb_shove_range in
(* let sb_shove_freq = get_frac_of_all_hands_without_conflict i sb_shove_range in *)
let ev_call = eq_i_vs_shove_range *. 2.0 *. stack_size in
if ev_shove > ev_fold
then
begin
new_bb_shove_range.(i) <- 1.0;
(* new_bb_call_range.(i) <- 0.0 *)
end
else new_bb_shove_range.(i) <- 0.0;
if ev_call > ev_fold
then
begin
new_bb_call_range.(i) <- 1.0;
(* new_bb_shove_range.(i) <- 0.0 *)
end
else
begin
new_bb_call_range.(i) <- 0.0;
end
done
;;
let get_num_hands_in range =
let sum = ref 0.0 in
for i=0 to num_hands-1 do
sum.contents <- !sum +. range.(i)
done;
!sum
;;
let main =
read_pf_data equities_file pf_equities;
read_pf_data combos_file pf_combos;
let stack_size = float_of_string Sys.argv.(1) in
(* epsilon value is half a bb every 100 hands.
If the difference between total EVs for the SB between iterations is less than this it stops the fictitious play *)
let epsilon = 5e-5 in
let i = ref 0 in
let prev_total_ev = ref infinity in
let total_ev = ref 0.0 in
while abs_float (!total_ev -. !prev_total_ev) >= epsilon do
incr i;
prev_total_ev.contents <- !total_ev;
(* update SB strategy *)
let new_sb_minr_range = Array.make num_hands 0.0 in
let new_sb_shove_range = Array.make num_hands 0.0 in
let new_sb_call_range = Array.make num_hands 0.0 in
total_ev.contents <- get_sb_best_response new_sb_minr_range new_sb_shove_range new_sb_call_range bb_call_range bb_shove_range stack_size;
(* Printf.printf "EV diff %f iteration %d\n" (abs_float (!total_ev -. !prev_total_ev)) !i; *)
update_strategy sb_minr_range new_sb_minr_range !i;
update_strategy sb_shove_range new_sb_shove_range !i;
update_strategy sb_call_range new_sb_call_range !i;
(* update BB strategy *)
let new_bb_shove_range = Array.make num_hands 0.0 in
let new_bb_call_range = Array.make num_hands 0.0 in
get_bb_best_response new_bb_shove_range new_bb_call_range sb_minr_range sb_shove_range sb_call_range stack_size;
update_strategy bb_shove_range new_bb_shove_range !i;
update_strategy bb_call_range new_bb_call_range !i
done;
Printf.printf "Converged minr/shove game solver after %d iterations...\n" !i;
(* print results *)
Printf.printf "SB Minr Range (%f ambiguous hands):\n" (get_num_hands_in sb_minr_range);
print_range sb_minr_range;
Printf.printf "\nSB Shove Range (%f ambiguous hands):\n" (get_num_hands_in sb_shove_range);
print_range sb_shove_range;
Printf.printf "\nSB Call Range (%f ambiguous hands):\n" (get_num_hands_in sb_call_range);
print_range sb_call_range;
Printf.printf "\nBB Shove Range (%f ambiguous hands):\n" (get_num_hands_in bb_shove_range);
print_range bb_shove_range;
Printf.printf "\nBB Call Range (%f ambiguous hands):\n" (get_num_hands_in bb_call_range);
print_range bb_call_range;
print_string "\n"
;;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment