update
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
# Chess-like Game Example - MCTS for Game Playing
|
||||
|
||||
This example demonstrates MCTS for a simplified chess-like game where the goal is to capture the opponent's pieces.
|
||||
|
||||
```julia
|
||||
using LLMMCTS
|
||||
|
||||
# Simple game state
|
||||
# board: Dict mapping positions to pieces
|
||||
# turn: :white or :black
|
||||
struct GameState
|
||||
board::Dict{String, String} # position => piece
|
||||
turn::Symbol
|
||||
piece_count::Int
|
||||
end
|
||||
|
||||
# Initialize a simple board
|
||||
function init_board()
|
||||
board = Dict{String, String}()
|
||||
|
||||
# Place some pieces
|
||||
board["e1"] = "K" # White King
|
||||
board["e8"] = "k" # Black King
|
||||
|
||||
# Random pieces
|
||||
board["d4"] = "P" # White Pawn
|
||||
board["d5"] = "p" # Black Pawn
|
||||
|
||||
return board
|
||||
end
|
||||
|
||||
# Check if position is on board
|
||||
function on_board(pos::String)
|
||||
cols = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
|
||||
rows = ['1', '2', '3', '4', '5', '6', '7', '8']
|
||||
length(pos) == 2 &&
|
||||
pos[1] in cols &&
|
||||
pos[2] in rows
|
||||
end
|
||||
|
||||
# Game transition function
|
||||
function chess_transition(state::Dict, args::NamedTuple)
|
||||
current_step = get(state, :step, 0)
|
||||
board = state[:board]
|
||||
turn = state[:turn]
|
||||
|
||||
if current_step >= args.max_moves
|
||||
# Max moves reached, end game
|
||||
newstate = Dict(
|
||||
:step => current_step + 1,
|
||||
:board => board,
|
||||
:turn => turn,
|
||||
:reward => 0.0,
|
||||
:isterminal => true
|
||||
)
|
||||
return Dict(
|
||||
:newNodeKey => "max_moves",
|
||||
:newstate => newstate,
|
||||
:progressvalue => 5.0
|
||||
)
|
||||
end
|
||||
|
||||
# Generate possible moves
|
||||
possible_moves = String[]
|
||||
|
||||
# Find all pieces of current turn's color
|
||||
turn_prefix = turn == :white ? "upper" : "lower"
|
||||
|
||||
# Simple move generation: try moving each piece
|
||||
for (pos, piece) in board
|
||||
if !isempty(piece)
|
||||
# Try moving to adjacent positions
|
||||
for dx in [-1, 0, 1]
|
||||
for dy in [-1, 0, 1]
|
||||
if dx == 0 && dy == 0
|
||||
continue
|
||||
end
|
||||
|
||||
# Simple coordinate conversion
|
||||
col = pos[1]
|
||||
row = parse(Int, pos[2])
|
||||
|
||||
new_col = col + dx
|
||||
new_row = row + dy
|
||||
|
||||
if new_col >= 'a' && new_col <= 'h' &&
|
||||
new_row >= 1 && new_row <= 8
|
||||
new_pos = string(new_col, new_row)
|
||||
if on_board(new_pos)
|
||||
push!(possible_moves, pos * new_pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if isempty(possible_moves)
|
||||
# No moves available, game over
|
||||
newstate = Dict(
|
||||
:step => current_step + 1,
|
||||
:board => board,
|
||||
:turn => turn,
|
||||
:reward => turn == :white ? 10.0 : -10.0,
|
||||
:isterminal => true
|
||||
)
|
||||
return Dict(
|
||||
:newNodeKey => "game_over",
|
||||
:newstate => newstate,
|
||||
:progressvalue => turn == :white ? 10.0 : 0.0
|
||||
)
|
||||
end
|
||||
|
||||
# LLM would select the best move
|
||||
# For this example, pick a random valid move
|
||||
move_idx = (current_step - 1) % length(possible_moves) + 1
|
||||
move = possible_moves[move_idx]
|
||||
|
||||
# Simulate the move (simplified)
|
||||
from_pos = move[1:2]
|
||||
to_pos = move[3:4]
|
||||
|
||||
new_board = copy(board)
|
||||
piece = get(new_board, from_pos, "")
|
||||
new_board[to_pos] = piece
|
||||
delete!(new_board, from_pos)
|
||||
|
||||
# Calculate reward based on capture
|
||||
reward = 0.0
|
||||
if !isempty(get(new_board, to_pos, ""))
|
||||
reward = 5.0 # Capture!
|
||||
end
|
||||
|
||||
# Progress value: estimate of game state quality
|
||||
progressvalue = 5.0 + reward # Capturing is good
|
||||
|
||||
# Switch turns
|
||||
new_turn = turn == :white ? :black : :white
|
||||
|
||||
newstate = Dict(
|
||||
:step => current_step + 1,
|
||||
:board => new_board,
|
||||
:turn => new_turn,
|
||||
:reward => reward,
|
||||
:isterminal => false
|
||||
)
|
||||
|
||||
return Dict(
|
||||
:newNodeKey => "move_$current_step",
|
||||
:newstate => newstate,
|
||||
:progressvalue => progressvalue
|
||||
)
|
||||
end
|
||||
|
||||
# Initial state
|
||||
initialstate = Dict(
|
||||
:step => 0,
|
||||
:board => init_board(),
|
||||
:turn => :white,
|
||||
:reward => 0,
|
||||
:isterminal => false
|
||||
)
|
||||
|
||||
# Transition arguments
|
||||
transitionargs = (
|
||||
max_moves = 10,
|
||||
)
|
||||
|
||||
# Run MCTS
|
||||
result = runMCTS(
|
||||
initialstate,
|
||||
chess_transition,
|
||||
transitionargs;
|
||||
maxiterations = 30,
|
||||
explorationweight = 2.0, # More exploration for game playing
|
||||
maxSimulationDepth = 4,
|
||||
horizontalSampleExpansionPhase = 5
|
||||
)
|
||||
|
||||
# Display results
|
||||
println("Chess-like Game MCTS")
|
||||
println("====================")
|
||||
println()
|
||||
println("Best move sequence:")
|
||||
println(" Initial board state")
|
||||
println(" → ", result.bestTerminalState[:step], " moves")
|
||||
println()
|
||||
println("Final board has ", length(result.bestTerminalState[:board]), " pieces")
|
||||
println("Root node visits: ", result.root.visits)
|
||||
println("High value states: ", length(result.highValueStateList))
|
||||
```
|
||||
Reference in New Issue
Block a user