//
//      ver 0.3 aug 2007, Gothenburg Sweden
//
//      ********************************************************************
//      * JAVASCRIPT CHESSPROGRAM (C)2007 ROBERT HUBER ALL RIGHTS RESERVED *
//      * INFORMATION ABOUT THIS SCRIPT:    http://www.javascriptchess.com *
//      ********************************************************************
//


var debug=0;

var cb_ = new Array(0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x21,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0);

var cb = new Array(0x24,0x22,0x28,0x23,0x2C,0x28,0x22,0x24,0,0,0,0,0,0,0,0,
                   0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0,0,0,0,0,0,0,0,
                   0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0,0,0,0,0,0,0,0,
                   0x14,0x12,0x18,0x13,0x1C,0x18,0x12,0x14,0,0,0,0,0,0,0,0);

var sei = new Array(0,0,256,0,512,0,0,0,768,0,0,0,1024,0,0,0,0);

var se = new Array(0,  0,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,// black
                   0,  0,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,// pawn
                  -4, -6,-12,-15,-15, -4, -6, -4,  0,0,0,0,0,0,0,0,
                  -4, -7,-18,-25,-25,-16, -7, -4,  0,0,0,0,0,0,0,0,
                  -6,-11,-18,-27,-27,-16,-11, -6,  0,0,0,0,0,0,0,0,
                 -10,-15,-24,-32,-32,-24,-15,-10,  0,0,0,0,0,0,0,0,
                 -50,-55,-64,-72,-72,-64,-55,-50,  0,0,0,0,0,0,0,0,
                   0,  0,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,

                   0,  0,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,// white
                  50, 55, 64, 72, 72, 64, 55, 50,  0,0,0,0,0,0,0,0,// pawn
                  10, 15, 24, 32, 32, 24, 15, 10,  0,0,0,0,0,0,0,0,
                   6, 11, 18, 27, 27, 16, 11,  6,  0,0,0,0,0,0,0,0,
                   4,  7, 18, 25, 25, 16,  7,  4,  0,0,0,0,0,0,0,0,
                   4,  6, 12, 15, 15,  4,  6,  4,  0,0,0,0,0,0,0,0,
                   0,  0,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   0,  0,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,

                   7,  3, -1, -3, -3, -1,  3,  7,  0,0,0,0,0,0,0,0,// black
                  -2, -6,-14,-20,-20,-14, -6, -2,  0,0,0,0,0,0,0,0,// knight
                  -6,-14,-22,-26,-26,-22,-14, -6,  0,0,0,0,0,0,0,0,
                  -8,-18,-26,-30,-30,-26,-18, -8,  0,0,0,0,0,0,0,0,
                  -8,-18,-30,-32,-32,-30,-18, -8,  0,0,0,0,0,0,0,0,
                  -6,-14,-28,-32,-32,-28,-14, -6,  0,0,0,0,0,0,0,0,
                  -2, -6,-14,-20,-20,-14, -6, -2,  0,0,0,0,0,0,0,0,
                   7,  3, -1, -3, -3, -1,  3,  7,  0,0,0,0,0,0,0,0,

                  -7, -3,  1,  3,  3,  1, -3, -7,  0,0,0,0,0,0,0,0,// white
                   2,  6, 14, 20, 20, 14,  6,  2,  0,0,0,0,0,0,0,0,// knight
                   6, 14, 28, 32, 32, 28, 14,  6,  0,0,0,0,0,0,0,0,
                   8, 18, 30, 32, 32, 30, 18,  8,  0,0,0,0,0,0,0,0,
                   8, 18, 26, 30, 30, 26, 18,  8,  0,0,0,0,0,0,0,0,
                   6, 14, 22, 26, 26, 22, 14,  6,  0,0,0,0,0,0,0,0,
                   2,  6, 14, 20, 20, 14,  6,  2,  0,0,0,0,0,0,0,0,
                  -7, -3,  1,  3,  3,  1, -3, -7,  0,0,0,0,0,0,0,0,

                   0,  0,  0, -3, -3,  0,  0,  0,  0,0,0,0,0,0,0,0,// black
                   2,  0,  0,  0,  0,  0,  0,  2,  0,0,0,0,0,0,0,0,// rook
                   2,  0,  0,  0,  0,  0,  0,  2,  0,0,0,0,0,0,0,0,
                   2,  0,  0,  0,  0,  0,  0,  2,  0,0,0,0,0,0,0,0,
                   2,  0,  0,  0,  0,  0,  0,  2,  0,0,0,0,0,0,0,0,
                   2,  0,  0,  0,  0,  0,  0,  2,  0,0,0,0,0,0,0,0,
                 -10,-10,-10,-10,-10,-10,-10,-10,  0,0,0,0,0,0,0,0,
                   0,  0,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,

                   0,  0,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,// white
                  10, 10, 10, 10, 10, 10, 10, 10,  0,0,0,0,0,0,0,0,// rook
                  -2,  0,  0,  0,  0,  0,  0, -2,  0,0,0,0,0,0,0,0,
                  -2,  0,  0,  0,  0,  0,  0, -2,  0,0,0,0,0,0,0,0,
                  -2,  0,  0,  0,  0,  0,  0, -2,  0,0,0,0,0,0,0,0,
                  -2,  0,  0,  0,  0,  0,  0, -2,  0,0,0,0,0,0,0,0,
                  -2,  0,  0,  0,  0,  0,  0, -2,  0,0,0,0,0,0,0,0,
                   0,  0,  0,  3,  3,  0,  0,  0,  0,0,0,0,0,0,0,0,

                 -16,-16,-16,-16,-16,-16,-16,-16,  0,0,0,0,0,0,0,0,// black
                 -26,-29,-31,-31,-31,-31,-29,-26,  0,0,0,0,0,0,0,0,// bishop
                 -26,-28,-32,-32,-32,-32,-28,-26,  0,0,0,0,0,0,0,0,
                 -16,-26,-32,-32,-32,-32,-26,-16,  0,0,0,0,0,0,0,0,
                 -16,-26,-32,-32,-32,-32,-26,-16,  0,0,0,0,0,0,0,0,
                 -16,-28,-32,-32,-32,-32,-28,-16,  0,0,0,0,0,0,0,0,
                 -16,-29,-31,-31,-31,-31,-29,-16,  0,0,0,0,0,0,0,0,
                 -16,-16,-16,-16,-16,-16,-16,-16,  0,0,0,0,0,0,0,0,

                  16, 16, 16, 16, 16, 16, 16, 16,  0,0,0,0,0,0,0,0,// white
                  16, 29, 31, 31, 31, 31, 29, 16,  0,0,0,0,0,0,0,0,// bishop
                  16, 28, 32, 32, 32, 32, 28, 16,  0,0,0,0,0,0,0,0,
                  16, 26, 32, 32, 32, 32, 26, 16,  0,0,0,0,0,0,0,0,
                  16, 26, 32, 32, 32, 32, 26, 16,  0,0,0,0,0,0,0,0,
                  26, 28, 32, 32, 32, 32, 28, 26,  0,0,0,0,0,0,0,0,
                  26, 29, 31, 31, 31, 31, 29, 26,  0,0,0,0,0,0,0,0,
                  16, 16, 16, 16, 16, 16, 16, 16,  0,0,0,0,0,0,0,0,

                   2,  2,  2,  0,  0,  2,  2,  2,  0,0,0,0,0,0,0,0,// black
                   0,  0, -1, -1, -1,  0,  0,  0,  0,0,0,0,0,0,0,0,// queen
                   0, -1, -1, -1, -1,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   0,  0,  0, -2, -2,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   0,  0,  0, -2, -2,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   2,  2,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   2,  2,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   2,  2,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,

                  -2, -2,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,// white
                  -2, -2,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,// queen
                  -2, -2,  0,  0,  0,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   0,  0,  0,  2,  2,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   0,  0,  0,  2,  2,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   0,  1,  1,  1,  1,  0,  0,  0,  0,0,0,0,0,0,0,0,
                   0,  1,  1,  1,  1,  0,  0,  0,  0,0,0,0,0,0,0,0,
                  -2, -2, -2,  0,  0, -2, -2, -2,  0,0,0,0,0,0,0,0);

var mv = new Array(0,   0,   0,     0,    0,0,0,0,    0,0,0,0,     0,0,0,0, 
                   0, 100, 300,  9999,  500,0,0,0,  300,0,0,0,  1000,0,0,0,
                   0,-100,-300, -9999, -500,0,0,0, -300,0,0,0, -1000,0,0,0,
                   0,   0,   0,     0,    0,0,0,0,    0,0,0,0,     0,0,0,0);

