Source

ocaml-minigames / mills / ai_hybrid.ml

open Mill
open Ai_alphabeta
open Lazy

let find_best_moves state lastmove depth =
  let root = Ai_alphabeta.build state lastmove depth in
  let children = match force root with Node (_, _, c) -> c in
  let scores = List.map (score estimate) children in
  let better = if (get_turn state) mod 2 = 0 then (<=) else (>=) in
  let init = if (get_turn state) mod 2 = 0 then max_int else min_int in
  let rec select nodes scores selected score =
    if nodes = [] then selected
    else
      let n, s = (List.hd nodes), (List.hd scores) in
      if better s score then select (List.tl nodes) (List.tl scores) (n:: selected) s
      else select (List.tl nodes) (List.tl scores) selected score
  in
  select children scores [] init

let find_best state selection scores =
  let better = if (get_turn state) mod 2 = 0 then (<) else (>) in
  let rec select nodes scores selected score =
    if nodes = [] then selected
    else
      let n, s = (List.hd nodes), (List.hd scores) in
      if better s score then select (List.tl nodes) (List.tl scores) n s
      else select (List.tl nodes) (List.tl scores) selected score
  in
  let thunk = select selection scores (List.hd selection) (List.hd scores) in
  force thunk

let player =
  let playouts = 50000 in
  let turns = 20 in
  object (self)
    val mutable last_move = Init
    
    method put state =
      let moves = find_best_moves state Init 4 in
      let nplayouts = playouts / (List.length moves) in
      let montecarlo selection =
        let s = copy state in
        match force selection with
        | Node(_, Put i, _) -> put s i; Ai_montecarlo.estimate s 0 nplayouts turns
        | _ -> 0
      in
      let scores = List.map montecarlo moves in
      match find_best state moves scores with
      | Node(_, Put i, _) -> last_move <- Put i ; i
      | _ -> failwith "no put found"
    method move state =
      let moves = find_best_moves state Init 4 in      
      let nplayouts = playouts / (List.length moves) in
      let montecarlo selection =
        let s = copy state in
        match force selection with
        | Node(_, Move (f, g), _) -> move s f g; Ai_montecarlo.estimate s 0 nplayouts turns
        | _ -> 0
      in
      let scores = List.map montecarlo moves in
      match find_best state moves scores with
      | Node(_, Move (f, g), _) -> last_move <- Move (f, g) ; f, g
      | _ -> failwith "no move found"
    method fly state =
      let moves = find_best_moves state Init 4 in
      let nplayouts = playouts / (List.length moves) in      
      let montecarlo selection =
        let s = copy state in
        match force selection with
        | Node(_, Fly (f, g), _) -> fly s f g; Ai_montecarlo.estimate s 0 nplayouts turns
        | _ -> 0
      in
      let scores = List.map montecarlo moves in
      match find_best state moves scores with
      | Node(_, Fly (f, g), _) -> last_move <- Fly (f, g) ; f, g
      | _ -> failwith "no fly found"
    method capture state =
      end_of_turn state; (* unrolled later *)
      let moves = find_best_moves state Init 4 in
      let nplayouts = playouts / (List.length moves) in      
      let montecarlo selection =
        let s = copy state in
        match force selection with
        | Node(_, Capture i, _) -> capture s i; Ai_montecarlo.estimate s 0 nplayouts turns
        | _ -> 0
      in
      let scores = List.map montecarlo moves in
      match find_best state moves scores with
      | Node(_, Capture i, _) -> last_move <- Capture i ; i
      | _ -> failwith "no capture found"
  end
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.