topoffset=155;
leftoffset=100;
tileheight=41;
tilewidth=33;
tileoffset=10;
layeroffset=-4;
copytopoffset=486;
copyleftoffset=584;

var move;
n=144;

function UnCryptMailto(s) {	//
	var n=0;
	var r="";
	for(var i=0; i < s.length; i++) {
		n=s.charCodeAt(i);
		if (n>=8364) {n = 128;}
		r += String.fromCharCode(n-(1));
	}
	return r;
}

function linkTo_UnCryptMailto(s)	{	//
	location.href=UnCryptMailto(s);
}


function preload()
{
count=0;
image=new Array ('bg.jpg','bamb1.gif','bamb2.gif','bamb3.gif','bamb4.gif','bamb5.gif','bamb6.gif','bamb7.gif','bamb8.gif','bamb9.gif','circ1.gif','circ2.gif','circ3.gif','circ4.gif','circ5.gif','circ6.gif','circ7.gif','circ8.gif','circ9.gif','numb1.gif','numb2.gif','numb3.gif','numb4.gif','numb5.gif','numb6.gif','numb7.gif','numb8.gif','numb9.gif','wind1.gif','wind2.gif','wind3.gif','wind4.gif','drag1.gif','drag2.gif','drag3.gif','flow1.gif','flow2.gif','flow3.gif','flow4.gif','seas1.gif','seas2.gif','seas3.gif','seas4.gif','mark.gif','new.gif','restart.gif','undo.gif','moves.gif','hint.gif','help.gif','info.gif','email.gif');
picture=new Array(image.length);
for (i=0;i<image.length;i++)
{
picture[i]=new Image();
picture[i].onload=loadcheck;
picture[i].src=image[i];
}
}

function loadcheck()
{
count++;
if (count==1) 
{
display="<font style=\"font-family:Arial,sans-serif;font-size:14pt;white-space:nowrap;position:absolute;top:"+(topoffset)+";left:"+(leftoffset+tilewidth)+"\">Solitaire Mahjongg is loading...<\/font>";
document.getElementById("screen").innerHTML=display;
}
else if (count==image.length) setup();
}

function select(i,face)
{
i=i-120;
suggest=0;
test(i);
if (cond)
{
if (move==1)select2(i,face);
else select1(i,face);
}
else noselect();
}

function noselect()
{
message="Tile is not free!";
mark[k]="";
move=0;
show();
wait();
}

function nomatch()
{
message="Tiles are different!";
mark[k]="";
move=0;
show();
wait();
}

function equal()
{
message="No tile selected.";
mark[k]="";
move=0;
show();
wait();
}

function select1(i,face)
{
i1sto=i;
facesto=face;
message="Tile selected...";
k=i;
mark[k]="<a href=\"javascript:equal()\"><img src=\"mark.gif\" style=\"position:absolute;top:"+(offsetfact[k]*layeroffset+topoffset+tilefacty[k]*tileheight)+";left:"+(offsetfact[k]*layeroffset+leftoffset+tilefactx[k]*tilewidth)+"\" border=\"0\" alt=\"\"><\/a>";
move=1;
showhelp=0;
showinfo=0;
show();
}

function select2(i,face)
{
if (facesto!=face)nomatch();
else
{
i2sto=i;
ihistory[ihistory.length]=i1sto;
ihistory[ihistory.length]=i2sto;
tilehistory[tilehistory.length]=tile[i1sto];
tilehistory[tilehistory.length]=tile[i2sto];
tile[i1sto]=notile[i1sto];
tile[i2sto]=notile[i2sto];
message="Selected tiles match!";
mark[k]="";
move=0;
back++;
show();
counter-=2;
wait();
}
}

function shuffle()
{
randomnumber=new Array(n);
for (i=0;i<n;i++)
{
random=parseInt(Math.random()*(i+1));
randomnumber[i]=randomnumber[random];
randomnumber[random]=i;
}
}