var moff = new Array(  0,  0, 32, 41, 13,  0,  0,  0, 18,  0,  0,  0, 23,
                      -1,  1,-16, 16,  0,
                     -17,-15, 15, 17,  0,
                      -1,  1,-16, 16,-17,-15, 15, 17,  0,
                     -33,-31,-14,-18, 14, 31, 33, 18,  0,
                      -1,  1,-15,-16,-17, 16, 15, 17,  0);

var adir = new Array(  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
                       4,  4,  8,  8,  0,
                       2,  1,  1,  2,  0,
                       4,  4,  8,  8,  2,  1,  1,  2,  0,
                       0,  0,  0,  0,  0,  0,  0,  0,  0,
                       0,  0,  0,  0,  0,  0,  0,  0,  0);

var pm = new Array(17,15,0);

var mstv= new Array(0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4);

var kingPosX = new Array(115,3);
//var kingPosX = new Array(101,87);

var ctm = new Array(128); // chess threat matrix
var cdtm = new Array(128); // chess dynamic threat matrix
var attackTable=new Array(2048); // 2*4*256
var evalPoints=new Array(200);

var pvlFr = new Array(20);
var pvlTo = new Array(20);
var pvlAlfa = new Array(20);

var m_stFr = new Array(500);
var m_stTo = new Array(500);
var m_moveType = new Array(500);
var m_moveSort = new Array(500);
var m_sp=0;

var lstCap=-1; // last capture
var enPas=-1; // en passant
var enPla=-1; // en passant player

var stFr = new Array(500);
var stTo = new Array(500);
var moveType = new Array(500);
var stackErased = new Array(500);
var stackPointer=0;
var whitePlayer=0;
var toggle=0, from; // note global
var Evalue=0;
var debugout="";
var bestMoveFrom=-1;
var bestMoveTo=-1;
var bestMoveAlfa=0;
var bestMoveLine="";
var kingThreat=0;
var check=false;
var kingPos=-1;
var lMoves;
var pattVal=0; // evalueringsfunktione returnerar vid patt

var buttonCtrlState=15;
var gameMode=0;
var movesWhite="<b>Vit</b><br><br>";
var movesBlack="<b>Svart</b><br><br>";
var moveRecord="";
var bestMoveWho="";
var computerMove=whitePlayer;

// Inledningsspelet (1-3 första dragen) 
// följer kända partier om möjligt
//
//
var openStr = new Array(

	// open games
	"e2e4e7e5", "Standardöppning",
	"e2e4e7e5g1f3b8c6f1b5", "Ruy Lopez",
	"e2e4e7e5g1f3b8c6c2c3", "Ponziani",
	"e2e4e7e5g1f3b8c6d2d4", "Scotch Game",
	"e2e4e7e5g1f3b8c6f1c4", "Italiensk öppning", 
	"e2e4e7e5g1f3b8c6f1c4c7c5", "Giuoco Piano",
	"e2e4e7e5g1f3b8c6f1c4c7c5b2b4", "William Davies Evans",
	"e2e4e7e5g1f3b8c6f1c4g8f6", "Två hästar",
	"e2e4e7e5g1f3b8c6f1c4f8e7", "Ungerskt försvar",
	"e2e4e7e5g1f3b8c6b1c3g8f6", "Fyra hästar",

	// semi-open games
	"e2e4d7d6d2d4g8f6b1c3g7g6","Pirc försvar", 

	// closed games
	"d2d4d7d5b1c3g8f6c1g5", "Richter-Veresov Attack",

	// indiska system
	"d2d4g8f6c2c4d7d6", "Gammalt indiskt försvar",
	"d2d4g8f6c2c4e7e5", "Budapest försvar",
	"d2d4g8f6c2c4e7e6g1f3f8b4", "Bogo-indiskt försvar",

	// övrigt
	"d2d4e7e6c2c4b7b6", "Engelskt försvar"

)

// Returnerar -1 om drag saknas
// dessutom sätts bestMoveFrom, bestMoveTo, bestMoveWho
//
function nextMoveLoopup(m)
{
	var tl="";
	lstr="hgfedcba";
	dstr="87654321";
	for (i=0;i<stackPointer;i++)
	{
		tl=tl+num2Note(stFr[i])+num2Note(stTo[i]);	
	}
	for (var i=0;i<openStr.length;i+=2)
	{
		ol=openStr[i];
		bestMoveWho="";
		if (ol.substr(0,tl.length)==tl)
		{
			if (ol.length>tl.length)
			{
				nmf=ol.substr(tl.length,2);
				nmt=ol.substr(tl.length+2,2);
				bestMoveFrom=lstr.indexOf(nmf.charAt(0))+
				              (dstr.indexOf(nmf.charAt(1)))*16;
				bestMoveTo  =lstr.indexOf(nmt.charAt(0))+
				              (dstr.indexOf(nmt.charAt(1)))*16;
				bestMoveWho=openStr[i+1];
				setText("kommentar",bestMoveWho);
				break;
			}
		}
	}
	return (bestMoveWho!="");
}

function displayMoves()
{	
	setText("moverecord",moveRecord);
}

function setCookie(name,value,days) 
{
	var date = new Date();
	date.setTime(date.getTime()+(days*24*60*60*1000));
	var expires = "; expires="+date.toGMTString();
	document.cookie = name+"="+value+expires+"; path=/";
}

function getCookie(name) 
{
	var cookiestring=""+document.cookie;
	var indexBegin=cookiestring.indexOf(name);
	if (indexBegin==-1 || name=="") return ""; 
	var indexEnd=cookiestring.indexOf(';',indexBegin);
	if (indexEnd==-1) indexEnd=cookiestring.length; 
	return unescape(cookiestring.substring(indexBegin+name.length+1,indexEnd));
}

function saveGame()
{
	alert('Spara partiet i en kaka - ej implementerat');
}

function updateControl(s)
{
	var ctrls="";
	if (s&1)
	{
		ctrls='<a href="javascript:javascript:undoMove(1);"><img src="buttons/back_en.gif" border=0 alt="Backa en ply"></a>&nbsp;';
	}
	else
	{
		ctrls='<img src="buttons/back_dis.gif" alt="Backa en ply" border=0>&nbsp;';
	}
	if (s&1)
	{
		ctrls=ctrls+'<a href="javascript:javascript:undoAllMove(1);"><img src="buttons/restart_en.gif" alt="Börja om" border=0></a>&nbsp;';
	}
	else
	{
		ctrls=ctrls+'<img src="buttons/restart_dis.gif" alt="Börja om" border=0>&nbsp;';
	}
	if (s&2)
	{
		ctrls=ctrls+'<a href="javascript:javascript:turnBoard(0);"><img src="buttons/turnboard_en.gif" alt="Byt sida" border=0></a>&nbsp;';
	}
	else
	{
		ctrls=ctrls+'<img src="buttons/turnboard_dis.gif" alt="Byt sida" border=0>&nbsp;';
	}
	if (s&1)
	{
//		ctrls=ctrls+'<a href="javascript:saveGame()"><img src="buttons/save_en.gif" alt="Spara partiet i en kaka" border=0></a>&nbsp;';
	}
	else
	{
//		ctrls=ctrls+'<img src="buttons/save_dis.gif" alt="Spara partiet i en kaka" border=0>&nbsp;';
	}

	ctrls=ctrls+'<a href="javascript:newStyle();"><img src="buttons/newstyle_en.gif"  alt="Byt stil på schackbrädan" border=0></a>&nbsp;';
	setText("buttons",ctrls);
}

