public War() { InitializeComponent(); OverallStats = new GameStats(); num_iterations.Maximum = long.MaxValue; num_threads.Value = num_threads.Maximum = Environment.ProcessorCount; cb_dealfirst.Items.Add("Player"); cb_dealfirst.Items.Add("Computer"); cb_dealfirst.Items.Add("Every Other"); cb_dealfirst.Items.Add("Random"); // Select every other by default cb_dealfirst.SelectedIndex = 2; }
public void AddToStats(GameStats s) { Start = s.Time; this.ComputerWeight += s.ComputerWeight; this.ComputerWins += s.ComputerWins; this.CorrectPred += s.CorrectPred; this.Draws += s.Draws; this.PlayerWeight += s.PlayerWeight; this.PlayerWins += s.PlayerWins; this.Turns += s.Turns; }
// War Game Functions //---------------------------------------------------------------------------------------------------------- private static void RunGame(GameStats g, List<Deck> CardDeck, Queue<Deck> PlayerDeck, Queue<Deck> ComputerDeck, bool FastShuffle, bool DealFirst) { if (FastShuffle) CardDeck.FastShuffle(); else CardDeck.Shuffle(); DealCards(PlayerDeck, ComputerDeck, CardDeck, DealFirst); // Calculate hand weight for each player foreach (Deck c in PlayerDeck) g.PlayerWeight += c.Value - 8; foreach (Deck c in ComputerDeck) g.ComputerWeight += c.Value - 8; // Create temporary deck to store cards in List<Deck> Temp = new List<Deck>(); // Main game loop ulong turns = 0; while (PlayerDeck.Count > 0 && ComputerDeck.Count > 0) { turns++; // Grab a card from each player Deck PlayerCard = PlayerDeck.Dequeue(); Deck ComputerCard = ComputerDeck.Dequeue(); Temp.Add(PlayerCard); Temp.Add(ComputerCard); // Check to see who's card has a higher value if (PlayerCard.Value > ComputerCard.Value) CombineDecks(PlayerDeck, Temp); else if (ComputerCard.Value > PlayerCard.Value) CombineDecks(ComputerDeck, Temp); else // tie TieBreaker(PlayerDeck, ComputerDeck, Temp); Temp.Clear(); } if (PlayerDeck.Count == 0 && ComputerDeck.Count == 0) // There was a tie for every card! g.Draws++; else if (ComputerDeck.Count == 0) g.PlayerWins++; else g.ComputerWins++; g.Turns += turns; }
// Threading functions //---------------------------------------------------------------------------------------------------------- private void WarWorker_DoWork(object sender, DoWorkEventArgs e) { // Reset progress Progress = 0; // Start stopwatch LastUpdated.Start(); // Record when the operation started DateTime Start = DateTime.Now; // Fetch the arguments array List<object> Args = (List<object>)e.Argument; // Get the number of threads int WarThreads = (int)Args[4]; // Calculate the workload for each thread long[] workload = new long[WarThreads]; long total = (long)Args[0]; long extra = total % WarThreads; long perIteration = (total - extra) / WarThreads; for(int i = 0; i < WarThreads; i++) { if (extra > 0) { workload[i] = perIteration + 1; extra--; } else workload[i] = perIteration; } // Start a parallel loop for each thread Parallel.For(0, WarThreads, i => { GameStats stat = new GameStats(Start); // Create decks for each player, plus a deck to draw cards from List<Deck> CardDeck = new List<Deck>(); Queue<Deck> PlayerDeck = new Queue<Deck>(); Queue<Deck> ComputerDeck = new Queue<Deck>(); // Pick who to deal cards to first int dealFirst = (int)Args[1]; bool deal = Convert.ToBoolean(dealFirst); // Add cards to the main deck PopulateDeck(CardDeck, (bool)Args[3]); long j = 0; while (j < workload[i] && !WarWorker.CancellationPending) { // Determine who to deal if random or every other was choosen if (dealFirst == 2) deal = !deal; else if (dealFirst == 3) deal = Convert.ToBoolean(ThreadSafeRandom.ThisThreadsRandom.Next(0, 2)); RunGame(stat, CardDeck, PlayerDeck, ComputerDeck, (bool)Args[2], deal); PlayerDeck.Clear(); ComputerDeck.Clear(); j++; if (j % 100 == 0) UpdateProgress(100); } if (!WarWorker.CancellationPending) Finish(stat); return; }); if (WarWorker.CancellationPending) e.Cancel = true; }
// Stats //---------------------------------------------------------------------------------------------------------- private void UpdateStats(GameStats stats) { if (stats.Total < 1) return; double PlayerAvg = (double)stats.PlayerWins / stats.Total * 100.0; double ComputerAvg = (double)stats.ComputerWins / stats.Total * 100.0; double DrawAvg = (double)stats.Draws / stats.Total * 100.0; double PredictAvg = (double)stats.CorrectPred / stats.Total * 100.0; double avgturns = stats.Turns / stats.Total; // Update labels lbl_cwin_val.Text = String.Format("{0} ({1:0.###}%)", stats.ComputerWins, ComputerAvg); lbl_pwins_val.Text = String.Format("{0} ({1:0.###}%)", stats.PlayerWins, PlayerAvg); lbl_draws_val.Text = String.Format("{0} ({1:0.###}%)", stats.Draws, DrawAvg); lbl_compweight_val.Text = String.Format("{0:0.##}", (double)stats.ComputerWeight / stats.Total); lbl_playerweight_val.Text = String.Format("{0:0.##}", (double)stats.PlayerWeight / stats.Total); lbl_winnerweight_val.Text = String.Format("{0:0.#}%", PredictAvg); lbl_sims_val.Text = String.Format("{0}", stats.Total); lbl_turns_val.Text = String.Format("{0:0}", avgturns); lbl_gametime_val.Text = String.Format("{0:0} µs", gameTime.TotalMilliseconds * 1000 / stats.Total); }
private void Finish(GameStats s) { if (InvokeRequired) { BeginInvoke(new Action<GameStats>(Finish), new object[] { s }); return; } OverallStats.AddToStats(s); }