diff --git a/xtrn/chess/board.js b/xtrn/chess/board.js index 84a2aa2d6868372eeefacbd31afb18db2c3e91cc..34fd4dac8b2e11ef290e012926a920c459d0e3cb 100644 --- a/xtrn/chess/board.js +++ b/xtrn/chess/board.js @@ -51,6 +51,8 @@ function Board(moves) this.king = {} this.king[COLOUR.white] = this.pieces[0][4]; this.king[COLOUR.black] = this.pieces[7][4]; + this.draw_counter_turns; + this.position_count={}; this.moves=[]; if(moves) { for(move in moves) { @@ -59,12 +61,10 @@ function Board(moves) } } } +Board.prototype.drawn=false; Board.prototype.handleMove=function(move) { - // TODO: Promotions m=move.match(/^([a-h][1-8])([a-h][1-8])(.*)$/); - if(m==null) - return false; if(m!=null) { piece=this.getPiece(parsePos(m[1])); if(piece.constructor.name=='Pawn') { @@ -78,7 +78,7 @@ Board.prototype.handleMove=function(move) case 'b': piece.promote_to=Bishop; break; - case 'k': + case 'n': piece.promote_to=Knight; break; } @@ -86,15 +86,89 @@ Board.prototype.handleMove=function(move) if(!piece.moveTo(parsePos(m[2]))) return false; } + if(move.search(/'D$/) != -1) { + if(this.draw_offer && this.draw_offer != this.turn()) + this.drawn=true; + else if(m==null) + return false; + this.draw_offer = this.turn(); + } + else + delete this.draw_offer; this.moves.push(move); return true; } +Board.prototype.checkForMove=function(t) +{ + var x,y,p; + var x2,y2; + + /* + * This tests for stalemate and checkmate. Checkmate is simply + * a stalemate where the king is in check + */ + for(y=0;y<=8;y++) { + for(x=0;x<=8;x++) { + p=this.getPiece({x:x,y:y}); + if(p==null) + continue; + if(p.colour != t) + continue; + for(y2=1;y2<=8;y2++) { + for(x2=1;x2<=8;x2++) { + if(p.moveTo({x:x2,y:y2},false)) + return true; + } + } + } + } + return false; +} +Board.prototype.newTurn=function() +{ + var t=this.turn(); + var s; + + if(this.drawn) + return 'DRAW'; + + /* Check for check and check mate */ + if(!this.checkForMove(t)) { + if(this.check(t)) + return 'CHECKMATE'; + return 'STALEMATE'; + } + + /* Check for threefold repitition */ + s=this.stateString(); + if(this.position_count[s]==undefined) + this.position_count[s]=1; + else + this.position_count[s]++; + + /* Check for 50 turn limit */ + this.draw_counter_turns++; + if(this.draw_counter_turns >= 100) { + if(this.draw_offer && this.draw_offer != t) + return 'DRAW'; + else + this.draw_offer = t; + } + if(this.position_count[s]>=3) { + if(this.draw_offer && this.draw_offer != t) + return 'DRAW'; + else + this.draw_offer = t; + } +} Board.prototype.pieces=null; Board.prototype._domove=function(from, to) { var piece=this.getPiece(from); if(piece==null) return false; + if(piece.constructor.name=='Pawn' || this.pieces[to.y-1][to.x-1]) + this.draw_counter_turns=-1; this.pieces[to.y-1][to.x-1]=piece; this.pieces[piece.y-1][piece.x-1]=null; piece.x=to.x; @@ -123,6 +197,19 @@ Board.prototype.check=function(colour) Board.prototype.reason=function(str) { } +Board.prototype.turn=function() +{ + if(this.moves.length % 2) + return COLOUR.black; + return COLOUR.white; +} +Board.prototype.lastTurn=function() +{ + if(this.moves.length % 2) + return COLOUR.white; + return COLOUR.black; +} +// TODO: There's a notation (FEN?) for this. Board.prototype.stateString= function() { var ret=''; @@ -189,7 +276,7 @@ Board.prototype.stateString= function() ret += 'r'; break; case 'Knight': - ret += 'k'; + ret += 'n'; break; } } diff --git a/xtrn/chess/pieces.js b/xtrn/chess/pieces.js index faf25fed99dd3915eca67703649bc88ede9363b4..095503123597ff4afffce71a551e1d99ad15b304 100644 --- a/xtrn/chess/pieces.js +++ b/xtrn/chess/pieces.js @@ -24,17 +24,9 @@ Piece.prototype={ return false; } } - if(this.board.moves.length % 2) { - if(this.colour == COLOUR.white) { - this.board.reason("White move on black's turn"); - return false; - } - } - else { - if(this.colour == COLOUR.black) { - this.board.reason("Black move on white's turn"); - return false; - } + if(this.colour != this.board.turn()) { + this.board.reason("Attempted move out of turn"); + return false; } if(update) { var brd=new Board(this.board.moves); @@ -160,8 +152,10 @@ Pawn.prototype.moveTo=function(pos, update) } ret=Piece.prototype.moveTo.apply(this, [pos, update]); - if(update && ret && ydist==2) - this.double_move_num=this.board.moves.length; + if(update && ret) { + if(ydist==2) + this.double_move_num=this.board.moves.length; + } if(ret && this.y == 4.5+(3.5*this.colour)) { // Promotion! if(this.promote_to == null)