mirror of
https://github.com/epasveer/seer.git
synced 2026-08-29 16:40:42 +08:00
161 lines
6.2 KiB
Fortran
161 lines
6.2 KiB
Fortran
|
|
! ============================================
|
|
! Main Program: Human vs Computer
|
|
! ============================================
|
|
PROGRAM Fortran_Chess
|
|
USE Chess_Types
|
|
USE Board_Utils
|
|
USE Move_Generation ! Needs Make_Unmake implicitly
|
|
USE Make_Unmake
|
|
USE Search
|
|
IMPLICIT NONE
|
|
|
|
TYPE(Board_Type) :: game_board
|
|
TYPE(Move_Type) :: chosen_move
|
|
TYPE(UnmakeInfo_Type) :: move_info ! Needed for make_move call
|
|
LOGICAL :: move_found, is_human_turn, game_over, is_checkmate_flag, is_stalemate_flag
|
|
INTEGER :: human_player_color, ai_player_color, winner
|
|
INTEGER :: search_depth
|
|
CHARACTER(LEN=10) :: user_input
|
|
CHARACTER(LEN=1) :: from_f_char, from_r_char, to_f_char, to_r_char, promo_char
|
|
TYPE(Square_Type) :: parsed_from_sq, parsed_to_sq
|
|
INTEGER :: parsed_promo_piece
|
|
TYPE(Move_Type), DIMENSION(MAX_MOVES) :: legal_moves
|
|
INTEGER :: num_legal_moves, i
|
|
|
|
search_depth = 4 ! AI Difficulty
|
|
|
|
! --- Player Color Selection ---
|
|
DO
|
|
PRINT *, "Choose your color (White/Black): "
|
|
READ *, user_input
|
|
SELECT CASE (TRIM(ADJUSTL(user_input))) ! Basic input handling
|
|
CASE ('White', 'white', 'W', 'w')
|
|
human_player_color = WHITE
|
|
ai_player_color = BLACK
|
|
PRINT *, "You play as White."
|
|
EXIT
|
|
CASE ('Black', 'black', 'B', 'b')
|
|
human_player_color = BLACK
|
|
ai_player_color = WHITE
|
|
PRINT *, "You play as Black."
|
|
EXIT
|
|
CASE DEFAULT
|
|
PRINT *, "Invalid input. Please enter 'White' or 'Black'."
|
|
END SELECT
|
|
END DO
|
|
|
|
! --- Initialize and Print Board ---
|
|
CALL init_board(game_board)
|
|
CALL print_board(game_board)
|
|
|
|
! --- Game Loop ---
|
|
game_over = .FALSE.
|
|
DO WHILE (.NOT. game_over)
|
|
|
|
! 1. Check Game Over
|
|
! Need a way to check checkmate/stalemate without modifying board state here,
|
|
! or accept that generate_moves modifies it temporarily.
|
|
CALL generate_moves(game_board, legal_moves, num_legal_moves)
|
|
IF (num_legal_moves == 0) THEN
|
|
IF (is_in_check(game_board, game_board%current_player)) THEN
|
|
winner = get_opponent_color(game_board%current_player)
|
|
IF (winner == WHITE) THEN
|
|
PRINT *, "=== CHECKMATE! White wins! ==="
|
|
ELSE
|
|
PRINT *, "=== CHECKMATE! Black wins! ==="
|
|
END IF
|
|
ELSE
|
|
PRINT *, "=== STALEMATE! Draw. ==="
|
|
END IF
|
|
game_over = .TRUE.
|
|
EXIT ! Exit game loop
|
|
END IF
|
|
|
|
! 2. Determine Turn
|
|
is_human_turn = (game_board%current_player == human_player_color)
|
|
|
|
IF (is_human_turn) THEN
|
|
! --- Human's Turn ---
|
|
PRINT *, " " ! Newline
|
|
PRINT *, "Your turn. Enter move (e.g., e2e4, e7e8q): "
|
|
move_found = .FALSE.
|
|
DO WHILE (.NOT. move_found)
|
|
READ *, user_input
|
|
IF (TRIM(ADJUSTL(user_input)) == 'quit' .OR. TRIM(ADJUSTL(user_input)) == 'exit') THEN
|
|
PRINT *, "Exiting game."
|
|
game_over = .TRUE.
|
|
EXIT ! Exit inner loop
|
|
END IF
|
|
|
|
! Basic Parsing (Needs Error Handling!)
|
|
IF (LEN_TRIM(user_input) >= 4) THEN
|
|
from_f_char = user_input(1:1); from_r_char = user_input(2:2)
|
|
to_f_char = user_input(3:3); to_r_char = user_input(4:4)
|
|
parsed_from_sq%file = char_to_file(from_f_char)
|
|
parsed_from_sq%rank = char_to_rank(from_r_char)
|
|
parsed_to_sq%file = char_to_file(to_f_char)
|
|
parsed_to_sq%rank = char_to_rank(to_r_char)
|
|
|
|
parsed_promo_piece = NO_PIECE
|
|
IF (LEN_TRIM(user_input) == 5) THEN
|
|
promo_char = user_input(5:5)
|
|
SELECT CASE(promo_char)
|
|
CASE('q'); parsed_promo_piece = QUEEN
|
|
CASE('r'); parsed_promo_piece = ROOK
|
|
CASE('b'); parsed_promo_piece = BISHOP
|
|
CASE('n'); parsed_promo_piece = KNIGHT
|
|
END SELECT
|
|
END IF
|
|
|
|
! Find the move in the legal list
|
|
DO i = 1, num_legal_moves
|
|
IF (legal_moves(i)%from_sq%rank == parsed_from_sq%rank .AND. &
|
|
legal_moves(i)%from_sq%file == parsed_from_sq%file .AND. &
|
|
legal_moves(i)%to_sq%rank == parsed_to_sq%rank .AND. &
|
|
legal_moves(i)%to_sq%file == parsed_to_sq%file .AND. &
|
|
legal_moves(i)%promotion_piece == parsed_promo_piece) THEN
|
|
chosen_move = legal_moves(i)
|
|
move_found = .TRUE.
|
|
EXIT ! Exit move finding loop
|
|
END IF
|
|
END DO
|
|
END IF
|
|
|
|
IF (.NOT. move_found .AND. .NOT. game_over) THEN
|
|
PRINT *, "Invalid or illegal move. Try again:"
|
|
END IF
|
|
END DO ! End move input loop
|
|
|
|
IF (game_over) EXIT ! Exit game loop if user quit
|
|
|
|
! Make human move
|
|
PRINT *, "You moved." ! Add more detail later
|
|
CALL make_move(game_board, chosen_move, move_info)
|
|
|
|
ELSE
|
|
! --- AI's Turn ---
|
|
PRINT *, " " ! Newline
|
|
PRINT *, "Computer's turn. Thinking..."
|
|
CALL find_best_move(game_board, search_depth, move_found, chosen_move)
|
|
IF (move_found) THEN
|
|
PRINT *, "Computer moved." ! Add move details later
|
|
CALL make_move(game_board, chosen_move, move_info)
|
|
ELSE
|
|
! Should be caught by game over check, but safety print
|
|
PRINT *, "Error: AI found no move but game not over?"
|
|
game_over = .TRUE.
|
|
END IF
|
|
END IF
|
|
|
|
! Print board after move (if game not over)
|
|
IF (.NOT. game_over) THEN
|
|
CALL print_board(game_board)
|
|
END IF
|
|
|
|
END DO ! End game loop
|
|
|
|
PRINT *, "Game finished."
|
|
|
|
END PROGRAM Fortran_Chess
|