Created
September 6, 2013 02:41
-
-
Save deanrad/6458897 to your computer and use it in GitHub Desktop.
BDD version of an incremental version of player-to-player chess
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
</html> | |
<head> | |
<title>Jasmine Test Suite for Player-to-Player Chess</title> | |
</head> | |
<body> | |
<script type="text/javascript" src="//searls.github.io/jasmine-all/jasmine-all-min.js"></script> | |
<!-- script type="text/javascript" src="/js/jasmine-all-min.js"></script --> | |
<script type="text/javascript"> | |
describe("Positions Vectors and Sides, oh my", function(){ | |
it("are indexed a1-h8", function(){ | |
var p = new Position('a1'); | |
expect(p.file).toEqual('a'); | |
expect(p.rank).toEqual('1'); | |
expect(p.fileidx).toEqual( 0 ); | |
expect(p.rankidx).toEqual( 0 ); | |
expect(p.toString()).toEqual('a1'); | |
var p = new Position('h8'); | |
expect(p.file).toEqual('h'); | |
expect(p.rank).toEqual('8'); | |
expect(p.fileidx).toEqual( 7 ); | |
expect(p.rankidx).toEqual( 7 ); | |
expect(p.toString()).toEqual('h8'); | |
}); | |
it("calls the vector from d2 to d4 [0,2]", function(){ | |
var d2 = new Position('d2'), d4 = new Position('d4'); | |
expect(d4.minus(d2)).toEqual([0,2]); | |
}); | |
it("Asserts that d2 + [0,2] is d4", function(){ | |
var d2 = new Position('d2'), d4 = new Position('d4'); | |
expect(d2.plus([0,2])).toEqual( d4 ); | |
}); | |
it("Asserts that d2 + [1,1] is e3", function(){ | |
var d2 = new Position('d2'), e3 = new Position('e3'); | |
expect(d2.plus([1,1])).toEqual( e3 ); | |
}); | |
it("Asserts that a8 is colored white (aka 'white on right' rule)", function(){ | |
var a8 = new Position('a8'); | |
var a1 = new Position('a1'); | |
expect(a8.color()).toEqual('white'); | |
expect(a1.color()).toEqual('black'); | |
}); | |
it("Asserts that black is the opposite of white", function(){ | |
expect('white'.opposite()).toEqual('black'); | |
expect('black'.opposite()).toEqual('white'); | |
}); | |
}); | |
describe("The Board", function(){ | |
it("calls the advance direction of white [0,1]", function(){ | |
expect(Board.advanceVector('white')).toEqual([0,1]); | |
}); | |
it("calls the advance direction of black [0,-1]", function(){ | |
expect(Board.advanceVector('black')).toEqual([0, -1]); | |
}); | |
it("has a configurable size, set to 8 for chess", function(){ | |
expect(Board.xSize).toEqual(8); | |
expect(Board.ySize).toEqual(8); | |
}); | |
it("detects invalid positions", function(){ | |
expect(Board.validPosition('a1')).toEqual(true); | |
expect(Board.validPosition('d2')).toEqual(true); | |
expect(Board.validPosition('h8')).toEqual(true); | |
expect(Board.validPosition('B8')).toEqual(false); | |
expect(Board.validPosition('a9')).toEqual(false); | |
expect(Board.validPosition('Q11')).toEqual(false); | |
expect(Board.validPosition('')).toEqual(false); | |
expect(Board.validPosition(null)).toEqual(false); | |
expect(Board.validPosition(undefined)).toEqual(false); | |
}); | |
it("knows either black or white is next to move", function(){ | |
var b = new Board(); | |
expect(b.turnToMove('white')).toEqual(true); | |
}); | |
it("knows whether white/black king/queenside castling is available", function(){ | |
var b = new Board(); | |
//initially true, until a move makes it so (to be implemented later, just a field now) | |
expect(b.castle_available_white_king).toEqual(true); | |
expect(b.castle_available_white_queen).toEqual(true); | |
expect(b.castle_available_black_king).toEqual(true); | |
expect(b.castle_available_black_queen).toEqual(true); | |
//can change any of them | |
b.castle_available_white_king = false; | |
expect( b.castle_available_white_king ).toEqual(false); | |
}); | |
it("has or does not have an enpassant square", function(){ | |
var b = new Board(); | |
expect(b.en_passant_square).toBeUndefined(); | |
}); | |
}); | |
/* | |
Board state | |
- See FEN - the following fields define the complete state of a game, for resume purposes | |
- Pieces positions, who to move, castling avail w/b k/q, ep target, 1/2 move clock, 1 move clock | |
Liberties | |
- piece.liberties(board): those moves a piece is capable of regardless of game state | |
- board.positionOf(piece) must be defined | |
- passing board allows answer to be relative to a forward direction / the boards edges | |
- example: for a pawn, only the three forward single-steps are liberties | |
Blocking/Capturing rules | |
- piece.blocked?(board, from, to) | |
- eg. a piece's 'to' is blocked by its own color, can capture if the other color | |
- except a pawn, whose diagonal liberties are 'blocked' by emptiness also, and whose forward liberty is blocked by anything | |
- intervening pieces of any color matter, except for knights whose crooked liberties define no intervening pieces | |
Special cases | |
- for a pawn, moving double is an option if on its home rank, but it must set EP on the board | |
- | |
*/ | |
describe("Space Kitty", function(){ | |
it("meows, of course", function(){ | |
expect( spaceKitty()).toEqual("meow!"); | |
}); | |
}); | |
</script> | |
<script type="text/javascript"> | |
/* begin chess code */ | |
function Position(file,rank){ | |
if(!rank){ | |
if(!file || file.length != 2) return null; | |
f = file.substr(0,1); | |
r = file.substr(1,1); | |
} | |
this.file = f; | |
this.rank = r; | |
this.fileidx = f.charCodeAt(0) - 97; | |
this.rankidx = r - 1; | |
}; | |
Position.prototype.initialize = function(fileidx, rankidx){ | |
this.fileidx = fileidx; | |
this.rankidx = rankidx; | |
this.file = String.fromCharCode(fileidx + 97); | |
this.rank = rankidx+1+""; | |
return this; | |
} | |
Position.prototype.toString = function(){ | |
return this.file + this.rank; | |
} | |
Position.prototype.minus = function(other){ | |
return [this.fileidx-other.fileidx, this.rankidx-other.rankidx]; | |
} | |
Position.prototype.plus = function(filerank_vector){ | |
var newpos = new Position('a1'); //ignored | |
return newpos.initialize(this.fileidx + filerank_vector[0], this.rankidx + filerank_vector[1]); | |
} | |
Position.prototype.color = function(){ | |
return ((this.fileidx+this.rankidx) % 2 == 0 ) ? 'black' : 'white'; | |
} | |
//see FEN | |
function Board(){ | |
this.nextToMove = 'white'; | |
this.castle_available_white_king = true; | |
this.castle_available_white_queen = true; | |
this.castle_available_black_king = true; | |
this.castle_available_black_queen = true; | |
} | |
Board.xSize = 8; | |
Board.ySize = 8; | |
Board.validPosition = function(pos){ | |
p = new Position(pos); | |
return p.fileidx >= 0 && p.fileidx < this.xSize && | |
p.rankidx >= 0 && p.rankidx < this.ySize ; | |
} | |
Board.advanceVector = function(side){ | |
if(side.indexOf('w') > -1) | |
return [0,1]; | |
else | |
return [0,-1]; | |
}; | |
Board.prototype.turnToMove = function(side){ | |
return (side==this.nextToMove); | |
} | |
String.prototype.opposite = function(){ | |
if (this.toString()=='white') return 'black'; | |
if (this.toString()=='black') return 'white'; | |
return null; | |
} | |
/* end chess code */ | |
window.spaceKitty = function(){ return "meow!"; }; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment