//********************** bj3dttt.js ****************************
/*
 * 3D Tic Tac Toe.
 *
 * Original Author Unknown
 *
 * Ported to JavaScript by Bo Johansson 99-02-11
 *             Modified by Bo Johansson 99-02-20 
 */


/*
 * Constants
 */
EMPTY = 0;
PLAYER = 1;
BEAST = 5;

STATUS_WAIT = -1;
STATUS_RUN = 0;
STATUS_PLAYER_WIN = 1;
STATUS_BEAST_WIN = 2;
STATUS_DRAW = 3;

STATUS_START = 99

gameStatus = STATUS_START;

/*
 * This is the board.
 * Starts off all empty.
 */
the_board = new Array;


/*
 * This is a table of all winning combinations.
 * From Kilobaud, April 78.
 * You can look there to see how it is ordered.
 */
var win_comb = new Array;

   win_comb[0] = 0;   // level 1, Row 1
   win_comb[1] = 1;
   win_comb[2] = 2;
   win_comb[3] = 3;
   
   win_comb[4] = 4;   // level 1, Row 2
   win_comb[5] = 5;
   win_comb[6] = 6;
   win_comb[7] = 7;
   
   win_comb[8] = 8;   // level 1, Row 3   
   win_comb[9] = 9;
   win_comb[10] = 10;
   win_comb[11] = 11;
   
   win_comb[12] = 12;   // level 1, Row 4
   win_comb[13] = 13;
   win_comb[14] = 14;
   win_comb[15] = 15;
   
   win_comb[16] = 0;   // level 1, Col 1   
   win_comb[17] = 4;
   win_comb[18] = 8;
   win_comb[19] = 12;
   
   win_comb[20] = 1;   // level 1, Col 2
   win_comb[21] = 5;
   win_comb[22] = 9;
   win_comb[23] = 13;
   
   win_comb[24] = 2;   // level 1, Col 3
   win_comb[25] = 6;
   win_comb[26] = 10;
   win_comb[27] = 14;
   
   win_comb[28] = 3;   // level 1, Col 4
   win_comb[29] = 7;
   win_comb[30] = 11;
   win_comb[31] = 15;
   
   win_comb[32] = 0;   // level 1, Diagonal \
   win_comb[33] = 5;
   win_comb[34] = 10;
   win_comb[35] = 15;
   
   win_comb[36] = 3;   // level 1, Diagonal /
   win_comb[37] = 6;
   win_comb[38] = 9;
   win_comb[39] = 12;
   
   win_comb[40] = 16;   // level 2, Row 1
   win_comb[41] = 17;
   win_comb[42] = 18;
   win_comb[43] = 19;
   
   win_comb[44] = 20;   // level 2, Row 2
   win_comb[45] = 21;
   win_comb[46] = 22;
   win_comb[47] = 23;
   
   win_comb[48] = 24;   // level 2, Row 3
   win_comb[49] = 25;
   win_comb[50] = 26;
   win_comb[51] = 27;
   
   win_comb[52] = 28;   // level 2, Row 4
   win_comb[53] = 29;
   win_comb[54] = 30;
   win_comb[55] = 31;
   
   win_comb[56] = 16;   // level 2, Col 1
   win_comb[57] = 20;
   win_comb[58] = 24;
   win_comb[59] = 28;
   
   win_comb[60] = 17;   // level 2, Col 2
   win_comb[61] = 21;
   win_comb[62] = 25;
   win_comb[63] = 29;
   
   win_comb[64] = 18;   // level 2, Col 3
   win_comb[65] = 22;
   win_comb[66] = 26;
   win_comb[67] = 30;
   
   win_comb[68] = 19;   // level 2, Col 4
   win_comb[69] = 23;
   win_comb[70] = 27;
   win_comb[71] = 31;
   
   win_comb[72] = 16;   // level 2, Diagonal \
   win_comb[73] = 21;
   win_comb[74] = 26;
   win_comb[75] = 31;
   
   win_comb[76] = 19;   // level 2, Diagonal /
   win_comb[77] = 22;
   win_comb[78] = 25;
   win_comb[79] = 28;
   
   win_comb[80] = 32;   // level 3, Row 1
   win_comb[81] = 33;
   win_comb[82] = 34;
   win_comb[83] = 35;
   
   win_comb[84] = 36;   // level 3, Row 2
   win_comb[85] = 37;
   win_comb[86] = 38;
   win_comb[87] = 39;
   
   win_comb[88] = 40;   // level 3, Row 3
   win_comb[89] = 41;
   win_comb[90] = 42;
   win_comb[91] = 43;
   
   win_comb[92] = 44;   // level 3, Row 4
   win_comb[93] = 45;
   win_comb[94] = 46;
   win_comb[95] = 47;
   
   win_comb[96] = 32;   // level 3, Col 1
   win_comb[97] = 36;
   win_comb[98] = 40;
   win_comb[99] = 44;
   
   win_comb[100] = 33;   // level 3, Col 2
   win_comb[101] = 37;
   win_comb[102] = 41;
   win_comb[103] = 45;
   
   win_comb[104] = 34;   // level 3, Col 3
   win_comb[105] = 38;
   win_comb[106] = 42;
   win_comb[107] = 46;
   
   win_comb[108] = 35;   // level 3, Col 4
   win_comb[109] = 39;
   win_comb[110] = 43;
   win_comb[111] = 47;
   
   win_comb[112] = 32;   // level 3, Diagonal \
   win_comb[113] = 37;
   win_comb[114] = 42;
   win_comb[115] = 47;
   
   win_comb[116] = 35;   // level 3, Diagonal /
   win_comb[117] = 38;
   win_comb[118] = 41;
   win_comb[119] = 44;
   
   win_comb[120] = 48;   // level 4, Row 1
   win_comb[121] = 49;
   win_comb[122] = 50;
   win_comb[123] = 51;
   
   win_comb[124] = 52;   // level 4, Row 2
   win_comb[125] = 53;
   win_comb[126] = 54;
   win_comb[127] = 55;
   
   win_comb[128] = 56;   // level 4, Row 3
   win_comb[129] = 57;
   win_comb[130] = 58;
   win_comb[131] = 59;
   
   win_comb[132] = 60;   // level 4, Row 4
   win_comb[133] = 61;
   win_comb[134] = 62;
   win_comb[135] = 63;
   
   win_comb[136] = 48;   // level 4, Col 1
   win_comb[137] = 52;
   win_comb[138] = 56;
   win_comb[139] = 60;
   
   win_comb[140] = 49;   // level 4, Col 2
   win_comb[141] = 53;
   win_comb[142] = 57;
   win_comb[143] = 61;
   
   win_comb[144] = 50;   // level 4, Col 3
   win_comb[145] = 54;
   win_comb[146] = 58;
   win_comb[147] = 62;
   
   win_comb[148] = 51;   // level 4, Col 1
   win_comb[149] = 55;
   win_comb[150] = 59;
   win_comb[151] = 63;
   
   win_comb[152] = 48;   // level 4, Diagonal \
   win_comb[153] = 53;
   win_comb[154] = 58;
   win_comb[155] = 63;
   
   win_comb[156] = 51;   // level 4, Diagonal /
   win_comb[157] = 54;
   win_comb[158] = 57;
   win_comb[159] = 60;
   
   win_comb[160] = 0;   // Row 1 - Col 1 vertical
   win_comb[161] = 16;
   win_comb[162] = 32;
   win_comb[163] = 48;
   
   win_comb[164] = 1;   // Row 1 - Col 2 vertical
   win_comb[165] = 17;
   win_comb[166] = 33;
   win_comb[167] = 49;
   
   win_comb[168] = 2;   // Row 1 - Col 3 vertical
   win_comb[169] = 18;
   win_comb[170] = 34;
   win_comb[171] = 50;
   
   win_comb[172] = 3;   // Row 1 - Col 4 vertical
   win_comb[173] = 19;
   win_comb[174] = 35;
   win_comb[175] = 51;
   
   win_comb[176] = 4;   // Row 2 - Col 1 vertical
   win_comb[177] = 20;
   win_comb[178] = 36;
   win_comb[179] = 52;
   
   win_comb[180] = 5;   // Row 2 - Col 2 vertical
   win_comb[181] = 21;
   win_comb[182] = 37;
   win_comb[183] = 53;
   
   win_comb[184] = 6;   // Row 2 - Col 3 vertical
   win_comb[185] = 22;
   win_comb[186] = 38;
   win_comb[187] = 54;
   
   win_comb[188] = 7;   // Row 2 - Col 4 vertical
   win_comb[189] = 23;
   win_comb[190] = 39;
   win_comb[191] = 55;
   
   win_comb[192] = 8;   // Row 3 - Col 1 vertical
   win_comb[193] = 24;
   win_comb[194] = 40;
   win_comb[195] = 56;
   
   win_comb[196] = 9;   // Row 3 - Col 2 vertical
   win_comb[197] = 25;
   win_comb[198] = 41;
   win_comb[199] = 57;
   
   win_comb[200] = 10;   // Row 3 - Col 3 vertical
   win_comb[201] = 26;
   win_comb[202] = 42;
   win_comb[203] = 58;
   
   win_comb[204] = 11;   // Row 3 - Col 4 vertical
   win_comb[205] = 27;
   win_comb[206] = 43;
   win_comb[207] = 59;
   
   win_comb[208] = 13;   // Row 4 - Col 2 vertical   ***** order?
   win_comb[209] = 29;
   win_comb[210] = 45;
   win_comb[211] = 61;
   
   win_comb[212] = 12;   // Row 4 - Col 1 vertical   ***** order?
   win_comb[213] = 28;
   win_comb[214] = 44;
   win_comb[215] = 60;
   
   win_comb[216] = 14;   // Row 4 - Col 3 vertical
   win_comb[217] = 30;
   win_comb[218] = 46;
   win_comb[219] = 62;
   
   win_comb[220] = 15;   // Row 4 - Col 4 vertical
   win_comb[221] = 31;
   win_comb[222] = 47;
   win_comb[223] = 63;
   
   win_comb[224] = 0;   // Diagonal 111 - 444
   win_comb[225] = 21;
   win_comb[226] = 42;
   win_comb[227] = 63;
   
   win_comb[228] = 4;   // Row 2 Diagonal 121 - 424
   win_comb[229] = 21;
   win_comb[230] = 38;
   win_comb[231] = 55;
   
   win_comb[232] = 8;
   win_comb[233] = 25;
   win_comb[234] = 42;
   win_comb[235] = 59;
   
   win_comb[236] = 12;
   win_comb[237] = 25;
   win_comb[238] = 38;
   win_comb[239] = 51;
   
   win_comb[240] = 1;
   win_comb[241] = 21;
   win_comb[242] = 41;
   win_comb[243] = 61;
   
   win_comb[244] = 13;
   win_comb[245] = 25;
   win_comb[246] = 37;
   win_comb[247] = 49;
   
   win_comb[248] = 2;
   win_comb[249] = 22;
   win_comb[250] = 42;
   win_comb[251] = 62;
   
   win_comb[252] = 14;
   win_comb[253] = 26;
   win_comb[254] = 38;
   win_comb[255] = 50;
   
   win_comb[256] = 3;
   win_comb[257] = 22;
   win_comb[258] = 41;
   win_comb[259] = 60;
   
   win_comb[260] = 7;
   win_comb[261] = 22;
   win_comb[262] = 37;
   win_comb[263] = 52;
   
   win_comb[264] = 11;
   win_comb[265] = 26;
   win_comb[266] = 41;
   win_comb[267] = 56;
   
   win_comb[268] = 15;
   win_comb[269] = 26;
   win_comb[270] = 37;
   win_comb[271] = 48;
   
   win_comb[272] = 0;
   win_comb[273] = 20;
   win_comb[274] = 40;
   win_comb[275] = 60;
   
   win_comb[276] = 0;
   win_comb[277] = 17;
   win_comb[278] = 34;
   win_comb[279] = 51;
   
   win_comb[280] = 3;
   win_comb[281] = 18;
   win_comb[282] = 33;
   win_comb[283] = 48;
   
   win_comb[284] = 3;
   win_comb[285] = 23;
   win_comb[286] = 43;
   win_comb[287] = 63;
   
   win_comb[288] = 12;
   win_comb[289] = 24;
   win_comb[290] = 36;
   win_comb[291] = 48;
   
   win_comb[292] = 12;
   win_comb[293] = 29;
   win_comb[294] = 46;
   win_comb[295] = 63;
   
   win_comb[296] = 15;
   win_comb[297] = 30;
   win_comb[298] = 45;
   win_comb[299] = 60;
   
   win_comb[300] = 15;
   win_comb[301] = 27;
   win_comb[302] = 39;
   win_comb[303] = 51;


