Mercurial > projects > doodle
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 } |