// (c) Copyright 1997 - 2004, Wayne Davis. Author: Wayne Davis. Email:  wpdavis@ozemail.com.au  Date: Saturday, January 31, 1998 
cell = new Array(100); 
 choice = new Array(100);
 score = new Array(100);
 begin = new Array(100);
 rounds = new Array(100);
 Pbias = new Array(100);
 Tbias = new Array(100);
 Sbias = new Array(100);
 Rbias = new Array(100);
 age = new Array(100);
colour = new Array(255);
hex = new Array(15);

stop = false;	
index = 0;
row = 0;
col = 0;
active = 0;
timer1 = null;
timer2 = null;
 indexshow = 0;
subTotalRounds = 0;
lives = 0;
 playRounds = 25;
muteSize = 2;
hex[0] = "0";
hex[1] = "1";
hex[2] = "2";
hex[3] = "3";
hex[4] = "4";
hex[5] = "5";
hex[6] = "6";
hex[7] = "7";
hex[8] = "8";
hex[9] = "9";
hex[10] = "A";
hex[11] = "B";
hex[12] = "C";
hex[13] = "D";
hex[14] = "E";
hex[15] = "F";

for (sub = 0; sub <= 256; sub++) {
	colour[sub] = hex[(Math.floor(sub/16))%16] + hex[sub%16] ;
}

function reset () {
	if (active == 1){
		clearTimeout(timer1);
		alert("stopping simulation....");
	}
	stop = true;
	active = 0;
   	graph.focus();
}
				


function setCustomBias(custom){
	for (var sub=0; sub <= 100; sub++){
		if (custom.options[sub].selected) {
			return sub
		};
	}
	return sub;
}

function initialise(){
	if (active == 1){ alert("Cannot change as simulation is in progress") ; return;}
 
stop = false;	
index = 0;
row = 0;
col = 0;
active = 0;
timer1 = null;
timer2 = null;
 indexshow = 0;
totalRounds = 0;
lives = 1;
playRounds = 25;
muteSize = 2;
subTotalRounds = 0;

	for (index = 0; index < 100; index++){
	        cell[index] = 0;
		choice[index]=0;
		score[index] = 0;
		rounds[index] = 0
		begin[index] = 0;
		Pbias[index] = 0;
		Tbias[index] = 0;	
		Sbias[index] = 0;	
		Rbias[index] = 0;
		age[index] = 0;
	}

	// put in starting pattern

			cell[55] = 0.001;
			cell[56] = 0.001;
			Tbias[55] = setCustomBias(document.tally.custom1_t);
			Pbias[55] = setCustomBias(document.tally.custom1_p);
			Rbias[55] = setCustomBias(document.tally.custom1_r);
			Sbias[55] = setCustomBias(document.tally.custom1_s);
			begin[55] = setCustomBias(document.tally.custom1_b);
			Tbias[56] = setCustomBias(document.tally.custom2_t);
			Pbias[56] = setCustomBias(document.tally.custom2_p);
			Rbias[56] = setCustomBias(document.tally.custom2_r);
			Sbias[56] = setCustomBias(document.tally.custom2_s);
			begin[56] = setCustomBias(document.tally.custom2_b);
			if (document.tally.evo[0].checked) {muteSize = 2; playRounds = 25;}
			if (document.tally.evo[1].checked) {muteSize = 10; playRounds = 5;}
}

