public WelcomeForm() { InitializeComponent(); UIConfig.FindImgFolder(5); playerInput1.Color = PlayerColor.red; playerInput2.Color = PlayerColor.green; playerInput3.Color = PlayerColor.blue; playerInput4.Color = PlayerColor.yellow; playerInputs[0] = playerInput1; playerInputs[1] = playerInput2; playerInputs[2] = playerInput3; playerInputs[3] = playerInput4; foreach (PlayerInput playerInput in playerInputs) { playerInput.AddDefaultAI(typeof(TestAI)); playerInput.AddAI(typeof(MCTSAI)); playerInput.AddAI(typeof(EvolutionA)); playerInput.AddAI(typeof(EvolutionB)); playerInput.AddAI(typeof(MCTSIR)); } }
public async Task PlayAsync(IAction action, System.Action endGame, System.Action redraw = null) { Move(action); redraw?.Invoke(); IPlayer currentAIPlayer; int week, year; while (!AreAllPlayersDone() && ActivePlayer is IAIPlayer) { // save info to check for faulty AI week = ActivePlayer.Time.CurrentWeek; year = ActivePlayer.Time.CurrentYear; currentAIPlayer = ActivePlayer; action = await Task.Run(() => ((IAIPlayer)ActivePlayer).AI.TakeAction(this)); Move(action); //check for broken AI infinite loop if (ActivePlayer == currentAIPlayer && ActivePlayer.Time.CurrentWeek == week && ActivePlayer.Time.CurrentYear == year && !(action is ZeppelinAction)) { UIConfig.ErrorDialog("It looks like the AI is trying to make an invalid move. You can try to let it decide again, but if it's deterministic you'll probably have to end the game."); } redraw?.Invoke(); } if (AreAllPlayersDone()) { endGame?.Invoke(); } }
/// <summary> /// Loads the game from file specified by tbFilePath.Text and starts it /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void bStartLoaded_Click(object sender, EventArgs e) { string filePath = tbFilePath.Text; IUIGame game; try { game = GameState.Deserialize(filePath); } catch (Exception exception) { UIConfig.ErrorDialog("Error loading the game from file:\n" + exception.Message); return; } this.Hide(); GameForm gameForm = new GameForm(game); gameForm.ShowDialog(); this.Close(); }
/// <summary> /// Opens file browser and then saves the current game state /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void bSaveGame_Click(object sender, EventArgs e) { //open file browser SaveFileDialog sfd = new SaveFileDialog() { Filter = "THB | *.thb", RestoreDirectory = true }; if (sfd.ShowDialog() == DialogResult.OK) { try { GameState.Serialize(game, sfd.FileName); MessageBox.Show("Game state successfully saved"); } catch (Exception exception) { UIConfig.ErrorDialog("Error saving the game state:\n" + exception.Message); return; } } }
/// <summary> /// Starts a new game with the player data from this form. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void bStartNew_Click(object sender, EventArgs e) { // check player count int playerCount; if ((playerCount = GetPlayerCount()) < 2 || playerCount > 4) { MessageBox.Show("Unsupported number of players"); return; } // load config file (.thc) try { GameSettings.LoadFromFile(@"thebes_config.thc"); } catch (Exception exception) { if (exception is FileNotFoundException) { UIConfig.ErrorDialog("File not found error:\n" + exception.Message); } else if (exception is FormatException) { UIConfig.ErrorDialog("Error processing the config file:\n" + exception.Message); } else { UIConfig.ErrorDialog("Unknown error reading the config file:\n" + exception.Message); } return; } // check for invalid namess if (AnyInvalidNames()) { MessageBox.Show("Each player has to have a distinct name"); return; } UIGame game = new UIGame(playerCount); // Create Players Dictionary <IPlayer, PlayerColor> players = new Dictionary <IPlayer, PlayerColor>(); Player player; foreach (PlayerInput playerInput in playerInputs) { if (playerInput.Selected()) { if (playerInput.IsHuman()) { player = new Player( playerInput.PlayerName(), GameSettings.Places.OfType <IDigSite>().ToList(), GameSettings.StartingPlace, UIConfig.ErrorDialog, game.AvailableCards.ChangeDisplayedCards, game.AvailableCards.GiveCard, game.Deck.Discard, game.ActiveExhibitions.GiveExhibition, game.DrawTokens, game.PlayersOnWeek ); } else { player = new AIPlayer( playerInput.PlayerName(), GameSettings.Places.OfType <IDigSite>().ToList(), GameSettings.StartingPlace, GameSettings.Places, UIConfig.ErrorDialog, game.AvailableCards.ChangeDisplayedCards, game.AvailableCards.GiveCard, game.Deck.Discard, game.ActiveExhibitions.GiveExhibition, game.DrawTokens, game.PlayersOnWeek ); IAI ai = (IAI)playerInput.Type.Assembly.CreateInstance(playerInput.Type.FullName, false, 0, null, new object[] { playerCount }, null, null); ((AIPlayer)player).Init(ai); } players.Add(player, playerInput.Color); } } // initialize game try { game.Initialize(players); } catch (Exception exception) { UIConfig.ErrorDialog("Error initializing the game:\n" + exception.Message); return; } // open game form this.Hide(); GameForm gameForm = new GameForm(game); gameForm.ShowDialog(); this.Close(); }
/// <summary> /// Called after every action. Redraws the board with current data /// </summary> public void UpdateBoard() { // zeppelin button if (game.ActivePlayer.Zeppelins > 0 && !(game.ActivePlayer is IAIPlayer)) { cbUseZeppelin.Checked = false; cbUseZeppelin.Visible = true; } else { cbUseZeppelin.Visible = false; } // player displays foreach (PlayerDisplay playerDisplay in playerDisplays) { playerDisplay.UpdateInfo(); } // display cards for (int i = 0; i < displayCards.Length; i++) { UIConfig.ReplaceImage(displayCards[i], GetImage(game.DisplayedCards[i])); cardToolTips[i].SetToolTip(displayCards[i], game.DisplayedCards[i]?.Description); } // exhibitions for (int i = 0; i < exhibitions.Length; i++) { if (game.DisplayedExhibitions[i] != null) { UIConfig.ReplaceImage(exhibitions[i], GetImage(game.DisplayedExhibitions[i])); exhibitionToolTips[i].SetToolTip(exhibitions[i], game.DisplayedExhibitions[i].Description); } else { UIConfig.RemoveImage(exhibitions[i]); } } // week counter foreach (KeyValuePair <IPlayer, TransparentPictureBox> player_pb in smallPieces.OrderByDescending(kvp => kvp.Key)) { player_pb.Value.Location = layout.WeekCounter[player_pb.Key.Time.CurrentWeek - 1].RectanglePositionCenter(player_pb.Value.Width, player_pb.Value.Height); player_pb.Value.Top -= 10 * (player_pb.Key.Time.SameWeekOrder - 1); player_pb.Value.BringToFront(); } //bonus tokens foreach (KeyValuePair <IDigSite, TransparentPictureBox> kvp in bonusTokens) { if (game.BonusTokens[kvp.Key] == null) { if (pBoard.Controls.Contains(kvp.Value)) { pBoard.Controls.Remove(kvp.Value); } } } // player pieces int offset = 0; foreach (KeyValuePair <IPlayer, TransparentPictureBox> player_pb in bigPieces) { player_pb.Value.Location = layout.Places[player_pb.Key.CurrentPlace.Name].RectanglePositionCenter(player_pb.Value.Width, player_pb.Value.Height); player_pb.Value.Left += offset; offset += 20; } // year counter int index = (game.ActivePlayer.Time.CurrentYear % 10) - 1; if (index > 2) { index = 2; } yearCounter.Location = layout.YearCounter[index].RectanglePositionCenter(yearCounter.Width, yearCounter.Height); // grey out buttons if (game.ActivePlayer is IAIPlayer) { bEndYear.Enabled = false; } else { bEndYear.Enabled = true; } this.Refresh(); }