Code viewer for World: Chess
// Constants
// -------------------------------------------------------------------------------------------------------------------------------------------------------------

// Death sound, credit:
// https://www.youtube.com/watch?v=r6JK-gRELI0

const soundDead = "/uploads/dalye54/Wilhelm_death.mp3";
const startRadius   = 500;
const maxRadius     = startRadius * 10;
const skycolor      = '#4442ff'; 

var deathSound = new Audio(soundDead);

AB.clockTick       = 50; 

AB.maxSteps        = 1000000; 

ABWorld.drawCameraControls 	= false; 

// beach skyboxes, credit:
// https://opengameart.org/content/beach-skyboxes
 const skyboxArray = ["/uploads/dalye54/posx.jpg",
                      "/uploads/dalye54/negx.jpg",
                      "/uploads/dalye54/posy.jpg",
                      "/uploads/dalye54/negy.jpg",
                      "/uploads/dalye54/posz.jpg",
                      "/uploads/dalye54/negz.jpg"
                      ];

const walnutCube = new THREE.TextureLoader().load('/uploads/dalye54/walnut.jpg');
const beechCube = new THREE.TextureLoader().load('/uploads/dalye54/beech.jpg');


// Class Information
// -------------------------------------------------------------------------------------------------------------------------------------------------------------

var selectorSide = new THREE.BoxGeometry (10, 1, 50); // Used for displaying the selector.
var selectorRoof = new THREE.BoxGeometry (50, 1, 10); // Used for displaying the selector.
var nextMove = new THREE.BoxGeometry(30, 1, 30); // Used for displaying the next possible moves.
var nextKillSide = new THREE.BoxGeometry(10,1,30); // Used for displaying the next possible moves when opposite piece is in the position.
var nextKillRoof = new THREE.BoxGeometry(30,1,10); // Used for displaying the next possible moves when opposite piece is in the position.

var chessPieces;

// Load in the 3D objects for the chess pieces.
function loadResources()
{

 	var first = new THREE.MTLLoader();
	first.setResourcePath ( "/uploads/dalye54/" );
	first.setPath         ( "/uploads/dalye54/" );
	first.load ("chess.mtl", function (materials)
	{
	    materials.preload();
	    var second = new THREE.OBJLoader();
	    second.setPath( "/uploads/dalye54/" );
	    second.setMaterials(materials);
 	    second.load("chess.obj", function (object)
     	    {
     	        chessPieces = object;
     	        if ( asynchFinished() ) displayPieces() ;
     	    });
 	});
}

// Function for waiting for the load to finish.
function asynchFinished()		 
{
	if ( chessPieces ) return true;  
	else return false;
}

// Game class, which keeps track of what colour should be making a move.
class Game
{
    constructor() // Set the colour to white at the start.
    {
        this.turn = "white";
        this.winner = false;
        this.colourWinner;
    }
    
    switchTurn() // Switch colour when a move has been made.
    {
        if (this.turn == "white")
        {
            this.turn = "black";
            return;
        }
        else if (this.turn == "black")
        {
            this.turn = "white";
            return;
        }
    }
    
    displayTurn() // Return the current colour that has to make a move.
    {
        return this.turn;
    }
    
    gameOver(winColour)
    {
        this.colourWinner = winColour;
        this.winner = true;
    }
}

// Player class, keeps track of what colour the player has picked to play.
class Player
{
    constructor() // Set the colour to white at the start.
    {
        this.colour = "white";
    }
    
    displayColour() // Return the current colour the place has chosen.
    {
        return this.colour;
    }
    setBlack() // Switch colour to black.
    {
        this.colour = 'black';
    }
    setWhite() // Switch colour to white.
    {
        this.colour = 'white';
    }
}

var user = new Player(); // Initialise the player class.

// DisplaySelect class which is the blue box that is what the user controls when moving.
class DisplaySelect
{
    constructor(x_cord, z_cord) // Set the cords of the selecter to somewhere on the board.
    {
        this.piecePosition = [x_cord, z_cord];
        this.parts = [];
    }
    displayPiece() // Displays the piece on the board
    {
        colour = new THREE.MeshBasicMaterial( { color: 'blue' } );
        theLeft = new THREE.Mesh(selectorSide, colour);
        theLeft.position.x = -195 + (50*this.piecePosition[0]); 
        theLeft.position.y = 25.5;
        theLeft.position.z = -175 + (50*this.piecePosition[1]);
        theRight = new THREE.Mesh(selectorSide, colour);
        theRight.position.x = -155 + (50*this.piecePosition[0]); 
        theRight.position.y = 25.5;
        theRight.position.z = -175 + (50*this.piecePosition[1]); 
        theBottom = new THREE.Mesh(selectorRoof, colour);
        theTop = new THREE.Mesh(selectorRoof, colour);
        theTop.position.x = -175 + (50*this.piecePosition[0]); 
        theTop.position.y = 25.5;
        theTop.position.z = -195 + (50*this.piecePosition[1]);
        theBottom.position.x = -175 + (50*this.piecePosition[0]); 
        theBottom.position.y = 25.5;
        theBottom.position.z = -155 + (50*this.piecePosition[1]);
        this.parts.push(theLeft,theRight,theBottom,theTop);
        ABWorld.scene.add(theLeft);
        ABWorld.scene.add(theRight);
        ABWorld.scene.add(theTop);
        ABWorld.scene.add(theBottom);
    }
    deletePiece() // Delete the piece from the board
    {
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            ABWorld.scene.remove(this.parts[i]);
        }
        
    }
    down() // Move the piece down
    {
        if (this.piecePosition[1] == 7)
        {
            return;
        }
        this.piecePosition[1] += 1;
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            this.parts[i].translateZ(50);
        }
    }
    up() // Move the piece up
    {
        if (this.piecePosition[1] === 0)
        {
            return;
        }
        this.piecePosition[1] -= 1;
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            this.parts[i].translateZ(-50);
        }
    }
    right() // Move the piece right
    {
        if (this.piecePosition[0] == 7)
        {
            return;
        }
        this.piecePosition[0] += 1;
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            this.parts[i].translateX(50);
        }
    }
    left() // Move the piece left
    {
        if (this.piecePosition[0] === 0)
        {
            return;
        }
        this.piecePosition[0] -= 1;
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            this.parts[i].translateX(-50);
        }
    }
    location() // Return the current location of the piece
    {
        return this.piecePosition;
    }
    
}

var part;
var enPassant = [];

// Pawn class 
class Pawn 
{
    constructor(x_cord, z_cord, pieceColour) // Sets the starting coordinate for the piece and the colour
    {
        this.piecePosition = [x_cord, z_cord];
        this.pieceColour = pieceColour;
        this.parts = [];
    } 
    displayPiece() // Displays the piece
    {
        if (this.pieceColour === 'white') // Displays the white model if its a white piece
        {
            part = chessPieces['children'][6].clone();
            part.scale.multiplyScalar ( .25 );
            part.position.x = -341 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = 375 + (50*this.piecePosition[1]);
        }
        else // Displays the black model if its a black piece
        {
            part = chessPieces['children'][0].clone();
            part.scale.multiplyScalar ( .25 );
            part.position.x = -341 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = 212 + (50*this.piecePosition[1]);
        }
        this.parts.push(part);
        ABWorld.scene.add(part); // Add the piece to the world
    }
    
