comparison doodle/main/util/chess.d @ 134:89e8b0d92f36

Ported to bob2 !!!
author David Bryant <bagnose@gmail.com>
date Thu, 02 Aug 2012 17:20:52 +0930
parents doodle/main/prog/chess.d@bc5baa585b32
children
comparison
equal deleted inserted replaced
133:9e1a313d8003 134:89e8b0d92f36
1 //
2 // Notes:
3 // ply = half move (ie black or white's half of the move)
4
5 import std.stdio;
6 import std.ascii;
7 import std.traits;
8 import std.range;
9
10 enum Side {
11 White, Black
12 }
13
14 enum Name {
15 King, Queen, Rook, Bishop, Knight, Pawn
16 }
17
18 struct Piece {
19 Side side;
20 Name name;
21 }
22
23 string toString(Piece piece) {
24 return
25 [
26 [ "\u2654", "\u2655", "\u2656", "\u2657", "\u2658", "\u2659" ],
27 [ "\u265A", "\u265B", "\u265C", "\u265D", "\u265E", "\u265F" ]
28 ]
29 [piece.side][piece.name];
30 }
31
32 //
33 //
34 //
35
36 enum File {
37 _A, _B, _C, _D, _E, _F, _G, _H
38 }
39
40 char toChar(File f) {
41 return "abcdefgh"[f];
42 }
43
44 enum Rank {
45 _1, _2, _3, _4, _5, _6, _7, _8
46 }
47
48 char toChar(Rank r) {
49 return "12345678"[r];
50 }
51
52 struct Coord {
53 File file;
54 Rank rank;
55 }
56
57 string toString(in Coord coord) {
58 return toChar(coord.file) ~ "+" ~ toChar(coord.rank);
59 }
60
61 //
62 //
63 //
64
65 struct Board {
66 struct Square {
67 this(in Side side, in Name name) {
68 occupied = true;
69 piece = Piece(side, name);
70 }
71
72 bool occupied = false;
73 Piece piece; // valid if occupied
74 }
75
76 this(in Square[8][8] squares_) {
77 squares = squares_;
78 }
79
80 Square square(Coord coord) const {
81 return squares[coord.file][coord.rank];
82 }
83
84 private:
85 Square * at(Coord coord) {
86 return &squares[coord.file][coord.rank];
87 }
88
89 void add(Piece piece, Coord coord) {
90 auto square = at(coord);
91 if (square.occupied) {
92 // error
93 }
94 else {
95 square.occupied = true;
96 square.piece = piece;
97 }
98 }
99
100 void remove(Coord coord) {
101 auto square = at(coord);
102 if (square.occupied) {
103 square.occupied = false;
104 }
105 else {
106 // error
107 }
108 }
109
110 void move(Coord source, Coord dest) {
111 auto source_sq = at(source);
112 auto dest_sq = at(dest);
113
114 if (source_sq.occupied && !dest_sq.occupied) {
115 source_sq.occupied = false;
116 dest_sq.occupied = true;
117 dest_sq.piece = source_sq.piece;
118 }
119 else {
120 // error
121 }
122 }
123
124 Square[8][8] squares =
125 [
126 [ Square(Side.White, Name.Rook), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Rook) ],
127 [ Square(Side.White, Name.Knight), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Knight) ],
128 [ Square(Side.White, Name.Bishop), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Bishop) ],
129 [ Square(Side.White, Name.Queen), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Queen) ],
130 [ Square(Side.White, Name.King), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.King) ],
131 [ Square(Side.White, Name.Bishop), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Bishop) ],
132 [ Square(Side.White, Name.Knight), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Knight) ],
133 [ Square(Side.White, Name.Rook), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Rook) ]
134 ];
135 }
136
137 void dump(in Board board) {
138 bool light_square = true;
139
140 foreach_reverse(r; EnumMembers!Rank) {
141 write(toChar(r));
142 foreach(f; EnumMembers!File) {
143
144 if (light_square) {
145 write("\033[47m");
146 }
147 else {
148 write("\033[40m");
149 }
150
151 Board.Square square = board.square(Coord(f, r));
152 if (square.occupied) {
153 write(toString(square.piece));
154 }
155 else {
156 write(" ");
157 }
158
159 light_square = !light_square;
160 }
161 writeln("\033[0m");
162
163 light_square = !light_square;
164 }
165
166 write(" ");
167 foreach(f; EnumMembers!File) {
168 writef("%s", toChar(f));
169 }
170 writeln("");
171 }
172
173 //
174 //
175 //
176
177 enum KingState {
178 Safe,
179 Check,
180 CheckMate
181 }
182
183 class Game {
184 struct SideState {
185 KingState kingState;
186 bool kingMoved;
187 bool queenRookMoved;
188 bool kingRookMoved;
189 }
190
191 struct Ply {
192 this(Coord source_, Coord dest_) {
193 source = source_;
194 dest = dest_;
195 }
196
197 Coord source;
198 Coord dest;
199 }
200
201 @property Board board() { return _board; }
202
203 struct Flags {
204 bool check;
205 bool mate;
206 }
207
208 // Default initial pieces, white to play
209 this () {
210 }
211
212 // Restore a previous game
213 this (Board board, Flags whiteFlags, Flags blackFlags, Side nextPly) {
214 _board = board;
215 _nextPly = nextPly;
216 }
217
218 enum Acceptance {
219 Normal,
220 Check,
221 Mate,
222 Illegal
223 }
224
225 Acceptance apply(in Ply ply) {
226 auto source = _board.square(ply.source);
227 auto dest = _board.square(ply.dest);
228
229 /+
230 auto sq1 = square(update.source);
231 auto sq2 = square(update.dest);
232
233 if (sq1.piece == Piece.Pawn && update.dest.file != update.source.file) {
234 // en-passant
235 }
236 else if (sq1.piece == Piece.King && update.dest.file - update.source.file > 1) {
237 // castle
238 }
239 +/
240
241 return Acceptance.Normal;
242 }
243
244 private {
245 struct PieceState {
246 bool uncaptured;
247 Coord coord; // valid if uncaptured
248 }
249
250 Board _board;
251 Side _nextPly;
252 SideState _whiteSideState;
253 PieceState[8] _whitePieceState;
254 SideState _blackSideState;
255 PieceState[8] _blackPieceState;
256 }
257 }
258
259 void main(string[] args) {
260 Board board;
261 dump(board);
262
263 /+
264 Game game;
265 +/
266 }