Scripts/yah_gem_blackjack.js |
"use strict";
this.name = "yah_gem_blackjack";
this.author = "spara";
//add interface, if the player has started the game anywhere elsewhere than constore
this.startUpComplete = function() {
if (!player.ship.dockedStation.hasRole("constore")) {
this.shipExitedWitchspace();
}
}
this.shipExitedWitchspace = function() {
var constores = system.shipsWithRole("constore");
if (constores.length > 0) {
for (var i = 0; i < constores.length; i++) {
constores[i].setInterface("yah_gem-blackjack",{
title: "Video blackjack",
category: expandMissionText("yah_gem-gambling-category"),
summary: expandMissionText("yah_gem-blackjack-summary"),
callback: this.$intro.bind(this)
});
}
}
}
//init a new deck
this.$virginDeck = function() {
var deck = new Array();
var suits = ["triangle", "crescent", "square", "star"];
for (var i = 0; i < 4; i++) {
for (var j = 1; j < 14; j++) {
var card = new Object();
card.suit = suits[i];
card.rank = j;
card.double = 0;
card.hide = 0;
if (j > 10) card.value = 10;
else if (j === 1) card.value = 11;
else card.value = card.rank;
deck.push(card);
}
}
return deck;
}
//calculate the value of a hand
this.$calculateHandValue = function(cards) {
var finished = false;
while (!finished) {
var sum = 0;
for (var i = 0; i < cards.length; i++) {
sum += cards[i].value;
}
if (sum > 21) {
//change aces' value from 11 to 1
for (var i = 0; i < cards.length; i++) {
if (cards[i].value === 11) {
cards[i].value = 1;
break;
}
}
//all aces have been changed, sum stands.
if (i === cards.length)
finished = true;
}
else finished = true;
}
return sum;
}
//intro screen
this.$intro = function() {
var credits = "\n\nGems: " + player.ship.manifest["gem_stones"] + " g";
//gambling choices
var options = {
"1_EXIT" : "Exit"
};
if (player.ship.manifest["gem_stones"] >= 2)
options["2_10"] = "Bet 1";
else credits += expandMissionText("yah_gem-no-credit");
if (player.ship.manifest["gem_stones"] >= 4)
options["3_50"] = "Bet 5";
if (player.ship.manifest["gem_stones"] >= 8)
options["4_100"] = "Bet 10";
mission.runScreen({
titleKey: "yah_gem-blackjack-title",
message: expandMissionText("yah_gem-blackjack-intro-story") + credits,
model: "yah_gem_casino_blackjack_card_intro",
background: "yah_gem_table_bg.png",
choices: options,
allowInterrupt: true,
screenID: "yah_gem_blackjack",
exitScreen: "GUI_SCREEN_INTERFACES"
},
function (choice) {
if (choice === "2_10") this.$playGame(2);
else if (choice === "3_50") this.$playGame(4);
else if (choice === "4_100") this.$playGame(8);
});
}
//first pay, then deal
this.$playGame = function(bet) {
//pay up first
player.ship.manifest["gem_stones"] -= bet;
this.$bet = bet;//initial bet
this.$totalBet = bet;//sum of all bets in round
//init a new deck
this.$playDeck = this.$virginDeck();
//dealer initial hand
var dealerHand = new Object();
dealerHand.cards = [this.$drawCard(), this.$drawCard()];
dealerHand.cards[1].hide = 1;
this.$dealerHands = [dealerHand];
//player initial hand
var playerHand = new Object();
playerHand.cards = [this.$drawCard(), this.$drawCard()];
playerHand.bet = bet;
this.$playerHands = [playerHand];
//lets play some blackjack
this.$deal(0);
}
this.$updateHandProps = function(hand, hands) {
hand.value = this.$calculateHandValue(hand.cards);
if (hand.value === 21) {
if (hands.length === 1 && hand.cards.length === 2) {
hand.status = "blackjack";
}
else hand.status = "21";
}
else if (hand.value > 21) hand.status = "busted";
else if (hand.status !== "stand") hand.status = "hit";
}
//Deal
this.$deal = function() {
//rotate till playable hand
for (var hand = 0; hand < this.$playerHands.length; hand++) {
var playerHand = this.$playerHands[hand];
this.$updateHandProps(playerHand, this.$playerHands);
if (playerHand.value < 21 && playerHand.status !== "stand")
break;
}
//dealer's turn?
if (hand === this.$playerHands.length) {
this.$resolve();
return;
}
//choices
var options = {};
if (playerHand.status === "hit") {
options["1_HIT"] = "Hit";
options["2_STAND"] = "Stand";
}
if (playerHand.cards.length === 2 && playerHand.status === "hit" && player.ship.manifest["gem_stones"] >= this.$bet) {
options["3_DOUBLE"] = "Double Down (" + this.$bet + " g)";
}
if (playerHand.cards.length === 2 && (playerHand.cards[0].value === playerHand.cards[1].value || playerHand.cards[0].rank === playerHand.cards[1].rank) && this.$playerHands.length < 4) {
options["4_SPLIT"] = "Split (" + this.$bet + " g)";
}
if (playerHand.cards.length === 2 && this.$playerHands.length === 1) {
options["5_SURRENDER"] = "Surrender";
}
//status message
var message = "Player hand: " + playerHand.value + "\n\n";
message += "Total bet: " + this.$totalBet;
message += "\nGems: " + player.ship.manifest["gem_stones"] + " g";
mission.runScreen({
titleKey: "yah_gem-blackjack-title",
model: "yah_gem_casino_blackjack_card_base",
background: "yah_gem_table_bg.png",
message: message,
spinModel: false,
screenID: "yah_gem_blackjack",
choices: options
},
function (choice) {
if (choice === "1_HIT") {
playerHand.cards.push(this.$drawCard());
this.$deal();
return;
}
else if (choice === "2_STAND") {
playerHand.status = "stand";
this.$deal();
return;
}
else if (choice === "3_DOUBLE") {
playerHand.cards.push(this.$drawCard());
this.$updateHandProps(playerHand, this.$playerHands);
if (playerHand.value < 21) playerHand.status = "stand";
player.ship.manifest["gem_stones"] -= this.$bet;
this.$totalBet += this.$bet;
playerHand.bet = 2 * playerHand.bet;
this.$deal();
return;
}
else if (choice === "4_SPLIT") {
//limit to one card after splitting aces!!!!!!!
if (playerHand.cards[0].rank === 1) {
playerHand.cards[0].value = 11;
playerHand.cards[1].value = 11;
}
player.ship.manifest["gem_stones"] -= this.$bet;
this.$totalBet += this.$bet;
var newHand = new Object();
newHand.cards = [playerHand.cards.pop(), this.$drawCard()];
newHand.bet = this.$bet;
this.$playerHands.push(newHand);
playerHand.cards.push(this.$drawCard());
this.$deal();
return;
}
else if (choice === "5_SURRENDER") {
playerHand.status = "surrender";
this.$resolve();
return;
}
else {
this.$intro();
return;
}
}
);
this.$updateScreen();
//update flasher markers
//while playing: yellow - current hand, red - busted hand
for (var i = 0; i < this.$playerHands.length; i++) {
var status = this.$playerHands[i].status;
if (i === hand)
mission.displayModel.flashers[i].color = "yellowColor";
else if (status === "busted")
mission.displayModel.flashers[i].color = "redColor";
else {
mission.displayModel.flashers[i].position = [0, 0, 50];
}
}
for (var j = i; j < 4; j++)
mission.displayModel.flashers[j].position = [0, 0, 50];
}
this.$resolve = function() {
var dealerHand = this.$dealerHands[0];
this.$updateHandProps(dealerHand, this.$dealerHands);
dealerHand.cards[1].hide = false;
//check player for non-busted hands
var busted = true;
for (var i = 0; i < this.$playerHands.length; i++) {
if (this.$playerHands[i].status !== "busted") {
busted = false;
break;
}
}
//if all player cards are busted, dealer automatically wins
if (busted || this.$playerHands[i].status === "surrender") {
for (var i = 0; i < this.$playerHands.length; i++) {
this.$playerHands[i].result = "loss";
}
}
else {
//start drawing cards until we go over 16.
while (dealerHand.value < 17) {
dealerHand.cards.push(this.$drawCard());
this.$updateHandProps(dealerHand, this.$dealerHands);
}
//compare player hands to the dealer hand
for (var i = 0; i < this.$playerHands.length; i++) {
var playerHand = this.$playerHands[i];
//if the player has not busted, we'll compare
if (playerHand.status !== "busted") {
//blackjack
if (playerHand.status === "blackjack") {
if (dealerHand.status === "blackjack")
playerHand.result = "push";
else playerHand.result = "win";
}
//push
else if (dealerHand.value === playerHand.value)
playerHand.result = "push";
//win
else if (dealerHand.value > 21 || (21 - playerHand.value < 21 - dealerHand.value))
playerHand.result = "win";
//loss
else playerHand.result = "loss";
}
//if the player has busted, it's a loss
else playerHand.result = "loss";
}
}
//calculate the winnings
var win = 0;
for (var i = 0; i < this.$playerHands.length; i++) {
var playerHand = this.$playerHands[i];
if (playerHand.result === "win") {
if (playerHand.status === "blackjack")
win += 2.5 * playerHand.bet;
else win += 2 * playerHand.bet;
}
else if (playerHand.result === "push")
win += playerHand.bet;
else if (playerHand.status === "surrender" && dealerHand.status !== "blackjack")
win += playerHand.bet / 2;
}
player.ship.manifest["gem_stones"] += win;
//status message
var resultMessage = "";
//player
for (var i = 0; i < this.$playerHands.length; i++) {
var playerHand = this.$playerHands[i]
resultMessage += "Player hand: ";
if (playerHand.status === "blackjack")
resultMessage += "Blackjack\n";
else if (playerHand.status === "busted")
resultMessage += "Busted\n";
else if (playerHand.result === "push")
resultMessage += "Push\n";
else if (playerHand.status === "surrender")
resultMessage += "Surrender\n";
else resultMessage += playerHand.value + "\n";
}
//dealer
if (dealerHand.status === "blackjack")
resultMessage += "Dealer hand: Blackjack\n\n"
else if (dealerHand.status === "busted")
resultMessage += "Dealer hand: Busted\n\n"
else resultMessage += "Dealer hand: " + dealerHand.value + "\n\n";
//winnings
var notifySound = new SoundSource;
if (win - this.$totalBet > 0) {
resultMessage += "You win " + (win - this.$totalBet) + " g\n";
notifySound.sound = "yah_gem_win.ogg";
}
else if (win - this.$totalBet < 0) {
resultMessage += "You lose " + (this.$totalBet - win) + " g\n";
notifySound.sound = "yah_gem_lose.ogg";
}
else {
resultMessage += "You get even\n";
notifySound.sound = "yah_gem_win.ogg";
}
notifySound.play();
resultMessage += "\nGems: " + player.ship.manifest["gem_stones"] + " g";
var options = {
"2_REBET" : "Change bet",
"3_EXIT" : "Exit"
};
if (player.ship.manifest["gem_stones"] >= this.$bet)
options["1_AGAIN"] = "Deal again (" + this.$bet + " g)";
mission.runScreen({
titleKey: "yah_gem-blackjack-title",
model: "yah_gem_casino_blackjack_card_base",
message: resultMessage,
spinModel: false,
background: "yah_gem_table_bg.png",
choices: options,
allowInterrupt: true,
screenID: "yah_gem_blackjack",
exitScreen: "GUI_SCREEN_INTERFACES"
},
function (choice) {
if (choice === "1_AGAIN") {
this.$playGame(this.$bet);
return;
}
else if (choice === "2_REBET") {
this.$intro();
return;
}
});
this.$updateScreen(-1);
//red: lose
//green: win
//yellow: push
for (var i = 0; i < this.$playerHands.length; i++) {
var result = this.$playerHands[i].result;
if (result === "win")
mission.displayModel.flashers[i].color = "greenColor";
else if (result === "loss")
mission.displayModel.flashers[i].color = "redColor";
else mission.displayModel.flashers[i].color = "yellowColor";
}
for (var j = i; j < 4; j++)
mission.displayModel.flashers[j].position = [0, 0, 50];
}
//draws a card from the current deck in play
this.$drawCard = function() {
return this.$playDeck.splice(Math.floor(this.$playDeck.length * Math.random()),1)[0];
}
//update textures and positions for cards
this.$updateScreen = function() {
//player cards subents 0-10, 11-21, 22 -32, 33-43
//dealer cards subents 44-54
//player cards
for (var i = 0; i < this.$playerHands.length; i++) {
//show player hand
var playerHand = this.$playerHands[i];
for (var j = 0; j < playerHand.cards.length; j++) {
var card = playerHand.cards[j];
var fileName = "yah_gem_card_" + card.suit + "_" + card.rank + ".png";
var place = i * 11 + j;
mission.displayModel.subEntities[place].setMaterials({"casino_poker_card_diffuse.png": {diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor"}});
}
//double down
if (playerHand.bet === 2 * this.$bet) {
mission.displayModel.subEntities[place].orientation = [0.5, 0.5, 0.5, 0.5];
}
//hide non used player subents from view
for (var k = j; k < 11; k++) this.$hideCard(i * 11 + k);
}
//hide non used player subents from view
for (var k = i * 11; k < 44; k++) this.$hideCard(k);
//dealer cards
var dealerHand = this.$dealerHands[0];
for (var j = 0; j < dealerHand.cards.length; j++) {
var card = dealerHand.cards[j];
if (card.hide) {
var fileName = "yah_gem_blackjack_card_diffuse.png";
}
else {
var fileName = "yah_gem_card_" + card.suit + "_" + card.rank + ".png";
}
mission.displayModel.subEntities[4 * 11 + j].setMaterials({"casino_poker_card_diffuse.png": {diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor"}});
}
//hide non used dealer subents from view
for (var k = 4 * 11 + j; k < 54; k++) this.$hideCard(k);
}
//moves the cards to the centerline and turns them out of view
this.$hideCard = function(place) {
var position = mission.displayModel.subEntities[place].position;
position[2] = 0;
mission.displayModel.subEntities[place].position = position;
var orientation = [0, 0, 0, 1];
mission.displayModel.subEntities[place].orientation = orientation;
}
|
Scripts/yah_gem_dice.js |
"use strict";
this.name = "yah_gem_dice";
this.author = "spara";
//game track with bet multipliers
this.$track = [0, 0, 0, 4, 0, 8, 0, 17, 0, 35];
//add interface, if the player has started the game anywhere elsewhere than constore
this.startUpComplete = function() {
if (!player.ship.dockedStation.hasRole("constore")) {
this.shipExitedWitchspace();
}
}
this.shipExitedWitchspace = function() {
var constores = system.shipsWithRole("constore");
if (constores.length > 0) {
for (var i = 0; i < constores.length; i++) {
constores[i].setInterface("yah_gem-dice",{
title: "Smuggler's run",
category: expandMissionText("yah_gem-gambling-category"),
summary: expandMissionText("yah_gem-dice-summary"),
callback: this.$intro.bind(this)
});
}
}
}
//helper function for tabulating text on screen
this.$tabulate = function(line, width) {
var hairSpace = String.fromCharCode(31);
var space = defaultFont.measureString(" ");
while (defaultFont.measureString(line) < width - space)
line += " ";
while (defaultFont.measureString(line) < width)
line += hairSpace;
return line;
}
//intro screen
this.$intro = function() {
var bets = [1, 5, 10];
//build and format the payoff table for screen
var payoffMessage = "Bet:";
for (var i = 0; i < 3; i++) {
payoffMessage = this.$tabulate(payoffMessage, 5 * (i + 1));
payoffMessage += bets[i] + " g";
}
var payoffMessage2 = "Score";
for (var i = 0; i < 3; i++) {
payoffMessage2 = this.$tabulate(payoffMessage2, 5 * (i + 1));
payoffMessage2 += "Win!";
}
payoffMessage = "\n\n" + payoffMessage + "\n\n" + payoffMessage2 + "\n";
for (i = this.$track.length - 1; i > 0; i--) {
if (this.$track[i] !== 0) {
var line = this.$tabulate("", 0.5) + (i + 1);
for (var j = 0; j < 3; j++) {
line = this.$tabulate(line, 5 * (j + 1));
line += this.$track[i] * bets[j] + " g";
}
payoffMessage += line+"\n";
}
}
//format player credits for screen
var credits = expandMissionText("yah_gem-credits")+player.ship.manifest["gem_stones"] + " g";
var options = {
"1_EXIT" : "Exit"
};
if (player.ship.manifest["gem_stones"] >= 1)
options["2_10"] = "Bet 1";
else credits += expandMissionText("yah_gem-no-credit");
if (player.ship.manifest["gem_stones"] >= 5)
options["3_50"] = "Bet 5";
if (player.ship.manifest["gem_stones"] >= 10)
options["4_100"] = "Bet 10";
mission.runScreen({
titleKey: "yah_gem-dice-title",
screenID: "yah_gem_dice",
message: expandMissionText("yah_gem-dice-intro-story") + payoffMessage + credits,
choices: options,
background: "yah_gem_dice_bg-intro.png",
exitScreen: "GUI_SCREEN_INTERFACES"
},
function (choice) {
if (choice === "2_10") this.$playGame(1);
else if (choice === "3_50") this.$playGame(5);
else if (choice === "4_100") this.$playGame(10);
}
);
}
//da game
this.$playGame = function(bet, prevSum, round, track, select) {
//init the game
if (typeof round === 'undefined') {
var round = 0;
var track = this.$tabulate(" ", 3);
player.ship.manifest["gem_stones"] -= bet;
}
//roll the dice
var die1 = Math.ceil(6 * Math.random());
var die2 = Math.ceil(6 * Math.random());
var sum = die1 + die2;
//check the guess
var pass = true;
if (typeof prevSum !== 'undefined') {
if (select === "high_same") {
if (sum < prevSum)
pass = false;
}
else if (select === "high") {
if (sum <= prevSum)
pass = false;
}
else if (select === "low_same") {
if (sum > prevSum)
pass = false;
}
else if (select === "low") {
if (sum >= prevSum)
pass = false;
}
}
//debug
//pass = true;
//build the track display
track += sum;
//don't add tabs to the final score
if (round < this.$track.length) {
track = this.$tabulate(track, 3 + (round + 1) * 2.7);
}
var messageTrack = track;
for (var i = round; i < this.$track.length; i++) {
if (this.$track[i] !== 0) {
messageTrack += bet * this.$track[i] + " g";
}
else messageTrack += "?";
if (i < this.$track.length - 1) {
messageTrack = this.$tabulate(messageTrack, 3 + (i + 2) * 2.7);
}
}
var credits = "Gems: " + player.ship.manifest["gem_stones"] + " g";
var betText = "Bet: " + bet + "\n";
//correct guess
if (pass) {
var options = {};
//cash out
if (round > 0 && this.$track[round-1] !== 0) {
var cash_out = bet * this.$track[round-1] + " g";
options["1_CASH"] = "Cash out " + cash_out;
var message = expandMissionText("yah_gem-dice-track-cash");
var background = "yah_gem_dice_bg-cash.png";
}
else {
var message = expandMissionText("yah_gem-dice-track-basic");
var background = "yah_gem_dice_bg-basic.png";
}
var background = "yah_gem_dice_bg-" + round + ".png"
//guess choices
if (round !== this.$track.length) {
if (sum >= 7)
options["2_HIGH_SAME"] = "Higher or same";
else
options["3_HIGH"] = "Higher";
if (sum <= 7)
options["4_LOW_SAME"] = "Lower or same";
else
options["5_LOW"] = "Lower";
}
//game finished
else {
var message = expandMissionText("yah_gem-dice-track-final");
}
mission.runScreen({
titleKey: "yah_gem-dice-title",
screenID: "yah_gem_dice",
overlay: "yah_gem_dice_"+die1+"-"+die2+".png",
message: "\n" + messageTrack + "\n\n" + message + "\n\n" + credits + "\n" + betText,
choices: options,
background: background
},
function (choice) {
if (choice === "1_CASH") {
var win = this.$track[round-1] * bet;
player.ship.manifest["gem_stones"] += win;
var notifySound = new SoundSource;
notifySound.sound = "yah_gem_win.ogg";
notifySound.play();
this.$intro();
return;
}
else if (choice === "2_HIGH_SAME") {
this.$playGame(bet, sum, round + 1, track, "high_same");
return;
}
else if (choice === "3_HIGH") {
this.$playGame(bet, sum, round + 1, track, "high");
return;
}
else if (choice === "4_LOW_SAME") {
this.$playGame(bet, sum, round + 1, track, "low_same");
return;
}
else if (choice === "5_LOW") {
this.$playGame(bet, sum, round + 1, track, "low");
return;
}
}
);
}
else {
var sound = "yah_gem_lose.ogg";
var options = {
"1_EXIT" : "Exit",
"2_AGAIN" : "Change bet"
};
if (player.ship.manifest["gem_stones"] >= bet) options["3_PLAY"] = "Play again";
mission.runScreen({
titleKey: "yah_gem-dice-title",
screenID: "yah_gem_dice",
overlay: "yah_gem_dice_"+die1+"-"+die2+".png",
message: "\n" + messageTrack + "\n\n" + expandMissionText("yah_gem-dice-track-fail") + "\n\n" + credits + "\n" + betText,
choices: options,
music: sound,
background: "yah_gem_dice_bg-fail.png",
exitScreen: "GUI_SCREEN_INTERFACES"
},
function (choice) {
if (choice === "2_AGAIN") {
this.$intro();
return;
}
else if (choice === "3_PLAY") {
this.$playGame(bet);
return;
}
}
);
}
}
|
Scripts/yah_gem_holdem.js |
"use strict";
this.name = "yah_gem_holdem";
this.author = "spara";
this.$highNames = ["Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace"];
this.$handRanks = ["High", "Pair","Two Pair","Three of a Kind","Straight","Flush","Full House","Four of a Kind","Straight Flush","Royal Flush"];
//add interface, if the player has started the game anywhere elsewhere than constore
this.startUpComplete = function() {
if (!player.ship.dockedStation.hasRole("constore")) {
this.shipExitedWitchspace();
}
}
this.shipExitedWitchspace = function() {
var constores = system.shipsWithRole("constore");
if (constores.length > 0) {
for (var i = 0; i < constores.length; i++) {
constores[i].setInterface("yah_gem-holdem",{
title: "hOopy hold'em",
category: expandMissionText("yah_gem-gambling-category"),
summary: expandMissionText("yah_gem-holdem-summary"),
callback: this.$intro.bind(this)
});
}
}
}
//init a new deck
this.$virginDeck = function() {
var deck = new Array();
var suits = ["triangle", "crescent", "square", "star"];
for (var i = 0; i < 4; i++) {
for (var j = 1; j < 14; j++) {
var card = new Object();
card.suit = suits[i];
card.rank = j;
card.show = false;
deck.push(card);
}
}
return deck;
}
//draws a card from the current deck in play
this.$drawCard = function() {
return this.$playDeck.splice(Math.floor(this.$playDeck.length * Math.random()),1)[0];
}
this.$intro = function() {
var credits = "\n\nGems: " + player.ship.manifest["gem_stones"] + " g";
var options = {};
options["1_EXIT"] = "Exit";
if (player.ship.manifest["gem_stones"] >= 3)
options["2_10"] = "Bet 1";
else credits += expandMissionText("yah_gem-no-credit") + " Minimum of 3 g is needed to play.";
if (player.ship.manifest["gem_stones"] >= 15)
options["3_50"] = "Bet 5";
if (player.ship.manifest["gem_stones"] >= 30)
options["4_100"] = "Bet 10";
mission.runScreen({
titleKey: "yah_gem-holdem-title",
message: expandMissionText("yah_gem-holdem-intro-story") + credits,
model: "yah_gem_casino_holdem_intro",
background: "yah_gem_table_bg.png",
choices: options,
allowInterrupt: true,
screenID: "yah_gem_holdem",
exitScreen: "GUI_SCREEN_INTERFACES"
},
function (choice) {
if (choice === "2_10") this.$play(1);
else if (choice === "3_50") this.$play(5);
else if (choice === "4_100") this.$play(10);
}
);
}
//first pay, then deal
this.$play = function(bet) {
player.ship.manifest["gem_stones"] -= bet;
this.$ante = bet;
this.$bets = 0;
this.$playDeck = this.$virginDeck();
this.$cards = new Array();
for (var i = 0; i < 9; i++) this.$cards.push(this.$drawCard());
//debug hands
//var deal = [48, 41, 5, 6, 23, 33, 19, 21, 30];
//for (var i = 0; i < 9; i++) {
// this.$cards.push(this.$playDeck[deal[i]]);
//}
this.$deal("deal");
}
this.$deal = function(phase) {
var message = "Ante: " + this.$ante;
if (this.$bets > 0) message += "\nBets: " + this.$bets;
message += "\n\nGems: " + player.ship.manifest["gem_stones"] + " g";
var options = {};
switch(phase) {
case "deal" : this.$cards[7].show = true;
this.$cards[8].show = true;
options["1_FLOP"] = "Play (" + this.$ante * 2 + " g)";
options["2_FOLD"] = "Fold";
break;
case "flop" : this.$cards[2].show = true;
this.$cards[3].show = true;
this.$cards[4].show = true;
options["3_CHECK_TURN"] = "Check";
if (player.ship.manifest["gem_stones"] >= this.$ante)
options["4_BET_TURN"] = "Bet (" + this.$ante + " g)";
break;
case "turn" : this.$cards[5].show = true;
options["5_CHECK_RIVER"] = "Check";
if (player.ship.manifest["gem_stones"] >= this.$ante)
options["6_BET_RIVER"] = "Bet (" + this.$ante + " g)";
break;
};
mission.runScreen({
titleKey: "yah_gem-holdem-title",
model: "yah_gem_casino_holdem_base",
message: message,
background: "yah_gem_table_bg.png",
spinModel: false,
screenID: "yah_gem_holdem",
choices: options
},
function(choice) {
switch(choice) {
case "1_FLOP" : player.ship.manifest["gem_stones"] -= 2 * this.$ante;
this.$bets += 2 * this.$ante;
this.$deal("flop");
return;
case "2_FOLD" : this.$showDown(true);
return;
case "3_CHECK_TURN" : this.$deal("turn");
return;
case "4_BET_TURN" : player.ship.manifest["gem_stones"] -= this.$ante;
this.$bets += this.$ante;
this.$deal("turn");
return;
case "5_CHECK_RIVER" : this.$showDown(false);
return;
case "6_BET_RIVER" : player.ship.manifest["gem_stones"] -= this.$ante;
this.$bets += this.$ante;
this.$showDown(false);
return;
}
});
this.$updateCards();
}
this.$handName = function(value, high) {
if (value > 0)
return this.$handRanks[value];
else
return this.$highNames[high - 7] + " " + this.$handRanks[0];
}
this.$formatHand = function(hand) {
var formatted = "(";
for (var i = 0; i < 5; i++) {
var value = hand[0][i].value;
if (value === 11) value = "J";
else if (value === 12) value = "Q";
else if (value === 13) value = "K";
else if (value === 14 || value === 1) value = "A";
formatted += value;
if (i < 4) formatted += ", ";
else formatted += ")";
}
return formatted;
}
this.$showDown = function(fold) {
for (var i = 0; i < 9; i++) this.$cards[i].show = true;
var playerHand = this.$bestHand(2);
var dealerHand = this.$bestHand(0);
var playerValues = "\n" + this.$formatHand(playerHand) + "\n\n";
var dealerValues = "\n" + this.$formatHand(dealerHand) + "\n\n";
var message = "Player: " + this.$handName(playerHand[1], playerHand[0][0].value) + playerValues;
message += "Dealer: " + this.$handName(dealerHand[1], dealerHand[0][0].value) + dealerValues;
if (fold) var result = "fold";
else {
var result = "push";
if (dealerHand[1] > playerHand[1])
result = "loss";
else if (dealerHand[1] < playerHand[1]) {
result = "win";
}
else {
for (var i = 0; i < 5; i++) {
if (playerHand[0][i].value > dealerHand[0][i].value) {
result = "win";
break;
}
else if (playerHand[0][i].value < dealerHand[0][i].value) {
result = "loss";
break;
}
}
}
}
var notifySound = new SoundSource;
switch (result) {
case "win" : if (playerHand[1] > 3) {
var win = 2 * (this.$bets + this.$ante);
}
else var win = this.$ante + 2 * (this.$bets);
message += "You win " + (win - this.$bets - this.$ante) + " g";
player.ship.manifest["gem_stones"] += win;
notifySound.sound = "yah_gem_win.ogg";
break;
case "loss" : message += "Dealer wins, you lose " + this.$bets + " g";
notifySound.sound = "yah_gem_lose.ogg";
break;
case "push" : message += "It's a push, wagers returned.";
notifySound.sound = "yah_gem_win.ogg";
player.ship.manifest["gem_stones"] += this.$bets + this.$ante;
break;
case "fold" : message += "You fold and lose " + this.$ante + " g";
notifySound.sound = "yah_gem_lose.ogg";
break;
}
notifySound.play();
message += "\n\nGems: " + player.ship.manifest["gem_stones"] + " g";
var options = {};
if (player.ship.manifest["gem_stones"] >= 3 * this.$ante)
options["7_DEAL"] = "Deal again (" + this.$ante + " g)";
options["8_BET"] = "Change ante";
options["9_EXIT"] = "Exit";
mission.runScreen({
titleKey: "yah_gem-holdem-title",
model: "yah_gem_casino_holdem_base",
message: message,
background: "yah_gem_table_bg.png",
spinModel: false,
choices: options,
allowInterrupt: true,
screenID: "yah_gem_holdem",
exitScreen: "GUI_SCREEN_INTERFACES"
},
function(choice) {
switch(choice) {
case "7_DEAL" : this.$play(this.$ante);
return;
case "8_BET" : this.$intro(1);
return;
};
});
this.$updateCards();
}
this.$updateCards = function() {
for (var i = 0; i < 9; i++) {
var card = this.$cards[i];
if (card.show) {
var fileName = "yah_gem_card_" + card.suit + "_" + card.rank + ".png";
}
else var fileName = "yah_gem_holdem_card_diffuse.png";
mission.displayModel.subEntities[i].setMaterials({"casino_poker_card_diffuse.png": {diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor"}});
}
}
this.$bestHand = function(start) {
//make a new hand with new objects
var hand = new Array();
for (var i = start; i < start + 7; i++) {
var suits = ["triangle", "crescent", "square", "star"];
var card = new Object();
card.value = this.$cards[i].rank;
card.suit = suits.indexOf(this.$cards[i].suit);
if (card.value === 1) card.value = 14;
hand.push(card);
}
//order cards by suit
hand.sort(function(a, b) {return a.suit - b.suit});
//handle flushes first
if (hand[0].suit === hand[4].suit || hand[1].suit === hand[5].suit || hand[2].suit === hand[6].suit) {
//suit of flush
var suit = hand[2].suit;
//remove wrong suit cards
for (var i = 0; i < 7; i++) {
if (hand[6 - i].suit !== suit)
hand.splice(6 - i, 1);
}
//order cards by value
hand.sort(function(a, b) {return b.value - a.value})
//handle possible ace by duplicating to a different value
if (hand[0].value === 14) {
card = new Object();
card.value = 1;
card.suit = suit;
hand.push(card);
}
//look for a straight
var straight = -1;
var length = 0;
for (var i = 0; i < hand.length - 1; i++) {
//tracking a straight
if (hand[i].value - hand[i + 1].value === 1) length++;
else if (hand[i].value - hand[i + 1].value != 0) length = 0;
if (length === 4) {
//highest straight starts from index i - 3
straight = i - 3;
break;
}
}
//straight flush found
if (straight > -1) {
hand = hand.splice(straight, 5);
//royal flush
if (hand[0].value === 14)
return [hand, 9];
//straight flush
else return [hand, 8];
}
//a plain flush found
else {
//take five most valuable cards
hand = hand.splice(0, 5);
return [hand, 5];
}
}
//order cards by value
hand.sort(function(a, b) {return b.value - a.value});
//handle possible ace by duplicating to a different value
if (hand[0].value === 14) {
card = new Object();
card.value = 1;
card.suit = hand[0].suit;
hand.push(card);
}
//look for a straight
var straight = -1;
var length = 0;
for (var i = 0; i < hand.length - 1; i++) {
//tracking a straight
if (hand[i].value - hand[i + 1].value === 1) length++;
else if (hand[i].value - hand[i + 1].value != 0) length = 0;
if (length === 4) {
//highest straight starts from index i - 3
straight = i - 3;
break;
}
}
//straight found
if (straight > -1) {
hand = hand.splice(straight, 5);
return [hand, 4];
}
//remove possible added ace. this was needed for straight search
if (hand[0].value === 14)
hand.pop();
//make a new array of the cards so that cards with the same value are grouped ot sub arrays
var grouped = new Array();
grouped.push([hand[0]]);
for (var i = 1; i < hand.length; i++) {
//if there is a group for this card value, then push the card into it.
if (hand[i].value === grouped[grouped.length - 1][0].value)
grouped[grouped.length - 1].push(hand[i]);
//otherwise create a new group
else grouped.push([hand[i]]);
}
//sort grouped cards by group size
grouped.sort(function(a, b) {return b.length - a.length});
//four of a kind
if (grouped[0].length === 4) {
var newHand = grouped[0];
var kicker = grouped[1][0];
for (var i = 2; i < grouped.length; i++) {
if (grouped[i][0] > kicker) kicker = grouped[i][0];
}
newHand.push(kicker);
return [newHand, 7];
}
//three of a kind or full house
if (grouped[0].length === 3) {
var newHand = grouped[0];
//full house
if (grouped[1].length > 1) {
newHand.push(grouped[1][0]);
newHand.push(grouped[1][1]);
return [newHand, 6];
}
//three of a kind
else {
newHand.push(grouped[1][0]);
newHand.push(grouped[2][0]);
return [newHand, 3];
}
}
//pair or two pair
if (grouped[0].length === 2) {
var newHand = grouped[0];
//two pair
if (grouped[1].length > 1) {
newHand.push(grouped[1][0]);
newHand.push(grouped[1][1]);
newHand.push(grouped[2][0]);
return [newHand, 2];
}
//pair
else {
newHand.push(grouped[1][0]);
newHand.push(grouped[2][0]);
newHand.push(grouped[3][0]);
return [newHand, 1];
}
}
hand = hand.splice(0, 5);
return [hand, 0];
}
|
Scripts/yah_gem_poker.js |
"use strict";
this.name = "yah_gem_poker";
this.author = "spara";
this.payoffHands = ["Jacks or Better","Two Pair","Three of a Kind","Straight","Flush","Full House","Four of a Kind","Straight Flush","Royal Flush"];
this.payoffTable = [[1,2,3,4,6,9,25,50,250],[2,4,6,8,12,18,50,100,500],[3,6,9,12,18,27,75,150,750],[4,8,12,16,24,36,100,200,1000],[5,10,15,20,30,45,125,250,4000]];
//add interface, if the player has started the game anywhere elsewhere than constore
this.startUpComplete = function() {
if (!player.ship.dockedStation.hasRole("constore")) {
this.shipExitedWitchspace();
}
}
this.shipExitedWitchspace = function() {
var constores = system.shipsWithRole("constore");
if (constores.length > 0) {
for (var i = 0; i < constores.length; i++) {
constores[i].setInterface("yah_gem-poker",{
title: "Video poker",
category: expandMissionText("yah_gem-gambling-category"),
summary: expandMissionText("yah_gem-poker-summary"),
callback: this.$intro.bind(this)
});
}
}
}
//init a new deck
this.$virginDeck = function() {
var deck = new Array();
var suits = ["triangle", "crescent", "square", "star"];
for (var i = 0; i < 4; i++) {
for (var j = 1; j < 14; j++) {
var card = new Object();
card.suit = suits[i];
card.rank = j;
card.hold = 0;
deck.push(card);
}
}
return deck;
}
//helper function for tabulating text on screen
this.$tabulate = function(line, width) {
var hairSpace = String.fromCharCode(31);
var space = defaultFont.measureString(" ");
while (defaultFont.measureString(line) < width - space)
line += " ";
while (defaultFont.measureString(line) < width)
line += hairSpace;
return line;
}
//intro screen
this.$intro = function() {
//build and format the payoff table for screen
var payoffMessage = this.$tabulate("Hand", 10);
for (var i = 0; i < 5; i++) {
payoffMessage += i + 1 + " g";
payoffMessage = this.$tabulate(payoffMessage, 10 + 4 * (i + 1));
}
payoffMessage = "\n" + payoffMessage + "\n\n";
for (i = 0; i < this.payoffHands.length; i++) {
var line = this.payoffHands[this.payoffHands.length - i - 1];
line = this.$tabulate(line, 10);
for (var j = 0; j < 5; j++) {
line = this.$tabulate(line, 10 + 4 * j);
line += this.payoffTable[j][this.payoffHands.length - i - 1];
}
payoffMessage += line+"\n";
}
//format player credits for screen
var credits = "Gems: " + player.ship.manifest["gem_stones"] + " g\n";
//gambling choices
var options = {
"1_EXIT" : "Exit"
};
if (player.ship.manifest["gem_stones"] >= 1) {
options["2_10"] = "Bet 1";
}
else payoffMessage += expandMissionText("yah_gem-no-credit");
if (player.ship.manifest["gem_stones"] >= 2)
options["3_20"] = "Bet 2";
if (player.ship.manifest["gem_stones"] >= 3)
options["4_30"] = "Bet 3";
if (player.ship.manifest["gem_stones"] >= 4)
options["5_40"] = "Bet 4";
if (player.ship.manifest["gem_stones"] >= 5)
options["6_50"] = "Bet 5";
mission.runScreen({
titleKey: "yah_gem-poker-title",
message: this.$tabulate(expandMissionText("yah_gem-poker-intro-story"), 26) + credits + payoffMessage,
model: "yah_gem_casino_poker_card_spin",
background: "yah_gem_table_bg.png",
choices: options,
allowInterrupt: true,
screenID: "yah_gem_poker",
exitScreen: "GUI_SCREEN_INTERFACES"
},
function (choice) {
if (choice === "2_10") this.$play(1);
else if (choice === "3_20") this.$play(2);
else if (choice === "4_30") this.$play(3);
else if (choice === "5_40") this.$play(4);
else if (choice === "6_50") this.$play(5);
}
);
}
//first pay, then deal
this.$play = function(bet) {
player.ship.manifest["gem_stones"] -= bet;
//init a new deck and draw a hand (don't show it yet)
this.$playDeck = this.$virginDeck();
var hand = new Array();
for (var i = 0; i < 5; i++) hand.push(this.$drawCard());
this.$deal(bet, hand);
}
//Deal
this.$deal = function(bet, hand, choice) {
if (typeof choice === 'undefined') var choice = "0_HOLD";
var options = {
"0_HOLD" : "Hold/Cancel 1.",
"1_HOLD" : "Hold/Cancel 2.",
"2_HOLD" : "Hold/Cancel 3.",
"3_HOLD" : "Hold/Cancel 4.",
"4_HOLD" : "Hold/Cancel 5.",
"5_DEAL" : "Draw"
}
var credits = "Gems: " + player.ship.manifest["gem_stones"] + " g\n";
var betText = "Bet: " + bet + "\n";
mission.runScreen({
titleKey: "yah_gem-poker-title",
message: this.$tabulate(expandMissionText("yah_gem-poker-deal-story"), 26) + credits + this.$tabulate(" ", 26) + betText,
model: "yah_gem_casino_poker_card_base",
background: "yah_gem_table_bg.png",
spinModel: false,
choices: options,
screenID: "yah_gem_poker",
initialChoicesKey: choice
},
function (choice) {
if (choice === "0_HOLD")
hand[0].hold = (hand[0].hold + 1) % 2;
else if (choice === "1_HOLD")
hand[1].hold = (hand[1].hold + 1) % 2;
else if (choice === "2_HOLD")
hand[2].hold = (hand[2].hold + 1) % 2;
else if (choice === "3_HOLD")
hand[3].hold = (hand[3].hold + 1) % 2;
else if (choice === "4_HOLD")
hand[4].hold = (hand[4].hold + 1) % 2;
else if (choice === "5_DEAL") {
this.$outCome(bet, hand);
return;
}
this.$deal(bet, hand, choice);
return;
}
);
//update the cards on screen
for (var i = 0; i < 5; i++)
this.$changeCard(i, hand[i]);
}
//draw && outcome
this.$outCome = function(bet, hand) {
//draw new cards
for (var i = 0; i < 5; i++) {
if (!hand[i].hold)
hand[i] = this.$drawCard();
else hand[i].hold = 0;
}
//check for wins
var result = this.winCheck(hand);
//fail
if (result === -1) {
var sound = "yah_gem_lose.ogg";
var resultText = expandMissionText("yah_gem-poker-fail");
}
//win
else {
var win = this.payoffTable[(bet - 1)][result];
var resultText = this.payoffHands[result] + ", you win " + win + " g of Gems.";
player.ship.manifest["gem_stones"] += win;
var sound = "yah_gem_win.ogg";
}
//format player credits for screen
var credits = "Gems: " + player.ship.manifest["gem_stones"] + " g\n";
var betText = "Bet: " + bet;
var options = {
"1_EXIT" : "Exit",
"2_AGAIN" : "Change bet",
};
if (player.ship.manifest["gem_stones"] >= bet) options["3_DEAL"] = "Deal again";
mission.runScreen({
titleKey: "yah_gem-poker-title",
message: this.$tabulate(resultText, 26) + credits + this.$tabulate(" ", 26) + betText,
model: "yah_gem_casino_poker_card_base",
background: "yah_gem_table_bg.png",
spinModel: false,
choices: options,
music: sound,
allowInterrupt: true,
screenID: "yah_gem_poker",
exitScreen: "GUI_SCREEN_INTERFACES"
},
function (choice) {
if (choice === "2_AGAIN") {
this.$intro();
return;
}
else if (choice === "3_DEAL") {
this.$play(bet);
return;
}
}
)
//update the cards on screen
for (var i = 0; i < 5; i++)
this.$changeCard(i, hand[i]);
}
//draws a card from the current deck in play
this.$drawCard = function() {
return this.$playDeck.splice(Math.floor(this.$playDeck.length * Math.random()),1)[0];
}
//update the texture and position for a card
this.$changeCard = function(place, card) {
var fileName = "yah_gem_card_" + card.suit + "_" + card.rank + ".png";
mission.displayModel.subEntities[place].setMaterials({"casino_poker_card_diffuse.png": {diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor"}});
if (card.hold) {
var position = mission.displayModel.subEntities[place].position;
position[2] = 3;
mission.displayModel.subEntities[place].position = position;
}
}
//rules for a winning hand
this.winCheck = function(hand) {
//work with a hand that has been ordered by rank
var orderedHand = hand.concat();
orderedHand.sort(function(a, b) {return a.rank - b.rank});
//check for flush
var suit = orderedHand[0].suit;
var i = 0;
var flush = false;
for (i = 1; i < 5; i++) {
if (orderedHand[i].suit !== suit) {
i = -1;
break;
}
}
//flush found
if (i !== -1) flush = true;
//check for straight
var prevRank = orderedHand[0].rank;
var straight = false
for (i = 1; i < 5; i++) {
if (orderedHand[i].rank - prevRank !== 1 && (i !== 1 || orderedHand[i].rank !== 10 || prevRank !== 1)) {
i = -1;
break;
}
prevRank = orderedHand[i].rank;
}
//straight found
if (i !== -1) straight = true;
//straight flush
if (flush && straight) {
if (orderedHand[0].rank === 1 && orderedHand[4].rank === 13)
return 8;//royal_flush
else return 7;//straight_flush
}
//flush
if (flush) return 4;//flush"
//straight
if (straight) return 3;//straight
//in the ordered list, for every adjacent two cards, check if they form a rank pair.
prevRank = orderedHand[0].rank;
var pairs = new Array();
for (i = 1; i < 5; i++) {
if (orderedHand[i].rank === prevRank) pairs.push(i);
prevRank = orderedHand[i].rank;
}
//four of a kind (3 adjacent pairs)
//full house (3 adjacent pairs)
if (pairs.length === 3) {
if (orderedHand[1].rank === orderedHand[2].rank && orderedHand[2].rank === orderedHand[3].rank)
return 6;//four_of_a_kind
else return 5;//full_house
}
//three of a kind (2 adjacent pairs)
//two pair (2 adjacent pairs)
if (pairs.length === 2) {
if (pairs[1] - pairs[0] === 1)
return 2;//three_of_a_kind
else return 1;//two pair
}
//pair (jacks or better)
if (pairs.length === 1) {
if (orderedHand[pairs[0]].rank > 10 || orderedHand[pairs[0]].rank === 1)
return 0;
}
return -1;
}
|