    deletePiece() // Removes the piece model
    {
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            ABWorld.scene.remove(this.parts[i]);
        }
        
    }
    displayMoves() // Uses a different method for displaying moves as pawns can have a different type of move for their first.
    {
        var tmpXCord, tmpZCord;
        possibleMoves[0].push(this.piecePosition);
        if (this.pieceColour == 'white') // Direction switches by the colour of the piece.
        {
            tmpZCord = this.piecePosition[1] - 1;
        } else {
            tmpZCord = this.piecePosition[1] + 1;
        }
        tmpXCord = this.piecePosition[0];
        var lengthCheck;
        if (this.pieceColour == "black")
        {
            if (this.piecePosition[1] == 1) // If it is the pawns first move then it can move 2 spaces
            {
                lengthCheck = 2;
            } else 
            {
                lengthCheck = 1;
            }
        } else 
        {
            if (this.piecePosition[1] == 6)
            {
                lengthCheck = 2;
            } else 
            {
                lengthCheck = 1;
            }
        }
        
        for (var i = 0; i < lengthCheck; i++) // Loop to check the possible moves a piece could make
        {   
            if (tmpZCord == 8 || tmpZCord == -1 || tmpXCord == 8 || tmpXCord == -1) // Makes sure the coordinate is on the board
            {
                break;
            }
            if (map[tmpZCord][tmpXCord] == "")
            {
                displayOnBoard(tmpXCord,tmpZCord);
                possibleMoves[1].push([tmpXCord,tmpZCord]);
            } else
            {
                break;
            }
            if (this.pieceColour == 'white')
            {
                tmpZCord -= 1;
            } else {
                tmpZCord += 1;
            }
        }
        tmpXCord = this.piecePosition[0];
        tmpZCord = this.piecePosition[1];
        if (this.pieceColour == 'white') // Checks to see if the white pawn can take any pieces diagonal from it
        {
            if (tmpZCord != 8 && tmpZCord != 0 && tmpXCord != 7 && tmpXCord != -1 && map[tmpZCord - 1][tmpXCord + 1][0] == 'black') // Check that the piece is the opposite colour and is on the board
            {
                displayDeathOnBoard(tmpXCord + 1,tmpZCord - 1);
                possibleMoves[1].push([tmpXCord + 1,tmpZCord - 1]);
            } 
            if (tmpZCord != 8 && tmpZCord != 0 && tmpXCord != 8 && tmpXCord != 0 && map[tmpZCord - 1][tmpXCord - 1][0] == 'black')
            {
                displayDeathOnBoard(tmpXCord - 1, tmpZCord - 1);
                possibleMoves[1].push([tmpXCord - 1,tmpZCord - 1]);
            }
        } else { // Checks to see if the black pawn can take any pieces diagonal from it
            if (tmpZCord != 7 && tmpZCord != -1 && tmpXCord != 7 && tmpXCord != -1 && map[tmpZCord + 1][tmpXCord + 1][0] == 'white') // Check that the piece is the opposite colour and is on the board
            {
                displayDeathOnBoard(tmpXCord + 1,tmpZCord + 1);
                possibleMoves[1].push([tmpXCord + 1,tmpZCord + 1]);
            } 
            if (tmpZCord != 7 && tmpZCord != -1 && tmpXCord != 8 && tmpXCord != 0 && map[tmpZCord + 1][tmpXCord - 1][0] == 'white') 
            {
                displayDeathOnBoard(tmpXCord - 1, tmpZCord + 1);
                possibleMoves[1].push([tmpXCord - 1,tmpZCord + 1]);
            }
        }
        if (enPassant.length > 0) // En Passant check to see if this pawn could peform an En Passant maneuver. 
        {
            if (enPassant[0] == true) // If the list is set to true that means a pawn has just moved 2 pieces
            {
                length = 2;
                for (i = 0; i < length; i++)
                {
                    if (enPassant[1][i][0] == this.piecePosition[0] && enPassant[1][i][1] == this.piecePosition[1]) // If we are beside the pawn we can perform the maneuver
                    {
                        displayDeathOnBoard(enPassant[2][0], enPassant[2][1]);
                        possibleMoves[1].push(enPassant[2]);
                        console.log("We can En Passant this!")
                    }
                }
            }
        }
        
    }
    updatePosition(XCord, ZCord) // Updates on the board once the piece has been moved
    {
        var xPosition = XCord - this.piecePosition[0]; // Gets the difference between the original location and the new location
        var zPosition = ZCord - this.piecePosition[1];
        this.piecePosition[0] = XCord;
        this.piecePosition[1] = ZCord;
        length = this.parts.length;
        for (var i = 0; i < length; i++) // Translates the piece to the new postion
        {
            this.parts[i].translateX(xPosition * 50);
            this.parts[i].translateZ(zPosition * 50);
        }
    }
    checkKing() // For marking where the opposing king cant move too
    {
        var xCord = this.piecePosition[0]
        var zCord = this.piecePosition[1]
        if (this.pieceColour == "white")
        {
            if ((zCord - 1) <= 7 && (zCord - 1) >= 0 && (xCord + 1) <= 7 && (xCord + 1) >= 0)
            {
                checkMap[zCord - 1][xCord + 1] = "x";
            }
            if ((zCord - 1) <= 7 && (zCord - 1) >= 0 && (xCord - 1) <= 7 && (xCord - 1) >= 0)
            {
                checkMap[zCord - 1][xCord - 1] = "x";
            }
        } else 
        {
            if ((zCord + 1) <= 7 && (zCord + 1) >= 0 && (xCord + 1) <= 7 && (xCord + 1) >= 0)
            {
                checkMap[zCord + 1][xCord + 1] = "x";
            }
            if ((zCord + 1) <= 7 && (zCord + 1) >= 0 && (xCord - 1) <= 7 && (xCord - 1) >= 0)
            {
                checkMap[zCord + 1][xCord - 1] = "x";
            }
            
        }
    }
    
    pieceType() // Returns the name of the piece
    {
        return "pawn";
    }
}

// Rook class 
class Rook 
{
    constructor(x_cord, z_cord, pieceColour) // Sets the starting coordinate for the piece and the colour
    {
        this.piecePosition = [x_cord, z_cord];
        this.pieceColour = pieceColour;
        this.parts = [];
        this.hasMoved = false; // Has a special attribute used for Castling
    }
    displayPiece() // Displays the piece
    {
        if (this.pieceColour === 'white') // Displays the white model if its a white piece
        {
            part = chessPieces['children'][7].clone();
            part.scale.multiplyScalar ( .25 );
            part.position.x = -5 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = 378 + (50*this.piecePosition[1]);
        }
        else // Displays the black model if its a black piece
        {
            part = chessPieces['children'][1].clone();
            part.scale.multiplyScalar ( .25 );
            part.position.x = -5 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = 212 + (50*this.piecePosition[1]);
        }
        this.parts.push(part);
        ABWorld.scene.add(part); // Add the piece to the world
    }
    deletePiece() // Removes the piece model
    {
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            ABWorld.scene.remove(this.parts[i]);
        }
        
    }
    displayMoves() // Displays all the possible moves the rook piece can make
    {
        var xCord, zCord;
        possibleMoves[0].push(this.piecePosition);
        xCord = this.piecePosition[0];
        zCord = this.piecePosition[1];
        displayLineCheck([xCord, zCord], 0, 1, this.pieceColour) // Uses a function to perform the tasks of displaying a certain direction of moves
        displayLineCheck([xCord, zCord], 0, -1, this.pieceColour)
        displayLineCheck([xCord, zCord], 1, 0, this.pieceColour)
        displayLineCheck([xCord, zCord], -1, 0, this.pieceColour)
    }
    updatePosition(XCord, ZCord) // Updates on the board once the piece has been moved
    {
        var xPosition = XCord - this.piecePosition[0]; // Gets the difference between the original location and the new location
        var zPosition = ZCord - this.piecePosition[1];
        this.piecePosition[0] = XCord;
        this.piecePosition[1] = ZCord;
        length = this.parts.length;
        for (var i = 0; i < length; i++) // Translates the piece to the new postion
        {
            this.parts[i].translateX(xPosition * 50);
            this.parts[i].translateZ(zPosition * 50);
        }
    }
    pieceMoved() // When the castle has moved it can no longer castle with the king
    {
        this.hasMoved = true;
    }
    checkMove() // Returns whether the rook has moved
    {
        return this.hasMoved
    }
    pieceType() // Returns the name of the piece
    {
        return "rook";
    }
    checkKing() // For marking where the opposing king cant move too
    {
        var xCord = this.piecePosition[0];
        var zCord = this.piecePosition[1];
        lineCheck([xCord, zCord], 0, 1);
        lineCheck([xCord, zCord], 1, 0);
        lineCheck([xCord, zCord], 0, -1);
        lineCheck([xCord, zCord], -1, 0);
    }
}

