public override ActionType GetBestAction(Game game) { ActionType a1 = primary.GetBestAction(game); ActionType a2 = secondary.GetBestAction(game); if (a1 != a2 && !IsDiff) { List<ActionEv> l1 = primary.GetActions(game); Diff = 0.0; if (l1 != null) { for (int i = 0; i < l1.Count; i++) { if (l1[i].Action == a2) { Diff = l1[0].Ev - l1[i].Ev; break; } } } IsDiff = true; } return a1; }
public override int Bet(Game game) { if (card_counter.CurrentEV > ev_cutoff) return max_bet; else return game.Rules.MinBet; }
private CardSet GetSeenCards(Game game, bool showdown) { CardSet seen_cards = new CardSet(); if (showdown) { foreach (Card card in game.DealerHand) { seen_cards.Add(card); } } else { seen_cards.Add(game.DealerHand[0]); } foreach (Hand hand in game.PlayerHandSet) { if (hand.IsSplit()) continue; foreach (Card card in hand) { seen_cards.Add(card); } } return seen_cards; }
public override int Bet(Game game) { if (cardCounter.CurrentEV > 0.0) return max_bet; else return game.Rules.MinBet; }
public static bool TakeInsurance(Game game) { int[] shoe = game.Shoe.Counts; shoe[game.DealerHand[1].PointValue - 1]++; double insurance_ev = Eval.InsuranceEv(game.Bet, shoe); if (insurance_ev >= 0.0) return true; else return false; }
public override int Bet(Game game) { // unseen tells how many cards still to come before shuffle //int unseen = 84 - (game.Rules.Decks * 52 - game.Shoe.Count); //int true_count = (int)Math.Round(((double)running_count / (double)unseen)); if (card_counter.CurrentEV > ev_cutoff) { if (betting_system != null) { return betting_system.BetSize(card_counter.CurrentEV, current_roll); } return max_bet; } else return game.Rules.MinBet; }
public static void Initialize(Game game) { HandSet playerHands = game.PlayerHandSet; List<Hand> active = new List<Hand>(); active.Add(playerHands.ActiveHand); bool allBusted = true; int numBusted = 0; foreach (Hand hand in game.PlayerHandSet) { if (!hand.Finished) { if (hand != playerHands.ActiveHand) active.Add(hand); } else { if (hand.IsBust()) { numBusted++; } else { if (!hand.IsSplit()) allBusted = false; } } } SHand[] shands = new SHand[active.Count]; for (int i = 0; i < shands.Length; i++) { shands[i] = new SHand(active[i]); } int[] shoe = game.Shoe.Counts; shoe[game.DealerHand[1].PointValue - 1]++; int upcard = game.DealerHand[0].PointValue; InitializeEvaluation(shands, shands.Length, allBusted, numBusted, upcard, shoe, game.Bet); }
public override ActionType GetBestAction(Game game) { ActionType a1 = primary.GetBestAction(game); ActionType a2 = secondary.GetBestAction(game); if (a1 != a2 && !IsDiff) { List<ActionEv> l1 = primary.GetActions(game); List<ActionEv> l2 = secondary.GetActions(game); int m = 0; if (l1 != null) m = l1.Count; if (l2 != null && l2.Count > m) m = l2.Count; Console.WriteLine("STRATEGY MISMATCH"); Console.WriteLine(); Console.WriteLine(game.ToString()); Console.WriteLine(string.Format("{0,-25} {1,-25}", primary.GetType(), secondary.GetType())); Console.WriteLine(); Console.WriteLine(string.Format("{0,-25} {1,-25}", a1, a2)); Console.WriteLine(); for (int i = 0; i < m; i++) { ActionEv e1 = new ActionEv(), e2 = new ActionEv(); if (l1 != null && i < l1.Count) e1 = l1[i]; if (l2 != null && i < l2.Count) e2 = l2[i]; Console.WriteLine(string.Format("{0,-25} {1,-25}", e1, e2)); } Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); } return a1; }
public override List<ActionEv> GetActions(Game game) { List<ActionType> allowed_actions = new List<ActionType>(); if (game.IsValidAction(ActionType.Stand)) allowed_actions.Add(ActionType.Stand); if (game.IsValidAction(ActionType.Hit)) allowed_actions.Add(ActionType.Hit); if (game.IsValidAction(ActionType.Double)) allowed_actions.Add(ActionType.Double); if (game.IsValidAction(ActionType.Split)) allowed_actions.Add(ActionType.Split); if (game.IsValidAction(ActionType.Surrender)) allowed_actions.Add(ActionType.Surrender); CardSet some_cards = new CardSet(); //Hand active_hand = game.PlayerHandSet.ActiveHand; List<CardSet> player_hands = new List<CardSet>(); foreach (Hand hand in game.PlayerHandSet) { player_hands.Add(hand.Cards); } return agent.GetActions(GetSeenCards(game, false), game.DealerHand[0], player_hands.ToArray(), game.PlayerHandSet.ActiveIndex, allowed_actions); }
public override List<ActionEv> GetActions(Game game) { SuperEval.Initialize(game); int split_card = game.PlayerHandSet.ActiveHand[0].PointValue; List<ActionEv> actions = new List<ActionEv>(); if (game.IsValidAction(ActionType.Stand)) actions.Add(new ActionEv() { Action = ActionType.Stand, Ev = SuperEval.StandEv() }); if (game.IsValidAction(ActionType.Hit)) actions.Add(new ActionEv() { Action = ActionType.Hit, Ev = SuperEval.HitEv() }); if (game.IsValidAction(ActionType.Double)) actions.Add(new ActionEv() { Action = ActionType.Double, Ev = SuperEval.DoubleEv() }); if (game.IsValidAction(ActionType.Surrender)) actions.Add(new ActionEv() { Action = ActionType.Surrender, Ev = SuperEval.SurrenderEv() }); if (game.IsValidAction(ActionType.Split)) actions.Add(new ActionEv() { Action = ActionType.Split, Ev = SuperEval.SplitEv(split_card, game.Rules.Splits - game.SplitCount) }); actions.Sort(delegate(ActionEv ae1, ActionEv ae2) { return ae2.Ev.CompareTo(ae1.Ev); }); return actions; }
// should +ev in some cases, study // insurance should be taken when probability of dealer having // blackjack is greater than 1/3 (0.3333333%), i guess because // of how the payoff goes public override bool TakeInsurance(Game game) { // the number of seen tens int tens_count = card_counter[10]; // check if newly dealt player hand has tens and add them to the count if (game.PlayerHandSet.ActiveHand[0].IsTenValue()) tens_count++; if (game.PlayerHandSet.ActiveHand[1].IsTenValue()) tens_count++; // switch to number of tens still in shoe tens_count = game.Rules.Decks * 4 * 4 - tens_count; // the +1 comes from the dealer's unknown which has been removed from the shoe if (((double)tens_count / (double)(game.Shoe.Count + 1)) + pp_multiplier * 0.0002 > (1.0 / 3.0)) return true; return false; }
public override void Showdown(Game game) { // update count foreach (Card card in game.DealerHand) { card_counter.RemoveCard(card.PointValue); } foreach (Hand hand in game.PlayerHandSet) { if (hand.IsSplit()) continue; foreach (Card card in hand) { card_counter.RemoveCard(card.PointValue); } } }
public override void ResetShoe(Game game) { card_counter.Reset(); }
public override bool TakeInsurance(Game game) { return false; }
public override ActionType GetBestAction(Game game) { List<ActionEv> actions = GetActions(game); return actions[0].Action; }
// ask for a bet amount in the beginning of the round public override int Bet(Game game) { return primary.Bet(game); }
static void TestSuper() { Random random = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; SuperOptStrategy b = new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier); //PseudoOptStrategy b = new PseudoOptStrategy(); Game game = new Game(rules, b, pp_multiplier, random); game.PlayerMoney = 0; double expected_money = (double)game.PlayerMoney; game.Bet = 100; // 1$ int lowest = game.PlayerMoney, highest = game.PlayerMoney; int runs = 0; while (true) { double total_money = (game.PlayerMoney + pp_multiplier * game.PartyPoints) / 100.0; if (runs % 10000 == 0) { Console.WriteLine("runs: " + runs + " win: " + (double)game.PlayerMoney / 100.0 + "$" + " pp: " + game.party_points); Console.WriteLine("lowest: " + (double)lowest / 100.0 + "$" + " highest: " + (double)highest / 100.0 + "$"); Console.WriteLine("total: " + total_money + "$ | expected: " + expected_money / 100.0 + "$"); Console.WriteLine(); } game.StartRound(); game.DealRound(); expected_money += b.ShoeEV() * game.Bet; if (game.PlayerMoney < lowest) lowest = game.PlayerMoney; if (game.PlayerMoney > highest) highest = game.PlayerMoney; runs++; } }
public override int Bet(Game game) { return game.Rules.MinBet; }
public override void ResetShoe(Game game) { primary.ResetShoe(game); secondary.ResetShoe(game); }
public override List<ActionEv> GetActions(Game game) { List<ActionEv> actions = new List<ActionEv>(); int[] shoe = game.Shoe.Counts; /*int[] test = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int test_count = 0; foreach (Card card in game.Shoe) { test[card.PointValue - 1]++; test_count++; } for (int i = 0; i < 10; i++) { if (test[i] != shoe[i]) { Console.Write(game.Shoe.Count + "| "); for (int j = 0; j < 10; j++) Console.Write(shoe[j] + " "); Console.WriteLine(); Console.Write(test_count + "| "); for (int j = 0; j < 10; j++) Console.Write(test[j] + " "); Console.WriteLine(); Console.ReadLine(); break; } }*/ shoe[game.DealerHand[1].PointValue - 1]++; SHand shand; int soft_total = game.PlayerHandSet.ActiveHand.SoftTotal(); if (soft_total <= 21 && game.PlayerHandSet.ActiveHand.HasAce()) { shand.Total = soft_total; shand.Soft = true; } else { shand.Total = game.PlayerHandSet.ActiveHand.HardTotal(); shand.Soft = false; } int upcard = game.DealerHand[0].PointValue; int split_card = game.PlayerHandSet.ActiveHand[0].PointValue; BjEval.Eval.CacheDealerProbs(upcard, shoe); /* for (int i = 0; i < 10; i++) Console.Write(shoe[i] + " "); Console.WriteLine(); Console.WriteLine("SHand: " + shand.Total + " soft=" + shand.Soft); */ if (game.IsValidAction(ActionType.Stand)) actions.Add(new ActionEv() { Action = ActionType.Stand, Ev = BjEval.Eval.StandEv(shand, upcard, shoe) }); if (game.IsValidAction(ActionType.Hit)) actions.Add(new ActionEv() { Action = ActionType.Hit, Ev = BjEval.Eval.HitEv(shand, upcard, shoe) }); if (game.IsValidAction(ActionType.Double)) actions.Add(new ActionEv() { Action = ActionType.Double, Ev = BjEval.Eval.DoubleEv(shand, upcard, max_bet, shoe) }); if (game.IsValidAction(ActionType.Surrender)) actions.Add(new ActionEv() { Action = ActionType.Surrender, Ev = BjEval.Eval.SurrenderEv() }); if (game.IsValidAction(ActionType.Split)) actions.Add(new ActionEv() { Action = ActionType.Split, Ev = BjEval.Eval.SplitEv(split_card, upcard, max_bet, game.Rules.Splits - game.SplitCount, shoe) }); actions.Sort(delegate(ActionEv ae1, ActionEv ae2) { return ae2.Ev.CompareTo(ae1.Ev); }); return actions; }
public override bool TakeInsurance(Game game) { return SuperEval.TakeInsurance(game); }
public override bool TakeInsurance(Game game) { int[] shoe = game.Shoe.Counts; shoe[game.DealerHand[1].PointValue - 1]++; double insurance_ev = Eval.InsuranceEv(max_bet, shoe); if (insurance_ev >= 0.0) return true; else return false; /* // remember the unseen dealt second dealer card, which is still reduced from shoe! // take into account int seen_tens = card_counts[9]; if (game.PlayerHandSet.ActiveHand[0].IsTenValue()) seen_tens++; if (game.PlayerHandSet.ActiveHand[1].IsTenValue()) seen_tens++; // add the dealer's second dealt card to unknown count (+1) double bj_prob = (double)(8*4*4-seen_tens) / (double)(game.Shoe.Count + 1); double insurance_ev = 1.0*bj_prob-0.5*(1.0-bj_prob); // we take insurance if (insurance_ev >= 0.0) return true; else return false;*/ }
public override ActionType GetBestAction(Game game) { /*Console.WriteLine("upcard: " + upcard + " hand: " + game.PlayerHandSet.ActiveHand); foreach (ActionEv ae in actions) Console.WriteLine(ae.Action + " " + ae.Ev); Console.ReadLine();*/ List<ActionEv> actions = GetActions(game); return actions[0].Action; }
public override ActionType GetBestAction(Game game) { List<ActionEv> actions = Evaluate(game.Upcard(), game.PlayerHandSet.ActiveHand); foreach (ActionEv ae in actions) { if (game.IsValidAction(ae.Action)) return ae.Action; else { //Console.WriteLine("OMGGG " + ae.Action); } } Console.WriteLine("BIG FUCCCCKKK"); return ActionType.Split; }
public override bool TakeInsurance(Game game) { bool take1 = primary.TakeInsurance(game); bool take2 = secondary.TakeInsurance(game); if (take1 != take2) { Console.WriteLine("Insurance mismatch: " + take1 + " <> " + take2); Console.WriteLine(game.ToString()); } return take1; }
/* static void PrintGameState(Game game) { double total_money = (game.PlayerMoney + pp_multiplier * game.PartyPoints) / 100.0; Console.WriteLine("runs: " + runs + " win: " + (double)game.PlayerMoney / 100.0 + "$" + " pp: " + game.party_points); Console.WriteLine("total: " + total_money + "$ | expected: " + expected_money / 100.0 + "$"); Console.WriteLine(); }*/ static double TotalMoney(Game game) { double total_money = (game.PlayerMoney + game.TotalPartyPoints) / 100.0; return total_money; }
static void CompareStrategies2() { Random masterRandom = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; SuperOptStrategy b1 = new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier); OptStrategy b2 = new OptStrategy(max_bet, ev_cutoff, pp_multiplier); BasicStrategy b3 = new BasicStrategy(max_bet, ev_cutoff, pp_multiplier); Game game1 = new Game(rules, b1, pp_multiplier, new NPack.MersenneTwister()); Game game2 = new Game(rules, b2, pp_multiplier, new NPack.MersenneTwister()); Game game3 = new Game(rules, b3, pp_multiplier, new NPack.MersenneTwister()); int runs = 0; double expected = 0; while (true) { if (runs % 10000 == 0) { double total1 = TotalMoney(game1); double total2 = TotalMoney(game2); double total3 = TotalMoney(game3); Console.WriteLine(); Console.WriteLine("Runs: {0}", runs); Console.WriteLine("Expected total: $ {0:0.00}", expected); Console.WriteLine("SuperOpt total: $ {1:0.00} ({2:0.00} c/hand)", b1.GetType(), total1, total1 * 100.0 / (double)runs); Console.WriteLine("Opt total: $ {1:0.00} ({2:0.00} c/hand)", b2.GetType(), total2, total2 * 100.0 / (double)runs); Console.WriteLine("Basic total: $ {1:0.00} ({2:0.00} c/hand)", b3.GetType(), total3, total3 * 100.0 / (double)runs); TextWriter writer = new StreamWriter("compare.txt", true); writer.WriteLine(string.Format("{0} {1} {2} {3} {4}", runs, expected, total1, total2, total3)); writer.Close(); } int seed = masterRandom.Next(); game1.Random = new NPack.MersenneTwister(seed); game2.Random = new NPack.MersenneTwister(seed); game3.Random = new NPack.MersenneTwister(seed); game1.ResetShoe(); game2.ResetShoe(); game3.ResetShoe(); int remove_count = masterRandom.Next(84); game1.RemoveCards(remove_count); game2.RemoveCards(remove_count); game3.RemoveCards(remove_count); expected += b1.ShoeEV() * b1.Bet(game1) / 100.0; game1.StartRound(); game2.StartRound(); game3.StartRound(); game1.DealRound(); game2.DealRound(); game3.DealRound(); runs++; } }
static void CompareStrategies() { Random masterRandom = new NPack.MersenneTwister(); Random random1 = new NPack.MersenneTwister(); Random random2 = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; DiffStrategy b1 = new DiffStrategy( new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier), new OptStrategy(max_bet, ev_cutoff, pp_multiplier) ); OptStrategy b2 = new OptStrategy(max_bet, ev_cutoff, pp_multiplier); Game game1 = new Game(rules, b1, pp_multiplier, random1); Game game2 = new Game(rules, b2, pp_multiplier, random2); int runs = 0; double expected = 0; double expected_diff = 0; int diff_count = 0; while (true) { if (runs % 1000 == 0) { double total1 = TotalMoney(game1); double total2 = TotalMoney(game2); Console.WriteLine(); Console.WriteLine("Runs: {0}", runs); Console.WriteLine("Expected total: $ {0:0.00}", expected); Console.WriteLine("SuperOpt total: $ {1:0.00} ({2:0.00} c/hand)", b1.GetType(), total1, total1 * 100.0 / (double)runs); Console.WriteLine("Opt total: $ {1:0.00} ({2:0.00} c/hand)", b2.GetType(), total2, total2 * 100.0 / (double)runs); Console.WriteLine("Different choices: {0:0} ({1:0.00}%)", diff_count, 100.0 * diff_count / (double)runs); Console.WriteLine("Difference: $ {0:0.00}", total1 - total2); Console.WriteLine("Expected difference: $ {0:0.00}", expected_diff); TextWriter writer = new StreamWriter("compare.txt", true); writer.WriteLine(string.Format("{0} {1} {2} {3}", runs, expected, TotalMoney(game1), TotalMoney(game2))); writer.Close(); } int seed = masterRandom.Next(); game1.Random = new NPack.MersenneTwister(seed); game2.Random = new NPack.MersenneTwister(seed); game1.ResetShoe(); game2.ResetShoe(); int remove_count = masterRandom.Next(84); game1.RemoveCards(remove_count); game2.RemoveCards(remove_count); expected += b1.ShoeEV() * b1.Bet(game1) / 100.0; game1.StartRound(); game2.StartRound(); game1.DealRound(); game2.DealRound(); if (b1.IsDiff) { expected_diff += game1.Bet * b1.Diff / 100.0; diff_count++; b1.IsDiff = false; } runs++; } }
// called when the round has ended public override void Showdown(Game game) { primary.Showdown(game); secondary.Showdown(game); }
static void MakeTestRun(int run_number, Random random, int targetRuns, double ev_cutoff, BettingSystem betting_system, ResetSystem reset) { Console.WriteLine(run_number + " - EV cutoff " + ev_cutoff + " " + betting_system); TextWriter deal_file = new StreamWriter(string.Format("expected{0}.txt", run_number)); TextWriter roll_file = new StreamWriter(string.Format("roll{0}.txt", run_number)); double pp_multiplier = 0; Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; //OptStrategy b = new OptStrategy(10000, ev_cutoff, pp_multiplier); BasicStrategy b = new BasicStrategy(20000, ev_cutoff, pp_multiplier, betting_system); Game game = new Game(rules, b, pp_multiplier, random); int start_roll = 20000 * 100; //game.PlayerMoney = 10000000; // 100000$ game.PlayerMoney = start_roll; double expected_money = (double)game.PlayerMoney; game.Bet = 100; // 1$ double lowest = TotalMoney(game), highest = TotalMoney(game); int runs = 0; double total_big_bet_ev = 0; double total_big_bet = 0; int num_big_bets = 0; int resets = 0; int reset_counter = 0; bool written_200k = false; while (true) { double total_money = TotalMoney(game); if (total_money < lowest) lowest = total_money; if (total_money > highest) highest = total_money; if (runs % 5000 == 0) { Console.WriteLine(runs + " " + (double)game.PlayerMoney / 100.0 + "$" + " pp: " + game.PartyPoints + " expected: " + expected_money / 100.0 + "$"); Console.WriteLine("lowest: " + (double)lowest + "$" + " highest: " + (double)highest + "$"); Console.WriteLine("Total: ${0}", game.PlayerMoney/100.0); Console.WriteLine("Expected: ${0}", expected_money/100.0); /*Console.WriteLine("Average big bet: {0:0.00} ({1:0.0000})", (total_big_bet / 100.0) / num_big_bets, (total_big_bet_ev / 100.0) / num_big_bets); Console.WriteLine("Resets {0} ({1:0.000}%)", resets, resets / (double)runs); */ Console.WriteLine(); } if (game.PlayerMoney <= 0) { deal_file.WriteLine(expected_money / 100.0); roll_file.WriteLine(game.PlayerMoney / 100.0); Write200kResult(0); WriteFinalResult(0); break; } if (runs % 1000 == 0) { //file.WriteLine(string.Format("{0} {1} {2} {3} {4} {5}", runs, game.PlayerMoney / 100.0, game.PartyPoints, total_money, lowest, highest)); deal_file.WriteLine(expected_money / 100.0); roll_file.WriteLine(game.PlayerMoney / 100.0); if (runs >= targetRuns) { if (!written_200k) { Write200kResult(game.PlayerMoney / 100.0); written_200k = true; } if (game.PlayerMoney >= start_roll) { WriteFinalResult(game.PlayerMoney / 100.0); break; } } //if (game.party_points >= 20000) break; } if (reset_counter > 0) { reset_counter--; runs++; continue; } if (reset!=null && reset.Reset(52 * game.Rules.Decks - game.Shoe.Count, b.ShoeEV())) { resets++; runs++; reset_counter = 1; game.ResetShoe(); continue; } b.CurrentRoll = game.PlayerMoney; Shoe shoe = new Shoe(8); shoe.Clear(); shoe.Add(game.Shoe); game.StartRound(); game.DealRound(); Card p1 = game.PlayerHandSet[0][0], p2 = game.PlayerHandSet[0][1], d = game.DealerHand[0]; shoe.Remove(p1); shoe.Remove(p2); shoe.Remove(d); BjEval.Eval.CacheDealerProbs(d.PointValue, shoe.ToArray()); double deal_ev = BjEval.Eval.DealEv( p1.PointValue, p2.PointValue, d.PointValue, shoe.ToArray(), game.Bet); //Console.WriteLine("EV: {0} {1} {2} {3} {4}", p1.PointValue, p2.PointValue, d.PointValue, shoe.CardCount, deal_ev); expected_money += deal_ev * game.Bet; if (game.Bet > 100) { total_big_bet += game.Bet; total_big_bet_ev += game.Bet * deal_ev; num_big_bets++; } runs++; } deal_file.Close(); roll_file.Close(); b.Stop(); }