djs-systems
Version:
The simplest way to build complex Discord bots.
943 lines • 64.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tictactoe = void 0;
const discord_js_1 = require("discord.js");
const misc_1 = require("./misc");
const error_1 = require("./error");
const limiter = [];
// ------------------------------
// ------ F U N C T I O N -------
// ------------------------------
const combinations = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
/**
* One line implementation of a super enjoyable **tictactoe game**.
* @param message
* @param options
* @link `Documentation:` https://simplyd.js.org/docs/Fun/tictactoe
* @example simplydjs.tictactoe(interaction)
*/
async function tictactoe(message, options = { max: 6, strict: false }) {
return new Promise(async (resolve) => {
try {
const { client } = message;
let interaction;
if (message.commandId) {
interaction = message;
if (!interaction.deferred)
await interaction.deferReply({ fetchReply: true });
}
let opponent;
const extInteraction = message;
const extMessage = message;
let id = limiter.findIndex((a) => a.guild == message.guild.id);
if (!limiter[id] || !limiter[id].guild) {
limiter.push({
guild: message.guild.id,
limit: 0
});
id = limiter.findIndex((a) => a.guild == message.guild.id);
}
if (limiter[id].limit >= (options?.max || 6)) {
if (interaction)
return extInteraction.followUp({
content: 'Sorry, There is a game happening right now. Please try later.'
});
else if (!interaction)
return extMessage.reply({
content: 'Sorry, There is a game happening right now. Please try later.'
});
}
const x_emoji = options.buttons?.X?.emoji?.id ||
options.buttons?.X?.emoji ||
'❌';
const o_emoji = options.buttons?.O?.emoji?.id ||
options.buttons?.O?.emoji ||
'⭕';
const blank_emoji = options.buttons?.blank?.emoji || '➖';
if (options?.buttons?.blank?.style)
options.buttons.blank.style = (0, misc_1.toButtonStyle)(options?.buttons?.blank?.style);
if (options?.buttons?.X?.style)
options.buttons.X.style = (0, misc_1.toButtonStyle)(options?.buttons?.X?.style);
if (options?.buttons?.O?.style)
options.buttons.O.style = (0, misc_1.toButtonStyle)(options?.buttons?.O?.style);
const emptyStyle = options.buttons?.blank?.style || discord_js_1.ButtonStyle.Secondary;
const XStyle = options.buttons?.X?.style || discord_js_1.ButtonStyle.Danger;
const OStyle = options.buttons?.O?.style || discord_js_1.ButtonStyle.Success;
if (interaction) {
opponent = options.user || extInteraction.options.getUser('user');
if (!opponent)
return ai(message, {
max: options?.max || 6,
blank_emoji: blank_emoji,
x_emoji: x_emoji,
o_emoji: o_emoji,
x_style: XStyle,
o_style: OStyle,
emptyStyle: emptyStyle,
embed: options.embed,
buttons: options.buttons,
type: options.type
});
if (opponent.bot)
return extInteraction.followUp({
content: 'You cannot play with bots!',
ephemeral: true
});
if (opponent.id == message.user.id)
return extInteraction.followUp({
content: 'You cannot play with yourself!',
ephemeral: true
});
}
else if (!interaction) {
opponent = extMessage.mentions.users.first();
if (!opponent)
return ai(message, {
max: options?.max || 6,
blank_emoji,
x_emoji,
o_emoji,
x_style: XStyle,
o_style: OStyle,
emptyStyle,
embed: options.embed,
buttons: options.buttons,
type: options.type
});
if (opponent.bot)
return extMessage.reply({
content: "You can't play with bots!"
});
if (opponent.id === message.member.user.id)
return extMessage.reply({
content: 'You cannot play with yourself!'
});
}
const requestEmbed = new discord_js_1.EmbedBuilder()
.setTitle(options?.embed?.request?.title ||
`Tictactoe with ${opponent.username}`)
.setDescription(options?.embed?.request?.description ||
'Waiting for the opponent to accept/deny')
.setAuthor(options?.embed?.request?.author || {
name: message.member.user.username,
iconURL: message.member.user.displayAvatarURL({
forceStatic: false
})
})
.setColor(options.embed?.request?.color || (0, misc_1.toRgb)('#406DBC'))
.setFooter(options.embed?.request?.footer
? options.embed?.request?.footer
: {
text: '©️ Rahuletto. npm i simply-djs',
iconURL: 'https://i.imgur.com/XFUIwPh.png'
});
if (options?.embed?.request?.fields)
requestEmbed.setFields(options.embed?.request?.fields);
if (options?.embed?.request?.author)
requestEmbed.setAuthor(options.embed?.request?.author);
if (options?.embed?.request?.image)
requestEmbed.setImage(options.embed?.request?.image);
if (options?.embed?.request?.thumbnail)
requestEmbed.setThumbnail(options.embed?.request?.thumbnail);
if (options?.embed?.request?.timestamp)
requestEmbed.setTimestamp(options.embed?.request?.timestamp);
if (options?.embed?.request?.title)
requestEmbed.setTitle(options.embed?.request?.title);
if (options?.embed?.request?.url)
requestEmbed.setURL(options.embed?.request?.url);
const accept = new discord_js_1.ButtonBuilder()
.setLabel('Accept')
.setStyle(discord_js_1.ButtonStyle.Success)
.setCustomId('accept-ttt');
const deny = new discord_js_1.ButtonBuilder()
.setLabel('Deny')
.setStyle(discord_js_1.ButtonStyle.Danger)
.setCustomId('deny-ttt');
const row = new discord_js_1.ActionRowBuilder().addComponents([
accept,
deny
]);
let m;
if (interaction) {
m = await extInteraction.followUp({
content: `<@${opponent.id}>, You got a tictactoe request from ${message.member.user.username}`,
embeds: [requestEmbed],
components: [row]
});
}
else if (!interaction) {
m = await extMessage.reply({
content: `<@${opponent.id}>, You got a tictactoe request from ${message.member.user.username}`,
embeds: [requestEmbed],
components: [row]
});
}
limiter[id].limit += 1;
const collector = m.createMessageComponentCollector({
componentType: discord_js_1.ComponentType.Button,
time: (0, misc_1.ms)('30s')
});
collector.on('collect', async (button) => {
if (button.user.id !== opponent.id) {
await button.reply({
content: `Only <@!${opponent.id}> can use these buttons!`,
ephemeral: true
});
return;
}
if (button.customId == 'deny-ttt') {
await button.deferUpdate();
collector.stop('decline');
}
else if (button.customId == 'accept-ttt') {
await button.deferUpdate();
collector.stop();
const players = [message.member.user.id, opponent.id].sort(() => Math.random() > 0.5 ? 1 : -1);
const gameEmbed = new discord_js_1.EmbedBuilder()
.setTitle(options.embed?.game?.title ||
`${message.member.user.username} VS ${opponent.username}`)
.setAuthor(options.embed?.game?.author || {
name: message.member.user.username,
iconURL: message.member.user.displayAvatarURL({
forceStatic: false
})
})
.setColor(options.embed?.game?.color || (0, misc_1.toRgb)('#406DBC'))
.setFooter(options.embed?.game?.footer
? options.embed?.game?.footer
: {
text: '©️ Rahuletto. npm i simply-djs',
iconURL: 'https://i.imgur.com/XFUIwPh.png'
});
if (options?.embed?.game?.fields)
gameEmbed.setFields(options.embed?.game?.fields);
if (options?.embed?.game?.author)
gameEmbed.setAuthor(options.embed?.game?.author);
if (options?.embed?.game?.image)
gameEmbed.setImage(options.embed?.game?.image);
if (options?.embed?.game?.thumbnail)
gameEmbed.setThumbnail(options.embed?.game?.thumbnail);
if (options?.embed?.game?.timestamp)
gameEmbed.setTimestamp(options.embed?.game?.timestamp);
if (options?.embed?.game?.url)
gameEmbed.setURL(options.embed?.game?.url);
const msg = await button.message.edit({
embeds: [
gameEmbed.setDescription(`Waiting for Input | <@!${players[0]}>, Your Emoji: ${client.emojis.cache.get(o_emoji) || '⭕'}`)
]
});
const Game = {
user: 0,
userid: '',
board: Array(9).fill({
style: emptyStyle,
emoji: blank_emoji,
disabled: false
})
};
await tictactoeEngine(msg, {
blank_emoji: blank_emoji
});
async function tictactoeEngine(m, styles = {}) {
const { blank_emoji } = styles;
Game.userid = players[Game.user];
const won = {
O: false,
X: false
};
function checkWin(emoji) {
return combinations.some((combination) => {
return combination.every((index) => {
return Game.board[index].emoji == emoji;
});
});
}
function isDraw() {
return [...Game.board].every((cell) => {
return cell.emoji == x_emoji || cell.emoji == o_emoji;
});
}
const a1 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[0].style)
.setEmoji(Game.board[0].emoji)
.setCustomId('0')
.setDisabled(Game.board[0].disabled);
const a2 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[1].style)
.setEmoji(Game.board[1].emoji)
.setCustomId('1')
.setDisabled(Game.board[1].disabled);
const a3 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[2].style)
.setEmoji(Game.board[2].emoji)
.setCustomId('2')
.setDisabled(Game.board[2].disabled);
const b1 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[3].style)
.setEmoji(Game.board[3].emoji)
.setCustomId('3')
.setDisabled(Game.board[3].disabled);
const b2 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[4].style)
.setEmoji(Game.board[4].emoji)
.setCustomId('4')
.setDisabled(Game.board[4].disabled);
const b3 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[5].style)
.setEmoji(Game.board[5].emoji)
.setCustomId('5')
.setDisabled(Game.board[5].disabled);
const c1 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[6].style)
.setEmoji(Game.board[6].emoji)
.setCustomId('6')
.setDisabled(Game.board[6].disabled);
const c2 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[7].style)
.setEmoji(Game.board[7].emoji)
.setCustomId('7')
.setDisabled(Game.board[7].disabled);
const c3 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[8].style)
.setEmoji(Game.board[8].emoji)
.setCustomId('8')
.setDisabled(Game.board[8].disabled);
const a = new discord_js_1.ActionRowBuilder().addComponents([
a1,
a2,
a3
]);
const b = new discord_js_1.ActionRowBuilder().addComponents([
b1,
b2,
b3
]);
const c = new discord_js_1.ActionRowBuilder().addComponents([
c1,
c2,
c3
]);
const buttons = [a, b, c];
const winEmbed = new discord_js_1.EmbedBuilder()
.setTitle(options.embed?.win?.title ||
`${message.member.user.username} VS ${opponent.username}`)
.setColor(options.embed?.win?.color || `DarkGreen`)
.setFooter(options.embed?.win?.footer
? options.embed?.win?.footer
: {
text: '©️ Rahuletto. npm i simply-djs',
iconURL: 'https://i.imgur.com/XFUIwPh.png'
});
if (options?.embed?.win?.fields)
winEmbed.setFields(options.embed?.win?.fields);
if (options?.embed?.win?.author)
winEmbed.setAuthor(options.embed?.win?.author);
if (options?.embed?.win?.image)
winEmbed.setImage(options.embed?.win?.image);
if (options?.embed?.win?.thumbnail)
winEmbed.setThumbnail(options.embed?.win?.thumbnail);
if (options?.embed?.win?.timestamp)
winEmbed.setTimestamp(options.embed?.win?.timestamp);
if (options?.embed?.win?.url)
winEmbed.setURL(options.embed?.win?.url);
if (checkWin(o_emoji))
won['O'] = true;
if (checkWin(x_emoji))
won['X'] = true;
if (won['O'] == true) {
limiter[id].limit -= 1;
if (limiter[id].limit < 0)
limiter[id].limit = 0;
const winner = await client.users
.fetch(players[Game.user === 0 ? 1 : 0])
.catch(console.error);
resolve(winner);
if (!options.type || options.type === 'Button')
return m
.edit({
content: `<@${players[Game.user === 0 ? 1 : 0]}> (${client.emojis.cache.get(o_emoji) || '⭕'}) won`,
components: (0, misc_1.disableButtons)(buttons),
embeds: [
winEmbed
.setAuthor(options.embed?.win?.author || {
name: winner.username,
iconURL: winner.displayAvatarURL({
forceStatic: false
})
})
.setDescription(`<@!${players[Game.user === 0 ? 1 : 0]}> (${client.emojis.cache.get(o_emoji) || '⭕'}) won, That was a nice game.`)
]
})
.then((m) => {
m.react(client.emojis.cache.get(o_emoji) || '⭕');
});
else if (options?.type === 'Embed')
return m
.edit({
content: `<@${players[Game.user === 0 ? 1 : 0]}> (${client.emojis.cache.get(o_emoji) || '⭕'}) won`,
embeds: [
winEmbed
.setAuthor(options.embed?.win?.author || {
name: winner.username,
iconURL: winner.displayAvatarURL({
forceStatic: false
})
})
.setDescription(`<@!${players[Game.user === 0 ? 1 : 0]}> (${client.emojis.cache.get(o_emoji) || '⭕'}) won.. That was a nice game.\n` +
`\`\`\`\n${Game.board[0].emoji} | ${Game.board[1].emoji} | ${Game.board[2].emoji}\n${Game.board[3].emoji} | ${Game.board[4].emoji} | ${Game.board[5].emoji}\n${Game.board[6].emoji} | ${Game.board[7].emoji} | ${Game.board[8].emoji}\n\`\`\``
.replaceAll(blank_emoji, '➖')
.replaceAll(o_emoji, '⭕')
.replaceAll(x_emoji, '❌'))
],
components: []
})
.then((m) => {
m.react(client.emojis.cache.get(o_emoji) || '⭕');
});
}
else if (won['X'] == true) {
limiter[id].limit -= 1;
if (limiter[id].limit < 0)
limiter[id].limit = 0;
const winner = await client.users
.fetch(players[Game.user === 0 ? 1 : 0])
.catch(console.error);
resolve(winner);
if (!options.type || options.type === 'Button')
return m
.edit({
content: `<@${players[Game.user === 0 ? 1 : 0]}> (${client.emojis.cache.get(x_emoji) || '❌'}) won`,
components: (0, misc_1.disableButtons)(buttons),
embeds: [
winEmbed
.setAuthor(options.embed?.win?.author || {
name: winner.username,
iconURL: winner.displayAvatarURL({
forceStatic: false
})
})
.setDescription(`<@!${players[Game.user === 0 ? 1 : 0]}> (${client.emojis.cache.get(x_emoji) || '❌'}) won, That was a nice game.`)
]
})
.then((m) => {
m.react(client.emojis.cache.get(x_emoji) || '❌');
});
else if (options?.type === 'Embed')
return m
.edit({
content: `<@${players[Game.user === 0 ? 1 : 0]}> (${client.emojis.cache.get(o_emoji) || '❌'}) won`,
embeds: [
winEmbed
.setAuthor(options.embed?.win?.author || {
name: winner.username,
iconURL: winner.displayAvatarURL({
forceStatic: false
})
})
.setDescription(`<@!${players[Game.user === 0 ? 1 : 0]}> (${client.emojis.cache.get(x_emoji) || '❌'}) won.. That was a nice game.\n` +
`\`\`\`\n${Game.board[0].emoji} | ${Game.board[1].emoji} | ${Game.board[2].emoji}\n${Game.board[3].emoji} | ${Game.board[4].emoji} | ${Game.board[5].emoji}\n${Game.board[6].emoji} | ${Game.board[7].emoji} | ${Game.board[8].emoji}\n\`\`\``
.replaceAll(blank_emoji, '➖')
.replaceAll(o_emoji, '⭕')
.replaceAll(x_emoji, '❌'))
],
components: []
})
.then((m) => {
m.react(client.emojis.cache.get(x_emoji) || '❌');
});
}
if (isDraw()) {
limiter[id].limit -= 1;
if (limiter[id].limit < 0)
limiter[id].limit = 0;
const drawEmbed = new discord_js_1.EmbedBuilder()
.setTitle(options.embed?.draw?.title ||
`${message.member.user.username} VS ${opponent.username}`)
.setColor(options.embed?.draw?.color || 'Grey')
.setFooter(options.embed?.draw?.footer
? options.embed?.draw?.footer
: {
text: '©️ Rahuletto. npm i simply-djs',
iconURL: 'https://i.imgur.com/XFUIwPh.png'
});
if (options?.embed?.draw?.fields)
drawEmbed.setFields(options.embed?.draw?.fields);
if (options?.embed?.draw?.author)
drawEmbed.setAuthor(options.embed?.draw?.author);
if (options?.embed?.draw?.image)
drawEmbed.setImage(options.embed?.draw?.image);
if (options?.embed?.draw?.thumbnail)
drawEmbed.setThumbnail(options.embed?.draw?.thumbnail);
if (options?.embed?.draw?.timestamp)
drawEmbed.setTimestamp(options.embed?.draw?.timestamp);
if (options?.embed?.draw?.url)
drawEmbed.setURL(options.embed?.draw?.url);
if (!options.type || options.type === 'Button')
return m
.edit({
content: 'Its a Tie!',
embeds: [
drawEmbed.setDescription(`You have tied. Play again to see who wins.`)
],
components: buttons
})
.then((m) => {
m.react(blank_emoji);
});
else
return m
.edit({
content: 'Its a Tie !',
embeds: [
drawEmbed.setDescription(`You have tied. Play again to see who wins.\n` +
`\`\`\`\n${Game.board[0].emoji} | ${Game.board[1].emoji} | ${Game.board[2].emoji}\n${Game.board[3].emoji} | ${Game.board[4].emoji} | ${Game.board[5].emoji}\n${Game.board[6].emoji} | ${Game.board[7].emoji} | ${Game.board[8].emoji}\n\`\`\``
.replaceAll(blank_emoji, '➖')
.replaceAll(o_emoji, '⭕')
.replaceAll(x_emoji, '❌'))
],
components: []
})
.then((m) => {
m.react(blank_emoji);
})
.catch(() => { });
}
const play = await client.users.fetch(players[Game.user]);
m.edit({
content: `<@${Game.userid}>`,
embeds: [
gameEmbed
.setAuthor(options.embed?.game?.author || {
name: play.username,
iconURL: play.displayAvatarURL({
forceStatic: false
})
})
.setDescription(`Waiting for Input | <@!${Game.userid}> | Your Emoji: ${Game.user == 0
? `${client.emojis.cache.get(o_emoji) || '⭕'}`
: `${client.emojis.cache.get(x_emoji) || '❌'}`}`)
],
components: [a, b, c]
});
const collector = m.createMessageComponentCollector({
componentType: discord_js_1.ComponentType.Button,
max: 1,
time: (0, misc_1.ms)('30s')
});
collector.on('collect', async (b) => {
if (b.user.id !== Game.userid &&
b.user.id === message.member.user.id) {
b.reply({
content: `It's <@!${opponent.id}>'s' turn!`,
ephemeral: true
});
}
else if (b.user.id !== Game.userid &&
b.user.id === opponent.id) {
b.reply({
content: `It's <@!${message.member.user.id}>'s' turn!`,
ephemeral: true
});
}
else if (b.user.id !== Game.userid &&
b.user.id !== opponent.id &&
b.user.id !== message.member.user.id) {
b.reply({
content: `You cannot play this game!`,
ephemeral: true
});
}
else if (b.user.id === Game.userid &&
(b.user.id === opponent.id ||
b.user.id === message.member.user.id) &&
Game.board[Number(b.customId)].emoji === x_emoji) {
b.reply({
content: `That position is pre-occupied by ${client.emojis.cache.get(x_emoji) || '❌'}!`,
ephemeral: true
});
}
else if (b.user.id === Game.userid &&
(b.user.id === opponent.id ||
b.user.id === message.member.user.id) &&
Game.board[Number(b.customId)].emoji === o_emoji) {
b.reply({
content: `That position is pre-occupied by ${client.emojis.cache.get(o_emoji) || '⭕'}!`,
ephemeral: true
});
}
else {
await b.deferUpdate();
if (Game.user == 0) {
Game.user = 1;
Game.board[Number(b.customId)] = {
style: OStyle,
emoji: o_emoji,
disabled: true
};
}
else {
Game.user = 0;
Game.board[Number(b.customId)] = {
style: XStyle,
emoji: x_emoji,
disabled: true
};
}
}
await tictactoeEngine(m, {
blank_emoji: blank_emoji
});
});
collector.on('end', (collected, reason) => {
limiter[id].limit -= 1;
if (limiter[id].limit < 0)
limiter[id].limit = 0;
const timeoutEmbed = new discord_js_1.EmbedBuilder()
.setTitle(options.embed?.timeout?.title || 'Game Timed Out!')
.setColor(options.embed?.timeout?.color || 'Red')
.setDescription(options.embed?.timeout?.description ||
'The opponent didnt respond in time (30s)')
.setFooter(options.embed?.timeout?.footer
? options.embed?.timeout?.footer
: {
text: '©️ Rahuletto. npm i simply-djs',
iconURL: 'https://i.imgur.com/XFUIwPh.png'
});
if (options?.embed?.timeout?.fields)
timeoutEmbed.setFields(options.embed?.timeout?.fields);
if (options?.embed?.timeout?.author)
timeoutEmbed.setAuthor(options.embed?.timeout?.author);
if (options?.embed?.timeout?.image)
timeoutEmbed.setImage(options.embed?.timeout?.image);
if (options?.embed?.timeout?.thumbnail)
timeoutEmbed.setThumbnail(options.embed?.timeout?.thumbnail);
if (options?.embed?.timeout?.timestamp)
timeoutEmbed.setTimestamp(options.embed?.timeout?.timestamp);
if (options?.embed?.timeout?.url)
timeoutEmbed.setURL(options.embed?.timeout?.url);
if (collected.size === 0 && reason == 'idle')
if (!options.type || options.type === 'Button')
m.edit({
content: `<@!${Game.userid}> didn't react in time! (30s)`,
embeds: [timeoutEmbed],
components: (0, misc_1.disableButtons)(buttons)
});
else
m.edit({
content: `The opponent didnt respond in time (30s)`,
embeds: [
timeoutEmbed.setDescription(`<@!${Game.userid}> didn't react in time! (30s)\n` +
`\`\`\`\n${Game.board[0].emoji} | ${Game.board[1].emoji} | ${Game.board[2].emoji}\n${Game.board[3].emoji} | ${Game.board[4].emoji} | ${Game.board[5].emoji}\n${Game.board[6].emoji} | ${Game.board[7].emoji} | ${Game.board[8].emoji}\n\`\`\``
.replaceAll(blank_emoji, '➖')
.replaceAll(o_emoji, '⭕')
.replaceAll(x_emoji, '❌'))
],
components: []
});
});
}
}
});
collector.on('end', (_collected, reason) => {
limiter[id].limit -= 1;
if (limiter[id].limit < 0)
limiter[id].limit = 0;
if (reason == 'time') {
const timeoutEmbed = new discord_js_1.EmbedBuilder()
.setTitle(options.embed?.timeout?.title || 'Game Timed Out!')
.setColor(options.embed?.timeout?.color || 'Red')
.setDescription(options.embed?.timeout?.description ||
'The opponent didnt respond in time (30s)')
.setFooter(options.embed?.timeout?.footer
? options.embed?.timeout?.footer
: {
text: '©️ Rahuletto. npm i simply-djs',
iconURL: 'https://i.imgur.com/XFUIwPh.png'
});
if (options?.embed?.timeout?.fields)
timeoutEmbed.setFields(options.embed?.timeout?.fields);
if (options?.embed?.timeout?.author)
timeoutEmbed.setAuthor(options.embed?.timeout?.author);
if (options?.embed?.timeout?.image)
timeoutEmbed.setImage(options.embed?.timeout?.image);
if (options?.embed?.timeout?.thumbnail)
timeoutEmbed.setThumbnail(options.embed?.timeout?.thumbnail);
if (options?.embed?.timeout?.timestamp)
timeoutEmbed.setTimestamp(options.embed?.timeout?.timestamp);
if (options?.embed?.timeout?.url)
timeoutEmbed.setURL(options.embed?.timeout?.url);
m.edit({
content: `<@${opponent.id}> did not accept in time!`,
embeds: [timeoutEmbed],
components: []
});
}
else if (reason == 'decline') {
const declineEmbed = new discord_js_1.EmbedBuilder()
.setColor(options.embed?.decline?.color || 'Red')
.setFooter(options.embed?.decline?.footer
? options.embed?.decline?.footer
: {
text: '©️ Rahuletto. npm i simply-djs',
iconURL: 'https://i.imgur.com/XFUIwPh.png'
})
.setTitle(options.embed?.decline?.title || 'Game Declined!')
.setDescription(options.embed?.decline?.description ||
`${opponent.username} has declined your game request!`);
if (options?.embed?.decline?.fields)
declineEmbed.setFields(options.embed?.decline?.fields);
if (options?.embed?.decline?.author)
declineEmbed.setAuthor(options.embed?.decline?.author);
if (options?.embed?.decline?.image)
declineEmbed.setImage(options.embed?.decline?.image);
if (options?.embed?.decline?.thumbnail)
declineEmbed.setThumbnail(options.embed?.decline?.thumbnail);
if (options?.embed?.decline?.timestamp)
declineEmbed.setTimestamp(options.embed?.decline?.timestamp);
if (options?.embed?.decline?.url)
declineEmbed.setURL(options.embed?.decline?.url);
m.edit({
embeds: [declineEmbed],
components: []
});
}
});
}
catch (err) {
{
if (options?.strict)
throw new error_1.SimplyError({
function: 'tictactoe',
title: 'An Error occured when running the function ',
tip: err.stack
});
else
console.log(`SimplyError - tictactoe | Error: ${err.stack}`);
}
}
});
}
exports.tictactoe = tictactoe;
async function ai(msgOrint, options = { max: 5 }) {
const { client } = msgOrint;
let board = ['', '', '', '', '', '', '', '', ''];
let message;
let interaction;
if (msgOrint.commandId) {
interaction = msgOrint;
}
const extInteraction = msgOrint;
const extMessage = msgOrint;
let id = limiter.findIndex((a) => a.guild == msgOrint.guild.id);
if (!limiter[id] || !limiter[id].guild) {
limiter.push({
guild: msgOrint.guild.id,
limit: 0
});
id = limiter.findIndex((a) => a.guild == msgOrint.guild.id);
}
if (limiter[id].limit >= (options?.max || 6)) {
if (interaction)
return extInteraction.followUp({
content: 'Sorry, There is a game happening right now. Please try later.'
});
else if (!interaction)
return extMessage.reply({
content: 'Sorry, There is a game happening right now. Please try later.'
});
}
const Game = {
board: Array(9).fill({
style: options.emptyStyle,
emoji: options.blank_emoji,
disabled: false
})
};
const opponent = msgOrint.client.user;
const gameEmbed = new discord_js_1.EmbedBuilder()
.setTitle(options.embed?.game?.title ||
`${msgOrint.member.user.username} VS ${opponent.username}`)
.setAuthor(options.embed?.game?.author || {
name: msgOrint.member.user.username,
iconURL: msgOrint.member.user.displayAvatarURL({
forceStatic: false
})
})
.setDescription(`Waiting for Input | <@!${msgOrint.member.user.id}> | Your Emoji: ${client.emojis.cache.get(options.x_emoji) || '❌'}`)
.setColor(options.embed?.game?.color || (0, misc_1.toRgb)('#406DBC'))
.setFooter(options.embed?.game?.footer
? options.embed?.game?.footer
: {
text: '©️ Rahuletto. npm i simply-djs',
iconURL: 'https://i.imgur.com/XFUIwPh.png'
});
if (options?.embed?.game?.fields)
gameEmbed.setFields(options.embed?.game?.fields);
if (options?.embed?.game?.author)
gameEmbed.setAuthor(options.embed?.game?.author);
if (options?.embed?.game?.image)
gameEmbed.setImage(options.embed?.game?.image);
if (options?.embed?.game?.thumbnail)
gameEmbed.setThumbnail(options.embed?.game?.thumbnail);
if (options?.embed?.game?.timestamp)
gameEmbed.setTimestamp(options.embed?.game?.timestamp);
if (options?.embed?.game?.url)
gameEmbed.setURL(options.embed?.game?.url);
const buttons = update();
if (interaction) {
message = await extInteraction.followUp({
embeds: [gameEmbed],
components: buttons
});
}
else if (!interaction) {
message = await extMessage.reply({
embeds: [gameEmbed],
components: buttons
});
}
limiter[id].limit += 1;
function checkWin(emoji) {
return combinations.some((combination) => {
return combination.every((index) => {
return Game.board[index].emoji == emoji;
});
});
}
function isDraw() {
return [...Game.board].every((cell) => {
return cell.emoji == options.x_emoji || cell.emoji == options.o_emoji;
});
}
function update() {
const a1 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[0].style)
.setEmoji(Game.board[0].emoji)
.setCustomId('0')
.setDisabled(Game.board[0].disabled);
const a2 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[1].style)
.setEmoji(Game.board[1].emoji)
.setCustomId('1')
.setDisabled(Game.board[1].disabled);
const a3 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[2].style)
.setEmoji(Game.board[2].emoji)
.setCustomId('2')
.setDisabled(Game.board[2].disabled);
const b1 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[3].style)
.setEmoji(Game.board[3].emoji)
.setCustomId('3')
.setDisabled(Game.board[3].disabled);
const b2 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[4].style)
.setEmoji(Game.board[4].emoji)
.setCustomId('4')
.setDisabled(Game.board[4].disabled);
const b3 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[5].style)
.setEmoji(Game.board[5].emoji)
.setCustomId('5')
.setDisabled(Game.board[5].disabled);
const c1 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[6].style)
.setEmoji(Game.board[6].emoji)
.setCustomId('6')
.setDisabled(Game.board[6].disabled);
const c2 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[7].style)
.setEmoji(Game.board[7].emoji)
.setCustomId('7')
.setDisabled(Game.board[7].disabled);
const c3 = new discord_js_1.ButtonBuilder()
.setStyle(Game.board[8].style)
.setEmoji(Game.board[8].emoji)
.setCustomId('8')
.setDisabled(Game.board[8].disabled);
const a = new discord_js_1.ActionRowBuilder().addComponents([a1, a2, a3]);
const b = new discord_js_1.ActionRowBuilder().addComponents([b1, b2, b3]);
const c = new discord_js_1.ActionRowBuilder().addComponents([c1, c2, c3]);
return [a, b, c];
}
const filter = (interaction) => {
if (interaction.user.id === msgOrint.member.user.id)
return true;
interaction.reply({
content: `You cannot play this game!`,
ephemeral: true
});
return;
};
const aiCollector = message.createMessageComponentCollector({
componentType: discord_js_1.ComponentType.Button,
idle: 30000,
filter: filter
});
let aiTurn = false;
aiCollector.on('collect', async (button) => {
if (isDraw() || checkWin(options.x_emoji) || checkWin(options.o_emoji))
aiCollector.stop();
if (!button.deferred)
await button.deferUpdate();
if (aiTurn) {
await button.followUp({
content: `It's <@!${opponent.id}>'s turn!`,
ephemeral: true
});
return;
}
else if (Game.board[Number(button.customId)].emoji === options.x_emoji) {
await button.followUp({
content: `That position is pre-occupied by ${client.emojis.cache.get(options.x_emoji) || '❌'}!`,
ephemeral: true
});
return;
}
else if (Game.board[Number(button.customId)].emoji === options.o_emoji) {
await button.followUp({
content: `That position is pre-occupied by ${client.emojis.cache.get(options.o_emoji) || '⭕'}!`,
ephemeral: true
});
return;
}
aiTurn = true;
board[Number(button.customId)] = 'x';
const buttonInitial = update();
await message.edit({
components: buttonInitial
});
for (let i = 0; i < board.length; i++) {
const elem = board[i];
if (elem == 'x') {
Game.board[i] = {
style: options.x_style,
emoji: options.x_emoji,
disabled: true
};
}
}
const buttonUpdateX = update();
if (!isDraw() && !checkWin(options.x_emoji) && !checkWin(options.o_emoji))
message.edit({
embeds: [
gameEmbed
.setDescription(`AI is Thinking.. | <@!${opponent.id}> | Your Emoji: ${client.emojis.cache.get(options.o_emoji) || '⭕'}`)
.setColor(`DarkerGrey`)
],
components: buttonUpdateX
});
if (!isDraw() && !checkWin(options.x_emoji) && !checkWin(options.o_emoji)) {
aiCollector.resetTimer();
board = await aiEngine(board);
}
for (let i = 0; i