var flashTimes;
function flashMove()
{
	// problemet med att räkna ut detta värde och utgå ifrån om det är schack är att det kan vara flera drag kvar innan schackmatt
	// men i kombination men med iterativ fördjupning kan man antaga att detta värde är rationellt
	var i,pla=(whitePlayer?0x10:0x20), mate=bestMoveAlfa>99999; //mate=(whitePlayer?bestMoveAlfa<-99999:bestMoveAlfa>99999);
	if (mate)
	{
		if (!computerMove) 
		{
			setText("kommentar","Schackmatt! Grattis! Bra spelat.");
		}
		else
		{
			setText("kommentar","Du är schackmatt. Jag vann!");
		}
		//return;
	}
	createBoard((flashTimes%2?-2:-1)); 
	if (--flashTimes>0)
	{
		setTimeout ("flashMove()", 200);
	}
	else
	{		
		if (stackPointer%2)
		{
			movesBlack=movesBlack+chessNote(bestMoveFrom,bestMoveTo)+"<br/>";
			moveRecord=moveRecord+" "+chessNote(bestMoveFrom,bestMoveTo)+"<br/>";
		}
		else
		{
			movesWhite=movesWhite+chessNote(bestMoveFrom,bestMoveTo)+"<br/>";
			moveRecord=moveRecord+eval(1+div(stackPointer,2))+". "+chessNote(bestMoveFrom,bestMoveTo);
		}
		computerMove=1-computerMove;
		doMove(bestMoveFrom,bestMoveTo,((cb[bestMoveFrom]&0x30)==0x10)?0:1,stackPointer);
		createBoard(-3); 
		buttonCtrlState|=1;
		updateControl(buttonCtrlState);
		displayMoves();
		for (i=0;i<128;i++)
		{
			if ((cb[i]&(0x03|pla))==(0x03|pla))
			{
				kingPos=i;
			}
		}
		if (mate)
		{
			return;
		}
		kingPos=kingPosX[1-whitePlayer];
		if (computerMove)
		{
			bestMoveWho="";
			if(isMate(1-whitePlayer))
			{
				setText("kommentar","Du vann. Schackmatt.");
				return;
			}
			if (isChecked(1-whitePlayer,kingPos))
			{				
				setText("kommentar","Hm Schack ... (tyst jag tänker)");
			}
			else
			{
				setText("kommentar","Min tur ... (tyst jag tänker)");
			}

			if (stackPointer<10)
			{
				nextMoveLoopup(0);
			}
			if (bestMoveWho!="")
			{
				bestMoveWho=bestMoveWho+". ";
				flashTimes=10;
				flashMove();
			}
			else
			{	
				setTimeout ("calcMove(0)", 0);
			}
		}
		else
		{
			kingPos=kingPosX[whitePlayer];
			if (isChecked(whitePlayer,kingPos))
			{
				bestMoveWho="Jag säger SCHACK! ";
			}

			if (debug)
			{
				setText("kommentar",bestMoveWho+"Din tur ... "+Evalue);
			}
			else
			{
				setText("kommentar",bestMoveWho+"Din tur ... ");	
			}
		}
	}
    //  setText("debugwindow","E="+Evalue+"<br>");

}


function turnBoard(m)
{
	whitePlayer=1-whitePlayer;
	computerMove=whitePlayer;
	if (whitePlayer)
	{
		setText("kommentar","Mitt drag ...");
		gameMode=1; // spel startat
		flashTimes=10;
		bestMoveFrom=99; // E2-E4
		bestMoveTo=99-32;
		flashMove();
	}
	else
	{
		createBoard(-3); 
	}
	buttonCtrlState&=13;
	updateControl(buttonCtrlState);
}

function newStyle()
{
	verBoard++;
	if(verBoard>7)
	{
		verBoard=4;
	}
	createBoard(-3);
}

function setup(m)
{
  createAttackTable(0);
  createBoard(-3);
  buttonCtrlState=14;
  updateControl(buttonCtrlState);
}

function createAttackTable(m)
{
	var b,w,t,p,w_bb,b_bb,w_iv,b_iv,black_bits,white_bits; 
	var mvl=new Array(0,100,300,0,500,0,0,0,1000,0,0,0,0,0,0,0);
	var mvl_cp=new Array(100,300,500,1000);
	var mvl_bp=new Array(0xFE,0xFD,0xFB,0xF7);
	for(col=0;col<2;col++)
	for(cp=0;cp<4;cp++)
	{
		//document.write("col:"+col+", p:"+cp+"   ---------------<br>");

		for(b=0;b<16;b++)
		for(w=0;w<16;w++)
		{
			w_bb=0xFF;
			b_bb=0xFF;
			w_iv=0;
			b_iv=0;
			p=0; //mvl_cp[cp];
			(col==0)?w_bb=mvl_bp[cp]:b_bb=mvl_bp[cp];
			(col==0)?w_iv=mvl_cp[cp]:b_iv=mvl_cp[cp];

			story='['+w_iv;

			black_bits=b;
			white_bits=w;

			for(iter=1;(iter<4);iter++)
			{
				if (col==1) 
				{
					for(t=1;t<16;t=t<<1)
					{
						if(w&t&w_bb&white_bits) // vit försvarar
						{
							p-=b_iv;
							story=story+","+eval(b_iv);
							w_iv=mvl[w&t];
							b_iv=0;
							white_bits^=t;
							t=16;
						}
					}
				}

				for(t=1;t<16;t=t<<1)
				{
					if(b&t&b_bb&black_bits) // svart attackerar
					{
						(col==0)?p-=w_iv:p+=w_iv;
						story=story+","+eval(-w_iv);
						b_iv=mvl[b&t];
						w_iv=0;
						black_bits^=t;
						t=16;
					}
				}

				if (col==0)
				{
					for(t=1;t<16;t=t<<1)
					{
						if(w&t&w_bb&white_bits) // vit försvarar
						{
							p+=b_iv;
							story=story+","+eval(b_iv);
							w_iv=mvl[w&t];
							b_iv=0;
							white_bits^=t;
							t=16;
						}
					}
				}

				if (((!black_bits)||(!white_bits))&&(iter<3))
				{
					iter=3;
				}
			}
			story=story+']';
			//document.write(dec2bin(w+(b*16))+"  "+p+"  "+story+"<br>");
			attackTable[w+(b*16)+(cp*256)+(col*1024)]=p;
		}
	}
}

function resetBoard(m)
{
	var i;
	for (i=0;i<500;i++)
	{
		evalPoints[i]=0;
		m_moveType[i]=0;
		m_moveSort[i]=0;
		moveType[i]=0;
		stackErased[i]=0;
		if(i<128)
		{
			ctm[i]=0;
			cdtm[i]=0;
		}
	}
	m_sp=0;
	for (i=0;i<128;i++)cb[i]|=0x40; // sätt N -biten ("Not moved")

// Testa best-line
//	pvlFr[0]=118;
//	pvlTo[0]=85;
}


function div(X, Y) 
{ 
	return Math.floor(X/Y)
}

function returnMoveStack(player)
{
	var i,p,pre,f,t,lr,kr,ms;
      pcs="  SKT   L   D";
	letters="hgfedcba";
	r="<b>"+(player==0?"Vit":"Svart")+"</b><br><br>";
	m_sp=0;
	generateMovelist(player,0);
	for(i=0;i<m_sp;i++)
	{
		f=m_stFr[i];
		t=m_stTo[i];
		ms=m_moveSort[i];
		kr=((f&0x0F)==3)&&((t&0x0F)==1);
		lr=((f&0x0F)==3)&&((t&0x0F)==5);
		if ((kr||lr)&&((cb[f]&0x0F)==0x03))
		{
			r=r+(kr?"0-0":"0-0-0");
		}
		else
		{
			if (ms>0)
			{	
				if (ms>190){r=r+"<font color=#0000AA>";}else{r=r+"<font color=#6666FF>";}
			}
			if (ms<0)
			{
				r=r+"<font color=silver>";
			}
			pre=pcs.charAt(cb[f]&0x0F);
			if (p=cb[t]&0x3F) // filtrera bort TN -biterna)
			{
				if (pre==" ")
				{
					pre=letters.charAt(f%8);
				}				
				pre=pre+"<font color=\"red\">x</font>";
			}
			y=div(t,16)+1;
			r=r+pre+letters.charAt(t%8)+y;
			if ((pre==" ")&&((f%8)!=(t%8))&&(!p))
			{
				r=r+"&nbsp;e.p.";
			}
			if (ms)
			{
				r=r+"<br/>("+ms+")</font>";
				//r=r+"</font>";

			}
		}
//		r=r+"<br/>"+m_stFr[i]+"-"+m_stTo[i];
		r=r+"<br/>";
	}
	return r;
}


function bms(start,stop)
{
	var temp,j, more=true;
	
	while(more)	
	{
		more=false;
		for (j=start+1;j<=stop;j++)
		if ((m_moveSort[j]>m_moveSort[j-1]))
		{
			more=true;
			temp=m_stFr[j];
			m_stFr[j]=m_stFr[j-1];
			m_stFr[j-1]=temp;
			temp=m_stTo[j];
			m_stTo[j]=m_stTo[j-1];
			m_stTo[j-1]=temp;
			temp=m_moveSort[j];
			m_moveSort[j]=m_moveSort[j-1];
			m_moveSort[j-1]=temp;
		}
	}
}