function setup()
{
counter=n;
message="Game ready: "+n+" tiles are set up.";
move=0;
showhelp=0;
showinfo=0;
k=0;
suggest=0;
back=0;
tile=new Array(n);
notile=new Array(n);
mark=new Array(n);
value=new Array(n);
ihistory=new Array();
tilehistory=new Array();
fig=new Array(n);
tilevalue=new Array(10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,22,22,22,22,23,23,23,23,24,24,24,24,25,25,25,25,26,26,26,26,27,27,27,27,28,28,28,28,29,29,29,29,30,30,30,30,31,31,31,31,32,32,32,32,33,33,33,33,34,34,34,34,35,35,35,35,36,36,36,36,37,37,37,37,38,38,38,38,39,39,39,39,40,40,40,40,41,41,41,41,42,42,42,42,43,43,43,43,44,44,44,44,45,45,45,45);
tileface=new Array('circ1','circ1','circ1','circ1','circ2','circ2','circ2','circ2','circ3','circ3','circ3','circ3','circ4','circ4','circ4','circ4','circ5','circ5','circ5','circ5','circ6','circ6','circ6','circ6','circ7','circ7','circ7','circ7','circ8','circ8','circ8','circ8','circ9','circ9','circ9','circ9','bamb1','bamb1','bamb1','bamb1','bamb2','bamb2','bamb2','bamb2','bamb3','bamb3','bamb3','bamb3','bamb4','bamb4','bamb4','bamb4','bamb5','bamb5','bamb5','bamb5','bamb6','bamb6','bamb6','bamb6','bamb7','bamb7','bamb7','bamb7','bamb8','bamb8','bamb8','bamb8','bamb9','bamb9','bamb9','bamb9','numb1','numb1','numb1','numb1','numb2','numb2','numb2','numb2','numb3','numb3','numb3','numb3','numb4','numb4','numb4','numb4','numb5','numb5','numb5','numb5','numb6','numb6','numb6','numb6','numb7','numb7','numb7','numb7','numb8','numb8','numb8','numb8','numb9','numb9','numb9','numb9','wind1','wind1','wind1','wind1','wind2','wind2','wind2','wind2','wind3','wind3','wind3','wind3','wind4','wind4','wind4','wind4','drag1','drag1','drag1','drag1','drag2','drag2','drag2','drag2','drag3','drag3','drag3','drag3','seas1','seas2','seas3','seas4','flow1','flow2','flow3','flow4');
shuffle();
for (i=0;i<n;i++)
{
tile[i]="<a href=\"javascript:select("+(randomnumber[i]+120)+","+tilevalue[i]+")\"><img src=\""+tileface[i];
notile[i]="";
mark[i]="";
value[i]=(randomnumber[i]+120)*1000+tilevalue[i];
}
tile.sort();
value.sort();
tilepos=".gif\" style=\"position:absolute;top:";
offsetfact=new Array(4,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,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,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,0,0,0,0,0,0,0);
tilefacty=new Array(3.5,3,3,4,4,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3.5,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,3.5,3.5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7);
tilefactx=new Array(6.5,6,7,6,7,5,6,7,8,5,6,7,8,5,6,7,8,5,6,7,8,4,5,6,7,8,9,4,5,6,7,8,9,4,5,6,7,8,9,4,5,6,7,8,9,4,5,6,7,8,9,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,10,11,12,3,4,5,6,7,8,9,10,2,3,4,5,6,7,8,9,10,11,0,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,13,14,2,3,4,5,6,7,8,9,10,11,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11,12);
for (i=0;i<n;i++)
tile[i]=tile[i]+tilepos+(offsetfact[i]*layeroffset+topoffset+tilefacty[i]*tileheight)+";left:"+(offsetfact[i]*layeroffset+leftoffset+tilefactx[i]*tilewidth)+"\" border=\"0\" alt=\"\"><\/a>";
background="<img src=\"bg.jpg\" style=\"position:absolute;top:"+(topoffset-tileoffset)+";left:"+(leftoffset-tileoffset)+"\" alt=\"\">";
copyright="<font style=\"font-family:Arial,sans-serif;font-size:7pt;white-space:nowrap;position:absolute;top:"+copytopoffset+";left:"+copyleftoffset+"\">&copy; twb<\/font>";
menu="<br><a href=\"javascript:setup()\"><img src=\"new.gif\" border=\"0\" alt=\"\" title=\"Sets up new game\"><\/a><a href=\"javascript:restart()\"><img src=\"restart.gif\" border=\"0\" alt=\"\" title=\"Restarts same game\"><\/a><a href=\"javascript:undo()\"><img src=\"undo.gif\" border=\"0\" alt=\"\" title=\"Withdraws last move\"><\/a><a href=\"javascript:moves()\"><img src=\"moves.gif\" border=\"0\" alt=\"\" title=\"Displays number of possible moves\"><\/a><a href=\"javascript:hint()\"><img src=\"hint.gif\" border=\"0\" alt=\"\" title=\"Shows possible moves\"><\/a><a href=\"javascript:help()\"><img src=\"help.gif\" border=\"0\" alt=\"\" title=\"Displays rules of the game\"><\/a><a href=\"javascript:info()\"><img src=\"info.gif\" border=\"0\" alt=\"\" title=\"Displays game information\"><\/a><a href=\"javascript:linkTo_UnCryptMailto('nbjmup;benjoAnbikpohh/di');\"><img src=\"email.gif\" border=\"0\" alt=\"\" title=\"Sends email to the author\"><\/a>";
show();
wait();
}

