User:Writ Keeper/Scripts/blackjackExp.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:Writ Keeper/Scripts/blackjackExp. |
//only do anything if on the blackjack homepage
if (mw.config.get("wgPageName") == "User:Writ_Keeper/blackjack")
{
//Global state variables
var currentBalance = 500;
var currentBetSetting = 10;
var splitBetValue = 10;
var playerHand = {count:0,softAce:false,container:"#playerGroup",value:currentBetSetting};
var dealerHand = {count:0,softAce:false,container:"#cardTableDealer"};
var splitHand = {count:0,softAce:false,container:"#splitGroup",value:0};
var previousBalanceExists = true;
var faceDownCard = null;
var isSplit = false;
var splitWinnings = 0;
var numDecks = 6;
var shoe = null;
var nextCard = -1;
function shuffleDeck()
{
var rng = window.crypto || window.msCrypto;
var shoeSize = 52*numDecks;
var rngArray = new Uint16Array(shoeSize);
var rejectArray = new Uint16Array(1);
var maxInt = 65536;
shoe = new Array(shoeSize);
for(i = 0; i < shoe.length; i++)
{
shoe[i] = i;
}
rng.getRandomValues(rngArray);
for(i=(shoe.length - 1); i >= 0; i--)
{
//discard values greater than the maximum multiple of shoeSize below maxInt; these values would skew the distribution
while(rngArray[i] >= Math.floor(maxInt/shoeSize) * shoeSize)
{
console.log("value rejected in " + i + "th shuffle");
rng.getRandomValues(rejectArray);
rngArray[i] = rejectArray[0];
}
var tempStorage = shoe[i];
shoe[i] = shoe[(rngArray[i]%shoeSize)];
shoe[(rngArray[i]%shoeSize)] = tempStorage;
shoeSize--;
}
nextCard = 0;
return shoe;
}
function changeButton(gameButton, clickFunction, label)
{
gameButton.off("click");
gameButton.click(clickFunction);
gameButton.find(".mw-ui-button").html(label);
gameButton.show();
}
function changeActionButton(gameButton, clickFunction, gameHand, label)
{
gameButton.off("click");
gameButton.click({hand:gameHand},clickFunction);
gameButton.find(".mw-ui-button").html(label);
gameButton.show();
}
function changeBet()
{
var rawResponse = prompt("Enter the new bet (whole numbers, from 1 - " + currentBalance + "):");
if(rawResponse == null)
{
return;
}
var userResponse = parseInt(rawResponse);
if (isNaN(userResponse))
{
alert("That's not a number.");
return;
}
if (userResponse > currentBalance)
{
alert("You can't bet money you don't have.");
return;
}
if (userResponse < 1)
{
alert("This ain't a charity.");
return;
}
currentBetSetting = userResponse;
playerHand.value = currentBetSetting;
$("#betAmount").html(currentBetSetting);
}
function peaceOut()
{
var userResponse = confirm("This makes an edit (which will show up in your contribs) to record your closing balance.\n\nIs that okay?");
if (userResponse)
{
mw.loader.using("mediawiki.api.edit").done(function ()
{
var api = new mw.Api();
if (previousBalanceExists)
{
api.edit("User:" + mw.config.get("wgUserName") + "/blackjackBalance.js", function ()
{
return {minor:true,text:currentBalance,summary:"updating [[User:Writ_Keeper/blackjack|blackjack]] balance"};
}
).done(function ()
{
location.reload(true);
}
);
}
else
{
api.create("User:" + mw.config.get("wgUserName") + "/blackjackBalance.js",
{summary: "updating [[User:Writ_Keeper/blackjack|blackjack]] balance"},
"" + currentBalance).done(function ()
{
location.reload(true);
}
).fail(function ()
{
api.edit("User:" + mw.config.get("wgUserName") + "/blackjackBalance.js", function ()
{
return {minor:true,text:currentBalance,summary:"updating [[User:Writ_Keeper/blackjack|blackjack]] balance"};
}
).done(function ()
{
location.reload(true);
}
);
}
);
}
}
);
}
}
function randomCard()
{
var cardIndex = shoe[nextCard];
nextCard++;
return {"suit": ((Math.floor(cardIndex/13)%4)+1),"rank":(cardIndex%13 + 1)};
}
function getCardBackground(card)
{
var cardBackground = {"x":0,"y":0};
switch (card.rank)
{
case 1:
cardBackground.x = -1;
break;
case 2:
cardBackground.x = -100;
break;
case 3:
cardBackground.x = -199;
break;
case 4:
cardBackground.x = -298;
break;
case 5:
cardBackground.x = -396;
break;
case 6:
cardBackground.x = -495;
break;
case 7:
cardBackground.x = -593;
break;
case 8:
cardBackground.x = -691;
break;
case 9:
cardBackground.x = -790;
break;
case 10:
cardBackground.x = -888;
break;
case 11:
cardBackground.x = -987;
break;
case 12:
cardBackground.x = -1085;
break;
case 13:
cardBackground.x = -1184;
break;
default:
cardBackground.x = -199;
}
switch (card.suit)
{
case 1:
case 2:
case 3:
case 4:
cardBackground.y = (-2+-143*(card.suit-1));
break;
default:
cardBackground.y = -574;
}
return cardBackground;
}
function addToCount(card, currentTotal)
{
switch(card.rank)
{
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
if(currentTotal.count + card.rank > 21 && currentTotal.softAce == true)
{
currentTotal.softAce = false;
currentTotal.count = currentTotal.count - 10 + card.rank ;
}
else currentTotal.count += card.rank ;
break;
case 10:
case 11:
case 12:
case 13:
if(currentTotal.count + 10 > 21 && currentTotal.softAce == true)
{
currentTotal.softAce = false;
}
else currentTotal.count += 10;
break;
case 1:
if(currentTotal.count + 11 > 21)
{
currentTotal.count += 1;
}
else
{
currentTotal.count += 11;
currentTotal.softAce = true;
}
}
}
function addCard(card, cardContainer, isFaceDown)
{
var newCard = '<div class="cardContainer cardFaceDown newCard"><div class="cardFace"> </div></div>';
var lastCard = $(cardContainer).children(".cardContainer").last();
$(cardContainer).append(newCard);
$("#verticalSpacer").hide();
newCardDom = $(".newCard");
newCardDom.removeClass("newCard");
if(lastCard.length != 0)
{
lastCard.removeClass("cardFaceUp");
lastCard.addClass("cardCovered");
}
if(!isFaceDown)
{
newCardDom.removeClass("cardFaceDown");
var coords = getCardBackground(card);
newCardDom.find(".cardFace").css("background-position", ""+ coords.x + "px " + coords.y + "px");
newCardDom.addClass("cardFaceUp");
}
}
function dealCard(hand, isFaceDown)
{
var nextCard = randomCard();
addToCount(nextCard, hand);
addCard(nextCard, hand.container, isFaceDown);
if(isFaceDown)
{
faceDownCard = nextCard;
}
return nextCard;
}
function flipCard()
{
var lastCard = $(".cardFaceDown");
lastCard.removeClass("cardFaceDown");
var coords = getCardBackground(faceDownCard);
lastCard.find(".cardFace").css("background-position", ""+ coords.x + "px " + coords.y + "px");
lastCard.addClass("cardFaceUp");
}
function endHand(isBlackjack)
{
isSplit = false;
$("#splitGroup").removeClass("selectedSplit");
$("#playerGroup").removeClass("selectedSplit");
var resultValue = (splitHand.value + playerHand.value)
currentBalance += resultValue;
var resultString = "";
if(isBlackjack)
{
resultString = "BLACKJACK! ";
}
if(resultValue > 0)
{
resultString += "You won $" + resultValue + "! ";
}
else if(resultValue == 0)
{
resultString += "You pushed. ";
}
else
{
resultString += "Sorry, you lost $" + Math.abs(resultValue) + ". ";
}
playerHand.count = 0;
playerHand.softAce = false;
dealerHand.count = 0;
dealerHand.softAce = false;
splitHand.count = 0
splitHand.softAce = false;
playerHand.value = currentBetSetting;
splitHand.value = 0;
faceDownCard = null;
if(currentBalance >= 1)
{
resultString += "Play again?";
$("#gameStatus").html(resultString);
$("#bankAmount").html(currentBalance.toFixed(2));
if(currentBalance < currentBetSetting)
{
currentBetSetting = Math.floor(currentBalance);
playerHand.value = currentBetSetting;
$("#betAmount").html(currentBetSetting);
}
changeButton($("#gameOption1"), cleanAndDeal, "Deal");
changeButton($("#gameOption2"), changeBet, "Change bet");
changeButton($("#gameOption3"), peaceOut, "I'm out");
$("#gameOption4").hide();
}
else
{
resultString += "Sorry, you're broke.";
$("#gameStatus").html(resultString);
$("#bankAmount").html(currentBalance.toFixed(2));
currentBetSetting = 0;
playerHand.value = currentBetSetting;
splitHand.value = 0;
$("#betAmount").html("0");
changeButton($("#gameOption1"), peaceOut, "Start over");
$("#gameOption2").hide();
$("#gameOption3").hide();
$("#gameOption4").hide();
}
}
function playDealer()
{
flipCard();
while(dealerHand.count < 17)
{
dealCard(dealerHand, false);
}
resolveHand(splitHand);
resolveHand(playerHand);
endHand(false);
}
function resolveHand(hand)
{
if(dealerHand.count <= 21 && hand.count > 0 && dealerHand.count > hand.count)
{
hand.value = -(hand.value);
}
else if(dealerHand.count == hand.count)
{
hand.value = 0;
}
return hand.value;
}
function cleanAndDeal()
{
$("#cardTableDealer").html("");
$("#playerGroup").html("");
$("#splitGroup").html("");
$("#splitGroup").hide();
dealHand();
}
function dealHand()
{
if(nextCard < 0 || nextCard > 26*numDecks)
{
shuffleDeck();
}
var firstCard = dealCard(playerHand, false);
dealCard(dealerHand, false);
var secondCard = dealCard(playerHand, false);
dealCard(dealerHand, true);
if(playerHand.count == 21)
{
flipCard();
if(dealerHand.count == 21)
{
playerHand.value = 0;
endHand(true);
return;
}
playerHand.value = currentBetSetting*3/2;
endHand(true);
return;
}
if(dealerHand.count == 21)
{
flipCard();
playerHand.value = -(currentBetSetting);
endHand(false);
return;
}
$("#gameStatus").html("You have " + playerHand.count + " points. What will you do?");
changeActionButton($("#gameOption1"), hitMe, playerHand, "Hit");
changeActionButton($("#gameOption2"), standDown, playerHand, "Stand");
if(currentBalance >= 2*currentBetSetting)
{
changeActionButton($("#gameOption3"), doubleDown, playerHand, "Double");
}
else
{
$("#gameOption3").hide();
}
if(firstCard.rank == secondCard.rank && currentBalance >= 2*currentBetSetting)
{
changeButton($("#gameOption4"), splitIt, "Split");
}
else
{
$("#gameOption4").hide();
}
}
function hitMe(e)
{
var currentHand;
if(e.data != null && e.data.hand != null)
{
currentHand = e.data.hand;
}
else
{
currentHand = playerHand;
}
dealCard(currentHand, false);
if(currentHand.count > 21)
{
currentHand.value = -(currentBetSetting);
currentHand.count = 0;
standDown();
return;
}
else if(currentHand.count == 21)
{
standDown();
return;
}
else
{
$("#gameOption3").hide();
$("#gameOption4").hide();
$("#gameStatus").html("You have " + currentHand.count + " points. What will you do?");
}
}
function standDown()
{
if(playerHand.count == 0 && splitHand.count == 0)
{
endHand(false);
return;
}
else if(isSplit)
{
isSplit = false;
$("#splitGroup").removeClass("selectedSplit");
$("#playerGroup").addClass("selectedSplit");
changeActionButton($("#gameOption1"), hitMe, playerHand, "Hit");
changeActionButton($("#gameOption2"), standDown, playerHand, "Stand");
if(currentBalance >= (2*currentBetSetting + Math.abs(splitBetValue)))
{
changeActionButton($("#gameOption3"), doubleDown, playerHand, "Double");
}
else
{
$("#gameOption3").hide();
}
$("#gameStatus").html("Your second hand has " + playerHand.count + " points. What will you do?");
}
else
{
playDealer();
}
}
function doubleDown(e)
{
var currentHand;
if(e.data != null && e.data.hand != null)
{
currentHand = e.data.hand;
}
else
{
currentHand = playerHand;
}
currentHand.value = currentBetSetting * 2;
dealCard(currentHand, false);
if(isSplit && playerHand.count < 21)
{
if(currentHand.count > 21)
{
currentHand.value = -(currentHand.value);
currentHand.count = 0;
}
standDown();
return;
}
else if(currentHand.count > 21)
{
currentHand.count = 0;
currentHand.value = -(currentHand.value);
endHand();
return;
}
else
{
playDealer();
}
}
function splitIt()
{
isSplit = true;
splitHand.value = currentBetSetting;
$("#gameOption4").hide();
var firstCard = $("#playerGroup").find(".cardContainer")[0];
$(firstCard).appendTo($("#splitGroup"));
$("#splitGroup").show();
if(playerHand.softAce)
{
splitHand.count = 11;
splitHand.softAce = true;
playerHand.count = 11;
dealCard(splitHand, false);
dealCard(playerHand, false);
playDealer();
return;
}
else
{
splitHand.count = playerHand.count / 2;
splitHand.softAce = false;
playerHand.count = splitHand.count;
dealCard(splitHand, false);
dealCard(playerHand, false);
$("#splitGroup").addClass("selectedSplit");
}
changeActionButton($("#gameOption1"), hitMe, splitHand, "Hit");
changeActionButton($("#gameOption2"), standDown, splitHand, "Stand");
if(currentBalance >= (3*currentBetSetting))
{
changeActionButton($("#gameOption3"), doubleDown, splitHand, "Double");
}
else
{
$("#gameOption3").hide();
}
$("#gameStatus").html("You split! Your first hand has " + splitHand.count + " points; what will you do?");
}
function runTheNumbers()
{
$("#bankAmount").html(currentBalance.toFixed(2));
$("#betAmount").html(currentBetSetting);
$("#gameStatus").html("Ready to deal; you in?");
changeButton($("#gameOption1"), dealHand, "Deal");
changeButton($("#gameOption2"), changeBet, "Change bet");
changeButton($("#gameOption3"), peaceOut, "I'm out");
$("#gameOption4").hide();
}
function loadSave()
{
var loadRequestData =
{
"action": "raw",
"title": "User:" + mw.config.get("wgUserName") + "/blackjackBalance.js"
};
$.post("/w/index.php", loadRequestData, function (response)
{
var retrievedValue = parseFloat(response);
if (!(isNaN(retrievedValue)) && retrievedValue >= 1)
{
currentBalance = retrievedValue;
if (Math.floor(currentBalance / 10) < 10)
{
currentBetSetting = Math.floor(currentBalance / 10);
if (currentBetSetting < 1)
{
currentBetSetting = 1;
}
}
else
{
currentBetSetting = 10;
}
}
else
{
alert("Sorry, you're broke! No worries, I'll get you started with $500.");
currentBalance = 500;
currentBetSetting = 10;
}
runTheNumbers();
}
).fail(function()
{
alert("Ah, you're new here? I'll get you started with $500.");
currentBalance = 500;
currentBetSetting = 10;
previousBalanceExists = false;
runTheNumbers();
});
}
function prepareBlackjack()
{
$("#gameStatus").html("Welcome to Blackjack!");
changeButton($("#gameOption1"), loadSave, "Get started");
$("#splitGroup").hide();
$("#gameOption2").hide();
$("#gameOption3").hide();
$("#gameOption4").hide();
}
$(document).ready(prepareBlackjack);
}