// Knight class 
class Knight 
{
    constructor(x_cord, z_cord, pieceColour) // Sets the starting coordinate for the piece and the colour
    {
        this.piecePosition = [x_cord, z_cord];
        this.pieceColour = pieceColour;
        this.parts = [];
    }
    displayPiece() // Displays the piece
    {
        if (this.pieceColour === 'white') // Displays the white model if its a white piece
        {
            part = chessPieces['children'][8].clone();
            part.scale.multiplyScalar ( .25 );
            part.position.x = -277 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = -725 + (50*this.piecePosition[1]);
            part.rotation.y = Math.PI / 1; // Rotate the piece so it is facing the correct way
        }
        else // Displays the black model if its a black piece
        {
            part = chessPieces['children'][2].clone();
            part.scale.multiplyScalar ( .25 );
            part.position.x = -72 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = 212 + (50*this.piecePosition[1]);
        }
        this.parts.push(part);
        ABWorld.scene.add(part);
    }
    deletePiece() // Removes the piece model
    {
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            ABWorld.scene.remove(this.parts[i]);
        }
        
    }
    displayMoves() // Displays all the possible moves the knight piece can make
    {
        var tmpXCord, tmpZCord;
        possibleMoves[0].push(this.piecePosition);
        tmpXCord = this.piecePosition[0];
        tmpZCord = this.piecePosition[1];
        displaySingleCheck([tmpXCord, tmpZCord], 2,-1,this.pieceColour,this.pieceType()); // A knight uses a different function to display each move
        displaySingleCheck([tmpXCord, tmpZCord], 2,1,this.pieceColour,this.pieceType()); // This function does not use a for loop and simply displays the specific position
        displaySingleCheck([tmpXCord, tmpZCord], 1,2,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], 1,-2,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], -1,2,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], -1,-2,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], -2,-1,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], -2,1,this.pieceColour,this.pieceType());
        
    }
    updatePosition(XCord, ZCord) // Updates on the board once the piece has been moved
    {
        var xPosition = XCord - this.piecePosition[0]; // Gets the difference between the original location and the new location
        var zPosition = ZCord - this.piecePosition[1];
        this.piecePosition[0] = XCord;
        this.piecePosition[1] = ZCord;
        length = this.parts.length;
        if (this.pieceColour === 'white') // Translates the piece to the new postion
        {
            for (var i = 0; i < length; i++) // If the piece is white then it must move the opposite direction due to the fact the position of the piece was turned around
            {
                this.parts[i].translateX(xPosition * -50);
                this.parts[i].translateZ(zPosition * -50);
            }
        }
        else 
        {
            for (var i = 0; i < length; i++)
            {
                this.parts[i].translateX(xPosition * 50);
                this.parts[i].translateZ(zPosition * 50);
            }
        } 
    }
    checkKing() // For marking where the opposing king cant move too
    {
        var xCord = this.piecePosition[0];
        var zCord = this.piecePosition[1];
        singleValueCheck([xCord, zCord],2, -1)
        singleValueCheck([xCord, zCord],2, 1)
        singleValueCheck([xCord, zCord],1, 2)
        singleValueCheck([xCord, zCord],1, -2)
        singleValueCheck([xCord, zCord],-1, 2)
        singleValueCheck([xCord, zCord],-1, -2)
        singleValueCheck([xCord, zCord],-2, -1)
        singleValueCheck([xCord, zCord],-2, 1)
    }
    pieceType() // Returns the name of the piece
    {
        return "knight";
    }
}

// Bishop class
class Bishop 
{
    constructor(x_cord, z_cord, pieceColour) // Sets the starting coordinate for the piece and the colour
    {
        this.piecePosition = [x_cord, z_cord];
        this.pieceColour = pieceColour;
        this.parts = [];
    }
    displayPiece() // Displays the piece
    {
        if (this.pieceColour === 'white') // Displays the white model if its a white piece
        {
            part = chessPieces['children'][9].clone();
            part.scale.multiplyScalar (0.25);
            part.position.x = -210 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = -725 + (50*this.piecePosition[1]);
            part.rotation.y = Math.PI / 1;
        }
        else // Displays the black model if its a black piece
        {
            part = chessPieces['children'][3].clone();
            part.scale.multiplyScalar (0.25);
            part.position.x = -141 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = 212 + (50*this.piecePosition[1]);
        }
        this.parts.push(part);
        ABWorld.scene.add(part); // Add the piece to the world
    }
    deletePiece() // Removes the piece model
    {
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            ABWorld.scene.remove(this.parts[i]);
        }
        
    }
    displayMoves() // Displays all the possible moves the Bishop piece can make
    {
        var xCord, zCord;
        possibleMoves[0].push(this.piecePosition);
        xCord = this.piecePosition[0];
        zCord = this.piecePosition[1];
        displayLineCheck([xCord, zCord], 1, 1, this.pieceColour);
        displayLineCheck([xCord, zCord], 1, -1, this.pieceColour);
        displayLineCheck([xCord, zCord], -1, 1, this.pieceColour);
        displayLineCheck([xCord, zCord], -1, -1, this.pieceColour);
    }
    updatePosition(XCord, ZCord) // Updates on the board once the piece has been moved
    {
        var xPosition = XCord - this.piecePosition[0]; // Gets the difference between the original location and the new location
        var zPosition = ZCord - this.piecePosition[1];
        this.piecePosition[0] = XCord;
        this.piecePosition[1] = ZCord;
        length = this.parts.length;
        if (this.pieceColour === 'white') // Translates the piece to the new postion
        {
            for (var i = 0; i < length; i++) // If the piece is white then it must move the opposite direction due to the fact the position of the piece was turned around
            {
                this.parts[i].translateX(xPosition * -50);
                this.parts[i].translateZ(zPosition * -50);
            }
        }
        else 
        {
            for (var i = 0; i < length; i++)
            {
                this.parts[i].translateX(xPosition * 50);
                this.parts[i].translateZ(zPosition * 50);
            }
        }
    }
    checkKing() // For marking where the opposing king cant move too
    {
        var xCord = this.piecePosition[0];
        var zCord = this.piecePosition[1];
        lineCheck([xCord, zCord], 1, 1);
        lineCheck([xCord, zCord], 1, -1);
        lineCheck([xCord, zCord], -1, 1);
        lineCheck([xCord, zCord], -1, -1);
    }
    pieceType() // Returns the name of the piece
    {
        return "bishop";
    }
}

