open Unix open Protocol let ( |> ) x f = f x (* Description of data structures *) exception Eliminated_ex of string type player = P1 | P2 let other_player = function P1 -> P2 | P2 -> P1 type game_status = | TurnOf of player | Won of player | Tie | Eliminated of player type player_proc_status = | Loading | StandBy of float (* temps restant sur toute la partie *) | Thinking of (float * float) (* temps restant ; heure de début de réflexion *) | Saving | Dead module type GAME = sig type game (* immutable structure *) val name : string (* ex: Morpion récursif *) val id : string (* ex: morpion_rec *) val new_game : game val play : game -> string -> game val s : game -> game_status val display_game : game -> (string * string) -> unit val gui_act_at : game -> (int * int) -> string end module type CORE = sig module G : GAME type game val p1 : game -> player_proc_status val p2 : game -> player_proc_status val pn : game -> string * string val s : game -> game_status val g : game -> G.game val hist : game -> G.game list (* head: same as g g *) val init : unit -> unit val finish : unit -> unit val handle_events : unit -> bool (* is anything happening ? *) val add_rounds : unit -> unit (* adds one game of everyone against everyone *) val ql : unit -> int val scores : unit -> (string * int) list val games : unit -> game list end (* ****************************************** *) (* BEGIN IMPLEMENTATION *) (* ****************************************** *) module Core (G: GAME) : CORE = struct module G : GAME = G type player = { name: string; binary: string; dir: string; log_out: file_descr; mutable score: int; mutable running: player_proc option; } and player_proc = { pid: int; cfd: file_descr list; p: player; i: in_channel; o: out_channel; mutable s: player_proc_status; } type game = { mutable hist: G.game list; p1: player_proc; p2: player_proc; mutable s: game_status; } let p1 g = g.p1.s let p2 g = g.p2.s let pn g = (g.p1.p.name, g.p2.p.name) let s g = g.s let g g = List.hd g.hist let hist g = g.hist let players = Hashtbl.create 12 let planned_games = ref [] let r_games = ref [] let ql () = List.length !planned_games (* program paremeters *) let par_games = ref 2 (* default: launch two simultaneous games *) let game_time = ref 30.0 (* default: 30 sec for each player *) let pt_win = ref 3 (* default: on win, score += 3 *) let pt_tie = ref 1 (* default: on tie, score += 1 *) let pt_lose = ref 0 (* default: on lose, score does not change *) let pt_elim = ref (-1) (* default: on eliminated, score -= 1 *) let log_games = ref false (* default: do not log games *) let scores () = Hashtbl.fold (fun _ p l -> (p.name, p.score)::l) players [] let games () = !r_games let init () = (* 1. PARSE ARGUMENTS *) let game_dir = ref "." in let args = [ "-p", Arg.Set_int par_games, "How many games to run in parallel (2)"; "-s", Arg.Set_float game_time, "Time (seconds) allotted to each player for a game (30)"; "-w", Arg.Set_int pt_win, "Points granted on win (+3)"; "-t", Arg.Set_int pt_tie, "Points granted on tie (+1)"; "-l", Arg.Set_int pt_lose, "Points granted on lose (0)"; "-e", Arg.Set_int pt_elim, "Points granted on eliminated (-1)"; "-v", Arg.Set log_games, "Log all games (false)"; ] in Arg.parse args (fun s -> game_dir := s) "Usage: judge [