Dots and Boxes Command

This commit is contained in:
Dragon Fire
2020-04-09 17:24:36 -04:00
parent 74723aaff6
commit 537de46ed4
4 changed files with 165 additions and 4 deletions
-2
View File
@@ -3,5 +3,3 @@ package-lock.json
logs/
*.log
.env
commands/games-mp/dots-and-boxes.js
+2 -1
View File
@@ -132,7 +132,7 @@ in the appropriate channel's topic to use it.
## Commands
Total: 382
Total: 383
### Utility:
@@ -388,6 +388,7 @@ Total: 382
* **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.
* **connect-four:** Play a game of Connect Four with another user.
* **dots-and-boxes:** Play a game of Dots and Boxes with another user.
* **emoji-emoji-revolution:** Can you type arrow emoji faster than anyone else has ever typed them before?
* **gunfight:** Engage in a western gunfight against another user. High noon.
* **pick-a-number:** Two players pick a number between 1 and 10. Whoever's closer wins.
+162
View File
@@ -0,0 +1,162 @@
const Command = require('../../structures/Command');
const { stripIndents } = require('common-tags');
const { verify } = require('../../util/Util');
const squareIDs = [5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, 20, 21, 22, 23];
module.exports = class DotsAndBoxesCommand extends Command {
constructor(client) {
super(client, {
name: 'dots-and-boxes',
aliases: ['dots-boxes', 'dot-box', 'dot-and-box', 'territory-capture'],
group: 'games-mp',
memberName: 'dots-and-boxes',
description: 'Play a game of Dots and Boxes with another user.',
guildOnly: true,
args: [
{
key: 'opponent',
prompt: 'What user would you like to challenge?',
type: 'user'
}
]
});
}
async run(msg, { opponent }) {
if (opponent.bot) return msg.reply('Bots may not be played against.');
if (opponent.id === msg.author.id) return msg.reply('You may not play against yourself.');
const current = this.client.games.get(msg.channel.id);
if (current) return msg.reply(`Please wait until the current game of \`${current.name}\` is finished.`);
this.client.games.set(msg.channel.id, { name: this.name });
try {
await msg.say(`${opponent}, do you accept this challenge?`);
const verification = await verify(msg.channel, opponent);
if (!verification) {
this.client.games.delete(msg.channel.id);
return msg.say('Looks like they declined...');
}
const board = this.generateBoard();
const taken = [];
const owned = {};
let userTurn = true;
let winner = null;
while (taken.length < 24) {
const user = userTurn ? msg.author : opponent;
await msg.say(stripIndents`
${user}, which connection do you pick? Type \`end\` to forefeit.
_Format like \`1-2\` or \`0-5\`. Any two spaces bordering **vertical or horizontal**._
P1: ${msg.author.tag} | P2: ${opponent.tag}
${this.displayBoard(board, taken, owned)}
`);
const filter = res => {
if (res.author.id !== user.id) return false;
const choice = res.content;
if (choice.toLowerCase() === 'end') return true;
const matched = choice.match(/([0-9]+)\-([0-9]+)/);
if (!match) return false;
let first = Number.parseInt(matched[1], 10);
let second = Number.parseInt(matched[2], 10);
if (first === second) return false;
if (second > first) {
const temp = first;
first = second;
second = temp;
}
if (first > 24 || second > 24 || first < 0 || second < 0) return false;
const column1 = first % 5;
const column2 = second % 5;
if (second !== first + 1 && column1 !== column2) {
const row1 = Math.floor(first / 5);
const row2 = Math.floor(second / 5);
if (row2 !== row1 - 1) return false;
return !taken.includes(`${first}-${second}`);
}
return !taken.includes(`${first}-${second}`);
};
const turn = await msg.channel.awaitMessages(filter, {
max: 1,
time: 60000
});
if (!turn.size) {
await msg.say('Sorry, time is up!');
userTurn = !userTurn;
continue;
}
const choice = turn.first().content;
if (choice.toLowerCase() === 'end') {
winner = userTurn ? opponent : msg.author;
break;
}
const matched = choice.match(/([0-9]+)\-([0-9]+)/);
let first = Number.parseInt(matched[1], 10);
let second = Number.parseInt(matched[2], 10);
if (second > first) {
const temp = first;
first = second;
second = temp;
}
taken.push(`${first}-${second}`);
const newSquare = this.calcNewSquare(taken, owned);
if (newSquare) {
owned[newSquare] = userTurn ? 'P1' : 'P2';
await msg.say(`${user}, great job! Keep going until you can\'t make any more!`);
} else {
userTurn = !userTurn;
}
}
this.client.games.delete(msg.channel.id);
return msg.say(winner ? `Congrats, ${winner}!` : 'Looks like it\'s a draw...');
} catch (err) {
this.client.games.delete(msg.channel.id);
throw err;
}
}
calcSquare(num, taken) {
return taken.includes(`${num}-${num + 1}`)
&& taken.includes(`${num}-${num + 5}`)
&& taken.includes(`${num + 1}-${num + 1 + 5}`)
&& taken.includes(`${num + 5}-${num + 1 + 5}`);
}
calcNewSquare(taken, owned) {
for (const square of squareIDs) {
if (owned[square]) continue;
if (this.calcSquare(square, taken)) return square;
}
return null;
}
generateBoard() {
const arr = [];
for (let i = 0; i < 5; i++) {
const row = [];
for (let j = 0 + (i * 5); j < 5 + (i * 5); j++) row.push(j);
arr.push(row);
}
return arr;
}
displayBoard(board, taken, owned) {
const displayed = [];
board.map((values, row) => {
if (row !== 0) {
let takenMids = '';
for (let i = 0 + (row * 5); i < 5 + (row * 5); i++) {
if (taken.includes(`${i - 5}-${i}`)) takenMids += '||';
else takenMids += ' ';
takenMids += owned[i] || ' ';
}
displayed.push(takenMids);
}
displayed.push(values.map(slot => {
let val = slot.toString().padStart(2, '0');
if (taken.includes(`${slot}-${slot + 1}`)) val += '==';
else val += ' ';
return val;
}).join(''));
});
return displayed.join('\n');
}
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xiao",
"version": "112.19.15",
"version": "112.20.0",
"description": "Your personal server companion.",
"main": "Xiao.js",
"scripts": {