Search in sources :

Example 1 with SpaceType

use of tel.discord.rtab.board.SpaceType in project RtaB6 by Telnaior.

the class GameController method useTruesight.

public String useTruesight(int player, int space) {
    Player eyeballer = players.get(player);
    if (player == currentTurn) {
        peekStreak++;
        if (peekStreak == 3)
            Achievement.EXTRA_PEEKS.check(eyeballer);
    }
    channel.sendMessage(eyeballer.getName() + " used an Eye of Truth to look at space " + (space + 1) + "!").queue();
    eyeballer.hiddenCommand = HiddenCommand.NONE;
    String spaceIdentity = gameboard.truesightSpace(space, baseNumerator, baseDenominator);
    SpaceType peekedSpace = gameboard.getType(space);
    // Add the space to the internal list, the same as with a regular peek
    if (peekedSpace.isBomb())
        eyeballer.knownBombs.add(space);
    else
        // Otherwise add it to their known safe spaces
        eyeballer.safePeeks.add(space);
    if (!eyeballer.isBot)
        eyeballer.user.openPrivateChannel().queue((channel) -> channel.sendMessage(String.format("Space %d: **%s**.", space + 1, spaceIdentity)).queue());
    return spaceIdentity;
}
Also used : Cash(tel.discord.rtab.board.Cash) Arrays(java.util.Arrays) Game(tel.discord.rtab.board.Game) ScheduledFuture(java.util.concurrent.ScheduledFuture) Boost(tel.discord.rtab.board.Boost) ListIterator(java.util.ListIterator) BombType(tel.discord.rtab.board.BombType) SpaceType(tel.discord.rtab.board.SpaceType) TextChannel(net.dv8tion.jda.api.entities.TextChannel) Member(net.dv8tion.jda.api.entities.Member) ChannelType(net.dv8tion.jda.api.entities.ChannelType) Board(tel.discord.rtab.board.Board) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Pair(net.dv8tion.jda.internal.utils.tuple.Pair) Guild(net.dv8tion.jda.api.entities.Guild) EventType(tel.discord.rtab.board.EventType) Role(net.dv8tion.jda.api.entities.Role) TestMinigameCommand(tel.discord.rtab.commands.TestMinigameCommand) LinkedList(java.util.LinkedList) ThreadFactory(java.util.concurrent.ThreadFactory) Path(java.nio.file.Path) HiddenCommand(tel.discord.rtab.board.HiddenCommand) Message(net.dv8tion.jda.api.entities.Message) RaceToABillionBot.waiter(tel.discord.rtab.RaceToABillionBot.waiter) Files(java.nio.file.Files) IOException(java.io.IOException) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) MiniGame(tel.discord.rtab.games.MiniGame) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) Paths(java.nio.file.Paths) BooleanSetting(tel.discord.rtab.commands.channel.BooleanSetting) Comparator(java.util.Comparator) MessageReceivedEvent(net.dv8tion.jda.api.events.message.MessageReceivedEvent) Collections(java.util.Collections) SpaceType(tel.discord.rtab.board.SpaceType)

Example 2 with SpaceType

use of tel.discord.rtab.board.SpaceType in project RtaB6 by Telnaior.

the class GameController method runTurn.

private void runTurn(int player) {
    // There is NO reason why we should be running a turn for anyone other than the current player
    if (player != currentTurn)
        return;
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    // If someone from the Gallery has given our hapless player a blammo, they get that instead of their normal turn
    if (futureBlammo) {
        futureBlammo = false;
        resolvingTurn = true;
        if (repeatTurn > 0)
            repeatTurn--;
        channel.sendMessage(players.get(player).getSafeMention() + ", someone from the gallery has given you a **BLAMMO!**").queue();
        startBlammo(player, false);
        return;
    }
    // Count down if necessary
    if (finalCountdown) {
        // End the game if we're out of turns
        if (fcTurnsLeft == 0) {
            gameOver();
            return;
        } else // Otherwise display the appropriate message
        if (fcTurnsLeft == 1)
            channel.sendMessage("The round will end **after this pick!**").queue();
        else
            channel.sendMessage(String.format("The round will end in **%d picks**.", fcTurnsLeft)).queue();
        // And then subtract one
        fcTurnsLeft--;
    }
    // Figure out who to ping and what to tell them
    if (repeatTurn > 0 && !firstPick) {
        if (!(players.get(player).isBot))
            channel.sendMessage(players.get(player).getSafeMention() + ", pick again.").queue();
    } else {
        firstPick = false;
        if (!players.get(player).isBot)
            channel.sendMessage(players.get(player).getSafeMention() + ", your turn. Choose a space on the board.").queue();
    }
    if (repeatTurn > 0)
        repeatTurn--;
    displayBoardAndStatus(true, false, false);
    // Ready up the space picker depending on if it's a bot up next
    if (players.get(player).isBot) {
        // Sleep for a couple of seconds so they don't rush
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // Get safe spaces, starting with all unpicked spaces
        ArrayList<Integer> openSpaces = new ArrayList<>(boardSize);
        for (int i = 0; i < boardSize; i++) if (!pickedSpaces[i])
            openSpaces.add(i);
        // Remove all known bombs
        ArrayList<Integer> safeSpaces = new ArrayList<>(boardSize);
        safeSpaces.addAll(openSpaces);
        for (Integer bomb : players.get(player).knownBombs) safeSpaces.remove(bomb);
        // Test for hidden command stuff
        switch(players.get(player).hiddenCommand) {
            // Fold if they have no peeks, jokers, there's been no starman, and a random chance is hit
            case FOLD:
                if (!starman && players.get(player).peeks < 1 && players.get(player).jokers == 0 && Math.random() * spacesLeft < 1) {
                    useFold(player);
                    return;
                }
                break;
            // Bonus bag under same condition as the fold, but more frequently because of its positive effect
            case BONUS:
                if (!starman && players.get(player).peeks < 1 && players.get(player).jokers == 0 && Math.random() * spacesLeft < 3) {
                    // Let's just pick one randomly
                    SpaceType desire = SpaceType.BOOSTER;
                    if (Math.random() * 2 < 1)
                        desire = SpaceType.GAME;
                    if (Math.random() * 3 < 1)
                        desire = SpaceType.CASH;
                    if (Math.random() * 4 < 1)
                        desire = SpaceType.EVENT;
                    useBonusBag(player, desire);
                    return;
                }
                break;
            // But do increase the chance for it compared to folding
            case BLAMMO:
                if (!starman && players.get(player).peeks < 1 && repeatTurn == 0 && players.get(player).jokers == 0 && Math.random() * spacesLeft < players.size())
                    useBlammoSummoner(player);
                break;
            // Teeeeeechnically it isn't playing to win with this, but it is making the game more exciting for the real players.
            case WAGER:
                if (players.size() * 4 < spacesLeft)
                    useWager(player);
                break;
            // Truesight under the same condition as a peek
            case TRUESIGHT:
                if (safeSpaces.size() > 1 && Math.random() < 0.5) {
                    int truesightIndex = (int) (Math.random() * safeSpaces.size());
                    int truesightSpace = safeSpaces.get(truesightIndex);
                    if (!players.get(player).safePeeks.contains(truesightSpace)) {
                        // We know there's another so this is fine
                        safeSpaces.remove(truesightIndex);
                        String truesightIdentity = useTruesight(player, truesightSpace);
                        boolean badPeek = false;
                        if (truesightIdentity.startsWith("-") || truesightIdentity.contains("BOMB"))
                            badPeek = true;
                        else
                            switch(truesightIdentity) {
                                case "BLAMMO":
                                case "Split & Share":
                                case "Bowser Event":
                                case "Reverse":
                                case "Minefield":
                                    badPeek = true;
                            }
                        if (!badPeek) {
                            resolveTurn(player, truesightSpace);
                            return;
                        }
                    }
                }
                break;
            // With minesweeper, look for an opportunity every turn
            case MINESWEEP:
                if (safeSpaces.size() > 1) {
                    // Look for a space with only one adjacent to it
                    ArrayList<Integer> minesweepOpportunities = new ArrayList<Integer>();
                    for (int i = 0; i < boardSize; i++) if (!pickedSpaces[i]) {
                        int adjacentSpaces = 0;
                        for (int j : RtaBMath.getAdjacentSpaces(i, players.size())) if (!pickedSpaces[j])
                            adjacentSpaces++;
                        if (adjacentSpaces == 1)
                            minesweepOpportunities.add(i);
                    }
                    // If we found one, choose one at random to sweep
                    if (minesweepOpportunities.size() > 0)
                        useMinesweeper(player, minesweepOpportunities.get((int) (Math.random() * minesweepOpportunities.size())));
                }
            // Repel/Defuse/Failsafe are more situational and aren't used at this time
            default:
                break;
        }
        // With chance depending on current board risk, look for a previous peek to use
        if (Math.random() * (spacesLeft - 1) < playersAlive) {
            // Check for known peeked spaces that are still available
            ArrayList<Integer> peekedSpaces = new ArrayList<>(boardSize);
            for (Integer peek : players.get(player).safePeeks) {
                if (openSpaces.contains(peek))
                    peekedSpaces.add(peek);
            }
            // If there's any, pick one and end our logic
            if (peekedSpaces.size() > 0) {
                resolveTurn(player, peekedSpaces.get((int) (Math.random() * peekedSpaces.size())));
                return;
            }
        }
        // If there's any spaces that aren't known bombs, pick one and resolve it
        if (safeSpaces.size() > 0) {
            /*
				 * Use a peek under the following conditions:
				 * - The bot has one to use
				 * - It hasn't already peeked the space selected
				 * - 50% chance (so it won't always fire immediately)
				 * Note that they never bluff peek their own bomb (it's just easier that way)
				 */
            if (players.get(player).peeks > 0 && safeSpaces.size() > 1 && Math.random() < 0.5) {
                int peekSpace = safeSpaces.get((int) (Math.random() * safeSpaces.size()));
                // Don't use the peek if we've already seen this space
                if (!players.get(player).safePeeks.contains(peekSpace)) {
                    // Let the players know what's going on
                    channel.sendMessage("(" + players.get(player).getName() + " peeks space " + (peekSpace + 1) + ")").queue();
                    // Then use the peek, and decide what to do from there
                    switch(usePeek(player, peekSpace)) {
                        // If it's a minigame or booster, take it immediately - it's guaranteed safe
                        case BOOSTER:
                        case GAME:
                            resolveTurn(player, peekSpace);
                            break;
                        // Blammos and grab bags peek as cash and event respectively, so the bot handles them this way too
                        case CASH:
                        case EVENT:
                        case GRAB_BAG:
                        case BLAMMO:
                            if (Math.random() < 0.5 || players.size() == 2)
                                resolveTurn(player, peekSpace);
                            else
                                resolveTurn(player, safeSpaces.get((int) (Math.random() * safeSpaces.size())));
                            break;
                        // And obviously, don't pick it if it's a bomb!
                        case BOMB:
                        case GB_BOMB:
                            safeSpaces.remove(new Integer(peekSpace));
                            // Make sure there's still a safe space left to pick, otherwise BAH
                            if (safeSpaces.size() > 0)
                                resolveTurn(player, safeSpaces.get((int) (Math.random() * safeSpaces.size())));
                            else
                                resolveTurn(player, openSpaces.get((int) (Math.random() * openSpaces.size())));
                            break;
                    }
                } else // If we've already peeked the space we rolled, let's just take it
                {
                    resolveTurn(player, peekSpace);
                }
            } else
                // Otherwise just pick a space
                resolveTurn(player, safeSpaces.get((int) (Math.random() * safeSpaces.size())));
        } else // Otherwise it sucks to be you, bot, eat bomb (or defuse bomb) (or failsafe)!
        {
            if (players.get(player).hiddenCommand == HiddenCommand.FAILSAFE) {
                useFailsafe(player);
                return;
            }
            int bombToPick = openSpaces.get((int) (Math.random() * openSpaces.size()));
            if (players.get(player).hiddenCommand == HiddenCommand.DEFUSE)
                useShuffler(player, bombToPick);
            resolveTurn(player, bombToPick);
        }
    } else {
        warnPlayer = timer.schedule(() -> {
            // If they're out of the round somehow, why are we warning them?
            if (players.get(player).status == PlayerStatus.ALIVE && gameStatus == GameStatus.IN_PROGRESS && player == currentTurn && !resolvingTurn) {
                channel.sendMessage(players.get(player).getSafeMention() + ", thirty seconds left to choose a space!").queue();
                displayBoardAndStatus(true, false, false);
            }
        }, 60, TimeUnit.SECONDS);
        waiter.waitForEvent(MessageReceivedEvent.class, // Right player and channel
        e -> {
            if (players.get(player).status != PlayerStatus.ALIVE || gameStatus != GameStatus.IN_PROGRESS || player != currentTurn) {
                return true;
            } else if (e.getAuthor().equals(players.get(player).user) && e.getChannel().equals(channel) && checkValidNumber(e.getMessage().getContentStripped())) {
                int location = Integer.parseInt(e.getMessage().getContentStripped());
                try {
                    if (pickedSpaces[location - 1]) {
                        channel.sendMessage("That space has already been picked.").queue();
                        return false;
                    } else {
                        return true;
                    }
                } catch (ArrayIndexOutOfBoundsException e1) {
                    return false;
                }
            }
            return false;
        }, // Parse it and call the method that does stuff
        e -> {
            warnPlayer.cancel(false);
            // If they're somehow taking their turn when they're out of the round, just don't do anything
            if (players.get(player).status == PlayerStatus.ALIVE && gameStatus == GameStatus.IN_PROGRESS && player == currentTurn) {
                int location = Integer.parseInt(e.getMessage().getContentStripped()) - 1;
                // Anyway go play out their turn
                timer.schedule(() -> resolveTurn(player, location), 500, TimeUnit.MILLISECONDS);
            }
        }, 90, TimeUnit.SECONDS, () -> {
            // If they're somehow taking their turn when they shouldn't be, just don't do anything
            if (players.get(player).status == PlayerStatus.ALIVE && gameStatus == GameStatus.IN_PROGRESS && player == currentTurn && !resolvingTurn) {
                timer.schedule(() -> timeOutTurn(player), 500, TimeUnit.MILLISECONDS);
            }
        });
    }
}
Also used : SpaceType(tel.discord.rtab.board.SpaceType) ArrayList(java.util.ArrayList)

