diff --git a/KfChatDotNetBot/Commands/Kasino/MinesCommand.cs b/KfChatDotNetBot/Commands/Kasino/MinesCommand.cs index 5ccc357..31f1848 100644 --- a/KfChatDotNetBot/Commands/Kasino/MinesCommand.cs +++ b/KfChatDotNetBot/Commands/Kasino/MinesCommand.cs @@ -142,7 +142,7 @@ public class MinesCommand : ICommand int minesCount = Convert.ToInt32(mines.Value); if (minesCount < 1 || minesCount > (boardSize * boardSize) - 1) { - await botInstance.SendChatMessageAsync($"{user.FormatUsername()}, number of mines must be between 1 and {boardSize * boardSize - 1}(boardSize * boardSize - 1).",true, autoDeleteAfter: cleanupDelay); + await botInstance.SendChatMessageAsync($"{user.FormatUsername()}, number of mines must be between 1 and {boardSize * boardSize - 1}(size^2 - 1).",true, autoDeleteAfter: cleanupDelay); return; } //at this point all valid values so good to continue making the game @@ -185,6 +185,11 @@ public class MinesCommand : ICommand } else if (arguments.TryGetValue("betString", out var betString)) //if they are using precise picks manually or from the tool to select specific squares to reveal { + if (betString.Value == "cashout" || betString.Value == " cashout") + { + await KasinoMines.Cashout(KasinoMines.ActiveGames[gambler.Id]); + return; + } var matches = Regex.Matches(message.Message, BetPattern); if (matches.Count == 0 || matches == null) //if invalid bet string { diff --git a/KfChatDotNetBot/Services/KasinoMines.cs b/KfChatDotNetBot/Services/KasinoMines.cs index 7d925ba..2024f18 100644 --- a/KfChatDotNetBot/Services/KasinoMines.cs +++ b/KfChatDotNetBot/Services/KasinoMines.cs @@ -151,9 +151,9 @@ public class KasinoMines bool revealedSpace; for (int r = 0; r < Size; r++) { - revealedSpace = false; for (int c = 0; c < Size; c++) { + revealedSpace = false; foreach (var bet in BetsPlaced) { if (bet.r == r && bet.c == c) revealedSpace = true; @@ -292,7 +292,7 @@ public class KasinoMines await RemoveGame(game.Creator.Id); } - public async Task Bet(int gamblerId, int count, SentMessageTrackerModel msg, bool cashOut = false) //returns false if you hit a bomb, true if you didn't + public async Task Bet(int gamblerId, int count, SentMessageTrackerModel msg, bool cashOut) //returns false if you hit a bomb, true if you didn't { await GetSavedGames(gamblerId); var game = ActiveGames[gamblerId]; @@ -302,18 +302,48 @@ public class KasinoMines await game.ResetMessage(msg); } List<(int r, int c)> betCoords = new(); - (int r, int c) coord; - while (betCoords.Count != count)//creates a list of coordinates to bet on using the coordinate bet function + List<(int r, int c)> validBets = new(); + int numGems = 0; + + //first get a list of valid coordinates that could be bet on + for (int r = 0; r < game.Size; r++) { - coord = (Money.GetRandomNumber(game.Creator, 0, game.Size-1), Money.GetRandomNumber(game.Creator, 0, game.Size-1)); - if (!betCoords.Contains(coord) && !game.BetsPlaced.Contains(coord)) betCoords.Add(coord); + for (int c = 0; c < game.Size; c++) + { + if (game.MinesBoard[r,c] == 'G' && !game.BetsPlaced.Contains((r, c))) numGems++; + else if (!game.BetsPlaced.Contains((r, c))) validBets.Add((r, c)); + + } } - return await Bet(gamblerId, betCoords, msg, cashOut); + if (count > numGems) + { + count = numGems; + await _kfChatBot.SendChatMessageAsync( + $"{game.Creator.User.FormatUsername()}, there are only {numGems} gems left, so you bet on {count} gems, and will automatically cash out if you win.", + true, autoDeleteAfter: TimeSpan.FromSeconds(5)); + cashOut = true; + } + else if (count == numGems && cashOut == false) + { + 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]); + } + + return await Bet(gamblerId, betCoords, msg, cashOut, true); } - public async Task Bet(int gamblerId, List<(int r, int c)> coords, SentMessageTrackerModel msg, bool cashOut = false) + public async Task Bet(int gamblerId, List<(int r, int c)> coords, SentMessageTrackerModel msg, bool cashOut, bool calledFromBet = false) { + await GetSavedGames(gamblerId); var game = ActiveGames[gamblerId]; game.LastInteracted = DateTimeOffset.UtcNow; @@ -321,7 +351,59 @@ public class KasinoMines { await game.ResetMessage(msg); } - foreach (var coord in coords) //the main portion of the game + + List<(int r, int c)> bets = new(); + if (!calledFromBet) + { + List<(int r, int c)> validBets = new(); + int numGems = 0; + + //first get a list of valid coordinates that could be bet on + for (int r = 0; r < game.Size; r++) + { + for (int c = 0; c < game.Size; c++) + { + if (game.MinesBoard[r,c] == 'G' && !game.BetsPlaced.Contains((r, c))) numGems++; + else if (!game.BetsPlaced.Contains((r, c))) validBets.Add((r, c)); + + } + } + + var invalidBetMsg = await _kfChatBot.SendChatMessageAsync($"{game.Creator.User.FormatUsername()}, checking bets...", true); + 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) + { + + await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageId!.Value, + $"{game.Creator.User.FormatUsername()}, you bet on {bets.Count} gems, but there are only {numGems} left. Your list of bets was automatically truncated, and the game will automatically cash out if you win."); + bets.RemoveRange(numGems, bets.Count - numGems); + cashOut = true; + } + else if (bets.Count == numGems) + { + await _kfChatBot.KfClient.EditMessageAsync(invalidBetMsg.ChatMessageId!.Value, + $"{game.Creator.User.FormatUsername()}, you bet on all gems, so you will automatically cash out if you win."); + cashOut = true; + } + + await Task.Delay(5); + _ = _kfChatBot.KfClient.DeleteMessageAsync(invalidBetMsg.ChatMessageId.Value); + + } + else bets = coords; + foreach (var coord in bets) //the main portion of the game { await Task.Delay(100); if (game.MinesBoard[coord.r, coord.c] == 'M') @@ -349,8 +431,10 @@ public class KasinoMines var newBalance = await Money.NewWagerAsync(game.Creator.Id, game.Wager, -game.Wager, WagerGame.Mines); var net = -game.Wager; await _kfChatBot.SendChatMessageAsync( - $"{game.Creator.User.FormatUsername()}, you lost your {await game.Wager.FormatKasinoCurrencyAsync()} bet on mines, collecting {game.BetsPlaced.Count} gems until you hit one of {game.Mines} mines. Net: {await net.FormatKasinoCurrencyAsync()}. Balance: {await newBalance.FormatKasinoCurrencyAsync()}", + $"R! {game.Creator.User.FormatUsername()}, you lost your {await game.Wager.FormatKasinoCurrencyAsync()} bet on mines, collecting {game.BetsPlaced.Count} gems until you hit one of {game.Mines} mines. Net: {await net.FormatKasinoCurrencyAsync()}. Balance: {await newBalance.FormatKasinoCurrencyAsync()}", true, autoDeleteAfter: TimeSpan.FromSeconds(15)); + await RemoveGame(gamblerId); + return false; } else {