function show()
{
for (i=0;i<n;i++)fig[i]=tile[i]+mark[i];
display="<font style=\"font-family:Arial,sans-serif;font-size:8pt;white-space:nowrap;position:absolute;top:"+(topoffset-50)+";left:"+(leftoffset+tilewidth)+"\"> <\/font>"+background+copyright+fig[57]+fig[58]+fig[59]+fig[60]+fig[61]+fig[62]+fig[63]+fig[64]+fig[65]+fig[66]+fig[67]+fig[68]+fig[69]+fig[70]+fig[71]+fig[72]+fig[73]+fig[74]+fig[75]+fig[76]+fig[77]+fig[78]+fig[79]+fig[80]+fig[81]+fig[82]+fig[83]+fig[84]+fig[85]+fig[86]+fig[87]+fig[88]+fig[89]+fig[90]+fig[91]+fig[92]+fig[93]+fig[94]+fig[95]+fig[96]+fig[97]+fig[98]+fig[99]+fig[100]+fig[101]+fig[102]+fig[103]+fig[104]+fig[105]+fig[106]+fig[107]+fig[108]+fig[109]+fig[110]+fig[111]+fig[112]+fig[113]+fig[114]+fig[115]+fig[116]+fig[117]+fig[118]+fig[119]+fig[120]+fig[121]+fig[122]+fig[123]+fig[124]+fig[125]+fig[126]+fig[127]+fig[128]+fig[129]+fig[130]+fig[131]+fig[132]+fig[133]+fig[134]+fig[135]+fig[136]+fig[137]+fig[138]+fig[139]+fig[140]+fig[141]+fig[142]+fig[143]+fig[21]+fig[22]+fig[23]+fig[24]+fig[25]+fig[26]+fig[27]+fig[28]+fig[29]+fig[30]+fig[31]+fig[32]+fig[33]+fig[34]+fig[35]+fig[36]+fig[37]+fig[38]+fig[39]+fig[40]+fig[41]+fig[42]+fig[43]+fig[44]+fig[45]+fig[46]+fig[47]+fig[48]+fig[49]+fig[50]+fig[51]+fig[52]+fig[53]+fig[54]+fig[55]+fig[56]+fig[5]+fig[6]+fig[7]+fig[8]+fig[9]+fig[10]+fig[11]+fig[12]+fig[13]+fig[14]+fig[15]+fig[16]+fig[17]+fig[18]+fig[19]+fig[20]+fig[1]+fig[2]+fig[3]+fig[4]+fig[0]+"<table width=\""+(tilewidth*12)+"\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"position:absolute;top:"+(topoffset+tileheight*9)+";left:"+(leftoffset+tilewidth)+"\"><tr><td style=\"font-family:Arial,sans-serif;font-size:14pt\"><br>"+message+"<\/td><\/tr><tr><td>"+menu+"<\/td><\/tr><\/table>";
document.getElementById("screen").innerHTML=display;
}

function wait()
{
showhelp=0;
showinfo=0;
if (counter!=0) message="Score: "+(n-counter);
else message="Score: "+(n-counter)+" &#150; congratulations! You win!";
setTimeout('show()',2000);
}