function refreshAttackValuePos(fpos,mode)
{
	var ix,kx,ox,top,i,j,ms,t,plm, attack_to, attack_fr, mpoint, ad, cp, wo=0, pvp=0, fromp;
	var m_spStart=m_sp;
	var pl_inv=0x20,pl2=0x60;
	var sc=-1;
	//debugout=debugout+"generate move:"+pl+"<br>";
	check=false;

	fromp=cb[fpos];

	if ((fromp&0x20)==0x20) // svart pjäs
	{
		sc=1;
		pl=0x20;
		plm=0x0F;
		pl_inv=0x10;
		pl2=0;
	}
	else
	{
		plm=0xF0;
		pl=0x10;
	}

	if (fromp&pl)
	{
		fromp&=0x0F;
		if (fromp==0x01) // bonde
		{
			ix=0;
			while (ox=(sc*pm[ix++]))
			{
				ox+=fpos;
				if (!(ox&0x88))
				{
					pvp=0;
					cdtm[ox]=0;   // nollställ här?
					ctm[ox]&=plm; // nollställ här?
					if (mode)
					{
						if (ox==enPas)
						{
							if (enPla==pl)
							{
								if (pl2)
								{
									ctm[ox]|=0x01;
								}
								else
								{
									ctm[ox]|=0x10;
								}
							}
						}

						top=cb[ox];

						if (pl2)
						{
							ctm[ox]|=0x01;
						}
						else
						{
							ctm[ox]|=0x10;
						}
					}
				}
			}
		}
		if (fromp&0x0E)
		{
			jx=moff[fromp&0x0F];
			while (t=moff[jx])
			{
				ix=1;
				ad=adir[jx];
				while (ix<8)
				{
					ox=fpos+ix*t;
					if (ox&0x88) break;                         // utanför spelplanen

					cdtm[ox]=0;   // nollställ här?
//					ctm[ox]&=plm; // nollställ här?

					if (pl2)
					{
						if ((fromp==0x02)||(fromp==0x08))
						{
							ctm[ox]&=0xFD;
						}
						if (fromp==0x04)
						{
							ctm[ox]&=0xFB;
						}
						if (fromp==0x0C)
						{
							ctm[ox]&=0xF7;
						}
//						cdtm[ox]|=ad;
					}
					else
					{
						if ((fromp==0x02)||(fromp==0x08))
						{
							ctm[ox]&=0xDF;
						}
						if (fromp==0x04)
						{
							ctm[ox]&=0xBF;
						}
						if (fromp==0x0C)
						{
							ctm[ox]&=0x7F;
						}
//						cdtm[ox]|=(ad*16); // optimera med shift-bit ??
					}


					if (mode)
					{					
						if (pl2)
						{
							if ((fromp==0x02)||(fromp==0x08))
							{
								ctm[ox]|=0x02;
							}
							if (fromp==0x04)
							{
								ctm[ox]|=0x04;
							}
							if (fromp==0x0C)
							{
								ctm[ox]|=0x08;
							}
							cdtm[ox]|=ad;
						}
						else
						{
							if ((fromp==0x02)||(fromp==0x08))
							{
								ctm[ox]|=0x20;
							}
							if (fromp==0x04)
							{
								ctm[ox]|=0x40;
							}
							if (fromp==0x0C)
							{
							ctm[ox]|=0x80;
							}
							cdtm[ox]|=(ad*16); // optimera med shift-bit ??
						}
					}


					top=cb[ox]&0x3F;                            // filtrera bort TN -bitarna
//					if (top&pl) break;              // kan inte slå ut egen pjäs
//					if (top&pl_inv) break;

					if (top) break;
					if (fromp&0x02) break;
					ix++;
				}
				jx++;
			}
		}
	}
}


function refreshAttackValue(pl,kpos)
{
	var t,jx, ix, ox;
	jx=13; //  13, där ligger först torn + 0 + löpare
	ctm[kpos]=0;
	plv=(pl?0x10:0x01);
	pla=(pl?0x10:0x20);
	while (t=moff[jx++])             // torn | drottning 's rörelser
	{
		ix=0;
		while(++ix<9)
		{
			ox=kpos+ix*t;
			if (ox&0x88) break;  // utanför spelplanen
			if ((cb[ox]&(0x04|pla))==(0x04|pla))     // torn | drottning
			{
				ctm[kpos]|=plv;
				return true;
			}
			if (cb[ox]&0x3F) break;
		}
	}
	while (t=moff[jx++])             // löpare | drottning's rörelser
	{
		ix=0;
		while(++ix<9)
		{
			ox=kpos+ix*t;
			if (ox&0x88) break;  // utanför spelplanen
			if ((cb[ox]&(0x08|pla))==(0x08|pla))     // löpare | drottning
			{
				ctm[kpos]|=plv;
				return true;
			}
			if (cb[ox]&0x3F) break;
		}
	}
	return false;
}

function isChecked(plg,kpos)
{
	var t,jx, ix, ox;
	jx=13; //  13, där ligger först torn + 0 + löpare
	ctm[kpos]=0;
	pla=(plg?0x20:0x10);
	// efter kpos inte verkar fungera löser vi det så här tills vidare
	for(iii=0;iii<128;iii++)
	{
		if ((cb[iii]&(0x03|pla))==(0x03|pla))
		{
			kpos=iii;
			iii=128;
		}
	}
	pla=(plg?0x10:0x20);
	while (t=moff[jx++])          // torn | drottning 's rörelser
	{
		ix=0;
		while(++ix<9)
		{
			ox=kpos+ix*t;
			if (ox&0x88) break;  // utanför spelplanen
			if ((cb[ox]&(0x04|pla))==(0x04|pla))     // torn | drottning
			{
				return true;
			}
			if (cb[ox]&0x3F) break;
		}
	}
	while (t=moff[jx++])        // löpare | drottning's rörelser
	{
		ix=0;
		while(++ix<9)
		{
			ox=kpos+ix*t;
			if (ox&0x88) break;  // utanför spelplanen
			if ((cb[ox]&(0x08|pla))==(0x08|pla))     // löpare | drottning
			{
				return true;
			}
			if (cb[ox]&0x3F) break;
		}
	}
	jx=32; // häst
	while (t=moff[jx++])       // häst
	{
		ox=kpos+t;
		if (!(ox&0x88))
		{
			if ((cb[ox]&(0x0F|pla))==(0x02|pla))     // häst 0x0F för att inte förväxlas med kung
			{
				return true;
			}
		}
	}
	while (t=moff[jx++])       // kung
	{
		ox=kpos+t;
		if (!(ox&0x88))
		{
			if ((cb[ox]&(0x03|pla))==(0x03|pla))     // kung
			{
				return true;
			}
		}
	}
	jx=0; // bonde för pm
	while (t=pm[jx++])       // bonde
	{
		ox=kpos+(plg?t:-t); // pl=0 då -t annars +t
		if (!(ox&0x88))
		{
			if ((cb[ox]&(0x01|pla))==(0x01|pla))     // bonde
			{
				return true;
			}
		}
	}
	return false;
}

