Apps Home
|
My Uploads
|
Create an App
unaahangman
Author:
unaa
Description
Source Code
Launch App
Current Users
Created by:
Unaa
App Images
const IMAGES = [ "2bcb001e-8e4f-4613-98d6-cbb209c2ff28", "5687e2c7-6ed2-473e-8d3a-ad876e9f89d7", "9bac252a-de1b-4c4c-b28e-1b8e1665622b", "b4d42a99-9fa0-4e5c-9f11-8f4f9111cb88", "a5fdaf07-493c-4d9c-bb7b-00f49f407af1", "a931aafd-7ad9-49b4-8cee-ae897af6e483", "b44667fb-a53e-4f4c-be34-3b93e4ddff39", "cec8dce4-e0ee-473c-9f15-48a8e9fce22d", "05d50321-95b5-4b57-b268-9ee564773655", "aa74e06d-540a-4ed8-a881-464fefba094a", "da35d0a7-7aac-4971-80de-63ca7a0f7b45", "34800945-dbae-440b-92c4-c3fe4437b9f6", "6039aa18-13f3-420c-9641-6cedcef5bb7f" ]; class Hangman { constructor(words, goals) { this.words = this._parseWords(words || ""); this.goals = this._parseGoals(goals || ""); this.doneGoals = []; this.doneWords = []; this.wordIndex = -1; this.goalIndex = -1; cb.onMessage((c) => this._handleChatMessage(c)); cb.onTip((tip) => this._handleTip(tip.from_user, tip.amount, tip.message)); cb.onEnter((user) => this._sendIntroNotice(user.user)); this.startRound(); } /** * Starts a new round of hangman. */ startRound() { this.gameOver = false; this.wrongCount = 0; this.wrongLetters = []; this.wordIndex = this._pickRandomIndex(this.words, this.wordIndex, this.doneWords); this.goalIndex = this._pickRandomIndex(this.goals, this.goalIndex, this.doneGoals); this.word = this.words[this.wordIndex]; this.goal = this.goals[this.goalIndex]; this.letters = this.word.split(""); this.guessed = Array(this.word.length).fill("_"); cb.log(this.word); cb.log(JSON.stringify(this.letters)); // cb.log("CURRENT WORD: " + this.word); // cb.log("CURRENT GOAL: " + this.goal); this._sendIntroNotice(); cb.onDrawPanel(() => this._drawPanel()); cb.drawPanel(); } /** * Let the given username guess the specified letter. * * @param {string} username * @param {string} letter */ guessLetter(username, letter) { // Don't do anything if the game is already over. if (this.gameOver) { return; } // Check if the current round is over. if (this.wrongCount === 12) { this.endRound(false); return; } // If the guessed letter is not in the word, notify the user privately and increase the wrong-guess count. if (this.letters.indexOf(letter) === -1) { // Check if this letter was already guessed wrong. if (this.wrongLetters.indexOf(letter) !== -1) { cb.sendNotice("Sorry " + username + ", but that letter was already guessed and is not part of the word.", username); return; } cb.sendNotice("Sorry " + username + ", but that letter is not part of the word.", username); this.wrongCount++; this.wrongLetters.push(letter); cb.drawPanel(); if (this.wrongCount === 12) { this.endRound(false, username); } return; } // Update the 'guessed letters' display. for (let i = 0; i < this.letters.length; i++) { if (this.letters[i] === letter) { this.guessed[i] = letter; } } // Check if we finished the round. let positionsToGo = 0; for (let i = 0; i < this.guessed.length; i++) { positionsToGo += (this.guessed[i] === "_") ? 1 : 0; } if (positionsToGo > 0) { // We still have at least one letter to guess. cb.drawPanel(); return; } this.endRound(true, username); } endRound(won, username) { // Don't do anything if the game is already over. if (this.gameOver) { return; } this.gameOver = true; if (!won) { cb.sendNotice(`GAME OVER! Starting a new round of hangman in 3 seconds...`, undefined, "#84f", "#fff", "bolder"); // Start another round after 3 seconds. setTimeout(() => this.startRound(), 3000); return; } // Update the panel. this.guessed = this.letters; cb.drawPanel(); cb.sendNotice(`CONGRATULATIONS ${username} FOR FINISHING THIS ROUND!`, undefined, "#84f", "#fff", "bolder"); cb.sendNotice(`THE PRIZE FOR THIS ROUND IS: ${this.goal}!`, undefined, "#95f", "#fff", "bolder"); cb.sendNotice(`STARTING ANOTHER ROUND IN 30 seconds...`, undefined, "#a6f", "#fff", "bolder"); this.doneGoals.push(this.goal); this.doneWords.push(this.word); setTimeout(() => this.startRound(), 30000); } /** * Sends the help/intro notice to chat. * * @param username * @private */ _sendIntroNotice(username = undefined) { cb.sendNotice( `A round of hangman has started! Tip at least ${cb.settings.minTokensToGuessLetter} with ONE LETTER in the tip message to take a guess.`, username, "#84f", "#fff", "bolder" ); cb.sendNotice( `If you think you know the word, tip at least ${cb.settings.minTokensToGuessWord} with JUST THE WORD in the tip message to take a guess.`, username, "#84f", "#fff", "bolder" ); if (cb.settings.allowSeeGuessedLetters) { cb.sendNotice( `You can type /guessed to see which letters were already guessed but were not part of the word.`, username, "#95f", "#fff", "bold" ); } } /** * Handle chat message. (@TODO: REPLACE WITH onTip) * @param chat * @private */ _handleChatMessage(chat) { if (! cb.settings.allowSeeGuessedLetters) { return; } if (chat.m.startsWith("/guessed")) { chat['X-Spam'] = true; let message = `These letters were guessed wrong previously: ${this.wrongLetters.join(', ')}.`; cb.sendNotice(message, chat.user); } } /** * @param {string} username * @param {number} amount * @param {string} message * @private */ _handleTip(username, amount, message) { // Make sure the tip amount is equal or greater than the configured minimum amount. if (amount < cb.settings.minTokensToGuessLetter) { return; } // If the tipped amount is equal or greater than the configured amount needed to guess a word, do this first. if (amount >= cb.settings.minTokensToGuessWord) { // Make sure the user ONLY sent a word. if (message.split(" ") > 1) { return; } // Check if the given word is the right one. let word = message.toUpperCase(); if (word === this.word) { this.guessed = this.letters; return this.endRound(true, username); } } // If the tip message only consists of one letter, play along... let letter = message.toUpperCase(); if (letter.length === 1) { this.guessLetter(username, letter); } } /** * Draws the app panel. * @private */ _drawPanel() { return { "template": "image_template", "layers": [ {"type": "image", "fileID": IMAGES[this.wrongCount]}, { "type": "text", "text": this.guessed.join(" "), "top": 15, "left": 70, "font-size": 14, "font-family": "monospace", "color": "white" }, { "type": "text", "text": this.goal, "top": 38, "left": 70, "font-size": 13, "font-family": "Monotype Corsiva, Comic Sans MS, cursive", "color": "grey" } ] }; } /** * Picks a random index from the given array. * * @param {Array} array * @param {number} lastIndex * @returns {number} * @private */ _pickRandomIndex(array, lastIndex = -1, usedValues = []) { if (lastIndex === -1 || array.length === 1) { return Math.floor(Math.random() * array.length); } let result = lastIndex; while (result === lastIndex) { result = Math.floor(Math.random() * array.length); } if (usedValues.length < array.length && usedValues.indexOf(result) !== -1) { return this._pickRandomIndex(array, lastIndex, usedValues); } if (usedValues.length === array.length) { cb.log('All words/goals have been used! Resetting used values list'); for (let i = 0; i < usedValues.length; i++) { cb.log('Removing [' + usedValues[i] + ']'); delete usedValues[i]; } } return result; } /** * Parses the configured words into a usable array. * * @returns {string[]} * @private */ _parseWords(w) { let words = []; w.split(",").forEach((word) => { words.push(word.toUpperCase().trim()); }); return words; } /** * Parses the configured goals into a usable array. * * @returns {string[]} * @private */ _parseGoals(g) { let goals = []; g.split(",").forEach((goal) => { goals.push(goal.trim()); }); return goals; } } cb.settings_choices = [ { name: "words", label: "Words (separated by comma)", type: "str", minLength: 0, maxLength: 1024, defaultValue: "tranquility,dancing,happiness,delightful" }, { name: "goals", label: "Goals (separated by comma)", type: "str", minLength: 0, maxLength: 1024, defaultValue: "Sexy dance,Challenge,Double Trouble" }, { name: "minTokensToGuessLetter", label: "Amount of tokens to guess a letter", type: "int", minValue: 1, maxValue: 300, defaultValue: 15 }, { name: "minTokensToGuessWord", label: "Amount of tokens to guess a word (0 to disable)", type: "int", minValue: 1, maxValue: 2000, defaultValue: 200 }, { name: "allowSeeGuessedLetters", label: "Allow users to see what letters have been guessed before", type: "choice", choice1: "Yes", choice2: "No", defaultValue: "Yes" } ]; new Hangman(cb.settings.words, cb.settings.goals);
© Copyright Chaturbate 2011- 2025. All Rights Reserved.