Skip to content

Instantly share code, notes, and snippets.

@Californ1a
Last active January 10, 2021 00:01
Show Gist options
  • Save Californ1a/3170202cd5182a300a381b810560ade6 to your computer and use it in GitHub Desktop.
Save Californ1a/3170202cd5182a300a381b810560ade6 to your computer and use it in GitHub Desktop.
test uno with discord
// #region discord.js
require("dotenv").config();
const Discord = require("discord.js");
const bot = new Discord.Client();
const token = process.env.DISCORD_TOKEN;
const sendM = (chan, msg, options) => {
return new Promise((resolve, reject) => {
if (options) {
chan.send(msg, options).then(m => {
resolve(m);
}).catch(e => {
reject(e);
});
} else {
chan.send(msg).then(m => {
resolve(m);
}).catch(e => {
reject(e);
});
}
});
};
const send = (chan, msg, options) => {
return new Promise((resolve, reject) => {
if (chan.content) {
if (chan.guild) {
sendM(chan.channel, msg, options).then(m => {
resolve(m);
}).catch(e => {
reject(e);
});
} else {
sendM(chan.author, msg, options).then(m => {
resolve(m);
}).catch(e => {
reject(e);
});
}
} else {
sendM(chan, msg, options).then(m => {
resolve(m);
}).catch(e => {
reject(e);
});
}
});
};
// #endregion
// #region uno setup
const {
Game,
Card,
Colors,
Values
} = require("uno-engine");
let game;
const getCard = (args, p) => {
//#region Shorthand for quick testing games
switch (args[0]) {
case "r":
args[0] = "red";
break;
case "g":
args[0] = "green";
break;
case "y":
args[0] = "yellow";
break;
case "b":
args[0] = "blue";
break;
case "w":
args[0] = "wild";
break;
case "wd4":
args[0] = "wild_draw_four";
break;
}
switch (args[1]) {
case "r":
args[1] = "reverse";
break;
case "s":
args[1] = "skip";
break;
case "0":
args[1] = "zero";
break;
case "1":
args[1] = "one";
break;
case "2":
args[1] = "two";
break;
case "3":
args[1] = "three";
break;
case "4":
args[1] = "four";
break;
case "5":
args[1] = "five";
break;
case "6":
args[1] = "six";
break;
case "7":
args[1] = "seven";
break;
case "8":
args[1] = "eight";
break;
case "9":
args[1] = "nine";
break;
case "dt":
args[1] = "draw_two";
break;
case "w":
args[1] = "wild";
break;
case "wd4":
args[1] = "wild_draw_four";
break;
}
//#endregion
args[0] = args[0].toUpperCase();
args[1] = args[1].toUpperCase();
const c = (Colors.get(args[0])) ? Colors.get(args[0]) : Colors.get(args[1]);
const v = (Values.get(args[1])) ? Values.get(args[1]) : Values.get(args[0]);
let card = Card(v, c);
if (args.includes("WILD") || args.includes("WILD_DRAW_FOUR")) {
card = p.getCardByValue(v);
card.color = Colors.get(c);
}
return card;
};
const resetGame = (msg) => {
msg.channel.unoPlayers = [];
msg.channel.unoRunning = false;
game = null;
};
const showHand = (msg, p) => {
if (p.name) {
p = p.name;
}
const handArr = game.getPlayer(p).hand; //.toString().toLowerCase().split(",");
const hand = [];
for (const elt of handArr) {
if (elt.value.toString() === "WILD") {
hand.push("wild");
} else if (elt.value.toString() === "WILD_DRAW_FOUR") {
hand.push("WD4");
} else if (elt.value.toString() === "DRAW_TWO") {
hand.push(`${elt.color.toString().toLowerCase()} DT`);
} else {
hand.push(elt.toString().toLowerCase());
}
}
const member = msg.guild.members.get(p);
send(msg.channel, `${member} Your Uno hand: ${hand.join(", ")}`); //TODO: send privately to `member` when inline pm is available - direct msg works but is annoying
};
const startGame = (msg, players) => {
if (players.length < 2) {
return send(msg.channel, "No one joined.");
// TODO: Add bot as player
}
game = Game(players);
game.newGame();
const member = msg.guild.members.get(game.currentPlayer.name);
game.on("end", (err, winner, score) => {
send(msg.channel, `${member} wins! Score: ${score}`);
resetGame(msg);
});
msg.channel.unoRunning = true;
send(msg.channel, `${msg.author} has started Uno!`);
send(msg.channel, `You're up ${member} - Card: ${game.discardedCard.toString()}`);
players.forEach(p => {
showHand(msg, p);
});
};
// #endregion
// #region uno
bot.on("message", msg => {
console.log(msg.content);
if (msg.content.startsWith("!uno")) {
if (msg.channel.unoRunning) {
//return send(msg.channel, "Uno is already running");
send(msg.channel, "Do you want to end Uno?");
msg.channel.awaitMessages(r => (r.content === "y" || r.content === "yes" || r.content === "n" || r.content === "no") && msg.author.id === r.author.id, {
max: 1,
time: 30000,
errors: ["time"]
}).then((collected) => {
if (collected.first().content === "n" || collected.first().content === "no") {
return send(msg.channel, "Uno will continue.");
}
resetGame(msg);
return send(msg.channel, "Uno has been forced ended.");
}).catch(() => {
return send(msg.channel, "You took too long to respond. Uno will continue.");
});
} else {
if (!msg.channel.unoPlayers) {
msg.channel.unoPlayers = [];
}
const players = msg.channel.unoPlayers;
players.push(msg.author.id);
send(msg.channel, `${msg.author} wants to play Uno! Type \`join\` in the channel to join the game. Game will start in 30 seconds.`);
const collector = msg.channel.createMessageCollector(m => m.content.toLowerCase() === "join", {
time: 30000
});
collector.on("collect", (m) => {
if (!players.includes(m.author.id) && players.length < 10) {
send(msg.channel, `${m.guild.members.get(m.author.id).displayName} will play!`);
players.push(m.author.id);
}
});
collector.on("end", () => { //arg=collected collection
startGame(msg, players);
});
}
} else if (msg.content.startsWith("play")) {
if (typeof msg.channel.unoRunning === "boolean" && msg.channel.unoRunning) {
if (msg.author.id !== game.currentPlayer.name) {
return send(msg.channel, "It's not your turn");
}
const player = game.currentPlayer;
const args = msg.content.split(" ").slice(1);
if (args.length === 2) {
try {
game.play(getCard(args, game.currentPlayer));
} catch (e) {
if (e.message.includes("does not have card")) {
return send(msg.channel, "You do not have that card.");
} else if (e.message.includes("from discard pile, does not match")) {
send(msg.channel, "That card can't be played now.");
} else {
return console.error(e);
}
}
if (player.hand.length !== 0) {
const member = msg.guild.members.get(game.currentPlayer.name);
send(msg.channel, `You're up ${member} - Card: ${game.discardedCard.toString()}`);
showHand(msg, game.currentPlayer);
}
}
} else {
return send(msg.channel, "Uno isn't running.");
}
} else if (msg.content === "draw") {
if (typeof msg.channel.unoRunning === "boolean" && msg.channel.unoRunning) {
if (msg.author.id !== game.currentPlayer.name) {
return send(msg.channel, "It's not your turn");
}
game.draw();
const card = game.currentPlayer.hand[game.currentPlayer.hand.length - 1];
const name = (card.color) ? card.toString().toLowerCase() : card.value.toString().toLowerCase();
send(msg.channel, `${msg.author} drew a ${name}`);
} else {
return send(msg.channel, "Uno isn't running.");
}
} else if (msg.content === "pass") {
if (typeof msg.channel.unoRunning === "boolean" && msg.channel.unoRunning) {
if (msg.author.id !== game.currentPlayer.name) {
return send(msg.channel, "It's not your turn");
}
try {
game.pass();
} catch (e) {
if (e.message.includes("must draw at least one card")) {
return send(msg.channel, "You must draw before passing.");
}
}
send(msg.channel, `You're up ${msg.guild.members.get(game.currentPlayer.name)} - Card: ${game.discardedCard.toString()}`);
// const hand = game.currentPlayer.hand.toString().toLowerCase().split(",").join(", ");
// send(msg.channel, `${msg.guild.members.get(game.currentPlayer.name)} Your Uno hand: ${hand}`);
showHand(msg, game.currentPlayer);
} else {
return send(msg.channel, "Uno isn't running.");
}
} else if (msg.content === "hand") {
if (typeof msg.channel.unoRunning === "boolean" && msg.channel.unoRunning) {
if (msg.channel.unoPlayers.includes(msg.author.id)) {
// const hand = game.getPlayer(msg.author.id).hand.toString().toLowerCase().split(",").join(", ");
// send(msg.channel, `${msg.author} Your Uno hand: ${hand}`);
showHand(msg, game.getPlayer(msg.author.id));
}
} else {
return send(msg.channel, "Uno isn't running.");
}
} else if (msg.content === "score") {
if (typeof msg.channel.unoRunning === "boolean" && msg.channel.unoRunning) {
if (msg.channel.unoPlayers.includes(msg.author.id)) {
const players = [];
for (const p of msg.channel.unoPlayers) {
players.push(game.getPlayer(p));
}
const score = players.map(player => player.hand).reduce((amount, cards) => {
amount += cards.reduce((s, c) => s += c.score, 0);
return amount;
}, 0);
send(msg.channel, `Score: ${score}`);
}
} else {
return send(msg.channel, "Uno isn't running.");
}
}
});
// #endregion
// #region bot login
bot.on("ready", () => {
console.log("Ready!");
});
bot.login(token);
// #endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment