Apps Home
|
Create an App
Game Night
Author:
auspunk
Description
Source Code
Launch App
Current Users
Created by:
Auspunk
/*global cb: false, cbjs: false */ /*jshint forin: false */ "use strict"; var colours = { aliceblue: '#f0f8ff', antiquewhite: '#faebd7', aqua: '#00ffff', aquamarine: '#7fffd4', azure: '#f0ffff', beige: '#f5f5dc', bisque: '#ffe4c4', black: '#000000', blanchedalmond: '#ffebcd', blue: '#0000ff', blueviolet: '#8a2be2', brown: '#a52a2a', burlywood: '#deb887', cadetblue: '#5f9ea0', chartreuse: '#7fff00', chocolate: '#d2691e', coral: '#ff7f50', cornflowerblue: '#6495ed', cornsilk: '#fff8dc', crimson: '#dc143c', cyan: '#00ffff', darkblue: '#00008b', darkcyan: '#008b8b', darkgoldenrod: '#b8860b', darkgray: '#a9a9a9', darkgreen: '#006400', darkgrey: '#a9a9a9', darkkhaki: '#bdb76b', darkmagenta: '#8b008b', darkolivegreen: '#556b2f', darkorange: '#ff8c00', darkorchid: '#9932cc', darkred: '#8b0000', darksalmon: '#e9967a', darkseagreen: '#8fbc8f', darkslateblue: '#483d8b', darkslategray: '#2f4f4f', darkslategrey: '#2f4f4f', darkturquoise: '#00ced1', darkviolet: '#9400d3', deeppink: '#ff1493', deepskyblue: '#00bfff', dimgray: '#696969', dimgrey: '#696969', dodgerblue: '#1e90ff', firebrick: '#b22222', floralwhite: '#fffaf0', forestgreen: '#228b22', fuchsia: '#ff00ff', gainsboro: '#dcdcdc', ghostwhite: '#f8f8ff', gold: '#ffd700', goldenrod: '#daa520', gray: '#808080', green: '#008000', greenyellow: '#adff2f', grey: '#808080', honeydew: '#f0fff0', hotpink: '#ff69b4', indianred: '#cd5c5c', indigo: '#4b0082', ivory: '#fffff0', khaki: '#f0e68c', lavender: '#e6e6fa', lavenderblush: '#fff0f5', lawngreen: '#7cfc00', lemonchiffon: '#fffacd', lightblue: '#add8e6', lightcoral: '#f08080', lightcyan: '#e0ffff', lightgoldenrodyellow: '#fafad2', lightgray: '#d3d3d3', lightgreen: '#90ee90', lightgrey: '#d3d3d3', lightpink: '#ffb6c1', lightsalmon: '#ffa07a', lightseagreen: '#20b2aa', lightskyblue: '#87cefa', lightslategray: '#778899', lightslategrey: '#778899', lightsteelblue: '#b0c4de', lightyellow: '#ffffe0', lime: '#00ff00', limegreen: '#32cd32', linen: '#faf0e6', magenta: '#ff00ff', maroon: '#800000', mediumaquamarine: '#66cdaa', mediumblue: '#0000cd', mediumorchid: '#ba55d3', mediumpurple: '#9370db', mediumseagreen: '#3cb371', mediumslateblue: '#7b68ee', mediumspringgreen: '#00fa9a', mediumturquoise: '#48d1cc', mediumvioletred: '#c71585', midnightblue: '#191970', mintcream: '#f5fffa', mistyrose: '#ffe4e1', moccasin: '#ffe4b5', navajowhite: '#ffdead', navy: '#000080', oldlace: '#fdf5e6', olive: '#808000', olivedrab: '#6b8e23', orange: '#ffa500', orangered: '#ff4500', orchid: '#da70d6', palegoldenrod: '#eee8aa', palegreen: '#98fb98', paleturquoise: '#afeeee', palevioletred: '#db7093', papayawhip: '#ffefd5', peachpuff: '#ffdab9', peru: '#cd853f', pink: '#ffc0cb', plum: '#dda0dd', powderblue: '#b0e0e6', purple: '#800080', rebeccapurple: '#663399', red: '#ff0000', rosybrown: '#bc8f8f', royalblue: '#4169e1', saddlebrown: '#8b4513', salmon: '#fa8072', sandybrown: '#f4a460', seagreen: '#2e8b57', seashell: '#fff5ee', sienna: '#a0522d', silver: '#c0c0c0', skyblue: '#87ceeb', slateblue: '#6a5acd', slategray: '#708090', slategrey: '#708090', snow: '#fffafa', springgreen: '#00ff7f', steelblue: '#4682b4', tan: '#d2b48c', teal: '#008080', thistle: '#d8bfd8', tomato: '#ff6347', turquoise: '#40e0d0', violet: '#ee82ee', wheat: '#f5deb3', white: '#ffffff', whitesmoke: '#f5f5f5', yellow: '#ffff00', yellowgreen: '#9acd32' }; cb.settings_choices = [ {name: 'gamedata', type: 'str', label: 'Game data', defaultValue: ''} ]; var FINAL_PRIZE = '_nothing'; // just a keyword used internally. can't be used for other things. var BONUS_LAST_RESORT = 'nobonus'; // ---------------------------------------------------------------------------- // // UTILITY FUNCTIONS // // ---------------------------------------------------------------------------- function is_digits(thing) { if (typeof(thing) !== 'undefined' && /^[0-9]+$/.test(thing.toString())) { return true; } else { return false; } } // ---------------------------------------------------------------------------- // // COMMUNICATION FUNCTIONS // // ---------------------------------------------------------------------------- var interp = { user: function(text, user) { return text.replace(/%%/ig, user); }, admin: function(text) { return text.replace(/&&/ig, cb.room_slug); }, prize: function(text, prizetext) { return text.replace(/\^\^/ig, prizetext); }, number: function(text, num) { return text.replace(/##/ig, num.toString()); }, ordinal: function(text, num) { var ordsuffix = ''; var two = ''; var one = ''; if (is_digits(num)) { // get last two digits and last digit two = parseInt(('00' + num.toString()).slice(-2), 10); one = parseInt(('00' + num.toString()).slice(-1), 10); // teenths are special if (two >= 10 && two <= 19) { ordsuffix = 'th'; } else { switch (one) { case 1: ordsuffix = 'st'; break; case 2: ordsuffix = 'nd'; break; case 3: ordsuffix = 'rd'; break; default: ordsuffix = 'th'; } } } else { ordsuffix = ''; } return text.replace(/##/ig, num.toString() + ordsuffix); } }; var tell = { all: function (message, about) { if (typeof(about) === 'string' && about !== '') { cb.chatNotice(interp.admin(interp.user(message, about)), '', '', colours.deeppink, 'bold'); } else { cb.chatNotice(interp.admin(message), '', '', colours.deeppink, 'bold'); } }, prize: function (message, about) { if (typeof(about) === 'string' && about !== '') { cb.chatNotice(interp.admin(interp.user(message, about)), '', colours.palegreen, colours.black, 'bold'); } else { cb.chatNotice(interp.admin(message), '', colours.palegreen, colours.black, 'bold'); } }, one: function (message, to) { cb.chatNotice(interp.admin(interp.user(message, to)), to, '', colours.blue, 'bold'); }, boss: function(message) { cb.chatNotice(interp.admin(message), cb.room_slug, '', colours.steelblue, ''); }, debug: function(message) { cb.log(message); } }; // ---------------------------------------------------------------------------- // // ROOM WATCHER // // ---------------------------------------------------------------------------- var room = { _welcome: "Welcome to &&'s room!", _users: { all: [cb.room_slug], current: [cb.room_slug] }, _alarms: { users: [], visitors: [] }, notice: function(username) { if (!cbjs.arrayContains(room._users.all, username)) { room._users.all.push(username); } if (!cbjs.arrayContains(room._users.current, username)) { room._users.current.push(username); } }, on_enter: function(username) { // Track users room.notice(username); // Welcome message tell.one(room._welcome, username); // Announcements. if (typeof(room._alarms.users[room.user_count()]) !== 'undefined') { tell.all(room._alarms.users[room.user_count()], username); delete room._alarms.users[room.user_count()]; } if (typeof(room._alarms.visitors[room.visitor_count()]) !== 'undefined') { tell.all(room._alarms.visitors[room.visitor_count()], username); delete room._alarms.visitors[room.visitor_count()]; } }, on_leave: function(username) { if (cbjs.arrayContains(room._users.current, username)) { cbjs.arrayRemove(room._users.current, username); } }, is_user: function(username) { return cbjs.arrayContains(room._users.current, username); }, user_count: function() { // length - 1 so the broadcaster isn't counted. return room._users.current.length - 1; }, visitor_count: function() { // length - 1 so the broadcaster isn't counted. return room._users.all.length - 1; }, init_alarms: function(data) { // array of { visitors, message } or { users, message } objects for (var i = 0; i < data.length; i++) { if (typeof(data[i].message) === 'string' && is_digits(data[i].users)) { room.set_users_alarm(data[i].users, data[i].message); } if (typeof(data[i].message) === 'string' && is_digits(data[i].visitors)) { room.set_visitors_alarm(data[i].visitors, data[i].message); } } }, show_welcome: function() { tell.boss(room._welcome); }, show_users_alarms: function() { tell.boss('Room currently at ' + room.user_count() + ' user(s).'); for (var i = 0; i < room._alarms.users.length; i++) { if (typeof(room._alarms.users[i]) !== 'undefined') { tell.boss(i + ' users: ' + room._alarms.users[i]); } } }, show_visitors_alarms: function() { tell.boss('Room currently at ' + room.visitor_count() + ' total visitor(s).'); for (var i = 0; i < room._alarms.visitors.length; i++) { if (typeof(room._alarms.visitors[i]) !== 'undefined') { tell.boss(i + ' visitors: ' + room._alarms.visitors[i]); } } }, set_welcome: function(message) { if (typeof(message) === 'string' && message.length > 0) { if (room._welcome !== message) { tell.all(message, 'everyone'); } room._welcome = message; } }, set_users_alarm: function(count, message) { if (typeof(message) !== 'string' || message.length === 0) { // clear alarm if (typeof(room._alarms.users[count]) !== 'undefined') { delete room._alarms.users[count]; tell.boss('Users alarm ' + count + ' cleared.'); } } else { // set alarm room._alarms.users[count] = interp.number(message, count); tell.boss('At ' + count + ' users: ' + room._alarms.users[count]); } }, set_visitors_alarm: function(count, message) { if (typeof(message) !== 'string' || message.length === 0) { // clear alarm if (typeof(room._alarms.visitors[count]) !== 'undefined') { delete room._alarms.visitors[count]; tell.boss('Visitors alarm ' + count + ' cleared.'); } } else { // set alarm room._alarms.visitors[count] = interp.ordinal(message, count); tell.boss('At visitor ' + count + ': ' + room._alarms.visitors[count]); } } }; var cmds = { _cmds: { // hashes of {keyword: function} callbacks. admin: {}, // Set once and left alone. Calling convention is function(params, force). params is a string with everything except the command. force is a boolean. player: {} // Wiped for each game round. Calling convention is function(user). Can't expect channel visitors to figure out fancy syntax. }, register_admin: function(command, callback) { tell.debug("New admin command: " + command); if (typeof(command) === 'string' && typeof(callback) === 'function') cmds._cmds.admin[command] = callback; }, register_player: function(command, callback) { tell.debug("New player command: " + command); if (typeof(command) === 'string' && typeof(callback) === 'function') cmds._cmds.player[command] = callback; }, clear_player: function() { tell.debug("Clearing player commands."); cmds._cmds.player = {}; }, on_end_round: function() { cmds.clear_player(); }, interpret: function(msg) { // chaturbate message object (i.e. msg.m, msg.user etc.) var m = msg.m; var u = msg.user; var force = false; if (m[0] === '/') { m = m.slice(1); // check for force flag e.g. /!play if (m[0] === '!') { force = true; m = m.slice(1); } var keyword = (m.length > 0) ? m.toLowerCase().match(/^[\S]+/)[0] : ''; var params = m.slice(keyword.length).trim(); if (typeof(cmds._cmds.player[keyword]) === 'function') { if (engine.current_player() === '') { tell.debug("Locking in player: " + u); engine.set_player(u); cb.drawPanel(); } if (engine.current_player() === u) { tell.debug("Executing player callback for keyword '" + keyword + "'"); cmds._cmds.player[keyword](u); } else if (u === cb.room_slug) { if (force) { tell.debug("Executing admin override player callback for keyword '" + keyword + "'"); cmds._cmds.player[keyword](u); } else { tell.boss("Use /!command to take over from the player."); } } else { tell.debug("Matched player keyword '" + keyword + "' but no permissions."); } } else if (typeof(cmds._cmds.admin[keyword]) === 'function') { if (u === cb.room_slug) { tell.debug("Executing admin callback for keyword '" + keyword + "'"); cmds._cmds.admin[keyword].call(admin, params, force); } else { tell.debug("Matched admin keyword '" + keyword + "' but no permissions."); } } } } }; // ---------------------------------------------------------------------------- // // PANEL FUNCTIONS // // ---------------------------------------------------------------------------- var panel = { _last_prize: '', set_prize: function(prizetext) { panel._last_prize = prizetext; }, data: function() { var current_player; if (engine.in_game()) { current_player = engine.current_player(); if (current_player === '') current_player = "Anyone! Type /spin"; } else { current_player = ''; } return { 'template': '3_rows_12_22_31', 'row1_label': 'Current Player:', 'row1_value': current_player, 'row2_label': 'Last Prize:', 'row2_value': panel._last_prize, 'row3_value': '' }; } }; // ---------------------------------------------------------------------------- // // ADMIN FUNCTIONS // // ---------------------------------------------------------------------------- var admin = { init: function() { for (var key in admin) { if (typeof(admin[key]) === 'object' && typeof(admin[key].keywords) === 'object' && typeof(admin[key].code) === 'function') { for (var i = 0; i < admin[key].keywords.length; i++) { cmds.register_admin(admin[key].keywords[i], admin[key].code); } } } }, reset: { keywords: ['reset'], code: function(params, force) { void(params); if (force) { engine.end_round(); tell.boss("Game reset."); } else { tell.boss("Use /!reset."); } } }, play: { keywords: ['go', 'play'], code: function(params, force) { var delay = 0; var player = ''; var error = false; if (!engine.in_game()) { // Interpret parameters var words = params.trim().split(/\s+/); // Delete empty words because JS sucks for (var j = words.length; j--; ) { if (words[j] === '') words.splice(j, 1); } if (words.length > 2) { tell.boss("Too many parameters. Use '/play username delay' (both optional)."); error = true; } if (force) { if (typeof(words[0]) === 'string') { tell.debug('Forced player: ' + words[0]); player = words[0]; } if (typeof(words[1]) !== 'undefined') { if (is_digits(words[1])) { tell.debug('Identified delay: ' + words[1]); delay = parseInt(words[1], 10); } else { tell.boss("Delay must be an integer if present."); error = true; } } } else { tell.debug ("Processing " + words.length + " words"); for (var i = 0; i < words.length; i++) { if (room.is_user(words[i])) { tell.debug('Identified player: ' + words[i]); player = words[i]; } else if (is_digits(words[i])) { tell.debug('Identified delay: ' + words[i]); delay = parseInt(words[i], 10); } else { tell.boss("Can't recognise " + words[i] + " as a player. Use '/!play username delay' to override."); error = true; } } } // Start or schedule game round if (!error) { if (delay === 0) { engine.new_round(player); } else { tell.boss("Game round scheduled for " + delay + " seconds."); cb.setTimeout(function() { engine.new_round(player); }, delay * 1000); } } } else { tell.boss("Game already active. /reset if necessary."); } } }, tierinfo: { keywords: ['tierinfo'], code: function(params, force) { void(params); void(force); pool.show_tier_info(); } }, tierweights: { keywords: ['tier', 'tiers', 'tierweight', 'tierweights'], code: function(params, force) { void(force); var i; var words; var tier; var weight; var error; var validnames; var tierweights; var defaultweight = -1; if (params.length === 0) { pool.show_tier_weights(); } else { error = false; tierweights = {}; validnames = pool.tier_names(); words = params.trim().split(/\s+/); for (i = 0; i < words.length; i++) { if (i % 2 === 0) { // expect keyword tier = ''; weight = 0; if (typeof(words[i]) === 'string' && (typeof(validnames[words[i]]) !== 'undefined' || words[i] === '*')) { tier = words[i]; } else { error = true; tell.boss("Invalid tier name: " + words[i]); break; } } else { // expect weight if (is_digits(words[i])) { weight = parseInt(words[i], 10); if (tier === '*') { defaultweight = weight; } else { tierweights[tier] = weight; } } else { error = true; tell.boss("Invalid tier weight: " + words[i]); break; } } } if (!error) { for (tier in validnames) { if (typeof(tierweights[tier]) === 'undefined') tierweights[tier] = defaultweight; } pool.set_tier_weights(tierweights); } } } }, modeweights: { keywords: ['mode', 'modes', 'modeweight', 'modeweights'], code: function(params, force) { void(force); var i; var words; var mode; var weight; var error; var validgames; var modeweights; var defaultweight = -1; if (params.length === 0) { prize_games.show_weights(); } else { error = false; modeweights = {}; validgames = prize_games.list(); words = params.trim().split(/\s+/); for (i = 0; i < words.length; i++) { if (i % 2 === 0) { // expect keyword mode = ''; weight = 0; if (typeof(words[i]) === 'string' && (typeof(validgames[words[i]]) !== 'undefined' || words[i] === '*')) { mode = words[i]; } else { error = true; tell.boss("Invalid mode name: " + words[i]); break; } } else { // expect weight if (is_digits(words[i])) { weight = parseInt(words[i], 10); if (mode === '*') { defaultweight = weight; } else { modeweights[mode] = weight; } } else { error = true; tell.boss("Invalid mode weight: " + words[i]); break; } } } if (!error) { for (mode in validgames) { if (typeof(modeweights[mode]) === 'undefined') modeweights[mode] = defaultweight; } prize_games.set_weights(modeweights); } } } }, bonusweights: { keywords: ['bonus', 'bonuses', 'bonusweight', 'bonusweights'], code: function(params, force) { void(force); var i; var words; var type; var bonus; var weight; var error; var validtypes; var validgames; var bonusweights; var defaultweight = -1; if (params.length === 0) { bonus_games.show_weights(); } else { validtypes = pool.type_names(); words = params.trim().split(/\s+/); if (typeof(words[0]) === 'string' && typeof(validtypes[words[0]]) !== 'undefined') { type = words[0]; if (params.length === 1) { bonus_games.show_weights(type); } else { error = false; bonusweights = {}; validgames = bonus_games.list(); for (i = 1; i < words.length; i++) { if (i % 2 === 1) { // expect keyword bonus = ''; weight = 0; if (typeof(words[i]) === 'string' && (typeof(validgames[words[i]]) !== 'undefined' || words[i] === '*')) { bonus = words[i]; } else { error = true; tell.boss("Invalid bonus name: " + words[i]); break; } } else { // expect weight if (is_digits(words[i])) { weight = parseInt(words[i], 10); if (bonus === '*') { defaultweight = weight; } else { bonusweights[bonus] = weight; } } else { error = true; tell.boss("Invalid bonus weight: " + words[i]); break; } } } if (!error) { for (bonus in validgames) { if (typeof(bonusweights[bonus]) === 'undefined') bonusweights[bonus] = defaultweight; } bonus_games.set_weights(type, bonusweights); } } } else { tell.boss("Invalid prize type: " + words[0]); } } } }, /* modeweights: { keywords: ['mode', 'modes', 'modeweight', 'modeweights'], code: function(params, force) { var error = false; params.shift(); if (params.length === 0) { core_showmodeinfo(); } else if (params.length === modes.length) { for (var i = 0; i < params.length; i++) { if (!(/^[0-9]+$/.test(params[i]))) { error = true; whisper("Weights must be whole numbers > 0.", username); } } if (!error) { for (var i = 0; i < params.length; i++) { modes[i].weight = parseInt(params[i], 10); } core_showmodeinfo(); } } else { whisper("All " + modes.length + " modes need weights specified.", username); } } } */ welcome: { keywords: ['welcome'], code: function(params, force) { void(force); if (params.length === 0) { room.show_welcome(); } else { room.set_welcome(params); } } }, user_alarms: { keywords: ['user', 'users'], code: function(params, force) { void (force); var count = (params.length > 0) ? params.toLowerCase().match(/^[\S]+/)[0] : ''; var message = params.slice(count.length).trim(); if (params.length === 0) { room.show_users_alarms(); } else { room.set_users_alarm(count, message); } } }, visitor_alarms: { keywords: ['visit', 'visitor', 'visitors'], code: function(params, force) { void (force); var count = (params.length > 0) ? params.toLowerCase().match(/^[\S]+/)[0] : ''; var message = params.slice(count.length).trim(); if (params.length === 0) { room.show_visitors_alarms(); } else { room.set_visitors_alarm(count, message); } } }, show_presets: { keywords: ['preset', 'presets'], code: function(params, force) { void (params); void (force); tell.boss('Available presets: ' + presets.preset_names().join(', ')); } }, load_preset: { keywords: ['load'], code: function(params, force) { void(force); if (cbjs.arrayContains(presets.preset_names(), params)) { presets.apply(params); } else { tell.boss('Available presets: ' + presets.preset_names().join(', ')); } } } }; // ---------------------------------------------------------------------------- // // PRIZE POOL // // ---------------------------------------------------------------------------- var pool = { _types: {}, _tiers: {}, init_types: function(data) { var key; var bonus; for (key in data) { if (typeof(pool._types[key]) === 'undefined') { pool._types[key] = {}; if (typeof(data[key].description) === 'string') { pool._types[key].description = data[key].description; } else { pool._types[key].description = key; } pool._types[key].bonusgames = {}; for (bonus in bonus_games.list()) { pool._types[key].bonusgames[bonus] = {}; if (typeof(data[key].bonusgames[bonus]) !== 'object') data[key].bonusgames[bonus] = {}; pool._types[key].bonusgames[bonus].weight = (is_digits(data[key].bonusgames[bonus].weight)) ? data[key].bonusgames[bonus].weight : 0; pool._types[key].bonusgames[bonus].strings = {}; if (typeof(data[key].bonusgames[bonus].intro) === 'string') pool._types[key].bonusgames[bonus].strings.intro = data[key].bonusgames[bonus].intro; if (typeof(data[key].bonusgames[bonus].win) === 'string') pool._types[key].bonusgames[bonus].strings.win = data[key].bonusgames[bonus].win; if (typeof(data[key].bonusgames[bonus].lose) === 'string') pool._types[key].bonusgames[bonus].strings.lose = data[key].bonusgames[bonus].lose; } } else { tell.debug('Ignoring duplicate type: ' + key); } } // Ensure default type can't be fucked with pool._types._nothing = {}; pool._types._nothing.description = 'Default prize type (no bonus games)'; pool._types._nothing.bonusgames = {}; for (bonus in bonus_games.list()) { pool._types._nothing.bonusgames[bonus] = {}; pool._types._nothing.bonusgames[bonus].intro = 'Undefined intro: ' + bonus; pool._types._nothing.bonusgames[bonus].weight = 0; } }, init_tiers: function(data) { for (var key in data) { if (typeof(pool._tiers[key]) === 'undefined') { pool._tiers[key] = {}; if (typeof(data[key].description) === 'string') { pool._tiers[key].description = data[key].description; } else { pool._tiers[key].description = key; } if (typeof(data[key].announce) === 'boolean') { pool._tiers[key].announce = data[key].announce; } else { pool._tiers[key].announce = false; } if (is_digits(data[key].reuse_delay)) { pool._tiers[key].reuse_delay = data[key].reuse_delay; } else { pool._tiers[key].reuse_delay = 0; } if (is_digits(data[key].weight)) { pool._tiers[key].weight = data[key].weight; } else { pool._tiers[key].weight = 0; } if (typeof(data[key].prizes) === 'object') { pool._tiers[key].prizes = []; for (var i = 0; i < data[key].prizes.length; i++ ) { if (typeof(data[key].prizes[i].text) === 'string') { var newprize = {}; newprize.text = data[key].prizes[i].text; newprize.type = (typeof(data[key].prizes[i].type) === 'string' && typeof(pool._types[data[key].prizes[i].type]) === 'object') ? data[key].prizes[i].type : FINAL_PRIZE; pool._tiers[key].prizes.push(newprize); } } } else { pool._tiers[key].prizes = []; } pool._tiers[key].waitlist = []; // prizes on hold; array of { prize: obj, delay: int } objects } else { tell.debug('Ignoring duplicate tier: ' + key); } } }, tier_names: function() { var result = {}; for (var key in pool._tiers) { result[key] = true; } return result; }, type_names: function() { var result = {}; for (var key in pool._types) { result[key] = true; } return result; }, set_tier_weights: function(weights) { // object of keyword: weight values for (var key in pool._tiers) { if (is_digits(weights[key])) { if (pool._tiers[key].announce && pool._tiers[key].weight === 0 && weights[key] > 0) { tell.all('Prize tier unlocked: ' + pool._tiers[key].description); pool._tiers[key].announce = false; } pool._tiers[key].weight = weights[key]; } } pool.show_tier_weights(); }, set_bonus_weights: function(typename, weights) { // object of keyword: weight values var need_show = 0; if (typeof(pool._types[typename]) === 'object') { for (var key in pool._types[typename].bonusgames) { if (is_digits(weights[key])) { if (weights[key] > 0 || pool._types[typename].bonusgames[key].weight > 0) need_show = true; pool._types[typename].bonusgames[key].weight = weights[key]; } } if (need_show) pool.show_bonus_weights(typename); } }, get_bonus_texts: function(typename, bonus) { if (typeof(pool._types[typename]) === 'object') { if (typeof(pool._types[typename].bonusgames[bonus]) === 'object') { return pool._types[typename].bonusgames[bonus].strings; } } return {}; }, show_tier_weights: function() { var totalweight; var key; var elements = []; totalweight = 0; for (key in pool._tiers) { totalweight += pool._tiers[key].weight; } for (key in pool._tiers) { elements.push(key + ": " + pool._tiers[key].weight + " (" + Math.floor(100 * pool._tiers[key].weight / totalweight) + "%)"); } tell.boss("Tiers - " + elements.join(', ')); }, show_bonus_weights: function(typename) { var totalweight; var bonus; var types_to_list; var type; var elements = []; if (typeof(typename) === 'string') { types_to_list = {}; types_to_list[typename] = true; } else { types_to_list = pool._types; } for (type in types_to_list) { totalweight = 0; elements = []; for (bonus in bonus_games.list()) { totalweight += pool._types[type].bonusgames[bonus].weight; } if (totalweight > 0 || typeof(typename) === 'string') { for (bonus in bonus_games.list()) { elements.push(bonus + ": " + pool._types[type].bonusgames[bonus].weight + " (" + Math.floor(100 * pool._types[type].bonusgames[bonus].weight / totalweight) + "%)"); } tell.boss("Bonuses for " + type + " - " + elements.join(', ')); } } }, show_tier_info: function() { var totalweight; var key; totalweight = 0; for (key in pool._tiers) { totalweight += pool._tiers[key].weight; } for (key in pool._tiers) { tell.boss(key + " (" + pool._tiers[key].description + "): weight " + pool._tiers[key].weight + " (" + Math.floor(100 * pool._tiers[key].weight / totalweight) + "%), " + pool._tiers[key].prizes.length + " active prizes, " + pool._tiers[key].waitlist.length + " inactive prizes."); } }, available_prizes: function() { var total = 0; for (var key in pool._tiers) { if (pool._tiers[key].weight > 0) { total += pool._tiers[key].prizes.length; } } return total; }, get_prize: function() { var rnd; var key; var totalweight; var chosentier; var chosenprize; var tempprize; // Decide on a prize tier totalweight = 0; for (key in pool._tiers) { if (pool._tiers[key].prizes.length > 0) { totalweight += pool._tiers[key].weight; } } if (totalweight === 0) return { type: FINAL_PRIZE, text: 'The chance to laugh at ' + cb.room_slug + ' for running out of prizes and breaking the game' }; rnd = Math.floor(Math.random() * totalweight); for (key in pool._tiers) { if (pool._tiers[key].prizes.length > 0) { rnd -= pool._tiers[key].weight; if (rnd < 0) { chosentier = key; break; } } } // Decide on a prize rnd = Math.floor(Math.random() * pool._tiers[chosentier].prizes.length); chosenprize = pool._tiers[chosentier].prizes[rnd]; // Remove prize from list pool._tiers[chosentier].prizes.splice(rnd, 1); if (pool._tiers[chosentier].reuse_delay >= 0) { pool._tiers[chosentier].waitlist.push( { prize: chosenprize, delay: pool._tiers[chosentier].reuse_delay } ); } // Create new prize object so bonus games don't change the original tempprize = { type: chosenprize.type, text: chosenprize.text }; return tempprize; }, select_bonus_game: function(type) { var totalweight; var rnd; var key; // Decide on a game mode totalweight = 0; for (key in pool._types[type].bonusgames) { totalweight += pool._types[type].bonusgames[key].weight; } if (totalweight === 0) { return BONUS_LAST_RESORT; } rnd = Math.floor(Math.random() * totalweight); for (key in pool._types[type].bonusgames) { rnd -= pool._types[type].bonusgames[key].weight; if (rnd < 0) { return key; } } }, on_end_round: function() { var key; var j; for (key in pool._tiers) { for (j = pool._tiers[key].waitlist.length; j--; ) { if (pool._tiers[key].waitlist[j].delay === 0) { pool._tiers[key].prizes.push(pool._tiers[key].waitlist[j].prize); pool._tiers[key].waitlist.splice(j, 1); } else { pool._tiers[key].waitlist[j].delay--; } } // If tier is still empty, refill it if (pool._tiers[key].prizes.length === 0) { for (j = pool._tiers[key].waitlist.length; j--; ) { pool._tiers[key].prizes.push(pool._tiers[key].waitlist[j].prize); } pool._tiers[key].waitlist = []; } } } }; // ---------------------------------------------------------------------------- // // PRESET MANAGEMENT // // ---------------------------------------------------------------------------- var presets = { _presets: {}, _autopreset: {}, init_presets: function(data) { for (var key in data) { if (typeof(presets._presets[key]) === 'undefined') { presets._presets[key] = {}; if (typeof(data[key].welcome_text) === 'string') { presets._presets[key].welcome_text = data[key].welcome_text; } // else leave undefined if (typeof(data[key].autopreset) === 'object' && typeof(data[key].autopreset.preset) === 'string' && is_digits(data[key].autopreset.count)) { presets._presets[key].autopreset = { count: data[key].autopreset.count, preset: data[key].autopreset.preset }; } // else leave undefined if (typeof(data[key].tierweights) !== 'object') { data[key].tierweights = {}; } // presets must define weights for all tiers (0 by default) presets._presets[key].tierweights = {}; for (var tier in pool.tier_names()) { if (is_digits(data[key].tierweights[tier])) { presets._presets[key].tierweights[tier] = data[key].tierweights[tier]; } else { presets._presets[key].tierweights[tier] = 0; } } if (typeof(data[key].modeweights) !== 'object') { data[key].modeweights = {}; } // presets must define weights for all game modes (0 by default) presets._presets[key].modeweights = {}; for (var mode in prize_games.list()) { if (is_digits(data[key].modeweights[mode])) { presets._presets[key].modeweights[mode] = data[key].modeweights[mode]; } else { presets._presets[key].modeweights[mode] = 0; } } if (typeof(data[key].bonusweights) !== 'object') { data[key].bonusweights = {}; } // presets must define weights for all bonus games for all prize types (0 by default) presets._presets[key].bonusweights = {}; for (var type in pool.type_names()) { if (typeof(data[key].bonusweights[type]) !== 'object') { data[key].bonusweights[type] = {}; } presets._presets[key].bonusweights[type] = {}; for (var bonus in bonus_games.list()) { if (is_digits(data[key].bonusweights[type][bonus])) { presets._presets[key].bonusweights[type][bonus] = data[key].bonusweights[type][bonus]; } else { presets._presets[key].bonusweights[type][bonus] = 0; } } } } else { tell.debug('Ignoring duplicate preset: ' + key); } } }, preset_names: function() { var result = []; for (var key in presets._presets) { result.push(key); } return result; }, apply: function(preset) { // string: preset name to apply if (typeof(presets._presets[preset]) === 'object') { room.set_welcome(presets._presets[preset].welcome_text); if (typeof(presets._presets[preset].autopreset) === 'object') { presets.set_auto_preset(presets._presets[preset].autopreset.count, presets._presets[preset].autopreset.preset); } else { presets.set_auto_preset(); } pool.set_tier_weights(presets._presets[preset].tierweights); prize_games.set_weights(presets._presets[preset].modeweights); for (var type in presets._presets[preset].bonusweights) { bonus_games.set_weights(type, presets._presets[preset].bonusweights[type]); } } }, set_auto_preset: function(count, preset) { if (is_digits(count) && typeof(presets._presets[preset]) === 'object') { presets._autopreset = { count: count, preset: preset }; presets.on_end_round(); // can potentially apply next preset immediately if count == 0. dumb, but can do it. } else { presets._autopreset = {}; } }, on_end_round: function() { if (is_digits(presets._autopreset.count)) { if (presets._autopreset.count === 0) { tell.boss('Automatically applying preset: ' + presets._autopreset.preset); presets.apply(presets._autopreset.preset); } else { tell.boss(presets._autopreset.count + ' round(s) until preset: ' + presets._autopreset.preset); presets._autopreset.count--; } } } }; // ---------------------------------------------------------------------------- // // PRIZE GAMES // // ---------------------------------------------------------------------------- var prize_games = { _games: {}, list: function() { // returns an object instead of an array because I'm an idiot and this was the easiest place to fix it. var result = {}; for (var key in prize_games._games) { result[key] = true; } return result; }, register: function(game, description, initfunction) { if (typeof(prize_games._games[game]) === 'undefined') { prize_games._games[game] = { description: description, initfunction: initfunction, weight: 0 }; } else { // potentially different behaviour later prize_games._games[game] = { description: description, initfunction: initfunction, weight: 0 }; } }, set_weights: function(weights) { // object of keyword: weight values for (var key in prize_games._games) { if (is_digits(weights[key])) { prize_games._games[key].weight = weights[key]; } } prize_games.show_weights(); }, show_weights: function() { var totalweight; var key; var elements = []; totalweight = 0; for (key in prize_games._games) { totalweight += prize_games._games[key].weight; } for (key in prize_games._games) { elements.push(key + ": " + prize_games._games[key].weight + " (" + Math.floor(100 * prize_games._games[key].weight / totalweight) + "%)"); } tell.boss("Modes - " + elements.join(', ')); }, show_info: function() { var totalweight; var key; totalweight = 0; for (key in prize_games._games) { totalweight += prize_games._games[key].weight; } for (key in prize_games._games) { tell.boss(key + " (" + prize_games._games[key].description + "): weight " + prize_games._games[key].weight + " (" + Math.floor(100 * prize_games._games[key].weight / totalweight) + "%)"); } }, select: function() { var totalweight; var rnd; var key; // Decide on a game mode totalweight = 0; for (key in prize_games._games) { totalweight += prize_games._games[key].weight; } if (totalweight === 0) { return; } rnd = Math.floor(Math.random() * totalweight); for (key in prize_games._games) { rnd -= prize_games._games[key].weight; if (rnd < 0) { return key; } } }, start: function(game) { if (typeof(prize_games._games[game]) === 'object') { tell.debug("Starting game: " + game); prize_games._games[game].initfunction(); cb.drawPanel(); if (engine.current_player() === '') { tell.all('Time to play! Someone just needs to /spin the wheel.'); } else { tell.all('Time to play, %%! Just /spin the wheel.', engine.current_player()); } } } }; // ---------------------------------------------------------------------------- // // BONUS GAMES // // ---------------------------------------------------------------------------- var bonus_games = { _games: {}, list: function() { // returns an object instead of an array because I'm an idiot and this was the easiest place to fix it. var result = {}; for (var key in bonus_games._games) { result[key] = true; } return result; }, register: function(game, description, initfunction) { if (typeof(bonus_games._games[game]) === 'undefined') { bonus_games._games[game] = { description: description, initfunction: initfunction }; } else { // potentially different behaviour later bonus_games._games[game] = { description: description, initfunction: initfunction }; } }, set_weights: function(type, weights) { // object of keyword: weight values pool.set_bonus_weights(type, weights); }, show_weights: function(typename) { pool.show_bonus_weights(typename); }, select: function(type) { return pool.select_bonus_game(type); }, start: function(game, prize) { if (typeof(bonus_games._games[game]) === 'object') { tell.debug("Starting game: " + game); bonus_games._games[game].initfunction(prize); } } }; // ---------------------------------------------------------------------------- // // CORE GAME ENGINE // // ---------------------------------------------------------------------------- var engine = { _end_round_callbacks: [], _mode: '', // empty string means no game in progress, otherwise game's keyword _player: '', register_end_round_callback: function(fn) { engine._end_round_callbacks.push(fn); }, end_round: function() { engine._mode = ''; for (var i = 0; i < engine._end_round_callbacks.length; i++) { engine._end_round_callbacks[i](); } cb.drawPanel(); }, in_game: function() { return (typeof(engine._mode) !== 'undefined' && engine._mode !== ''); }, current_player: function() { return engine._player; }, set_player: function(username) { if (typeof(username) === 'string') { if (engine._player !== '') tell.boss("Replacing player " + engine._player + " with " + username + "!"); engine._player = username; } }, new_round: function(username) { // username is optional, otherwise anyone can play // cleanup if necessary; should never happen if (engine.in_game()) engine.end_round(); engine._mode = prize_games.select(); if (typeof(engine._mode) === 'undefined') { tell.boss("No game nodes active. Use /modeweight to fix.", cb.room_slug); } else { engine._player = (typeof(username) === 'string') ? username : ''; prize_games.start(engine._mode); } }, award_prize: function(prize) { tell.debug("Considering prize '" + prize.text + "' of type '" + prize.type + "'"); cmds.clear_player(); if (prize.type === FINAL_PRIZE) { tell.debug("Awarding prize."); tell.prize('%% wins: ' + prize.text, engine.current_player()); panel.set_prize(prize.text); engine.end_round(); } else { engine._mode = bonus_games.select(prize.type); tell.debug("Bonus game mode: " + engine._mode); bonus_games.start(engine._mode, prize); } } }; // ---------------------------------------------------------------------------- // // PRIZE GAME MODE: BASIC WHEEL SPIN // // ---------------------------------------------------------------------------- var wheel = { _prize: {}, init: function() { wheel._prize = {}; cmds.register_player('spin', wheel.spin); }, spin: function(username) { wheel._prize = pool.get_prize(); tell.all('%% spins the wheel! It lands on: ' + wheel._prize.text + '.', username); engine.award_prize(wheel._prize); } }; // ---------------------------------------------------------------------------- // // PRIZE GAME MODE: THREE-WAY // // ---------------------------------------------------------------------------- var three = { _prizes: [], init: function() { three._prizes = []; cmds.register_player('spin', three.spin); }, spin: function(username) { var numprizes = pool.available_prizes(); if (numprizes > 3) numprizes = 3; three._prizes.push(pool.get_prize()); // always need at least one, even if it's the error if (numprizes >= 2) three._prizes.push(pool.get_prize()); if (numprizes >= 3) three._prizes.push(pool.get_prize()); switch (numprizes) { case 3: cmds.clear_player(); cmds.register_player('1', function(username) { three.choose(username, 1); } ); cmds.register_player('2', function(username) { three.choose(username, 2); } ); cmds.register_player('3', function(username) { three.choose(username, 3); } ); tell.all('Time for a three-way! %% gets to choose from: (1) ' + three._prizes[0].text + ', (2) ' + three._prizes[1].text + ', (3) ' + three._prizes[2].text + '. Choose /1, /2 or /3.', username); break; case 2: cmds.clear_player(); cmds.register_player('1', function(username) { three.choose(username, 1); } ); cmds.register_player('2', function(username) { three.choose(username, 2); } ); tell.all('Decision time! %% gets to choose from: (1) ' + three._prizes[0].text + ', (2) ' + three._prizes[0].text + '. Choose /1 or /2.', username); break; default: tell.all('%% spins the wheel! It lands on: ' + three._prizes[0].text + '.', username); engine.award_prize(three._prizes[0]); break; } }, choose: function(username, choice) { if (three._prizes.length >= choice) { tell.all('%% makes a decision: ' + three._prizes[choice - 1].text + '.', username); engine.award_prize(three._prizes[choice - 1]); } } }; // ---------------------------------------------------------------------------- // // PRIZE GAME MODE: FREE RESPIN // // ---------------------------------------------------------------------------- var respin = { _prize: {}, init: function() { respin._prize = {}; cmds.register_player('spin', respin.spin); }, spin: function(username) { respin._prize = pool.get_prize(); if (pool.available_prizes() >= 1) { // already picked one, so only need one more to allow a respin cmds.clear_player(); cmds.register_player('spin', respin.respin); cmds.register_player('keep', respin.keep); tell.all('Second chance round! %% spins up: ' + respin._prize.text + '. /keep it or /spin again?', username); } else { tell.all('%% spins the wheel! It lands on: ' + respin._prize.text + '.', username); engine.award_prize(respin._prize); } }, respin: function(username) { respin._prize = pool.get_prize(); tell.all('%% takes a chance and trades in for: ' + respin._prize.text + '.', username); engine.award_prize(respin._prize); }, keep: function(username) { tell.all('%% plays it safe and locks in: ' + respin._prize.text + '.', username); engine.award_prize(respin._prize); } }; // ---------------------------------------------------------------------------- // // PRIZE GAME MODE: FREE CHOICE // // ---------------------------------------------------------------------------- var freechoice = { _prizes: [], init: function() { freechoice._prizes = []; cmds.register_player('spin', freechoice.spin); }, spin: function(username) { var i; var numprizes; numprizes = pool.available_prizes(); for (i = 0; i < numprizes; i++) { freechoice._prizes.push(pool.get_prize()); } if (numprizes > 1) { cmds.clear_player(); tell.all("FREE CHOICE! %% gets to choose from all available prizes!", username); for (i = 0; i < numprizes; i++) { cmds.register_player((i + 1).toString(), new Function("username", "freechoice.choose(username, " + (i + 1) + ");")); tell.all("(" + (i + 1) + ') ' + freechoice._prizes[i].text); } tell.all('%%, choose from the list above! /1, /2 etc. Sometimes CB gets things out of order, so look at the numbers.', username); } else { tell.all('%% spins the wheel! It lands on: ' + freechoice._prizes[0].text + '.', username); engine.award_prize(freechoice._prizes[0]); } }, choose: function(username, choice) { tell.debug("Free choice: " + choice); if (freechoice._prizes.length >= choice) { tell.all('%% makes a decision: ' + freechoice._prizes[choice - 1].text + '.', username); engine.award_prize(freechoice._prizes[choice - 1]); } } }; // ---------------------------------------------------------------------------- // // BONUS GAME MODE: NO BONUS // // ---------------------------------------------------------------------------- var nobonus = { init: function(prize) { engine.award_prize( { type: FINAL_PRIZE, text: prize.text } ); } }; // ---------------------------------------------------------------------------- // // BONUS GAME MODE: COIN TOSS // // ---------------------------------------------------------------------------- var cointoss = { _prize: {}, _texts: {}, init: function(prize) { cointoss._prize = prize; cointoss._texts = pool.get_bonus_texts(prize.type, 'cointoss'); if (typeof(cointoss._texts.intro) === 'undefined') cointoss._texts.intro = "Coin toss bonus round! Ask && what the bonus/penalty are."; if (typeof(cointoss._texts.win ) === 'undefined') cointoss._texts.win = "^^ (with bonus)"; if (typeof(cointoss._texts.lose ) === 'undefined') cointoss._texts.lose = "^^ (with penalty)"; cmds.register_player('h', function(username) { cointoss.toss(username, 'heads'); } ); cmds.register_player('head', function(username) { cointoss.toss(username, 'heads'); } ); cmds.register_player('heads', function(username) { cointoss.toss(username, 'heads'); } ); cmds.register_player('t', function(username) { cointoss.toss(username, 'tails'); } ); cmds.register_player('tail', function(username) { cointoss.toss(username, 'tails'); } ); cmds.register_player('tails', function(username) { cointoss.toss(username, 'tails'); } ); cmds.register_player('keep', cointoss.keep); tell.all(cointoss._texts.intro + " /keep the prize or call /heads or /tails?"); }, init_mustplay: function(prize) { cointoss._prize = prize; cointoss._texts = pool.get_bonus_texts(prize.type, 'cointoss_mustplay'); if (typeof(cointoss._texts.intro) === 'undefined') cointoss._texts.intro = "Coin toss bonus round! Ask && what the bonus/penalty are."; if (typeof(cointoss._texts.win ) === 'undefined') cointoss._texts.win = "^^ (with bonus)"; if (typeof(cointoss._texts.lose ) === 'undefined') cointoss._texts.lose = "^^ (with penalty)"; cmds.register_player('h', function(username) { cointoss.toss(username, 'heads'); } ); cmds.register_player('head', function(username) { cointoss.toss(username, 'heads'); } ); cmds.register_player('heads', function(username) { cointoss.toss(username, 'heads'); } ); cmds.register_player('t', function(username) { cointoss.toss(username, 'tails'); } ); cmds.register_player('tail', function(username) { cointoss.toss(username, 'tails'); } ); cmds.register_player('tails', function(username) { cointoss.toss(username, 'tails'); } ); tell.all(cointoss._texts.intro + " /heads or /tails?"); }, keep: function(username) { tell.all('%% plays it safe and locks in: ' + cointoss._prize.text + '.', username); cointoss._prize.type = FINAL_PRIZE; engine.award_prize(cointoss._prize); }, toss: function(username, choice) { var rnd; var result; rnd = Math.floor(Math.random() * 2); result = (rnd === 0) ? 'heads' : 'tails'; if (choice === result) { tell.all("%% calls " + choice + ". It's " + result + "! Congratulations!", username); cointoss._prize.text = interp.prize(cointoss._texts.win, cointoss._prize.text); } else { tell.all("%% calls " + choice + ". It's " + result + ". Sorry.", username); cointoss._prize.text = interp.prize(cointoss._texts.lose, cointoss._prize.text); } cointoss._prize.type = FINAL_PRIZE; engine.award_prize(cointoss._prize); } }; // ---------------------------------------------------------------------------- // // BONUS GAME MODE: HIGH/LOW CARD // // ---------------------------------------------------------------------------- var highlow = { _prize: {}, _texts: {}, _card_admin: NaN, _card_player: NaN, _cards: ['an Ace', 'a 2', 'a 3', 'a 4', 'a 5', 'a 6', 'a 7', 'an 8', 'a 9', 'a 10', 'a Jack', 'a Queen', 'a King'], init: function(prize) { highlow._prize = prize; highlow._texts = pool.get_bonus_texts(prize.type, 'highlow'); if (typeof(highlow._texts.intro) === 'undefined') highlow._texts.intro = "High/low card bonus round! Ask && what the bonus/penalty are."; if (typeof(highlow._texts.win ) === 'undefined') highlow._texts.win = "^^ (with bonus)"; if (typeof(highlow._texts.lose ) === 'undefined') highlow._texts.lose = "^^ (with penalty)"; highlow._card_admin = NaN; highlow._card_player = NaN; cmds.register_player('keep', highlow.keep ); cmds.register_player('draw', highlow.draw ); tell.all(highlow._texts.intro + " /keep the prize /draw a card?"); }, init_mustplay: function(prize) { highlow._prize = prize; highlow._texts = pool.get_bonus_texts(prize.type, 'highlow_mustplay'); if (typeof(highlow._texts.intro) === 'undefined') highlow._texts.intro = "High/low card bonus round! Ask && what the bonus/penalty are."; if (typeof(highlow._texts.win ) === 'undefined') highlow._texts.win = "^^ (with bonus)"; if (typeof(highlow._texts.lose ) === 'undefined') highlow._texts.lose = "^^ (with penalty)"; highlow._card_admin = NaN; highlow._card_player = NaN; tell.all(highlow._texts.intro); highlow.draw(engine.current_player()); }, keep: function(username) { tell.all('%% plays it safe and locks in: ' + highlow._prize.text + '.', username); highlow._prize.type = FINAL_PRIZE; engine.award_prize(highlow._prize); }, draw: function(username) { cmds.clear_player(); cmds.register_player('h', function(username) { highlow.resolve(username, 'higher'); } ); cmds.register_player('high', function(username) { highlow.resolve(username, 'higher'); } ); cmds.register_player('higher', function(username) { highlow.resolve(username, 'higher'); } ); cmds.register_player('l', function(username) { highlow.resolve(username, 'lower'); } ); cmds.register_player('low', function(username) { highlow.resolve(username, 'lower'); } ); cmds.register_player('lower', function(username) { highlow.resolve(username, 'lower'); } ); highlow._card_admin = Math.floor(Math.random() * 13); tell.all("%% wants to play! && shuffles the deck and draws " + highlow._cards[highlow._card_admin] + ". What will the next card be, /higher or /lower?", username); }, resolve: function(username, choice) { var rnd; var output; while (isNaN(highlow._card_player)) { highlow._card_player = Math.floor(Math.random() * 13); if (highlow._card_player === highlow._card_admin) { // make it fair, can't draw the same card twice rnd = Math.floor(Math.random() * 4); if (rnd === 0) highlow._card_player = NaN; } } // first part of result text output = "%% guesses " + choice + " than " + highlow._cards[highlow._card_admin] + ", and draws " + highlow._cards[highlow._card_player] + "."; if (highlow._card_admin === highlow._card_player) { // draws go to the broadcaster output += " It's a draw. Sorry."; highlow._prize.text = interp.prize(highlow._texts.lose, highlow._prize.text); } else { // rig the value of an ace in the player's favour if (highlow._card_admin === 0 && choice === 'lower') highlow._card_admin = 13; if (highlow._card_player === 0 && choice === 'higher') highlow._card_player = 13; // reverse signs of values if testing for lower if (choice === 'lower') { highlow._card_admin = -highlow._card_admin; highlow._card_player = -highlow._card_player; } // test result if (highlow._card_player > highlow._card_admin) { output += " it's " + choice + ", congratulations!"; highlow._prize.text = interp.prize(highlow._texts.win, highlow._prize.text); } else { output += " Sorry, it's " + (choice === 'higher' ? 'lower' : 'higher') + "."; highlow._prize.text = interp.prize(highlow._texts.lose, highlow._prize.text); } } tell.all(output, username); highlow._prize.type = FINAL_PRIZE; engine.award_prize(highlow._prize); } }; // ---------------------------------------------------------------------------- // // CB TRIGGERS // // ---------------------------------------------------------------------------- cb.onEnter(function (user) { room.on_enter(user.user); } ); cb.onLeave(function (user) { room.on_leave(user.user); } ); cb.onDrawPanel(function() { return panel.data(); }); cb.onMessage(function(msg) { room.notice(msg.user); if (msg.m[0] === '/') { msg['X-Spam'] = true; cmds.interpret(msg); } return msg; }); // ---------------------------------------------------------------------------- // // INITIALISATION // // ---------------------------------------------------------------------------- if (typeof(cb.settings.gamedata) !== 'undefined') { prize_games.register( 'wheel', 'Standard Wheel Spin', wheel.init ); prize_games.register( 'three', 'Pick From 3', three.init ); prize_games.register( 'respin', 'Second Chance Spin', respin.init ); prize_games.register( 'freechoice', 'Free Choice', freechoice.init ); bonus_games.register( 'nobonus', 'No Bonus Game', nobonus.init ); bonus_games.register( 'cointoss', 'Coin Toss', cointoss.init ); bonus_games.register( 'cointoss_mustplay', 'Coin Toss (Must Play)', cointoss.init_mustplay ); bonus_games.register( 'highlow', 'High/Low Card', highlow.init ); bonus_games.register( 'highlow_mustplay', 'High/Low Card (Must Play)', highlow.init_mustplay ); var _gamedata = eval('(' + ( cb.settings.gamedata || '{}' ) + ')'); if (typeof(_gamedata.types ) === 'object') pool.init_types (_gamedata.types) ; else pool.init_types ({}); if (typeof(_gamedata.tiers ) === 'object') pool.init_tiers (_gamedata.tiers) ; else pool.init_tiers ({}); if (typeof(_gamedata.presets) === 'object') presets.init_presets(_gamedata.presets); else presets.init_presets({}); if (typeof(_gamedata.alarms ) === 'object') room.init_alarms (_gamedata.alarms) ; else room.init_alarms ([]); engine.register_end_round_callback(pool.on_end_round); engine.register_end_round_callback(presets.on_end_round); engine.register_end_round_callback(cmds.on_end_round); admin.init(); }
© Copyright Chaturbate 2011- 2026. All Rights Reserved.