function generateKillMovelist(pl__,dp)
{
	var ix,kx,ox,top,i,j,fpos=0,ms,t,pl__m, attack_to, attack_fr, mpoint, ad, cp, wo=0, pvp=0;
	var m_spStart=m_sp;
	var pl___inv=0x20,pl__2=0x60;
	var sc=-1;
	//debugout=debugout+"generate move:"+pl__+"<br>";

	if (pl__==1)
	{
		sc=1;
		pl__=0x20;
		pl__m=0x0F;
		pl___inv=0x10;
		pl__2=0;
	}
	else
	{
		pl__m=0xF0;
		pl__=0x10;
	}

	while (fpos<120)
	{
		cdtm[fpos]=0;
		ctm[fpos++]&=pl__m;
	}

	fpos=0;
	while (fpos<120)
	{
		if (fpos&0x88)
		{
			fpos+=8;
		}
		fromp=cb[fpos];
		if (fromp&pl__)
		{
			//tmv=mv[fromp&0x3F]/10; // this material value
			fromp&=0x0F;
			if (fromp==0x01) // bonde
			{
				ix=0;
				while (ox=(sc*pm[ix++]))
				{
					ox+=fpos;
					if (!(ox&0x88))
					{
						pvp=0;
						if (ox==enPas)
						{
							if (enpl__a==pl__)
							{
								if (pl__2)
								{
									ctm[ox]|=0x01;
								}
								else
								{
									ctm[ox]|=0x10;
								}
								m_stFr[m_sp]=fpos;
								m_stTo[m_sp]=ox;
								m_sp++;
							}
						}
	
						top=cb[ox];
	
						if (pl__2)
						{
							ctm[ox]|=0x01;
						}
						else
						{
							ctm[ox]|=0x10;
						}

						if (top&pl___inv)
						{
							m_stFr[m_sp]=fpos;
							m_stTo[m_sp]=ox;
							m_sp++;
						}
					}
				}
			}

			if (fromp&0x0E)
			{
				jx=moff[fromp&0x0F];
				while (t=moff[jx])
				{
					ix=1;
					ad=adir[jx];
					while (ix<8)
					{
						ox=fpos+ix*t;
						if (ox&0x88) break;                         // utanför spelpl__anen
						if ((ctm[ox]&pl__m)&&((fromp&0x03)==0x30)) break;   // kung rör sig mot hotad ruta

						top=cb[ox]&0x3F;                            // filtrera bort TN -bitarna
						pvp=0;
						if (pl__2)
						{
							if ((fromp==0x02)||(fromp==0x08))
							{
								ctm[ox]|=0x02;
							}
							if (fromp==0x04)
							{
								ctm[ox]|=0x04;
							}
							if (fromp==0x0C)
							{
								ctm[ox]|=0x08;
							}
							cdtm[ox]|=ad;
						}
						else
						{
							if ((fromp==0x02)||(fromp==0x08))
							{
								ctm[ox]|=0x20;
							}
							if (fromp==0x04)
							{
								ctm[ox]|=0x40;
							}
							if (fromp==0x0C)
							{
								ctm[ox]|=0x80;
							}
							cdtm[ox]|=(ad*16); // optimera med shift-bit ??
						}


						if (top&pl__) break;                          // kan inte slå ut egen pjäs
						if (top&pl___inv)
						{
							m_stFr[m_sp]=fpos;
							m_stTo[m_sp]=ox;
							m_sp++;
							break;
						}
						if (fromp&0x02) break;
						ix++;
					}
					jx++;
				}
			}
		}
		fpos++;
	}

	return(m_sp-m_spStart);
}

function generateMovelist(pl__,dp)
{
//	var ix,kx,ox,top,i,j,fpos=0,ms,t,pl__m, attack_to, attack_fr, mpoint, ad, cp, wo=0, pvp=0;
	var ix,kx,ox,oxk,jxk,tk,top,i,j,fpos=0,ms,t,pl__m, attack_to, attack_fr, mpoint, ad, cp, wo=0, pvp=0;
	var m_spStart=m_sp;
	var pl___inv=0x20,pl__2=0x60;
	var sc=-1;
	//debugout=debugout+"generate move:"+pl__+"<br>";
	check=false;

	if (pl__==1)
	{
		sc=1;
		pl__=0x20;
		pl__m=0x0F;
		pl___inv=0x10;
		pl__2=0;
	}
	else
	{
		pl__m=0xF0;
		pl__=0x10;
	}

	while (fpos<120)
	{
		cdtm[fpos]=0;
		ctm[fpos++]&=pl__m;
	}

	fpos=0;
	while (fpos<120)
	{
		if (fpos&0x88)
		{
			fpos+=8;
		}
		fromp=cb[fpos];
		if (fromp&pl__)
		{
			//tmv=mv[fromp&0x3F]/10; // this material value
			fromp&=0x0F;
			if (fromp==0x03) // kung, rockad
			{
				kingPos=fpos;

				//
				// står kungen på hotad ruta = CHECK
				// typ (behövs kingpos)
//				check = (ctm[kingPos]&pl__m)!=0;
				//if (check)alert('schack '+ctm[kingPos]);
	

				if (!(ctm[fpos]&pl__m))  // kung ej schackad
				{
					pvp=0;
					if ((!(ctm[fpos-2]&pl__m))&&(!(ctm[fpos-1]&pl__m))&&(!((cb[fpos-2]&0x3F)|(cb[fpos-1]&0x3F)))&&(cb[fpos-3]==(0x44|pl__))&&(cb[fpos]==(0x43|pl__)))
					{
						if ((pvlTo[dp]==ox)&&(pvlFr[dp]==fpos))
						{
							pvp=10000;
						}
						m_moveSort[m_sp]=500+pvp;
						m_stFr[m_sp]=fpos;
						m_stTo[m_sp]=fpos-2;
						m_sp++;
					}
					if ((!(ctm[fpos+1]&pl__m))&&(!(ctm[fpos+2]&pl__m))&&(!(ctm[fpos+3]&pl__m))&&(!((cb[fpos+1]&0x3F)|(cb[fpos+2]&0x3F)|(cb[fpos+3]&0x3F)))&&(cb[fpos+4]==(0x44|pl__))&&(cb[fpos]==(0x43|pl__)))
					{
						if ((pvlTo[dp]==ox)&&(pvlFr[dp]==fpos))
						{
							pvp=10000;
						}
						m_moveSort[m_sp]=500+pvp;
						m_stFr[m_sp]=fpos;
						m_stTo[m_sp]=fpos+2;
						m_sp++;
					}
				}
			}
			if (fromp==0x01) // bonde
			{
				ix=0;
				while (ox=(sc*pm[ix++]))
				{
					ox+=fpos;
					if (!(ox&0x88))
					{
						pvp=0;
						if (ox==enPas)
						{
							if (enpl__a==pl__)
							{
								if (pl__2)
								{
									ctm[ox]|=0x01;
								}
								else
								{
									ctm[ox]|=0x10;
								}
	
								if ((pvlTo[dp]==ox)&&(pvlFr[dp]==fpos))
								{
									pvp=10000;
								}
								m_moveSort[m_sp]=pvp;
								m_stFr[m_sp]=fpos;
								m_stTo[m_sp]=ox;
								m_sp++;
							}
						}
	
						top=cb[ox];
	
						if (pl__2)
						{
							ctm[ox]|=0x01;
						}
						else
						{
							ctm[ox]|=0x10;
						}

						if (top&pl___inv)
						{
							m_stFr[m_sp]=fpos;
							m_stTo[m_sp]=ox;
							ms=((lstCap==ox)?6000:mv[16+(cb[ox]&0xF)]);
							m_moveSort[m_sp]+=ms;
							m_sp++;
						}
					}
				}
				ox=fpos+16*sc;
				if (ox&0x88) break;

				top=cb[ox]&0x3F; // filtrera bort TN -biterna
				if (!top)
				{
					if ((pvlTo[dp]==ox)&&(pvlFr[dp]==fpos))
					{
						pvp=10000;
					}
					m_moveSort[m_sp]=pvp;
					m_stFr[m_sp]=fpos;
					m_stTo[m_sp]=ox;
					m_sp++;
				
					if ((fpos&0x60)==pl__2)
					{
						ox=fpos+32*sc;
						top=cb[ox]&0x3F; // filtrera bort TN -biterna					
						if (!top)
						{
							pvp=0;
							if ((pvlTo[dp]==ox)&&(pvlFr[dp]==fpos))
							{
								pvp=10000;
							}
							m_moveSort[m_sp]=pvp;
							m_stFr[m_sp]=fpos;
							m_stTo[m_sp]=ox;
							m_sp++;
						}
					}
				}
			}

			if (fromp&0x0E)
			{
				jx=moff[fromp&0x0F];
				while (t=moff[jx])
				{
					ix=1;
					ad=adir[jx];
					while (ix<8)
					{
						ox=fpos+ix*t;
						if (ox&0x88) break;                         // utanför spelpl__anen

// raden nedan ..
// kung rör sig mot hotad ruta OBS  fung. ej för kung då kung ej delar ut attackkvärde.
// denna finess går inte heller att använda om inte ctm uppdateras av doMove+undoMove

//						if ((ctm[ox]&pl__m)&&((fromp&0x03)==0x03)) break;   

// Kolla om kungen rör sig mot en ruta attackerad av kung. 

						if ((fromp&0x03)==0x03)
						{
							jxk=41; // index för kungen i moff
							while(tk=moff[jxk++])
							{
								oxk=tk+ox;
								if (((cb[oxk]&0x03)==0x03)&&(oxk!=fpos))
								{
									break;
								}								
							}
							if (tk) break;
						}


						top=cb[ox]&0x3F;                            // filtrera bort TN -bitarna
						pvp=0;
						if (pl__2)
						{
							if ((fromp==0x02)||(fromp==0x08))
							{
								ctm[ox]|=0x02;
							}
							if (fromp==0x04)
							{
								ctm[ox]|=0x04;
							}
							if (fromp==0x0C)
							{
								ctm[ox]|=0x08;
							}
							cdtm[ox]|=ad;
						}
						else
						{
							if ((fromp==0x02)||(fromp==0x08))
							{
								ctm[ox]|=0x20;
							}
							if (fromp==0x04)
							{
								ctm[ox]|=0x40;
							}
							if (fromp==0x0C)
							{
								ctm[ox]|=0x80;
							}
							cdtm[ox]|=(ad*16); // optimera med shift-bit ??
						}

						if (top&pl__) break;                          // kan inte slå ut egen pjäs

						if ((pvlTo[dp]==ox)&&(pvlFr[dp]==fpos))
						{
							pvp=10000;
						}
						m_moveSort[m_sp]=pvp;
						m_stFr[m_sp]=fpos;
						m_stTo[m_sp]=ox;
						if (top&pl___inv)
						{
							ms=((lstCap==ox)?6000:mv[16+(cb[ox]&0xF)]);
							m_moveSort[m_sp]+=ms;
							m_sp++;
							break;
						}
						m_sp++;
						if (fromp&0x02) break;
						ix++;
					}
					jx++;
				}
			}
		}
		fpos++;
	}
	wo=pl__2?0:1024;
	for (i=m_spStart;i<(m_sp-m_spStart);i++)
	{
		cp=mstv[cb[m_stFr[i]]&0xF]-1;
		if(cp>=0)
		{
			attack_to=ctm[m_stTo[i]];
			if (attack_to)
			{
				if (cb[m_stTo[i]]&0xF) // pjäs attackeras
				{	
					mpoint=attackTable[attack_to+cp*256+wo];
					m_moveSort[i]+=mpoint;
				}
				else
				{
					mpoint=attackTable[attack_to+cp*256+wo];
					m_moveSort[i]+=(mpoint/10);
				}
			}
		}
	}
	bms(m_spStart,m_sp-1);
// Tag bort alla drag med negativt värde
//	if (pl__==10)
//	{
//		while(m_moveSort[m_sp-m_spStart]<0)
//		{
//			m_sp--;
//		}
//	}

//	debugout=debugout+"P:"+pl__+"  :"+ctm[kingPos]+"-"+check+"<br>";

	return(m_sp-m_spStart);
}

