public void GameOver(Game game) { string line = "Final game status:".li(); AddDetailEvent(line); line = game.ListPlayersForSummary(); AddDetailEvent(line); WriteFiles(Path.Combine(Program.BaseDir, DateTime.Now.ToString("yyyy-MM-dd") + " - " + game.Title)); }
public void Cancel(Player player, Action action, Game game) { if (game.IsOverlord(player)) { gameLog.Info("Cancelling " + game); RemoveGame(game); Gmail.MessagePlayer(player, game, game.Title + " has been cancelled."); } }
/// <summary> /// Converts a given line to an <see cref="Action"/> of type actionType. /// </summary> /// <param name="line"></param> /// <param name="actionType"></param> /// <param name="actionText"></param> /// <returns></returns> public Action StringToAction(string line, GameSystem.ActionEnum actionType, string actionText, Game game) { string param = line.GetTextAfter(actionText).Trim(); Player target = null; if (game != null) target = game.GetPlayer(param, ""); Action action = new Action(actionType); if (target == null) action.Text = param; else action.Target = target; return action; }
public void NewCycle(Game game) { string line = game.FullTitle + " has begun."; AddEvent(line.li()); line = "<ul>"; AddEvent(line); line = "Players:".li(); AddDetailEvent(line); line = game.ListPlayersForSummary(); AddDetailEvent(line); }
private void DoDayVotes(Game game) { Player candidate = (Player)game.GetLivingPlayers().PickOne(); foreach (Player p in game.GetLivingPlayers()) { SendAction(game, p, candidate, "vote"); while (p.MyAction == null && game.IsInProgress && game.ActiveCycle == Game.Cycle.Day) { Player newCandidate = (Player)game.GetLivingPlayers().PickOne(); SendAction(game, p, newCandidate, "vote"); } } }
/// <summary> /// Ensures the minimum team composition doesn't exceed 100%. /// </summary> private bool validateTeamComposition(Game game) { int totalPercent = 0; foreach (Team t in game.GetTeamsPlayingUnique()) { totalPercent += t.MinPercentage; } if (totalPercent > 100) { throw new System.Exception("Minimum team composition required can be greater than 100%"); } return true; }
/// <summary> /// Validates no more than the maximum percentage is made of the given role. Even if the maximum is less than or = 1, 1 player of any role is allowed. /// </summary> /// <param name="game"></param> /// <returns></returns> private bool ValidateRoleMaxPercentage(Game game) { foreach (Role r in game.GetPlayingRoles()) { int count = 0; foreach (Player p in game.Players) { if (p.Role.Equals(r)) count++; } int maxPercent = MathX.Percent(game.Players.Count, r.MaxPercentage); if (count > maxPercent && count > 1) { return false; } } return true; }
public void GameGenerationTest() { for (int tests = 0; tests < 100; tests++) { for (int i = 3; i < 25; i = i + 3) { List<Player> players = TestX.GenListOfPlayers(i); Game game = new Game(gameSystem.GetNextGameId(), players[0]); Assert.IsTrue(validateTeamComposition(game)); for (int j = 1; j < players.Count; j++) { game.AddPlayer(players[j]); } List<Type> roleTypes = gameSystem.GetRoleTypes(); game.Start(); Assert.IsTrue(ValidateRoleMaxPercentage(game)); Assert.IsTrue(ValidateTeamMinPercent(game)); } } }
public void GameOverTest() { for (int tests = 0; tests < 1; tests++) { for (int i = 3; i < 15; i = i + 3) { List<Player> players = TestX.GenListOfPlayers(i); Game game = new Game(gameSystem.GetNextGameId(), players[0]); for (int j = 1; j < players.Count; j++) { game.AddPlayer(players[j]); } Assert.IsTrue(game.Start()); while (!game.IsGameOver()) { KillNextPlayer(players); } } } }
/// <summary> /// Processes all actions in the message, calls <see cref="ParseActions(SimpleMessage)"/> to get a list of valid actions. /// Passes each action to <see cref="GameSystem.PerformAction(Game, Player, Action)"/>. /// </summary> /// <param name="message">The message to process</param> /// <param name="game">The game the player is playing in</param> /// <seealso cref="ParseActions(SimpleMessage)"/> private void ProcessActions(SimpleMessage message, Game game) { GameSystem gameSystem = GameSystem.Instance; string address = message.From; Player player = null; if (game != null) player = game.GetPlayer("", address); List<Action> actions = ParseActions(message, player, game); if (game == null) gameSystem.NewGame(message, actions); else if (player == null) gameSystem.ValidateJoinAction(address, actions, game); else { foreach (Action action in actions) { gameSystem.PerformAction(game, player, action); } } }
private void DoNightActions(Game game) { Player sheepleCandidate = (Player)LivingSheeple(game).PickOne(); foreach (Player p in game.GetLivingPlayers()) { Player candidate = (Player)game.GetLivingPlayers().PickOne(); if (p.Team.Equals("Illuminati")) SendAction(game, p, sheepleCandidate, p.Role.ActionText); else SendAction(game, p, candidate, p.Role.ActionText); while (p.MyAction == null && game.IsInProgress && game.ActiveCycle == Game.Cycle.Night) { if (p.Team.Equals("Illuminati")) { sheepleCandidate = (Player)LivingSheeple(game).PickOne(); SendAction(game, p, sheepleCandidate, p.Role.ActionText); } else { candidate = (Player)game.GetLivingPlayers().PickOne(); SendAction(game, p, candidate, p.Role.ActionText); } } } }
private void SendAction(Game game, Player p, Player candidate, string actionText) { SimpleMessage msg = new SimpleMessage(); msg.From = p.Address; msg.Subject = "New Game"; if(game != null) msg.Subject = game.FullTitle; msg.Body = actionText + " " + candidate.Name.ToLowerInvariant(); MessageParser.Instance.ParseMessage(msg); }
/// <summary> /// The given player isn't playing in any games, but they did reference a valid game id. See if they want to join it. /// </summary> /// <param name="address"></param> /// <param name="actions"></param> /// <param name="game"></param> public void ValidateJoinAction(string address, List<Action> actions, Game game) { foreach (Action action in actions) { if (action.Type == ActionEnum.JoinAs) { Player player = new Player(action.Text.ToTitleCase(), address); if (String.IsNullOrEmpty(player.Name)) { HandleBadAction(game, player, action, "You didn't specify the name you wished to join the game as. To do this reply to this message with \"Join as <i>name</i>\" where <i>name</i> is your name."); return; } else if (game.IsInProgress) { HandleBadAction(game, player, action, "You cannot join " + game + " because it is in progress."); } else if (game.GetPlayer(player.Name, "") != null) { HandleBadAction(game, player, action, "Someone else is already using " + player.Name.b() + " as their name, please choose a different name."); } else { ProcessJoinAction(player, action, game); } return; } } //None of the actions were join actions, and they aren't playing in any games so... string msg = "You aren't playing any games, the only action you may take is joining a game or creating a game. To start a new game reply to this message with \"Join as <i>name</i>\" where <i>name</i> is your name."; log.Warn("Unknown malformed action from " + address); Gmail.MessagePerson(address, game.Subject, msg); }
public void Status(Player player, Action action, Game game) { gameLog.Info("Sending Status of " + game + " to " + player.Address); Gmail.MessagePlayer(player, game, game.Status()); }
private List<Player> LivingSheeple(Game game) { List<Player> sheeple = new List<Player>(); foreach (Player p in game.GetLivingPlayers()) { if (!p.Team.Equals("Illuminati")) sheeple.Add(p); } return sheeple; }
/// <summary> /// Validates the following: /// <para />For each team: Percentage of players in this game is greater than <see cref="Team.MinPercentage"/> /// <para />At least 2 teams are playing. /// <para /><see cref="Role.MaxPlayers"/> is not violated. /// </summary> /// <returns></returns> private bool ValidateTeamMinPercent(Game game) { if (game.GetTeamsPlayingUnique().Count < 2) return false; foreach (Team t in game.GetTeamsPlayingUnique()) { int teamMembersCount = game.GetCountOfPlayersOnTeam(t); int minMembers = MathX.Percent(game.Players.Count, t.MinPercentage); if (teamMembersCount < minMembers) return false; } return true; }
public void Quit(Player player, Action action, Game game) { if (game.IsInProgress) { player.Quit(); Gmail.MessagePlayer(player, game, "Your character in " + game.Title + ", " + player.Name + " is now dead."); gameLog.Info(player + " is dead because they quit " + game); } else { game.RemovePlayer(player); Gmail.MessagePlayer(player, game, "You have been removed from " + game); gameLog.Info(player + " is quitting " + game); } }
/// <summary> /// Parses a line of the body for game commands. /// </summary> /// <param name="line"></param> /// <param name="player"></param> /// <returns></returns> private Action ParseGameAction(string line, Player player, Game game) { string actionText = player.Role.ActionText.ToLowerInvariant(); if (line.StartsWith(actionText) && game.ActiveCycle == Game.Cycle.Night) { return StringToAction(line, GameSystem.ActionEnum.Role, actionText, game); } if (line.StartsWith("vote") && player.IsAlive && game.ActiveCycle == Game.Cycle.Day) { return StringToAction(line, GameSystem.ActionEnum.Vote, "vote", game); } return null; }
private void HandleBadAction(Game game, Player player, Action action, string error, Exception e) { log.Warn("Exception thrown when parsing action: " + e.Message); HandleBadAction(game, player, action, error); }
public void RemoveGame(Game game) { Games.Remove(game); }
private void Vote(Player player, Action action, Game game) { Player nominee = action.Target; if (nominee == null) { if (action.Text.Equals("no one") || action.Text.Equals("nobody") || action.Text.Equals("noone")) { Player NoOne = new Player("No one", "nobody"); nominee = NoOne; } else { HandleBadAction(game, player, action, "You voted for an invalid player <b>" + action.Target + "</b> see the player's names below." + FlavorText.Divider + game.Status()); return; } } if (nominee.Equals(player)) { HandleBadAction(game, player, action, "You cannot vote for yourself."); } else if (!nominee.IsAlive) { HandleBadAction(game, player, action, nominee.Name.b() + " is already dead. See who's alive below:" + FlavorText.Divider + game.Status()); } else { Action vote = new Action(ActionEnum.Vote); vote.Target = nominee; player.AddAction(vote); Gmail.MessagePlayer(player, game, "Registered your vote for <b>" + nominee.Name + "</b>."); game.CheckEndOfCycle(); } }
private void RoleAction(Player player, Action action, Game game) { //As of now role actions only happen at night if (game.ActiveCycle == Game.Cycle.Night) { string result = player.Role.AddAction(player, action, game); if (!String.IsNullOrEmpty(result)) { HandleBadAction(game, player, action, result); return; } game.CheckEndOfCycle(); } }
/// <summary> /// Join game request is valid, process it. /// </summary> /// <param name="player"></param> /// <param name="action"></param> /// <param name="game"></param> private void ProcessJoinAction(Player player, Action action, Game game) { game.AddPlayer(player); Gmail.MessagePlayer(player, game, "Successfully added you to the game, <b>" + game.Overlord + "</b> is the Overlord.<br />" + "I will notify you when the game has started." + "<br /><br />" + game.Help(player)); Gmail.MessagePlayer(game.Overlord, game, "<b>" + player + "</b> has joined " + game.Title); gameLog.Info("Added player " + player + " to " + game); }
private void HandleBadAction(Game game, Player player, Action action, string error) { log.Warn("Malformed action " + action.Type + " with target " + action.Target + " and text " + action.Text + " from " + player.Address); Gmail.MessagePlayer(player, game, error); }
public void PerformAction(Game game, Player player, Action action) { if (action.Type == ActionEnum.JoinAs) { //If JoinAs gets hit here, it's only because the player is already playing in a different game Game g = GetGameByPlayer(player); if (g != null) HandleBadAction(g, player, action, "Failed to join " + game.Title + ". You are already playing in " + g.Title + "."); } else if (action.Type == ActionEnum.Status) Status(player, action, game); else if (action.Type == ActionEnum.Cancel) Cancel(player, action, game); else if (action.Type == ActionEnum.Start) Start(player, action, game); else if (action.Type == ActionEnum.Quit) Quit(player, action, game); else if (action.Type == ActionEnum.Vote && game.ActiveCycle == Game.Cycle.Day) Vote(player, action, game); else if (action.Type == ActionEnum.Help) Help(player, action, game); else if (action.Type == ActionEnum.Role) RoleAction(player, action, game); //TODO Implement Kick & Ban //if (action.Name == ActionEnum.Kick) Kick(player, action, game); //if (action.Name == ActionEnum.Ban) Ban(player, action, game); }
private List<Action> ParseActions(SimpleMessage message, Player player, Game game) { List<Action> actions = new List<Action>(); foreach (string line in message.BodyAsLines()) { Action action = null; if (player != null && game != null && game.IsInProgress) { action = ParseGameAction(line, player, game); } if (action == null) { action = ParseSystemAction(line); } if (action != null) actions.Add(action); } return actions; }
public Summary(Game game) { string line = game.Title.b() + " created with " + game.Overlord.b() + " as the Overlord."; line = line.tag("h1"); AddEvent(line); }
private void JoinPlayers(List<Player> players, Game game) { for(int i = 1; i < players.Count; i++) { SendAction(game, players[i], players[i], "join as"); } }
public void NewGame(SimpleMessage message, List<Action> actions) { string address = message.From; string name = ""; Action joinAction = null; foreach (Action action in actions) { if (action.Type == ActionEnum.JoinAs) joinAction = action; } name = joinAction.Text; Player player = new Player(name, address); if (String.IsNullOrEmpty(name)) { HandleBadAction(null, player, joinAction, "You didn't specify the name you wished to join the game as. To do this send a new email with \"Join as <i>name</i>\" where <i>name</i> is your name."); return; } Game game = GetGameByPlayer(player); if (game != null) { HandleBadAction(null, player, joinAction, "You are already playing in " + game + " , you may only play one game at a time."); return; } game = new Game(GetNextGameId(), player); Games.Add(game); Gmail.MessagePlayer(player, game, game.Title + " has been started, you are the <b>Overlord</b>." + "<br /><br />Have your friends join by sending a message with the subject \"" + game.Title + "\" and body \"Join as <i>name</i>\" where <i>name</i> is their name.<br />" + game.Help(player) + "<br /><hr><br />" + Program.License.Replace('\n'.ToString(), "<br />") + "<br /><br />Download this program on " + Program.GitHub); gameLog.Info("Started new game: " + game); }
public void Start(Player player, Action action, Game game) { if (game.IsOverlord(player)) { gameLog.Info("Attempting to start " + game); if (!game.Start()) { HandleBadAction(game, player, action, "You need at least 3 players to start a game." + FlavorText.Divider + game.Status()); } } }