/*
 * Different language versions possible.
 */
function initStrings(lang)
{
    if(lang == 1)   // Swedish
    {
        waitString = "Vänta...";

        choiseString = "Vem skall göra första draget?";

        promtString = "Gör ditt drag";

        alertString = "Fel: den rutan är upptagen";

        playerString = "Du vinner, din lyckans ost!";

        beastString = "Jag vinner, du förlorar!";

        drawString = "Oavgort!";
    }

    else   // default: English
    {
        waitString = "Wait...";

        choiseString = "Who will make the first move?";

        promtString = "Make your move";

        alertString = "Error: that square is occupied";

        playerString = "You win, you lucky dog!";

        beastString = "I win, you lose!";

        drawString = "Draw!";
    }
}


/*
 * Accept a user move. return gameStatus = STATUS_PLAYER_WIN if he wins.
 */
function user_move(p)
{
    gameStatus = STATUS_WAIT;
    
    document.tttForm1.messageField.value = waitString;

	if( (p >= 0) && (p <= 63) && (the_board[p] != EMPTY) )
	{
		alert(alertString);

        gameStatus = STATUS_RUN;
    
        document.tttForm1.messageField.value = promtString;

	    return gameStatus;
	}

	the_board[p] = PLAYER;

	document.tttForm1.outputField[p].value = " X ";

	for(i=0; i<4*76; i+=4)
    {
		t = 0;

		for(j=0; j<4; ++j)
			t += the_board[win_comb[i+j]];

		if(t == 4*PLAYER)
        {
            document.tttForm1.messageField.value = playerString;

			gameStatus = STATUS_PLAYER_WIN;
			
			break;
		}
	}

    if(gameStatus != STATUS_PLAYER_WIN)
        beast_move();
    
	return gameStatus;
}

