mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-04 16:23:11 +02:00
feat: make move piece and initial ai algorithm
This commit is contained in:
parent
c71b6c3aa7
commit
98232581ff
264
lab2/main.py
264
lab2/main.py
@ -11,9 +11,9 @@ class Game:
|
||||
self.black_positions = self.initialize_black()
|
||||
print(self.white_positions)
|
||||
print(self.black_positions)
|
||||
self.check_move_piece_capable(1, 0, 1, 0, True)
|
||||
|
||||
def initialize_white(self):
|
||||
"""Initialize white pieces"""
|
||||
white_positions = []
|
||||
for y_coordinate in range(3):
|
||||
for x_coordinate in range(self.board_size):
|
||||
@ -26,6 +26,7 @@ class Game:
|
||||
return white_positions
|
||||
|
||||
def initialize_black(self):
|
||||
"""Initialize black pieces"""
|
||||
black_positions = []
|
||||
for y_coordinate in range(self.board_size - 3, self.board_size):
|
||||
for x_coordinate in range(self.board_size):
|
||||
@ -37,122 +38,106 @@ class Game:
|
||||
black_positions.append((x_coordinate, y_coordinate, False))
|
||||
return black_positions
|
||||
|
||||
def print_move_info(self, piece_x_coord, piece_y_coord, x_final, y_final):
|
||||
print("(piece_x_coordinate, piece_y_coordinate): " + (piece_x_coord, piece_y_coord))
|
||||
print("(x_final_coordinate, y_final_coordinate): " + (x_final, y_final))
|
||||
|
||||
def check_move_out_of_bounds(self, piece_x_coord, piece_y_coord, x_final, y_final):
|
||||
error = False
|
||||
if x_final < 0:
|
||||
print("Illegal move! final x coordinate can't be below 0!")
|
||||
print_move_info(piece_x_coord, piece_y_coord, x_final, y_final)
|
||||
error = True
|
||||
if (x_final > self.board_size):
|
||||
print(f"Illegal move! final x coordinate can't be above board size! board_size: ${self.board_size}")
|
||||
print_move_info(piece_x_coord, piece_y_coord, x_final, y_final)
|
||||
error = True
|
||||
if y_final < 0:
|
||||
print("Illegal move! final y coordinate can't be below 0!")
|
||||
print_move_info(piece_x_coord, piece_y_coord, x_final, y_final)
|
||||
error = True
|
||||
if (y_final > self.board_size):
|
||||
print(f"Illegal move! final y coordinate can't be above board size! board_size: ${self.size}")
|
||||
print_move_info(piece_x_coord, piece_y_coord, x_final, y_final)
|
||||
error = True
|
||||
return error
|
||||
|
||||
def check_spot_taken(self, piece_x_coord, piece_y_coord, x_final, y_final, player_color):
|
||||
error = False
|
||||
if player_color:
|
||||
if (x_final, y_final) in self.white_positions or (x_final, y_final) in self.white_positions:
|
||||
print("Illegal move! can't move into position taken by any other piece")
|
||||
print_move_info(piece_x_coord, piece_y_coord, x_final, y_final)
|
||||
error = True
|
||||
return error
|
||||
|
||||
def check_piece_exists(self, piece_x_coord, piece_y_coord, player_color):
|
||||
error = False
|
||||
if player_color:
|
||||
if not (piece_x_coord, piece_y_coord) in self.white_positions:
|
||||
print("Illegal move! There is no piece on those coordinates or piece does not belong to white player")
|
||||
error = True
|
||||
elif not (piece_x_coord, piece_y_coord) in self.black_positons:
|
||||
print("Illegal move! There is no piece on those coordinates or piece does not belong to black player")
|
||||
error = True
|
||||
return error
|
||||
|
||||
def check_move_diagonally(self, from, to, player_color, king):
|
||||
if not king:
|
||||
if player_color:
|
||||
if to[0] == from[0] - 1 or to[0] == from[0] + 1:
|
||||
if to[1] == from[1] + 1:
|
||||
return False
|
||||
elif x_final == piece_x_coord - 1 or x_final == piece_x_coord + 1:
|
||||
if y_final == piece_y_coord - 1:
|
||||
return False
|
||||
if king:
|
||||
if player_color:
|
||||
if x_final == piece_x_coord - 1 or x_final == piece_x_coord + 1:
|
||||
return False
|
||||
elif x_final == piece_x_coord - 1 or x_final == piece_x_coord + 1:
|
||||
return False
|
||||
return True
|
||||
|
||||
def check_piece_king(self, from, player_color):
|
||||
if player_color == "white":
|
||||
if (from[0], from[1], True) in self.white_positions:
|
||||
return True
|
||||
elif (from[0], from[1], True) in self.black_positions:
|
||||
def check_move_out_of_bounds(self, from_, to):
|
||||
"""Check if the move destination is out of the bounds of the board"""
|
||||
if to[0] < 0 or to[0] >= self.board_size:
|
||||
print(f"Illegal move! Final x coordinate must be between 0 and {self.board_size}!")
|
||||
if to[1] < 0 or to[1] >= self.board_size:
|
||||
print(f"Illegal move! Final y coordinate must be between 0 and {self.board_size}!")
|
||||
return True
|
||||
return False
|
||||
|
||||
# https://stackoverflow.com/a/2191707
|
||||
def check_move_piece_capable(self, from, to, player_color):
|
||||
error = True
|
||||
king = self.check_piece_king(from, player_color)
|
||||
error = self.check_move_diagonally(from, to, player_color, king)
|
||||
return error
|
||||
def check_piece_exists(self, coords, color):
|
||||
"""Check if a piece of given color exists at a given spot"""
|
||||
if color == "white":
|
||||
if (*coords, False) | (*coords, False) in self.white_positions:
|
||||
return True
|
||||
else:
|
||||
if (*coords, False) | (*coords, False) in self.black_positons:
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_capture(self, from, to, player_color):
|
||||
capture = False
|
||||
if player_color == "white":
|
||||
if (to[0] - 1, to[1] - 1) in self.black_positions or (t[0] + 1, to[1] - 1) in self.black_positions
|
||||
capture = True
|
||||
elif (to[0], to[1] - 1) in self.white_positions or (to[0] + 1, t0[1] - 1) in self.white_positions
|
||||
capture = True
|
||||
def check_piece_king(self, coords, color):
|
||||
"""Check if a piece of in a given spot and of a given color is a king. Return false if no piece is found"""
|
||||
if color == "white":
|
||||
return (*coords, True) in self.white_positions
|
||||
else:
|
||||
return (*coords, True) in self.black_positions
|
||||
|
||||
# https://stackoverflow.com/a/2191707
|
||||
def check_move_piece_capable(self, from_, to, color):
|
||||
"""Check if the move is exactly one square diagonally"""
|
||||
if abs(to[0] - from_[0]) == 1:
|
||||
if self.check_piece_king(from_, color):
|
||||
return True
|
||||
else:
|
||||
if color == "white":
|
||||
return to[1] == from_[1] + 1
|
||||
elif color == "black":
|
||||
return to[1] == from_[1] - 1
|
||||
return False
|
||||
|
||||
def check_capture(self, from_, to, color):
|
||||
"""Check if a piece was captured for a given move. Return captured piece coordinates or None"""
|
||||
# captures can only happen if the player moved twice-diagonally
|
||||
if(abs(to[0]-from_[0])!=2 or abs(to[1]-from_[1]!=2)):
|
||||
return None
|
||||
|
||||
middle = (abs(to[0]-from_[0])//2, abs(to[1]-from_[1])//2)
|
||||
|
||||
if color == "white" and self.check_piece_exists(middle, "black"):
|
||||
return middle
|
||||
elif color == "black" and self.check_piece_exists(middle, "white"):
|
||||
return middle
|
||||
return None
|
||||
|
||||
def check_move_legal(self, from_, to, color):
|
||||
"""Check if a move is legal. Return a boolean or coordinates of captured piece"""
|
||||
if self.check_move_out_of_bounds(from_, to):
|
||||
print("Illegal move! Final position is out of the bounds of the board")
|
||||
return False
|
||||
if not self.check_piece_exists(from_, color):
|
||||
print("Illegal move! There is no piece on the starting position that belongs to the player")
|
||||
return False
|
||||
if self.check_piece_exists(to, "white") or check_piece_exists(to, "black"):
|
||||
print("Illegal move! Cannot move to position taken by another piece")
|
||||
return False
|
||||
capture = self.check_capture(from_, to, color)
|
||||
if capture == None:
|
||||
return self.check_move_piece_capable(from_, to, color)
|
||||
return capture
|
||||
|
||||
def check_move_legal(self, from, to, player_color):
|
||||
if self.check_move_out_of_bounds(from, to):
|
||||
return False
|
||||
if self.check_piece_exists(from, to, player_color):
|
||||
return False
|
||||
if self.check_spot_taken(from, to, player_color):
|
||||
return False
|
||||
capture = self.check_capture(from, to, player_color)
|
||||
if not capture:
|
||||
return self.check_move_piece_capable(from, to, player_color):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def make_move(self, from, to, color):
|
||||
def make_move(self, from_, to, color):
|
||||
"""Move a piece on the board and remove any captured pieces"""
|
||||
move_legal = self.check_move_legal(from_, to, color)
|
||||
if move_legal == False:
|
||||
return False
|
||||
capture = move_legal if type(move_legal) is tuple else None
|
||||
king = self.check_piece_king(from_, color)
|
||||
|
||||
if(color == "white"):
|
||||
self.white_pieces.remove(from)
|
||||
self.white_pieces.append(to)
|
||||
self.white_pieces.remove(*from_, king)
|
||||
self.white_pieces.append(*to, king)
|
||||
if(capture):
|
||||
captured_king = self.check_piece_king(capture, "black")
|
||||
self.black_pieces.remove(*move_legal, captured_king)
|
||||
|
||||
else:
|
||||
self.black_pieces.remove(from)
|
||||
self.black_pieces.append(to)
|
||||
if not check_move_legal(piece_x_coord, piece_y_coord, x_final, y_final, player_color):
|
||||
return False
|
||||
self.black_pieces.remove(*from_, king)
|
||||
self.black_pieces.append(*to, king)
|
||||
if(capture):
|
||||
captured_king = self.check_piece_king(capture, "white")
|
||||
self.white_pieces.remove(*move_legal, captured_king)
|
||||
return True
|
||||
|
||||
|
||||
def print_board(self):
|
||||
"""Print the board in the console"""
|
||||
print(" ", end="")
|
||||
for x in range(self.board_size):
|
||||
print(" " + chr(97 + x), end=" ")
|
||||
print(f" {chr(ord('a')+x)} ", end="")
|
||||
print(" ")
|
||||
line = 0
|
||||
for y in range(self.board_size*4):
|
||||
@ -178,23 +163,92 @@ class Game:
|
||||
case 0:
|
||||
print("+---", end="")
|
||||
case 1 | 3:
|
||||
print("|" + 3*bg, end="")
|
||||
print(f"|{3*bg}", end="")
|
||||
case 2:
|
||||
print("|" + bg + checker + bg, end="")
|
||||
print(f"|{bg}{checker}{bg}", end="")
|
||||
if(line%4==0):
|
||||
print("+")
|
||||
else:
|
||||
print("|", end=f"{y//4}\n" if line%4==2 else "\n")
|
||||
print(f"|{y//4}" if line%4==2 else "|")
|
||||
line+=1
|
||||
print(" ", end="")
|
||||
for x in range(self.board_size):
|
||||
print("+---", end="")
|
||||
print("+\n ", end="")
|
||||
for x in range(self.board_size):
|
||||
print(" " + chr(97 + x), end=" ")
|
||||
print(f" {chr(ord('a')+x)}", end=" ")
|
||||
print()
|
||||
|
||||
# Ran first in the code
|
||||
|
||||
def get_possible_moves(color):
|
||||
# toDo: get possible moves for single piece, then iterate through all pieces
|
||||
#if color == "white":
|
||||
# for s
|
||||
pass
|
||||
|
||||
def alpha_beta(self, depth, alpha, beta, player):
|
||||
if depth == 0:
|
||||
return self.evaluate(), None
|
||||
|
||||
if player == 'x':
|
||||
max_eval = float('-inf')
|
||||
best_move = None
|
||||
|
||||
for move in state.get_possible_moves(player):
|
||||
new_state = copy.deepcopy(state)
|
||||
new_state.move(*move)
|
||||
eval, _ = alpha_beta(new_state, depth-1, alpha, beta, 'o')
|
||||
|
||||
if eval > max_eval:
|
||||
max_eval = eval
|
||||
best_move = move
|
||||
|
||||
alpha = max(alpha, eval)
|
||||
|
||||
if alpha >= beta:
|
||||
break
|
||||
|
||||
return max_eval, best_move
|
||||
|
||||
else:
|
||||
min_eval = float('inf')
|
||||
best_move = None
|
||||
|
||||
for move in state.get_possible_moves(player):
|
||||
new_state = copy.deepcopy(state)
|
||||
new_state.move(*move)
|
||||
eval, _ = alpha_beta(new_state, depth-1, alpha, beta, 'x')
|
||||
|
||||
if eval < min_eval:
|
||||
min_eval = eval
|
||||
best_move = move
|
||||
|
||||
beta = min(beta, eval)
|
||||
|
||||
if beta <= alpha:
|
||||
break
|
||||
|
||||
return min_eval, best_move
|
||||
|
||||
def evaluate(self):
|
||||
white_score = 0
|
||||
black_score = 0
|
||||
|
||||
for white_position in self.white_positions:
|
||||
if white_position[2]:
|
||||
white_score += 2
|
||||
else:
|
||||
white_score += 2
|
||||
|
||||
for black_position in self.black_positions:
|
||||
if black_position[2]:
|
||||
black_score += 2
|
||||
else:
|
||||
black_score += 2
|
||||
|
||||
return x_score - o_score
|
||||
|
||||
if __name__ == "__main__":
|
||||
game = Game(8)
|
||||
game.print_board()
|
||||
|
||||
1
lab2/reportLink.txt
Normal file
1
lab2/reportLink.txt
Normal file
@ -0,0 +1 @@
|
||||
https://www.overleaf.com/8592159577skmysmsphtkr
|
||||
Loading…
Reference in New Issue
Block a user