Code viewer for World: Don't Get Tackled!
//This is a user controlled game, the aim is to get to the end zone. Then the difficulty is increased by adding more tacklers. Enjoy! 
 
const   CLOCKTICK   = 100;          
const   MAXSTEPS  = 1000;        
 

const  SCREENSHOT_STEP = 5;




//---- global constants: -------------------------------------------------------

const gridsize = 20;            

const squaresize = 100;        
const MAXPOS = gridsize * squaresize;    
  
const SKYCOLOR  = 0xddffdd;      
const BLANKCOLOR  = SKYCOLOR ;      




const show3d = true;            
 
const startRadiusConst    = MAXPOS * 0.8 ;    
const skyboxConst     = MAXPOS * 3 ;    
const maxRadiusConst    = MAXPOS * 10  ;      





const ACTION_LEFT     = 0;       
const ACTION_RIGHT    = 1;
const ACTION_UP       = 2;     
const ACTION_DOWN     = 3;
const ACTION_STAYSTILL    = 4;


const GRID_BLANK  = 0;
const GRID_WALL   = 1;
const GRID_POST = 3;
const GRID_CROSSBAR = 4;
//Shot variables

var beam = new Array(gridsize);
 
var cuberotatex = 0;
var cuberotatey = 0;
var shot1;
var shot1x = 2;
var shot1y = randomintAtoB(3,17);
var nrShots = 1;
var skip1 = false;
var shot1Initialised = true;
var shot1Painted = false;

var shot2;
var shot2x = 2;
var shot2y = randomintAtoB(3,17);
var skip2 = false;
var shot2Initialised = false;
var shot2Painted = false;

var shot3;
var shot3x = 2;
var shot3y = randomintAtoB(3,17);
var skip3 = false;
var shot3Initialised = false;
var shot3Painted = false;

var shot4;
var shot4x = 2;
var shot4y = randomintAtoB(3,17);
var skip4 = false;
var shot4Initialised = false;
var shot4Painted = false;

var shot5;
var shot5x = 2;
var shot5y = randomintAtoB(3,17);
var skip5 = false;
var shot5Initialised = false;
var shot5Painted = false;

var shot6;
var shot6x = 2;
var shot6y = randomintAtoB(3,17);
var skip6 = false;
var shot6Initialised = false;
var shot6Painted = false;

var shot7;
var shot7x = 2;
var shot7y = randomintAtoB(3,17);
var skip7 = false;
var shot7Initialised = false;
var shot7Painted = false;

var shot8;
var shot8x = 2;
var shot8y = randomintAtoB(3,17);
var skip8 = false;
var shot8Initialised = false;
var shot8Painted = false;

var touchdowns = 0;


function randomfloatAtoB ( A, B )      
{
 return ( A + ( Math.random() * (B-A) ) );
}

function randomintAtoB ( A, B )      
{
 return  ( Math.round ( randomfloatAtoB ( A, B ) ) );
}
  
function randomBoolean()       
{
 if ( Math.random() < 0.5 ) { return false; }
 else { return true; }
}