function doMove(f,t,p,d)
{
	var tmp,cp, po=sei[cb[f]&0x0F]+(p?0:128);

	refreshAttackValuePos(f,0);

	moveType[stackPointer]=0;
	stFr[stackPointer]=f;
	stTo[stackPointer]=t;
	lstCap=((stackErased[stackPointer]=cb[t]&0x3F)?t:-1);
	enPas=-1;
	stackErased[stackPointer]|=cb[f]&0x40;

	evalPoints[stackPointer]=Evalue;

	Evalue=Evalue-mv[cb[t]&0x3F]-se[f+po]+se[t+po];
	//Evalue=Evalue-mv[cb[t]&0x3F];

	tmp=cb[t]=cb[f]&0xBF; // plocka bort N -biten
	cb[f]=0;

	if ((tmp&0x0F)==0x01) // bonde
	{
		if ((t+16)&0x88) // bondeförvanling till drottning
		{
			moveType[stackPointer]=cb[t]=0x2C;
			Evalue-=900;
		}
		if ((t-16)&0x88) // bondeförvanling till drottning
		{
			moveType[stackPointer]=cb[t]=0x1C;
			Evalue+=900;
		}
	}
	stackPointer++;
//	evalPoints[stackPointer]=Evalue;

	if ((tmp&0x0F)==3) // flyttar kung
	{
//		kingPos=t;
		kingPosX[p]=t;
		if (f==115)
		{
			if(t==(f-2))
			{
				moveType[stackPointer]=2;
				cb[f-1]=0x04|(cb[f-3]&0x30);
				cb[f-3]=0;
				stackPointer++;
			}
			if (t==(f+2))
			{
				moveType[stackPointer]=5;
				cb[f+1]=0x04|(cb[f+4]&0x30);
				cb[f+4]=0;
				stackPointer++;
			}
		}

		if (f==3)
		{
			if (t==(f-2))
			{
				moveType[stackPointer]=4;
				cb[f-1]=0x04|(cb[f-3]&0x30);
				cb[f-3]=0;
				stackPointer++;
			}
			if (t==(f+2))
			{
				moveType[stackPointer]=3;
				cb[f+1]=0x04|(cb[f+4]&0x30);
				cb[f+4]=0;
				stackPointer++;
			}
		}
	}

	// Svart bonde slår vit bonde - en passant
//	if (tmp==11)
//	{
//		stackErased[stackPointer]=cb[t+8];
//		cb[t+8]=0;
//		moveType[stackPointer]=1;
//		stTo[stackPointer]=t+8;
//		stackPointer++;
//	}
//	if (tmp==1)
//	{
//		stackErased[stackPointer]=cb[t-8];
//		cb[t-8]=0;
//		moveType[stackPointer]=1;
//		stTo[stackPointer]=t-8;
//		stackPointer++;
//	}
//
//	// Svart bonde skapar potentiell en passant
//	if ((f>=16)&&(f<=23)&&((t-f)==32))
//	{
//		enPas=f+16;
//		enPla=0x10;
//	}
//	// Vit bonde skapar potentiell en passant
//	if ((f>=96)&&(f<=103)&&((f-t)==32))
//	{
//		enPas=f-16;
//		enPla=0x20;
//	}

	refreshAttackValuePos(t,1);

//	debugout=debugout+"("+stackPointer+")"+eval(Evalue)+"<br>";
//	setText("debugwindow",debugout);
//	setText("eval","E= "+Evalue+ " poäng");

}


function undoMove(m)
{
	var f,t,mt;
	lstCap=-1;
	stackPointer--;
	mt=moveType[stackPointer];
	switch(mt)
	{
		case 1:
		{
			cb[stTo[stackPointer]]=stackErased[stackPointer];
			stackPointer--;
		}
		break;
		case 4:
		{
			cb[0]=0x24|0x40;
			cb[2]=0x40;
			stackPointer--;
		}
		break;
		case 3:
		{
			cb[7]=0x24|0x40;
			cb[4]=0x40;
			stackPointer--;
		}
		break;
		case 2:
		{
			cb[112]=0x14|0x40;
			cb[114]=0x40;
			stackPointer--;
		}
		break;
		case 5:
		{
			cb[119]=0x14|0x40;
			cb[116]=0x40;
			stackPointer--;
		}
		break;
	}
	f=stFr[stackPointer];
	t=stTo[stackPointer];

	cb[f]=cb[t]|(stackErased[stackPointer]&0x40);
	cb[t]=stackErased[stackPointer];

	if ((cb[f]&0x0F)==3) // flyttar (tillbaka) kung
	{
//		kingPos=f;
		kingPosX[cb[f]&0x10?0:1]=f;
	}

	switch(mt)
	{
		case 0x1C: // bondeförvanling
		{
			cb[f]=0x11;
		}
		break;
		case 0x2C: // bondeförvanling
		{
			cb[f]=0x21;
		}
	}
	Evalue=evalPoints[stackPointer];
	if (m==1) 
	{
		createBoard(-3);

		// ta bort ett drag i movesBlack/white
		// använd att det finns en <br> som separerar varje
		// drag och plocka bara bort sista i listan


		if ((whitePlayer)&&(stackPointer<1))
		{
			turnBoard(0);
			gameMode=0;
		}

		if (stackPointer<1)
		{
			movesWhite="<b>Vit</b><br><br>";
			movesBlack="<b>Svart</b><br><br>";
			moveRecord="";
			displayMoves();
			setText("kommentar","Byt sida eller gör ditt första drag");
			buttonCtrlState=14;
			kingPosX[0]=115;
			kingPosX[1]=3;
		}

		updateControl(buttonCtrlState);
	}

// Nedan är viktiga - men måste fungera rätt också om det ska vara ngn mening.	
//	refreshAttackValuePos(f,(cb[f]&0x0F)?1:0);
//	refreshAttackValuePos(t,1);


//	setText("movestack0",returnMoveStack(0));
//	setText("movestack1",returnMoveStack(1));

//	debugout=debugout+"("+eval(stackPointer)+")"+eval(Evalue)+"<br>";
//	setText("debugwindow",debugout);
//	setText("eval","E= "+Evalue+ " poäng");

}

function undoAllMove(m)
{
  undoMove(1);
  if (stackPointer>0)
  {
    setTimeout('undoAllMove(0)',250);
  }
}

