/* *	EXACHESS JAVASCRIPT FUNCTIONS FOR WEB EXPORT OF CHESS GAMES  v.3.1.1 *	Copyright (c) 2004 Exant Software / Rolf Exner  r.exner@exachess.com */var size = 32;var varparen = false;var endvar = "<br>";var repeatdelay = 800;var animate = true;var pieces = "PNBRQK";var posmsg = false;var gebi = document.getElementById;var games = new Array();function G(i,n,k) { games[i-1].Go(n,k); }function Ed(sq,s) { return ((((sq&7)+((s+18)&7)-2) & ~7) || ((((sq>>3)&7)+(((s+18)>>3)&7)-2) & ~7)); }function ChessGame (title,gametext){	this.index = games.length;	games[this.index] = this;	this.base = document.images.length;	this.repeat = 0;	this.timerId = 0;	this.anc = null;	this.ctr = 0;	this.bd = new Array();	this.boardDoc = this.movesDoc = document;	this.mvstr = new Array(); this.movNo = new Array(); this.nest = new Array();	this.pm = new Array(), this.pc = new Array(), this.pp = new Array();	this.sqf = new Array(), this.sqt = new Array(); this.psq = new Array();	this.next = new Array(); this.prev = new Array(); this.nvar = new Array();	this.Init = Init; this.Board = Board; this.Moves = Moves; this.Show = Show;	this.GetSqf = GetSqf; this.PutSq = PutSq; this.Go = Go; this.Move = Move;		this.title = (arguments.length == 1)? "" : title;	this.Init((arguments.length == 1)? title : gametext);}function Init (gametext){	this.result = "";	this.rev = this.movNo[0] = this.k = 0;	s = "";	var bkrk = new Array(4,2,3,5,6,3,2,4);	var subs = new Array(), kstk = new Array(), mstk = new Array();	var mstrs = gametext.split(" ");	str = mstrs[j=0];	for (sq = 0; sq < 64; sq++) 		this.bd[sq] = 0;	if (str.charAt(0) != '/')		for (sq = 0; sq < 8; sq++) {			this.PutSq(sq,bkrk[sq]); this.PutSq(sq+8, 1); 			this.PutSq(sq+48,7); this.PutSq(sq+56,bkrk[sq]+6);			}	else { //  /r3k2r/ppp2Npp/2n5/3Bpb2/4K2q/8/PPPP3P/RNB1Q2R w kq -/ 12 Ke3		for (j++, k = sq = 0; k < str.length && sq<64; k++, sq++) {			ix = ("12345678"+pieces+pieces.toLowerCase()+",w/").indexOf(str.charAt(k));			if (ix >= 0 && ix < 8) sq += ix;			else if (ix>=8 && ix < 20) this.PutSq (sq + 8*(7-2*(sq>>3)), ix-7);			else sq--;			}		s += str + " ";		while (j < mstrs.length && mstrs[j-1].charAt(mstrs[j-1].length-1) != '/')			s += mstrs[j++] + " ";		s += "<p>";		this.movNo[0] = 2 * (parseInt (mstrs[j]) - 1) + ((j>1 && mstrs[1] == 'b')? 1 : 0);		}		m = nest = lk = 0; k = 1; mn = this.movNo[0]+1; cmt = "";	while (j < mstrs.length && mstrs[j].length > 0) {		laststr = str;		if (m < subs.length)			str = subs[m++];		else {			str = mstrs[j++]; subs.length = 0;			for (m = 0; str.charAt(m) == "("; m++) subs[m] = "("; 			for (t = 0; (c=str.charAt(str.length-t-1)) == ")" || c==";"; t++);			if (m > 0 || t > 0) {				subs[m] = str.substring(m,str.length-t), m++;				while (t-- > 0) subs[m++] = str.charAt(str.length-t-1);				m = 0, str = subs[m++];				}			}		if (cmt.length > 0 || str.charAt(0) == "{") {			cmt += ((str==")" || laststr=="(")? "":" ") + str;			if (cmt.charAt (cmt.length-1) == '}')				s += (nest==0? endvar:"") + " <span class=com>" + cmt.substring (2, cmt.length-1) 					+ "</span> " + (nest==0?endvar:""), cmt = "";			}		else if (str == "(") {			kstk[nest] = lk; mstk[nest++] = mn--; lk = this.prev[lk];			comvar = nest==1 && laststr.substring(laststr.length-1,laststr.length) == "}";			if (comvar) s = s.substring(0,s.length-endvar.length);			s += (nest==1)? (comvar?"":endvar)+" <span class=var>"+(varparen?"(":"") : " (";			}		else if (str == ";") {			mn = mstk[--nest]; lk = kstk[nest];			kstk[nest] = lk; mstk[nest++] = mn--; lk = this.prev[lk];			s += ";";			}		else if (str == ")") {			mn = mstk[--nest]; lk = kstk[nest];			if (s.charAt(s.length-1) == ' ') s = s.substring(0,s.length-1);			s += (nest==0)? (varparen?")":"")+"</span>"+endvar : ")";			}		else if (str=="1-0" || str=="1/2" || str=="1/2-1/2" || str=="0-1") 			{ this.result = str; s += " " + str;}		else if ("1" <= (c1 = str.charAt(0)) && c1 <= "9") 			s += ((s.length==0 || s.charAt(s.length-1)=="(")? "":" ") + str;		else if ((c=str.charAt(0)) == "+" || c == "=" || c == "-")			s += ' ' + str;		else {			wtm = (mn&1)? 1:0; c = (wtm?0:6);			this.mvstr[k] = str;			len = str.length;			while ((c1=str.charAt(len-1))=='!' || c1=='?' || c1=='+' || c1=='#') 				str = str.substring(0,--len);			if (str.substring(0,3) == "0-0" || str.substring(0,3) == "O-O")				str = "K" + (len==3? "g":"c") + (wtm? "1":"8"), len=3;			pieceNames = " " + pieces;			if (str.charAt(len-2) == "=") 				this.pp[k] = pieceNames.indexOf(str.charAt(len-1)) + c, len-=2, str = str.substring(0,len);					this.sqt[k] = (((str.charCodeAt(len-1)-49)&7) << 3) + ((str.charCodeAt(len-2)-97)&7);			this.pm[k] = ((p = pieceNames.indexOf(str.charAt(0))) < 0? 1:p) + c;			m1 = p<0? 0:1;			m2 = len - 2 - ((len > 2 && ((c1=str.charAt(len-3)) == '-' || c1 == 'x'))? 1:0);			if (m1 == m2) this.sqf[k] = -256;			else {				r = (c1 = str.charCodeAt(m2-1)) <= 48+8? c1-49 : 0;				f = (c2 = str.charCodeAt(m1)) >= 97? c2-97 : 0;				this.sqf[k] = (r<<3) + f + (m1==m2-1? ((c1<=48+8? 128:64) - 256) : 0);				}			s += ' <a '+(!nest?'class=mv ':'class=v ')+				'id=G'+(this.index+1)+'_'+mn+(!nest?'':'_'+k)+' '+				'href="javascript:G('+(this.index+1)+','+mn+(!nest?'':','+k)+')">' 				+ this.mvstr[k] + '</a>';			if (!this.next[lk]) this.next[lk] = k; 			else { for (kv = this.next[lk]; this.nvar[kv]; kv = this.nvar[kv]); this.nvar[kv] = k; }			this.prev[k] = lk; this.next[k] = 0; this.movNo[k] = mn; this.nest[k] = nest; this.nvar[k] = 0;			lk = k; k++; mn++;			}		}	this.gamemoves = s;}function Board (rev){	s1 = this.boardDoc.URL; s2 = this.boardDoc.URLUnencoded; noframe = this.boardDoc==document;	if (s1.indexOf('/') > s1.indexOf('\\'))		path = s1.substring(0,s1.lastIndexOf("/")) + (noframe? "/s":"") + "/s" + size + "/";	else		path = s2.substring(0,s2.lastIndexOf("\\")) + (noframe? "\\s":"") + "\\s" + size + "\\";	if (arguments.length < 1) rev = false;	if (this.base == this.boardDoc.images.length) {		g = "games[" + this.index + "]";		str = "";		str += '<table border=1 bordercolor="black"><tr><td><div style="position:relative">'			+'<table background="'+path+'bg'+size+'.gif" width='+(8*size)+' height='+(8*size)			+' border="0" cellspacing="0" cellpadding="0"><tr><td>';		if (gebi) str += '<div id=anim_'+this.index+' style="position:absolute"><img src="'+path+'w'+size+'.gif" height='+size+' width='+size+'></div>';		for (i = 0; i < 64; i++)			str += ((i>0&&i%8==0)?'<br>':'')+'<img src="'+path+'w'+size+'.gif" height='+size+' width='+size+'>';		str += '</td></tr></table></div></td></tr></table>\n';		if (posmsg) str += "<FONT size=-1><br><SPAN id='lastmove'>Starting position<br></SPAN></FONT>";		str += '<p><form>' + (posmsg?'':'Position after: <input type="text" size="14" name="lastMv"><p>')		+'<input type="button" value="|&lt" onclick="'+g+'.Go(-1000)">'		//+'<input type="button" value=" &lt;&lt;" ondblclick="'+g+'.Go(-10)" onkeypress="'+g+'.Go(-10)" onclick="'+g+'.Go(-10)">'		+'<input type="button" value=" &lt; " onclick="'+g+'.Go(-1)" ondblclick="'+g+'.Go(-1)" onkeypress="'+g+'.Go(-1)">'		+'<input type="button" value=" * " name="go" onclick="'+g+'.Go(0,0)">'		+'<input type="button" value=" &gt; " onclick="'+g+'.Go(1)" ondblclick="'+g+'.Go(1)" onkeypress="'+g+'.Go(1)">'		//+'<input type="button" value=" &gt;&gt;" onclick="'+g+'.Go(10)" ondblclick="'+g+'.Go(10)" onkeypress="'+g+'.Go(10)">'		//+'<input type="button" value=" v " onclick="'+g+'.Go(1,-1)" ondblclick="'+g+'.Go(1,-1)">'		+'<input type="button" value="&gt|" onclick="'+g+'.Go(1000)">'		+'<input type="button" value=" rev" onclick="'+g+'.Board(1)">'		+'</form><p>';		this.boardDoc.write(str);		if (gebi) this.anim = this.boardDoc.getElementById("anim_"+this.index).style;		if (gebi) this.lastmove = document.getElementById("lastmove");		this.lastmv = this.boardDoc.forms[this.index].elements["lastMv"];		this.go = this.boardDoc.forms[this.index].elements["go"];		}	if (rev)		this.rev = !this.rev;	for (sq = 0; sq < 64; sq++)		this.PutSq (sq, this.bd[sq], 1);}function Moves(){	this.movesDoc.write("<span class=game>" + this.gamemoves + "</span><p>");	this.anc = null;}function Show(){	k = this.k; mn = this.movNo[k];	s = (k==0? "Starting position" : "Position after " + (1+((mn-1)>>1)) + " " + (((mn-1)%2)?"... ":" ") 		+ this.mvstr[k] + (!this.nest[k] && !this.next[k]? " "+this.result : ""));	if (this.lastmove) this.lastmove.firstChild.nodeValue = s;	if (this.lastmv) this.lastmv.value = (k==0? "" : (1+((mn-1)>>1)) + " " + (((mn-1)%2)?"... ":" ") 		+ this.mvstr[k] + (!this.nest[k] && !this.next[k]? " "+this.result : ""));	if (this.go) this.go.style.backgroundColor = this.repeat? "#A0A0A0" : "#FFFFFF";	if (this.anc) {this.anc.style.backgroundColor = "#FFFFFF"; this.anc = null; }	if (gebi) this.anc = this.movesDoc.getElementById("G"+(this.index+1)+"_"+mn+(!this.nest[k]?"":"_"+k)); 	if (this.anc) this.anc.style.backgroundColor = "#B0B0FF";}function GetSqf(){	var ss = new Array (-1,8,1,-8,7,9,-7,-9,6,15,17,10,-6,-15,-17,-10, 8,4,0,0,16,8,4,8);	k = this.k; mn = this.movNo[k];	wtm = (mn&1)? 1:0; c = wtm?0:6;	sqf = this.sqf[k]; sqt = this.sqt[k]; pm = this.pm[k];	this.pc[k] = this.bd[sqt];	if (pm == 1+c)		s = (wtm?-8:8), sqf = sqt + s + ((sqf&64)? ((sqf&7)<(sqt&7)?-1:1) : (this.bd[sqt+s]==0? s:0));	else if (pm == 6+c)		sqf = this.psq[pm];	else		for (h=ss[pm-c+14]; h < ss[pm-c+18] && sqf < 0; h++) {			for (sq = sqt+ss[h], s = ss[h]; !Ed(sq-s,s); sq+=s) {				if ((pce = this.bd[sq]) == pm 						&& (!(sqf&128)||(sq&56)==(sqf&56)) && (!(sqf&64)||(sq&7)==(sqf&7))) {					ksq = this.psq[6+c];					r = ((sq>>3)&7) - ((ksq>>3)&7); f = (sq&7) - (ksq&7);					s2 = ((r<0?-1:(r==0?0:1))<<3) + ((f<0?-1:(f==0?0:1)));					if ((r*f && f!=r && f!= -r) || s2 == s || s2 == -s) 						sqf = sq;					else {						for (sqi = ksq+s2; (sqi == sq || !this.bd[sqi]) && !Ed(sqi,s2); sqi += s2) ;						if (((p = this.bd[sqi]-6+c) != 5 && p != (r*f?3:4)) || s2<0&&sqi>sq || s2>0&&sqi<sq) sqf = sq;						}					}				if (sqf >= 0 || pce != 0 || pm == 2+c) break;				}			}	if (sqf < 0) sqf = -1, this.cnt = 0;	this.sqf[k] = sqf;	return sqf;}function PutSq(sq,pce,drawOnly){	if (pce<0||pce>12||sq<0||sq>(drawOnly?64:63)) return;	if (!drawOnly)		this.bd[sq] = pce, this.psq[pce] = sq;	i = (sq==64)? 0 : (gebi?1:0) + (this.rev? 8*(sq>>3)+7-(sq&7) : 56-8*(sq>>3)+(sq&7));	if (this.base < this.boardDoc.images.length)		this.boardDoc.images[this.base+i].src = path + (pce<7? "w":"b") + (pce?"pnbrqkpnbrqk".charAt(pce-1):"") + size + ".gif";}function Go(n,newk){	var trace = new Array();	mainline = true;	nargs = arguments.length;	if (nargs == 0 || (n == 0 && newk == 0 && !this.repeat))		this.repeat = n = nargs = 1;	else		{ if (this.repeat) clearTimeout (this.timerId); this.repeat = 0; this.Show(); }	if (this.ctr > 0 || (n == 0 && newk == 0 && !this.repeat)) 		return;		if (nargs == 1) {		if (n > 0 && (k2 = this.next[this.k]) == 0) { n = 0; this.repeat = 0 }		else if (n > 0 && this.next[k2] == 0) n = 1;		else if (n <= (b = this.movNo[0] - this.movNo[this.k])) n = b;		nb = (n<0)?-n:0, nf = (n>0)?n:0;		}	else if (!newk || k < 0) {		for (nb=nf=0, k = this.k; k > 0 && this.nest[k] > 0; nb++, k = this.prev[k]) ;		if (n >= (mn=this.movNo[k])) nf = n - mn; else nb -= n - mn;		}	else {		mainline = false;		if (newk == -1) { newk = this.nvar[this.k]; if (!newk) return; }		for (nf = nb = 0, k1 = this.k, k2 = newk; k1 != k2; )			if (this.movNo[k1] < this.movNo[k2]) trace[nf++] = k2, k2 = this.prev[k2];			else nb++, k1 = this.prev[k1]; 		}		this.ctr = (gebi && animate && nb+nf==1)? 1 : 0;	for (cnt = 0, nfi = nf; cnt < nb+nf && (cnt < nb || this.next[this.k]); cnt++) {		fwd = (cnt >= nb);		oldk = this.k;		this.k = fwd? (mainline? this.next[oldk] : trace[--nfi]) : this.prev[oldk];		this.Move (fwd, oldk);		}	this.Show();	if (this.repeat)		this.timerId = setTimeout ("games["+this.index+"].Go()", repeatdelay);}function Move(fwd,oldk){	k = fwd? this.k : oldk;	sqf = this.sqf[k]; if (sqf < 0) sqf = this.GetSqf();	sqt = this.sqt[k];		if (this.ctr > 0) {		a = fwd? sqf:sqt; b = fwd? sqt:sqf;		if (this.ctr == 1)			this.PutSq(a,0,1), this.PutSq(64,this.pm[k],1);		ax = size * (this.rev? 7-(a&7) : (a&7)); ay = size * (this.rev? (a>>3) : 7 - (a>>3));		bx = size * (this.rev? 7-(b&7) : (b&7)); by = size * (this.rev? (b>>3) : 7 - (b>>3));		if (this.anim) this.anim.left = (ax + ((this.ctr*(bx - ax))>>4)) +'px';		if (this.anim) this.anim.top = (ay + ((this.ctr*(by - ay))>>4)) +'px';		this.ctr++; if (this.ctr > 16) this.ctr = 0;		timerId = setTimeout ("games["+this.index+"].Move("+fwd+","+k+")", 8);		}	else {		pm = this.pm[k]; pc = this.pc[k];		wtm = (pm<=6)? 1:0; c = (wtm?0:6);		if (gebi) this.PutSq (64,0,1);		this.PutSq(sqf, fwd? 0:pm);		this.PutSq(sqt, fwd? pm:pc);		if (pm == 1+c && ((sqf&7) != (sqt&7)) && pc == 0)			this.PutSq(sqt-(wtm?8:-8), fwd? 0:7-c);		else if (pm == 1+c && (sqt>>3) == (wtm?7:0))			this.PutSq (fwd?sqt:sqf, fwd? this.pp[k] : pm);		else if (pm == 6+c && (sqt == sqf-2 || sqt == sqf+2)) {			this.PutSq (sqf+(sqf<sqt? 1:-1), fwd?pm-2:0);			this.PutSq (sqf+(sqf<sqt?3:-4), fwd?0:pm-2);			}		}}
