78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
import { GuildMember, SlashCommandBuilder, CommandInteraction, messageLink } from 'discord.js';
|
|
import { getTextResponsePrettyPlease, randomWord, sendSegments, startGame } from '../lib/game';
|
|
import { Command } from '../types/index';
|
|
|
|
const END_TEMPLATES = [
|
|
'Alright! Here\'s the messages you all conjured:',
|
|
'Here are the abominations you all have made:',
|
|
'Time\'s up! Here\'s what you\'ve managed to achieve:',
|
|
'That does it! Here\'s what you\'ve all cooked up together:'
|
|
];
|
|
|
|
export default {
|
|
data: new SlashCommandBuilder()
|
|
.setName('markov')
|
|
.setDescription('Play a Markov chain game')
|
|
.addIntegerOption(option =>
|
|
option
|
|
.setName('context')
|
|
.setRequired(false)
|
|
.setDescription('Amount of words to show as context')
|
|
.setMinValue(1)
|
|
.setMaxValue(100)
|
|
)
|
|
.addIntegerOption(option =>
|
|
option
|
|
.setName('iterations')
|
|
.setRequired(false)
|
|
.setDescription('Amount of rounds to do')
|
|
.setMinValue(1)
|
|
.setMaxValue(100)),
|
|
|
|
execute: async (interaction: CommandInteraction) => {
|
|
if (!interaction.isChatInputCommand()) return;
|
|
|
|
const member = interaction.member! as GuildMember;
|
|
|
|
const context = interaction.options.getInteger('context') || 3;
|
|
const maxIterations = interaction.options.getInteger('iterations') || 10;
|
|
|
|
startGame(interaction, member.user, 'Markov Chain', async (participants, channel) => {
|
|
let sentences: string[][] = Array(participants.length).fill(0);
|
|
sentences = sentences.map(() => []);
|
|
let iterations = 0;
|
|
|
|
// eslint-disable-next-line no-constant-condition
|
|
while (true) {
|
|
await Promise.all(
|
|
participants.map(async (p, i) => {
|
|
const sentence = sentences[(i + iterations) % sentences.length];
|
|
const prompt = (`Continue the following sentence: [${iterations}/${maxIterations}]\n\n> _${context < sentence.length ? '…' : ''}${sentence.length > 0 ? sentence.slice(-context).join(' ') : `start a sentence... (try working with: “${randomWord()}”)`}_` + (iterations === 0 ? '\n\n**Send a message to continue**' : '')).slice(0, 2000);
|
|
|
|
const resp = await getTextResponsePrettyPlease(p, prompt);
|
|
sentence.push(...resp.split(' '));
|
|
})
|
|
);
|
|
|
|
iterations++;
|
|
|
|
if (iterations > maxIterations) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
const endTemplate = END_TEMPLATES[Math.floor(Math.random() * END_TEMPLATES.length)];
|
|
|
|
const segments = [
|
|
endTemplate + '\n',
|
|
...sentences.map(sentence => '- ' + sentence.join(' ')),
|
|
'\nThank you for participating :)'
|
|
];
|
|
|
|
const messages = await sendSegments(segments, channel);
|
|
participants.forEach(player => {
|
|
player.send(`**The game has concluded!** See your results here: ${messageLink(messages[0].channelId, messages[0].id)}`);
|
|
});
|
|
});
|
|
}
|
|
} satisfies Command; |