/*
 * Given a total along a winning combination, return the weight value.
 */
function weight(at)
{
	t = at;

	if(t == PLAYER)
		return(1);

	if(t == 2*PLAYER)
		return(4);

	if(t == BEAST)
		return(1);

	if(t == 2*BEAST)
		return(2);

	return(0);
}

/*
 * Move for the machine.
 */
function beast_move()
{
	v = new Array;
	t = 0;

	for(i=0; i<4*76; i+=4)
    {
		t = 0;

		for(j=0; j<4; ++j)
			t += the_board[win_comb[i+j]];

		v[i>>2] = t;

		if(t == 3*BEAST)
			break;
	}

	if(i < 4*76)     // A winning move exists
    {
		for(j=0; j<4; ++j)
		{
		    if(the_board[win_comb[i+j]] == EMPTY)
            {
				the_board[win_comb[i+j]] = BEAST;
				break;
			}
		}

		document.tttForm1.outputField[win_comb[i+j]].value = " 0 ";

        document.tttForm1.messageField.value = beastString;

		gameStatus = STATUS_BEAST_WIN;
			
		return gameStatus;
	}

	bt = 0;

	for(s=0; s<64; ++s)
    {
		if(the_board[s] != EMPTY)
			continue;

		t = 0;

		for(i=0; i<4*76; i+=4)
        {
			for(j=0; j<4; ++j)
				if(win_comb[i+j] == s)
					break;

			if(j != 4)
            {
				if(v[i>>2] == 3*PLAYER)
                {
					the_board[s] = BEAST;

					document.tttForm1.outputField[s].value = " 0 ";
					
		            gameStatus = STATUS_RUN;
			
                    document.tttForm1.messageField.value = promtString;
                    
		            return gameStatus;
				}
				t += weight(v[i>>2]);
			}
		}
		if(t > bt)
        {
			bt = t;
			bs = s;
		}
	}

	if(bt != 0)
	{
		the_board[bs] = BEAST;

		document.tttForm1.outputField[bs].value = " 0 ";
    }
    
	else
    {
		for(s=0; s<64; ++s)
			if(the_board[s] == EMPTY)
				break;

		if(s == 64)
        {
            document.tttForm1.messageField.value = drawString;

		    gameStatus = STATUS_DRAW;

		    return gameStatus;
		}
		
		the_board[s] = BEAST;

		document.tttForm1.outputField[s].value = " 0 ";
	}
    gameStatus = STATUS_RUN;
    
    document.tttForm1.messageField.value = promtString;

    return gameStatus;
}

/*
 * The run() function just starts the game.
 */
function run(lang)
{
    initStrings(lang);

    document.tttForm1.messageField.value = waitString;

    for(i = 0; i < 64; i++)
    {
       the_board[i] = EMPTY;
       
       document.tttForm1.outputField[i].value = "__"
    }
    
	if(document.tttForm1.startRadio[1].checked)
		beast_move();
		
	else
    {
        document.tttForm1.messageField.value = promtString;

        gameStatus = STATUS_RUN;
    }
}

function resetBoard()
{
    document.tttForm1.messageField.value = waitString;

    gameStatus = STATUS_START;
    
    for(i = 0; i < 64; i++)
    {
       the_board[i] = EMPTY;
       
       document.tttForm1.outputField[i].value = "__"
    }

    document.tttForm1.messageField.value = choiseString;
}
//********************** bj3dttt.js ****************************
