mirror of
				https://github.com/tiyn/yeschess.git
				synced 2025-10-31 02:41:16 +01:00 
			
		
		
		
	chess: improved documentation and deleted unused stuff
This commit is contained in:
		| @@ -16,3 +16,9 @@ Testing is done by `einheit` by [jyapayne](https://github.com/jyapayne/einheit). | |||||||
| All legal chess moves are implemented in `chess.nim` and tested by the TestSuite | All legal chess moves are implemented in `chess.nim` and tested by the TestSuite | ||||||
| in `test.nim`. | in `test.nim`. | ||||||
| You can simply run the tests with `nim c -r test.nim`. | You can simply run the tests with `nim c -r test.nim`. | ||||||
|  |  | ||||||
|  | ## Documentation | ||||||
|  |  | ||||||
|  | Documentation is written into the code via DocGen. | ||||||
|  | For this reason it is not saved in this repository. | ||||||
|  | To extract it into html run `nim doc --project --index:on --outdir:htmldocs game.nim` | ||||||
|   | |||||||
							
								
								
									
										293
									
								
								chess.nim
									
									
									
									
									
								
							
							
						
						
									
										293
									
								
								chess.nim
									
									
									
									
									
								
							| @@ -4,71 +4,87 @@ import algorithm | |||||||
|  |  | ||||||
| type | type | ||||||
|   Color* = enum |   Color* = enum | ||||||
|     Black = -1, White = 1 |     ## `Color` describes the possible color of players. | ||||||
|   ## Board that saves the board |     Black = -1, | ||||||
|   Board* = array[0..119, int] |     White = 1 | ||||||
|   ## Board that checks if pieces moved |   Board* = array[0..119, int] ## \ | ||||||
|   Moved* = array[0..119, bool] |     ## `Board` saves the position of the chess pieces. | ||||||
|   ## Castle rights for each player |   Moved* = array[0..119, bool] ## \ | ||||||
|  |     ## `Moved` saves the position of squares a piece moved on or from. | ||||||
|  |  | ||||||
|   CastleRights = tuple |   CastleRights = tuple | ||||||
|     wk: bool |     # `CastleRights` contains the rights to castling for each player. | ||||||
|     wq: bool |     wk: bool # `wk` describes White kingside castle | ||||||
|     bk: bool |     wq: bool # `wq` describes White queenside castle | ||||||
|     bq: bool |     bk: bool # `bk` describes Black kingside castle | ||||||
|   ## Game as object of different values |     bq: bool # `bq` describes Black queenside castle | ||||||
|   Game* = object |   Game* = object | ||||||
|  |     ## `Game` stores all important information of a chess game. | ||||||
|     board*: Board |     board*: Board | ||||||
|     moved: Moved |     moved: Moved | ||||||
|     toMove*: Color |     toMove*: Color | ||||||
|     previousBoard: seq[Board] |     previousBoard: seq[Board] | ||||||
|     previousCastleRights: seq[CastleRights] |     previousCastleRights: seq[CastleRights] | ||||||
|     fiftyMoveCounter: int |     fiftyMoveCounter: int | ||||||
|   ## Move as object |  | ||||||
|   Move* = object |   Move* = object | ||||||
|  |     ## `Move` stores all important information for a move. | ||||||
|     start: int |     start: int | ||||||
|     dest: int |     dest: int | ||||||
|     color: Color |     color: Color | ||||||
|     prom: int |     prom: int | ||||||
|   ## Amount of pieces of a player |   PieceAmount = tuple | ||||||
|   Pieces = tuple |     # `PieceAmount` describes the number of pieces of a certain type a/both | ||||||
|     p: int |     # player/s  has/have. | ||||||
|     k: int |     p: int # `p` describes the amount of pawns. | ||||||
|     b: int |     n: int # `n` describes the amount of knights. | ||||||
|     r: int |     b: int # `b` describes the amount of bishops. | ||||||
|     q: int |     r: int # `r` describes the amount of rooks. | ||||||
|  |     q: int # `q` describes the amount of queens. | ||||||
|  |  | ||||||
| const | const | ||||||
|   # IDs for piece |   Block* = 999 ## \ | ||||||
|   BlockID* = 999 |     ## `Block` is the value assigned to empty blocked fields in a board. | ||||||
|   PawnID* = 1 |   WPawn* = 1 | ||||||
|   KnightID* = 2 |     ## `WPawn` is the value assigned to a square in a board with a white pawn. | ||||||
|   BishopID* = 3 |   WKnight* = 2 ## \ | ||||||
|   RookID* = 4 |     ## `WKnight` is the value assigned to a square in a board with a white | ||||||
|   QueenID* = 5 |     ## knight. | ||||||
|   KingID* = 6 |   WBishop* = 3 ## \ | ||||||
|   EnPassantID* = 7 |     ## `WBishop` is the value assigned to a square in a board with a white | ||||||
|   # IDs that are saved in the array |     ## bishop. | ||||||
|   Block* = BlockID |   WRook* = 4 ## \ | ||||||
|   WPawn* = PawnID |     ## `WRook` is the value assigned to a square in a board with a white rook. | ||||||
|   WKnight* = KnightID |   WQueen* = 5 ## \ | ||||||
|   WBishop* = BishopID |     ## `WQueen` is the value assigned to a square in a board with a white | ||||||
|   WRook* = RookID |     ## queen. | ||||||
|   WQueen* = QueenID |   WKing* = 6 ## \ | ||||||
|   WKing* = KingID |     ## `WKing` is the value assigned to a square in a board with a white king. | ||||||
|   WEnPassant* = EnPassantID |   WEnPassant* = 7 ## \ | ||||||
|   BPawn* = -PawnID |     ## `WEnPassant` is assigned to a square in a board with an invisible white | ||||||
|   BKnight* = -KnightID |     ## en passant pawn. | ||||||
|   BBishop* = -BishopID |   BPawn* = -WPawn ## \ | ||||||
|   BRook* = -RookID |     ## `BPawn` is the value assigned to a square in a board with a black pawn. | ||||||
|   BQueen* = -QueenID |   BKnight* = -WKnight ## \ | ||||||
|   BKing* = -KingID |     ## `BKnight` is the value assigned to a square in a board with a black\ | ||||||
|   BEnPassant* = EnPassantID |     ## knight. | ||||||
|   # Directions of movement |   BBishop* = -WBishop ## \ | ||||||
|   N = 10 |     ## `BBishop` is the value assigned to a square in a board with a black\ | ||||||
|   S = -N |     ## bishop. | ||||||
|   W = 1 |   BRook* = -WRook ## \ | ||||||
|   E = -W |     ## `BRook` is the value assigned to a square in a board with a black rook. | ||||||
|   # Movement options for pieces (Bishop/Rook/Queen can repeat in the same direction) |   BQueen* = -WQueen ## \ | ||||||
|  |     ## `BQueen` is the value assigned to a square in a board with a black queen. | ||||||
|  |   BKing* = -WKing ## \ | ||||||
|  |     ## `BKing` is the value assigned to a square in a board with a black king. | ||||||
|  |   BEnPassant* = -WEnPassant ## \ | ||||||
|  |     ## `BEnPassant` is assigned to a square in a board with an invisible black | ||||||
|  |     ## en passant pawn. | ||||||
|  |   # Directions of squares from whites perspective. | ||||||
|  |   N = 10 # move up | ||||||
|  |   S = -N # Move down | ||||||
|  |   W = 1 # Move left | ||||||
|  |   E = -W # Move right | ||||||
|  |   # Directions for the pieces. Special moves are in separate arrays. | ||||||
|   Knight_Moves = [N+N+E, N+N+W, E+E+N, E+E+S, S+S+E, S+S+W, W+W+N, W+W+S] |   Knight_Moves = [N+N+E, N+N+W, E+E+N, E+E+S, S+S+E, S+S+W, W+W+N, W+W+S] | ||||||
|   Bishop_Moves = [N+E, N+W, S+E, S+W] |   Bishop_Moves = [N+E, N+W, S+E, S+W] | ||||||
|   Rook_Moves = [N, E, S, W] |   Rook_Moves = [N, E, S, W] | ||||||
| @@ -78,49 +94,46 @@ const | |||||||
|   Pawn_Moves_White = [N] |   Pawn_Moves_White = [N] | ||||||
|   Pawn_Moves_White_Double = [N+N] |   Pawn_Moves_White_Double = [N+N] | ||||||
|   Pawn_Moves_White_Attack = [N+E, N+W] |   Pawn_Moves_White_Attack = [N+E, N+W] | ||||||
|  |   # Material as PieceAmount where a forced checkmate is not possible. | ||||||
| let PieceChar = { |   InsufficientMaterial: array[4,PieceAmount] = [ | ||||||
|   0: " ", |     (0, 0, 0, 0, 0), # only kings | ||||||
|   1: "P", |     (0, 0, 1, 0, 0), # knight only | ||||||
|   2: "N", |     (0, 1, 0, 0, 0), # bishop only | ||||||
|   3: "B", |     (0, 2, 0, 0, 0)  # 2 knights | ||||||
|   4: "R", |  | ||||||
|   5: "Q", |  | ||||||
|   6: "K", |  | ||||||
|   7: " ", |  | ||||||
|   -1: "p", |  | ||||||
|   -2: "n", |  | ||||||
|   -3: "b", |  | ||||||
|   -4: "r", |  | ||||||
|   -5: "q", |  | ||||||
|   -6: "k", |  | ||||||
|   -7: " ", |  | ||||||
|   999: "-" |  | ||||||
| }.newTable |  | ||||||
|  |  | ||||||
| let FileChar = { |  | ||||||
|   "a": 7, |  | ||||||
|   "b": 6, |  | ||||||
|   "c": 5, |  | ||||||
|   "d": 4, |  | ||||||
|   "e": 3, |  | ||||||
|   "f": 2, |  | ||||||
|   "g": 1, |  | ||||||
|   "h": 0 |  | ||||||
| }.newTable |  | ||||||
|  |  | ||||||
| const InsufficientMaterial = @[ |  | ||||||
|   #p, n, b, r, q |  | ||||||
|     # lone kings |  | ||||||
|   (0, 0, 0, 0, 0), |  | ||||||
|   # knight only |  | ||||||
|   (0, 0, 1, 0, 0), |  | ||||||
|   # bishop only |  | ||||||
|   (0, 1, 0, 0, 0), |  | ||||||
|   # 2 knights |  | ||||||
|   (0, 2, 0, 0, 0) |  | ||||||
|   ] |   ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | let | ||||||
|  |   # Representation of the pieces by ID. | ||||||
|  |   PieceChar = { | ||||||
|  |     0: " ", | ||||||
|  |     WPawn: "P", | ||||||
|  |     WKnight: "N", | ||||||
|  |     WBishop: "B", | ||||||
|  |     WRook: "R", | ||||||
|  |     WQueen: "Q", | ||||||
|  |     WKing: "K", | ||||||
|  |     WEnPassant: " ", | ||||||
|  |     BPawn: "p", | ||||||
|  |     BKnight: "n", | ||||||
|  |     BBishop: "b", | ||||||
|  |     BRook: "r", | ||||||
|  |     BQueen: "q", | ||||||
|  |     BKing: "k", | ||||||
|  |     BEnPassant: " ", | ||||||
|  |   }.newTable | ||||||
|  |   # Files on the chess board mapped to according integers. | ||||||
|  |   FileChar = { | ||||||
|  |     "a": 7, | ||||||
|  |     "b": 6, | ||||||
|  |     "c": 5, | ||||||
|  |     "d": 4, | ||||||
|  |     "e": 3, | ||||||
|  |     "f": 2, | ||||||
|  |     "g": 1, | ||||||
|  |     "h": 0 | ||||||
|  |   }.newTable | ||||||
|  |  | ||||||
| proc setField(board: var Board, field: int, val: int): bool {.discardable.} = | proc setField(board: var Board, field: int, val: int): bool {.discardable.} = | ||||||
|   try: |   try: | ||||||
|     if (val in PieceChar): |     if (val in PieceChar): | ||||||
| @@ -173,8 +186,8 @@ proc checkInsufficientMaterial(board: Board): bool = | |||||||
|         bq = bq + 1 |         bq = bq + 1 | ||||||
|       else: |       else: | ||||||
|         continue |         continue | ||||||
|   let wpieces = (wp, wn, wb, wr, wq) |   let wpieces: PieceAmount = (wp, wn, wb, wr, wq) | ||||||
|   let bpieces = (bp, bn, bb, br, bq) |   let bpieces: PieceAmount = (bp, bn, bb, br, bq) | ||||||
|   return (wpieces in InsufficientMaterial) and (bpieces in InsufficientMaterial) |   return (wpieces in InsufficientMaterial) and (bpieces in InsufficientMaterial) | ||||||
|  |  | ||||||
| proc initBoard(): Board = | proc initBoard(): Board = | ||||||
| @@ -227,7 +240,8 @@ proc initMoved(): Moved = | |||||||
| proc initGame*(): Game = | proc initGame*(): Game = | ||||||
|   ## Create and return a Game object. |   ## Create and return a Game object. | ||||||
|   let game = Game(board: initBoard(), moved: initMoved(), |   let game = Game(board: initBoard(), moved: initMoved(), | ||||||
|       to_move: Color.White, previousBoard: @[], previousCastleRights: @[], fiftyMoveCounter: 0) |       to_move: Color.White, previousBoard: @[], previousCastleRights: @[], | ||||||
|  |           fiftyMoveCounter: 0) | ||||||
|   return game |   return game | ||||||
|  |  | ||||||
| proc initGame*(board: array[0..63, int], color: Color): Game = | proc initGame*(board: array[0..63, int], color: Color): Game = | ||||||
| @@ -240,19 +254,20 @@ proc initGame*(board: array[0..63, int], color: Color): Game = | |||||||
|     same_piece = (board[ind] != compare[ind]) |     same_piece = (board[ind] != compare[ind]) | ||||||
|     moved.setField(ind, same_piece) |     moved.setField(ind, same_piece) | ||||||
|   let game = Game(board: board, moved: moved, |   let game = Game(board: board, moved: moved, | ||||||
|       to_move: color, previousBoard: @[], previousCastleRights: @[], fiftyMoveCounter: 0) |       to_move: color, previousBoard: @[], previousCastleRights: @[], | ||||||
|  |           fiftyMoveCounter: 0) | ||||||
|   return game |   return game | ||||||
|  |  | ||||||
| proc getMove*(start: int, dest: int, prom: int, color: Color): Move = | proc getMove*(start: int, dest: int, prom: int, color: Color): Move = | ||||||
|   ## Get a move object from `start` to `dest` with an eventual promition to `prom` |   ## Get a move object from `start` to `dest` with an eventual promition to `prom` | ||||||
|   var move = Move(start: start, dest: dest, prom: prom * ord(color), color: color) |   var move = Move(start: start, dest: dest, prom: prom * ord(color), color: color) | ||||||
|   if (KnightID > prom or QueenID < prom): |   if (WKnight > prom or WQueen < prom): | ||||||
|     move.prom = QueenID |     move.prom = WQueen | ||||||
|   return move |   return move | ||||||
|  |  | ||||||
| proc getMove*(start: int, dest: int, color: Color): Move = | proc getMove*(start: int, dest: int, color: Color): Move = | ||||||
|   ## Get a move object from `start` to `dest` with automatic promition to `queen` |   ## Get a move object from `start` to `dest` with automatic promition to `queen` | ||||||
|   var move = Move(start: start, dest: dest, prom: QueenID * ord(color), color: color) |   var move = Move(start: start, dest: dest, prom: WQueen * ord(color), color: color) | ||||||
|   return move |   return move | ||||||
|  |  | ||||||
| proc echoBoard*(game: Game, color: Color) = | proc echoBoard*(game: Game, color: Color) = | ||||||
| @@ -319,13 +334,13 @@ proc notationToMove*(notation: string, color: Color): Move = | |||||||
|       var prom: int |       var prom: int | ||||||
|       case promStr: |       case promStr: | ||||||
|         of "Q": |         of "Q": | ||||||
|           prom = QueenID * ord(color) |           prom = WQueen * ord(color) | ||||||
|         of "R": |         of "R": | ||||||
|           prom = RookID * ord(color) |           prom = WRook * ord(color) | ||||||
|         of "B": |         of "B": | ||||||
|           prom = BishopID * ord(color) |           prom = WBishop * ord(color) | ||||||
|         of "N": |         of "N": | ||||||
|           prom = KnightID * ord(color) |           prom = WKnight * ord(color) | ||||||
|       move = getMove(start, dest, prom, color) |       move = getMove(start, dest, prom, color) | ||||||
|     return move |     return move | ||||||
|   except IndexError: |   except IndexError: | ||||||
| @@ -343,9 +358,9 @@ proc genBishopDests(game: Game, field: int, color: Color): seq[int] = | |||||||
|       dest = field+move |       dest = field+move | ||||||
|       target = game.board[dest] |       target = game.board[dest] | ||||||
|       while (target != 999 and (ord(color) * target <= 0) or target == |       while (target != 999 and (ord(color) * target <= 0) or target == | ||||||
|           EnPassantID or target == -EnPassantID): |           WEnPassant or target == -WEnPassant): | ||||||
|         res.add(dest) |         res.add(dest) | ||||||
|         if (ord(color) * target < 0 and ord(color) * target > -EnPassantID): |         if (ord(color) * target < 0 and ord(color) * target > -WEnPassant): | ||||||
|           break |           break | ||||||
|         dest = dest+move |         dest = dest+move | ||||||
|         target = game.board[dest] |         target = game.board[dest] | ||||||
| @@ -364,9 +379,9 @@ proc genRookDests(game: Game, field: int, color: Color): seq[int] = | |||||||
|       dest = field+move |       dest = field+move | ||||||
|       target = game.board[dest] |       target = game.board[dest] | ||||||
|       while (target != 999 and (ord(color) * target <= 0) or target == |       while (target != 999 and (ord(color) * target <= 0) or target == | ||||||
|           EnPassantID or target == -EnPassantID): |           WEnPassant or target == -WEnPassant): | ||||||
|         res.add(dest) |         res.add(dest) | ||||||
|         if (ord(color) * target < 0 and ord(color) * target > -EnPassantID): |         if (ord(color) * target < 0 and ord(color) * target > -WEnPassant): | ||||||
|           break |           break | ||||||
|         dest = dest+move |         dest = dest+move | ||||||
|         target = game.board[dest] |         target = game.board[dest] | ||||||
| @@ -385,9 +400,9 @@ proc genQueenDests(game: Game, field: int, color: Color): seq[int] = | |||||||
|       dest = field+move |       dest = field+move | ||||||
|       target = game.board[dest] |       target = game.board[dest] | ||||||
|       while (target != 999 and (ord(color) * target <= 0) or target == |       while (target != 999 and (ord(color) * target <= 0) or target == | ||||||
|           EnPassantID or target == -EnPassantID): |           WEnPassant or target == -WEnPassant): | ||||||
|         res.add(dest) |         res.add(dest) | ||||||
|         if (ord(color) * target < 0 and ord(color) * target > -EnPassantID): |         if (ord(color) * target < 0 and ord(color) * target > -WEnPassant): | ||||||
|           break |           break | ||||||
|         dest = dest+move |         dest = dest+move | ||||||
|         target = game.board[dest] |         target = game.board[dest] | ||||||
| @@ -429,7 +444,7 @@ proc genKingDests(game: Game, field: int, color: Color): seq[int] = | |||||||
|     for move in King_Moves: |     for move in King_Moves: | ||||||
|       dest = field + move |       dest = field + move | ||||||
|       target = game.board[dest] |       target = game.board[dest] | ||||||
|       if (target == 999 or (ord(color) * target > 0 and ord(color) * target != EnPassantID)): |       if (target == 999 or (ord(color) * target > 0 and ord(color) * target != WEnPassant)): | ||||||
|         continue |         continue | ||||||
|       res.add(dest) |       res.add(dest) | ||||||
|     res.add(game.genKingCastleDest(field, color)) |     res.add(game.genKingCastleDest(field, color)) | ||||||
| @@ -447,7 +462,7 @@ proc genKnightDests(game: Game, field: int, color: Color): seq[int] = | |||||||
|     for move in Knight_Moves: |     for move in Knight_Moves: | ||||||
|       dest = field + move |       dest = field + move | ||||||
|       target = game.board[dest] |       target = game.board[dest] | ||||||
|       if (target == 999 or (ord(color) * target > 0 and ord(color) * target != EnPassantID)): |       if (target == 999 or (ord(color) * target > 0 and ord(color) * target != WEnPassant)): | ||||||
|         continue |         continue | ||||||
|       res.add(dest) |       res.add(dest) | ||||||
|     return res |     return res | ||||||
| @@ -499,7 +514,7 @@ proc genPawnDests(game: Game, field: int, color: Color): seq[int] = | |||||||
|     for move in Pawn_Moves_White: |     for move in Pawn_Moves_White: | ||||||
|       dest = field + move * ord(color) |       dest = field + move * ord(color) | ||||||
|       target = game.board[dest] |       target = game.board[dest] | ||||||
|       if (target != 0 and target != ord(color) * EnPassantID): |       if (target != 0 and target != ord(color) * WEnPassant): | ||||||
|         continue |         continue | ||||||
|       res.add(dest) |       res.add(dest) | ||||||
|     res.add(game.genPawnAttackDests(field, color)) |     res.add(game.genPawnAttackDests(field, color)) | ||||||
| @@ -520,24 +535,24 @@ proc isAttacked(game: Game, position: int, color: Color): bool = | |||||||
|   ## Check if a field is attacked by the opposite of `color` in a `game`. |   ## Check if a field is attacked by the opposite of `color` in a `game`. | ||||||
|   var attacked = false |   var attacked = false | ||||||
|   attacked = attacked or game.pieceOn(color, game.genPawnAttackDests( |   attacked = attacked or game.pieceOn(color, game.genPawnAttackDests( | ||||||
|       position, color), PawnID) |       position, color), WPawn) | ||||||
|   attacked = attacked or game.pieceOn(color, game.genQueenDests(position, |   attacked = attacked or game.pieceOn(color, game.genQueenDests(position, | ||||||
|       color), QueenID) |       color), WQueen) | ||||||
|   attacked = attacked or game.pieceOn(color, game.genKingDests(position, |   attacked = attacked or game.pieceOn(color, game.genKingDests(position, | ||||||
|       color), KingID) |       color), WKing) | ||||||
|   attacked = attacked or game.pieceOn(color, game.genRookDests(position, |   attacked = attacked or game.pieceOn(color, game.genRookDests(position, | ||||||
|       color), RookID) |       color), WRook) | ||||||
|   attacked = attacked or game.pieceOn(color, game.genBishopDests(position, |   attacked = attacked or game.pieceOn(color, game.genBishopDests(position, | ||||||
|       color), BishopID) |       color), WBishop) | ||||||
|   attacked = attacked or game.pieceOn(color, game.genKnightDests(position, |   attacked = attacked or game.pieceOn(color, game.genKnightDests(position, | ||||||
|       color), KnightID) |       color), WKnight) | ||||||
|   return attacked |   return attacked | ||||||
|  |  | ||||||
| proc isInCheck*(game: Game, color: Color): bool = | proc isInCheck*(game: Game, color: Color): bool = | ||||||
|   ## Check if the King of a given `color` is in check in a `game`. |   ## Check if the King of a given `color` is in check in a `game`. | ||||||
|   var king_pos: int |   var king_pos: int | ||||||
|   for i in countup(0, game.board.high): |   for i in countup(0, game.board.high): | ||||||
|     if game.board[i] == ord(color) * KingID: |     if game.board[i] == ord(color) * WKing: | ||||||
|       king_pos = i |       king_pos = i | ||||||
|   return game.isAttacked(king_pos, color) |   return game.isAttacked(king_pos, color) | ||||||
|  |  | ||||||
| @@ -567,12 +582,12 @@ proc moveLeadsToCheck(game: Game, start: int, dest: int, | |||||||
| proc removeEnPassant(board: var Board, color: Color): void = | proc removeEnPassant(board: var Board, color: Color): void = | ||||||
|   ## Removes every en passant of given `color` from the `game`. |   ## Removes every en passant of given `color` from the `game`. | ||||||
|   for field in board.low..board.high: |   for field in board.low..board.high: | ||||||
|     if board[field] == ord(color) * EnPassantID: |     if board[field] == ord(color) * WEnPassant: | ||||||
|       board.setField(field, 0) |       board.setField(field, 0) | ||||||
|  |  | ||||||
| proc genLegalKnightMoves(game: Game, field: int, color: Color): seq[Move] = | proc genLegalKnightMoves(game: Game, field: int, color: Color): seq[Move] = | ||||||
|   ## Generates all legal knight moves starting from `field` in a `game` for a `color`. |   ## Generates all legal knight moves starting from `field` in a `game` for a `color`. | ||||||
|   if game.board[field] != KnightID * ord(color): |   if game.board[field] != WKnight * ord(color): | ||||||
|     return @[] |     return @[] | ||||||
|   var res = newSeq[Move]() |   var res = newSeq[Move]() | ||||||
|   var moves = game.genKnightDests(field, color) |   var moves = game.genKnightDests(field, color) | ||||||
| @@ -583,7 +598,7 @@ proc genLegalKnightMoves(game: Game, field: int, color: Color): seq[Move] = | |||||||
|  |  | ||||||
| proc genLegalBishopMoves(game: Game, field: int, color: Color): seq[Move] = | proc genLegalBishopMoves(game: Game, field: int, color: Color): seq[Move] = | ||||||
|   ## Generates all legal bishop moves starting from `field` in a `game` for a `color`. |   ## Generates all legal bishop moves starting from `field` in a `game` for a `color`. | ||||||
|   if game.board[field] != BishopID * ord(color): |   if game.board[field] != WBishop * ord(color): | ||||||
|     return @[] |     return @[] | ||||||
|   var res = newSeq[Move]() |   var res = newSeq[Move]() | ||||||
|   var moves = game.genBishopDests(field, color) |   var moves = game.genBishopDests(field, color) | ||||||
| @@ -594,7 +609,7 @@ proc genLegalBishopMoves(game: Game, field: int, color: Color): seq[Move] = | |||||||
|  |  | ||||||
| proc genLegalRookMoves(game: Game, field: int, color: Color): seq[Move] = | proc genLegalRookMoves(game: Game, field: int, color: Color): seq[Move] = | ||||||
|   ## Generates all legal rook moves starting from `field` in a `game` for a `color`. |   ## Generates all legal rook moves starting from `field` in a `game` for a `color`. | ||||||
|   if game.board[field] != RookID * ord(color): |   if game.board[field] != WRook * ord(color): | ||||||
|     return @[] |     return @[] | ||||||
|   var res = newSeq[Move]() |   var res = newSeq[Move]() | ||||||
|   var moves = game.genRookDests(field, color) |   var moves = game.genRookDests(field, color) | ||||||
| @@ -605,7 +620,7 @@ proc genLegalRookMoves(game: Game, field: int, color: Color): seq[Move] = | |||||||
|  |  | ||||||
| proc genLegalQueenMoves(game: Game, field: int, color: Color): seq[Move] = | proc genLegalQueenMoves(game: Game, field: int, color: Color): seq[Move] = | ||||||
|   ## Generates all legal queen moves starting from `field` in a `game` for a `color`. |   ## Generates all legal queen moves starting from `field` in a `game` for a `color`. | ||||||
|   if game.board[field] != QueenID * ord(color): |   if game.board[field] != WQueen * ord(color): | ||||||
|     return @[] |     return @[] | ||||||
|   var res = newSeq[Move]() |   var res = newSeq[Move]() | ||||||
|   var moves = game.genQueenDests(field, color) |   var moves = game.genQueenDests(field, color) | ||||||
| @@ -616,7 +631,7 @@ proc genLegalQueenMoves(game: Game, field: int, color: Color): seq[Move] = | |||||||
|  |  | ||||||
| proc genLegalKingMoves(game: Game, field: int, color: Color): seq[Move] = | proc genLegalKingMoves(game: Game, field: int, color: Color): seq[Move] = | ||||||
|   ## Generates all legal king moves starting from `field` in a `game` for a `color`. |   ## Generates all legal king moves starting from `field` in a `game` for a `color`. | ||||||
|   if game.board[field] != KingID * ord(color): |   if game.board[field] != WKing * ord(color): | ||||||
|     return @[] |     return @[] | ||||||
|   var res = newSeq[Move]() |   var res = newSeq[Move]() | ||||||
|   var moves = game.genKingDests(field, color) |   var moves = game.genKingDests(field, color) | ||||||
| @@ -635,13 +650,13 @@ proc genPawnPromotion(move: Move, color: Color): seq[Move] = | |||||||
|   let start = move.start |   let start = move.start | ||||||
|   let dest = move.dest |   let dest = move.dest | ||||||
|   if (90 < dest and dest < 99) or (20 < dest and dest < 29): |   if (90 < dest and dest < 99) or (20 < dest and dest < 29): | ||||||
|     for piece in KnightID..QueenID: |     for piece in WKnight..WQueen: | ||||||
|       promotions.add(getMove(start, dest, piece, color)) |       promotions.add(getMove(start, dest, piece, color)) | ||||||
|   return promotions |   return promotions | ||||||
|  |  | ||||||
| proc genLegalPawnMoves(game: Game, field: int, color: Color): seq[Move] = | proc genLegalPawnMoves(game: Game, field: int, color: Color): seq[Move] = | ||||||
|   ## Generates all legal pawn moves starting from `field` in a `game` for a `color`. |   ## Generates all legal pawn moves starting from `field` in a `game` for a `color`. | ||||||
|   if game.board[field] != PawnID * ord(color): |   if game.board[field] != WPawn * ord(color): | ||||||
|     return @[] |     return @[] | ||||||
|   var res = newSeq[Move]() |   var res = newSeq[Move]() | ||||||
|   var moves = game.genPawnDests(field, color) |   var moves = game.genPawnDests(field, color) | ||||||
| @@ -658,19 +673,19 @@ proc genLegalMoves*(game: Game, field: int, color: Color): seq[Move] = | |||||||
|   ## Generates all legal moves starting from `field` in a `game` for a `color`. |   ## Generates all legal moves starting from `field` in a `game` for a `color`. | ||||||
|   var legal_moves = newSeq[Move]() |   var legal_moves = newSeq[Move]() | ||||||
|   var target = ord(color) * game.board[field] |   var target = ord(color) * game.board[field] | ||||||
|   if 0 < target and target < EnPassantID: |   if 0 < target and target < WEnPassant: | ||||||
|     legal_moves = case target: |     legal_moves = case target: | ||||||
|       of PawnID: |       of WPawn: | ||||||
|         game.genLegalPawnMoves(field, color) |         game.genLegalPawnMoves(field, color) | ||||||
|       of KnightID: |       of WKnight: | ||||||
|         game.genLegalKnightMoves(field, color) |         game.genLegalKnightMoves(field, color) | ||||||
|       of BishopID: |       of WBishop: | ||||||
|         game.genLegalBishopMoves(field, color) |         game.genLegalBishopMoves(field, color) | ||||||
|       of RookID: |       of WRook: | ||||||
|         game.genLegalRookMoves(field, color) |         game.genLegalRookMoves(field, color) | ||||||
|       of QueenID: |       of WQueen: | ||||||
|         game.genLegalQueenMoves(field, color) |         game.genLegalQueenMoves(field, color) | ||||||
|       of KingID: |       of WKing: | ||||||
|         game.genLegalKingMoves(field, color) |         game.genLegalKingMoves(field, color) | ||||||
|       else: |       else: | ||||||
|         @[] |         @[] | ||||||
| @@ -742,28 +757,28 @@ proc checkedMove*(game: var Game, move: Move): bool {.discardable.} = | |||||||
|     var fiftyMoveRuleReset = false |     var fiftyMoveRuleReset = false | ||||||
|     var move: Move |     var move: Move | ||||||
|     move = getMove(start, dest, color) |     move = getMove(start, dest, color) | ||||||
|     if (piece == PawnID * ord(color)): |     if (piece == WPawn * ord(color)): | ||||||
|       createEnPassant = dest in game.genPawnDoubleDests(start, color) |       createEnPassant = dest in game.genPawnDoubleDests(start, color) | ||||||
|       capturedEnPassant = (game.board[dest] == -1 * ord(color) * EnPassantID) |       capturedEnPassant = (game.board[dest] == -1 * ord(color) * WEnPassant) | ||||||
|       fiftyMoveRuleReset = true |       fiftyMoveRuleReset = true | ||||||
|     if (game.board[move.dest] != 0): |     if (game.board[move.dest] != 0): | ||||||
|       fiftyMoveRuleReset = true |       fiftyMoveRuleReset = true | ||||||
|     sequence.add(game.genLegalMoves(start, color)) |     sequence.add(game.genLegalMoves(start, color)) | ||||||
|     if (move in sequence): |     if (move in sequence): | ||||||
|       game.board.removeEnPassant(color) |       game.board.removeEnPassant(color) | ||||||
|       if (piece == KingID * ord(color) and (start - dest == (W+W))): |       if (piece == WKing * ord(color) and (start - dest == (W+W))): | ||||||
|         return game.castling(start, true, color) |         return game.castling(start, true, color) | ||||||
|       elif (piece == KingID * ord(color) and (start - dest == (E+E))): |       elif (piece == WKing * ord(color) and (start - dest == (E+E))): | ||||||
|         return game.castling(start, false, color) |         return game.castling(start, false, color) | ||||||
|       else: |       else: | ||||||
|         game.uncheckedMove(start, dest) |         game.uncheckedMove(start, dest) | ||||||
|       game.toMove = Color(ord(game.toMove)*(-1)) |       game.toMove = Color(ord(game.toMove)*(-1)) | ||||||
|       if createEnPassant: |       if createEnPassant: | ||||||
|         game.board.setField(dest-(N*ord(color)), EnPassantID * ord(color)) |         game.board.setField(dest-(N*ord(color)), WEnPassant * ord(color)) | ||||||
|       if capturedEnPassant: |       if capturedEnPassant: | ||||||
|         game.board.setField(dest-(N*ord(color)), 0) |         game.board.setField(dest-(N*ord(color)), 0) | ||||||
|       if ((90 < dest and dest < 99) or (20 < dest and dest < 29)) and |       if ((90 < dest and dest < 99) or (20 < dest and dest < 29)) and | ||||||
|           game.board[dest] == PawnID * ord(color): |           game.board[dest] == WPawn * ord(color): | ||||||
|         game.board.setField(dest, prom) |         game.board.setField(dest, prom) | ||||||
|       var prevBoard = game.previousBoard |       var prevBoard = game.previousBoard | ||||||
|       var prevCastle = game.previousCastleRights |       var prevCastle = game.previousCastleRights | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user