// JavaScript Document

//constants
var NONE = 0;

var FADE_IN = 1;
var FADE_OUT = 2;
var SET_VISIBLE = 3;
var SET_INVISIBLE = 4;
var WAIT = 5;
var FUNCTION = 6;
var MOVE = 7;
var SET_VALUE = 8;
var FINISHED = 9;
//chance card types
var MOVE_CARD = 1;
var TURN_CARD = 2;

//Global variables

var current_player = null;
var human = null;
var computer = null;
//all new events are pushed onto this.
var event_queue = new Array();
var dice = null;
var chance_stack = null;
var board = new Array(); // will be filled with spaces

//default switches:
var DEFAULT_FADE_TIME = 0.5; //OVERRIDE was 0.5
var DEFAULT_MOVE_TIME = 0.3; //OVERRIDE was 0.4
var DEFAULT_ALERT_TIME = 1.5;
var DIE_ROLL_TIME = 0.1;
var BOARD_HEIGHT = 500;
var BOARD_WIDTH = 800;
var TOKEN_SIZE = 30;

//references to window nodes, saved once:
var START_SCREEN = null;
var PICK_CHARACTERS_SCREEN = null;
var PICK_CHARACTERS_CONTINUE_BUTTON = null;

var WIN_SCREEN = null;
var PICK_CHANCE_SCREEN = null;
var CHANCE_PILE_SCREEN = null;
var CHANCE_PICKED_SCREEN = null;
var BOARD_SCREEN = null;
var ALERT_SCREEN = null;
var ROLL_BUTTON = null;
var DICE_SCREEN = null;
var DIE_ONE = null
var DIE_TWO = null;
var PICK_HUMAN = null;
var PICK_COMPUTER = null;

//****
var current_timeout = 0;
var die_timeout = 0;
var do_throb_roll = false;
var throb_roll_up = false;

function appendArrayMethods() {
	//hijack array methods with many useful new methods.
	Array.prototype.filter = function(n, func) {
		//operates ona list 
		var i;
		for (i=0;i<this.length;i++) {
			if((!func && this[i].number && this[i].number() == n) || (func && func(n,this[i]))) {
				//do nothing
			} else {
				// it doesn't belong
				this[i] = null; //mark for deletion
			}
		}
		//remove all items that are equal to null
		//marking and sweeping helps deal with invalid indexes if we removed them right away
		this.removeEmpty();
		return this;
	}
	
	Array.prototype.remove = function(n, func) {
		var i;
		for(i=0; i<this.length; i++) {
			if((!func && this[i].number && this[i].number() == n) || (func && func(n,this[i]))) {
				this[i] = null; // mark for deletion
			}
		}
		this.removeEmpty();
		return this;
	}
	
	Array.prototype.removeEmpty = function() {
		var i=0;
		//uses a special loop to remove all null parts of an array
		while(i< this.length) {
			//is this index to be removed?
			if(this[i] == null) {
				this.splice(i,1);
			} else {
				//look in the next location
				i++;
			}
		}
		return this;
	}
	
	Array.prototype.clone = function() {
		//returns a cloned copy of itself, so that modifying the array 
		//won't modify the original one.
		var i;
		var result = new Array();
		for(i=0;i<this.length;i++) {
			result[i] = this[i];
		}
		return result;
	}
	
	Array.prototype.map = function(func, n) {
		//takes a function that takes a single argument, and applys it to each element of array.
		var i;
		for(i=0;i<this.length;i++) {
			this[i] = func(this[i],n);
		}
		return this;
	}
	
	Array.prototype.append = function(array) {
		//concatenates the given array onto the current array
		var i;
		for(i =0; i<array.length; i++) {
			this[this.length] = array[i];
		}
		return this;
	}
}

function Space(_x, _y, _chance) {
	this.position = new Location(_x, BOARD_HEIGHT - _y); //woops, the numbers I meticiulously copied over from illustrator used bottom left as origin!
	this.chance = _chance;
	this.offsetPosition = function (isHuman) {
		var x = isHuman ? (this.position.x + 5) - (TOKEN_SIZE/2) : (this.position.x - 5) - (TOKEN_SIZE/2);
		var y = isHuman ? (this.position.y + 5) - (TOKEN_SIZE/2) : (this.position.y - 5) - (TOKEN_SIZE/2);
		return new Location(x,y);
	}
}