// Queen class
class Queen 
{
    constructor(x_cord, z_cord, pieceColour) // Sets the starting coordinate for the piece and the colour
    {
        this.piecePosition = [x_cord, z_cord];
        this.pieceColour = pieceColour;
        this.parts = [];
    }
    displayPiece() // Displays the piece
    {
        if (this.pieceColour === 'white') // Displays the white model if its a white piece
        {
            part = chessPieces['children'][10].clone();
            part.scale.multiplyScalar ( .25 );
            part.position.x = -140 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = -725 + (50*this.piecePosition[1]);
            part.rotation.y = Math.PI / 1; // Rotate the piece so it is facing the correct way
        }
        else // Displays the black model if its a black piece
        {
            part = chessPieces['children'][4].clone();
            part.scale.multiplyScalar ( .25 );
            part.position.x = -210 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = 212 + (50*this.piecePosition[1]);
        }
        this.parts.push(part);
        ABWorld.scene.add(part);
    }
    deletePiece() // Removes the piece model
    {
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            ABWorld.scene.remove(this.parts[i]);
        }
    }
    displayMoves() // Displays all the possible moves the Queen piece can make
    {
        var xCord, zCord;
        possibleMoves[0].push(this.piecePosition);
        xCord = this.piecePosition[0];
        zCord = this.piecePosition[1];
        displayLineCheck([xCord, zCord], 0, 1, this.pieceColour);
        displayLineCheck([xCord, zCord], 0, -1, this.pieceColour);
        displayLineCheck([xCord, zCord], 1, 0, this.pieceColour);
        displayLineCheck([xCord, zCord], -1, 0, this.pieceColour);
        displayLineCheck([xCord, zCord], 1, 1, this.pieceColour);
        displayLineCheck([xCord, zCord], 1, -1, this.pieceColour);
        displayLineCheck([xCord, zCord], -1, 1, this.pieceColour);
        displayLineCheck([xCord, zCord], -1, -1, this.pieceColour);
    }
    updatePosition(XCord, ZCord) // Updates on the board once the piece has been moved
    {
        var xPosition = XCord - this.piecePosition[0]; // Gets the difference between the original location and the new location
        var zPosition = ZCord - this.piecePosition[1];
        this.piecePosition[0] = XCord;
        this.piecePosition[1] = ZCord;
        length = this.parts.length;
        if (this.pieceColour === 'white') // Translates the piece to the new postion
        {
            for (var i = 0; i < length; i++) // If the piece is white then it must move the opposite direction due to the fact the position of the piece was turned around
            {
                this.parts[i].translateX(xPosition * -50);
                this.parts[i].translateZ(zPosition * -50);
            }
        }
        else 
        {
            for (var i = 0; i < length; i++)
            {
                this.parts[i].translateX(xPosition * 50);
                this.parts[i].translateZ(zPosition * 50);
            }
        }
    }
    checkKing() // For marking where the opposing king cant move too
    {
        var xCord = this.piecePosition[0];
        var zCord = this.piecePosition[1];
        lineCheck([xCord, zCord], 1, 1);
        lineCheck([xCord, zCord], 1, -1);
        lineCheck([xCord, zCord], -1, 1);
        lineCheck([xCord, zCord], -1, -1);
        lineCheck([xCord, zCord], 1, 0);
        lineCheck([xCord, zCord], -1, 0);
        lineCheck([xCord, zCord], 0, 1);
        lineCheck([xCord, zCord], 0, -1);
    }
    pieceType() // Returns the name of the piece
    {
        return "queen";
    }
}

// King class 
class King 
{
    constructor(x_cord, z_cord, pieceColour) // Sets the starting coordinate for the piece and the colour
    {
        this.piecePosition = [x_cord, z_cord];
        this.pieceColour = pieceColour;
        this.parts = [];
        this.hasMoved = false; // Has a special attribute used for Castling
    }
    displayPiece() // Displays the piece
    {
        if (this.pieceColour === 'white') // Displays the white model if its a white piece
        {
            part = chessPieces['children'][11].clone();
            part.scale.multiplyScalar ( 0.25 );
            part.position.x = -71 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = -725 + (50*this.piecePosition[1]);
            part.rotation.y = Math.PI / 1; // Rotate the piece so it is facing the correct way
        }
        else // Displays the black model if its a black piece
        {
            part = chessPieces['children'][5].clone();
            part.scale.multiplyScalar ( 0.25 );
            part.position.x = -279 + (50*this.piecePosition[0]);
            part.position.y = 25;
            part.position.z = 212 + (50*this.piecePosition[1]);
        }
        this.parts.push(part);
        ABWorld.scene.add(part);
    }
    deletePiece() // Removes the piece model
    {
        length = this.parts.length;
        for (var i = 0; i < length; i++)
        {
            ABWorld.scene.remove(this.parts[i]);
        }
    }
    displayMoves() // Displays all the possible moves the king piece can make
    {
        var tmpXCord, tmpZCord;
        possibleMoves[0].push(this.piecePosition);
        tmpXCord = this.piecePosition[0];
        tmpZCord = this.piecePosition[1];
        displaySingleCheck([tmpXCord, tmpZCord], 1,-1,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], 1,0,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], 1,1,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], 0,1,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], 0,-1,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], -1,-1,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], -1,0,this.pieceColour,this.pieceType());
        displaySingleCheck([tmpXCord, tmpZCord], -1,1,this.pieceColour,this.pieceType());
        if (map[tmpZCord][tmpXCord][2].checkMove() === false && map[tmpZCord][tmpXCord + 1] === "" && map[tmpZCord][tmpXCord + 2] === "" && map[tmpZCord][tmpXCord + 3] !== "" && map[tmpZCord][tmpXCord + 3][2].pieceType() == "rook" && map[tmpZCord][tmpXCord + 3][2].checkMove() === false)
        {
            displaySingleCheck([tmpXCord, tmpZCord], 2,0,this.pieceColour,this.pieceType());
        }
        if (map[tmpZCord][tmpXCord][2].checkMove() === false && map[tmpZCord][tmpXCord - 1] === "" && map[tmpZCord][tmpXCord - 2] === "" &&  map[tmpZCord][tmpXCord - 3] === "" && map[tmpZCord][tmpXCord - 4] !== "" && map[tmpZCord][tmpXCord - 4][2].pieceType() == "rook" && map[tmpZCord][tmpXCord - 4][2].checkMove() === false)
        {
            displaySingleCheck([tmpXCord, tmpZCord], -2,0,this.pieceColour,this.pieceType());
        }
    }
    updatePosition(XCord, ZCord) // Updates on the board once the piece has been moved
    {
        var xPosition = XCord - this.piecePosition[0]; // Gets the difference between the original location and the new location
        var zPosition = ZCord - this.piecePosition[1];
        this.piecePosition[0] = XCord;
        this.piecePosition[1] = ZCord;
        length = this.parts.length;
        if (this.pieceColour === 'white') // Translates the piece to the new postion
        {
            for (var i = 0; i < length; i++) // If the piece is white then it must move the opposite direction due to the fact the position of the piece was turned around
            {
                this.parts[i].translateX(xPosition * -50);
                this.parts[i].translateZ(zPosition * -50);
            }
        }
        else 
        {
            for (var i = 0; i < length; i++)
            {
                this.parts[i].translateX(xPosition * 50);
                this.parts[i].translateZ(zPosition * 50);
            }
        }
    }
    checkKing() // For marking where the opposing king cant move too
    {
        var xCord = this.piecePosition[0];
        var zCord = this.piecePosition[1];
        singleValueCheck([xCord, zCord],0, 1);
        singleValueCheck([xCord, zCord],1, 1);
        singleValueCheck([xCord, zCord],-1, 1);
        singleValueCheck([xCord, zCord],-1, 0);
        singleValueCheck([xCord, zCord],1, 0);
        singleValueCheck([xCord, zCord],0, -1);
        singleValueCheck([xCord, zCord],1, -1);
        singleValueCheck([xCord, zCord],-1, -1);
    }
    pieceMoved()
    {
        this.hasMoved = true;
    }
    checkMove()
    {
        return this.hasMoved;
    }
    pieceType() // Returns the name of the piece
    {
        return "king";
    }
}

var displaySelector = new DisplaySelect(0,0); // initialise the selecter at postion 0,0

