Last active
January 10, 2021 00:01
-
-
Save Californ1a/3170202cd5182a300a381b810560ade6 to your computer and use it in GitHub Desktop.
test uno with discord
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// #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