Example 3 with SpaceType

use of tel.discord.rtab.board.SpaceType in project RtaB6 by Telnaior.

the class BonusCommand method execute.

@Override
protected void execute(CommandEvent event) {
    for (GameController game : RaceToABillionBot.game) {
        if (game.channel.equals(event.getChannel())) {
            SpaceType desire;
            switch(event.getArgs().toUpperCase()) {
                case "CASH":
                case "C":
                case "MONEY":
                case "M":
                    desire = SpaceType.CASH;
                    break;
                case "BOOST":
                case "BOOSTER":
                case "B":
                    desire = SpaceType.BOOSTER;
                    break;
                case "MINIGAME":
                case "GAME":
                case "G":
                    desire = SpaceType.GAME;
                    break;
                case "EVENT":
                case "E":
                case "SPLIT AND SHARE":
                    desire = SpaceType.EVENT;
                    break;
                case "BOMB":
                    event.reply("Well, if you say so.");
                case "GRAB BAG":
                case "BILLION":
                case "ONE BILLION DOLLARS":
                case "A BILLION DOLLARS":
                case "A BILLION":
                case "AMULET OF YENDOR":
                case "THE AMULET OF YENDOR":
                    // greedy
                    desire = SpaceType.BOMB;
                    break;
                // Useless memes follow
                case "BLAMMO":
                    if (Math.random() < 0.5)
                        event.reply("Does this look like !blammo to you?");
                    else
                        event.reply("There are no blammos in the bonus bag.");
                    return;
                case "NUMBERWANG":
                case "NEGATIVE BILLION":
                case "A NEGATIVE BILLION":
                    event.reply("You found **Numberwang**, worth shinty-six. Your score is unaffected.");
                    return;
                case "TRIFORCE":
                    event.reply("You found **The Triforce**! " + "Click here to claim your prize: <https://www.youtube.com/watch?v=dQw4w9WgXcQ>");
                    return;
                case "MEME":
                    event.reply("https://niceme.me");
                    return;
                case "HIDDEN":
                case "HIDDEN COMMAND":
                case "A HIDDEN COMMAND":
                    event.reply("If you're using this command, you already have one.");
                    return;
                case "BLESSED FIXED GREASED +2 GRAY DRAGON SCALE MAIL":
                case "BLESSED FIXED GREASED +2 GREY DRAGON SCALE MAIL":
                case "BLESSED FIXED GREASED +2 SILVER DRAGON SCALE MAIL":
                    event.reply("Unfortunately, nothing happens. (It's the bonus bag, not a wand of wishing)");
                    return;
                default:
                    event.reply("Use !bonus cash, !bonus boost, !bonus game, or !bonus event to specify what you want.");
                    return;
            }
            int player = game.findPlayerInGame(event.getAuthor().getId());
            // it's their turn, and they haven't picked a space) (this is getting a little silly)
            if (game.gameStatus != GameStatus.IN_PROGRESS || player != game.currentTurn || game.resolvingTurn || game.currentBlammo || game.players.get(player).status != PlayerStatus.ALIVE || game.players.get(player).hiddenCommand != HiddenCommand.BONUS)
                event.reply("You can't do this right now.");
            else
                game.useBonusBag(player, desire);
            return;
        }
    }
    // We aren't in a game channel? Uh...
    event.reply("This is not a game channel.");
}
Also used : SpaceType(tel.discord.rtab.board.SpaceType) GameController(tel.discord.rtab.GameController)