function graphIt(){
	graph=window.open("","graph","toolbar=no,directories=no,height=300,width=250,status=no,tscrollbars=yes,resize=yes,menubar=yes");
	graph.document.open();
	graph.document.write('<HTML><HEAD><title>Prisoner\'s Dilemma: Evolution Simulator</title></HEAD>');
	graph.document.write('<body text=\"#F03030\" background=\"whtsand.jpg\"><center>\n');
	graph.document.write('<TABLE border=0 cellpadding=3 cellspacing=1>\n');
	for (row = 10; row < 100; row += 10){
		graph.document.write("<TR><TH align=left  nowrap><FONT SIZE=-1>" + row + "</TH>"); 
		for (col = 1; col <= 9; col++){	
			
			 if (cell[row+col] > 0){	
				T = colour[Math.round((Tbias[row + col])* 2.55)];
				P = colour[Math.round((Pbias[row + col])* 2.55)];
				R = colour[Math.round((Rbias[row + col])* 2.55)];
				S = colour[Math.round((Sbias[row + col])* 2.55)];
				if (Sbias[row + col] < 20) {
					graph.document.write("<TH bgcolor=\'#" + T + P + R +"\'>&nbsp; &nbsp;</TH>"); 
				}
				else { 
					if (Sbias[row + col] < 40) {
						graph.document.write("<TH bgcolor=\'#" + T + P + R +"\'>.&nbsp;</TH>"); 
					}
					else {
						if (Sbias[row + col] < 60) {
							graph.document.write("<TH bgcolor=\'#" + T + P + R +"\'>:&nbsp;</TH>"); 
						}
						else {
                                                                                        if (Sbias[row + col] < 80) {
							graph.document.write("<TH bgcolor=\'#" + T + P + R +"\'>:.</TH>"); 
						        	}
						         else {
							    graph.document.write("<TH bgcolor=\'#" + T + P + R +"\'>::</TH>"); 
						  	}
						  }
					}
				}
			}
			else {
				graph.document.write("<TH>&nbsp; &nbsp;</TH>"); 
			}
		}
		graph.document.write("</TR>\n");
	} 	
	graph.document.write("<TR><TH colspan=1 align=right><FONT SIZE=-1>&nbsp;</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>1</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>2</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>3</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>4</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>5</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>6</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>7</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>8</TH>");
	graph.document.write("<TH colspan=1 align=right><FONT SIZE=-1>9</TH></TR></TABLE>");
	graph.document.close();
	
}


function playIPD(i){
	choice[index] = begin[index];
	choice[i] = begin[i];
	for (interact = 1; interact <= playRounds; interact++) {
		 rounds[index]++;
		 rounds[i]++;
		 if (choice[i] == 1) {
			if (choice[index] == 1) {
				choice[index] = Math.round(Math.random()*0.999 + (Rbias[index])/100 - 0.5) 
				choice[i] = Math.round(Math.random()*0.999 + (Rbias[i])/100 - 0.5) 
				score[index] += 3;
				score[i] += 3;
			}
			else {
				choice[index] = Math.round(Math.random()*0.999 + (Tbias[index])/100 - 0.5) 
				choice[i] = Math.round(Math.random()*0.999 + (Sbias[i])/100 - 0.5) 
				score[index] += 5;
			}
		}
		else {
			if (choice[index] == 1) {
				choice[index] = Math.round(Math.random()*0.999 + (Sbias[index])/100 - 0.5) 
				choice[i] = Math.round(Math.random()*0.999 + (Tbias[i])/100 - 0.5) 
				score[i] += 5;
				
			}
			else {
				choice[index] = Math.round(Math.random()*0.999 + (Pbias[index])/100 - 0.5) 
				choice[i] = Math.round(Math.random()*0.999 + (Pbias[i])/100 - 0.5) 
				score[index]++;
				score[i] ++;
			}
		}
	}
	cell[index] = score[index]/rounds[index];
	cell[i] = score[i]/rounds[i];

}