function Location(_x, _y) {
	this.x = _x ? _x : 0;
	this.y = _y ? _y : 0;
}

function DiceController() {
	//controlls two dice
	this.min = 2;
	this.max = 12;
	this.dieMin = 1; //the lowest number possible for a single die
	this.dieMax = 6; //the highest number possible for a single die
	this.resetMinMax = function() {
		this.min = 2;
		this.max = 12;
	}
	this.roll = function(func) {
		//returns a number that is the result, within bounds (min and max).  also, sets up the event loop, calling func to terminate it
		var obj = new Object();
		//obj.result = this.getResult(); // get a random roll within tolerances
		//split it into two dice
		do {
		obj.die1 = Math.floor(Math.random() * ((this.dieMax + 1) - this.dieMin)) + this.dieMin;
		obj.die2 = Math.floor(Math.random() * ((this.dieMax + 1) - this.dieMin)) + this.dieMin;
		obj.result = obj.die1 + obj.die2;
		} while(obj.result > this.max || obj.result < this.min);
		return obj;
	}
	this.getResult = function() {
		//just returns a random number between tolerances without showing UI.
		//this.max should be a possibility for inclusion.
		//but this doesn't return individual dice----!!!
		var result = Math.floor((Math.random() * ((this.max + 1) - this.min))) + this.min;
		return (result > this.max) ? this.max : result;
	}
}



function ChanceStackController() {
	this.cards = new Array();
	
	this.add = function(card) {
		this.cards[this.cards.length] = card;
	}
	this.getCard = function() {
		//serves up a card based on current player, and the locaiton of other player.
		//and identity of both, of course
		//first, filters out any cards that are totally invalid in a clone of cards.
		//then, returns a random one.
		var weighted_cards = new Array();
		var weight = compositeWeight();
		var max_input = 20; //that is, for the computer, a comp of 1.0 will mean that one gets put in twenty times.
		//weighted cards is an array of integers representing an index into the array of cards.
		var i, j, upper, goodness;
		for(i = 0; i < this.cards.length; i++) {
			goodness = current_player.isHuman ? (-1 * this.cards[i].goodness()) : this.cards[i].goodness();
			upper = Math.max(1.0 , Math.ceil(weight * goodness * max_input));
			for(j = 0; j < upper; j++) {
				weighted_cards.push(i);
			}
		}
		
		return this.cards[weighted_cards[Math.floor(Math.random() * weighted_cards.length)]];
	}
}

function ChanceCard(_type, _amount, _description) {
	this.type = _type ? _type : NONE;
	this.amount = _amount ? _amount : 0;
	this.description = _description ? _description : "Chance card";
	this.picture = false;
	this.goodness = function() {
		//calulates the desireability of this card.
		// from - 1 to 1, 0 is ambiguous
		var result = this.amount;
		var denom = 12.0; //12.0 is really bad/good
		if(this.type == MOVE_CARD) {
			//we'll say a turn is worth 6 moves on average.
			result *= 6;
		}
		if(result >= 0) {
			//don't return more than 1.0
			return Math.min(1.0, result / denom);
		} 
		return Math.max(-1.0, result / denom);
		
	}
}

function Player() {
	this.isHuman = false;
	this.turns = 0;
	this.moves = 0;
	this.position = new Location();
	this.space = 0;
	this.node = null;
	this.other = false;
	this.card = false;
	this.roll = false;
	this.bigName = function() {
		return this.isHuman ? "The black token" : "The white token";
	}
	this.name = function() {
		return this.isHuman ? "the black token" : "the white token";
	}
	this.has = function () {
		return this.isHuman ? "has" : "has";
	}
	this.is = function() {
		return this.isHuman ? "is" : "is";
	}
	this.possessive = function() {
		return this.isHuman? "The black token's" : "The white token's";
	}
	this.shortPossessive = function() {
		return this.isHuman ? "Black Token's" : "White Token's";
	}
}

function fadeInEvent(_node, _dur) {
	var obj = new Object();
	obj.type = FADE_IN;
	obj.node = _node;
	obj.duration = _dur;
	return obj;
}