// Loop through a given direction displaying possible moves
function displayLineCheck(location, xCordDifference, zCordDifference, colour)
{
    var tmpXCord, tmpZCord;
    tmpXCord = location[0];
    tmpZCord = location[1];
    for (var i = 0; i < 8; i++) // Uses the same diagonal display moves as the Bishop class
    {   
        tmpZCord += zCordDifference; // Changing the z cord
        tmpXCord += xCordDifference; // Changing the x cord
        if (tmpZCord == 8 || tmpZCord == -1 || tmpXCord == 8 || tmpXCord == -1)  // Break the loop if the square is not blank or the coordinate is out of the board
        {
            break; // Break if any of the points are out of the 7x7 array
        }
        if (map[tmpZCord][tmpXCord] === "") // If an empty spot then display it as a move
        {
            displayOnBoard(tmpXCord,tmpZCord);
            possibleMoves[1].push([tmpXCord,tmpZCord]);
            
        } else if (map[tmpZCord][tmpXCord][0] !== colour) // If not empty but the opposite players colour then display it as a kill attempt
        {
            displayDeathOnBoard(tmpXCord,tmpZCord);
            possibleMoves[1].push([tmpXCord,tmpZCord]);
            break;
        } else
        {
            break;
        }
    }
}

// Check given input displaying it if its a possible move
function displaySingleCheck(location, xCordDifference, zCordDifference, colour, type)
{
    var tmpXCord, tmpZCord;
    tmpXCord = location[0] + xCordDifference;
    tmpZCord = location[1] + zCordDifference;
    if (tmpZCord > 7 || tmpZCord < 0 || tmpXCord > 7 || tmpXCord < 0)  // Checks to make sure the changed positions are on the board
    {
        return;
    }
    if (map[tmpZCord][tmpXCord] === "")
    {
        if (type == "king") // Checks if its a king checking its moves as a king wont be able to move into a square that a opposite piece could move too
        {
            if (checkMap[tmpZCord][tmpXCord] === "") // Checks on the checkMap to make sure their isnt an opposing piece watching that position
            {
                displayOnBoard(tmpXCord,tmpZCord);
                possibleMoves[1].push([tmpXCord,tmpZCord]);
                return;
            }
        } else 
        {
            displayOnBoard(tmpXCord,tmpZCord);
            possibleMoves[1].push([tmpXCord,tmpZCord]);
            return;
        }
        
    } else if (map[tmpZCord][tmpXCord][0] !== colour) // Same checks apply like the previous
    {
        if (type == "king")
        {
            if (checkMap[tmpZCord][tmpXCord] === "")
            {
                displayDeathOnBoard(tmpXCord,tmpZCord);
                possibleMoves[1].push([tmpXCord,tmpZCord]);
                return;
            }
        } else 
        {
            displayDeathOnBoard(tmpXCord,tmpZCord);
            possibleMoves[1].push([tmpXCord,tmpZCord]);
            return;
        }
    }
}

// For Positioning Pieces
// -----------------------------------------------------------------------------------------------------------------
var HL00,HL01,HL02,HL03,HL04,HL05,HL06,HL07,HL10,HL11,HL12,HL13,HL14,HL15,HL16,HL17,HL20,HL21,HL22,HL23,HL24,HL25,HL26,HL27,HL30,HL31,HL32,HL33,HL34,HL35,HL36,HL37,HL40,HL41,HL42,HL43,HL44,HL45,HL46,HL47,HL50,HL51,HL52,HL53,HL54,HL55,HL56,HL57,HL60,HL61,HL62,HL63,HL64,HL65,HL66,HL67,HL70,HL71,HL72,HL73,HL74,HL75,HL76,HL77; // Used for showing possible moves

var possibleMoves = [[],[]]; // Possible moves stores where a piece could be moved too

var BP1,BP2,BP3,BP4,BP5,BP6,BP7,BP8; // Pawns
var WP1,WP2,WP3,WP4,WP5,WP6,WP7,WP8; // Pawns

var BR1, BR2; // Rooks
var WR1, WR2; // Rooks
var BKN1, BKN2; // Knights
var WKN1, WKN2; // Knights
var BB1, BB2; // Bishops
var WB1, WB2; // Bishops
var BQ; // Queen
var WQ; // Queen
var BK; // King
var WK; // King



var theLeft, theRight, theBottom, theTop; // For Selector
var theLeftKill, theRightKill, theBottomKill, theTopKill; // Displaying the kill box for a piece

// Map of the board and the location of all the pieces
var map = [[['black','R',BR1],['black','Kn',BKN1],['black','B',BB1],['black','Q',BQ],['black','K',BK],['black','B',BB2],['black','Kn',BKN2],['black','R',BR2]],
           [['black','P',BP1],['black','P',BP2],['black','P',BP3],['black','P',BP4],['black','P',BP5],['black','P',BP6],['black','P',BP7],['black','P',BP8]],
           ['','','','','','','',''],
           ['','','','','','','',''],
           ['','','','','','','',''],
           ['','','','','','','',''],
           [['white','P',WP1],['white','P',WP2],['white','P',WP3],['white','P',WP4],['white','P',WP5],['white','P',WP6],['white','P',WP7],['white','P',WP8]],
           [['white','R',WR1],['white','Kn',BKN1],['white','B',WB1],['white','Q',WQ],['white','K',WK],['white','B',WB2],['white','Kn',WKN2],['white','R',WR2]]];

// CheckMap will display all the places the opposing pieces could take, if the king moved there
var checkMap = [['','','','','','','',''],
           ['','','','','','','',''],
           ['','','','','','','',''],
           ['','','','','','','',''],
           ['','','','','','','',''],
           ['','','','','','','',''],
           ['','','','','','','',''],
           ['','','','','','','','']];

// Map of variables used to display the possible move locations
var mapMoves = [[HL00,HL01,HL02,HL03,HL04,HL05,HL06,HL07],
               [HL10,HL11,HL12,HL13,HL14,HL15,HL16,HL17],
               [HL20,HL21,HL22,HL23,HL24,HL25,HL26,HL27],
               [HL30,HL31,HL32,HL33,HL34,HL35,HL36,HL37],
               [HL40,HL41,HL42,HL43,HL44,HL45,HL46,HL47],
               [HL50,HL51,HL52,HL53,HL54,HL55,HL56,HL57],
               [HL60,HL61,HL62,HL63,HL64,HL65,HL66,HL67],
               [HL70,HL71,HL72,HL73,HL74,HL75,HL76,HL77]];

// Function for displaying the yellow box of a move on the board
function displayOnBoard(xCord,zCord)
{
    colour = new THREE.MeshBasicMaterial( { color: 'yellow' } );
    mapMoves[zCord][xCord] = new THREE.Mesh(nextMove, colour);
    mapMoves[zCord][xCord].position.x = -175 + (50 * xCord);
    mapMoves[zCord][xCord].position.y = 25.5;
    mapMoves[zCord][xCord].position.z = -175 + (50 * zCord);
    ABWorld.scene.add(mapMoves[zCord][xCord]);
}

// Function for displaying the red kill box around the opposite colour of a piece
function displayDeathOnBoard(xCord,zCord)
{
    colour = new THREE.MeshBasicMaterial( { color: 'red' } );
    mapMoves[zCord][xCord] = [];
    theLeftKill = new THREE.Mesh(nextKillSide, colour);
    theLeftKill.position.x = -195 + (50*xCord); 
    theLeftKill.position.y = 26.5;
    theLeftKill.position.z = -175 + (50*zCord);
    theRightKill = new THREE.Mesh(nextKillSide, colour);
    theRightKill.position.x = -155 + (50*xCord); 
    theRightKill.position.y = 26.5;
    theRightKill.position.z = -175 + (50*zCord); 
    theBottomKill = new THREE.Mesh(nextKillRoof, colour);
    theBottomKill.position.x = -175 + (50*xCord); 
    theBottomKill.position.y = 26.5;
    theBottomKill.position.z = -155 + (50*zCord);
    theTopKill = new THREE.Mesh(nextKillRoof, colour);
    theTopKill.position.x = -175 + (50*xCord); 
    theTopKill.position.y = 26.5;
    theTopKill.position.z = -195 + (50*zCord);
    mapMoves[zCord][xCord].push(theLeftKill,theRightKill,theBottomKill,theTopKill);
    ABWorld.scene.add(theLeftKill);
    ABWorld.scene.add(theRightKill);
    ABWorld.scene.add(theBottomKill);
    ABWorld.scene.add(theTopKill);
}

