Пример #1
0
        /// <summary>
        /// Gives general information about the game and how to play it.
        /// </summary>
        /// <param name="funConfiguration"></param>
        /// <returns></returns>

        public EmbedBuilder Info(FunConfiguration funConfiguration)
        {
            return(new EmbedBuilder()
                   .WithColor(Color.Magenta)
                   .WithTitle("How To Play: Hangman")
                   .WithDescription("**Step 1**: Set a TERM! The master can choose a term in DMs with the `game SET TERM [Term]` command.\n" +
                                    "**Step 2**: Any player can say `guess` at any moment to see the current status of the guess.\n" +
                                    "**Step 3**: Start guessing letters! type `guess [letter]` to guess a letter (you can't guess twice in a row!).\n" +
                                    "Feeling brave? Guess the whole term with `guess [term]`, it doesn't cost lives, but it does cost a turn.\n" +
                                    "If you'd like to forego your turn, type `pass`. To check misguessed letters, type `mistakes`.\n" +
                                    "Keep guessing until you run out of lives or you complete the word! (Type `lives` to see how many lives you have left)"));
        }
Пример #2
0
 public void Reset(FunConfiguration funConfiguration, GamesDB gamesDB)
 {
     game.Data = EmptyData;
     game.LastUserInteracted = game.Master;
     if (gamesDB is null)
     {
         return;
     }
     Player[] players = gamesDB.GetPlayersFromInstance(game.GameID);
     foreach (Player p in players)
     {
         p.Score = 0;
         p.Lives = 0;
     }
 }
Пример #3
0
 public EmbedBuilder Info(FunConfiguration funConfiguration)
 {
     return(new EmbedBuilder()
            .WithColor(Discord.Color.Magenta)
            .WithTitle("How to Play: Minesweeper")
            .WithDescription("**Step 1**: Set your desired parameters for the board using the `~game set [field] [value]` command. These fields are `width`, `height` and `mines`.\n" +
                             "Here are some defaults, if you'd like to try them:\n" +
                             "Beginner: [10x10] (10💣)\n" +
                             "Intermediate: [16x16] (40💣)\n" +
                             "Advanced: [26x18] (99💣)\n" +
                             "**Step 2**: Create the board view by typing `board` into the game chat.\n" +
                             "**Step 3**: Begin probing cells! Type the name of one or more cells (e.g. `C3` or `G12 D4 H3`) to probe them. Or type `flag [Cell] (Cells...)` to toggle a flag in one or more cells.)\n" +
                             "Since this game is singleplayer, only the game master can interact with it. The number on each cell tells you how many mines are on its immediate surroundings, anywhere from 0 to 8. If you probe a mine, it's game over!\n" +
                             "You win once there are no more cells to probe that do not contain a mine.\n" +
                             "PRO TIP! Type `auto` to automatically probe any cells deemed safe by surrounding flags and danger levels."));
 }
Пример #4
0
        /// <summary>
        /// Resets the game state to its initial default value.
        /// </summary>
        /// <param name="FunConfiguration">Settings related to the fun module, which contain the default lives parameter.</param>
        /// <param name="GamesDB">The database containing player information, set to <see langword="null"/> to avoid resetting scores.</param>

        public void Reset(FunConfiguration FunConfiguration, GamesDB GamesDB)
        {
            game.Data = EmptyData;
            game.LastUserInteracted = game.Master;
            Lives = MaxLives = FunConfiguration.HangmanDefaultLives;
            if (GamesDB is null)
            {
                return;
            }
            Player[] Players = GamesDB.GetPlayersFromInstance(game.GameID);
            foreach (Player p in Players)
            {
                p.Score = 0;
                p.Lives = 0;
            }
        }
