pychessai 0.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.4
2
+ Name: pychessai
3
+ Version: 0.0.0
4
+ Summary: chess ai which plays like a human
5
+ Home-page: https://github.com/infinity390/mathai4
6
+ Requires-Python: >=3.7
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: lark-parser
9
+ Dynamic: description
10
+ Dynamic: description-content-type
11
+ Dynamic: home-page
12
+ Dynamic: requires-dist
13
+ Dynamic: requires-python
14
+ Dynamic: summary
15
+
16
+ dummy package
@@ -0,0 +1 @@
1
+ dummy package
File without changes
@@ -0,0 +1,344 @@
1
+ import random
2
+ import sys
3
+ import chess
4
+ import copy
5
+ def evaluate_material(board):
6
+ if board.is_checkmate():
7
+ # If it's checkmate, return ±infinity based on who won
8
+ return float('-inf') if board.turn else float('inf')
9
+
10
+ piece_values = {
11
+ chess.PAWN: 100,
12
+ chess.KNIGHT: 300,
13
+ chess.BISHOP: 300,
14
+ chess.ROOK: 500,
15
+ chess.QUEEN: 900
16
+ }
17
+
18
+ white_score = 0
19
+ black_score = 0
20
+ white_bishops = 0
21
+ black_bishops = 0
22
+
23
+ for square, piece in board.piece_map().items():
24
+ value = piece_values.get(piece.piece_type, 0)
25
+ if piece.color == chess.WHITE:
26
+ white_score += value
27
+ if piece.piece_type == chess.BISHOP:
28
+ white_bishops += 1
29
+ else:
30
+ black_score += value
31
+ if piece.piece_type == chess.BISHOP:
32
+ black_bishops += 1
33
+
34
+ # Bishop pair bonus
35
+ if white_bishops >= 2:
36
+ white_score += 50
37
+ if black_bishops >= 2:
38
+ black_score += 50
39
+
40
+ return white_score - black_score
41
+ def normalize_fen(fen):
42
+ parts = fen.split(" ")
43
+ return parts[0]
44
+
45
+ position_history = []
46
+
47
+ def legal_moves_without_threefold_repetition(board):
48
+ global position_history
49
+ legal_moves = []
50
+
51
+ for move in board.legal_moves:
52
+ board.push(move)
53
+ normalized_fen = normalize_fen(board.fen())
54
+ if position_history.count(normalized_fen) > 1 or board.halfmove_clock > 10 or board.is_stalemate():
55
+ board.pop() # Undo the move
56
+ continue # Skip this move
57
+
58
+ legal_moves.append(move)
59
+
60
+ board.pop() # Undo the move
61
+
62
+ return legal_moves
63
+
64
+ def negamax_capture_pv(board, depth, alpha=float("-inf"), beta=float("inf"), loc=None):
65
+ if depth == 0 or board.is_game_over():
66
+ return colorsign(board) * evaluate_material(board), []
67
+
68
+ max_eval = float("-inf")
69
+ best_line = []
70
+
71
+ # Capture moves
72
+ for move in legal_moves_without_threefold_repetition(board):
73
+ if board.is_capture(move) and (loc is None or loc == move.to_square):
74
+ board.push(move)
75
+ score, line = negamax_capture_pv(board, depth - 1, -beta, -alpha, move.to_square)
76
+ board.pop()
77
+
78
+ score = -score
79
+ if score > max_eval:
80
+ max_eval = score
81
+ best_line = [move] + line
82
+ alpha = max(alpha, score)
83
+ if alpha >= beta:
84
+ break # Beta cutoff
85
+
86
+ # Quiet moves at depth 0
87
+ for move in legal_moves_without_threefold_repetition(board):
88
+ if not board.is_capture(move):
89
+ board.push(move)
90
+ score, line = negamax_capture_pv(board, 0, -beta, -alpha)
91
+ board.pop()
92
+
93
+ score = -score
94
+ if score > max_eval:
95
+ max_eval = score
96
+ best_line = [move] + line
97
+ alpha = max(alpha, score)
98
+ if alpha >= beta:
99
+ break # Beta cutoff
100
+
101
+ if max_eval == float("-inf"):
102
+ return colorsign(board) * evaluate_material(board), []
103
+
104
+ return max_eval, best_line
105
+
106
+
107
+
108
+ def colorsign(board):
109
+ return 1 if board.turn == chess.WHITE else -1
110
+
111
+ PST = {
112
+ chess.PAWN: [
113
+ 0, 0, 0, 0, 0, 0, 0, 0,
114
+ 5, 5, 5, 5, 5, 5, 5, 5,
115
+ 1, 1, 2, 3, 3, 2, 1, 1,
116
+ 0, 0, 0, 2, 2, 0, 0, 0,
117
+ 0, 0, 0, -2, -2, 0, 0, 0,
118
+ 1, -1, -2, 0, 0, -2, -1, 1,
119
+ 1, 2, 2, -2, -2, 2, 2, 1,
120
+ 0, 0, 0, 0, 0, 0, 0, 0
121
+ ],
122
+
123
+ chess.KNIGHT: [
124
+ -5, -4, -3, -3, -3, -3, -4, -5,
125
+ -4, -2, 0, 0, 0, 0, -2, -4,
126
+ -3, 0, 1, 1.5, 1.5, 1, 0, -3,
127
+ -3, 0.5, 1.5, 2, 2, 1.5, 0.5, -3,
128
+ -3, 0, 1.5, 2, 2, 1.5, 0, -3,
129
+ -3, 0.5, 1, 1.5, 1.5, 1, 0.5, -3,
130
+ -4, -2, 0, 0.5, 0.5, 0, -2, -4,
131
+ -5, -4, -3, -3, -3, -3, -4, -5
132
+ ],
133
+
134
+ chess.BISHOP: [
135
+ -2, -1, -1, -1, -1, -1, -1, -2,
136
+ -1, 0, 0, 0, 0, 0, 0, -1,
137
+ -1, 0, 0.5, 1, 1, 0.5, 0, -1,
138
+ -1, 0.5, 0.5, 1, 1, 0.5, 0.5, -1,
139
+ -1, 0, 1, 1, 1, 1, 0, -1,
140
+ -1, 1, 1, 1, 1, 1, 1, -1,
141
+ -1, 0.5, 0, 0, 0, 0, 0.5, -1,
142
+ -2, -1, -1, -1, -1, -1, -1, -2
143
+ ],
144
+
145
+ chess.ROOK: [
146
+ 0, 0, 0, 0, 0, 0, 0, 0,
147
+ 0.5, 1, 1, 1, 1, 1, 1, 0.5,
148
+ -0.5, 0, 0, 0, 0, 0, 0, -0.5,
149
+ -0.5, 0, 0, 0, 0, 0, 0, -0.5,
150
+ -0.5, 0, 0, 0, 0, 0, 0, -0.5,
151
+ -0.5, 0, 0, 0, 0, 0, 0, -0.5,
152
+ -0.5, 0, 0, 0, 0, 0, 0, -0.5,
153
+ 0, 0, 0, 0.5, 0.5, 0, 0, 0
154
+ ],
155
+
156
+ chess.QUEEN: [
157
+ -2, -1, -1, -0.5, -0.5, -1, -1, -2,
158
+ -1, 0, 0, 0, 0, 0, 0, -1,
159
+ -1, 0, 0.5, 0.5, 0.5, 0.5, 0, -1,
160
+ -0.5, 0, 0.5, 0.5, 0.5, 0.5, 0, -0.5,
161
+ 0, 0, 0.5, 0.5, 0.5, 0.5, 0, -0.5,
162
+ -1, 0.5, 0.5, 0.5, 0.5, 0.5, 0, -1,
163
+ -1, 0, 0.5, 0, 0, 0, 0, -1,
164
+ -2, -1, -1, -0.5, -0.5, -1, -1, -2
165
+ ],
166
+
167
+ chess.KING: [
168
+ -3, -4, -4, -5, -5, -4, -4, -3,
169
+ -3, -4, -4, -5, -5, -4, -4, -3,
170
+ -3, -4, -4, -5, -5, -4, -4, -3,
171
+ -3, -4, -4, -5, -5, -4, -4, -3,
172
+ -2, -3, -3, -4, -4, -3, -3, -2,
173
+ -1, -2, -2, -2, -2, -2, -2, -1,
174
+ 2, 2, 0, 0, 0, 0, 2, 2,
175
+ 2, 3, 1, 0, 0, 1, 3, 2
176
+ ]
177
+ }
178
+
179
+
180
+ # Get PST value depending on piece color
181
+ def pst_value(piece_type, square, color):
182
+ if piece_type not in PST:
183
+ return 0
184
+ index = square if color == chess.WHITE else chess.square_mirror(square)
185
+ return PST[piece_type][index]
186
+
187
+ # Sort legal moves by PST score
188
+ def sort_moves_by_pst(board):
189
+ legal_moves = list(legal_moves_without_threefold_repetition(board))
190
+
191
+ def move_score(move):
192
+ piece = board.piece_at(move.from_square)
193
+ if piece is None:
194
+ return 0
195
+ return pst_value(piece.piece_type, move.to_square, piece.color)
196
+
197
+ return sorted(legal_moves, key=move_score, reverse=True)
198
+
199
+
200
+ def try_center_push(board):
201
+ sorted_moves = sort_moves_by_pst(board)
202
+ lst = []
203
+ for move in sorted_moves:
204
+ board2 = copy.deepcopy(board)
205
+ board2.push(move)
206
+ tmp, line = negamax_capture_pv(board2, 100)
207
+ lst.append([move, tmp])
208
+ print(line)
209
+ print(tmp)
210
+ print(evaluate_material(board))
211
+ if board.turn == chess.BLACK and -tmp - evaluate_material(board) >= 0:
212
+ return move
213
+ if board.turn == chess.WHITE and -tmp - evaluate_material(board) >= 0:
214
+ return move
215
+ if lst == []:
216
+ return None
217
+ return sorted(lst, key=lambda x: x[1])[0][0]
218
+
219
+
220
+ def king_search(board, depth=2, alpha=float("-inf"), beta=float("inf")):
221
+
222
+ if depth == 0 or board.is_game_over():
223
+ return colorsign(board) * evaluate_material(board), []
224
+
225
+ max_eval = float("-inf")
226
+ best_line = []
227
+
228
+ if depth == 2:
229
+ legal = [move for move in legal_moves_without_threefold_repetition(board) if board.gives_check(move)]
230
+ else:
231
+ legal = list(legal_moves_without_threefold_repetition(board))
232
+
233
+ for move in legal:
234
+ board.push(move)
235
+ score, line = None, None
236
+ if depth == 1:
237
+ score, line = negamax_capture_pv(board, 100, -beta, -alpha)
238
+ else:
239
+ score, line = king_search(board, depth - 1, -beta, -alpha)
240
+ board.pop()
241
+
242
+ score = -score
243
+ if score > max_eval:
244
+ max_eval = score
245
+ best_line = [move] + line
246
+
247
+ alpha = max(alpha, score)
248
+ if alpha >= beta:
249
+ break # Beta cutoff
250
+
251
+ if max_eval == float("-inf"):
252
+ return colorsign(board) * evaluate_material(board), []
253
+
254
+ return max_eval, best_line
255
+
256
+
257
+ '''
258
+ board = chess.Board()
259
+
260
+ fen = "r1b1kbnr/1pp1pppp/n7/p2q4/3P4/5N2/PPP2PPP/RNBQKB1R w KQkq - 0 1"
261
+ fen = "r1bk1bnr/1pNp1ppp/2n2q2/p3p3/4P3/5N2/PPPP1PPP/R1BQKB1R w KQkq - 0 1"
262
+ board.set_fen(fen)
263
+
264
+ print(board)
265
+ print(evaluate_material(board))
266
+ print()
267
+ print()
268
+
269
+ position startpos moves e2e3 g8f6 d2d3 f6e4 d3e4 b8c6
270
+ position startpos moves e2e3 g8f6 d2d3 f6e4 d3e4 b8c6 f2f3 d7d5
271
+ position startpos moves e2e3 g8f6 d2d3 f6e4 d3e4 b8c6 f2f3 d7d5 d1d5 d8d5 e4d5 c8d7 d5c6 d7c6 e3e4 e8c8 c2c3 e7e5
272
+ '''
273
+
274
+ def playmove2(board):
275
+
276
+ score, line = king_search(board)
277
+ if board.turn == chess.WHITE and score - evaluate_material(board) > 0:
278
+
279
+ return line[0]
280
+ elif board.turn == chess.BLACK and score - evaluate_material(board) > 0:
281
+
282
+ return line[0]
283
+
284
+ score, line = negamax_capture_pv(board, 100)
285
+ if board.turn == chess.WHITE and score - evaluate_material(board) > 0:
286
+ return line[0]
287
+ elif board.turn == chess.BLACK and score - evaluate_material(board) > 0:
288
+
289
+ return line[0]
290
+
291
+ tmp = try_center_push(board)
292
+
293
+ if tmp is not None:
294
+ return tmp
295
+ return random.choice(list(board.legal_moves))
296
+
297
+ def playmove(board):
298
+ tmp = playmove2(board)
299
+ if tmp is None:
300
+ return None
301
+ # Return the new board after applying the move from playmove2
302
+ board.push(tmp)
303
+ return board
304
+
305
+ def uci_loop():
306
+ global position_history
307
+ board = chess.Board()
308
+
309
+ while True:
310
+ try:
311
+ command = input().strip()
312
+ except EOFError:
313
+ break
314
+
315
+ if command == "uci":
316
+ print("id name MyEngine")
317
+ print("id author You")
318
+ print("uciok")
319
+ elif command == "isready":
320
+ print("readyok")
321
+ elif command.startswith("position"):
322
+ tokens = command.split()
323
+ board = chess.Board()
324
+ position_history = []
325
+ if "startpos" in tokens:
326
+ moves_index = tokens.index("moves") if "moves" in tokens else None
327
+ if moves_index:
328
+ for move in tokens[moves_index + 1:]:
329
+ board.push_uci(move)
330
+ position_history.append(normalize_fen(board.fen()))
331
+ # You can also add support for "fen" if needed to initialize the board
332
+ elif command.startswith("go"):
333
+ new_board = playmove(board)
334
+ if new_board:
335
+ move = new_board.peek() # Get the most recent move after playing the move
336
+ print(f"bestmove {move}")
337
+ else:
338
+ print("bestmove 0000")
339
+ elif command == "quit":
340
+ break
341
+
342
+ if __name__ == "__main__":
343
+ uci_loop()
344
+
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.4
2
+ Name: pychessai
3
+ Version: 0.0.0
4
+ Summary: chess ai which plays like a human
5
+ Home-page: https://github.com/infinity390/mathai4
6
+ Requires-Python: >=3.7
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: lark-parser
9
+ Dynamic: description
10
+ Dynamic: description-content-type
11
+ Dynamic: home-page
12
+ Dynamic: requires-dist
13
+ Dynamic: requires-python
14
+ Dynamic: summary
15
+
16
+ dummy package
@@ -0,0 +1,9 @@
1
+ README.md
2
+ setup.py
3
+ chessai/__init__.py
4
+ chessai/core.py
5
+ pychessai.egg-info/PKG-INFO
6
+ pychessai.egg-info/SOURCES.txt
7
+ pychessai.egg-info/dependency_links.txt
8
+ pychessai.egg-info/requires.txt
9
+ pychessai.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ lark-parser
@@ -0,0 +1 @@
1
+ chessai
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,15 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="pychessai",
5
+ version="0.0.0",
6
+ description="chess ai which plays like a human",
7
+ long_description=open("README.md").read(),
8
+ long_description_content_type="text/markdown",
9
+ url="https://github.com/infinity390/mathai4",
10
+ packages=find_packages(),
11
+ install_requires=[
12
+ "lark-parser"
13
+ ],
14
+ python_requires=">=3.7",
15
+ )