function help()
{
if (showhelp==0)
{
showhelp=1;
message="Solitaire Mahjongg, also called Taipei, Taipeh or Shanghai, is the web adaptation of an old Chinese board game. The objective is to remove all "+n+" tiles from the board; for each pair of tiles removed you will get two points.<p>Options:<p><ul><li>New: sets up a new game.<\/li><li>Restart: restarts the current game.<\/li><li>Undo: withdraws your moves one by one.<\/li><li>Moves: displays the number of currently possible moves.<\/li><li>Hints: shows currently possible moves one by one.<\/li><li>Help: displays the rules of the game.<\/li><li>Info: displays Solitaire Mahjongg game information.<\/li><li>Email: sends an email to the author.<\/li><\/ul><p>The rules are simple:<p>Starting from the sides, or from the central tile at the top of the pile, remove tiles by clicking on two equal symbols. If the tiles are identical, they will disappear, and your score will rise.<p>Selectable tiles always must have at least one empty side. If on both sides of a tile there is a neighbouring tile on the same level, it cannot be selected.<p><img src=\"seas1.gif\" alt=\"\"><img src=\"seas2.gif\" alt=\"\"><img src=\"seas3.gif\" alt=\"\"><img src=\"seas4.gif\" alt=\"\">&nbsp;&nbsp;<img src=\"flow1.gif\" alt=\"\"><img src=\"flow2.gif\" alt=\"\"><img src=\"flow3.gif\" alt=\"\"><img src=\"flow4.gif\" alt=\"\"><br>Note: The four tiles showing season symbols (above, left) match even if they are different; the four flower tiles (above, right) match respectively.";
suggest=0;
mark[k]="";
move=0;
show();
}
else
{
message="Back to the game.";
show();
wait();
}
}

function info()
{
if (showinfo==0)
{
showinfo=1;
message="In mathematical terms, Solitaire Mahjongg is easily described. There are 144!/(4!)<sup>36<\/sup> different games, the probability that you will encounter the same game twice is 1/1.1394912*10<sup>200<\/sup>. The number of games that actually can be won cannot be calculated exactly, yet experts estimate that good players win every third up to every second game.<p>This web version of Solitaire Mahjongg consists of two files coded in DHTML/CSS and Javascript. In addition, images are used for the tiles, buttons and game background. To play the game no plugins are needed. There are no special system requirements, except for a DHTML compatible browser. If the Javascript option is enabled, just surf and play.<p>The idea for this game came from the www.the5k.org competition first held in 2000, the objective of which it was to encourage lean, efficient, functional, original and aesthetic web programming. A <5kb version of Solitaire Mahjongg took part in the 2002  contest. We are re using the services of third party service providers to display advertisements on our website. These companies may under circumstance by setting up cookies use information about your visit on this site to display advertisements that suit your interests of products and services. The use of your name, your address, your email address or phone number will remain unaffected by these procedures. If you want to know how you can deactivate the setup of cookies please read the help section of your internet browser. If you would like to know more about the methods that are beeing used, please go to www.google.de/privacy_ads.html.<p>Solitaire Mahjongg v2.6<br>copyright &copy; by Thomas Weibel<br>4102 Binningen, Switzerland<p>Last update: November 5th, 2004";
suggest=0;
mark[k]="";
move=0;
show();
}
else
{
message="Back to the game.";
show();
wait();
}
}

function undo()
{
if (ihistory.length==0)
{
message="Undo not possible!";
suggest=0;
mark[k]="";
move=0;
show();
wait();
}
else
{
restore();
message="Move undone.";
suggest=0;
mark[k]="";
move=0;
back--;
show();
counter+=2;
wait();
}
}

function restart()
{
if (ihistory.length==0)
{
message="Restart not possible!";
suggest=0;
mark[k]="";
move=0;
show();
wait();
}
else
{
for (i=0;i<back;i++) restore();
message="Game restarted.";
suggest=0;
mark[k]="";
move=0;
back=0;
show();
counter=n;
wait();
}
}

function restore()
{
tile[ihistory[ihistory.length-1]]=tilehistory[tilehistory.length-1];
tile[ihistory[ihistory.length-2]]=tilehistory[tilehistory.length-2];
ihistory.length=ihistory.length-2;
tilehistory.length=tilehistory.length-2;
}

function moves()
{
suggest=0;
remain=0;
calc=new Array();
free=new Array();
for (i=0;i<n;i++)
{
remaining(i);
if (cond)
free[free.length]=calc[i];
}
free.sort();
for (i=0;i<(free.length-1);i++)
{
if (free[i]==free[i+1]&&free[i]==free[i+2]&&free[i]==free[i+3])
{
remain+=2; i+=3;
}
if (free[i]==free[i+1]&&free[i]==free[i+2])
{
remain++; i+=2;
}
if (free[i]==free[i+1])
{
remain++; i++;
}
}
if (remain==0) message="Game over: No moves left!";
else message="Possible moves: "+remain;
mark[k]="";
move=0;
show();
wait();
}

