From d5f04b522816c51e14849743b60f2e05b5a45889 Mon Sep 17 00:00:00 2001 From: alogindtractor <251821224+A-Log-In-D-Tractor@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:06:15 -0800 Subject: [PATCH] some sloppa fixes (#69) * update update * service service * Optimize message retrieval in MinesCommand Refactor message handling in MinesCommand to use last message directly. * Replace LastMessageId with LastMessage object --- .../Commands/Kasino/MinesCommand.cs | 62 ++++++++++++------- KfChatDotNetBot/Services/KasinoMines.cs | 49 ++++++++++----- 2 files changed, 71 insertions(+), 40 deletions(-) diff --git a/KfChatDotNetBot/Commands/Kasino/MinesCommand.cs b/KfChatDotNetBot/Commands/Kasino/MinesCommand.cs index 7901129..6c7b2bc 100644 --- a/KfChatDotNetBot/Commands/Kasino/MinesCommand.cs +++ b/KfChatDotNetBot/Commands/Kasino/MinesCommand.cs @@ -13,17 +13,19 @@ public class MinesCommand : ICommand { public List Patterns => [ //cashout - new Regex(@"^mines(? cashout)$", RegexOptions.IgnoreCase), + new Regex(@"^mines\s+cashout$", RegexOptions.IgnoreCase), //refresh - new Regex(@"^mines(? refresh)$", RegexOptions.IgnoreCase), - //attempting to start a game below here - new Regex(@"^mines (?\d+(?:\.\d+)?) (?\d+) (?\d+) (?\d+)(? cashout|)$", RegexOptions.IgnoreCase), - new Regex(@"^mines (?\d+(?:\.\d+)?) (?\d+) (?\d+) (?.+)(? cashout|)$", RegexOptions.IgnoreCase), - //attempting to continue a game below here - new Regex(@"^mines (?\d+)(? cashout|)$", RegexOptions.IgnoreCase), - new Regex(@"^mines (?.+)(? cashout|)$", RegexOptions.IgnoreCase), + new Regex(@"^mines\s+refresh$", RegexOptions.IgnoreCase), + //start game with number of picks + new Regex(@"^mines\s+(?\d+(?:\.\d+)?)\s+(?\d+)\s+(?\d+)\s+(?\d+)(?:\s+(?cashout))?$", RegexOptions.IgnoreCase), + //start game with coordinate string (must contain comma) + new Regex(@"^mines\s+(?\d+(?:\.\d+)?)\s+(?\d+)\s+(?\d+)\s+(?\d+,\d+(?:\s+\d+,\d+)*)(?:\s+(?cashout))?$", RegexOptions.IgnoreCase), + //continue game with number of picks + new Regex(@"^mines\s+(?\d+)(?:\s+(?cashout))?$", RegexOptions.IgnoreCase), + //continue game with coordinate string (must contain comma) + new Regex(@"^mines\s+(?\d+,\d+(?:\s+\d+,\d+)*)(?:\s+(?cashout))?$", RegexOptions.IgnoreCase), //get info - new Regex("^mines$") + new Regex(@"^mines$", RegexOptions.IgnoreCase) ]; public string? HelpText => "!mines to play simple mines. !mines for advanced mines. Tool: https://i.ddos.lgbt/raw/UJ9Dty.html"; public UserRight RequiredRight => UserRight.Loser; @@ -63,7 +65,22 @@ public class MinesCommand : ICommand throw new InvalidOperationException($"Caught a null when retrieving gambler for {user.KfUsername}"); KasinoMines = new KasinoMines(botInstance, gambler.Id); bool cashout = false; - if (message.Message.Contains("cashout")) cashout = true; + if (arguments.TryGetValue("cashout", out var cashOut)||message.Message.Contains("cashout")) cashout = true; + + if (!Regex.IsMatch(message.Message, @"\d") && cashout) //if the message has no ints its a cashout attempt + { + if (KasinoMines.ActiveGames.ContainsKey(gambler.Id)) + { + await KasinoMines.Cashout(KasinoMines.ActiveGames[gambler.Id]); + return; + } + else + { + await botInstance.SendChatMessageAsync($"{user.FormatUsername()}, you don't have a game running to cash out.", true, autoDeleteAfter: cleanupDelay); + return; + } + } + //check if user has an existing game already if (!KasinoMines.ActiveGames.ContainsKey(gambler.Id)) { @@ -86,15 +103,7 @@ public class MinesCommand : ICommand if (gambler.Balance < wager) { await botInstance.SendChatMessageAsync( - $"{user.FormatUsername()}, your balance is too low. Balance: {await gambler.Balance.FormatKasinoCurrencyAsync()}", true, autoDeleteAfter: cleanupDelay); - return; - } - - if (wager == 0) - { - await botInstance.SendChatMessageAsync( - $"{user.FormatUsername()}, you have to wager more than {await wager.FormatKasinoCurrencyAsync()}", true, - autoDeleteAfter: cleanupDelay); + $"{user.FormatUsername()}, your balance is too low. Balance: {gambler.Balance.FormatKasinoCurrencyAsync()}", true, autoDeleteAfter: cleanupDelay); return; } @@ -106,6 +115,13 @@ public class MinesCommand : ICommand true, autoDeleteAfter: TimeSpan.FromSeconds(10)); return; } + + if (wager <= 0) + { + await botInstance.SendChatMessageAsync( + $"{user.FormatUsername()}, you have to bet something to play mines.", true, autoDeleteAfter: cleanupDelay); + return; + } if (!arguments.TryGetValue("size", out var size) || !arguments.TryGetValue("mines", out var mines)) { await botInstance.SendChatMessageAsync( @@ -164,7 +180,7 @@ public class MinesCommand : ICommand var game = KasinoMines.ActiveGames[gambler.Id]; foreach (var coord in precisePicks) { - if (game.BetsPlaced.Contains(coord) || coord.r <= 0 || coord.r > game.Size || coord.c <= 0 || coord.c > game.Size) + if (game.BetsPlaced.Contains(coord) || coord.r < 0 || coord.r > game.Size || coord.c < 0 || coord.c > game.Size) { await botInstance.SendChatMessageAsync($"{user.FormatUsername()}, you can't place duplicate or invalid bets. Use the tool: {ToolUrl}", true, autoDeleteAfter: cleanupDelay); return; @@ -222,10 +238,8 @@ public class MinesCommand : ICommand true, autoDeleteAfter: cleanupDelay); return; } - var msg = await botInstance.SendChatMessageAsync( - $"{KasinoMines.ActiveGames[gambler.Id].ToString()}", true); - var msgSuccess = await botInstance.WaitForChatMessageAsync(msg, ct: ctx); - if (!msgSuccess) throw new InvalidOperationException("Timed out waiting for the message"); + + var msg = KasinoMines.ActiveGames[gambler.Id].LastMessage; if (pick == 0) //if using coordinates { var game = KasinoMines.ActiveGames[gambler.Id]; diff --git a/KfChatDotNetBot/Services/KasinoMines.cs b/KfChatDotNetBot/Services/KasinoMines.cs index e081c3c..bd7bbb3 100644 --- a/KfChatDotNetBot/Services/KasinoMines.cs +++ b/KfChatDotNetBot/Services/KasinoMines.cs @@ -23,8 +23,8 @@ public class KasinoMines public decimal Wager { get; set; } public int Size { get; set; } public int Mines { get; set; } - public List<(int r, int c)> BetsPlaced = new(); - public int LastMessageId; + public List<(int r, int c)> BetsPlaced; + public SentMessageTrackerModel LastMessage; public KasinoMinesGame(GamblerDbModel creator, decimal wager, int size, int mines) @@ -34,30 +34,38 @@ public class KasinoMines Mines = mines; Wager = wager; MinesBoard = CreateBoard(); + BetsPlaced = new(); } public async Task ResetMessage(SentMessageTrackerModel msg) { _logger.Info("Resetting message"); // 0 is the default for int - if (LastMessageId != 0) + if (LastMessage.ChatMessageId.Value != 0) { - await _kfChatBot.KfClient.DeleteMessageAsync(LastMessageId); + await _kfChatBot.KfClient.DeleteMessageAsync(LastMessage.ChatMessageId.Value); } if (msg.ChatMessageId == null) throw new InvalidOperationException($"ChatMessageId was null for {msg.Reference}"); - LastMessageId = msg.ChatMessageId.Value; + LastMessage = msg; } public async Task RigBoard((int r, int c) coord) //moves one of the mines to a specified coordinate for house edge rigging { //find the first mine (int r, int c) originalMine = (11, 11); + bool brek = false; for (int r = 0; r < Size; r++) { for (int c = 0; c < Size; c++) { - if (MinesBoard[r, c] == 'M') originalMine = (r, c); + if (MinesBoard[r, c] == 'M') + { + originalMine = (r, c); + brek = true; + break; + } } + if (brek) break; } MinesBoard[coord.r, coord.c] = 'M'; @@ -71,7 +79,7 @@ public class KasinoMines } public async Task Explode((int r, int c) mineLocation, SentMessageTrackerModel msg) { - if (LastMessageId != msg.ChatMessageId!.Value) + if (LastMessage.ChatMessageId.Value != msg.ChatMessageId!.Value) { await ResetMessage(msg); } @@ -133,7 +141,7 @@ public class KasinoMines } await Task.Delay(100); - await _kfChatBot.KfClient.EditMessageAsync(LastMessageId, $"{str}[br]{Creator.User.FormatUsername()}"); + await _kfChatBot.KfClient.EditMessageAsync(LastMessage.ChatMessageId.Value, $"{str}[br]{Creator.User.FormatUsername()}"); } await Task.Delay(TimeSpan.FromSeconds(10)); @@ -278,11 +286,11 @@ public class KasinoMines public async Task Cashout(KasinoMinesGame game) { decimal payout = 0; - decimal possiblePicks = game.Size * game.Size - game.Mines; + decimal numGems = game.Size * game.Size - game.Mines; for (int i = 0; i < game.BetsPlaced.Count; i++) { - payout += game.Wager * (possiblePicks / game.BetsPlaced.Count); - possiblePicks--; + payout += game.Wager * (game.Size * game.Size / numGems); + numGems--; } var newBalance = await Money.NewWagerAsync(game.Creator.Id, game.Wager, payout, WagerGame.Mines); @@ -297,7 +305,7 @@ public class KasinoMines await GetSavedGames(gamblerId); var game = ActiveGames[gamblerId]; game.LastInteracted = DateTimeOffset.UtcNow; - if (game.LastMessageId != msg.ChatMessageId!.Value) + if (game.LastMessage.ChatMessageId.Value != msg.ChatMessageId!.Value) { await game.ResetMessage(msg); } @@ -316,6 +324,12 @@ public class KasinoMines } } + if (validBets.Count == 0) + { + await _kfChatBot.SendChatMessageAsync($"{game.Creator.User.FormatUsername()}, unable to generate valid betting positions, game closed.", true, autoDeleteAfter: TimeSpan.FromSeconds(5)); + return false; + } + if (count > numGems) { count = numGems; @@ -329,13 +343,14 @@ public class KasinoMines await _kfChatBot.SendChatMessageAsync($"{game.Creator.User.FormatUsername()}, you bet on all gems, so you will automatically cash out if you win.", true, autoDeleteAfter: TimeSpan.FromSeconds(5)); cashOut = true; } + //randomly pull from that list to add coordinates to bet on for (int i = 0; i < count; i++) { int rand = Money.GetRandomNumber(game.Creator, 0, validBets.Count - 1); betCoords.Add(validBets[rand]); - validBets.Remove(betCoords[rand]); + validBets.RemoveAt(rand); } return await Bet(gamblerId, betCoords, msg, cashOut, true); @@ -347,7 +362,7 @@ public class KasinoMines await GetSavedGames(gamblerId); var game = ActiveGames[gamblerId]; game.LastInteracted = DateTimeOffset.UtcNow; - if (game.LastMessageId != msg.ChatMessageId!.Value) + if (game.LastMessage.ChatMessageId.Value != msg.ChatMessageId!.Value) { await game.ResetMessage(msg); } @@ -370,18 +385,19 @@ public class KasinoMines } var invalidBetMsg = await _kfChatBot.SendChatMessageAsync($"{game.Creator.User.FormatUsername()}, checking bets...", true); - await _kfChatBot.WaitForChatMessageAsync(invalidBetMsg); + await Task.Delay(3); foreach (var bet in coords) { if (!validBets.Contains(bet) || game.BetsPlaced.Contains(bet) || bets.Contains(bet)) { await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageId!.Value, $"{game.Creator.User.FormatUsername()}, invalid bet of {bet.r},{bet.c} removed (already placed, duplicate, or invalid coordinate)"); + await Task.Delay(3); } else bets.Add(bet); } - await _kfChatBot.KfClient.DeleteMessageAsync(invalidBetMsg.ChatMessageId!.Value); + if (bets.Count > numGems) { @@ -397,6 +413,7 @@ public class KasinoMines cashOut = true; } + await Task.Delay(5); _ = _kfChatBot.KfClient.DeleteMessageAsync(invalidBetMsg.ChatMessageId.Value); }