// Function for comparing the socket information with what is on this current board
function compareInput(first, second)
{
    enPassantBoolean = false;
    var tmp = map[first[1]][first[0]]; // Get the first location which is the original location of the piece
    if (tmp[2].pieceType() == "king" && tmp[2].checkMove() === false)
    {
        if (map[second[1]][second[0]] === '')
        {
            castleCheck(tmp, second);
        }
    }    
    if (map[second[1]][second[0]] === '') // If the second location is empty then simply move the piece
    {
        if (tmp[2].pieceType() == "pawn")
        {
            if (enPassant.length > 0 && second[0] == enPassant[2][0] && second[1] == enPassant[2][1])
            {
                deathSound.play(); // Play death sound
                map[enPassant[3][1]][enPassant[3][0]][2].deletePiece();
                map[enPassant[3][1]][enPassant[3][0]] = '';
            } else 
            {
                enPassantCheck(tmp, [first[0], first[1]], second);
            }
        }
        map[second[1]][second[0]] = tmp;
        map[first[1]][first[0]] = '';
        map[second[1]][second[0]][2].updatePosition(second[0],second[1]);
    } else if (map[second[1]][second[0]] !== '') // If the second location is not empty then delete the piece there and move the piece
    {
        deathSound.play(); // Play death sound
        if (map[second[1]][second[0]][2].pieceType() == "king")
        {
            chessGame.gameOver(map[first[1]][first[0]][0]);
        }
        map[second[1]][second[0]][2].deletePiece();
        map[second[1]][second[0]] = tmp;
        map[first[1]][first[0]] = '';
        map[second[1]][second[0]][2].updatePosition(second[0],second[1]);
    }
    if (second[1] === 0 || second[1] == 7) // If it is the first or last row check 
    {
        if (map[second[1]][second[0]][2].pieceType() == "pawn") // If the piece on the first or last row is a pawn then change that pawn into a queen
        {
            map[second[1]][second[0]][2].deletePiece();
            map[second[1]][second[0]][2] = undefined;
            map[second[1]][second[0]][2] = new Queen(second[0],second[1],map[second[1]][second[0]][0]); // Initialise the queen in the correct board location
            map[second[1]][second[0]][2].displayPiece(); // Display the new queen
        }
    }
}

// Remove all the possible moves from the board, i.e. the yellow boxes and reb boxes
function removeFromBoard()
{
    length = possibleMoves[1].length;
    for (var i = 0; i < length; i++) // Loop through the possiblemoves list and remove them from the board
    {
        if (Array.isArray(mapMoves[possibleMoves[1][i][1]][possibleMoves[1][i][0]]))
        {
            var lengthMini = mapMoves[possibleMoves[1][i][1]][possibleMoves[1][i][0]].length;
            for (var j = 0; j < lengthMini;j++)
            {
                ABWorld.scene.remove(mapMoves[possibleMoves[1][i][1]][possibleMoves[1][i][0]][j]);
            }
            mapMoves[possibleMoves[1][i][1]][possibleMoves[1][i][0]] = undefined;
            
        } else {
            ABWorld.scene.remove(mapMoves[possibleMoves[1][i][1]][possibleMoves[1][i][0]]);
        }
    }
}

// For 3D Graphics
// -----------------------------------------------------------------------------------------------------------------

// Set the gridsize
const gridsize = 8;

// Measurements for the board boxes
var boardCube = new THREE.BoxGeometry (50,50,50);

// Function for displaying the board
function displayBoard()
{
    var evenOdd = 1;
    for (var i = 0; i < gridsize; i += 1)
    {
        for (var j = 0; j < gridsize; j += 1)
        {
            if (evenOdd % 2 === 0) // Switch between the colours so the it has a grid pattern
            {
                colour = new THREE.MeshBasicMaterial( { map: walnutCube } );
            }
            else
            {
                colour = new THREE.MeshBasicMaterial( {  map: beechCube } );
    
            }
            theCube = new THREE.Mesh(boardCube, colour);
            theCube.position.x = -175 +(50 * j);
            theCube.position.z = -175 +(50 * i);
            ABWorld.scene.add(theCube); // DIsplay the cubes on the board
            evenOdd += 1;
        }
        evenOdd += 1;
    }
}

// Function for displaying pieces at the start of the game
function displayPieces()
{
    for (var i = 0; i < gridsize; i += 1)
    {
        for (var j = 0; j < gridsize; j += 1) // Loop through the grid and when the pieces are reached initialise them
        {
            if (map[i][j] != ' ') // If there is a piece, work out which piece it is
            {
                if (map[i][j][1] == 'P')  // If it is a P then the piece is a pawn
                {
                    map[i][j][2] = new Pawn(j,i,map[i][j][0]); // Initialise the pawn
                    map[i][j][2].displayPiece(); // Display the piece
                } else if (map[i][j][1] == 'R') // If it is a R then the piece is a rook
                {
                    map[i][j][2] = new Rook(j,i,map[i][j][0]); // Initialise the rook
                    map[i][j][2].displayPiece(); // Display the piece
                }
                else if (map[i][j][1] == 'Kn') // If it is a Kn then the piece is a knight
                {
                    map[i][j][2] = new Knight(j,i,map[i][j][0]); // Initialise the knight
                    map[i][j][2].displayPiece(); // Display the piece
                }
                else if (map[i][j][1] == 'B') // If it is a B then the piece is a bishop
                {
                    map[i][j][2] = new Bishop(j,i,map[i][j][0]); // Initialise the bishop
                    map[i][j][2].displayPiece(); // Display the piece
                }
                else if (map[i][j][1] == 'Q') // If it is a Q then the piece is a queen
                {
                    map[i][j][2] = new Queen(j,i,map[i][j][0]); // Initialise the queen
                    map[i][j][2].displayPiece(); // Display the piece
                }
                else if (map[i][j][1] == 'K') // If it is a K then the piece is a king
                {
                    map[i][j][2] = new King(j,i,map[i][j][0]); // Initialise the king
                    map[i][j][2].displayPiece(); // Display the piece
                }
            }
        }
    }
}


// Handling Inputs
// -----------------------------------------------------------------------------------------------------------------