Example 4 with SpaceType

use of tel.discord.rtab.board.SpaceType in project RtaB6 by Telnaior.

the class GameController method usePeek.

public SpaceType usePeek(int playerID, int space) {
    Player peeker = players.get(playerID);
    peeker.peeks--;
    if (playerID == currentTurn) {
        peekStreak++;
        if (peekStreak == 3)
            Achievement.EXTRA_PEEKS.check(peeker);
    }
    SpaceType peekedSpace = gameboard.getType(space);
    // If it's a bomb, add it to their known bombs
    if (peekedSpace.isBomb())
        peeker.knownBombs.add(space);
    else
        // Otherwise add it to their known safe spaces
        peeker.safePeeks.add(space);
    // If they're human, actually tell them what they won
    if (!peeker.isBot) {
        String peekClaim;
        switch(peekedSpace) {
            case CASH:
            case BLAMMO:
                peekClaim = "**CASH**";
                break;
            case GAME:
                peekClaim = "a **MINIGAME**";
                break;
            case BOOSTER:
                peekClaim = "a **BOOSTER**";
                break;
            case EVENT:
            case GRAB_BAG:
                peekClaim = "an **EVENT**";
                break;
            case BOMB:
            case GB_BOMB:
                peekClaim = "a **BOMB**";
                break;
            default:
                peekClaim = "an **ERROR**";
                break;
        }
        peeker.user.openPrivateChannel().queue((channel) -> channel.sendMessage(String.format("Space %d is %s.", space + 1, peekClaim)).queue());
    }
    return peekedSpace;
}
Also used : SpaceType(tel.discord.rtab.board.SpaceType)

Aggregations

SpaceType (tel.discord.rtab.board.SpaceType)4 ArrayList (java.util.ArrayList)2 IOException (java.io.IOException)1 Files (java.nio.file.Files)1 Path (java.nio.file.Path)1 Paths (java.nio.file.Paths)1 Arrays (java.util.Arrays)1 Collections (java.util.Collections)1 Comparator (java.util.Comparator)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 ListIterator (java.util.ListIterator)1 ScheduledFuture (java.util.concurrent.ScheduledFuture)1 ScheduledThreadPoolExecutor (java.util.concurrent.ScheduledThreadPoolExecutor)1 ThreadFactory (java.util.concurrent.ThreadFactory)1 TimeUnit (java.util.concurrent.TimeUnit)1 ChannelType (net.dv8tion.jda.api.entities.ChannelType)1 Guild (net.dv8tion.jda.api.entities.Guild)1 Member (net.dv8tion.jda.api.entities.Member)1