function birth(i){
	if (age[i] > 0 && cell[i] > 0.001 && cell[i] > cell[index]){
		cellValue = cell[i];
		age[index] = 0;
		cell[index] = 0.001;
		choice[index] = 0;
		score[index] = 0;
		rounds[index]=0;
		begin[index]=begin[i];
		Pbias[index] = Pbias[i];	
		Tbias[index] = Tbias[i];	
		Sbias[index] = Sbias[i];	
		Rbias[index] = Rbias[i];	
		replicated = true;
		var temp = Math.random();
		if (temp > 0.9198) {  muted = true }
		else {muted = false}        
		if (temp > 0.990) {if (Rbias[index] <= 100 - muteSize) { Rbias[index] += muteSize} else {Rbias[index]-= muteSize}} 
		else {	if (temp > 0.980) {if (Tbias[index] <= 100 - muteSize) { Tbias[index]+= muteSize} else {Tbias[index]-= muteSize}} 
			else { 	if (temp > 0.970) {if (Pbias[index] <= 100 - muteSize) { Pbias[index]+= muteSize} else {Pbias[index]-= muteSize}} 
				else {	if (temp > 0.960) {if (Sbias[index] <= 100 - muteSize) {Sbias[index]+= muteSize} else {Sbias[index]-= muteSize}} 
					else {	if (temp > 0.950) {if (Rbias[index] >= muteSize) { Rbias[index]-= muteSize} else {Rbias[index]+= muteSize}}
						else{	if (temp > 0.940) {if (Tbias[index] >= muteSize) { Tbias[index]-= muteSize} else {Tbias[index]+= muteSize}} 
							else {	if (temp > 0.930) {if (Pbias[index] >= muteSize) { Pbias[index]-= muteSize} else {Pbias[index]+= muteSize}} 
								else { 	if (temp > 0.920) {if (Sbias[index] >= muteSize) { Sbias[index]-= muteSize} else {Sbias[index]+= muteSize}} 
									else { if (temp > 0.9198) {if (begin[index] == 1) { begin[index] = 0} else {begin[index] = 1}} 
									}	
								}
							}
						}	
					}
				}
			}
		}
	}
}
function doScores(){
for (row = 10; row < 100; row += 10) {
	for (col = 1; col <= 9; col ++) {
                          	index = row + col;
		document.tally.process.value = row + col;
		neighbors = 0;
		if (cell[index] > 0) {
			age[index]++;	
			if (cell[index-11] > 0) {neighbors++; playIPD(index-11); }
      	             		if (cell[index-10] > 0){neighbors++; playIPD(index-10); }
              		if (cell[index-9] > 0) {neighbors++; playIPD(index-9); }
              	          	if (cell[index-1] > 0) {neighbors++; playIPD(index-1); }
          	              	if (cell[index+1] > 0) {neighbors++; playIPD(index+1); }
              	             if (cell[index+9] > 0) {neighbors++; playIPD(index+9); }
            	 	             if (cell[index+10] > 0) {neighbors++; playIPD(index+10); }
              	             if (cell[index+11] > 0) {neighbors++; playIPD(index+11); }
			if (cell[index] > highscore) {
				highscore = cell[index] ;
				document.tally.spot2.value =  row + col; 
				document.tally.computer2.value =  cell[index] ;
				document.tally.player2.value =  score[index] ;
				document.tally.round2.value =  rounds[index] ;
				document.tally.old2.value = age[index] ;
				document.tally.t2.value = Tbias[index]/100 ;
				document.tally.p2.value = Pbias[index]/100;
				document.tally.r2.value = Rbias[index]/100 ;
				document.tally.s2.value = Sbias[index]/100 ;
				document.tally.b2.value = begin[index] ;
			}
			if (cell[index] < lowscore) {
				lowscore = cell[index] ;
				document.tally.spot.value =  row + col; 
				document.tally.computer.value = cell[index] ;
				document.tally.player.value = score[index] ;
				document.tally.round.value = rounds[index] ;
				document.tally.old.value = age[index] ;
				document.tally.t.value = Tbias[index] /100;
				document.tally.p.value = Pbias[index]/100 ;
				document.tally.r.value = Rbias[index] /100;
				document.tally.s.value = Sbias[index]/100 ;
				document.tally.b.value = begin[index] ;
			}
			if (age[index] > oldest) {
				oldest = age[index] ;
				document.tally.spot1.value =  row + col; 
				document.tally.computer1.value = cell[index] ;
				document.tally.player1.value = score[index] ;
				document.tally.round1.value = rounds[index] ;
				document.tally.old1.value = age[index] ;
				document.tally.t1.value = Tbias[index]/100 ;
				document.tally.p1.value = Pbias[index]/100 ;
				document.tally.r1.value = Rbias[index] /100;
				document.tally.s1.value = Sbias[index] /100;
				document.tally.b1.value = begin[index] ;
			}
				
		}
	}
}		
}
function nextGeneration() {
	if (document.tally.evo[0].checked) {muteSize = 2; playRounds = 25;}
	if (document.tally.evo[1].checked) {muteSize = 10; playRounds = 5;}
              if (document.tally.abort[1].checked) {
                	reset(); 
                           initialise();
                           return;
              }
	 if ((document.tally.step[0].checked && subTotalRounds >= 1) ||  (document.tally.step[1].checked && subTotalRounds >= 2) ||  (document.tally.step[2].checked && subTotalRounds >= 5) ||  (document.tally.step[3].checked && subTotalRounds >= 10)  || 
	 (document.tally.step[4].checked && subTotalRounds >= 50) ||  (document.tally.step[5].checked && subTotalRounds >= 100)  || (document.tally.step[6].checked && subTotalRounds >= 1000) || (document.tally.step[7].checked && subTotalRounds >= 10000)) {
		subTotalRounds = 0;
		 if (confirm("Continue simulation?") == false) {
			stop = true;
			if (active == 1) clearTimeout(timer1);
			active = 0;
			graph.focus();
			return;
		}
              }
	subTotalRounds++;
	document.tally.gen.value = lives++;
	var neighbors;
	active = 1;
	highscore = 0;
	lowscore = 9999;
	offspring = 0;
	oldest = 0;
	mutes = 0;
	document.tally.births.value = offspring;
	document.tally.mutations.value = mutes;
// scores
	doScores();
// births
   for (row = 10; row < 100; row += 10) {
                for (col = 1; col <= 9; col++) {
                   	index = row + col;
		document.tally.process.value = row + col;
		neighbors = 0;
		muted = false;
		replicated = false; 
		cellValue = 0.001;
			if (cell[index-11] > cellValue ) {neighbors++; birth(index-11); }
      	         	  	if (cell[index-10] > cellValue) {neighbors++; birth(index-10); }
              		if (cell[index-9] > cellValue) {neighbors++; birth(index-9); }
              		if (cell[index-1] > cellValue ) {neighbors++; birth(index-1); }
          	      		if (cell[index+1] > cellValue ) {neighbors++; birth(index+1); }
              		if (cell[index+9] > cellValue) {neighbors++; birth(index+9); }
            	 		if (cell[index+10] > cellValue) {neighbors++; birth(index+10); }
              		if (cell[index+11] > cellValue) {neighbors++; birth(index+11); }
			if (muted == true) {document.tally.mutations.value = mutes++; }
			if (replicated == true) {document.tally.births.value = offspring++;}
		   
			score[index] = 0;
			rounds[index] = 0;
	}
   }

 if (document.tally.death[0].checked || document.tally.death[1].checked) {
// deaths
   for (row = 10; row < 100; row += 10) {
                for (col = 1; col <= 9; col++) {
                    	index = row + col;	
 		if (cell[index] > 0) {
 			if ((age[index] >= 2 && document.tally.death[0].checked) || (age[index] >= 3 && document.tally.death[1].checked)){
				cell[index] = 0; 
	 			choice[index]=0;
	 			score[index] = 0;
	 			rounds[index] = 0	
	 			begin[index] = 0;
	 			Pbias[index] = 0;
	 			Tbias[index] = 0;	
	 			Sbias[index] = 0;	
	 			Rbias[index] = 0;
	 			age[index] = 0;
	 		}
   	     	 }
 	}
   }
}        	
	
	if (active == 1){	
		graphIt();
		timer1 =  setTimeout("nextGeneration()", 500);
     	 }
	else { alert("simulation stopped")}
	graph.focus();
}