function keyHandler(event)		
{
    if (event.keyCode == 37) // If the left arrow is clicked then move the selector left
    {
        displaySelector.left();
    }
    else if (event.keyCode == 38) // If the up arrow is clicked then move the selector up
    {
        displaySelector.up();
    }
    else if (event.keyCode == 39) // If the right arrow is clicked then move the selector right
    {
        displaySelector.right();
    }
    else if (event.keyCode == 40) // If the down arrow is clicked then move the selector down
    {
        displaySelector.down();
    }
    else if (event.keyCode == 13) // If the Enter key is clicked then check what the user wants
    {
        length = possibleMoves[1].length;
        for (var i = 0; i < length; i++) // Check to see if the user has clicked a piece before
        {
            if (possibleMoves[1][i][0] == displaySelector.location()[0] && possibleMoves[1][i][1] == displaySelector.location()[1]) // If the user has clicked enter over a possible move location then make the move happen
            {
                chessGame.switchTurn(); // Switch the turn of the game
                updateOnAllBoards([possibleMoves[0][0][0],possibleMoves[0][0][1]], displaySelector.location()); // Send to the socket sender so all people on the game get the updated positions
                movingPieceOnBoard(); // Move the piece on the board
                removeFromBoard(); // Remove the possible moves from the board
                possibleMoves = [[],[]]; // Reset the possible moves list
                return; // Leave the functions
            }
        } // If the user didnt pick a possible move location then check what they clicked enter on
        removeFromBoard(); // Remove the possible moves from the board
        possibleMoves = [[],[]]; // Rest the possible moves list
        if (map[displaySelector.location()[1]][displaySelector.location()[0]] !== '') // If they clicked enter over a non empty area then display the moves of that piece if it is their colour
        {
            if (user.displayColour() == map[displaySelector.location()[1]][displaySelector.location()[0]][0] && chessGame.displayTurn() == map[displaySelector.location()[1]][displaySelector.location()[0]][0])
            {
                map[displaySelector.location()[1]][displaySelector.location()[0]][2].displayMoves(); // Display the moves of the piece the user clicked
            }
        }
    }
    else if (event.keyCode == 32) // Click spawn for testing
    {
        console.log(map);
    }
}

//
// Check for king check

// Marks all the postions a piece can take in a certain direction
function lineCheck(location, xCordDifference, zCordDifference)
{
    tmpXCord = location[0];
    tmpZCord = location[1];
    for (var i = 0; i < 8; i++) // Loop through displaying the possible moves that the piece could take
        {   
            tmpXCord += xCordDifference;
            tmpZCord += zCordDifference;
            if (tmpZCord == 8 || tmpZCord == -1 || tmpXCord == 8 || tmpXCord == -1) // Break the loop if the coordinate is out of the board
            {
                break;
            }
            if (map[tmpZCord][tmpXCord] === "") // If the space is blank add it to the array
            {
                checkMap[tmpZCord][tmpXCord] = "x";
            } else if (map[tmpZCord][tmpXCord] !== "") // If the space has a piece add it to the array and break the for loop
            {
                checkMap[tmpZCord][tmpXCord] = "x";
                break;
            } else {
                break;
            }
        }
}

// Marks if a postion can be moved too by a piece
function singleValueCheck(location, xCordDifference, zCordDifference)
{
    tmpXCord = location[0] + xCordDifference;
    tmpZCord = location[1] + zCordDifference;
    if (tmpZCord > 7 || tmpZCord < 0 || tmpXCord > 7 || tmpXCord < 0) // leave the function if the coordinate is out of the board
    {
        return;
    }
    if (map[tmpZCord][tmpXCord] === "")
    {
        checkMap[tmpZCord][tmpXCord] = "x";
        return;
    } else if (map[tmpZCord][tmpXCord] !== "")
    {
        checkMap[tmpZCord][tmpXCord] = "x";
        return;
    } 
}

// Resets the map of where a king can't move too once the go is over
function clearTheMap(checkMap)
{
    for (var i = 0; i < 8; i++)
    {
        for (var j = 0; j < 8; j++)
        {
            checkMap[i][j] = "";
        }
    }
}

// Displays the warning once your king has been placed in check
function splashCheck()
{
    if (chessGame.turn == "white")
    {
        return "<hr> <p> Warning <p> <hr> <p>White player has put you in check!<p> <button onclick='AB.removeSplash()'>Continue Game</button>";
    } else 
    {
        return "<hr> <p> Warning <p> <hr> <p>Black player has put you in check!<p> <button onclick='AB.removeSplash()'>Continue Game</button>";
        
    }
}

// Will check to see if the king is currently in check
function kingCheckMateCheck()
{
    clearTheMap(checkMap);
    var colour = chessGame.turn;
    var kingLocation;
    for (var i = 0; i < 8; i++)
    {
        for (var j = 0; j < 8; j++)
        {
            if (map[i][j] !== '')
            {
                if (map[i][j][0] == colour)
                {
                    map[i][j][2].checkKing();
                } else if (map[i][j][2].pieceType() == "king") // Save the kings position
                {
                    kingLocation = map[i][j][2].piecePosition;
                }
            }
        }
    }
    if (checkMap[kingLocation[1]][kingLocation[0]]) // If the kings positon has a 'x' on it in checkMap then it is in check
    {
        AB.newSplash();
        AB.splashHtml(splashCheck());
    }
}

// Will update a king or rook so they have made their first move
function checkFirstTurn(piece)
{
    if (piece.pieceType() == "king" || piece.pieceType() == "rook")
    {
        piece.pieceMoved();
    }
    return piece;
}

// Castle check to see if a player has moved to perform a castle manoeuvre
function castleCheck(tmp, list)
{
    if (tmp[0] == "white") // Checks if king is white
    {
        if (map[7][0][1] == 'R') // Check the white rook is in the right position
        {
            if (map[7][0][2].checkMove() === false) // Check the white rook has not moved
            {
                if (list[0] == 2 && list[1] == 7) // If it has moved to the side of the king, perform the castle manoeuvre
                {
                    var tmpRook = map[7][0];
                    map[7][3] = tmpRook;
                    map[7][0] = '';
                    map[7][3][2].updatePosition(3,7);
                    
                }
            }
        }
        if (map[7][7][1] == 'R') // Check the white rook is in the right position
        {
            if (map[7][7][2].checkMove() === false) // Check the white rook has not moved
            {
                if (list[0] == 6 && list[1] == 7) // If it has moved to the side of the king, perform the castle manoeuvre
                {
                    var tmpRook = map[7][7];
                    map[7][5] = tmpRook;
                    map[7][7] = '';
                    map[7][5][2].updatePosition(5,7);
                    
                }
            }
        }
    } else if (tmp[0] == "black") // Checks if king is black
    {
        if (map[0][0][1] == 'R') // Check the black rook is in the right position
        {
            if (map[0][0][2].checkMove() === false) // Check the black rook has not moved
            {
                if (list[0] == 2 && list[1] === 0) // If it has moved to the side of the king, perform the castle manoeuvre
                {
                    var tmpRook = map[0][0];
                    map[0][3] = tmpRook;
                    map[0][0] = '';
                    map[0][3][2].updatePosition(3,0);
                    
                }
            }
        }
        if (map[0][7][1] == 'R') // Check the black rook is in the right position
        {
            if (map[0][7][2].checkMove() === false) // Check the black rook has not moved
            {
                if (list[0] == 6 && list[1] === 0) // If it has moved to the side of the king, perform the castle manoeuvre
                {
                    var tmpRook = map[0][7];
                    map[0][5] = tmpRook;
                    map[0][7] = '';
                    map[0][5][2].updatePosition(5,0);
                    
                }
            }
        }
    }
}

// The En Passant check function
var enPassantBoolean;
function enPassantCheck(piece, first, second)
{
    if (piece[2].pieceColour == "white") // If a white pawn was moved
    {
        if (first[1] == 6) // From starting point and made a 2 jump move, it could be En Passanted
        {
            if (second[1] == 4)
            {
                // Save the location, in case a black pawn is nearby
                enPassant = [true, [[second[0] + 1, second[1]], [second[0] - 1, second[1]]], [second[0], second[1] + 1], [second[0],second[1]]];
                enPassantBoolean = true; // Set En Passant Boolean to true so the list is not reset
            }
        }
    } else if (piece[2].pieceColour == "black") // If a black pawn was moved
    {
        if (first[1] == 1) // From starting point and made a 2 jump move, it could be En Passanted
        {
            if (second[1] == 3)
            {
                // Save the location, in case a white pawn is nearby
                enPassant = [true, [[second[0] + 1, second[1]], [second[0] - 1, second[1]]], [second[0], second[1] - 1], [second[0],second[1]]];
                enPassantBoolean = true;
            }
        }
    }
}

