Apps Home
|
Create an App
BlackJackoff v2
Author:
cub4youuu
Description
Source Code
Launch App
Current Users
Created by:
Cub4youuu
/* * Title: BlackJackoff * Author: Calvin06 * Author: Cub4youuu * Version: 1.0 (02/26/13) * TODO: split and doubledown concepts */ // vars var totalTipped = 0; var topTipAmount = 0; var topTipper = null; var currentPlayer = null; var currentPlayerTip = 0; var deck = null; var CONFIG_TIPPER_COLOR = '#EBFAFA'; var CONFIG_TOP_TIPPER_COLOR = '#FFF700'; var CONFIG_ADVERT_TIME = 7; var nl = '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501'; var COMMAND_PRIZES = '!p'; var COMMAND_HIT = '!h'; var COMMAND_STAY = '!s'; var COMMAND_RULES = '!r'; //var COMMAND_SPLIT = '!split'; var COMMAND_STATS = '!stats'; var COMMAND_RESET = '!reset'; var COMMAND_PRACTICE = '!practice' var COMMAND_CMDS = '!cmds'; var CONFIG_PLAYERWINS = 'wins'; var CONFIG_PLAYERLOSES = 'loses'; function getCommandList() { return nl + '\n' + COMMAND_HIT + " player hits\n" + COMMAND_STAY + " player stands\n" + COMMAND_PRIZES + " see prize list\n" + COMMAND_STATS + " player stats\n" + COMMAND_RULES + " game rules\n" + COMMAND_RESET + " reset the game (broadcaster only)\n" + COMMAND_PRACTICE + " play a practice round (broadcaster only)\n" nl; } cb.settings_choices = [ {name: 'buyin', type: 'int', minValue: 1, defaultValue: 25, label: "Minimum token bet"}, {name: 'insurance', type: 'int', minValue: 0, defaultValue: 50, label: "Insurance bet (tipper \"pushes\" on loss)", required: false}, {name: 'goal', type: 'int', minValue: 0, defaultValue: 0, label: "Tip goal (optional)", required:false}, {name: 'goal_description', type: 'str', minLength: 0, maxLength: 255, label: 'Goal Description (optional)', required:false}, {name: 'wprize1', type: 'str', minLength: 1, maxLength: 255, label: 'Player Wins Prize 1'}, {name: 'wprize2', type: 'str', minLength: 0, maxLength: 255, label: 'Player Wins Prize 2', required:false}, {name: 'wprize3', type: 'str', minLength: 0, maxLength: 255, label: 'Player Wins Prize 3', required:false}, {name: 'wprize4', type: 'str', minLength: 0, maxLength: 255, label: 'Player Wins Prize 4', required:false}, {name: 'wprize5', type: 'str', minLength: 0, maxLength: 255, label: 'Player Wins Prize 5', required:false}, {name: 'lprize1', type: 'str', minLength: 1, maxLength: 255, label: 'You Win Prize 1'}, {name: 'lprize2', type: 'str', minLength: 0, maxLength: 255, label: 'You Win Prize 2', required:false}, {name: 'lprize3', type: 'str', minLength: 0, maxLength: 255, label: 'You Win Prize 3', required:false}, {name: 'lprize4', type: 'str', minLength: 0, maxLength: 255, label: 'You Win Prize 4', required:false}, {name: 'lprize5', type: 'str', minLength: 0, maxLength: 255, label: 'You Win Prize 5', required:false} ]; var dealerHand = new Array(); var playerHand = new Array(); var playerStats = {}; //username (str), {totaltips:(int),wins:(int),losses:(int),blackjacks:(int),pushes:(int)} var gameOver = true; var player_prizes = new Array(); var player_penalities = new Array(); //handlers cb.onTip(function(tip) { // 1. track all tips received totalTipped += tip['amount']; if (cb.settings.goal && cb.settings.goal !=0 && totalTipped > cb.settings.goal) totalTipped = cb.settings.goal; if (tip['amount'] > topTipAmount) { topTipAmount = tip['amount']; topTipper = tip['from_user']; } // 2. see if user met assignment minimum if (tip['amount'] >= cb.settings.buyin) { if (gameOver) { gameOver = false; currentPlayer = tip['from_user']; currentPlayerTip = tip['amount']; deal(); } else { cb.chatNotice('Thank you for the tip ' + tip['from_user'] + '. Game is already in progress. Please tip again to play when current game is over.'); } } updateSubject(); // 3. update panel for game in progress cb.drawPanel(); }); cb.onDrawPanel(function(user) { var row1label = 'Tips received:'; var row1value = '' + totalTipped; if (cb.settings.goal && cb.settings.goal !=0) { row1label = 'Tips received / goal:'; row1value = '' + totalTipped + ' / ' + cb.settings.goal; } var row2label = 'Top Tipper:'; var row2value = '--'; if (topTipper) { row2value = '' + formatName(topTipper,12) + ' (' + topTipAmount +')'; } var row3value = 'Deal in for ' + cb.settings.buyin + ' tokens!'; if (!gameOver) { row3value = 'Dealer: ' + dealerHand[0].draw() + ' -- Player: ' + drawHand(playerHand); } return { 'template': '3_rows_12_22_31', 'row1_label': row1label, 'row1_value': row1value, 'row2_label': row2label, 'row2_value': row2value, 'row3_value': row3value }; }); cb.onMessage(function (msg) { if (msg['m'] == COMMAND_RESET) { if (msg['user'] == cb.room_slug) { reset(); cb.chatNotice('Game reset by ' + cb.room_slug); } } if (msg['m'].indexOf(COMMAND_PRACTICE) != -1) { if (msg['user'] == cb.room_slug) { cb.chatNotice('Practice Round: ' + msg['m']); var practiceUserName = msg['m'].split(' ')[1]; if (gameOver) { gameOver = false; currentPlayer = practiceUserName; currentPlayerTip = 1; deal(); updateSubject(); // 3. update panel for game in progress cb.drawPanel(); } else { cb.chatNotice('Thank you for the tip ' + tip['from_user'] + '. Game is already in progress. Please tip again to play when current game is over.'); } } } if (msg['m'].indexOf(COMMAND_STATS) > -1) { drawPlayerStats(msg['user']); } if (msg['m'].indexOf(COMMAND_PRIZES) > -1) { drawPrizes(); } if (msg['m'].indexOf(COMMAND_CMDS) > -1) { cb.chatNotice(getCommandList()); } if (msg['m'].indexOf(COMMAND_HIT) > -1 && !gameOver) { if (msg['user'] == currentPlayer) { cb.chatNotice('Player hits!'); hit(); } } if (msg['m'].indexOf(COMMAND_STAY) > -1 && !gameOver) { if (msg['user'] == currentPlayer) { cb.chatNotice('Player Stands!'); stand(); } } if (msg['m'].indexOf(COMMAND_RULES) > -1) { cb.chatNotice(getRules()); } if (msg['user'] == currentPlayer && !gameOver) { msg['background'] = CONFIG_TIPPER_COLOR; msg['m'] = "[player]: " + msg['m']; } if (msg['user'] == topTipper) { //msg['background'] = CONFIG_TOP_TIPPER_COLOR; } return msg; }); function updateSubject() { cb.changeRoomSubject(getSubject()); } function getSubject() { var subject = 'We\'re playing a round of BlackJackoff! '; if (gameOver) { subject += 'Tip ' + cb.settings.buyin + ' to play!'; if (cb.settings.insurance && cb.settings.insurance != 0) subject += ' Tip ' + cb.settings.insurance + ' if you don\'t like to lose! (insurance). Type ' + COMMAND_CMDS + ' for more commands'; } else{ subject += 'Current player is ' + currentPlayer + '. Please wait for game to finish to place your bet.'; } if (cb.settings.goal_description && cb.settings.goal_description != '') { subject += ' Goal is [' + cb.settings.goal_description +']'; } if (cb.settings.goal && cb.settings.goal != 0 && cb.settings.goal != '') { subject += ' [' + tipsRemaining() + '] tokens left to reach goal!'; } return subject; } function getRules() { var rules = 'GAME RULES\n' + nl + '\nTip ' + cb.settings.buyin + ' to play.\n' + '- Objective is to achieve a total that is greater than that of the dealer, and which does not exceed 21.\n' + '- After you have been dealt two cards, choose to stand by typing ' + COMMAND_STAY + ' or receive another card with a hit by typing ' + COMMAND_HIT + '\n' + '- Hit as many times as you like but you may bust and lose if your card total exceeds 21\n'; '- Dealers must hit if their hand totals 16 or less. Dealers must stand if their hand totals 17 or more.\n'; if (cb.settings.insurance && cb.settings.insurance != 0) rules += '- If player has tipped insurance (' + cb.settings.insurance + ' tokens), player will push on losses.\n'; rules += nl; return rules; } function deal() { if ( deck.next_card > 39 ) { // shuffle the deck if 75% of cb.chatNotice('Shuffling deck...'); deck.shuffle(); // the cards have been used. } dealerHand = new Array(); playerHand = new Array(); dealerHand[ 0 ] = deck.dealCard(); // This is the hole card. dealerHand[ 1 ] = deck.dealCard(); // dealer down card playerHand[ 0 ] = deck.dealCard(); playerHand[ 1 ] = deck.dealCard(); drawHands('hide'); } function reset() { gameOver = true; currentPlayer = null; currentPlayerTip = 0; cb.drawPanel(); } function drawPlayerStats(user) { if (user in playerStats) { cb.chatNotice(nl + '\nPlayer stats ['+user+']:\nWins/Losses: ' + playerStats[user].wins + ' / ' + playerStats[user].losses + '\nPushes: ' + playerStats[user].pushes + '\nBlackjacks: ' + playerStats[user].blackjacks + '\nTotal Tips: ' + playerStats[user].totaltips + '\n' + nl); } } function drawPrizes() { var out = nl + '\nDealer prize list:\n'; for (var i=0;i<player_penalities.length;i++) { out += (i+1) + '. ' + player_penalities[i] + '\n'; } out += 'Player prize list:\n'; for (var i=0;i<player_prizes.length;i++) { out += (i+1) + '. ' + player_prizes[i] + '\n'; } out += nl; cb.chatNotice(out); } function drawHands(display) { var out = ''; out += nl + '\nPlayer ['+currentPlayer+']: ' + drawHandEmote(playerHand) + ' = ' + score(playerHand) + '\n' + nl; out += '\nDealer: '; for (var i=0; i<6; i++) { if (dealerHand[i]) { if (i==3) out += '\n'; if (i==1 && display=='hide') out += ' :cardback' + ' '; else out += ' ' + dealerHand[i].emote() + ' '; } } if (display != 'hide') out += ' = ' + score(dealerHand) + '\n' + nl; else out += '\n' + nl; if (!gameOver) out += '\n['+currentPlayer+'] type ' + COMMAND_STAY + ' to stay or ' + COMMAND_HIT + ' to hit.'; cb.chatNotice(out); } function drawHand(hand) { var out = ''; for (var i=0;i<6;i++) { if (hand[i]) { out += hand[i].draw() + ' '; } } return out; } function drawHandEmote(hand) { var out = ''; for (var i=0;i<6;i++) { if (hand[i]) { if (i==3) out += ' \n '; out += ' ' + hand[i].emote() + ' '; } } return out; } // Constructor for Card objects function Card(num,suit) { this.num = num; this.suit = suit; this.draw = drawCard; this.emote = emoteCard; } function drawCard() { var out = ''; if (this.num == 1 || this.num > 10) { if (this.num == 1 || this.num == 14) out += 'A'; if (this.num == 11) out += 'J'; if (this.num == 12) out += 'Q'; if (this.num == 13) out += 'K'; } else { out += this.num; } switch (this.suit) { case 'c': out += '\u2663'; break; case 'h': out += '\u2665'; break; case 's': out += '\u2660'; break; case 'd': out += '\u2666'; break; } return out; } function emoteCard() { return ':card'+this.num+this.suit; } // Constructor for Deck Object function Deck() { this.cards = new Array(52); this.next_card = 0; // fill the deck (in order, for now) for (var i=1; i<14; i++) { this.cards[i-1] = new Card(i,"c"); this.cards[i+12] = new Card(i,"h"); this.cards[i+25] = new Card(i,"s"); this.cards[i+38] = new Card(i,"d"); } this.shuffle = shuffle; this.dealCard = dealCard; } function shuffle() { for (var i=1; i<1000; i++) { // switch two randomly selected cards card1 = Math.floor( 52*Math.random() ); card2 = Math.floor( 52*Math.random() ); temp = this.cards[card2]; this.cards[card2] = this.cards[card1]; this.cards[card1] = temp; } this.next_card = 0; } function dealCard() { return this.cards[ this.next_card++ ]; } function hit() { var total = 0; var new_card = 0; // index for the new card position if ( !gameOver ) { new_card = playerHand.length; playerHand[ new_card ] = deck.dealCard(); total = score( playerHand ); if ( total > 21 ) { // Busted, game over. gameOver = true; drawHands('show'); winner(); } else { drawHands('hide'); } } cb.drawPanel(); } // end function hit() function stand() { var total = 0; var new_card = 0; // index for the new card position if ( gameOver ) { cb.chatNotice('Game Over'); } else { while ( score( dealerHand ) < 17 ) { // Dealer stands on soft 17 new_card = dealerHand.length; dealerHand[ new_card ] = deck.dealCard(); } total = score( dealerHand ); if ( total > 21 ) { // Busted cb.chatNotice('Dealer busts with ' + total); } else { cb.chatNotice('Dealer draws to ' + total); } } gameOver = true; // The game ends after the player stands. drawHands('show'); winner(); cb.drawPanel(); } // end function stand() function score(hand) { var total = 0; var soft = 0; // This variable counts the number of aces in the hand. var pips = 0; // The trump pictures on a card used to be called pips. for (var i=0; i<hand.length; i++ ) { pips = hand[i].num; if ( pips == 1 ) { soft = soft + 1; total = total + 11; } else { if ( pips == 11 || pips == 12 || pips == 13 ) { total = total + 10; } else { total = total + pips; } } } while ( soft > 0 && total > 21 ) { // Count the aces as 1 instead total = total - 10; // of 11 if the total is over 21 soft = soft - 1; } return total; } // end function score function winner() { var cantLose = false; if (cb.settings.insurance && cb.settings.insurance <= currentPlayerTip) cantLose = true; var bj = 0; var out = ''; var delayedOut = ''; var player_total = score( playerHand ); var dealer_total = score( dealerHand ); if (player_total == 21 && playerHand.length == 2) bj = 1; if ( player_total > 21 ) { // Busted out += 'Player busts! Dealer wins!'; if (cantLose) { out += '\nBUT! Player tipped with insurance. No action.'; updateUser(currentPlayer,currentPlayerTip,0,0,bj,1); } else { //out += '\nDealer reward [' + getAction(CONFIG_PLAYERLOSES) + ']'; delayedOut = 'Dealer reward [' + getAction(CONFIG_PLAYERLOSES) + ']'; updateUser(currentPlayer,currentPlayerTip,0,1,bj,0); } } else { if (bj == 1) out += ' B L A C K J A C K \n'; if ( dealer_total > 21 ) { // Busted out += cb.room_slug + ' busts! ' + currentPlayer + ' wins!\n'; //out += 'Player reward [' + getAction(CONFIG_PLAYERWINS) + ']'; delayedOut = 'Player reward [' + getAction(CONFIG_PLAYERWINS) + ']'; updateUser(currentPlayer,currentPlayerTip,1,0,bj,0); } else { if ( player_total == dealer_total ) { out += 'Push!'; updateUser(currentPlayer,currentPlayerTip,0,0,bj,1); } else { if ( player_total > dealer_total ) { out += 'Player wins!\n'; //out += 'Player reward [' + getAction(CONFIG_PLAYERWINS) + ']'; delayedOut = 'Player reward [' + getAction(CONFIG_PLAYERWINS) + ']'; updateUser(currentPlayer,currentPlayerTip,1,0,bj,0); } else { out += 'Dealer wins!\n'; if (cantLose) { out += 'BUT! Player tipped with insurance. No action.'; updateUser(currentPlayer,currentPlayerTip,0,0,bj,1); } else { //out += 'Dealer reward [' + getAction(CONFIG_PLAYERLOSES) + ']'; delayedOut = 'Dealer reward [' + getAction(CONFIG_PLAYERLOSES) + ']'; updateUser(currentPlayer,currentPlayerTip,0,1,bj,0); } } } } } if (out.substring(out.length-1) != '\n') out += '\n'; cb.chatNotice(out + nl); if (delayedOut != '') cb.setTimeout(cb.chatNotice(delayedOut,'','','','bold'),1000); updateSubject(); } function getAction(result) { var out = ''; if (result == CONFIG_PLAYERLOSES) { out += player_penalities[Math.floor(Math.random() * player_penalities.length)]; } else { out += player_prizes[Math.floor(Math.random() * player_prizes.length)]; } return out; } function updateUser(user,tip,win,loss,bj,push) { // username (str), {totaltips:(int),wins:(int),losses:(int),blackjacks:(int),pushes:(int)} if (user in playerStats) { playerStats[user].totaltips += tip; playerStats[user].wins += win; playerStats[user].losses += loss; playerStats[user].blackjacks += bj; playerStats[user].pushes += push; } else { playerStats[user] = {totaltips:tip,wins:win,losses:loss,blackjacks:bj,pushes:push}; } } function tipsRemaining() { if (!cb.settings.goal) return 0; var r = cb.settings.goal - totalTipped; if (r < 0) { return 0; } else { return r; } } function formatName(val,length) { if (val === null) { return "--"; } else { return val.substring(0, length); } } function advert() { cb.chatNotice(getSubject()); cb.setTimeout(advert, (6 * 60000)); } function init() { var wtemp = new Array(cb.settings.wprize1,cb.settings.wprize2,cb.settings.wprize3,cb.settings.wprize4,cb.settings.wprize5); var ltemp = new Array(cb.settings.lprize1,cb.settings.lprize2,cb.settings.lprize3,cb.settings.lprize4,cb.settings.lprize5); for (var i = 0; i<wtemp.length; i++) { if (wtemp[i] != '') { player_prizes.push(wtemp[i]); } } for (var i = 0; i <ltemp.length; i++) { if (ltemp[i] != '') { player_penalities.push(ltemp[i]); } } updateSubject(); deck = new Deck(); deck.shuffle(); cb.chatNotice(getSubject()); cb.setTimeout(advert, (6 * 60000)); } init();
© Copyright Chaturbate 2011- 2026. All Rights Reserved.