<commit_before>open Utils
open Types

type gametree = Gametree of (Types.position * (gametree list Lazy.t))

module PosHash = 
  struct
    type t = gametree
    let hash = function
      | Gametree (pos, _) -> Crc.pos_crc pos
    let equal gt1 gt2 =
      let Gametree (pos1, _) = gt1 in
      let Gametree (pos2, _) = gt2 in
      pos1.to_move = pos2.to_move &&
      pos1.sente_king = pos2.gote_king &&
      pos1.board = pos2.board &&
      begin
        let sh1 = pos1.sente_hand in
        let gh1 = pos1.gote_hand in
        let sh2 = pos2.sente_hand in
        let gh2 = pos2.gote_hand in
        List.length sh1 = List.length sh2 &&
        List.length gh1 = List.length gh2 &&
        sh1 @=@ sh2 && gh1 @=@ gh2
      end
  end

module WeakPosHash = Weak.Make(PosHash)

let global_weak_pos_hash = WeakPosHash.create 100000 (* TODO: 100000 ? *)

let rec create_gametree pos =
  let apply = lazy (Apply_move.apply_move pos) in
  let apply_moves = lazy (create_gametree $ (Lazy.force apply)) in
  let all_moves = lazy (Moves.find_all_moves pos pos.Types.to_move) in
  let possible = lazy (function
    | Gametree (p, _) -> not (Check.under_check p pos.Types.to_move)) in
  let all_branches = lazy (
    List.map
    (Lazy.force apply_moves)
    (Lazy.force all_moves)
  ) in
  let branches = lazy (
    List.filter
    (Lazy.force possible)
    (Lazy.force all_branches)
  ) in
  (* NB: illegal mate by pawn drop should be excluded at position evaluation *)
  Gametree (pos, branches)
(*
 * vim:sw=2
 *)
<commit_msg>Weak hash table in use<commit_after>open Utils
open Types

(* This is a state of the art code! It uses lazy evaluation, and recursive
 * types, and weak hash table! :-) *)

(* Gametree consists of the root position, and the lazy list of gametrees with
 * roots in positions arising after all possible moves. When a child gametree is
 * instantiated (by Lazy.force-ing the list of gametrees) its existance in
 * checked in the global weak hash table. If it's not there, it's added there.
 * If it's there, we take gametree from hash table instead. The benefit is that
 * the same root position in different places of the starting tree will give us
 * the same (phisically) object as a gametree, so after the position is
 * evaluated somewhere in a tree (forcing child branches as deep as needed), in
 * all other places it's available as already evaluated *)

type gametree = Gametree of (Types.position * (gametree list Lazy.t))

module PosHash = 
  struct
    type t = gametree
    let hash = function
      | Gametree (pos, _) -> Crc.pos_crc pos
    let equal gt1 gt2 =
      let Gametree (pos1, _) = gt1 in
      let Gametree (pos2, _) = gt2 in
      pos1.to_move = pos2.to_move &&
      pos1.sente_king = pos2.sente_king &&
      pos1.gote_king = pos2.gote_king &&
      pos1.board = pos2.board &&
      begin
        let sh1 = pos1.sente_hand in
        let gh1 = pos1.gote_hand in
        let sh2 = pos2.sente_hand in
        let gh2 = pos2.gote_hand in
        List.length sh1 = List.length sh2 &&
        List.length gh1 = List.length gh2 &&
        sh1 @=@ sh2 && gh1 @=@ gh2
      end
  end

module WeakPosHash = Weak.Make(PosHash)

let global_weak_pos_hash = WeakPosHash.create 100000 (* TODO: 100000 ? *)

let rec create_gametree pos =
  let apply = lazy (Apply_move.apply_move pos) in
  let apply_moves = lazy (create_gametree $ (Lazy.force apply)) in
  let all_moves = lazy (Moves.find_all_moves pos pos.Types.to_move) in
  let possible = lazy (function
    | Gametree (p, _) -> not (Check.under_check p pos.Types.to_move)) in
  let all_branches = lazy (
    List.map
    (Lazy.force apply_moves)
    (Lazy.force all_moves)
  ) in
  let branches = lazy (
    List.filter
    (Lazy.force possible)
    (Lazy.force all_branches)
  ) in
  (* NB: illegal mate by pawn drop should be excluded at position evaluation *)
  let gt_tmp = Gametree (pos, branches) in
(*
  let _ =
   try
     let _ = WeakPosHash.find global_weak_pos_hash gt_tmp in
     print_string "HIT "
   with Not_found  -> () in
*)
   WeakPosHash.merge global_weak_pos_hash gt_tmp
(*
 * vim:sw=2
 *)

{'fraction_non_alphanumeric': 0.0890461088070261, 'fraction_numerical': 0.020492803122712858, 'mean_word_length': 2.824626865671642, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2697552', 'n_tokens_mistral': 1485, 'n_tokens_neox': 1424, 'n_words': 462}