From 2cfb7e233869b61fcc9000fb57963d1da56d6670 Mon Sep 17 00:00:00 2001 From: Daniel Odendahl Jr Date: Mon, 17 Sep 2018 16:23:27 +0000 Subject: [PATCH] Blackjack Command --- README.md | 3 +- commands/games/blackjack.js | 141 ++++++++++++++++++++++++++++++++++++ commands/random/reddit.js | 2 +- package.json | 2 +- 4 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 commands/games/blackjack.js diff --git a/README.md b/README.md index 3579702d..8666b531 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Xiao is a Discord bot coded in JavaScript with The bot is no longer available for invite. You can self-host the bot, or use her on the [home server](https://discord.gg/sbMe32W). -## Commands (309) +## Commands (310) ### Utility: * **eval:** Executes JavaScript code. @@ -198,6 +198,7 @@ on the [home server](https://discord.gg/sbMe32W). * **akinator:** Think about a real or fictional character, I will try to guess who it is. * **balloon-pop:** Don't let yourself be the last one to pump the balloon before it pops! * **battle:** Engage in a turn-based battle against another user or the AI. +* **blackjack:** Play a game of blackjack. * **box-choosing:** Do you believe that there are choices in life? Taken from Higurashi Chapter 4. * **captcha-quiz:** Try to guess what the captcha says. * **chance:** Attempt to win with a 1 in 1000 (or your choice) chance of winning. diff --git a/commands/games/blackjack.js b/commands/games/blackjack.js new file mode 100644 index 00000000..3ca2bb4b --- /dev/null +++ b/commands/games/blackjack.js @@ -0,0 +1,141 @@ +const Command = require('../../structures/Command'); +const { stripIndents } = require('common-tags'); +const { shuffle, verify } = require('../../util/Util'); +const suits = ['♣', '♥', '♦', '♠']; +const faces = ['Jack', 'Queen', 'King']; + +module.exports = class BlackjackCommand extends Command { + constructor(client) { + super(client, { + name: 'blackjack', + aliases: ['twenty-one', '21'], + group: 'games', + memberName: 'blackjack', + description: 'Play a game of blackjack.' + }); + + this.decks = new Map(); + } + + async run(msg) { + if (this.decks.has(msg.channel.id)) return msg.reply('Only one game may be occurring per channel.'); + try { + this.decks.set(msg.channel.id, this.generateDeck()); + const dealerHand = []; + this.draw(msg.channel, dealerHand); + this.draw(msg.channel, dealerHand); + const playerHand = []; + this.draw(msg.channel, playerHand); + this.draw(msg.channel, playerHand); + const dealerInitialTotal = this.calculate(dealerHand); + const playerInitialTotal = this.calculate(playerHand); + if (dealerInitialTotal === 21 && playerInitialTotal === 21) { + this.decks.remove(msg.channel.id); + return msg.say('Well, both of you just hit blackjack. Right away. Rigged.'); + } else if (dealerInitialTotal === 21) { + this.decks.remove(msg.channel.id); + return msg.say('Ouch, the dealer hit blackjack right away! Try again!'); + } else if (playerInitialTotal === 21) { + this.decks.remove(msg.channel.id); + return msg.say('Wow, you hit blackjack right away! Lucky you!'); + } + let noDealerShow = true; + let playerTurn = true; + let win = false; + let reason; + while (!win) { + if (playerTurn) { + const dealerHandDisplay = dealerHand.map((card, i) => noDealerShow && i > 0 ? '???' : card.display); + await msg.say(stripIndents` + **Dealer:** + ${dealerHandDisplay.join('\n')} + + **You:** + ${playerHand.map(card => card.display).join('\n')} + + _Hit?_ + `); + const hit = await verify(msg.channel, msg.author); + if (hit) { + const card = this.draw(msg.channel, playerHand); + const total = this.calculate(playerHand); + if (total > 21) { + reason = `Drew ${card.display}, total of ${total}! Bust`; + break; + } + } else { + noDealerShow = false; + playerTurn = false; + } + } else { + const card = this.draw(msg.channel, dealerHand); + const total = this.calculate(dealerHand); + if (total > 21) { + reason = `Drew ${card.display}, total of ${total}! Dealer bust`; + win = true; + } + if (total >= 17) { + const playerTotal = this.calculate(playerHand); + if (total === playerTotal) { + reason = `${playerTotal}-${total}`; + break; + } else if (total > playerTotal) { + reason = `${playerTotal}-**${total}**`; + break; + } else { + reason = `**${playerTotal}**-${total}`; + win = true; + } + } + } + } + this.decks.remove(msg.channel.id); + if (win) return msg.say(`${reason}! You won!`); + return msg.say(`${reason}! Too bad.`); + } catch (err) { + this.decks.remove(msg.channel.id); + throw err; + } + } + + generateDeck() { + const deck = []; + for (let i = 0; i < 6; i++) { + for (const suit of suits) { + deck.push({ + value: 11, + display: `${suit} Ace` + }); + for (let j = 2; j <= 10; j++) { + deck.push({ + value: j, + display: `${suit} ${j}` + }); + } + for (const face of faces) { + deck.push({ + value: 10, + display: `${suit} ${face}` + }); + } + } + } + return shuffle(deck); + } + + draw(channel, hand) { + const deck = this.decks.get(channel.id); + const card = deck[0]; + deck.shift(); + hand.push(card); + return card; + } + + calculate(hand) { + return hand.reduce((a, b) => { + let { value } = b; + if (value === 11 && a + value > 21) value = 1; + return a + value; + }, 0); + } +}; diff --git a/commands/random/reddit.js b/commands/random/reddit.js index d37537bc..04c8e3f7 100644 --- a/commands/random/reddit.js +++ b/commands/random/reddit.js @@ -6,7 +6,7 @@ module.exports = class RedditCommand extends Command { constructor(client) { super(client, { name: 'reddit', - aliases: ['subreddit', 'r/'], + aliases: ['subreddit', 'r', 'r/', 'sub'], group: 'random', memberName: 'reddit', description: 'Responds with a random post from a subreddit.', diff --git a/package.json b/package.json index 37241fda..afef31d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xiao", - "version": "91.3.2", + "version": "91.4.0", "description": "Your personal server companion.", "main": "Xiao.js", "scripts": {