schat2-clive/src/games/hunt.js

164 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
const config = require('config');
const words = require('../../assets/mash-words.json');
const pickRandom = require('../utils/pick-random');
const style = require('../utils/style');
const games = new Map();
const targets = ['🐣', '🐕', '🐈', '🐢', '🐇', '🐁', '🦔'];
const predators = ['🦅', '🐍', '🦖', '🐅', '🐆', '🐊', '🐉'];
const trees = ['🌴', '🌳', '🌲', '🌵'];
const flowers = ['🌹', '🌻', '🌷', '🌱', '🍄', '🪨'];
function getGuesses(word) {
if (Array.isArray(config.hangman.guesses)) {
return config.hangman.guesses[word.length - 1] || config.hangman.guesses.at(-1);
}
return config.hangman.guesses;
}
function renderBoard(context) {
const game = games.get(context.room.id);
const word = game.partial.map((letter) => letter || '_').join(' ').toUpperCase();
const track = `${game.flower}${game.target}${game.track.slice(0, getGuesses(game.word) - game.progress).join('')}${game.predator}`;
context.sendMessage(`${style.bold(style.code(word))} ${track}`, context.room.id);
}
function getOutcome(target, predator) {
return pickRandom([
`${target} and ${predator} will now have to spend time together`,
`${target} will now have to listen to boring stories from ${predator}`,
`${target} must now endure a horrible tickle attack from ${predator}`,
`${target} and ${predator} are now going to waste an entire day arguing which one of them has more legs`,
`${predator} is out of breath now`,
`${target} will now have to explain why they never answer any texts from ${predator}`,
]);
}
function progress(context) {
const game = games.get(context.room.id);
game.progress += 1;
if (game.progress > getGuesses(game.word)) {
context.sendMessage(`The word ${style.bold(game.word)} was not guessed. ${getOutcome(game.target, game.predator)}.`, context.room.id);
games.delete(context.room.id);
return;
}
renderBoard(context);
}
function playLetter(playedLetter, context) {
const game = games.get(context.room.id);
if (game.partial.includes(playedLetter)) {
return;
}
if (!game.word.includes(playedLetter)) {
progress(context);
return;
}
game.partial = game.partial.map((letter, index) => letter
|| (game.word[index] === playedLetter && game.word[index])
|| null);
renderBoard(context);
if (game.partial.every((letter) => letter !== null)) {
context.sendMessage(style.bold('The word was completed!'), context.room.id);
games.delete(context.room.id);
}
}
function playWord(word, context) {
const game = games.get(context.room.id);
if (word === game.word) {
context.sendMessage(`The word ${style.answer(word)} was guessed, ${style.username(context.user.prefixedUsername)}, who gets a point!`, context.room.id);
context.setPoints(context.user);
games.delete(context.room.id);
return;
}
context.sendMessage('That\'s not it', context.room.id);
progress(context);
}
function stop(context) {
const game = games.get(context.room.id);
if (!game) {
context.sendMessage(`There is no game going on, ${style.username(context.user.prefixedUsername)}. You can start one with ${config.prefix}hunt!`, context.room.id);
return;
}
games.delete(context.room.id);
context.sendMessage(`The game was stopped by ${style.username(context.user.prefixedUsername)}. The word was ${style.bold(game.word)} with ${getGuesses(game.word) - game.progress} guesses remaining.`, context.room.id);
}
function onCommand(args, context) {
if (context.subcommand === 'stop') {
stop(context);
return;
}
const minLength = Number(args[0]) || config.hangman.minLength;
const maxLength = Number(args[0]) || config.hangman.maxLength;
const playableWords = Array.from({ length: (maxLength - minLength) + 1 }, (value, index) => Object.values(words[index + minLength] || {})).flat(2);
const word = pickRandom(playableWords);
if (!word) {
context.sendMessage('Sorry, I was not able to find a word to play.', context.room.id);
return;
}
context.logger.info(`Hangman played ${word.word} with ${getGuesses(word)} guesses`);
games.set(context.room.id, {
word: word.word,
progress: 0,
defintiions: word.definitions,
partial: word.word.split('').map(() => null),
flower: pickRandom(flowers),
target: pickRandom(targets),
predator: pickRandom(predators),
track: Array.from({ length: getGuesses(word) }, (value, index) => (index % 2 ? pickRandom(trees) : '')), // Em Space to ensure proper spacing in SChat
});
renderBoard(context);
}
function onMessage(message, context) {
if (games.has(context.room.id)) {
const letter = message.body.match(/^\s*\w\s*$/)?.[0];
const word = message.body.match(/^\s*\w{2,}\s*$/)?.[0];
if (letter) {
playLetter(letter.toLowerCase().trim(), context);
return;
}
if (word) {
playWord(word.toLowerCase().trim(), context);
}
}
}
module.exports = {
onCommand,
onMessage,
commands: ['hangman'],
};