Created
February 4, 2013 00:35
-
-
Save dabd/4704396 to your computer and use it in GitHub Desktop.
shove, minr/shove game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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