function reduceStatEvalImpact()
{
	var i;
	for (i=256;i<1280;i++)
	{
		if (se[i]>0)
		{
			se[i]--;
		}
		if (se[i]<0)
		{
			se[i]++;
		}
	}
	Evalue=0;
	for (i=0;i<128;i++)
	{
		Evalue+=mv[cb[i]&0x3F]+se[  i+sei[cb[i]&0x0F] + ((cb[i]&0x20)?0:128)   ];
	}
}

function note(b)
{
  var to;
  toggle=1-toggle;
  buttonCtrlState&=13;
  if(toggle==1)
  {    
    if (cb[eval(b)]>0)
    {
      document.forms[0].from.value=b;
      from=eval(b);
      createBoard(from);
    }
    else
    {
      toggle=0;
    }
  }
  else
  {
    document.forms[0].to.value=b;
    to=eval(b);
    if (from!=to)
    {
	flashTimes=10;
	bestMoveFrom=from;
	bestMoveTo=to;
	flashMove();
	buttonCtrlState|=1;

//	generateMovelist(((cb[from]&0x30)==0x10)?0:1,0); // tillfällig ?
//    doMove(from,to,((cb[from]&0x30)==0x10)?0:1,0);
//	document.forms[0].undo.disabled=false;
//	document.forms[0].undoall.disabled=false;
    }
    else
    {
      toggle=0;
    }

// Nedan enbart för debug
//    if (!(cb[document.forms[0].to.value]&0x10))
//    {
//	generateMovelist(1,0);
//      setText("movestack0",returnMoveStack(0));
//    	setText("movestack1",returnMoveStack(1));
//    }
//    else
//    {
//	generateMovelist(0,0);
//  	setText("movestack1",returnMoveStack(1));
//      setText("movestack0",returnMoveStack(0));
//    }

    createBoard(-1);
    updateControl(buttonCtrlState);
  }
    //  setText("debugwindow","E="+Evalue+"<br>");

}


function dec2bin(num)
{
	tn = num;
	res="</font>";
	for (p = 0; p < 8; p++)
	{
		if (p==4)
		{
			res="</font><font color=red>"+res;
		}
		if (tn%2)
		{
			res= "1" +res;
			tn--;
		}
		else
		{
			res= "0" +res;
		}
		if (tn>0)
		{
			tn=div(tn,2);
		}
	}
	res="<font color=blue>"+res;
	return res;
}

var verBoard=4;


function createBoard(m)
{
	var r,img,color,toggle,num,letters, nrMoves=0, isLegalMove;
	toggle=whitePlayer;
	nrMoves=generateMovelist(whitePlayer,0);
	r="<table cellpadding=0 cellspacing=0>";
	if (!whitePlayer)
	{
		letters="ABCDEFGH";
	}
	else
	{
	letters="HGFEDCBA";
	}
	r=r+"<tr><td></td>";
	for (i=0;i<8;i++)
	{
		r=r+"<td align=\"center\">"+letters.charAt(i)+"</td>";
	}
	r=r+"</tr>"
	for (i=0;i<8;i++)
	{
		toggle=1-toggle;
		r=r+"<tr>";
		for (j=0;j<8;j++)
		{
			toggle=1-toggle;
			if (!whitePlayer)
			{
				num=8-i;
			      tp_=i*16+(7-j);
			}
			else
			{
				num=i+1;
			      tp_=(7-i)*16+j;
			}
			color=(!toggle?"#D0D0D0":"#FAFAFA");
			if (verBoard==5||verBoard==7)
			{
				color="#FFFFFF";
			}
		      if ((m==tp_)||((m==-2)&&((bestMoveFrom==tp_)||(bestMoveTo==tp_))))
		      {
				color=(verBoard==5?"#CCCCCC":"#AAFFFF");
		      }
		      if (j==0)
		      {
				r=r+"<td>"+num+"&nbsp;</td>"
		      }
		      r=r+"<td bgcolor=\""+color+"\" width=40 height=40>";
		      switch(cb[tp_]&0x3F)
		      {
		        case 0x11: img="w_pawn"; break;
		        case 0x14: img="w_rook"; break;
		        case 0x12: img="w_knight"; break;
		        case 0x18: img="w_bishop"; break;
		        case 0x1C: img="w_queen"; break;
		        case 0x13: img="w_king"; break;
		        case 0x21: img="b_pawn"; break;
		        case 0x24: img="b_rook"; break;
		        case 0x22: img="b_knight"; break;
		        case 0x28: img="b_bishop"; break;
		        case 0x2C: img="b_queen"; break;
		        case 0x23: img="b_king"; break;      
		        default: img="blank";
		      }    
			img = img + "_" + verBoard;
			if (verBoard==5||verBoard==7)
			{
				if (!toggle)
				{
		      	  img = img + "_b";
				}
		      	else
				{
		      	  img = img + "_w";
				}
			}
			img = img + ".gif";
			isLegalMove=false; // för debug sätt =true (alla drag okej)
						
			if (m>=0)
			{
				for (u=m_sp-nrMoves;(u<m_sp)&&(!isLegalMove);u++)
				{
					if (m_stFr[u]==m)
					{
						if (tp_==m_stTo[u])
						{
							isLegalMove=true;
						}
					}
				}
			}
			else
			{
				for (u=m_sp-nrMoves;(u<m_sp)&&(!isLegalMove);u++)
				{
					if (m_stFr[u]==tp_)
					{
						isLegalMove=true;				
					}
				}
			}

			if ((m==tp_)||(isLegalMove))
			{  
			      r=r+"<a href=\"javascript:note("+eval(tp_)+")\">";
		      	r=r+"<img src=\"img\/"+img+"\" width=40 alt=\""+m+"-"+tp_+"-"+isLegalMove+"\" height=40 border=0></a></td>";
			}
			else
			{
		      	r=r+"<img src=\"img\/"+img+"\" width=40 height=40 alt=\""+m+"-"+tp_+"-"+isLegalMove+"\"  border=0></td>";
			}
		}
		r=r+"</tr>";
	}
	r=r+"</table>"
	m_sp-=nrMoves; // korrigera för anropet till generateMoveList ovan.
	setText("board",r);
}




function setText(namn,txt)
{
  if (document.all)
  {
    document.all[namn].innerHTML=txt;
  }
  else if (document.layers)
  {
    document[namn].document.open();
    document[namn].document.write(txt);
    document[namn].document.close();
  }
  else if (document.getElementById)
  {
    document.getElementById(namn).innerHTML=txt;   
  }
}

// SEARCH FUNC. LAB BELOW.
//
// 

function div(X, Y) 
{ 
	return Math.floor(X/Y)
}

function num2Note(num)
{
	letters="hgfedcba";
	x=num%8;
	y=7-div(num,16)+1;
	xl=letters.charAt(x);	
	num++;
	ret=xl+y; //+"("+num+")";
	return ret;
}


function QSearch(depth, alfa, beta, tp, mdepth)
{
	var E, nrMoves, nrMovesMem, local_sp, es=(tp)%2;	
	E = es?-Evalue:Evalue;
	if (E >= beta)
	{
		return beta;
	}
	
	if (E > alfa)
	{
		alfa = E;
	}

	nrMoves=nrMovesMem=generateKillMovelist(tp,depth);
	local_sp=m_sp-nrMoves-1;
	while (nrMoves--)
	{
		local_sp++;
		doMove(m_stFr[local_sp],m_stTo[local_sp],tp,depth);
		E = es?-Evalue:Evalue;

//		id="Q";
//		for(di=0;di<(6-depth);di++){	id=id+"&nbsp;&nbsp;&nbsp;&nbsp;";	}
//		debugout=debugout+id+"P:"+tp+"  "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+"  ("+Evalue+")<br>";

//		if ((E < -alfa)&&(depth>-6))
//		{
//			E = -QSearch(depth - 1, -beta, -alfa, 1-tp, mdepth);
//		}		
		// kolla max 6 ply fram
		if (depth>-6)
		{
			E = -QSearch(depth - 1, -beta, -alfa, 1-tp, mdepth);
		}
		undoMove(0);
		if (E >= beta)
		{
//			debugout=debugout+id+"BETACUT_2: "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+"  ("+Evalue+","+E+","+alfa+","+beta+")<br/>";
			m_sp-=nrMovesMem;
			return beta;
		}	
		if (E > alfa)
		{
			alfa = E;
		}
	}
	m_sp-=nrMovesMem;
	return alfa;
}