function fadeOutEvent(_node, _dur) {
	var obj = new Object();
	obj.type = FADE_OUT;
	obj.node = _node;
	obj.duration = _dur;
	return obj;
}

function setVisibleEvent(_node) {
	var obj = new Object();
	obj.type = SET_VISIBLE;
	obj.node = _node;
	return obj;
}

function setInvisibleEvent(_node) {
	var obj = new Object();
	obj.type = SET_INVISIBLE;
	obj.node = _node;
	return obj;
}

function waitEvent(_dur) {
	var obj = new Object();
	obj.type = WAIT;
	obj.duration = _dur;
	return obj;
}

function functionEvent(_func,_args, _continue) {
	var obj = new Object();
	obj.type = FUNCTION;
	obj.func = _func;
	if(_args) {
		obj.args = _args;
	}
	if(_continue) {
		obj.cont = _continue;
	}
	return obj;
}

function setValueEvent(_node, _value) {
	var obj = new Object();
	obj.type = SET_VALUE;
	obj.node = _node;
	obj.value = _value;
	return obj;
}

function moveEvent(_node, _from, _to, _dur) {
	var obj = new Object();
	obj.type = MOVE;
	obj.node = _node;
	obj.from = _from;
	obj.to = _to;
	obj.duration = _dur;
	return obj;
}

function finishedEvent() {
	var obj = new Object();
	obj.type = FINISHED;
	return obj;
}

function nextEvent() {
	//handles all event loops.  
	if(event_queue.length == 0) {
		//nothing to do here... technically, we're supposed to have wanted a finished event. but we don't really care.
		return;
	}
	var evt = event_queue.shift();
	switch(evt.type) {
		case FADE_IN:
			new Effect.Opacity(evt.node, {duration: evt.duration, from:0.0, to:1.0, afterFinish:nextEvent});
			break;
		case FADE_OUT:
			new Effect.Opacity(evt.node, {duration: evt.duration, from:1.0, to:0.0, afterFinish:nextEvent});
			break;
		case SET_VISIBLE:
			evt.node.style.visibility = "visible";
			evt.node.style.opacity = 0.0; /* prevent a quick flash */
			nextEvent();
			break;
		case SET_INVISIBLE:
			evt.node.style.visibility = "hidden";
			nextEvent();
			break;
		case WAIT:
			//setTimeOut wants it in milliseconds.
			current_timeout = window.setTimeout(nextEvent, evt.duration * 1000);
			break;
		case FUNCTION:
			evt.func(evt.args);//if there are none, none will be sent!
			if(evt.cont) {
				nextEvent();
			}
			break;
		case MOVE:
			var x, y;
			//evt.to, evt.from are location objects (x and y)
			x = evt.to.x - evt.from.x;
			y = evt.to.y - evt.from.y;
			new Effect.MoveBy(evt.node, y, x, {duration: evt.duration, afterFinish:nextEvent});
			break;
		case SET_VALUE:
			evt.node.nodeValue = evt.value;
			nextEvent();
		case FINISHED:
			//do nothing.
			//this is technically how it's supposed to tell us to stop executing events.
			break;
		default:
			alert("Unknown event type: " + evt.type);
	}
	
}


function showStartScreen() {

	event_queue.push(setVisibleEvent(START_SCREEN));
	event_queue.push(fadeInEvent(START_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(functionEvent(cleanUpPlayers)); //get them ready to go (especially reseting after other game)... under cover
	//let's go!
	nextEvent();
}

function hideStartScreen() {
	event_queue.push(fadeOutEvent(START_SCREEN,DEFAULT_FADE_TIME));
	event_queue.push(setInvisibleEvent(START_SCREEN));
	event_queue.push(functionEvent(pickCharacters));
	
	nextEvent();
}

function pickCharacters() {
	event_queue.push(setInvisibleEvent(PICK_HUMAN));
	event_queue.push(setInvisibleEvent(PICK_COMPUTER));
	event_queue.push(setInvisibleEvent(PICK_CHARACTERS_CONTINUE_BUTTON));
	event_queue.push(setVisibleEvent(PICK_CHARACTERS_SCREEN));
	event_queue.push(fadeInEvent(PICK_CHARACTERS_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(waitEvent(1.5));
	event_queue.push(setVisibleEvent(PICK_COMPUTER));
	event_queue.push(fadeInEvent(PICK_COMPUTER, DEFAULT_FADE_TIME));
	//event_queue.push(functionEvent(showComputersPlayer,false,true));
	event_queue.push(waitEvent(1.5));
	event_queue.push(setVisibleEvent(PICK_HUMAN));
	event_queue.push(fadeInEvent(PICK_HUMAN, DEFAULT_FADE_TIME));
	//event_queue.push(functionEvent(showHumansPlayer,false,true));
	event_queue.push(setVisibleEvent(PICK_CHARACTERS_CONTINUE_BUTTON));
	event_queue.push(fadeInEvent(PICK_CHARACTERS_CONTINUE_BUTTON, DEFAULT_FADE_TIME));
	
	//let's go!
	nextEvent();
	
}

function hidePickCharacters() {
	//reset character positions, spaces, etc!
	//pick a random player to go first.
	current_player = Math.random() > .5 ? computer : human;
	event_queue.push(fadeOutEvent(PICK_CHARACTERS_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(setInvisibleEvent(PICK_CHARACTERS_SCREEN));
	insertAlert(current_player.bigName() + " will go first.");
	event_queue.push(functionEvent(startTurn));
	nextEvent();
}

function insertAlert(alertText) {
	//inserts an alert string of events into the queue.
	event_queue.push(setValueEvent(ALERT_SCREEN.firstChild, alertText));
	event_queue.push(setVisibleEvent(ALERT_SCREEN));
	event_queue.push(fadeInEvent(ALERT_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(waitEvent(DEFAULT_ALERT_TIME));
	event_queue.push(fadeOutEvent(ALERT_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(setInvisibleEvent(ALERT_SCREEN));
	
}

function startTurn() {
	if(current_player.isHuman) {
		do_throb_roll = true;
		throbRollButton();
		return;
	}
	//otherwise, go straight to 
	rollDie();
}



function doRoll() {
	//called by the link.
	//only allow it if the switch is set.
	if(do_throb_roll) {
		do_throb_roll = false;
		rollDie();
	}
}

function throbRollButton() {
	//var do_throb_roll = false;

	if(do_throb_roll) {
		throb_roll_up = throb_roll_up ? false : true;
		if(throb_roll_up) {
			new Effect.Opacity(ROLL_BUTTON, {duration: DEFAULT_FADE_TIME , from:0.0, to:1.0, afterFinish:throbRollButton});
		} else {
			new Effect.Opacity(ROLL_BUTTON, {duration: DEFAULT_FADE_TIME , from:1.0, to:0.0, afterFinish:throbRollButton});
		}
	} else {
		new Effect.Opacity(ROLL_BUTTON, {duration: DEFAULT_FADE_TIME, to: 0.0});
		throb_roll_up = false;
	}
	
}



function gameProgressWeight() {
	//0 to 1, based on the average position of the two players.
	//never return NaN; at the worst, return 0.0
	//return Math.max(0.0, Math.pow(((human.space + computer.space) / 2) / (board.length - 1), 2));
	return Math.max(((human.space + computer.space) / 2) / (board.length - 1) , 0.0);
}

function computerBoostWeight() {
	//0 to 1 based on how important it is for human to go more than computer
	/*
	if(human.space <= computer.space) {
		return 0.0;
	} */
	return Math.max(Math.min(1.0, (human.space - computer.space + 5) / 10), 0.0); //being even isn't good enough; we should be five ahead.
}

function compositeWeight() {
	return Math.min(1.0, gameProgressWeight() * computerBoostWeight() + 0.1);
	//OLD: return (gameProgressWeight() * 0.4) + (computerBoostWeight() * 0.5) + (1 * 0.1);
}

function rollDie() {
	//rolls the die, puts the result in current_player.moves
	//wha! doesn't actually fix the rolls as of right now
	
	var weight =  compositeWeight();
	//alert("Comp Weight: " + weight); // OVERRIDE
	if(current_player.isHuman) {
		//a higher weight for human makes his rolls lower
		dice.min = 1;
		//4 is the absolute lowest, 12 is absolute highest. (and, round down)
		dice.max = Math.floor(4 + (8 * (1 - weight)));
	} else {
		//a higher weight for the computer makes his rolls higher
		dice.max = 12;
		//highest it may ever go is 8. (and, round up)
		dice.min = Math.ceil(8 * weight);
	}
	current_player.roll = dice.roll();
	current_player.moves = current_player.roll.result;
	showDieRoll();
}

function showDieRoll() {
	//fade up, set-up global vars for the main loop
	current_player.roll.counter1 = 24;
	current_player.roll.counter2 = 36;
	DICE_SCREEN.firstChild.nodeValue = current_player.shortPossessive() + " Roll";
	event_queue.push(setVisibleEvent(DICE_SCREEN));
	event_queue.push(fadeInEvent(DICE_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(functionEvent(dieRolling));
	nextEvent();
}

function dieRolling() {
	var obj = current_player.roll;
	if(obj.counter1 > 0) {
		//still animating one.
		obj.counter1--;
		if(obj.counter1 == 0) {
			//done with this one, set final
			//DIE_ONE.firstChild.nodeValue = obj.die1;
			setDieNode(DIE_ONE, obj.die1);
		} else {
			//scramble
			//DIE_ONE.firstChild.nodeValue = Math.floor(Math.random() * 6) + 1;
			setDieNode(DIE_ONE, Math.floor(Math.random() * 6) + 1);
		}
		
	} 
	if(obj.counter2 > 0) {
		//still animating two
		obj.counter2--;
		if(obj.counter2 == 0) {
			//done with this one, set final
			//DIE_TWO.firstChild.nodeValue = obj.die2;
			setDieNode(DIE_TWO, obj.die2);
		} else {
			//scramble
			//DIE_TWO.firstChild.nodeValue = Math.floor(Math.random() * 6) + 1;
			setDieNode(DIE_TWO, Math.floor(Math.random() * 6) + 1);
		}
	} 
	if(obj.counter2 <= 0 && obj.counter1 <=0) {
		//we're done!
		finishDieRoll();
		return;
	}
	die_timeout = window.setTimeout(dieRolling, DIE_ROLL_TIME * 1000);
}

function setDieNode(node, num) {
	num--;
	num *= -100;
	node.style.backgroundPosition = "0px " + num + "px";
}

function finishDieRoll() {
	event_queue.push(waitEvent(1.0));
	event_queue.push(fadeOutEvent(DICE_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(setInvisibleEvent(DICE_SCREEN));
	event_queue.push(functionEvent(moveSpaces));
	nextEvent();
}

function moveSpaces() {
	//moves the spaces in current_player.
	var oldLoc = current_player.position;
	var boardIndex = current_player.space;
	while(current_player.moves != 0 && boardIndex < (board.length - 1)) {
		if(current_player.moves > 0) {
			boardIndex++;
		} else {
			boardIndex--;
		}
		event_queue.push(moveEvent(current_player.node,oldLoc, board[boardIndex].offsetPosition(current_player.isHuman), DEFAULT_MOVE_TIME));
		event_queue.push(waitEvent(DEFAULT_FADE_TIME / 4));
		oldLoc = board[boardIndex].offsetPosition(current_player.isHuman);
		if(current_player.moves > 0) {
			current_player.moves--;
		} else {
			current_player.moves++;
		}
	}
	//set the player's current moves--ahead of time!
	current_player.space = boardIndex;
	current_player.position = board[boardIndex].offsetPosition(current_player.isHuman);
	event_queue.push(functionEvent(landedSpace));
	//done moving
	nextEvent();
}

function landedSpace() {
	//dice.resetMinMax(); // OVERRIDE
	if(current_player.space >= (board.length - 1)) {
		//they won!
		showWinScreen();
		
		// || dice.getResult() >= 6
	} else if(board[current_player.space].chance) { //show chance at least half the time. OVERRIDE
		//it's a chance card!
		showChance();
	} else {
		//just move to next player
		pickNextPlayer();
	}
}

function showWinScreen() {
	WIN_SCREEN.firstChild.firstChild.nodeValue = current_player.bigName() + " won!";
	event_queue.push(waitEvent(DEFAULT_FADE_TIME));//let people see that they won
	event_queue.push(setVisibleEvent(WIN_SCREEN));
	event_queue.push(fadeInEvent(WIN_SCREEN, DEFAULT_FADE_TIME));
	nextEvent();
	
}

function cleanUpPlayers() {
	//reset players for a new game (normaly behind the cover of showWinScreen)
	human.position = board[0].offsetPosition(human.isHuman);
	computer.position = board[0].offsetPosition(computer.isHuman);
	human.space = 0;
	computer.space = 0;
	human.turns = 0;
	computer.turns = 0;
	human.moves = 0;
	computer.moves = 0;
	human.node.style.left = "" + human.position.x + "px";
	human.node.style.top = "" + human.position.y + "px";
	computer.node.style.left = "" + computer.position.x + "px";
	computer.node.style.top = "" + computer.position.y + "px";
}
									

function hideWinScreen() {
	event_queue.push(fadeOutEvent(WIN_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(setInvisibleEvent(WIN_SCREEN));
	event_queue.push(functionEvent(showStartScreen));
	nextEvent();
}

function showChance() {
	if(current_player.isHuman) {
	event_queue.push(setVisibleEvent(CHANCE_PILE_SCREEN));
	event_queue.push(setInvisibleEvent(CHANCE_PICKED_SCREEN));
	event_queue.push(setVisibleEvent(PICK_CHANCE_SCREEN));
	event_queue.push(fadeInEvent(CHANCE_PILE_SCREEN, 0.001));
	event_queue.push(fadeInEvent(PICK_CHANCE_SCREEN,DEFAULT_FADE_TIME));
	} else {
		event_queue.push(setInvisibleEvent(CHANCE_PILE_SCREEN));
		event_queue.push(setVisibleEvent(PICK_CHANCE_SCREEN));
		event_queue.push(fadeInEvent(PICK_CHANCE_SCREEN,DEFAULT_FADE_TIME));
		pickChanceCard(0);
		return;
	}
	
	
	nextEvent();
	
	//alert("chance not implemented yet");
	//pickNextPlayer();
}

function pickChanceCard(num) {
	//the num is actually ignored.
	current_player.card = chance_stack.getCard();
	CHANCE_PICKED_SCREEN.firstChild.nodeValue = current_player.possessive() + " chance card is:";
	CHANCE_PICKED_SCREEN.childNodes[3].nodeValue = current_player.card.description;
	if(current_player.isHuman) {
		event_queue.push(fadeOutEvent(CHANCE_PILE_SCREEN,DEFAULT_FADE_TIME));
		event_queue.push(setInvisibleEvent(CHANCE_PILE_SCREEN));
	}
	event_queue.push(setVisibleEvent(CHANCE_PICKED_SCREEN));
	if(current_player.isHuman) {
	event_queue.push(fadeInEvent(CHANCE_PICKED_SCREEN,DEFAULT_FADE_TIME));
	} else {
		//come up with it
		event_queue.push(fadeInEvent(CHANCE_PICKED_SCREEN,.001));
	}
	nextEvent();
}

function hideChanceCard() {
	event_queue.push(fadeOutEvent(PICK_CHANCE_SCREEN, DEFAULT_FADE_TIME));
	event_queue.push(setInvisibleEvent(CHANCE_PICKED_SCREEN));
	event_queue.push(setInvisibleEvent(PICK_CHANCE_SCREEN));
	event_queue.push(functionEvent(interpretChanceCard));
	nextEvent();
	
}

function interpretChanceCard() {
	if(current_player.card && current_player.card.type == MOVE_CARD) {
		current_player.moves = current_player.card.amount;
		moveSpaces();
	} else if(current_player.card && current_player.card.type == TURN_CARD) {
		current_player.turns = current_player.card.amount;
		pickNextPlayer();
	} else {
		//oops!
		alert("Unknown chance card. stopping!");
	}
	
}

function pickNextPlayer() {
	//responsible for toggling the current character
	if(current_player.turns > 0) {
		//they have extra turns!
		//don't toggle
		current_player.turns--;
		insertAlert(current_player.bigName() + " " + current_player.has() + " an extra turn.");
		event_queue.push(functionEvent(startTurn));
		nextEvent();
		return;
	} 
	//toggle, start the loop to find the next player.
	current_player = current_player.other;
	while(true) {
		if(current_player.turns < 0) {
			//can't pick them! re-toggle!
			insertAlert(current_player.bigName() + " missed a turn.");
			current_player.turns++;
			current_player = current_player.other;
			continue;
		} 
		//okay, they should be fine to pick
		break;
	}
	event_queue.push(functionEvent(startTurn));
	nextEvent();
	return;
}




	

function loadChanceCards() {
	//make chance_stack a new ChanceStackController object
	//loop through, making cards and adding them to chance_stack
	chance_stack = new ChanceStackController();
	chance_stack.add(new ChanceCard(MOVE_CARD,5,"Move ahead five spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,3,"Move ahead three spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,3,"Move ahead three spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,3,"Move ahead three spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,3,"Move ahead three spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,1,"Move ahead one space."));
	chance_stack.add(new ChanceCard(MOVE_CARD,-5,"Move back five spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,-3,"Move back three spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,-3,"Move back three spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,-3,"Move back three spaces."));
	chance_stack.add(new ChanceCard(MOVE_CARD,-1,"Move back one space."));
	chance_stack.add(new ChanceCard(TURN_CARD,1,"Roll again!"));
	chance_stack.add(new ChanceCard(TURN_CARD,1,"Roll again!"));
	chance_stack.add(new ChanceCard(TURN_CARD,1,"Roll again!"));
	chance_stack.add(new ChanceCard(TURN_CARD,-1,"Miss a turn."));
	chance_stack.add(new ChanceCard(TURN_CARD,-1,"Miss a turn."));
	chance_stack.add(new ChanceCard(TURN_CARD,-2,"Miss two turns."));
}

function loadBoard() {
	//fills board with the spaces that make up board.
	//0
	board.push(new Space(42, 298,false));
	//1
	board.push(new Space(52, 252,false));
	//2
	board.push(new Space(79, 210,false));
	//3
	board.push(new Space(94, 174,false));
	//4
	board.push(new Space(123, 140,false));
	//5
	board.push(new Space(157, 112,false));
	//6
	board.push(new Space(196, 91,false));
	//7
	board.push(new Space(239, 76,false));
	//8
	board.push(new Space(283, 66,true));
	//9
	board.push(new Space(327, 58,false));
	//10
	board.push(new Space(372, 51,false));
	//11
	board.push(new Space(415, 45,false));
	//12
	board.push(new Space(461, 41,false));
	//13
	board.push(new Space(504, 38,true));
	//14
	board.push(new Space(550, 38,false));
	//15
	board.push(new Space(596, 40,false));
	//16
	board.push(new Space(641, 46,false));
	//17
	board.push(new Space(684, 57,false));
	//18
	board.push(new Space(725, 76,true));
	//19
	board.push(new Space(757, 101,false));
	//20
	board.push(new Space(768, 148,false));
	//21
	board.push(new Space(760, 197,false));
	//22
	board.push(new Space(728, 223,false));
	//23
	board.push(new Space(689, 245,true));
	//24
	board.push(new Space(647, 261,false));
	//25
	board.push(new Space(604, 275,false));
	//26
	board.push(new Space(561, 286,false));
	//27
	board.push(new Space(517, 294,false));
	//28
	board.push(new Space(472, 301,true));
	//29
	board.push(new Space(428, 305,false));
	//30
	board.push(new Space(383, 308,false));
	//31
	board.push(new Space(337, 308,false));
	//32
	board.push(new Space(292, 305,false));
	//33
	board.push(new Space(243, 297,false));
	//34
	board.push(new Space(223, 265,true));
	//35
	board.push(new Space(238, 224,false));
	//36
	board.push(new Space(284, 214,false));
	//37
	board.push(new Space(328, 210,false));
	//38
	board.push(new Space(375, 209,false));
	//39
	board.push(new Space(419, 209,false));
	//40
	board.push(new Space(464, 210,true));
	//41
	board.push(new Space(509, 210,false));
	//42
	board.push(new Space(554, 209,false));
	//43
	board.push(new Space(602, 204,false));
	//44
	board.push(new Space(644, 191,false));
	//45
	board.push(new Space(659, 150,true));
	//46
	board.push(new Space(630, 123,false));
	//47
	board.push(new Space(587, 111,false));
	//48
	board.push(new Space(540, 107,false));
	//49
	board.push(new Space(495, 106,false));
	//50
	board.push(new Space(449, 108,false));
	//51
	board.push(new Space(405, 112,false));
	//52
	board.push(new Space(360, 119,false));
	//53
	board.push(new Space(317, 129,true));
	//54
	board.push(new Space(274, 142,false));
	//55
	board.push(new Space(232, 157,false));
	//56
	board.push(new Space(192, 178,false));
	//57
	board.push(new Space(156, 205,true));
	//58
	board.push(new Space(129, 235,false));
	//59
	board.push(new Space(122, 284,false));
	//60
	board.push(new Space(130, 333,false));
	//61
	board.push(new Space(164, 355,true));
	//62
	board.push(new Space(208, 368,false));
	//63
	board.push(new Space(253, 373,false));
	//64
	board.push(new Space(298, 375,false));
	//65
	board.push(new Space(344, 374,false));
	//66
	board.push(new Space(388, 372,true));
	//67
	board.push(new Space(433, 369,false));
	//68
	board.push(new Space(477, 366,false));
	//69
	board.push(new Space(522, 363,false));
	//70
	board.push(new Space(566, 360,true));
	//71
	board.push(new Space(611, 357,false));
	//72
	board.push(new Space(657, 357,false));
	//73
	board.push(new Space(703, 360,false));
	//74
	board.push(new Space(749, 369,false));
	//75
	board.push(new Space(769, 406,true));
	//76
	board.push(new Space(747, 438,false));
	//77
	board.push(new Space(703, 451,false));
	//78
	board.push(new Space(657, 458,false));
	//79
	board.push(new Space(612, 461,false));
	//80
	board.push(new Space(567, 463,true));
	//81
	board.push(new Space(522, 463,false));
	//82
	board.push(new Space(477, 462,false));
	//83
	board.push(new Space(433, 460,false));
	//84
	board.push(new Space(388, 458,false));
	//85
	board.push(new Space(343, 455,false));
	//86
	board.push(new Space(299, 451,false));
	//87
	board.push(new Space(254, 447,false));
	//88
	board.push(new Space(210, 443,false));
	//89
	board.push(new Space(165, 438,false));
	//90
	board.push(new Space(121, 432,false));
	//91
	board.push(new Space(57, 426,false));
	
}

function startUp() {
	
	//check for ie
	var ua = window.navigator.userAgent.toLowerCase();
	if(ua.indexOf("opera") < 0 && ua.indexOf("msie") >= 0) {
		//it's ie, and probably not a poser like opera.
		//stop loading.
		return;
	}
	
	appendArrayMethods();
	
	START_SCREEN = document.getElementById("start-screen");
	PICK_CHARACTERS_SCREEN = document.getElementById("pick-characters-screen");
	PICK_CHARACTERS_CONTINUE_BUTTON = document.getElementById("hide-pick-characters-button");
	
	WIN_SCREEN = document.getElementById("win-screen");
	PICK_CHANCE_SCREEN = document.getElementById("pick-chance-screen");
	CHANCE_PILE_SCREEN = document.getElementById("chance-card-pile");
	CHANCE_PICKED_SCREEN = document.getElementById("chance-picked-screen");
	BOARD_SCREEN = document.getElementById("board");
	ALERT_SCREEN = document.getElementById("alert");
	ROLL_BUTTON = document.getElementById("roll-button");
	DICE_SCREEN = document.getElementById("dice-roll");
	DIE_ONE = document.getElementById("die1");
	DIE_TWO = document.getElementById("die2");
	PICK_HUMAN = document.getElementById("pick-human");
	PICK_COMPUTER = document.getElementById("pick-computer");
	//load up current_player, other_player.
	//load up dicecontrolelr into dice
	
	human = new Player();
	computer = new Player();
	human.isHuman = true;
	human.other = computer;
	computer.other = human;
	
	human.node = document.getElementById("human");
	computer.node = document.getElementById("computer");
	//hook up the nodes

	dice = new DiceController();

	loadChanceCards();
	loadBoard();
	cleanUpPlayers();
	
	event_queue.push(fadeOutEvent(document.getElementById("loading"),DEFAULT_FADE_TIME));
	event_queue.push(setInvisibleEvent(document.getElementById("loading")));
	event_queue.push(functionEvent(showStartScreen));
	nextEvent();
}



