.hangman completely rewritten. Should work almost the same, with some minor improvements (such as showing the category, and you can now guess the whole word at once)
This commit is contained in:
parent
53661b3337
commit
d5978a0d66
@ -2,18 +2,12 @@
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Extensions;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Common.Attributes;
|
||||
using NadekoBot.Common.Collections;
|
||||
using NadekoBot.Services.Impl;
|
||||
using NadekoBot.Modules.Games.Common.Acrophobia;
|
||||
|
||||
namespace NadekoBot.Modules.Games
|
||||
|
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Common.Hangman.Exceptions
|
||||
{
|
||||
public class TermNotFoundException : Exception
|
||||
{
|
||||
public TermNotFoundException() : base("Term of that type couldn't be found")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
169
src/NadekoBot/Modules/Games/Common/Hangman/Hangman.cs
Normal file
169
src/NadekoBot/Modules/Games/Common/Hangman/Hangman.cs
Normal file
@ -0,0 +1,169 @@
|
||||
using NadekoBot.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Common.Hangman
|
||||
{
|
||||
public class Hangman : IDisposable
|
||||
{
|
||||
public string TermType { get; }
|
||||
public HangmanObject Term { get; }
|
||||
|
||||
public string ScrambledWord => "`" + String.Concat(Term.Word.Select(c =>
|
||||
{
|
||||
if (c == ' ')
|
||||
return " \u2000";
|
||||
if (!(char.IsLetter(c) || char.IsDigit(c)))
|
||||
return $" {c}";
|
||||
|
||||
c = char.ToLowerInvariant(c);
|
||||
return _previousGuesses.Contains(c) ? $" {c}" : " ◯";
|
||||
})) + "`";
|
||||
|
||||
private Phase _currentPhase = Phase.Active;
|
||||
public Phase CurrentPhase
|
||||
{
|
||||
get => _currentPhase;
|
||||
set
|
||||
{
|
||||
if (value == Phase.Ended)
|
||||
_endingCompletionSource.TrySetResult(true);
|
||||
|
||||
_currentPhase = value;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
|
||||
|
||||
private readonly HashSet<ulong> _recentUsers = new HashSet<ulong>();
|
||||
|
||||
public uint Errors { get; private set; } = 0;
|
||||
public uint MaxErrors { get; } = 6;
|
||||
|
||||
public event Func<Hangman, string, Task> OnGameEnded = delegate { return Task.CompletedTask; };
|
||||
public event Func<Hangman, string, char, Task> OnLetterAlreadyUsed = delegate { return Task.CompletedTask; };
|
||||
public event Func<Hangman, string, char, Task> OnGuessFailed = delegate { return Task.CompletedTask; };
|
||||
public event Func<Hangman, string, char, Task> OnGuessSucceeded = delegate { return Task.CompletedTask; };
|
||||
|
||||
private readonly HashSet<char> _previousGuesses = new HashSet<char>();
|
||||
public ImmutableArray<char> PreviousGuesses => _previousGuesses.ToImmutableArray();
|
||||
|
||||
private readonly TaskCompletionSource<bool> _endingCompletionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
public Task EndedTask => _endingCompletionSource.Task;
|
||||
|
||||
public Hangman(TermType type)
|
||||
{
|
||||
this.TermType = type.ToString().Replace('_', ' ').ToTitleCase();
|
||||
this.Term = TermPool.GetTerm(type);
|
||||
}
|
||||
|
||||
private void AddError()
|
||||
{
|
||||
Errors++;
|
||||
if (Errors > MaxErrors)
|
||||
{
|
||||
CurrentPhase = Phase.Ended;
|
||||
var _ = OnGameEnded(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetHangman() => $@". ┌─────┐
|
||||
.┃...............┋
|
||||
.┃...............┋
|
||||
.┃{(Errors > 0 ? ".............😲" : "")}
|
||||
.┃{(Errors > 1 ? "............./" : "")} {(Errors > 2 ? "|" : "")} {(Errors > 3 ? "\\" : "")}
|
||||
.┃{(Errors > 4 ? "............../" : "")} {(Errors > 5 ? "\\" : "")}
|
||||
/-\";
|
||||
|
||||
public async Task Input(ulong userId, string userName, string input)
|
||||
{
|
||||
if (CurrentPhase == Phase.Ended)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return;
|
||||
|
||||
input = input.Trim().ToLowerInvariant();
|
||||
|
||||
await _locker.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (CurrentPhase == Phase.Ended)
|
||||
return;
|
||||
|
||||
if (input.Length > 1) // tried to guess the whole word
|
||||
{
|
||||
if (input != Term.Word) // failed
|
||||
return;
|
||||
|
||||
CurrentPhase = Phase.Ended;
|
||||
var _ = OnGameEnded?.Invoke(this, userName);
|
||||
return;
|
||||
}
|
||||
|
||||
var ch = input[0];
|
||||
|
||||
if (!(char.IsLetterOrDigit(ch)))
|
||||
return;
|
||||
|
||||
if (!_recentUsers.Add(userId)) // don't let a single user spam guesses
|
||||
return;
|
||||
|
||||
if (!_previousGuesses.Add(ch)) // that latter was already guessed
|
||||
{
|
||||
var _ = OnLetterAlreadyUsed?.Invoke(this, userName, ch);
|
||||
AddError();
|
||||
}
|
||||
else if (!Term.Word.Contains(ch)) // guessed letter doesn't exist
|
||||
{
|
||||
var _ = OnGuessFailed?.Invoke(this, userName, ch);
|
||||
AddError();
|
||||
}
|
||||
else if (Term.Word.All(x => _previousGuesses.IsSupersetOf(Term.Word.ToLowerInvariant()
|
||||
.Where(c => char.IsLetterOrDigit(c)))))
|
||||
{
|
||||
var _ = OnGameEnded.Invoke(this, userName); //if all letters are guessed
|
||||
}
|
||||
else //guessed but not last letter
|
||||
{
|
||||
var _ = OnGuessSucceeded?.Invoke(this, userName, ch);
|
||||
_recentUsers.Remove(userId); // he can guess again right away
|
||||
return;
|
||||
}
|
||||
|
||||
var clearSpam = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(3000).ConfigureAwait(false); // remove the user from the spamlist after 5 seconds
|
||||
_recentUsers.Remove(userId);
|
||||
});
|
||||
}
|
||||
finally { _locker.Release(); }
|
||||
}
|
||||
|
||||
public async Task Stop()
|
||||
{
|
||||
await _locker.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
CurrentPhase = Phase.Ended;
|
||||
}
|
||||
finally { _locker.Release(); }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
OnGameEnded = null;
|
||||
OnGuessFailed = null;
|
||||
OnGuessSucceeded = null;
|
||||
OnLetterAlreadyUsed = null;
|
||||
_previousGuesses.Clear();
|
||||
_recentUsers.Clear();
|
||||
_locker.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,214 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Common.Hangman
|
||||
{
|
||||
public class HangmanTermPool
|
||||
{
|
||||
const string termsPath = "data/hangman3.json";
|
||||
public static IReadOnlyDictionary<string, HangmanObject[]> data { get; }
|
||||
static HangmanTermPool()
|
||||
{
|
||||
try
|
||||
{
|
||||
data = JsonConvert.DeserializeObject<Dictionary<string, HangmanObject[]>>(File.ReadAllText(termsPath));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//ignored
|
||||
}
|
||||
}
|
||||
|
||||
public static HangmanObject GetTerm(string type)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type))
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
type = type.Trim();
|
||||
|
||||
var rng = new NadekoRandom();
|
||||
|
||||
if (type == "All") {
|
||||
var keys = data.Keys.ToArray();
|
||||
type = keys[rng.Next(0, keys.Length)];
|
||||
}
|
||||
|
||||
HangmanObject[] termTypes;
|
||||
data.TryGetValue(type, out termTypes);
|
||||
|
||||
if (termTypes == null || termTypes.Length == 0)
|
||||
return null;
|
||||
|
||||
return termTypes[rng.Next(0, termTypes.Length)];
|
||||
}
|
||||
}
|
||||
|
||||
public class HangmanGame: IDisposable
|
||||
{
|
||||
private readonly Logger _log;
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
public IMessageChannel GameChannel { get; }
|
||||
public HashSet<char> Guesses { get; } = new HashSet<char>();
|
||||
public HangmanObject Term { get; private set; }
|
||||
public uint Errors { get; private set; } = 0;
|
||||
public uint MaxErrors { get; } = 6;
|
||||
public uint MessagesSinceLastPost { get; private set; } = 0;
|
||||
public string ScrambledWord => "`" + String.Concat(Term.Word.Select(c =>
|
||||
{
|
||||
if (c == ' ')
|
||||
return " \u2000";
|
||||
if (!(char.IsLetter(c) || char.IsDigit(c)))
|
||||
return $" {c}";
|
||||
|
||||
c = char.ToUpperInvariant(c);
|
||||
return Guesses.Contains(c) ? $" {c}" : " ◯";
|
||||
})) + "`";
|
||||
|
||||
public bool GuessedAll => Guesses.IsSupersetOf(Term.Word.ToUpperInvariant()
|
||||
.Where(c => char.IsLetter(c) || char.IsDigit(c)));
|
||||
|
||||
public string TermType { get; }
|
||||
|
||||
public event Action<HangmanGame> OnEnded;
|
||||
|
||||
public HangmanGame(DiscordSocketClient client, IMessageChannel channel, string type)
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_client = client;
|
||||
|
||||
this.GameChannel = channel;
|
||||
this.TermType = type.ToTitleCase();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
this.Term = HangmanTermPool.GetTerm(TermType);
|
||||
|
||||
if (this.Term == null)
|
||||
throw new KeyNotFoundException("Can't find a term with that type. Use hangmanlist command.");
|
||||
// start listening for answers when game starts
|
||||
_client.MessageReceived += PotentialGuess;
|
||||
}
|
||||
|
||||
public async Task End()
|
||||
{
|
||||
_client.MessageReceived -= PotentialGuess;
|
||||
OnEnded(this);
|
||||
var toSend = "Game ended. You **" + (Errors >= MaxErrors ? "LOSE" : "WIN") + "**!\n" + GetHangman();
|
||||
var embed = new EmbedBuilder().WithTitle("Hangman Game")
|
||||
.WithDescription(toSend)
|
||||
.AddField(efb => efb.WithName("It was").WithValue(Term.Word))
|
||||
.WithFooter(efb => efb.WithText(string.Join(" ", Guesses)));
|
||||
if(Uri.IsWellFormedUriString(Term.ImageUrl, UriKind.Absolute))
|
||||
embed.WithImageUrl(Term.ImageUrl);
|
||||
|
||||
if (Errors >= MaxErrors)
|
||||
await GameChannel.EmbedAsync(embed.WithErrorColor()).ConfigureAwait(false);
|
||||
else
|
||||
await GameChannel.EmbedAsync(embed.WithOkColor()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private Task PotentialGuess(SocketMessage msg)
|
||||
{
|
||||
var _ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(msg is SocketUserMessage))
|
||||
return;
|
||||
|
||||
if (msg.Channel != GameChannel)
|
||||
return; // message's channel has to be the same as game's
|
||||
if (msg.Content.Length == 1) // message must be 1 char long
|
||||
{
|
||||
if (++MessagesSinceLastPost > 10)
|
||||
{
|
||||
MessagesSinceLastPost = 0;
|
||||
try
|
||||
{
|
||||
await GameChannel.SendConfirmAsync("Hangman Game",
|
||||
ScrambledWord + "\n" + GetHangman(),
|
||||
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (!(char.IsLetter(msg.Content[0]) || char.IsDigit(msg.Content[0])))// and a letter or a digit
|
||||
return;
|
||||
|
||||
var guess = char.ToUpperInvariant(msg.Content[0]);
|
||||
if (Guesses.Contains(guess))
|
||||
{
|
||||
MessagesSinceLastPost = 0;
|
||||
++Errors;
|
||||
if (Errors < MaxErrors)
|
||||
await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author} Letter `{guess}` has already been used.\n" + ScrambledWord + "\n" + GetHangman(),
|
||||
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||
else
|
||||
await End().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Guesses.Add(guess);
|
||||
|
||||
if (Term.Word.ToUpperInvariant().Contains(guess))
|
||||
{
|
||||
if (GuessedAll)
|
||||
{
|
||||
try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author} guessed a letter `{guess}`!").ConfigureAwait(false); } catch { }
|
||||
|
||||
await End().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
MessagesSinceLastPost = 0;
|
||||
try
|
||||
{
|
||||
await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman(),
|
||||
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
MessagesSinceLastPost = 0;
|
||||
++Errors;
|
||||
if (Errors < MaxErrors)
|
||||
await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author} Letter `{guess}` does not exist.\n" + ScrambledWord + "\n" + GetHangman(),
|
||||
footer: string.Join(" ", Guesses)).ConfigureAwait(false);
|
||||
else
|
||||
await End().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { _log.Warn(ex); }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public string GetHangman() => $@". ┌─────┐
|
||||
.┃...............┋
|
||||
.┃...............┋
|
||||
.┃{(Errors > 0 ? ".............😲" : "")}
|
||||
.┃{(Errors > 1 ? "............./" : "")} {(Errors > 2 ? "|" : "")} {(Errors > 3 ? "\\" : "")}
|
||||
.┃{(Errors > 4 ? "............../" : "")} {(Errors > 5 ? "\\" : "")}
|
||||
/-\";
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_client.MessageReceived -= PotentialGuess;
|
||||
OnEnded = null;
|
||||
}
|
||||
}
|
||||
}
|
14
src/NadekoBot/Modules/Games/Common/Hangman/Phase.cs
Normal file
14
src/NadekoBot/Modules/Games/Common/Hangman/Phase.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Common.Hangman
|
||||
{
|
||||
public enum Phase
|
||||
{
|
||||
Active,
|
||||
Ended,
|
||||
}
|
||||
}
|
52
src/NadekoBot/Modules/Games/Common/Hangman/TermPool.cs
Normal file
52
src/NadekoBot/Modules/Games/Common/Hangman/TermPool.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Modules.Games.Common.Hangman.Exceptions;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Common.Hangman
|
||||
{
|
||||
public class TermPool
|
||||
{
|
||||
const string termsPath = "data/hangman3.json";
|
||||
public static IReadOnlyDictionary<string, HangmanObject[]> data { get; } = new Dictionary<string, HangmanObject[]>();
|
||||
static TermPool()
|
||||
{
|
||||
try
|
||||
{
|
||||
data = JsonConvert.DeserializeObject<Dictionary<string, HangmanObject[]>>(File.ReadAllText(termsPath));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ImmutableArray<TermType> _termTypes = Enum.GetValues(typeof(TermType))
|
||||
.Cast<TermType>()
|
||||
.ToImmutableArray();
|
||||
|
||||
public static HangmanObject GetTerm(TermType type)
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
|
||||
if (type == TermType.Random)
|
||||
{
|
||||
var keys = data.Keys.ToArray();
|
||||
|
||||
type = _termTypes[rng.Next(0, _termTypes.Length - 1)]; // - 1 because last one is 'all'
|
||||
}
|
||||
if (!data.TryGetValue(type.ToString(), out var termTypes) || termTypes.Length == 0)
|
||||
throw new TermNotFoundException();
|
||||
|
||||
var obj = termTypes[rng.Next(0, termTypes.Length)];
|
||||
|
||||
obj.Word = obj.Word.Trim().ToLowerInvariant();
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
18
src/NadekoBot/Modules/Games/Common/Hangman/TermType.cs
Normal file
18
src/NadekoBot/Modules/Games/Common/Hangman/TermType.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Common.Hangman
|
||||
{
|
||||
[Flags]
|
||||
public enum TermType
|
||||
{
|
||||
Countries = 0,
|
||||
Movies = 1,
|
||||
Animals = 2,
|
||||
Things = 4,
|
||||
Random = 8,
|
||||
}
|
||||
}
|
@ -23,43 +23,102 @@ namespace NadekoBot.Modules.Games
|
||||
}
|
||||
|
||||
//channelId, game
|
||||
public static ConcurrentDictionary<ulong, HangmanGame> HangmanGames { get; } = new ConcurrentDictionary<ulong, HangmanGame>();
|
||||
public static ConcurrentDictionary<ulong, Hangman> HangmanGames { get; } = new ConcurrentDictionary<ulong, Hangman>();
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Hangmanlist()
|
||||
{
|
||||
await Context.Channel.SendConfirmAsync(Format.Code(GetText("hangman_types", Prefix)) + "\n" + string.Join(", ", HangmanTermPool.data.Keys));
|
||||
await Context.Channel.SendConfirmAsync(Format.Code(GetText("hangman_types", Prefix)) + "\n" + string.Join(", ", TermPool.data.Keys));
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Hangman([Remainder]string type = "All")
|
||||
public async Task Hangman([Remainder]TermType type = TermType.Random)
|
||||
{
|
||||
var hm = new HangmanGame(_client, Context.Channel, type);
|
||||
var hm = new Hangman(type);
|
||||
|
||||
if (!HangmanGames.TryAdd(Context.Channel.Id, hm))
|
||||
{
|
||||
hm.Dispose();
|
||||
await ReplyErrorLocalized("hangman_running").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
hm.OnGameEnded += Hm_OnGameEnded;
|
||||
hm.OnGuessFailed += Hm_OnGuessFailed;
|
||||
hm.OnGuessSucceeded += Hm_OnGuessSucceeded;
|
||||
hm.OnLetterAlreadyUsed += Hm_OnLetterAlreadyUsed;
|
||||
_client.MessageReceived += _client_MessageReceived;
|
||||
|
||||
hm.OnEnded += g =>
|
||||
{
|
||||
HangmanGames.TryRemove(g.GameChannel.Id, out _);
|
||||
};
|
||||
try
|
||||
{
|
||||
hm.Start();
|
||||
await Context.Channel.SendConfirmAsync(GetText("hangman_game_started") + $" ({hm.TermType})",
|
||||
hm.ScrambledWord + "\n" + hm.GetHangman())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch { }
|
||||
|
||||
await hm.EndedTask.ConfigureAwait(false);
|
||||
|
||||
|
||||
Task _client_MessageReceived(SocketMessage msg)
|
||||
{
|
||||
try { await Context.Channel.SendErrorAsync(GetText("hangman_start_errored") + " " + ex.Message).ConfigureAwait(false); } catch { }
|
||||
if(HangmanGames.TryRemove(Context.Channel.Id, out var removed))
|
||||
removed.Dispose();
|
||||
return;
|
||||
var _ = Task.Run(() =>
|
||||
{
|
||||
if (Context.Channel.Id == msg.Channel.Id)
|
||||
return hm.Input(msg.Author.Id, msg.Author.ToString(), msg.Content);
|
||||
else
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
await Context.Channel.SendConfirmAsync(GetText("hangman_game_started"), hm.ScrambledWord + "\n" + hm.GetHangman());
|
||||
Task Hm_OnGameEnded(Hangman game, string winner)
|
||||
{
|
||||
HangmanGames.TryRemove(Context.Channel.Id, out _);
|
||||
|
||||
if (winner == null)
|
||||
{
|
||||
var loseEmbed = new EmbedBuilder().WithTitle($"Hangman Game ({game.TermType}) - Ended")
|
||||
.WithDescription(Format.Bold("You lose."))
|
||||
.AddField(efb => efb.WithName("It was").WithValue(game.Term.Word.ToTitleCase()))
|
||||
.WithFooter(efb => efb.WithText(string.Join(" ", game.PreviousGuesses)))
|
||||
.WithErrorColor();
|
||||
|
||||
if (Uri.IsWellFormedUriString(game.Term.ImageUrl, UriKind.Absolute))
|
||||
loseEmbed.WithImageUrl(game.Term.ImageUrl);
|
||||
|
||||
return Context.Channel.EmbedAsync(loseEmbed);
|
||||
}
|
||||
|
||||
var winEmbed = new EmbedBuilder().WithTitle($"Hangman Game ({game.TermType}) - Ended")
|
||||
.WithDescription(Format.Bold($"{winner} Won."))
|
||||
.AddField(efb => efb.WithName("It was").WithValue(game.Term.Word.ToTitleCase()))
|
||||
.WithFooter(efb => efb.WithText(string.Join(" ", game.PreviousGuesses)))
|
||||
.WithOkColor();
|
||||
|
||||
if (Uri.IsWellFormedUriString(game.Term.ImageUrl, UriKind.Absolute))
|
||||
winEmbed.WithImageUrl(game.Term.ImageUrl);
|
||||
|
||||
return Context.Channel.EmbedAsync(winEmbed);
|
||||
}
|
||||
|
||||
private Task Hm_OnLetterAlreadyUsed(Hangman game, string user, char guess)
|
||||
{
|
||||
return Context.Channel.SendErrorAsync($"Hangman Game ({game.TermType})", $"{user} Letter `{guess}` has already been used. You can guess again in 3 seconds.\n" + game.ScrambledWord + "\n" + game.GetHangman(),
|
||||
footer: string.Join(" ", game.PreviousGuesses));
|
||||
}
|
||||
|
||||
private Task Hm_OnGuessSucceeded(Hangman game, string user, char guess)
|
||||
{
|
||||
return Context.Channel.SendConfirmAsync($"Hangman Game ({game.TermType})", $"{user} guessed a letter `{guess}`!\n" + game.ScrambledWord + "\n" + game.GetHangman());
|
||||
}
|
||||
|
||||
private Task Hm_OnGuessFailed(Hangman game, string user, char guess)
|
||||
{
|
||||
return Context.Channel.SendErrorAsync($"Hangman Game ({game.TermType})", $"{user} Letter `{guess}` does not exist. You can guess again in 3 seconds.\n" + game.ScrambledWord + "\n" + game.GetHangman(),
|
||||
footer: string.Join(" ", game.PreviousGuesses));
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
|
Loading…
Reference in New Issue
Block a user