// Function for moving a piece on the board locacally
function movingPieceOnBoard()
{
    enPassantBoolean = false;
    var tmp = map[possibleMoves[0][0][1]][possibleMoves[0][0][0]]; // Get the original location of the piece
    if (tmp[2].pieceType() == "king" && tmp[2].checkMove() === false)
    {
        if (map[displaySelector.location()[1]][displaySelector.location()[0]] === '')
        {
            castleCheck(tmp, displaySelector.location());
        }
    }
    if (map[displaySelector.location()[1]][displaySelector.location()[0]] === '') // If the location it is being moved to is empty then simply move the piece
    {
        tmp[2] = checkFirstTurn(tmp[2]);
        if (tmp[2].pieceType() == "pawn")
        {
            if (enPassant.length > 0 && displaySelector.location()[0] == enPassant[2][0] && displaySelector.location()[1] == enPassant[2][1]) // If the displayselector was moved to the En Passant position then delete the pawn
            {
                deathSound.play(); // Play death sound
                map[enPassant[3][1]][enPassant[3][0]][2].deletePiece();
                map[enPassant[3][1]][enPassant[3][0]] = '';
            } else 
            {
                enPassantCheck(tmp, [possibleMoves[0][0][0], possibleMoves[0][0][1]], displaySelector.location());
            }
        }
        map[displaySelector.location()[1]][displaySelector.location()[0]] = tmp;
        map[possibleMoves[0][0][1]][possibleMoves[0][0][0]] = '';
        map[displaySelector.location()[1]][displaySelector.location()[0]][2].updatePosition(displaySelector.location()[0],displaySelector.location()[1]);
    } else if (map[displaySelector.location()[1]][displaySelector.location()[0]] !== '') // If the location it is being moved to is not empty then delete the piece then move it
    {
        deathSound.play(); // Play death sound
        tmp[2] = checkFirstTurn(tmp[2]);
        if (map[displaySelector.location()[1]][displaySelector.location()[0]][2].pieceType() == "king")
        {
            chessGame.gameOver(map[possibleMoves[0][0][1]][possibleMoves[0][0][0]][0]);
        }
        map[displaySelector.location()[1]][displaySelector.location()[0]][2].deletePiece();
        map[displaySelector.location()[1]][displaySelector.location()[0]] = tmp;
        map[possibleMoves[0][0][1]][possibleMoves[0][0][0]] = '';
        map[displaySelector.location()[1]][displaySelector.location()[0]][2].updatePosition(displaySelector.location()[0],displaySelector.location()[1]);
    }
    if (displaySelector.location()[1] === 0 || displaySelector.location()[1] == 7) // If it is the first or last row check
        {
            if (map[displaySelector.location()[1]][displaySelector.location()[0]][2].pieceType() == "pawn") // If the piece on the first or last row is a pawn then change that pawn into a queen
            {
                map[displaySelector.location()[1]][displaySelector.location()[0]][2].deletePiece();
                map[displaySelector.location()[1]][displaySelector.location()[0]][2] = undefined;
                map[displaySelector.location()[1]][displaySelector.location()[0]][2] = new Queen(displaySelector.location()[0],displaySelector.location()[1],map[displaySelector.location()[1]][displaySelector.location()[0]][0]); // Initialise the queen in the correct board location
                map[displaySelector.location()[1]][displaySelector.location()[0]][2].displayPiece(); // Display the new queen
            }
        }
    if (enPassantBoolean === false) // Reset En Passant if no pawn made a 2 move
    {
        enPassant = [];
    }
}

// Have a light for showing the pieces
const LIGHTCOLOR 	= 0xffffff ;

// Commands in the side of the screen for users using the game
function commands()
{
    if (chessGame.displayTurn() == "white") // Picking white team
    {
        AB.msg ( ` <hr> <p> Chess game. Pick a side. Click buttons to pick colour. <p>
  	        <button onclick='user.setBlack()'  class=ab-largenormbutton > Black </button>  
            <button onclick='user.setWhite()'  class=ab-largenormbutton > White </button> <p> 
            <h1>White Turn</h1>
            </hr>`);
    }
    else if (chessGame.displayTurn() == "black") // Picking black team
    {
        AB.msg ( ` <hr> <p> Chess game. Pick a side. Click buttons to pick colour. <p>
  	        <button onclick='user.setBlack()'  class=ab-largenormbutton > Black </button>  
            <button onclick='user.setWhite()'  class=ab-largenormbutton > White </button> <p> 
            <h1>Black Turn</h1>
            </hr>`);
    }
}

var chessGame = new Game(); // initialise the game

AB.world.newRun = function()
{
	ABWorld.init3d ( startRadius, maxRadius, skycolor );
	loadResources(); // Load the models in
	displayBoard(); // Display the board
	displaySelector.displayPiece(); // Display the selector piece
	ABWorld.scene.background = new THREE.CubeTextureLoader().load ( skyboxArray,	function() 
	 { 
		ABWorld.render(); 
		AB.removeLoading();
	 });
	
	var thelight = new THREE.DirectionalLight ( LIGHTCOLOR, 1 ); // Set up the light
    thelight.position.set ( startRadius, startRadius, startRadius ); // Set a location for it
    ABWorld.scene.add(thelight); // Add it ot the world
    var newthelight = new THREE.DirectionalLight ( LIGHTCOLOR, 1 ); // Set up the light
    newthelight.position.set ( -500, 500, -500 ); // Set a location for it
    ABWorld.scene.add(newthelight); // Add it ot the world
    commands(); // Add it to the world
};


var turn = 0;
AB.world.nextStep = function()
{
	document.onkeydown = keyHandler; // Key handler for inputs
	if (chessGame.winner == true && turn == 0)
	{
	    setTimeout(function () 
	    {
	        AB.world.endRun();
	    }, 200);
	    turn = 1;
	}
};

AB.world.endRun = function()
{
    AB.newSplash();
    AB.splashHtml(splashEnd());
};

// Game over screen, with reset to start new game
function splashEnd()
{
    if (chessGame.colourWinner == "white")
    {
        return "<hr> <p> Game is complete <p> <hr> <p>White player won the game<p> <button onclick='window.location.reload(true)'>New Game</button>";
    } else 
    {
        return "<hr> <p> Game is complete <p> <hr> <p>Black player won the game<p> <button onclick='window.location.reload(true)'>New Game</button>";
    }
}

// Game is full screen
function splashFull()
{
    return "<hr> Game is full please try again later <hr>";
}

// Start Socket

AB.socketStart();

function updateOnAllBoards(first, second) // First co-ordinate is where the piece was, second co-ordinate is where the piece was moved too.
{
    if ( AB.socket )
    {
        if (AB.socket.connected)
        {
            data = { first : first,
                     second : second
            };
            AB.socketOut (data); // Sends the data to the other clients.
        }
    }
    commands();
}

var safe = false;

// Checks the amount of users on the world, if more then 2 then you can not play
AB.socketUserlist = function(userList)
{
    console.log(userList);
    console.log(AB.runReady);
    if (userList.length > 2 && safe === false) // If more then 2 then you don't get to play
    {
        AB.newSplash();
        console.log("To many players");
        AB.splashHtml(splashFull());
    } else { // If not more then 2 then set safe to true so you won't be removed
        safe = true;
    }
};

AB.socketIn = function(data) // When data is received pass it to a function to compare the differences.
{
    console.log(data);
    compareInput(data.first, data.second); // Make the changes on this local map with the new positions.
    kingCheckMateCheck(); // Once a move has been received, check to see if it puts a king in check.
    chessGame.switchTurn(); // Switch the turn. i.e. (from black to white or from white to black).
    commands();
};