UNPKG

d-bot

Version:

A quirky Discord bot made for single, small, private servers

156 lines (147 loc) โ€ข 6.34 kB
// Frank Catton can't get past the gaming board var util = require(__base+'core/util.js'); var storage = require(__base+'core/storage.js'); const Deck = require('./deck.js'); const validator = require('./../param-validator.js'); const game = storage.json('blackjack', { multi: 1, min: 10, sessions: {} }, '\t' ); const CHOICES = { hit: '๐Ÿƒ Hit', stay: '๐Ÿ”’ Stay', double: 'โญ๏ธ Double', safety: '๐Ÿ’ธ Safety' }; // TODO: Add split, "You 1" and "You 2" lines in output, commands are given sequentially, "stay hit" // TODO: Search within messages for choice, to allow e.g. 'hit me!' and 'oh god, stay!' const RESULTS = { push: 'โ†”๏ธ **Push**โ€ƒCredits returnedโ€‚`Bal: @bal`', bust: '๐Ÿ’ข **Bust!**โ€ƒ**@net**โ€‚โžœโ€‚`Bal: @bal`', '21': '๐ŸŒŸ **โซท ๐Ÿฎ๐Ÿญ โซธ**โ€ƒ**+@net**โ€‚โžœโ€‚`Bal: @bal`', win: 'โœจ๏ธ **You Win!**โ€ƒ**+@net**โ€‚โžœโ€‚`Bal: @bal`', lose: '๐Ÿ‘Ž **You Lose**โ€ƒ**@net**โ€‚โžœโ€‚`Bal: @bal`', 'safe-won': 'โœ…๏ธ **Safety**โ€ƒ**@net**โ€‚โžœโ€‚`Bal: @bal`', 'safe-lost': 'โ€ƒโŒ Safety lost, **@net**' }; function getScore(cards) { let score = 0, aceCount = 0; cards.map(c => Deck.card(c)).forEach(card => { if(card.number === 'a') aceCount++; score += card.number > 0 ? card.number : card.number === 'a' ? 11 : 10; }); while(score > 21 && aceCount > 0) { score -= 10; aceCount--; } return score; } function dealerDraw(dHand, deck, pScore) { let dScore = getScore(dHand); while(dHand.length === 1 || (dScore < 16 && dScore < pScore && pScore <= 21)) { dHand.push(deck.draw()); dScore = getScore(dHand); } } function play({ userData, deck, pHand, pScore, dHand, dScore, net = 0, choices, bet }, play) { deck = new Deck(deck); bet = bet || play.bet; let gameOver = false; let result; if(!pHand) { // New game deck.shuffle(); pHand = [deck.draw(''), deck.draw('')]; dHand = [deck.draw('')]; choices = ['hit', 'stay']; if(userData.balance >= bet * 2) choices.push('double'); pScore = getScore(pHand); dScore = getScore(dHand); if(pScore === 21) gameOver = true; if(deck.card(dHand[0]).number === 'a') choices.push('safety'); } else { // Playing util.findAndRemove('safety', choices); util.findAndRemove('double', choices); if(play.choice === 'hit' || play.choice === 'double') pHand.push(deck.draw('')); if(play.choice === 'double') bet = bet * 2; pScore = getScore(pHand); if(pScore >= 21 || play.choice === 'stay' || play.choice === 'double') gameOver = true; if(play.choice === 'safety') { dHand.push(deck.draw()); dScore = getScore(dHand); net = -bet / 2; gameOver = gameOver || dScore === 21; result = dScore === 21 ? 'safe-won' : 'safe-lost'; } } if(gameOver) { choices = []; dealerDraw(dHand, deck, pScore); dScore = getScore(dHand); if(result === 'safe-won') { // Nothing happens } else if(pScore > 21) { // Player busts net += -bet; result = 'bust'; } else if(pScore < dScore && dScore <= 21) { // Dealer has better score net += -bet; result = 'lose'; } else if(pScore === 21) { // Player has blackjack if(dScore === 21 && dHand.length <= pHand.length) result = 'push'; // Dealer ties else { // 21!! result = '21'; net += bet * 1.5 * game.get('multi'); } } else if(pScore <= 21 && pScore === dScore) result = 'push'; // Tie else if(pScore > dScore || dScore > 21) { // Better score or dealer busted net += bet * game.get('multi'); result = 'win'; } } return { userData, deck: deck.cards, bet, choices, net: Math.round(net), pHand, pScore, dHand, dScore, result, gameOver } } function getOutput({ pScore, dScore, pHand, dHand, choices, result, net, userData }) { let output = '```ini\n' + `You ${'[ ' + String(pScore).padStart(2) + ' ]'} ${pHand.map(c => Deck.card(c).shortName).join(', ')}\n` + `Dealer ${'[ ' + String(dScore).padStart(2) + ' ]'} ${dHand.map(c => Deck.card(c).shortName).join(', ')}` + '```' + choices.map(c => '`' + CHOICES[c] + '`').join('โ€ƒ'); if(result) output += RESULTS[result].replace('@net', net).replace('@bal', userData.balance + net); return output; } module.exports = { properName: 'Blackjack', names: ['blackjack', 'black-jack', 'bj', '21', 'twentyone', 'twenty-one'], parsePlay(sessionID, userData, params) { let playData = { userData }, session = game.get('sessions')[sessionID]; if(!session) { let validated = validator.validate([ new validator.Pattern(['bet'], params, [ new validator.Param().numeric('โŒ Provide a bet amount') .whole('โŒ Your bet must be a whole number') .min(game.get('min'), `๐Ÿ”บ Minimum bet: ${game.get('min')}`) .max(userData.balance, `โ— You only have ${userData.balance} credits`) ]) ]); playData.bet = +validated.bet; playData.error = validated.error; return playData; } return validator.validate([ new validator.Pattern(['choice'], params, [ new validator.Param().oneOf(session.choices, true) // True argument returns no message ]) ]); }, play(sessionID, playData) { let session = game.get('sessions')[sessionID] || { userData: playData.userData }; game.get('sessions')[sessionID] = session; Object.assign(session, play(session, playData)); let result = { output: getOutput(session), net: session.net }; if(session.gameOver) { delete game.get('sessions')[sessionID]; result.done = true; } game.save(); return result; } };