/**
 * O S k a t ( J S )
 * =================
 *
 * Copyright (c) 2004 Andre Gewert - agewert@foni.net
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * The card sets are taken from "kde-games", as included in Red Hat Linux 8.0,
 * and slightly modified. They are distributed under GPL, too.
 *
 * The toolbar icons are taken from KDE.
 *
 *------------------------------------------------
 * File ID		: $Id: oskat.js,v 1.5 2004/03/28 14:52:06 agewert Exp $
 * Revision		: $Revision: 1.5 $
 * Date			: $Date: 2004/03/28 14:52:06 $
 * Author		: $Author: agewert $
 *------------------------------------------------
 */

 	var gamerunning = false;
	var gameOver = false;
	var playerMoveFirst = false;
	var animateInfoText = false;
	var stack = Array();
	var pl_score = 0;
	var cp_score = 0;
	var pl_score2 = 0;
	var cp_score2 = 0;
	var trumpf = 0;
	
	var aniRunning = false;
	var aniCount = 0;
	var aniCount2 = 0;
	var aniId = '';
	var aniX = 0;
	var aniY = 0;
	var aniDx = 1;
	var aniDy = 1;
	var aniSteps = 15;
	var aniDelay = 50;
	var aniTarget = '';
	
	var round = 0;
	var scorelimit = 21;
	
	var computerShouldMove = false;
	var cards = Array();
	var cardpathprefix = 'cards';
	var cardpath = cardpathprefix + '/spaced';

	function showInfoScreen()
	{
		if (document.getElementById('infotable').style.display != 'block')
		{
			animateInfoText = true;
			document.getElementById('infotable').style.display = 'block';
			document.getElementById('infotext').style.top = '0px';
			window.setTimeout('infoAnim()', 2000);
		}
	}
	
	function infoAnim()
	{
		scrollMax = 150 -parseInt(document.getElementById('infotext').style.height);

		if (parseInt(document.getElementById('infotext').style.top) > scrollMax)
		{
			var newTop = parseInt(document.getElementById('infotext').style.top) -2;
			if (newTop < scrollMax) newTop = scrollMax;
			document.getElementById('infotext').style.top = String(newTop) +'px';
		}
		if (animateInfoText) window.setTimeout('infoAnim()', 50);
	}
	
	function setCardPath(newpath)
	{
		cardpath = cardpathprefix + '/' + newpath;
		for (var i = 0; i <= 15; i++)
		{
			document.getElementById('s' + String(i)).src = indexToFileName(fileNameToIndex(document.getElementById('s' +String(i)).src));
			document.getElementById('c' + String(i)).src = indexToFileName(fileNameToIndex(document.getElementById('c' +String(i)).src));
		}
		document.getElementById('m0').src = indexToFileName(fileNameToIndex(document.getElementById('m0').src));
		document.getElementById('m1').src = indexToFileName(fileNameToIndex(document.getElementById('m1').src));
	}

	function indexToFileName(cindex)
	{
		if (cindex == 0)
		{
			return(cardpath + '/' + 'empty.png');
		}
		else if (cindex == 255)
		{
			return(cardpathprefix + '/back/default.gif');
		}
		else
		{
			return(cardpath + '/' + String(cindex) + '.png');
		}
	}
	
	function colorIndexToFileName(cindex)
	{
		switch(cindex)
		{
			case 0:
				return('icons/pik.gif');
				break;
			case 1:
				return('icons/herz.gif');
				break;
			case 2:
				return('icons/kreuz.gif');
				break;
			case 3:
				return('icons/karo.gif');
				break;
			case 4:
				return('icons/grand.gif');
				break;
		}
	}

	function fileNameToIndex(fname)
	{
		if (result = fname.match(/default\.gif$/))
		{
			return(255);
		}
		else
		{
			if (result = fname.match(/\/?(\d+)\.png$/))
			{
				return(parseInt(RegExp.$1));
			}
			else
			{
				return(0);
			}
		}
	}
	
	function getCardFace(cindex)
	{
		while (cindex >= 14)
		{
			cindex = cindex -13;
		}
		return(parseInt(cindex));
	}
  
	function getCardColor(cindex)
	{
		var colorindex = 0;
		if (cindex > 13) { colorindex = 1; }
		if (cindex > 26) { colorindex = 2; }
		if (cindex > 39) { colorindex = 3; }
		return(parseInt(colorindex));
	}
	
	function isTrumpf(cindex)
	{
		if (cindex == 11 || cindex == 24 || cindex == 37 || cindex == 50) return(true);
		if (getCardColor(cindex) == trumpf) return(true);
		return(false);
	}

	function mixStack(max)
	{
		var pos1 = 0;
		var pos2 = 0;
		var i, dummy;
		
		for (i = 1; i <= 64; i++)
		{
			pos1 = Math.round(Math.random() *(max -1));
			pos2 = Math.round(Math.random() *(max -1));
			dummy = stack[pos1];
			stack[pos1] = stack[pos2];
			stack[pos2] = dummy;
		}
	}

	function randomTrumpf()
	{
		return(Math.round(Math.random() *4));
	}
	
	function countCards(stack)
	{
		var count = 0;
		for (var i = 0; i <= 15; i++)
		{
			if (getCardFace(fileNameToIndex(document.getElementById('s' + String(i)).src)) != 0) count++;
		}
		return(count);
	}
	
	function resetCards()
	{
		for (var i = 0; i <= 15; i++)
		{
			document.getElementById('s' + String(i)).style.display = 'inline';
			document.getElementById('c' + String(i)).style.display = 'inline';
		}
		document.getElementById('m0').src = indexToFileName(0);
		document.getElementById('m1').src = indexToFileName(0);
	}
	
	function getTarget()
	{
		if (getCardFace(fileNameToIndex(document.getElementById('m0').src)) == 0)
		{
			return('m0');
		}
		else
		{
			return('m1');
		}
	}
	
	function newRound()
	{
		for (var i = 7; i <= 13; i++)
		{
			stack[i -7] = i;
			stack[i] = i +13;
			stack[i +7] = i +26;
			stack[i +14] = i +39;
		}
		stack[28] = 1;
		stack[29] = 14;
		stack[30] = 27;
		stack[31] = 40;
		mixStack(32);
		
		for (i = 0; i <= 15; i++)
		{
			document.getElementById('s' + String(i)).src = indexToFileName(stack[i]);
			document.getElementById('c' + String(i)).src = indexToFileName(stack[i +16]);
		}
		resetCards();
		pl_score = 0;
		cp_score = 0;
		
		showScore();
		trumpf = randomTrumpf();
		showTrumpf(trumpf);
		
		round++;
		gamerunning = true;

		playerMoveFirst = !playerMoveFirst;
		if (playerMoveFirst)
		{
			document.getElementById('pl').style.border = 'solid 1px #aaaaaa';
			document.getElementById('cp').style.border = 'solid 1px #eeeeee';
		}
		else
		{
			document.getElementById('cp').style.border = 'solid 1px #aaaaaa';
			document.getElementById('pl').style.border = 'solid 1px #eeeeee';
			computerMove(getBestMove('c'));
		}
	}
	
	function startOskat()
	{
		round = 0;
		pl_score2 = 0;
		cp_score2 = 0;
		playerMoveFirst = false;
		newRound();
	}
	
	function closeScoreTable()
	{
		document.getElementById('scoretable').style.display = 'none';
		if (pl_score2 >= scorelimit || cp_score2 >= scorelimit)
		{
			if (confirm(lang['ask_new_game'])) startOskat();
		}
		else
		{
			newRound();
		}
	}
	
	function gameEnd()
	{
		gamerunning = false;
		pl_score2 = pl_score2 +getGameScore(pl_score);
		cp_score2 = cp_score2 +getGameScore(cp_score);
		showScore();
		if (pl_score2 >= scorelimit || cp_score2 >= scorelimit)
		{
			document.getElementById('scoretable_header').firstChild.nodeValue = String(lang['game_over']);
			document.getElementById('roundnr').firstChild.nodeValue = '';
		}
		else
		{
			document.getElementById('scoretable_header').firstChild.nodeValue = String(lang['round_over']);
			document.getElementById('roundnr').firstChild.nodeValue = ' (' + String(round) + ')';
		}
		document.getElementById('scoretable').style.display = 'block';
	}
	
	function showTrumpf(color)
	{
		document.getElementById('coloricon').src = colorIndexToFileName(color);
	}
	
	function showScore()
	{
		document.getElementById('plscore').firstChild.nodeValue = String(pl_score);
		document.getElementById('cpscore').firstChild.nodeValue = String(cp_score);
		document.getElementById('plscore2').firstChild.nodeValue = String(pl_score2);
		document.getElementById('cpscore2').firstChild.nodeValue = String(cp_score2);
		document.getElementById('plscore_table').firstChild.nodeValue = String(pl_score);
		document.getElementById('cpscore_table').firstChild.nodeValue = String(cp_score);
		document.getElementById('plscore2_table').firstChild.nodeValue = String(pl_score2);
		document.getElementById('cpscore2_table').firstChild.nodeValue = String(cp_score2);
	}
	
	function getCardIndex(stack, cindex)
	{
		return(fileNameToIndex(document.getElementById(String(stack) + String(cindex)).src));
	}
	
	function ownsColor(stack, color)
	{
		ret = false;
		for (var i = 0; i <= 15; i++)
		{
			if (cardIsOnTop(stack, i) && getCardFace(fileNameToIndex(document.getElementById(String(stack) + String(i)).src)) != 11 && getCardColor(fileNameToIndex(document.getElementById(String(stack) + String(i)).src)) == color)
			{
				return(true);
			}
		}
		return(false);
	}
	
	function ownsTrumpf(stack)
	{
		ret = false;
		for (var i = 0; i <= 15; i++)
		{
			if (cardIsOnTop(stack, i) && (getCardColor(getCardIndex(stack, i)) == trumpf || (getCardFace(getCardIndex(stack, i)) == 11)))
			{
				return(true);
			}
		}
		return(false);
	}
	
	/**
	 * @param	stack		String - 's' oder 'c'
	 * @param	cindex	Integer
	 * @return	boolean
	 */
	function cardIsOnTop(stack, cindex)
	{
		var card = document.getElementById(String(stack) + String(cindex));
		if (!card)
		{
			alert('Stack: ' + stack + ' - ' + cindex);
		}
		if (getCardFace(fileNameToIndex(card.src)) == 0) return(false);
		if (cindex > 7)
		{
			return (getCardFace(fileNameToIndex(card.src)) != 0);
		}
		else
		{
			card = document.getElementById(String(stack) + String(cindex +8));
			return (getCardFace(fileNameToIndex(card.src)) == 0);
		}
	}
	
	/**
	 * Checks if given card can be drawn
	 * @param		stack		
	 * @return		Boolean
	 */
	function isPossibleMove(stack, cindex)
	{
		if (getCardFace(fileNameToIndex(document.getElementById('m0').src)) != 0)
		{
			var playedCard = document.getElementById('m0');
			return(isPossibleMove2(stack, cindex, fileNameToIndex(playedCard.src)));
		}
		else
		{
			return(cardIsOnTop(String(stack), cindex));
		}
	}
	
	function isPossibleMove2(stack, cindex, card_one)
	{
		if (isTrumpf(card_one))
		{
			if (ownsTrumpf(stack))
			{
				return(cardIsOnTop(stack, cindex) && isTrumpf(getCardIndex(stack, cindex)));
			}
			else
			{
				return(cardIsOnTop(stack, cindex));
			}
		}
		else
		{
			if (ownsColor(stack, getCardColor(card_one)))
			{
				if (cardIsOnTop(String(stack), cindex))
				{
					return(getCardFace(getCardIndex(stack, cindex)) != 11 && getCardColor(getCardIndex(stack, cindex)) == getCardColor(card_one));
				}
				else
				{
					return(false);
				}
			}
			else
			{
				return(cardIsOnTop(String(stack), cindex));
			}
		}
	}
	
	function makeMove(cindex)
	{
		if (!gamerunning) return(false);
		if (aniRunning) return(false);
		if (isPossibleMove('s', cindex))
		{
			computerShouldMove = true;
			animateCard('s' + String(cindex), getTarget());
		}
		else
		{
			alert(lang['illegal_move']);
			return(false);
		}
	}
	
	/**
	 * @param	cindex	Card index
	 */
	function getCardValue(cindex)
	{
		cindex = getCardFace(cindex);
		switch(cindex)
		{
			case 1:
				return(11);
				break;
			case 10:
				return(10);
				break;
			case 11:
				return(2);
				break;
			case 12:
				return(3);
				break;
			case 13:
				return(4);
				break;
			default:
				return(0);
		}
	}
	
	/**
	 * Gets best possible move for one player
	 * Return the position of the best card.
	 * @param		stack		Stack/Player to be checked
	 * @return		Integer
	 */
	function getBestMove(stack)
	{
		var i;
		var highest_score = 0;
		var highest_pos = 16;
		var lowest_score = 0;
		var lowest_pos = 16;
		var card_one = fileNameToIndex(document.getElementById('m0').src);
		var card_cmp;
		
		var opp_stack = 'c';
		if (stack == 'c') opp_stack = 's';
		
		if (getCardFace(card_one) == 0)
		{
			// Copmuter makes first move
			for (i = 0; i <= 15; i++)
			{
				if (isPossibleMove(stack, i))
				{
					card_cmp = fileNameToIndex(document.getElementById(stack + String(i)).src);
					var opp_move = getBestMove2(opp_stack, card_cmp);
					var opp_card = fileNameToIndex(document.getElementById(opp_stack + String(opp_move)).src);
					if (isHigherCard(card_cmp, opp_card))
					{
						if (highest_pos > 15 || getCardValue(card_cmp) +getCardValue(opp_card) >= highest_score)
						{
							if (highest_pos > 15 || getCardValue(card_cmp) +getCardValue(opp_card) > highest_score || (getCardPrio(card_cmp) < getCardPrio(fileNameToIndex(document.getElementById(stack + String(highest_pos)).src))))
							{
								highest_score = getCardValue(card_cmp) +getCardValue(opp_card);
								highest_pos = i;
							}
						}
					}
					else
					{
						if (lowest_pos > 15 || (127 -getCardValue(card_cmp) -getCardValue(opp_card)) >= lowest_score)
						{
							if (lowest_pos > 15 || (127 -getCardValue(card_cmp) -getCardValue(opp_card)) > lowest_score || (getCardPrio(card_cmp) < getCardPrio(fileNameToIndex(document.getElementById(stack + String(lowest_pos)).src))))
							{
								lowest_score = 127 -getCardValue(card_cmp) -getCardValue(opp_card);
								lowest_pos = i;
							}
						}
					}	
				} // if possible move
			} // for i
			if (highest_pos < 16) return(highest_pos);
			return(lowest_pos);
		}
		else
		{
			return(getBestMove2(stack, card_one));
		}
	}
	
	/**
	 * Computes best move against another card
	 * @param	stack			Card stack to be checked ('s' = player, 'c' = computer)
	 * @param	card_one		First card
	 * @return	Integer		Best card
	 */
	function getBestMove2(stack, card_one)
	{
		var highest_score = 0;
		var highest_pos = 16;
		var lowest_score = 0;
		var lowest_pos = 16;

		var card_cmp;
		
		for (var i = 0; i <= 15; i++)
		{
			if (isPossibleMove2(stack, i, card_one))
			{
				card_cmp = fileNameToIndex(document.getElementById(stack + String(i)).src);
				if (!isHigherCard(card_one, card_cmp))
				{
					// Second card wins
					if (highest_pos > 15 || getCardValue(card_cmp) +getCardValue(card_one) >= highest_score)
					{
						if (highest_pos > 15 || getCardValue(card_cmp) +getCardValue(card_one) > highest_score || (getCardPrio(card_cmp) < getCardPrio(fileNameToIndex(document.getElementById(stack + String(highest_pos)).src))))
						{
							highest_score = getCardValue(card_cmp) +getCardValue(card_one);
							highest_pos = i;
						}
					}
				}
				else
				{
					// First card wins
					if (lowest_pos > 15 || (127 -getCardValue(card_cmp) -getCardValue(card_one)) >= lowest_score)
					{
						if (lowest_pos > 15 || (127 -getCardValue(card_cmp) -getCardValue(card_one)) > lowest_score || (getCardPrio(card_cmp) < getCardPrio(fileNameToIndex(document.getElementById(stack + String(lowest_pos)).src))))
						{
							lowest_score = 127 -getCardValue(card_cmp) -getCardValue(card_one);
							lowest_pos = i;
						}
					}
				}
			} // if possible move
		} // for i
		if (highest_pos < 16) return(highest_pos);
		return(lowest_pos);
	}
	
	function computerMove()
	{
		if (aniRunning)
		{
			window.setTimeout('computerMove()', aniDelay);
		}
		else
		{
			computerShouldMove = false;
			animateCard('c' + getBestMove('c'), getTarget());
		}
	}
	
	function animateCard(cid, tid)
	{
		var srcCard = document.getElementById(String(cid));
		var tgtCard = document.getElementById(String(tid));
		var aniCard = document.getElementById('aniCard');
		
		var targetx = parseInt(tgtCard.style.left);
		var targety = parseInt(tgtCard.style.top);

		aniId = cid;
		aniTarget = tid;
		aniX = parseInt(srcCard.style.left);
		aniY = parseInt(srcCard.style.top);
		aniDx = (targetx -aniX) / aniSteps;
		aniDy = (targety -aniY) / aniSteps;
		
		aniCard.src = srcCard.src;
		aniCard.style.left = aniX;
		aniCard.style.top = aniY;
		aniCard.style.display = 'inline';

		srcCard.style.display = 'none';
		
		aniRunning = true;
		posCard();
	}
	
	function posCard()
	{
		var aniCard = document.getElementById('aniCard');
		
		aniCard.style.top = Math.round(aniY +(aniDy *aniCount));
		aniCard.style.left = Math.round(aniX +(aniDx *aniCount));
		
		if (aniCount+1 < aniSteps)
		{
			// Naechsten Animationsschritt machen
			aniCount++;
			window.setTimeout('posCard()', aniDelay);
		}
		else
		{
			// Animation zu Ende
			var tgtCard = document.getElementById(String(aniTarget));
			var srcCard = document.getElementById(aniId);
			var movedCard = srcCard.id;
			tgtCard.src = srcCard.src;
			srcCard.src = indexToFileName(0);
			aniCount = 0;
			aniRunning = false;
			aniCard.style.display = 'none';
			var c1 = document.getElementById('m0');
			var c2 = document.getElementById('m1');
			if (getCardFace(fileNameToIndex(c1.src)) != 0 && getCardFace(fileNameToIndex(c2.src)) != 0)
			{
				// Zug Ende
				var computerIsWinner = isHigherCard(fileNameToIndex(c1.src), fileNameToIndex(c2.src));
				if (movedCard.charAt(0) == 'c') computerIsWinner = !computerIsWinner;
				
				if (computerIsWinner == true)
				{
					// Computer gewinnt den Stich
					cp_score += getCardValue(getCardFace(fileNameToIndex(c1.src)));
					cp_score += getCardValue(getCardFace(fileNameToIndex(c2.src)));
				}
				else
				{
					// Spieler gewinnt den Stich
					pl_score += getCardValue(getCardFace(fileNameToIndex(c1.src)));
					pl_score += getCardValue(getCardFace(fileNameToIndex(c2.src)));
				}
				c1.src = indexToFileName(0);
				c2.src = indexToFileName(0);
				showScore();
				if (countCards('s') == 0 && countCards('c') == 0)
				{
					gameEnd();
				}
				else
				{
					if (computerIsWinner == true)
					{
						document.getElementById('cp').style.border = 'solid 1px #aaaaaa';
						document.getElementById('pl').style.border = 'solid 1px #eeeeee';
						window.setTimeout('computerMove()', 10);
					}
					else
					{
						document.getElementById('pl').style.border = 'solid 1px #aaaaaa';
						document.getElementById('cp').style.border = 'solid 1px #eeeeee';
					}
				}
			}
			else
			{
				// Naechster Spieler macht Zug
				if (computerShouldMove)
				{
					computerShouldMove = false;
					document.getElementById('cp').style.border = 'solid 1px #aaaaaa';
					document.getElementById('pl').style.border = 'solid 1px #eeeeee';
					window.setTimeout('computerMove()', 10);
				}
				else
				{
					document.getElementById('pl').style.border = 'solid 1px #aaaaaa';
					document.getElementById('cp').style.border = 'solid 1px #eeeeee';
				}
			}
		}
	}
	
	/**
	 * Checks which card is the higher valued one
	 * Return TRUE if c1 is the higher one or FALSE
	 * if it is not.
	 * @param		c1				Card one (index)
	 * @param		c2				Card two (index)
	 * @return		Boolean
	 */
	function isHigherCard(c1, c2)
	{
		if (isTrumpf(c1))
		{
			// Trumpf gelegt
			if (isTrumpf(c2))
			{
				return(getTrumpfPrio(c1) > getTrumpfPrio(c2));
			}
			else
			{
				return(true);
			}
		}
		else
		{
			// Andere Farbe gelegt
			if (isTrumpf(c2))
			{
				// Trumpf gelegt
				return(false);
			}
			else
			{
				if (getCardColor(c1) == getCardColor(c2))
				{
					// Farbe bedient
					return(getCardPrio(c1) > getCardPrio(c2));
				}
				else
				{
					// Farbe nicht bedient
					return(true);
				}
			}
		}
	}
	
	function getTrumpfPrio(cindex)
	{
		if (getCardFace(cindex) == 11)
		{
			// Bube gelegt
			switch (getCardColor(cindex))
			{
				case 0:
					// Pik
					return(10); break;
				case 1:
					// Herz
					return(9); break;
				case 2:
					// Kreuz
					return(11); break;
				case 3:
					// Karo
					return(8); break;
			}
		}
		else
		{
			return(getCardPrio(cindex));
		}
	}
	
	function getCardPrio(cindex)
	{
		cindex = getCardFace(cindex);
		switch(cindex)
		{
			case 7:
				return(0); break;
			case 8:
				return(1); break;
			case 9:
				return(2); break;
			case 11:
				return(3); break;
			case 12:
				return(4); break;
			case 13:
				return(5); break;
			case 10:
				return(6); break;
			case 1:
				return(7); break;
			default:
				return(0);
		}
	}

	/**
	 * Gibt die Punkte zurück, die ein Spieler für diese Runde erhält
	 */
	function getGameScore(score)
	{
		if (score == 60)
		{
			return(1);
		}
		else if (score >= 61 && score <= 90)
		{
			return(2);
		}
		else if (score >= 91 && score <= 119)
		{
			return(3);
		}
		else if (score == 120)
		{
			return(4);
		}
		return(0);
	}

