// Oggetto che serve soprattutto come namespacing var GSlib = { /* DEBUG */ GSLog: function() { this.m = new Array(); this.get = function() { return this.m.join("\n"); } }, Util: { getCapture: function (objFen, a, b, x, y) { return ( objFen.board[x][y] != ' ' || (objFen.board[a][b].match(/^[Pp]$/) && objFen.enPassant == GSlib.GSChessboard.coordToCol(y) + GSlib.GSChessboard.coordToRow(x)) ); } }, /** Oggetto che mi permette di raggruppare quelle funzioni che servono per il Chess 960 */ Chess960: { conv1: function (info, p, y) { if ( (p == 'K' && info.objFen.canWhiteShortCastle != null && y == GSlib.GSChessboard.colToCoord(info.objFen.canWhiteShortCastle.toLowerCase())) || (p == 'k' && info.objFen.canBlackShortCastle != null && y == GSlib.GSChessboard.colToCoord(info.objFen.canBlackShortCastle.toLowerCase())) ) return 'O-O'; if ( (p == 'K' && info.objFen.canWhiteLongCastle != null && y == GSlib.GSChessboard.colToCoord(info.objFen.canWhiteLongCastle.toLowerCase())) || (p == 'k' && info.objFen.canBlackLongCastle != null && y == GSlib.GSChessboard.colToCoord(info.objFen.canBlackLongCastle.toLowerCase())) ) return 'O-O-O'; return null; }, convShortCastle: function (objFen) { if (objFen.who == 'w') { var king = GSlib.GSCheck.findKing(objFen.board, 'K'); return GSlib.GSChessboard.coordToCol(parseInt(king.charAt(1))) + '1' + objFen.canWhiteShortCastle.toLowerCase() + '1'; } else if (objFen.who == 'b') { var king = GSlib.GSCheck.findKing(objFen.board, 'k'); return GSlib.GSChessboard.coordToCol(parseInt(king.charAt(1))) + '8' + objFen.canBlackShortCastle.toLowerCase() + '8'; } return null; }, convLongCastle: function (objFen) { if (objFen.who == 'w') { var king = GSlib.GSCheck.findKing(objFen.board, 'K'); return GSlib.GSChessboard.coordToCol(parseInt(king.charAt(1))) + '1' + objFen.canWhiteLongCastle.toLowerCase() + '1'; } else if (objFen.who == 'b') { var king = GSlib.GSCheck.findKing(objFen.board, 'k'); return GSlib.GSChessboard.coordToCol(parseInt(king.charAt(1))) + '8' + objFen.canBlackLongCastle.toLowerCase() + '8'; } } }, /** Questo è l'oggetto che viene ricevuto dalla libreria quando viene eseguita una mossa. Basilarmente contiene la posizione in formato FEN e la mossa eseguita (casa di partenza, casa di arrivo) per esempio: e2e4 La lunghezza della stringa della mossa è pertanto costante 'prom' rappresenta il pezzo che deve essere sostituito al pedone in caso di promozione. Se non c'è promozione il suo valore è 'null' */ GSMoveMessage: function (strFen, move, prom, variant) { this.strFen = strFen; this.move = move; this.prom = prom; this.variant = variant; this.msg = null; // Messaggio da inserire nella MessageBoard }, /** Funzione che serve a convertire una mossa nella forma contratta come Cd7 oppure Txf1, ecc.. nella forma casaDiPartenza-casaDiArrivo come e2e4 e viceversa objFen rappresenta la posizione della scacchiera nella quale eseguire la mossa 'move' */ GSMoveConverter: function (objFen, move, variant) { if (move.match(/^[a-h][1-8][a-h][1-8]$/)) { // Devo convertire da g1f3 a Cf3 var m = ''; var a = GSlib.GSChessboard.rowToCoord(move.charAt(1)); var b = GSlib.GSChessboard.colToCoord(move.charAt(0)); var x = GSlib.GSChessboard.rowToCoord(move.charAt(3)); var y = GSlib.GSChessboard.colToCoord(move.charAt(2)); // Se non prendo alcun pezzo allora ritorno false // TODO: gestione dell'en passant if (objFen.board[a][b] == ' ') return false; var capture = GSlib.Util.getCapture(objFen, a, b, x, y); if (capture === true) m = 'x'; m = m + move.charAt(2) + move.charAt(3); var p = objFen.board[a][b]; if (p.match(/[pP]/)) { // Prendo un pedone if (capture === true) m = move.charAt(0) + m; } else { // Ho preso un pezzo // Controllo se altri pezzi dello stesso tipo giungono in 'move' var info = new GSlib.GSMoveInfo(objFen, a, b, x, y, capture); var piece = new GSlib.GSPiece(null, null); var coord = piece.getCoord(info); m = p.toUpperCase() + coord + m; } // Controllo speciale per gli arrocchi if (variant == 'chess 960') { var ret = GSlib.Chess960.conv1(info, p, y); if (ret != null) return ret; } else { if (p.match(/[kK]/) && b == 4) { if (y == 6) return 'O-O'; if (y == 2) return 'O-O-O'; } } return m; } else { // Devo convertire da Cf3 a g1f3 var a = move.split(/[^a-zA-Z0-9\-]/); var m = a[0].replace('x', ''); var x = GSlib.GSChessboard.rowToCoord(m.charAt(m.length-1)); var y = GSlib.GSChessboard.colToCoord(m.charAt(m.length-2)); if (m.match(/^[0|o]-[0|o]$/i)) { // Arrocco Corto if (variant == 'chess 960') { var ret = GSlib.Chess960.convShortCastle(objFen); if (ret != null) return ret; } else { // Scacchi classici (var = null) if (objFen.who == 'w') return 'e1g1'; else return 'e8g8'; } } else if (m.match(/^[0|o]-[0|o]-[0|o]$/i)) { // Arrocco Lungo if (variant == 'chess 960') { var ret = GSlib.Chess960.convLongCastle(objFen); if (ret != null) return ret; } else { // Scacchi classici (var = null) if (objFen.who == 'w') return 'e1c1'; else return 'e8c8'; } } else if (m.length == 2) { // E un pedone che avanza if (objFen.who == 'w') { if (objFen.board[x+1][y] == 'P') return m.charAt(0)+GSlib.GSChessboard.coordToRow(x+1)+m; if (objFen.board[x+2][y] == 'P') return m.charAt(0)+GSlib.GSChessboard.coordToRow(x+2)+m; } else { if (objFen.board[x-1][y] == 'p') return m.charAt(0)+GSlib.GSChessboard.coordToRow(x-1)+m; if (objFen.board[x-2][y] == 'p') return m.charAt(0)+GSlib.GSChessboard.coordToRow(x-2)+m; } } else if (isLower(m.charAt(0))) { // E' un pedone che mangia if (objFen.who == 'w') { if (objFen.board[x+1][y+1] == 'P' || objFen.board[x+1][y-1] == 'P') return m.charAt(0)+GSlib.GSChessboard.coordToRow(x+1)+m.charAt(1)+m.charAt(2); } else { if (objFen.board[x-1][y+1] == 'p' || objFen.board[x-1][y-1] == 'p') return m.charAt(0)+GSlib.GSChessboard.coordToRow(x-1)+m.charAt(1)+m.charAt(2); } } else if (isUpper(m.charAt(0))) { // Muove un pezzo var c = m.charAt(0); if (objFen.who == 'b') c = c.toLowerCase(); var a = GSlib.GSCheck.findPiece(objFen.board, c); for (var i in a) { var info = new GSlib.GSMoveInfo(objFen, parseInt(a[i].charAt(0)), parseInt(a[i].charAt(1)), x, y, false); info.variant = variant; var piece = GSlib.GSChessboard.getPiece(info.objFen.board, info.a, info.b); // Se non prendo alcun pezzo ritorno false if (piece === null) continue; var regObj = piece.superr.isRegularMove(info); if (regObj === false) continue; // Ora controllo se ci sono ulteriori coordinate che identificano // il pezzo da muovere. if (m.length == 4) { var co = m.charAt(1); if (Utility.isInteger(co)) { // Se la coordinata è un numero devo confrontarla con info.a if (co != GSlib.GSChessboard.coordToRow(info.a)) continue; } else { // Se la coordinata è una lettera devo confrontarla con info.b if (co != GSlib.GSChessboard.coordToCol(info.b)) continue; } } else if (m.length == 5) { } else if (m.length > 5) return false; return GSlib.GSChessboard.coordToCol(info.b) + GSlib.GSChessboard.coordToRow(info.a) + m.charAt(m.length-2) + m.charAt(m.length-1); } return false; } return false; } }, GSMoveInfo: function (objFen, a, b, x, y, capture) { this.objFen = objFen; this.a = a; this.b = b; this.x = x; this.y = y; this.capture = capture; this.prom = null; // this.variant = null; }, GSFen: function () { this.board = null; // In forma di Array this.who = null; this.canWhiteShortCastle = null; this.canWhiteLongCastle = null; this.canBlackShortCastle = null; this.canBlackLongCastle = null; this.enPassant = null; this.semiMoves = null; this.totMoves = null; /** Il Fen in formato stringa passato come parametro viene analizzato e vengono settati correttamente tutte le variabili della classe. */ this.analyze = function(strFen) { //if (typeof(strFen) == 'undefined') return; var chessInfo = strFen.split(' '); this.board = GSlib.GSChessboard.fenToBoard(strFen); // in forma di Array this.who = chessInfo[1]; this.enPassant = chessInfo[3]; this.semiMoves = chessInfo[4] ? parseInt(chessInfo[4]) : 0; this.totMoves = chessInfo[5] ? parseInt(chessInfo[5]) : 1; // Arrocco (esteso al Chess960) // Esempio di FEN 960: brqbknnr/pppppppp/8/8/8/8/PPPPPPPP/BRQBKNNR w HBhb - 0 1 if (chessInfo[2] == '-') return; var wKing = GSlib.GSCheck.findKing(this.board, 'K'); var bKing = GSlib.GSCheck.findKing(this.board, 'k'); var len = chessInfo[2].length; for (var i=0; i parseInt(wKing.charAt(1)) ) this.canWhiteShortCastle = c; else this.canWhiteLongCastle = c; } } else if (isLower(c)) { if (c.match(/[kq]/) != null) { if (c == 'k') this.canBlackShortCastle = c; else this.canBlackLongCastle = c; } else { if ( GSlib.GSChessboard.colToCoord(c.toLowerCase()) > parseInt(bKing.charAt(1)) ) this.canBlackShortCastle = c; else this.canBlackLongCastle = c; } } } } /** Dalle variabili della classe ottengo il Fen in formato stringa */ this.getFen = function() { var chessboard = ""; if (this.board == null) return; var k = 0; for (var i=0; i<8; i++) { for (var j=0; j<8; j++) { if (this.board[i][j] != ' ') { if (k>0) chessboard = chessboard + k; chessboard = chessboard + this.board[i][j]; k=0; } else k++; } if (k>0) chessboard = chessboard + k; chessboard = chessboard + "/"; k=0; } chessboard = chessboard.substr(0, chessboard.length -1); // Tolgo l'ultima "/" // ---------------- var arrocco = ''; if (this.canWhiteShortCastle != null) arrocco = arrocco + this.canWhiteShortCastle; if (this.canWhiteLongCastle != null) arrocco = arrocco + this.canWhiteLongCastle; if (this.canBlackShortCastle != null) arrocco = arrocco + this.canBlackShortCastle; if (this.canBlackLongCastle != null) arrocco = arrocco + this.canBlackLongCastle; if (arrocco == '') arrocco = '-'; var fen = chessboard+" "+this.who+" "+arrocco+" "+this.enPassant+" "+this.semiMoves+" "+this.totMoves; return fen; } }, /** Classe Principale che si viene chiamata dalle altre librerie Javascript. Il suo compito è quello di ricevere un oggetto GSMoveMessage, e ritornare la nuova posizione in formato FEN se la mossa è corretta. FALSE altrimenti */ GSMoveManager: function (message) { this.message = message; /* DEBUG */ this.log = null; /** Funzione che si occupa di analizzare il messaggio e di ritornare il nuovo FEN. */ this.play = function() { var move = this.message.move; var objFen = new GSlib.GSFen(); objFen.analyze(this.message.strFen); var a = GSlib.GSChessboard.rowToCoord(move.charAt(1)); // x di partenza var b = GSlib.GSChessboard.colToCoord(move.charAt(0)); // y di partenza var x = GSlib.GSChessboard.rowToCoord(move.charAt(3)); // x di arrivo var y = GSlib.GSChessboard.colToCoord(move.charAt(2)); // y di arrivo var capture = GSlib.Util.getCapture(objFen, a, b, x, y); var info = new GSlib.GSMoveInfo(objFen, a, b, x, y, capture); info.prom = this.message.prom; info.variant = this.message.variant; /* DEBUG */ info.log = new GSlib.GSLog(); var response = this.execute(info); /* DEBUG */ this.log = info.log; return response; } this.execute = function(info) { var sourceObjFen = Utility.clone(info.objFen); if (GSlib.GSCheckRegularMove(info, null) === false) return false; // La seguente linea di codice deve essere prima del controllo dello scacco per // permettere al pedone di minacciare correttamente info.objFen.who = (info.objFen.who == 'w') ? 'b' : 'w'; // Ora che ho eseguito la mossa devo verificare che il re non sia sotto scacco var bCheck = GSlib.GSCheck.isCheckTo(info, 'K'); // Scacco al Bianco var wCheck = GSlib.GSCheck.isCheckTo(info, 'k'); // Scacco al Nero if (GSlib.GSCheckCheck(info, wCheck, bCheck) === true) return false; // Ci sono alcune variabili di objFen che devo trattare qui if (info.objFen.who == 'w') info.objFen.totMoves = info.objFen.totMoves+1; if (info.capture === true) info.objFen.semiMoves = 0; // Se è stata mangiata una torre devo aggiornare il FEN per gli arrocchi this.checkEatingRook(info, sourceObjFen); // Ricavo la mossa secondo la notazione standard PGN (es: Cbd7+) var m = GSlib.GSMoveConverter(sourceObjFen, this.message.move, info.variant); // Osservo se c'è stata promozione di un pedone if (info.prom != null) m = m + '=' + info.prom; var msgBoard = null; if (wCheck || bCheck) { if (GSlib.GSCheckMate(info)) { // Controllo se è scacco matto m = m + '#'; msgBoard = 'Checkmate'; } else { // E' solo scacco m = m+'+'; msgBoard = 'Check'; } } else { // Controllo se è stallo if (info.objFen.semiMoves >= 100) msgBoard = 'Draw 50 Moves'; else if (GSlib.GSStaleMate(info)) msgBoard = 'Stalemate'; } var response = new GSlib.GSMoveMessage(info.objFen.getFen(), m, null, info.variant); response.msg = msgBoard; return response; } /** Questa funzione serve a controllare se è stata mangiata una torre, se così fosse allora bisogna fare qualche controllo per aggiornare le possibilità di arrocco dei due giocatori */ this.checkEatingRook = function (info, sourceObjFen) { if (sourceObjFen.board[info.x][info.y] == 'R') { if (info.objFen.canWhiteShortCastle != null) { if ( info.variant == 'chess 960' && info.x == 7 && info.y == GSlib.GSChessboard.colToCoord(info.objFen.canWhiteShortCastle.toLowerCase()) ) info.objFen.canWhiteShortCastle = null; else if (info.variant == null && info.x == 7 && info.y == 7) info.objFen.canWhiteShortCastle = null; } if (info.objFen.canWhiteLongCastle != null) { if ( info.variant == 'chess 960' && info.x == 7 && info.y == GSlib.GSChessboard.colToCoord(info.objFen.canWhiteLongCastle.toLowerCase()) ) info.objFen.canWhiteLongCastle = null; else if (info.variant == null && info.x == 7 && info.y == 0) info.objFen.canWhiteLongCastle = null; } } else if (sourceObjFen.board[info.x][info.y] == 'r') { if (info.objFen.canBlackShortCastle != null) { if ( info.variant == 'chess 960' && info.x == 0 && info.y == GSlib.GSChessboard.colToCoord(info.objFen.canBlackShortCastle.toLowerCase()) ) info.objFen.canBlackShortCastle = null; else if (info.variant == null && info.x == 0 && info.y == 7) info.objFen.canBlackShortCastle = null; } if (info.objFen.canBlackLongCastle != null) { if ( info.variant == 'chess 960' && info.x == 0 && info.y == GSlib.GSChessboard.colToCoord(info.objFen.canBlackLongCastle.toLowerCase()) ) info.objFen.canBlackLongCastle = null; else if (info.variant == null && info.x == 0 && info.y == 0) info.objFen.canBlackLongCastle = null; } } } }, /* ----------------------------------- */ /* */ /* ----------------------------------- */ /** Classe che contiene alcune utility per la scacchiera */ GSChessboard: { rows: ['8', '7', '6', '5', '4', '3', '2', '1'], cols: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], /** Funzione che ritorna un array bidimensionale 8x8 vuoto. La scacchiera è pensata nel seguente modo: 0 r n b q k b n r 1 p p p p p p p p 2 3 4 5 6 P P P P P P P P 7 R N B Q K B N R x/y 0 1 2 3 4 5 6 7 */ getEmptyBoard: function() { var array = new Array(); for (var i=0; i<8; i++) { var trArray = new Array(); for (var j=0; j<8; j++) trArray.push(' '); array.push(trArray); } return array; }, /** dato come input il FEN ritorna un array che rappresenta la scacchiera */ fenToBoard: function(fen) { var chessInfo = fen.split(" "); // Scacchiera var chessBoardFen = chessInfo[0]; var rows = chessBoardFen.split('/'); var k=0; // Indice delle celle var arrayBoard = GSlib.GSChessboard.getEmptyBoard(); // Array bidimensionale vuoto for (var i=0; i<8; i++) { var charInfos = rows[i].length; for (var c=0; c 1) ? arr.length : 0; for (i=0; iy) { done = true; if (board[i][j] != ' ') isEmpty = false; i++; j--; } i=a-1; j=b+1; while(i>x && jx && j>y) { done = true; if (board[i][j] != ' ') isEmpty = false; i--; j--; } return new GSlib.GSPieceResponse((done && isEmpty), null); } this.move = function(info) { // Sposto il Pezzo var objFen = info.objFen; objFen.board[info.x][info.y] = objFen.board[info.a][info.b]; objFen.board[info.a][info.b] = ' '; // Aggiorno enPassant objFen.enPassant = '-'; // Aggiorno semi mosse objFen.semiMoves = objFen.semiMoves+1; } }, GSRook: function () { this.isRightMove = function(info) { var board = info.objFen.board; var a = info.a; var b = info.b; var x = info.x; var y = info.y; var isEmpty = true; var done = false; // Mi muovo di una casa if ( (a+1 == x && b == y) || (x == a-1 && y == b) || (x == a && y == b+1) || (x == a && y == b-1) ) done = true; if (a == x) { for (var i=b+1; iy; i--) { done = true; if (board[a][i] != ' ') isEmpty = false; } } else if (b == y) { for (var i=a+1; ix; i--) { done = true; if (board[i][b] != ' ') isEmpty = false; } } return new GSlib.GSPieceResponse((done && isEmpty), null); } this.move = function(info) { // Sposto il Pezzo var objFen = info.objFen; objFen.board[info.x][info.y] = objFen.board[info.a][info.b]; objFen.board[info.a][info.b] = ' '; // Aggiorno enPassant objFen.enPassant = '-'; // Aggiorno semi mosse objFen.semiMoves = objFen.semiMoves+1; // Siccome è stata mossa una torre devo controllare quale e // Modificare opportunamente il FEN per l'arrocco. // >>> Compatibile con Chess960 if (objFen.who == 'w') { // Se non può arroccare nè corto nè lungo non sto a fare i calcoli if (objFen.canWhiteShortCastle == null && objFen.canWhiteLongCastle == null) return; var king = GSlib.GSCheck.findKing(objFen.board, 'K'); var y = parseInt(king.charAt(1)); if (y > info.b) objFen.canWhiteLongCastle = null; if (y < info.b) objFen.canWhiteShortCastle = null; } else if (objFen.who == 'b') { // Se non può arroccare nè corto nè lungo non sto a fare i calcoli if (objFen.canBlackShortCastle == null && objFen.canBlackLongCastle == null) return; var king = GSlib.GSCheck.findKing(objFen.board, 'k'); var y = parseInt(king.charAt(1)); if (y > info.b) objFen.canBlackLongCastle = null; if (y < info.b) objFen.canBlackShortCastle = null; } } }, GSQueen: function () { this.isRightMove = function(info) { var r = new GSlib.GSRook(); var b = new GSlib.GSBishop(); return new GSlib.GSPieceResponse((r.isRightMove(info).b || b.isRightMove(info).b), null); } this.move = function(info) { // Sposto il Pezzo var objFen = info.objFen; objFen.board[info.x][info.y] = objFen.board[info.a][info.b]; objFen.board[info.a][info.b] = ' '; // Aggiorno enPassant objFen.enPassant = '-'; // Aggiorno semi mosse objFen.semiMoves = objFen.semiMoves+1; } }, /** Non è aggiornato per il Chess960, ma è programmato solo per gli scacchi classici. Il controllo delle case dell'arrocco sotto scacco non può essere effuato all'interno di questa funzione perchè altrimenti si cadrebbe in un loop infinto. */ GSKing: function () { this.isRightMove = function(info) { var board = info.objFen.board; var i, a = info.a; var b = info.b; var x = info.x; var y = info.y; var m = null; var isRight = false; if (info.objFen.who == 'w') { if (info.variant == 'chess 960') { if (info.objFen.canWhiteShortCastle != null && x == 7 && y == GSlib.GSChessboard.colToCoord(info.objFen.canWhiteShortCastle.toLowerCase())) { isRight = true; var arrEmpty = new Array('75', '76'); var arrCheck = new Array('76'); for (i=b+1; i<5; i++) arrEmpty.push('7'+i); for (i=b; i<6; i++) arrCheck.push('7'+i); for (i in arrEmpty) { if (arrEmpty[i] == '7'+y || arrEmpty[i] == '7'+b) delete arrEmpty[i]; } m = new Array('castle', arrCheck, arrEmpty); } else if (info.objFen.canWhiteLongCastle != null && x == 7 && y == GSlib.GSChessboard.colToCoord(info.objFen.canWhiteLongCastle.toLowerCase())) { isRight = true; var arrEmpty = new Array('72', '73'); var arrCheck = new Array('72', '7'+b); for (i=b-1; i>3; i--) arrEmpty.push('7'+i); for (i=b-1; i>2; i--) arrCheck.push('7'+i); if (y == 0) arrEmpty.push('71'); for (i in arrEmpty) { if (arrEmpty[i] == '7'+y || arrEmpty[i] == '7'+b) delete arrEmpty[i]; } m = new Array('castle', arrCheck, arrEmpty); } } else { // Scacchi classici if (info.objFen.canWhiteShortCastle != null && x == 7 && y == 6) { isRight = true; m = new Array('castle', new Array('74', '75', '76'), new Array('75', '76')); } else if (info.objFen.canWhiteLongCastle != null && x == 7 && y == 2) { isRight = true; m = new Array('castle', new Array('74', '73', '72'), new Array('73', '72', '71')); } } } else if (info.objFen.who == 'b') { if (info.variant == 'chess 960') { if (info.objFen.canBlackShortCastle != null && x == 0 && y == GSlib.GSChessboard.colToCoord(info.objFen.canBlackShortCastle.toLowerCase())) { isRight = true; var arrEmpty = new Array('05', '06'); var arrCheck = new Array('06'); for (i=b+1; i<5; i++) arrEmpty.push('0'+i); for (i=b; i<6; i++) arrCheck.push('0'+i); for (i in arrEmpty) { if (arrEmpty[i] == '0'+y || arrEmpty[i] == '0'+b) delete arrEmpty[i]; } m = new Array('castle', arrCheck, arrEmpty); } else if (info.objFen.canBlackLongCastle != null && x == 0 && y == GSlib.GSChessboard.colToCoord(info.objFen.canBlackLongCastle.toLowerCase())) { isRight = true; var arrEmpty = new Array('02', '03'); var arrCheck = new Array('02', '0'+b); for (i=b-1; i>3; i--) arrEmpty.push('0'+i); for (i=b-1; i>2; i--) arrCheck.push('0'+i); if (y == 0) arrEmpty.push('01'); for (i in arrEmpty) { if (arrEmpty[i] == '0'+y || arrEmpty[i] == '0'+b) delete arrEmpty[i]; } m = new Array('castle', arrCheck, arrEmpty); } } else { // Arrocco per Nero if (info.objFen.canBlackShortCastle != null && x == 0 && y == 6) { isRight = true; m = new Array('castle', new Array('04', '05', '06'), new Array('05', '06')); } else if (info.objFen.canBlackLongCastle != null && x == 0 && y == 2) { isRight = true; m = new Array('castle', new Array('04', '03', '02'), new Array('03', '02', '01')); } } } if (isRight === false) { if ( ((abs(a-x) == 1) && (b == y)) || ((abs(b-y) == 1) && (a == x)) || ((abs(b-y) == 1) && (abs(a-x) == 1))) isRight = true; } return new GSlib.GSPieceResponse(isRight, m); } this.move = function(info) { // Sposto il Pezzo var objFen = info.objFen; objFen.board[info.x][info.y] = ' '; objFen.board[info.a][info.b] = ' '; // Aggiorno enPassant objFen.enPassant = '-'; // Aggiorno semi mosse objFen.semiMoves = objFen.semiMoves+1; // Gestione dell'arrocco if (info.objFen.who == 'w') { if ( info.objFen.canWhiteShortCastle != null && info.x == 7 && ( (info.variant == 'chess 960' && info.y == GSlib.GSChessboard.colToCoord(info.objFen.canWhiteShortCastle.toLowerCase())) || (info.variant == null && info.y == 6) ) ) { if (info.variant == null) objFen.board[7][7] = ' '; objFen.board[7][6] = 'K'; objFen.board[7][5] = 'R'; } else if ( info.objFen.canWhiteLongCastle != null && info.x == 7 && ( (info.variant == 'chess 960' && info.y == GSlib.GSChessboard.colToCoord(info.objFen.canWhiteLongCastle.toLowerCase())) || (info.variant == null && info.y == 2) ) ) { if (info.variant == null) objFen.board[7][0] = ' '; objFen.board[7][2] = 'K'; objFen.board[7][3] = 'R'; } else objFen.board[info.x][info.y] = 'K'; info.objFen.canWhiteShortCastle = null; info.objFen.canWhiteLongCastle = null; } else if (info.objFen.who == 'b') { if ( info.objFen.canBlackShortCastle != null && info.x == 0 && ( (info.variant == 'chess 960' && info.y == GSlib.GSChessboard.colToCoord(info.objFen.canBlackShortCastle.toLowerCase())) || (info.variant == null && info.y == 6) ) ) { if (info.variant == null) objFen.board[0][7] = ' '; objFen.board[0][6] = 'k'; objFen.board[0][5] = 'r'; } else if ( info.objFen.canBlackLongCastle != null && info.x == 0 && ( (info.variant == 'chess 960' && info.y == GSlib.GSChessboard.colToCoord(info.objFen.canBlackLongCastle.toLowerCase())) || (info.variant == null && info.y == 2) ) ) { if (info.variant == null) objFen.board[0][0] = ' '; objFen.board[0][2] = 'k'; objFen.board[0][3] = 'r'; } else objFen.board[info.x][info.y] = 'k'; info.objFen.canBlackShortCastle = null; info.objFen.canBlackLongCastle = null; } } }, /* ----------------------------------- */ /* */ /* ----------------------------------- */ GSPieceKnight: function (id) { this.superr = new GSlib.GSPiece(this, id); // super rappresenta l'oggetto Piece this.abstractt = new GSlib.GSKnight(); // abstract rappresenta la categoria del pezzo }, GSPieceRook: function (id) { this.superr = new GSlib.GSPiece(this, id); // super rappresenta l'oggetto Piece this.abstractt = new GSlib.GSRook(); // abstract rappresenta la categoria del pezzo }, GSPieceBishop: function (id) { this.superr = new GSlib.GSPiece(this, id); // super rappresenta l'oggetto Piece this.abstractt = new GSlib.GSBishop(); // abstract rappresenta la categoria del pezzo }, GSPieceQueen: function (id) { this.superr = new GSlib.GSPiece(this, id); // super rappresenta l'oggetto Piece this.abstractt = new GSlib.GSQueen(); // abstract rappresenta la categoria del pezzo }, GSPieceKing: function (id) { this.superr = new GSlib.GSPiece(this, id); // super rappresenta l'oggetto Piece this.abstractt = new GSlib.GSKing(); // abstract rappresenta la categoria del pezzo }, GSPiecePawn: function (id) { this.superr = new GSlib.GSPiece(this, id); // super rappresenta l'oggetto Piece this.abstractt = new GSlib.GSPawn(); // abstract rappresenta la categoria del pezzo } }