open Core open Graphics open Unix open Protocol module A (G : GAME) : sig val run : unit -> unit end = struct exception Unexpected of msg open G_util (* Init/Close *) let gui_init () = open_graph " 800x600"; set_font "-misc-fixed-bold-r-normal--15-120-90--c-90-iso8859-1"; auto_synchronize false; display_mode false; remember_mode true; fullscreen_msg "Starting up..." let gui_close () = close_graph () (* The functions *) let dg t g pnx = clear_graph(); text3 1 black t; hl(); G.display_game g pnx; synchronize() let display_result r (p1n, p2n) = let s = match r with | Won P1 -> p1n ^ " won" | Won P2 -> p2n ^ " won" | Tie -> "Tie" | Eliminated P1 -> p1n ^ " eliminated" | Eliminated P2 -> p2n ^ " eliminated" | _ -> assert false in fullscreen_msg (s ^ ". Press a key to exit."); ignore @@ read_key() let fwd ff g (send, recv) (p1n, p2n) = match G.s g with | TurnOf _ -> ff g (send, recv) (p1n, p2n) | s -> display_result s (p1n, p2n); send (match s with | Tie -> Tie | Won P1 when p1n = "AI" -> YouWin | Won P2 when p2n = "AI" -> YouWin | Won _ -> YouLose | _ -> Eliminated); match (recv ()) with | FairEnough -> () | x -> raise (Unexpected x) let rec human_turn g (send, recv) pnx = dg "Your turn !" g pnx; let rec x pmc = let st = wait_next_event [Button_down; Button_up; Mouse_motion; Key_pressed] in let act = G.gui_act_at g (st.mouse_x, st.mouse_y) in let g', ok = try G.play g act, true with _ -> g, false in let ok = ok && (match G.s g' with Eliminated _ -> false | _ -> true) in dg "Your turn !" (if ok then g' else g) pnx; if st.keypressed && st.key = 'q' then begin send (YouWin); fullscreen_msg "You abandon! Coward!" end else if pmc && not st.button && ok then begin send (Play act); fwd ai_turn g' (send, recv) pnx end else x st.button in x false and ai_turn g (send, recv) pnx = dg "AI's turn..." g pnx; send (YourTurn 30.0); match recv() with | Play x -> let g' = G.play g x in send OK; fwd human_turn g' (send, recv) pnx | x -> raise (Unexpected x) (* Arg parsing && Initialization *) let human_begin = ref false let start_proc player_dir = let b = Filename.concat player_dir "player" in let st = Unix.stat b in if not ((st.st_kind = S_REG || st.st_kind = S_LNK) && (st.st_perm land 0o100 <> 0)) then begin Format.eprintf "Could not find player binary in %s@." player_dir; exit 1 end; let (ff_i, o) = pipe () in let (i, ff_o) = pipe () in let pid = fork() in if pid = 0 then begin chdir player_dir; dup2 ff_i stdin; dup2 ff_o stdout; execvp b [| b |]; end; Format.eprintf "Started IA process, pid %d@." pid; i, o, pid let run () = let player_dir = ref "." in let args = [ "-h", Arg.Set human_begin, "Human begins (default: AI begins"; ] in Arg.parse args (fun s -> player_dir := s) "Usage: xx_guiplay [