Пример #5
0
        public bool Set(string field, string value, FunConfiguration funConfiguration, out string feedback)
        {
            bool   nonNumeric         = false;
            string nonNumericFeedback = $"This field is numeric, unable to parse \"{value}\" into an integer value.\n" +
                                        $"Did you mean to use a default field instead?";

            if (!int.TryParse(value, out int number))
            {
                nonNumeric = true;
            }

            int mines = Mines;

            switch (field.ToLower())
            {
            case "width":
                if (nonNumeric)
                {
                    feedback = nonNumericFeedback; return(false);
                }
                if (number > MaxWidth || number < MinWidth)
                {
                    feedback = $"Invalid width! The width must be between {MinWidth} and {MaxWidth}.";
                    return(false);
                }
                Width = number;
                if (mines > MaxMines)
                {
                    mines = MaxMines;
                }
                Board    = GenerateBoard(Height, Width, mines, new Random());
                State    = GenerateNewState(Height, Width);
                feedback = $"Set \"width\" to {number} and regenerated game board [{Width}x{Height}]. Maximum mine count for this size is {MaxMines}.";
                return(true);

            case "height":
                if (nonNumeric)
                {
                    feedback = nonNumericFeedback; return(false);
                }
                if (number > MaxHeight || number < MinHeight)
                {
                    feedback = $"Invalid height! The height must be between {MinHeight} and {MaxHeight}.";
                    return(false);
                }
                Height = number;
                if (mines > MaxMines)
                {
                    mines = MaxMines;
                }
                Board    = GenerateBoard(Height, Width, mines, new Random());
                State    = GenerateNewState(Height, Width);
                feedback = $"Set \"height\" to {number} and regenerated game board [{Width}x{Height}]. Maximum mine count for this size is {MaxMines}.";
                return(true);

            case "mines":
                if (nonNumeric)
                {
                    feedback = nonNumericFeedback; return(false);
                }
                if (number < 0)
                {
                    feedback = $"Invalid value! Number of mines can't be a negative number.";
                    return(false);
                }
                feedback = $"Set \"mines\" to {number} and regenerated game board [{Width}x{Height}]. Maximum mine count for this size is {MaxMines}.";
                Mines    = mines = number;
                if (mines > MaxMines)
                {
                    mines = MaxMines;
                }
                Board = GenerateBoard(Height, Width, mines, new Random());
                State = GenerateNewState(Height, Width);
                return(true);

            case "size":
                string[]   toParse = value.Split(" ");
                List <int> numbers = new List <int>();
                foreach (string s in toParse)
                {
                    if (int.TryParse(s, out int n))
                    {
                        numbers.Add(n);
                    }
                }
                if (numbers.Count < 2)
                {
                    feedback = $"You didn't provide enough numbers, please use the field-value syntax `size [WIDTH] [HEIGHT] (MINES)`.";
                    return(false);
                }
                if (numbers[0] > MaxWidth || numbers[0] < MinWidth)
                {
                    feedback = $"Invalid width! The width must be between {MinWidth} and {MaxWidth}.";
                    return(false);
                }
                if (numbers[1] > MaxHeight || numbers[1] < MinHeight)
                {
                    feedback = $"Invalid height! The height must be between {MinHeight} and {MaxHeight}.";
                    return(false);
                }

                Width  = numbers[0];
                Height = numbers[1];
                if (numbers.Count > 2)
                {
                    Mines = mines = numbers[2];
                }
                else
                {
                    mines = Mines;
                }

                if (mines > MaxMines)
                {
                    mines = MaxMines;
                }
                feedback = $"Set board size to [{Width}x{Height}] with a maximum mine count of {Mines}, current size can hold up to {MaxMines} mines.";
                Board    = GenerateBoard(Height, Width, mines, new Random());
                State    = GenerateNewState(Height, Width);
                return(true);

            case "difficulty":
                value = value.ToLower();
                if (!Difficulties.ContainsKey(value))
                {
                    feedback = $"\"{value}\" is not a valid difficulty! Available difficulties are: {string.Join(", ", Difficulties.Keys)}";
                    return(false);
                }
                Set("size", Difficulties[value], funConfiguration, out feedback);
                return(true);
            }

            feedback = $"Invalid field: \"{field}\" is not a default field nor \"width\", \"height\", \"mines\", \"size\", or \"difficulty\".";
            return(false);
        }