function World() { 




var BOXHEIGHT;    // 3d or 2d box height 

var GROUND = new Array(gridsize * gridsize);
var GRID  = new Array(gridsize);        
var WALLS   = new Array ( 4 * gridsize );   
var theagent, theenemy;
  

var ei, ej, ai, aj;

var badsteps;
var goodsteps;
var  step;

  var self = this;           

 




function initGrid()
{
 for (var i = 0; i < gridsize ; i++) 
 {
  GRID[i] = new Array(gridsize);   

  for (var j = 0; j < gridsize ; j++) 
  {
   GRID[i][j] = GRID_BLANK ;
  }
 }
}

function occupied ( i, j )    
{
 if ( ( ei == i ) && ( ej == j ) ) return true;   
 if ( ( ai == i ) && ( aj == j ) ) return true;

 if ( GRID[i][j] == GRID_WALL ) return true;     
   
 return false;
}

 

function translate ( x ) 
{
 return ( x - ( MAXPOS/2 ) );
}





//--- skybox ----------------------------------------------------------------------------------------------


function initSkybox() 
{


  var materialArray = [
  ( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/renatas/sides.jpg" ), side: THREE.BackSide } ) ),
  ( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/renatas/sides.jpg" ), side: THREE.BackSide } ) ),
  ( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/renatas/bottoms.jpg" ), side: THREE.BackSide } ) ),
  ( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/renatas/grass.jpg" ), side: THREE.BackSide } ) ),
  ( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/renatas/sides.jpg" ), side: THREE.BackSide } ) ),
  ( new THREE.MeshBasicMaterial ( { map: THREE.ImageUtils.loadTexture( "/uploads/renatas/sides.jpg" ), side: THREE.BackSide } ) )
  ];

  var skyGeometry = new THREE.CubeGeometry ( skyboxConst, skyboxConst, skyboxConst ); 
  var skyMaterial = new THREE.MeshFaceMaterial ( materialArray );
  var theskybox = new THREE.Mesh ( skyGeometry, skyMaterial );
  threeworld.scene.add( theskybox );           
}

  


function loadTextures()
{

 var loader1 = new THREE.TextureLoader();
 loader1.load ( '/uploads/renatas/wall.jpg',   function ( thetexture ) {      
    thetexture.minFilter = THREE.LinearFilter;
    paintWalls ( new THREE.MeshBasicMaterial( { map: thetexture } ) );
  } ); 
  
 var loader3 = new THREE.TextureLoader();
 loader3.load ( '/uploads/renatas/runner.jpg',  function ( thetexture ) {      
    thetexture.minFilter = THREE.LinearFilter;
    theagent.material =  new THREE.MeshBasicMaterial( { map: thetexture } );
  } ); 

 var loader4 = new THREE.TextureLoader();
 loader4.load ( '/uploads/renatas/rugby.jpg',  function ( thetexture ) {      
    thetexture.minFilter = THREE.LinearFilter;
    theenemy.material =  new THREE.MeshBasicMaterial( { map: thetexture } );
  } ); 

}


 



 
function initLogicalWalls()    
{
 for (var i = 0; i < gridsize ; i++) 
  for (var j = 0; j < gridsize ; j++) 
   if ( (( i === 0 ) || ( i==gridsize-1 ) || ( j ===0 ) || ( j == gridsize-1 )) && !(i > 4 && i < 15 && (j == 0 || j == gridsize -1)))
   {
      GRID[i][j] = GRID_WALL ;     
   }
   else if(i > 5 && i < 14 && (j == 0 || j == gridsize -1))
   {
     GRID[i][j] = GRID_CROSSBAR;
   }
   else if((i == 5 || i == 14) && (j == 0 || j == gridsize -1))
   {
     GRID[i][j] = GRID_POST;
   }
}

function initThreeWalls()   
{
 var t = 0;
 for (var i = 0; i < gridsize ; i++) 
  for (var j = 0; j < gridsize ; j++) 
  {
   if(GRID [i][j] == GRID_WALL && ((i == 0 || i == gridsize -1) && (j == 0 || j == gridsize -1)))
   {
      var shape    = new THREE.BoxGeometry( squaresize, BOXHEIGHT * 30, squaresize );      
      var thecube  = new THREE.Mesh( shape );
      thecube.material.color.setHex( BLANKCOLOR  );        
 
       thecube.position.x = translate ( i * squaresize );      
       thecube.position.z = translate ( j * squaresize );     
       thecube.position.y =  - BOXHEIGHT * 30 / 2 + BOXHEIGHT / 2; 
       threeworld.scene.add(thecube);
       WALLS[t] = thecube;        
       t++;     
   }
   else if ( GRID[i][j] == GRID_WALL )
   {
   var shape    = new THREE.BoxGeometry( squaresize, BOXHEIGHT * 30, squaresize );      
   var thecube  = new THREE.Mesh( shape );
   thecube.material.color.setHex( BLANKCOLOR  );        
 
       thecube.position.x = translate ( i * squaresize );       
       thecube.position.z = translate ( j * squaresize );     
       thecube.position.y =  - BOXHEIGHT * 30 / 2 + BOXHEIGHT / 2;  
 
   threeworld.scene.add(thecube);
   WALLS[t] = thecube;        // save it for later
   t++; 
   }
   else if( GRID[i][j] == GRID_POST && i == 5)
   {
     var post = new THREE.CylinderGeometry( 14, 14, BOXHEIGHT * 10, 64);
     var postmaterial = new THREE.MeshBasicMaterial( {color: 0xffffff} );
     var thepost  = new THREE.Mesh( post, postmaterial);
     
       thepost.position.x = translate ( i * squaresize  - squaresize / 2 + 14);      
       thepost.position.z = translate ( j * squaresize );     
       thepost.position.y = BOXHEIGHT * 5 - BOXHEIGHT / 2; 
       threeworld.scene.add(thepost);
   }
   else if( GRID[i][j] == GRID_POST && i == 14)
   {
     var post = new THREE.CylinderGeometry( 14, 14, BOXHEIGHT * 10, 64);
     var postmaterial = new THREE.MeshBasicMaterial( {color: 0xffffff} );
     var thepost  = new THREE.Mesh( post, postmaterial);
     
       thepost.position.x = translate ( i * squaresize  + squaresize / 2 - 14);       
       thepost.position.z = translate ( j * squaresize );     
       thepost.position.y = BOXHEIGHT * 5 - BOXHEIGHT / 2; 
       threeworld.scene.add(thepost);
   }
   else if( GRID[i][j] == GRID_CROSSBAR)
   {
     var crossbar = new THREE.CylinderGeometry( 14, 14, squaresize + 180, 64);
     var crossbarmaterial = new THREE.MeshBasicMaterial( {color: 0xffffff} );
     var thecrossbar  = new THREE.Mesh( crossbar, crossbarmaterial);
     
       thecrossbar.position.x = translate ( i * squaresize );      
       thecrossbar.position.z = translate ( j * squaresize );     
       thecrossbar.position.y =  BOXHEIGHT + BOXHEIGHT / 2; 
       thecrossbar.rotation.z = 1.58;
       threeworld.scene.add(thecrossbar);
   }
   else if (j % 3 === 0)
   {
     var geometry = new THREE.PlaneGeometry(squaresize, squaresize);
     var material = new THREE.MeshBasicMaterial( {color: 0xffffff, side: THREE.DoubleSide} );
     var plane = new THREE.Mesh( geometry, material );
     plane.position.x = translate ( i * squaresize);      
     plane.position.z = translate ( j * squaresize);    
     plane.position.y = -BOXHEIGHT / 2; 
     plane.rotation.x = 1.60;
     threeworld.scene.add( plane);
   }
   else
   {
     var geometry = new THREE.PlaneGeometry(squaresize, squaresize);
     var material = new THREE.MeshBasicMaterial( {color: 0x238e00, side: THREE.DoubleSide} );
     var plane = new THREE.Mesh( geometry, material );
     plane.position.x = translate ( i * squaresize);     
     plane.position.z = translate ( j * squaresize);    
     plane.position.y = -BOXHEIGHT / 2; 
     plane.rotation.x = 1.60;
     threeworld.scene.add( plane);
   }
  }
}

function initShot1()
{
  shot1Initialised = true;
  var shape = new THREE.BoxGeometry(squaresize, squaresize, squaresize);  
  shot1  = new THREE.Mesh(shape);
  loadTacklerTextures();
}

function drawShot1()
{
  if(skip1 === false)
  {
    if(shot1x != gridsize -2)
    {
      GRID[shot1x][shot1y] = 0;
      beam[shot1y] = true;
      shot1x += 1;
      GRID[shot1x][shot1y] = 2;
    }
    else 
    {
      GRID[shot1x][shot1y] = 0;
      beam[shot1y] = false;
      shot1x = 2;
      shot1y = randomintAtoB(3,gridsize -3);
      while(beam[shot1y] === true)
      {
        shot1y = randomintAtoB(3,gridsize -3);
      }
      GRID[shot1x][shot1y] = 2;
      beam[shot1y] = true;
    }
    shot1.position.x = translate ( shot1x * squaresize );     
    shot1.position.z = translate ( shot1y * squaresize ); 
    shot1.position.y = 0;
    threeworld.scene.add(shot1);
    skip1 = true;
  }
  else
  {
    shot1.position.x = translate ( shot1x * squaresize );       
    shot1.position.z = translate ( shot1y * squaresize ); 
    shot1.position.y = 0;
    threeworld.scene.add(shot1);
    skip1 = false;
  }
}

function initShot2()
{
  shot2Initialised = true;
  var shape = new THREE.BoxGeometry(squaresize, squaresize, squaresize);  
  shot2  = new THREE.Mesh(shape);
  loadTacklerTextures();
}

function drawShot2()
{
  if(skip2 === false)
  {
    if(shot2x != gridsize -2)
    {
      GRID[shot2x][shot2y] = 0;
      beam[shot2y] = true;
      shot2x += 1;
      GRID[shot2x][shot2y] = 2;
    }
    else 
    {
      GRID[shot2x][shot2y] = 0;
      beam[shot2y] = false;
      shot2x = 2;
      shot2y = randomintAtoB(3,gridsize -3);
      while(beam[shot2y] === true)
      {
        shot2y = randomintAtoB(3,gridsize -3);
      }
      GRID[shot2x][shot2y] = 2;
      beam[shot2y] = true;
    }
    shot2.position.x = translate ( shot2x * squaresize );       
    shot2.position.z = translate ( shot2y * squaresize ); 
    shot2.position.y = 0;
    threeworld.scene.add(shot2);
    skip2 = true;
  }
  else
  {
    shot2.position.x = translate ( shot2x * squaresize );        
    shot2.position.z = translate ( shot2y * squaresize ); 
    shot2.position.y = 0;
    threeworld.scene.add(shot2);
    skip2 = false;
  }
}

function initShot3()
{
  shot3Initialised = true;
  var shape = new THREE.BoxGeometry(squaresize, squaresize, squaresize);  
  shot3  = new THREE.Mesh(shape);
  loadTacklerTextures();
}

function drawShot3()
{
  if(skip3 === false)
  {
    if(shot3x != gridsize -2)
    {
      GRID[shot3x][shot3y] = 0;
      beam[shot3y] = true;
      shot3x += 1;
      GRID[shot3x][shot3y] = 2;
    }
    else 
    {
      GRID[shot3x][shot3y] = 0;
      beam[shot3y] = false;
      shot3x = 2;
      shot3y = randomintAtoB(3,gridsize -3);
      while(beam[shot3y] === true)
      {
        shot3y = randomintAtoB(3,gridsize -3);
      }
      beam[shot3y] = true;
      GRID[shot3x][shot3y] = 2;
    }
    shot3.position.x = translate ( shot3x * squaresize );       
    shot3.position.z = translate ( shot3y * squaresize ); 
    shot3.position.y = 0;
    threeworld.scene.add(shot3);
    skip3 = true;
  }
  else
  {
    shot3.position.x = translate ( shot3x * squaresize );       
    shot3.position.z = translate ( shot3y * squaresize ); 
    shot3.position.y = 0;
    threeworld.scene.add(shot3);
    skip3 = false;
  }
}

function initShot4()
{
  shot4Initialised = true;
  var shape = new THREE.BoxGeometry(squaresize, squaresize, squaresize);  
  shot4  = new THREE.Mesh(shape);
  loadTacklerTextures();
}

function drawShot4()
{
  if(skip4 === false)
  {
    if(shot4x != gridsize -2)
    {
      GRID[shot4x][shot4y] = 0;
      beam[shot4y] = true;
      shot4x += 1;
      GRID[shot4x][shot4y] = 2;
    }
    else 
    {
      GRID[shot4x][shot4y] = 0;
      beam[shot4y] = false;
      shot4x = 2;
      shot4y = randomintAtoB(3,gridsize -3);
      while(beam[shot4y] === true)
      {
        shot4y = randomintAtoB(3,gridsize -3);
      }
      beam[shot4y] = true;
      GRID[shot4x][shot4y] = 2;
    }
    shot4.position.x = translate ( shot4x * squaresize );       
    shot4.position.z = translate ( shot4y * squaresize ); 
    shot4.position.y = 0;
    threeworld.scene.add(shot4);
    skip4 = true;
  }
  else
  {
    shot4.position.x = translate ( shot4x * squaresize );       
    shot4.position.z = translate ( shot4y * squaresize ); 
    shot4.position.y = 0;
    threeworld.scene.add(shot4);
    skip4 = false;
  }
}

function initShot5()
{
  shot5Initialised = true;
  var shape = new THREE.BoxGeometry(squaresize, squaresize, squaresize);  
  shot5  = new THREE.Mesh(shape);
  loadTacklerTextures();
}

function drawShot5()
{
  if(skip5 === false)
  {
    if(shot5x != gridsize -2)
    {
      GRID[shot5x][shot5y] = 0;
      beam[shot5y] = true;
      shot5x += 1;
      GRID[shot5x][shot5y] = 2;
    }
    else 
    {
      GRID[shot5x][shot5y] = 0;
      beam[shot5y] = false;
      shot5x = 2;
      shot5y = randomintAtoB(3,gridsize -3);
      while(beam[shot5y] === true)
      {
        shot5y = randomintAtoB(3,gridsize -3);
      }
      beam[shot5y] = true;
      GRID[shot5x][shot5y] = 2;
    }
    shot5.position.x = translate ( shot5x * squaresize );       
    shot5.position.z = translate ( shot5y * squaresize ); 
    shot5.position.y = 0;
    threeworld.scene.add(shot5);
    skip5 = true;
  }
  else
  {
    shot5.position.x = translate ( shot5x * squaresize );       
    shot5.position.z = translate ( shot5y * squaresize ); 
    shot5.position.y = 0;
    threeworld.scene.add(shot5);
    skip5 = false;
  }
}

function initShot6()
{
  shot6Initialised = true;
  var shape = new THREE.BoxGeometry(squaresize, squaresize, squaresize);  
  shot6  = new THREE.Mesh(shape);
  loadTacklerTextures();
}

function drawShot6()
{
  if(skip6 === false)
  {
    if(shot6x != gridsize -2)
    {
      GRID[shot6x][shot6y] = 0;
      beam[shot6y] = true;
      shot6x += 1;
      GRID[shot6x][shot6y] = 2;
    }
    else 
    {
      GRID[shot6x][shot6y] = 0;
      beam[shot6y] = false;
      shot6x = 2;
      shot6y = randomintAtoB(3,gridsize -3);
      while(beam[shot6y] === true)
      {
        shot6y = randomintAtoB(3,gridsize -3);
      }
      beam[shot6y] = true;
      GRID[shot6x][shot6y] = 2;
    }
    shot6.position.x = translate ( shot6x * squaresize );       
    shot6.position.z = translate ( shot6y * squaresize ); 
    shot6.position.y = 0;
    threeworld.scene.add(shot6);
    skip6 = true;
  }
  else
  {
    shot6.position.x = translate ( shot6x * squaresize );       
    shot6.position.z = translate ( shot6y * squaresize ); 
    shot6.position.y = 0;
    threeworld.scene.add(shot6);
    skip6 = false;
  }
}

function initShot7()
{
  shot7Initialised = true;
  var shape = new THREE.BoxGeometry(squaresize, squaresize, squaresize);  
  shot7  = new THREE.Mesh(shape);
  loadTacklerTextures();
}

function drawShot7()
{
  if(skip7 === false)
  {
    if(shot7x != gridsize -2)
    {
      GRID[shot7x][shot7y] = 0;
      beam[shot7y] = true;
      shot7x += 1;
      GRID[shot7x][shot7y] = 2;
    }
    else 
    {
      GRID[shot7x][shot7y] = 0;
      beam[shot7y] = false;
      shot7x = 2;
      shot7y = randomintAtoB(3,gridsize -3);
      while(beam[shot7y] === true)
      {
        shot7y = randomintAtoB(3,gridsize -3);
      }
      beam[shot7y] = true;
      GRID[shot7x][shot7y] = 2;
    }
    shot7.position.x = translate ( shot7x * squaresize );      
    shot7.position.z = translate ( shot7y * squaresize ); 
    shot7.position.y = 0;
    threeworld.scene.add(shot7);
    skip7 = true;
  }
  else
  {
    shot7.position.x = translate ( shot7x * squaresize );      
    shot7.position.z = translate ( shot7y * squaresize ); 
    shot7.position.y = 0;
    threeworld.scene.add(shot7);
    skip7 = false;
  }
}

function initShot8()
{
  shot8Initialised = true;
  var shape = new THREE.BoxGeometry(squaresize, squaresize, squaresize);  
  shot8  = new THREE.Mesh(shape);
  loadTacklerTextures();
}

function drawShot8()
{
  if(skip8 === false)
  {
    if(shot8x != gridsize -2)
    {
      GRID[shot8x][shot8y] = 0;
      beam[shot8y] = true;
      shot8x += 1;
      GRID[shot8x][shot8y] = 2;
    }
    else 
    {
      GRID[shot8x][shot8y] = 0;
      beam[shot8y] = false;
      shot8x = 2;
      shot8y = randomintAtoB(3,gridsize -3);
      while(beam[shot8y] === true)
      {
        shot8y = randomintAtoB(3,gridsize -3);
      }
      beam[shot8y] = true;
      GRID[shot8x][shot8y] = 2;
    }
    shot8.position.x = translate ( shot8x * squaresize );       
    shot8.position.z = translate ( shot8y * squaresize ); 
    shot8.position.y = 0;
    threeworld.scene.add(shot8);
    skip8 = true;
  }
  else
  {
    shot8.position.x = translate ( shot8x * squaresize );      
    shot8.position.z = translate ( shot8y * squaresize ); 
    shot8.position.y = 0;
    threeworld.scene.add(shot8);
    skip8 = false;
  }
}


function paintWalls ( material )     
{
 for ( var i = 0; i < WALLS.length; i++ )
 { 
   if ( WALLS[i] )  WALLS[i].material = material;
 }
}

function paintTacklers(material)
{
  if(shot1Initialised === true)
    if(shot1Painted === false)
    {
      shot1.material = material;
      shot1Painted = true;
    }
  
  if(shot2Initialised === true)
    if(shot2Painted === false)
    {
      shot2.material = material;
      shot2Painted = true;
    }
    
  if(shot3Initialised === true)
    if(shot3Painted === false)
    {
      shot3.material = material;
      shot3Painted = true;
    }
    
  if(shot4Initialised === true)
    if(shot4Painted === false)
    {
      shot4.material = material;
      shot4Painted = true;
    }
    
  if(shot5Initialised === true)
    if(shot5Painted === false)
    {
      shot5.material = material;
      shot5Painted = true;
    }
  if(shot6Initialised === true)
    if(shot6Painted === false)
    {
      shot6.material = material;
      shot6Painted = true;
    }
  if(shot7Initialised === true)
    if(shot7Painted === false)
    {
      shot7.material = material;
      shot7Painted = true;
    }
  if(shot8Initialised === true)
    if(shot8Painted === false)
    {
      shot8.material = material;
      shot8Painted = true;
    }
}

function loadTacklerTextures()
{
  var loader2 = new THREE.TextureLoader();
  loader2.load ( '/uploads/renatas/tackler.jpg',    function ( thetexture ) {      
    thetexture.minFilter = THREE.LinearFilter;
    paintTacklers ( new THREE.MeshBasicMaterial( { map: thetexture }) );
  } ); 
}

function rotate()
{
  cuberotatex += 0.2; 
  cuberotatey += 0.2;
}



function drawEnemy()  
{
  var x = translate ( ei * squaresize );    
  var z = translate ( ej * squaresize );    
  var y =  0; 

 theenemy.position.x = x;
 theenemy.position.y = y;
 theenemy.position.z = z;
 threeworld.scene.add(theenemy);

 threeworld.lookat.copy ( theenemy.position );   
}


function initLogicalEnemy()
{
// start in random location:
 var i, j;
 do
 {
  i = randomintAtoB(1,gridsize-2);
  j = randomintAtoB(1,gridsize-2);
 }
 while ( occupied(i,j) );    
 ei = i;
 ej = j;
}


function initThreeEnemy()
{
 var shape    = new THREE.BoxGeometry( squaresize, BOXHEIGHT, squaresize );      
 theenemy = new THREE.Mesh( shape );
 theenemy.material.color.setHex( BLANKCOLOR  ); 
 drawEnemy();     
}


function moveLogicalEnemy()
{ 


 var i, j;
 if ( ei < ai ) i = randomintAtoB(ei, ei+1); 
 if ( ei == ai ) i = ei; 
 if ( ei > ai ) i = randomintAtoB(ei-1, ei); 

 if ( ej < aj ) j = randomintAtoB(ej, ej+1); 
 if ( ej == aj ) j = ej; 
 if ( ej > aj ) j = randomintAtoB(ej-1, ej); 
 
 if ( ! occupied(i,j) )   // if no obstacle then move, else just miss a turn
 {
  ei = i;
  ej = j;
 }
}





// --- agent functions -----------------------------------


function drawAgent() 
{
  var x = translate ( ai * squaresize );    
  var z = translate ( aj * squaresize );    
  var y =  0; 

 theagent.position.x = x;
 theagent.position.y = y;
 theagent.position.z = z;
 threeworld.scene.add(theagent);

 threeworld.follow.copy ( theagent.position );    
}


function initLogicalAgent()
{
// start in random location:
 var i, j;
 do
 {
  i = Math.trunc( gridsize / 2 );
  j = gridsize -2;
 }
 while ( occupied(i,j) );    

 ai = i;
 aj = j;
}

function initThreeAgent()
{
 var shape    = new THREE.BoxGeometry( squaresize, BOXHEIGHT, squaresize );      
 theagent = new THREE.Mesh( shape );
 theagent.material.color.setHex( BLANKCOLOR );  
 drawAgent();       
}


function moveLogicalAgent( a )      
{ 
 var i = ai;
 var j = aj;     

      if ( a == ACTION_LEFT )   i--;
 else if ( a == ACTION_RIGHT )  i++;
 else if ( a == ACTION_UP )     j++;
 else if ( a == ACTION_DOWN )   j--;

 if ( ! occupied(i,j) ) 
 {
  ai = i;
  aj = j;
 }
 if(detectCollision(ai,aj) === true)
 {
   return false;
 }
 if(aj === 1)
 {
   soundTouchdown();
   touchdowns++;
   nrShots++;
   ai = Math.trunc ( gridsize / 2 );
   aj = gridsize -2;
 }
 return true;
}

//false means no collision
function detectCollision(i, j)
{
  if(GRID[i-1][j] === 0)
    return false;
  else
    return true;
}




function keyHandler(e)    
// user control 
{
    if (e.keyCode == 37)  moveLogicalAgent ( ACTION_LEFT  );
    if (e.keyCode == 38)  moveLogicalAgent ( ACTION_DOWN    );
    if (e.keyCode == 39)  moveLogicalAgent ( ACTION_RIGHT   );
    if (e.keyCode == 40)  moveLogicalAgent ( ACTION_UP  );
}





// --- score: -----------------------------------


function badstep()     
{
 if ( ( Math.abs(ei - ai) < 2 ) && ( Math.abs(ej - aj) < 2 ) ) return true;
 else return false;
}


function agentBlocked()     
{
 return (   occupied (ai-1,aj)    && 
    occupied (ai+1,aj)    &&
    occupied (  ai,aj+1)    &&
    occupied (  ai,aj-1)  );    
} 


function updateStatusBefore(a)

{
 var x = self.getState();
 var status = " Step: <b> " + step + " </b> &nbsp; x = (" + x.toString() + ") &nbsp; a = (" + a + ") "; 

 $("#user_span3").html( status );
}


function   updateStatusAfter()    
{
 var y = self.getState();
 var status = " &nbsp; y = (" + y.toString() + ") <BR> "; 
 $("#user_span4").html( status );

 var score = self.getScore();

 var status = "   Bad steps: " + badsteps + 
    " &nbsp; Good steps: " + goodsteps + 
    " &nbsp; Score: " + score.toFixed(2) + "% "; 

 $("#user_span5").html( status + "Get to the end zone! Use the arrow keys and don't get tackled by players coming from the left." );
}






//--- public functions / interface / API ----------------------------------------------------------


this.endCondition;      



this.newRun = function() 
{


  this.endCondition = false;
  badsteps = 0; 
  goodsteps = 0;
  step = 0;



  initGrid();
  initLogicalWalls(); 
  initLogicalAgent();
  initLogicalEnemy();
    
    

  if ( true  )
  {
  if ( show3d )
  {
   BOXHEIGHT = squaresize;
   threeworld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR  );   
  }      
  else
  {
   BOXHEIGHT = 1;
   threeworld.init2d ( startRadiusConst, maxRadiusConst, SKYCOLOR  );          
  }

  initSkybox();
  initMusic();

  // Set up objects first:
  initThreeWalls(); 
  initThreeAgent();
  initThreeEnemy();
  initShot1();
  loadTacklerTextures();
 

  loadTextures(); 

  document.onkeydown = keyHandler;   
  }

};




this.getState = function()
{
 var x = [ ai, aj, ei, ej ];
  return ( x );  
};



this.takeAction = function ( a )
{
  step++;

  if ( true  )
   updateStatusBefore(a);     

  if(moveLogicalAgent(a) === false)
  {
    this.endCondition = true;
  }

  if ( ( step % 2 ) == 0 )   
    moveLogicalEnemy();


  if ( badstep() )
   badsteps++;
  else
   goodsteps++;

  if ( true  )
  {
   rotate();
   if (nrShots > 0)
   {
     if(shot1Initialised === false)
     {
       initShot1();
     }
     drawShot1();
   }
   if(nrShots > 1)
   {
     if(shot2Initialised === false)
     {
       initShot2();
     }
     drawShot2();
   }
   if(nrShots > 2)
   {
     if(shot3Initialised === false)
     {
       initShot3();
     }
     drawShot3();
   }
   if(nrShots > 3)
   {
     if(shot4Initialised === false)
     {
       initShot4();
     }
     drawShot4();
   }
   if(nrShots > 4)
   {
     if(shot5Initialised === false)
     {
       initShot5();
     }
     drawShot5();
   }
   if(nrShots > 5)
   {
     if(shot6Initialised === false)
     {
       initShot6();
     }
     drawShot6();
   }
   if(nrShots > 6)
   {
     if(shot7Initialised === false)
     {
       initShot7();
     }
     drawShot7();
   }
   if(nrShots > 7)
   {
     if(shot8Initialised === false)
     {
       initShot8();
     }
     drawShot8();
   }
   drawAgent();
   drawEnemy();
   updateStatusAfter();     
  }


  if ( agentBlocked() )    
  {
  this.endCondition = true;
  goodsteps = 0;            
    if ( true  )
    {
   musicPause();
  }
  }

};



this.endRun = function()
{
 if ( true  )
 {
  musicPause(); 
  if ( this.endCondition )
    $("#user_span6").html( " &nbsp; <font color=red> <B> Player Tackled! Touchdown count:"+ touchdowns + "</B> </font>   "  );
  else
    $("#user_span6").html( " &nbsp; <font color=red> <B> Run over. </B> </font>   "  );
 }
};


this.getScore = function()
{
 return ( ( goodsteps / step ) * 100 );
};


}

//---- end of World class -------------------------------------------------------










function initMusic()
{
    var x = "<audio  id=theaudio  src=/uploads/renatas/stadium.mp3   autoplay loop> </audio>" ;
    $("#user_span1").html( x );
} 
 

function musicPlay()  
{
  document.getElementById('theaudio').play();
}


function musicPause() 
{
  document.getElementById('theaudio').pause();
}


function soundTouchdown()
{
  var x = "<audio    src=/uploads/renatas/touchdown.mp3   autoplay  > </audio>";
    $("#user_span2").html( x );
}