function NegaMaxAlfaBeta(depth, alfa, beta, tp, mdepth)
{
	var E, nrMoves, nrMovesMem, local_sp, es=(tp)%2,t,bcheck, kingPosTemp,id;
	nrMoves=nrMovesMem=generateMovelist(tp,depth);

	local_sp=m_sp-nrMoves-1;
	lMoves=0;
	kingPos=kingPosX[tp];

	bcheck=isChecked(tp,kingPos); // schack före jag gör ett drag?

	while (nrMoves-->0)
	{
		local_sp++;
		doMove(m_stFr[local_sp],m_stTo[local_sp],tp,mdepth-depth);

		if (debug)
		{
			kingPosTemp=kingPos; // vid denna debug bara
			createBoard(0);
			kingPos=kingPosTemp;
			id="";
			for(di=0;di<(6-depth);di++){id=id+"&nbsp;&nbsp;&nbsp;&nbsp;";}
		}

		kingPos=kingPosX[tp];
		if (check=isChecked(tp,kingPos))
		{
			if (check&&debug)
			{
				debugout=debugout+id+"P:"+tp+"   CHECK (illegal move)  "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+"<br>";
			}

			// uppdatera om check fortfarande är sant - ett drag har ju gjorts
			while (check && (nrMoves-->0))
			{
				local_sp++;
				undoMove(0);

				doMove(m_stFr[local_sp],m_stTo[local_sp],tp,mdepth-depth);
				check=isChecked(tp,kingPos)
				if (debug)
				{
					if (check)
					{
						debugout=debugout+id+"P:"+tp+"   CHECK (illegal move,"+kingPos+")  "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+"<br>";
					}
					else
					{
						debugout=debugout+id+"P:"+tp+"  "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+"  ("+Evalue+")<br>";
					}
				}
			}
			if ((nrMoves<0)&&(lMoves==0))
			{
				undoMove(0);
				if (bcheck)
				{
					E = -100000-depth;
					if (debug)
					{
						debugout=debugout+id+"P:"+tp+"   ... CHECKMATE   NO LEGAL MOVE  <br>";
					}
				}
				else
				{
					E = -pattVal;
					if (debug)
					{
						debugout=debugout+id+"P:"+tp+"   ... DRAW!   NO LEGAL KING MOVE<br>";
					}
				}
				return E;
			}
			check=false;
		}
		else
		{
			if (debug)
			{
				debugout=debugout+id+"P:"+tp+"  "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+"  ("+Evalue+")<br>";
			}
		}
		lMoves++;

		if (depth==0)
		{
			bestMoveLine="";
			E = es?-Evalue:Evalue;
//			if (E > (alfa+99)) // så att enbart killermoves undersöks
//			{
//				E = -QSearch(depth - 1, -beta, -alfa, 1-tp, mdepth);
//				if (debug)
//				{
//					debugout=debugout+id+"P:"+tp+"   QSearch return "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+"  ("+E+")<br>";
//				}
//			}
//			else
//			{
//				E = alfa;
//			}
		}
		else
		{
			E = -NegaMaxAlfaBeta(depth - 1, -beta, -alfa, 1-tp, mdepth);
		}
		undoMove(0);
		if (E >= beta)
		{
			if (debug)
			{
				debugout=debugout+id+"BETACUT_2: "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+"  ("+Evalue+","+E+","+alfa+","+beta+")<br/>";
			}
			m_sp-=nrMovesMem;
			return beta;
		}	
		if (E > alfa)
		{
			pvlFr[mdepth-depth]=m_stFr[local_sp];
			pvlTo[mdepth-depth]=m_stTo[local_sp];
			pvlAlfa[mdepth-depth]=E;

			if (depth==mdepth) // startdraget
			{
				bestMoveFrom=m_stFr[local_sp];
				bestMoveTo=m_stTo[local_sp];
//				bestMoveAlfa=E; // behövs detta? Kaka på kaka då funktionen returnerar just detta.
				if (debug)
				{
					debugout=debugout+id+"bestmove_record("+local_sp+")("+depth+","+eval(local_sp)+")="+num2Note(bestMoveFrom)+"-"+num2Note(bestMoveTo)+"alfa= "+E+"<br/>";
				}
			}
			alfa = E;
		}
	}
	m_sp-=nrMovesMem;
	return alfa;
}

function isMate(tp)
{
	var E, nrMoves, nrMovesMem, local_sp, bcheck, ism=1;
	nrMoves=nrMovesMem=generateMovelist(tp,0);
	local_sp=m_sp-nrMoves-1;
	lMoves=0;
	kingPos=kingPosX[tp];
	bcheck=isChecked(tp,kingPos); // schack före jag gör ett drag?

	if(!bcheck)
	{
		return false;
	}

	while ((nrMoves-->0)&&ism)
	{
		local_sp++;
		doMove(m_stFr[local_sp],m_stTo[local_sp],tp,0);

		if (debug)
		{
			debugout=debugout+"<br>"+id+"P:"+tp+"  ISMATE-DOMOVE  "+num2Note(m_stFr[local_sp])+"-"+num2Note(m_stTo[local_sp])+" ("+Evalue+") ";
			setText("debugwindow",debugout);
		}

		kingPos=kingPosX[tp];
		if (!(check=isChecked(tp,kingPos)))
		{
			ism=0;
		}
		undoMove(0);
	}
	m_sp-=nrMovesMem;
	return ism;
}


function chessNote(f,t)
{
	var p,pre,f,t,lr,kr;
      pcs="  SKT   L   D";
	letters="hgfedcba";

	var r="";
	kr=lr=0;

	kr=((f&0x0F)==3)&&((t&0x0F)==1);
	lr=((f&0x0F)==3)&&((t&0x0F)==5);
	if ((kr||lr)&&((cb[f]&0x0F)==0x03))
	{
		r=r+(kr?"0-0":"0-0-0");
	}
	else
	{
		pre=pcs.charAt(cb[f]&0x0F);
		if (p=cb[t]&0x3F) // filtrera bort TN -biterna)
		{
			if (pre==" ") // bonde
			{
				pre=letters.charAt(f%8);
			}				
			pre=pre+"<font color=\"red\">x</font>";
		}
		y=8-div(t,16);
		r=r+pre+letters.charAt(t%8)+y;
		if ((pre==" ")&&((f%8)!=(t%8))&&(!p))
		{
			r=r+"&nbsp;e.p.";
		}
	}
 //     setText("debugwindow","E="+Evalue+"<br>");

	return r;
}

function calcMove(m)
{
	var p=1,t,maxDeep=2, ms_this, ms_start, ms_diff=0,i;
	p=1-whitePlayer;

	for (i=256;i<1280;i++)
	{
//		se[i]=0;
	}

	var d = new Date();
	ms_start=d.getSeconds(0);
	if (ms_start>30)
	{
		ms_start-=30;
		ms_diff=30;
	}
	
	if (debug)	
	{
		debugout=debugout+"calcMove() start..."+ms_start+"  E="+Evalue+"<br/>";
	}

	for (thisDepth=2;thisDepth<(maxDeep+1);thisDepth++)
	{
		m_sp=0;
		bestMoveAlfa=NegaMaxAlfaBeta(thisDepth, -999999, 999999,p,thisDepth);

		d = new Date();
		ms_this=d.getSeconds();
		ms_this-=ms_diff;

		if ((ms_this-ms_start)>40)
		{
			if (debug)
			{
				debugout=debugout+"time break..."+ms_this+"<br/>";
			}
			break;
		}
		if (debug)
		{
			debugout=debugout+"<br>pvline ("+thisDepth+"): ";
			for (t=0;t<thisDepth;t++)
			{
				debugout=debugout+num2Note(pvlFr[t])+"-"+num2Note(pvlTo[t])+" ("+pvlAlfa[t]+"),";
			}
			debugout=debugout+"<br>";
		}
	}

	if (debug)
	{
		setText("debugwindow",debugout);
	}

	flashTimes=10;
	flashMove();

//	debugout=debugout+"best move:"+num2Note(bestMoveFrom)+"("+bestMoveFrom+")-"+num2Note(bestMoveTo)+"("+bestMoveTo+") bestalfa="+bestMoveAlfa+"<br>";
//	for (thisDepth=0;thisDepth<maxDeep;thisDepth++)
//	{
//		debugout=debugout+num2Note(pvlFr[thisDepth])+"-"+num2Note(pvlTo[thisDepth])+" ("+pvlAlfa[thisDepth]+"),";
//	}
//	debugout=debugout+"  E="+Evalue+"<br>";

//	reduceStatEvalImpact();
////	reduceStatEvalImpact();
//	reduceStatEvalImpact();
}
