756 lines
28 KiB
JavaScript
756 lines
28 KiB
JavaScript
"use strict";
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var blackjack_exports = {};
|
|
__export(blackjack_exports, {
|
|
Blackjack: () => Blackjack,
|
|
commands: () => commands,
|
|
roomSettings: () => roomSettings
|
|
});
|
|
module.exports = __toCommonJS(blackjack_exports);
|
|
var import_lib = require("../../lib");
|
|
/**
|
|
* Blackjack Game
|
|
* Pokemon Showdown - http://pokemonshowdown.com/
|
|
*
|
|
* This allows users to play the classic blackjack card game.
|
|
* Credits: jd, panpawn
|
|
*
|
|
* @license MIT license
|
|
*/
|
|
class Blackjack extends Rooms.RoomGame {
|
|
constructor(room, user, autostartMinutes = 0) {
|
|
super(room);
|
|
this.gameNumber = room.nextGameNumber();
|
|
this.room = room;
|
|
this.turnTimeoutMinutes = 1;
|
|
this.timerTickSeconds = 5;
|
|
this.createdBy = user.name;
|
|
this.startedBy = "";
|
|
this.allowRenames = true;
|
|
this.playerCap = 16;
|
|
this.minimumPlayers = 2;
|
|
this.playerScrollWheel = 4;
|
|
this.cardWidth = 50;
|
|
this.cardHeight = 85;
|
|
this.spectators = /* @__PURE__ */ Object.create(null);
|
|
this.dealer = new BlackjackDealer();
|
|
this.symbols = {
|
|
"\u2665": "Hearts",
|
|
"\u2666": "Diamonds",
|
|
"\u2663": "Clubs",
|
|
"\u2660": "Spades"
|
|
};
|
|
this.deck = new BlackjackDeck().shuffle();
|
|
this.roomID = this.room.roomid;
|
|
this.title = `Blackjack (${room.title})`;
|
|
this.state = "signups";
|
|
this.lastMessage = "";
|
|
this.turnLog = "";
|
|
this.uhtmlChange = "";
|
|
this.curUsername = "";
|
|
this.endedBy = "";
|
|
this.infoboxLimited = "";
|
|
this.button = '<button class="button" name="send" value="/joingame" title="Join Blackjack">Join</button> | <button class="button" name="send" value="/leavegame" title="Leave Blackjack">Leave</button>';
|
|
this.spectateButton = '<button class="button" name="send" value="/blackjack spectate" title="Spectate Blackjack">Spectate</button>';
|
|
this.slideButton = '<button class="button" name="send" value="/blackjack slide" title="Slide the game log down in the chat">(<i class="fa fa-arrow-down" aria-hidden="true"></i> slide)</button>';
|
|
this.autostart = null;
|
|
this.dqTimer = null;
|
|
this.timerTick = null;
|
|
this.makeGame(autostartMinutes);
|
|
}
|
|
/**
|
|
* Game Setup
|
|
* makeGame - configures required settings for creating a game
|
|
* makePlayer - adds blackjack-specific properties to player object
|
|
* sendInvite - called when a game is created, or when a player joins/leaves
|
|
*/
|
|
makeGame(autostartMinutes = 0) {
|
|
if (autostartMinutes > 0) {
|
|
this.autostart = setTimeout(() => this.start(), autostartMinutes * 6e4);
|
|
}
|
|
this.sendInvite();
|
|
}
|
|
makePlayer(user) {
|
|
return new BlackjackPlayer(user, this);
|
|
}
|
|
sendInvite() {
|
|
const change = this.uhtmlChange;
|
|
const players = Object.keys(this.playerTable);
|
|
const playerList = [];
|
|
for (const player of players)
|
|
playerList.push(import_lib.Utils.escapeHTML(this.playerTable[player].name));
|
|
this.room.send(`|uhtml${change}|blackjack-${this.gameNumber}|<div class="infobox${this.infoboxLimited}">${this.createdBy} has created a game of Blackjack. ${this.button}<br /><strong>Players (${players.length}):</strong> ${!players.length ? "(None)" : playerList.join(", ")}</div>`);
|
|
this.uhtmlChange = "change";
|
|
}
|
|
/**
|
|
* Joining/Leaving/Viewing
|
|
* joinGame - joins the game
|
|
* leaveGame - leaves the game
|
|
* spectate - spectates the game
|
|
* unspectate - stops spectating the game
|
|
*/
|
|
joinGame(user) {
|
|
if (!user.named)
|
|
return this.errorMessage(user, `You must first choose a name to play Blackjack.`);
|
|
if (this.state === "started")
|
|
return this.errorMessage(user, `Blackjack has already started.`);
|
|
const joined = this.addPlayer(user);
|
|
if (!joined) {
|
|
this.errorMessage(user, `You are already in this game.`);
|
|
return false;
|
|
}
|
|
this.sendInvite();
|
|
if (Object.keys(this.playerTable).length === this.playerCap) {
|
|
this.start();
|
|
}
|
|
if (this.spectators[user.id])
|
|
delete this.spectators[user.id];
|
|
return true;
|
|
}
|
|
leaveGame(user) {
|
|
if (this.state === "started")
|
|
return this.errorMessage(user, `You cannot leave this game; it has already started.`);
|
|
if (!this.playerTable[user.id])
|
|
return this.errorMessage(user, "You are not in this game to leave.");
|
|
this.removePlayer(user);
|
|
this.sendInvite();
|
|
}
|
|
spectate(user) {
|
|
if (this.spectators[user.id])
|
|
return this.errorMessage(user, `You are already spectating this game.`);
|
|
if (this.playerTable[user.id]) {
|
|
return this.errorMessage(user, `You don't need to spectate the game; you're playing the game.`);
|
|
}
|
|
this.spectators[user.id] = user.id;
|
|
user.sendTo(this.roomid, `You are now spectating this game.`);
|
|
}
|
|
unspectate(user) {
|
|
if (!this.spectators[user.id])
|
|
return this.errorMessage(user, `You are already not spectating this game.`);
|
|
delete this.spectators[user.id];
|
|
user.sendTo(this.roomid, `You are no longer spectating this game.`);
|
|
}
|
|
/**
|
|
* Utility
|
|
* errorMessage - sends a user an error message
|
|
* add - adds/sends text to room
|
|
* display - displays gameplay to players and spectators
|
|
* clear - clears a user's gameplay screen
|
|
* clearAllTimers - clears all possible existing timers pertaining to blackjack
|
|
* slide - slides the game log down in the chat
|
|
* onConnect - handles replies to send when a user joins the room, if any
|
|
* onUpdateConnection - overrides default onUpdateConnection
|
|
* createTimer - creates a timer with a countdown for a player
|
|
* generateCard - generates the card for the UI
|
|
* getWinners - returns an array of the winners and their cards
|
|
*/
|
|
errorMessage(user, message) {
|
|
user.sendTo(this.room, import_lib.Utils.html`|html|<div class="message-error">${message}</div>`);
|
|
}
|
|
send(message, clean = false) {
|
|
const change = this.uhtmlChange;
|
|
this.room.send(`|uhtml${change}|blackjack-${this.gameNumber}|<div class="infobox${this.infoboxLimited}">${clean ? message : this.lastMessage + message}</div>`);
|
|
this.lastMessage += message;
|
|
this.uhtmlChange = "change";
|
|
}
|
|
display(text, clean = false, playerName, noChange = false, end = false) {
|
|
const force = end && this.endedBy;
|
|
let change = this.uhtmlChange;
|
|
if (noChange)
|
|
change = "";
|
|
if (clean)
|
|
this.lastMessage = "";
|
|
const message = `|uhtml${change}|blackjack-${this.gameNumber}|<div class="infobox${this.infoboxLimited}">`;
|
|
this.lastMessage += text;
|
|
if (end) {
|
|
text = `The game of blackjack has ${force ? `been forcibly ended by ${this.endedBy}` : "ended"}. <details><summary>View turn log</summary>${this.turnLog}</details>${text}`;
|
|
this.lastMessage = "";
|
|
}
|
|
for (const player of Object.keys(this.playerTable)) {
|
|
if (playerName && this.playerTable[player].name === playerName) {
|
|
this.playerTable[player].gameLog += `<span class="highlighted">${text}</span>`;
|
|
this.playerTable[player].sendRoom(`${message}${end ? text : this.playerTable[player].gameLog}</div>`);
|
|
} else {
|
|
this.playerTable[player].gameLog += text;
|
|
this.playerTable[player].sendRoom(`${message}${end ? text : this.playerTable[player].gameLog}</div>`);
|
|
}
|
|
}
|
|
for (const spectatorID of Object.keys(this.spectators)) {
|
|
const spectator = Users.get(this.spectators[spectatorID]);
|
|
if (spectator)
|
|
spectator.sendTo(this.roomid, `${message}${this.lastMessage + text}</div>`);
|
|
}
|
|
}
|
|
clear() {
|
|
const player = this.playerTable[this.curUsername];
|
|
if (!player)
|
|
throw new Error(`Player not in player table`);
|
|
player.sendRoom(`|uhtmlchange|user-blackjack-${this.gameNumber}|`);
|
|
}
|
|
clearAllTimers() {
|
|
if (this.dqTimer) {
|
|
clearTimeout(this.dqTimer);
|
|
this.dqTimer = null;
|
|
}
|
|
if (this.timerTick) {
|
|
clearInterval(this.timerTick);
|
|
this.timerTick = null;
|
|
}
|
|
if (this.autostart) {
|
|
clearTimeout(this.autostart);
|
|
this.autostart = null;
|
|
}
|
|
}
|
|
slide(user) {
|
|
user.sendTo(this.roomid, `|uhtml|blackjack-${this.gameNumber}|`);
|
|
this.display("", false, user.name);
|
|
}
|
|
onConnect(user) {
|
|
const message = `|uhtml|blackjack-${this.gameNumber}|<div class="infobox${this.infoboxLimited}">`;
|
|
if (this.state === "signups") {
|
|
this.sendInvite();
|
|
} else if (this.state === "started") {
|
|
const player = this.playerTable[user.id];
|
|
const spectator = this.spectators[user.id];
|
|
if (player && user.id === toID(this.curUsername)) {
|
|
player.sendRoom(`${message}${player.gameLog}`);
|
|
player.sendRoom(player.playScreen.replace("|uhtmlchange|", "|uhtml|"));
|
|
return;
|
|
} else if (player) {
|
|
player.sendRoom(`${message}${player.gameLog}`);
|
|
return;
|
|
} else if (spectator) {
|
|
user.sendTo(this.roomid, `${message}${this.lastMessage}`);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
onUpdateConnection() {
|
|
}
|
|
createTimer(user) {
|
|
const player = this.playerTable[user.id];
|
|
this.dqTimer = setTimeout(() => {
|
|
let cards = "";
|
|
for (const card of player.cards)
|
|
cards += `[${card}] `;
|
|
player.status = "stand";
|
|
this.display(
|
|
import_lib.Utils.html`<br /><strong>${player.name}</strong> stands with ${cards}` + ` (${player.points}) (Auto-stand: took too long to move)`,
|
|
false,
|
|
this.playerTable[this.curUsername].name
|
|
);
|
|
this.clear();
|
|
this.next();
|
|
}, this.turnTimeoutMinutes * 60 * 1e3);
|
|
this.timerTick = setInterval(() => {
|
|
const display = player.playScreen.replace("|uhtml|", "|uhtmlchange|");
|
|
if (display !== "") {
|
|
const timeLeft = player.timerTicksLeft - 5;
|
|
const buffer = String(timeLeft).length === 1 ? "0" : "";
|
|
const half = timeLeft <= this.turnTimeoutMinutes * 60 / 2;
|
|
player.sendRoom(`${display} | <span${half ? ` class="message-error"` : ``}>[<i class="fa fa-hourglass-${half ? 2 : 1}" aria-hidden="true"></i> 0:${buffer}${timeLeft}]</span>`);
|
|
player.timerTicksLeft -= this.timerTickSeconds;
|
|
}
|
|
}, this.timerTickSeconds * 1e3);
|
|
}
|
|
generateCard(card) {
|
|
const value = toID(card).toUpperCase();
|
|
const symbolName = this.symbols[card.substr(-1)];
|
|
const red = ["D", "H"].includes(symbolName.charAt(0));
|
|
let cardUI = value;
|
|
if (value === "K")
|
|
cardUI = "King";
|
|
if (value === "Q")
|
|
cardUI = "Queen";
|
|
if (value === "A")
|
|
cardUI = "Ace";
|
|
if (value === "J")
|
|
cardUI = "Joker";
|
|
return `<div title="${cardUI} of ${symbolName}" style="color: ${red ? "#992222" : "#000000"}; border-radius: 6px; background-color: #ffffff; position: relative; font-size: 14px; display: inline-block; width: ${this.cardWidth}px; height: ${this.cardHeight}px; border: 1px solid #000000; padding: 2px 4px;">${value}<br /> ${card.substr(-1)}<br /><span style="padding: 2px 4px; position: absolute; bottom: 0; right: 0; transform: rotate(-180deg);">${value}<br />${card.substr(-1)}</span></div> `;
|
|
}
|
|
getWinners(forceend = false) {
|
|
const winners = [];
|
|
if (forceend)
|
|
this.giveCard("dealer");
|
|
if (this.dealer.points > 21) {
|
|
for (const player of Object.keys(this.playerTable)) {
|
|
if (this.playerTable[player].status === "bust")
|
|
continue;
|
|
winners.push(
|
|
import_lib.Utils.html`<strong>${this.playerTable[player].name}</strong> ` + `[${this.playerTable[player].cards.join(", ")}]`
|
|
);
|
|
}
|
|
} else if (this.dealer.points !== 21) {
|
|
for (const player of Object.keys(this.playerTable)) {
|
|
if (this.playerTable[player].status === "bust" || this.playerTable[player].points <= this.dealer.points)
|
|
continue;
|
|
winners.push(
|
|
import_lib.Utils.html`<strong>${this.playerTable[player].name}</strong> ` + `[${this.playerTable[player].cards.join(", ")}]`
|
|
);
|
|
}
|
|
} else if (this.dealer.points === 21) {
|
|
winners.push(`<strong>${this.dealer.name}</strong> [${this.dealer.cards.join(", ")}]`);
|
|
}
|
|
return winners;
|
|
}
|
|
/**
|
|
* Game State Changes
|
|
* start - starts the game
|
|
* end - ends the game
|
|
* destroy - destroys the game
|
|
*/
|
|
start(user) {
|
|
const numberOfPlayers = Object.keys(this.playerTable).length;
|
|
if (numberOfPlayers < this.minimumPlayers) {
|
|
if (this.autostart) {
|
|
clearTimeout(this.autostart);
|
|
this.autostart = null;
|
|
}
|
|
this.send("<br />Not enough players to start; game canceled.");
|
|
this.destroy();
|
|
return;
|
|
}
|
|
if (user)
|
|
this.startedBy = import_lib.Utils.escapeHTML(user.name);
|
|
this.infoboxLimited = numberOfPlayers >= this.playerScrollWheel ? " infobox-limited" : "";
|
|
this.send(`[Blackjack has started. ${this.spectateButton}]`, true);
|
|
this.curUsername = Object.keys(this.playerTable)[0];
|
|
const header = `The game of blackjack has started${this.startedBy !== "" ? ` (started by ${this.startedBy})` : ``}. ${this.slideButton}<br />`;
|
|
this.state = "started";
|
|
this.giveCard("dealer");
|
|
this.giveCard("dealer");
|
|
this.turnLog += `<strong>${this.dealer.name}</strong>: [${this.dealer.cards[0]}]`;
|
|
for (const player of Object.keys(this.playerTable)) {
|
|
this.giveCard(this.playerTable[player].user.id);
|
|
this.giveCard(this.playerTable[player].user.id);
|
|
this.turnLog += import_lib.Utils.html`<br /><strong>${this.playerTable[player].name}</strong>: ` + `[${this.playerTable[player].cards[0]}] [${this.playerTable[player].cards[1]}] (${this.playerTable[player].points})`;
|
|
}
|
|
this.display(`${header}${this.turnLog}`, true, "");
|
|
this.next();
|
|
}
|
|
end(user, cmd) {
|
|
const force = cmd && toID(cmd) === "forceend";
|
|
if (user === true) {
|
|
this.state = "ended";
|
|
this.destroy();
|
|
return true;
|
|
}
|
|
if (this.state === "started" && cmd && !force) {
|
|
return this.errorMessage(
|
|
user,
|
|
`Because this game has started, you can only end this game by using /blackjack forceend.`
|
|
);
|
|
}
|
|
let winners = this.getWinners();
|
|
if (force) {
|
|
winners = this.getWinners(true);
|
|
this.endedBy = import_lib.Utils.escapeHTML(user.name);
|
|
if (this.curUsername) {
|
|
this.playerTable[this.curUsername].send(`|uhtmlchange|user-blackjack-${this.gameNumber}|`);
|
|
}
|
|
if (winners.length < 1) {
|
|
this.display(`There are no winners this time.`, false, void 0, false, true);
|
|
} else {
|
|
this.display(`<strong>Winner${Chat.plural(winners.length)}</strong>: ${winners.join(", ")}`, false, void 0, false, true);
|
|
}
|
|
}
|
|
if (!force && this.state !== "signups") {
|
|
if (winners.length < 1) {
|
|
this.display(`There are no winners this time.`, false, void 0, false, true);
|
|
} else {
|
|
this.display(`<strong>Winner${Chat.plural(winners.length)}</strong>: ${winners.join(", ")}`, false, void 0, false, true);
|
|
}
|
|
} else if (this.state === "signups") {
|
|
this.send(
|
|
import_lib.Utils.html`The game of blackjack has been ended by ${user.name}, ` + `and there are no winners because the game never started.`,
|
|
true
|
|
);
|
|
}
|
|
this.state = "ended";
|
|
this.destroy();
|
|
return true;
|
|
}
|
|
destroy() {
|
|
if (Object.keys(this.playerTable).length) {
|
|
for (const player of Object.keys(this.playerTable)) {
|
|
this.playerTable[player].destroy();
|
|
}
|
|
}
|
|
this.clearAllTimers();
|
|
this.room.game = null;
|
|
}
|
|
/**
|
|
* Gameplay
|
|
* hit - player decides to get a new card
|
|
* stand - player decides to keep current cards
|
|
* giveCard - gives a player a card from the deck
|
|
* getCardPoints - returns the point value of a user's cards
|
|
* next - game goes on to the next turn
|
|
*/
|
|
hit(user) {
|
|
if (this.state !== "started")
|
|
return this.errorMessage(user, `Blackjack hasn't started yet.`);
|
|
if (!this.playerTable[user.id])
|
|
return this.errorMessage(user, `You aren't a player in this game.`);
|
|
if (this.curUsername !== user.id)
|
|
return this.errorMessage(user, `It's not your turn.`);
|
|
this.playerTable[user.id].selfUhtml = "change";
|
|
this.playerTable[user.id].resetTimerTicks();
|
|
this.giveCard(user.id);
|
|
}
|
|
stand(user) {
|
|
const player = this.playerTable[user.id];
|
|
if (this.state !== "started")
|
|
return this.errorMessage(user, `Blackjack hasn't started yet.`);
|
|
if (!player)
|
|
return this.errorMessage(user, `You aren't a player in this game.`);
|
|
if (this.curUsername !== user.id)
|
|
return this.errorMessage(user, `It's not your turn.`);
|
|
player.status = "stand";
|
|
let cards = "";
|
|
for (const card of player.cards)
|
|
cards += `[${card}] `;
|
|
const turnLine = import_lib.Utils.html`<br /><strong>${player.name}</strong> stands with ${cards} ` + `(${player.points}${player.points === 21 ? " - blackjack!" : ""})`;
|
|
this.turnLog += turnLine;
|
|
this.display(turnLine, false, player.name);
|
|
this.clear();
|
|
this.next();
|
|
}
|
|
giveCard(userid) {
|
|
if (this.deck.length < 1)
|
|
this.deck = new BlackjackDeck().shuffle();
|
|
const player = userid === "dealer" ? this.dealer : this.playerTable[userid];
|
|
if (!player)
|
|
return;
|
|
player.cards.push(this.deck[0]);
|
|
this.deck.shift();
|
|
if (this.deck.length === 0) {
|
|
this.display(`<br />${this.dealer.name} has ran out of cards in the deck; shuffling a new deck...`);
|
|
this.deck = new BlackjackDeck().shuffle();
|
|
}
|
|
player.points = this.getCardPoints(userid);
|
|
if (player.cards.length < 3)
|
|
return;
|
|
let turnLine = import_lib.Utils.html`<br /><strong>${player.name}</strong> hit and received ` + `[${player.cards[player.cards.length - 1]}] (${player.points})`;
|
|
this.turnLog += turnLine;
|
|
if (player.cards.length > 2)
|
|
this.display(turnLine, false, player.name);
|
|
if (player instanceof BlackjackDealer) {
|
|
if (player.points > 21) {
|
|
let cards = "";
|
|
for (const card of player.cards) {
|
|
cards += `[${card}] `;
|
|
}
|
|
turnLine = import_lib.Utils.html`<br /><strong>${this.dealer.name}</strong> has busted with ${cards} (${player.points})`;
|
|
this.turnLog += turnLine;
|
|
this.display(turnLine);
|
|
this.end(true);
|
|
return;
|
|
} else if (player.points === 21) {
|
|
turnLine = import_lib.Utils.html`<br /><strong>${this.dealer.name}</strong> has blackjack!`;
|
|
this.turnLog += turnLine;
|
|
this.display(turnLine);
|
|
this.end(true);
|
|
return;
|
|
}
|
|
} else if (player.points > 21) {
|
|
player.status = "bust";
|
|
let cards = "";
|
|
for (const card of player.cards) {
|
|
cards += `[${card}] `;
|
|
}
|
|
turnLine = import_lib.Utils.html`<br /><strong>${player.name}</strong> has busted with ${cards} (${player.points})`;
|
|
this.turnLog += turnLine;
|
|
this.display(turnLine, false, player.name);
|
|
this.clear();
|
|
} else if (player.points === 21) {
|
|
player.status = "stand";
|
|
turnLine = import_lib.Utils.html`<br /><strong>${player.name}</strong> has blackjack!`;
|
|
this.turnLog += turnLine;
|
|
this.display(turnLine, false, player.name);
|
|
this.clear();
|
|
}
|
|
if (player !== this.dealer)
|
|
this.playerTable[userid].cards = player.cards;
|
|
this.next();
|
|
}
|
|
getCardPoints(playerid) {
|
|
const player = playerid === "dealer" ? this.dealer : this.playerTable[playerid];
|
|
let points = 0;
|
|
let aceCount = 0;
|
|
for (const card of player.cards.map((x) => toID(x).toUpperCase())) {
|
|
if (!isNaN(Number(card))) {
|
|
points += Number(card);
|
|
} else if (["K", "Q", "J"].includes(card)) {
|
|
points += 10;
|
|
} else if (card === "A") {
|
|
points += 11;
|
|
aceCount++;
|
|
}
|
|
}
|
|
while (points > 21 && aceCount > 0) {
|
|
points -= 10;
|
|
aceCount--;
|
|
}
|
|
return points;
|
|
}
|
|
next() {
|
|
this.clearAllTimers();
|
|
if (Object.keys(this.playerTable)[Object.keys(this.playerTable).length - 1] === this.curUsername && this.playerTable[this.curUsername].status !== "playing") {
|
|
if (this.dealer.points < 17) {
|
|
this.giveCard("dealer");
|
|
} else if (this.dealer.points >= 17) {
|
|
let cards = "";
|
|
for (const card of this.dealer.cards) {
|
|
cards += `[${card}] `;
|
|
}
|
|
const turnLine = `<br /><strong>${this.dealer.name}</strong> stands with ${cards} (${this.dealer.points})`;
|
|
this.turnLog += turnLine;
|
|
this.display(turnLine);
|
|
this.end(true);
|
|
}
|
|
return;
|
|
}
|
|
if (this.playerTable[this.curUsername].status !== "playing") {
|
|
let num = 0;
|
|
while (this.playerTable[Object.keys(this.playerTable)[num]].status !== "playing") {
|
|
num++;
|
|
}
|
|
this.curUsername = Object.keys(this.playerTable)[num];
|
|
}
|
|
let output = `|uhtml${this.playerTable[this.curUsername].selfUhtml}|user-blackjack-${this.gameNumber}|<div class="infobox" style="line-height: 20px;">`;
|
|
output += `It's your turn to move, ${this.playerTable[this.curUsername].name}<br />`;
|
|
for (const card of this.playerTable[this.curUsername].cards) {
|
|
output += this.generateCard(card);
|
|
}
|
|
output += `<br />Score: ${this.playerTable[this.curUsername].points}${this.playerTable[this.curUsername].points === 21 ? ` (you have blackjack!)` : ``}`;
|
|
output += `<br /><button class="button" name="send" value="/blackjack hit" title="Hit (get another card)">Hit</button> | <button class="button" name="send" value="/blackjack stand" title="Stand (just keep these cards)">Stand</button>`;
|
|
this.playerTable[this.curUsername].sendRoom(`|notify|Blackjack (${this.room.title})|It's your turn to play!`);
|
|
this.playerTable[this.curUsername].sendRoom(output);
|
|
this.playerTable[this.curUsername].playScreen = output;
|
|
this.createTimer(this.playerTable[this.curUsername].user);
|
|
}
|
|
}
|
|
class BlackjackPlayer extends Rooms.RoomGamePlayer {
|
|
constructor(user, game) {
|
|
super(user, game);
|
|
this.user = user;
|
|
this.cards = [];
|
|
this.points = 0;
|
|
this.slide = 0;
|
|
this.status = "playing";
|
|
this.selfUhtml = "";
|
|
this.gameLog = "";
|
|
this.playScreen = "";
|
|
this.timerTicksLeft = this.game.turnTimeoutMinutes * 60;
|
|
}
|
|
resetTimerTicks() {
|
|
this.timerTicksLeft = this.game.turnTimeoutMinutes * 60;
|
|
}
|
|
}
|
|
class BlackjackDealer {
|
|
constructor() {
|
|
this.cards = [];
|
|
this.points = 0;
|
|
this.name = "The Dealer";
|
|
}
|
|
}
|
|
class BlackjackDeck {
|
|
constructor() {
|
|
this.deck = [
|
|
"A\u2665",
|
|
"A\u2666",
|
|
"A\u2663",
|
|
"A\u2660",
|
|
"2\u2665",
|
|
"2\u2666",
|
|
"2\u2663",
|
|
"2\u2660",
|
|
"3\u2665",
|
|
"3\u2666",
|
|
"3\u2663",
|
|
"3\u2660",
|
|
"4\u2665",
|
|
"4\u2666",
|
|
"4\u2663",
|
|
"4\u2660",
|
|
"5\u2665",
|
|
"5\u2666",
|
|
"5\u2663",
|
|
"5\u2660",
|
|
"6\u2665",
|
|
"6\u2666",
|
|
"6\u2663",
|
|
"6\u2660",
|
|
"7\u2665",
|
|
"7\u2666",
|
|
"7\u2663",
|
|
"7\u2660",
|
|
"8\u2665",
|
|
"8\u2666",
|
|
"8\u2663",
|
|
"8\u2660",
|
|
"9\u2665",
|
|
"9\u2666",
|
|
"9\u2663",
|
|
"9\u2660",
|
|
"10\u2665",
|
|
"10\u2666",
|
|
"10\u2663",
|
|
"10\u2660",
|
|
"J\u2665",
|
|
"J\u2666",
|
|
"J\u2663",
|
|
"J\u2660",
|
|
"Q\u2665",
|
|
"Q\u2666",
|
|
"Q\u2663",
|
|
"Q\u2660",
|
|
"K\u2665",
|
|
"K\u2666",
|
|
"K\u2663",
|
|
"K\u2660"
|
|
];
|
|
}
|
|
shuffle() {
|
|
return import_lib.Utils.shuffle(this.deck);
|
|
}
|
|
}
|
|
const commands = {
|
|
blj: "blackjack",
|
|
blackjack: {
|
|
new: "create",
|
|
create(target, room, user) {
|
|
room = this.requireRoom();
|
|
this.checkCan("minigame", null, room);
|
|
if (room.game)
|
|
return this.errorReply("There is already a game running in this room.");
|
|
if (room.settings.blackjackDisabled)
|
|
return this.errorReply("Blackjack is currently disabled in this room.");
|
|
const autostartMinutes = target ? parseFloat(target) : 0;
|
|
if (isNaN(autostartMinutes) || autostartMinutes <= 0 || autostartMinutes * 60 * 1e3 > Chat.MAX_TIMEOUT_DURATION) {
|
|
return this.errorReply("Usage: /blackjack create [autostart] - where autostart is an integer");
|
|
}
|
|
this.privateModAction(`A game of blackjack was created by ${user.name}.`);
|
|
this.modlog(`BLACKJACK CREATE`);
|
|
room.game = new Blackjack(room, user, autostartMinutes);
|
|
},
|
|
start(target, room, user) {
|
|
room = this.requireRoom();
|
|
this.checkCan("minigame", null, room);
|
|
const game = this.requireGame(Blackjack);
|
|
if (game.state !== "signups")
|
|
return this.errorReply("This game of blackjack has already started.");
|
|
this.privateModAction(`The game of blackjack was started by ${user.name}.`);
|
|
this.modlog(`BLACKJACK START`);
|
|
game.start(user);
|
|
},
|
|
forceend: "end",
|
|
end(target, room, user, connection, cmd) {
|
|
room = this.requireRoom();
|
|
this.checkCan("minigame", null, room);
|
|
const game = this.requireGame(Blackjack);
|
|
const force = cmd === "forceend" ? "forcibly " : "";
|
|
const end = game.end(user, cmd);
|
|
if (end) {
|
|
this.privateModAction(`The game of blackjack was ${force}ended by ${user.name}.`);
|
|
this.modlog(`BLACKJACK END`);
|
|
}
|
|
},
|
|
hit(target, room, user) {
|
|
room = this.requireRoom();
|
|
const game = this.requireGame(Blackjack);
|
|
game.hit(user);
|
|
},
|
|
stand(target, room, user) {
|
|
room = this.requireRoom();
|
|
const game = this.requireGame(Blackjack);
|
|
game.stand(user);
|
|
},
|
|
slide(target, room, user) {
|
|
room = this.requireRoom();
|
|
const game = this.requireGame(Blackjack);
|
|
game.slide(user);
|
|
},
|
|
j: "join",
|
|
join(target, room, user) {
|
|
return this.parse("/joingame");
|
|
},
|
|
l: "leave",
|
|
leave(target, room, user) {
|
|
return this.parse("/leavegame");
|
|
},
|
|
unspectate: "spectate",
|
|
spectate(target, room, user, connection, cmd) {
|
|
room = this.requireRoom();
|
|
const game = this.requireGame(Blackjack);
|
|
if (cmd === "spectate") {
|
|
game.spectate(user);
|
|
} else if (cmd === "unspectate") {
|
|
game.unspectate(user);
|
|
}
|
|
},
|
|
disable(target, room, user) {
|
|
room = this.requireRoom();
|
|
this.checkCan("gamemanagement", null, room);
|
|
if (room.settings.blackjackDisabled) {
|
|
return this.errorReply("Blackjack is already disabled in this room.");
|
|
}
|
|
room.settings.blackjackDisabled = true;
|
|
room.saveSettings();
|
|
this.sendReply(`Blackjack has been disabled for this room.`);
|
|
},
|
|
enable(target, room, user) {
|
|
room = this.requireRoom();
|
|
this.checkCan("gamemanagement", null, room);
|
|
if (!room.settings.blackjackDisabled) {
|
|
return this.errorReply("Blackjack is already enabled in this room.");
|
|
}
|
|
delete room.settings.blackjackDisabled;
|
|
room.saveSettings();
|
|
this.sendReply(`Blackjack has been enabled for this room.`);
|
|
},
|
|
"": "help",
|
|
help(target, room, user) {
|
|
return this.parse("/help blackjack");
|
|
}
|
|
},
|
|
blackjackhelp: [
|
|
"/blackjack create - Creates a game of blackjack. Requires: % @ # &",
|
|
"/blackjack create [autostart] - Automatically creates a game of blackjack in [autostart] minutes. Requires: % @ # &",
|
|
"/blackjack start - Starts a game of blackjack. Requires: % @ # &",
|
|
"/blackjack end - Ends a game of blackjack. Requires: % @ # &",
|
|
"/blackjack join - Joins a game of blackjack.",
|
|
"/blackjack leave - Leaves a game of blackjack.",
|
|
"/blackjack spectate - Spectates a game of blackjack.",
|
|
"/blackjack unspectate - Stops spectating a game of blackjack.",
|
|
"/blackjack disable - Prevents games of blackjack from being made in the room. Requires: # &",
|
|
"/blackjack enable - Allows games of blackjack to be made in the room. Requires: # &"
|
|
]
|
|
};
|
|
const roomSettings = (room) => ({
|
|
label: "Blackjack",
|
|
permission: "editroom",
|
|
options: [
|
|
[`disabled`, room.settings.blackjackDisabled || "blackjack disable"],
|
|
[`enabled`, !room.settings.blackjackDisabled || "blackjack enable"]
|
|
]
|
|
});
|
|
//# sourceMappingURL=blackjack.js.map
|