function hint()
{
if (suggest==0)
{
calc=new Array();
free=new Array();
hints=new Array();
for (i=0;i<n;i++)
{
remaining(i);
if (cond)
free[free.length]=calc[i]*1000+i;
}
free.sort();
for (i=0;i<(free.length-1);i++)
{
if (parseInt(free[i]/1000)==parseInt(free[i+1]/1000))
{
hints[hints.length]=free[i]-parseInt(free[i]/1000)*1000;
hints[hints.length]=free[i+1]-parseInt(free[i+1]/1000)*1000;
}
}
if (hints.length==0)
{
message="Game over: No moves left!";
suggest=0;
}
else
{
remainmsg();
suggest=1;
}
}
else if (suggest==1)
{
remainmsg();
}
move=0;
show();
mark[hints[0]]="";
mark[hints[1]]="";
mark[k]="";
hints[hints.length]=hints[0];
hints[hints.length]=hints[1];
for (i=0;i<hints.length-2;i++)
hints[i]=hints[i+2];
hints.length=hints.length-2;
wait();
}

function remaining(i)
{
calc[i]=value[i]-parseInt(value[i]/1000)*1000;
test(i);
}

function remainmsg()
{
message="Possible move";
mark[hints[0]]="<img src=\"mark.gif\" style=\"position:absolute;top:"+(offsetfact[hints[0]]*layeroffset+topoffset+tilefacty[hints[0]]*tileheight)+";left:"+(offsetfact[hints[0]]*layeroffset+leftoffset+tilefactx[hints[0]]*tilewidth)+"\" alt=\"\">";
mark[hints[1]]="<img src=\"mark.gif\" style=\"position:absolute;top:"+(offsetfact[hints[1]]*layeroffset+topoffset+tilefacty[hints[1]]*tileheight)+";left:"+(offsetfact[hints[1]]*layeroffset+leftoffset+tilefactx[hints[1]]*tilewidth)+"\" alt=\"\">";
}

function test(i)
{
lr=(tile[i-1]==notile[i-1]||tile[i+1]==notile[i+1]);
loop=new Array();
vari=new Array(10,11,14,15,28,29,30,31,34,35,36,37,40,41,42,43,46,47,48,49,70,71,72,73,74,75,79,80,81,82,83,84,91,92,93,94,95,96,103,104,105,106,107,108,116,117,118,119,120,121,125,126,127,128,129,130);
for (j=1;j<57;j++) loop[j]=(i==vari[j-1]&&(lr&&tile[j]==notile[j]));
cond=((i==0||i==5||i==8||i==9||i==12||i==13||i==16||i==17||i==20||i==21||i==26||i==27||i==32||i==33||i==38||i==39||i==44||i==45||i==50||i==51||i==56||i==57||i==68||i==69||i==76||i==77||i==86||i==87||i==113||i==114||i==123||i==124||i==131||i==132||i==143||
((i>=1&&i<=4)&&tile[0]==notile[0])||
((i==6||i==7||i==18||i==19||(i>=22&&i<=25)||(i>=52&&i<=55)||(i>=58&&i<=67)||i==78||i==85||(i>=88&&i<=90)||i==97||i==98||i==101||i==102||(i>=109&&i<=111)||i==115||i==122||i==133||(i>=134&&i<=142))&&lr)||
loop[1]||loop[2]||loop[3]||loop[4]||loop[5]||loop[6]||loop[7]||loop[8]||loop[9]||loop[10]||loop[11]||loop[12]||loop[13]||loop[14]||loop[15]||loop[16]||loop[17]||loop[18]||loop[19]||loop[20]||loop[21]||loop[22]||loop[23]||loop[24]||loop[25]||loop[26]||loop[27]||loop[28]||loop[29]||loop[30]||loop[31]||loop[32]||loop[33]||loop[34]||loop[35]||loop[36]||loop[37]||loop[38]||loop[39]||loop[40]||loop[41]||loop[42]||loop[43]||loop[44]||loop[45]||loop[46]||loop[47]||loop[48]||loop[49]||loop[50]||loop[51]||loop[52]||loop[53]||loop[54]||loop[55]||loop[56]||
(i==99&&(tile[98]==notile[98]||tile[112]==notile[112]))||
(i==100&&(tile[87]==notile[87]||tile[101]==notile[101]))||
(i==112&&((tile[99]==notile[99]&&tile[111]==notile[111])||tile[113]==notile[113])))&&
tile[i]!=notile[i]);
}