Пример #6
0
        /// <summary>
        /// Handles a message sent by a player in the appropriate channel.
        /// </summary>
        /// <param name="message">The message context from which the author and content can be obtained.</param>
        /// <param name="gamesDB">The games database in case any player data has to be modified.</param>
        /// <param name="client">The Discord client used to parse users.</param>
        /// <param name="funConfiguration">The configuration file containing relevant game information.</param>
        /// <returns>A <c>Task</c> object, which can be awaited until the method completes successfully.</returns>

        public async Task HandleMessage(IMessage message, GamesDB gamesDB, DiscordSocketClient client, FunConfiguration funConfiguration)
        {
            if (message.Channel is IDMChannel)
            {
                return;
            }
            Player player = gamesDB.GetOrCreatePlayer(message.Author.Id);

            string msg = message.Content.Replace("@", "@-");

            if (msg.ToLower() == "pass")
            {
                if (game.LastUserInteracted == message.Author.Id)
                {
                    await message.Channel.SendMessageAsync($"It's not your turn, {message.Author.Mention}!");

                    return;
                }

                game.LastUserInteracted = message.Author.Id;
                await message.Channel.SendMessageAsync($"{message.Author.Mention} passed their turn!");

                await message.DeleteAsync();

                return;
            }

            if (msg.ToLower() == "mistakes")
            {
                await message.Channel.SendMessageAsync($"Mistakes: {MistakesExpression()}");

                return;
            }
            if (msg.ToLower() == "lives")
            {
                await message.Channel.SendMessageAsync($"Lives: {LivesExpression()}");

                return;
            }

            if (msg.ToLower().StartsWith("guess"))
            {
                string[] args = msg.Split(" ");
                if (args.Length == 1)
                {
                    await message.Channel.SendMessageAsync(DiscordifyGuess());

                    return;
                }
                if (message.Author.Id == game.Master)
                {
                    await message.Channel.SendMessageAsync("The game master isn't allowed to guess their own word.");

                    return;
                }
                if (game.LastUserInteracted == message.Author.Id)
                {
                    await message.Channel.SendMessageAsync("You've already guessed! Let someone else play, if it's only you, have the master pass their turn.");

                    return;
                }
                if (!Guess.Contains('_'))
                {
                    await message.Channel.SendMessageAsync($"The term was already guessed! You're late to the party. Waiting for the Game Master to change it.");

                    return;
                }
                if (Lives < 1)
                {
                    await message.Channel.SendMessageAsync($"You're out of lives! Choose a new term before continuing.");

                    return;
                }
                string newGuess = string.Join(' ', args[1..]);
Пример #7
0
        /// <summary>
        /// Sets a local <paramref name="field"/> to a given <paramref name="value"/>.
        /// </summary>
        /// <remarks>Valid <paramref name="field"/> values are: TERM, LIVES, MAXLIVES, and MISTAKES.</remarks>
        /// <param name="field">The name of the field to modify.</param>
        /// <param name="value">The value to set the field to.</param>
        /// <param name="funConfiguration">The Fun Configuration settings file, which holds relevant data such as default lives.</param>
        /// <param name="feedback">In case this operation wasn't possible, its reason, or useful feedback even if the operation was successful.</param>
        /// <returns><see langword="true"/> if the operation was successful, otherwise <see langword="false"/>.</returns>

        public bool Set(string field, string value, FunConfiguration funConfiguration, out string feedback)
        {
            feedback = "";
            int n;

            switch (field.ToLower())
            {
            case "word":
            case "term":
                if (value.Contains('_'))
                {
                    feedback = "The term cannot contain underscores!";
                    return(false);
                }
                else if (value.Contains('@'))
                {
                    feedback = "The term cannot contain the at symbol (@)!";
                    return(false);
                }
                else if (value.Length > 256)
                {
                    feedback = "The term is too long!";
                    return(false);
                }
                Reset(funConfiguration, null);
                Term     = value;
                Guess    = ObscureTerm(value);
                feedback = $"Success! Term = {value}, Guess = \"{DiscordifyGuess()}\"";
                return(true);

            case "lives":
                if (!int.TryParse(value, out n))
                {
                    feedback = $"Unable to parse {value} into an integer value.";
                    return(false);
                }
                if (n > MAX_LIVES_ALLOWED)
                {
                    feedback = $"Too many lives! Please keep it below {MAX_LIVES_ALLOWED}";
                    return(false);
                }
                Lives    = n;
                feedback = $"Lives set to {Lives}/{MaxLives}";
                return(true);

            case "maxlives":
                if (!int.TryParse(value, out n))
                {
                    feedback = $"Unable to parse {value} into an integer value.";
                    return(false);
                }
                if (n > MAX_LIVES_ALLOWED)
                {
                    feedback = $"Too many lives! Please keep it below {MAX_LIVES_ALLOWED}";
                    return(false);
                }
                MaxLives = n;
                feedback = $"Lives set to {Lives}/{MaxLives}";
                return(true);

            case "missed":
            case "mistakes":
                if (value.ToLower() == "none")
                {
                    LettersMissed = "";
                    feedback      = "Reset mistakes.";
                    return(true);
                }

                HashSet <char> missed = new HashSet <char>();
                foreach (char c in value.ToCharArray())
                {
                    if (!char.IsLetter(c))
                    {
                        missed.Add(char.ToUpper('c'));
                    }
                }
                LettersMissed = string.Join("", missed);
                feedback      = $"Missed letters set to {{{string.Join(", ", missed)}}}.";
                return(true);

            default:
                feedback = $"The given field ({field}) was not found, game-specific fields are `term`, `lives`, `maxlives`, and `mistakes`";
                return(false);
            }
        }