Back to Index Page generated: Dec 20, 2024, 7:22:10 AM

Expansion Your Ad Here Gem Casino

Content

Warnings

  1. Unknown key 'requires_oxp' at https://wiki.alioth.net/img_auth.php/5/5c/Yah_gem_casino_1.0.1.oxz!manifest.plist

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Adds casino games using gems as credits to the constores. Adds casino games using gems as credits to the constores.
Identifier oolite.oxp.spara.yah_gem_casino oolite.oxp.spara.yah_gem_casino
Title Your Ad Here Gem Casino Your Ad Here Gem Casino
Category Activities Activities
Author spara, CaptSolo spara, CaptSolo
Version 1.0.1 1.0.1
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/Your_Ad_Here! n/a
Download URL https://wiki.alioth.net/img_auth.php/5/5c/Yah_gem_casino_1.0.1.oxz n/a
License Creative Commons Attribution - Non-Commercial - Share Alike 4.0 license Creative Commons Attribution - Non-Commercial - Share Alike 4.0 license
File Size n/a
Upload date 1610873306

Documentation

Also read http://wiki.alioth.net/index.php/Your%20Ad%20Here%20Gem%20Casino

Equipment

This expansion declares no equipment. This may be related to warnings.

Ships

Name
yah_gem_blackjack_card_back
Video Poker Card
yah_gem_blackjack_card_pos10
yah_gem_blackjack_card_pos11
yah_gem_blackjack_card_pos12
yah_gem_blackjack_card_pos13
yah_gem_blackjack_card_pos14
yah_gem_blackjack_card_pos15
yah_gem_blackjack_card_pos16
yah_gem_blackjack_card_pos17
yah_gem_blackjack_card_pos18
yah_gem_blackjack_card_pos19
yah_gem_blackjack_card_pos2
yah_gem_blackjack_card_pos20
yah_gem_blackjack_card_pos21
yah_gem_blackjack_card_pos22
yah_gem_blackjack_card_pos23
yah_gem_blackjack_card_pos24
yah_gem_blackjack_card_pos25
yah_gem_blackjack_card_pos26
yah_gem_blackjack_card_pos27
yah_gem_blackjack_card_pos28
yah_gem_blackjack_card_pos29
yah_gem_blackjack_card_pos3
yah_gem_blackjack_card_pos30
yah_gem_blackjack_card_pos31
yah_gem_blackjack_card_pos32
yah_gem_blackjack_card_pos33
yah_gem_blackjack_card_pos34
yah_gem_blackjack_card_pos35
yah_gem_blackjack_card_pos36
yah_gem_blackjack_card_pos37
yah_gem_blackjack_card_pos38
yah_gem_blackjack_card_pos39
yah_gem_blackjack_card_pos4
yah_gem_blackjack_card_pos40
yah_gem_blackjack_card_pos41
yah_gem_blackjack_card_pos42
yah_gem_blackjack_card_pos43
yah_gem_blackjack_card_pos44
yah_gem_blackjack_card_pos45
yah_gem_blackjack_card_pos46
yah_gem_blackjack_card_pos47
yah_gem_blackjack_card_pos48
yah_gem_blackjack_card_pos49
yah_gem_blackjack_card_pos5
yah_gem_blackjack_card_pos50
yah_gem_blackjack_card_pos51
yah_gem_blackjack_card_pos52
yah_gem_blackjack_card_pos53
yah_gem_blackjack_card_pos54
yah_gem_blackjack_card_pos55
yah_gem_blackjack_card_pos6
yah_gem_blackjack_card_pos7
yah_gem_blackjack_card_pos8
yah_gem_blackjack_card_pos9
Video Blackjack Card
yah_gem_casino_blackjack_intro
Video Poker Card
yah_gem_casino_holdem_intro
Video Poker Card
yah_gem_casino_poker_card_spin
yah_gem_holdem_card_back
Video Hold'em Card
yah_gem_holdem_card_pos2
yah_gem_holdem_card_pos3
yah_gem_holdem_card_pos4
yah_gem_holdem_card_pos5
yah_gem_holdem_card_pos6
yah_gem_holdem_card_pos7
yah_gem_holdem_card_pos8
yah_gem_holdem_card_pos9
yah_gem_poker_card_back
Video Poker Card
yah_gem_poker_card_pos2
yah_gem_poker_card_pos3
yah_gem_poker_card_pos4
yah_gem_poker_card_pos5

Models

This expansion declares no models. This may be related to warnings.

Scripts

Path
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;
}