type card = | I | Zero | Succ | Dbl | Get | Put | S | K | Inc | Dec | Attack | Help | Copy | Revive | Zombie ;; let card_of_string s = match s with | "I" -> I | "zero" -> Zero | "Succ" -> Succ | "dbl" -> Dbl | "get" -> Get | "put" -> Put | "S" -> S | "K" -> K | "inc" -> Inc | "dec" -> Dec | "attack" -> Attack | "help" -> Help | "copy" -> Copy | "revive" -> Revive | "zombie" -> Zombie ;; type slot = { mutable vitality: int; mutable field: lambda } ;; let left_apply card slot = match card with | S -> slot.field <- s @ slot.field let proponent = Array.init 256 (fun _ -> {vitality = 10000; field = id}) let opponent = Array.init 256 (fun _ -> {vitality = 10000; field = id}) type 'a lambda = Lambda of ('a -> 'a) let unfold (Lambda x) = x let (@) a1 a2 = unfold a1 a2;; let s = Lambda(fun f -> Lambda(fun g -> Lambda(fun Lambda(x) -> (f @ x) @ (g @ x)))) type lambda = |Const of int |Lambda of (lambda -> lambda);; let out (Lambda x) = x let (!) x = Lambda x let (@) a1 a2 = out a1 a2 let id = !(fun x -> x) let zero = Const 0 let succ (Const n) = if n < 65535 then Const (n+1) else Const n let dbl (Const n) = if n<32768 then Const(2*n) else Const n let get (Const i) = if player1.(i).vitality > 0 then player1.(i).field else failwith "dead" let put = !(fun x -> id) let s = !(fun f -> !(fun g -> !(fun x -> (f @ x) @ (g @ x)))) let k = !(fun x -> Lambda(fun y -> y)) let inc (Const i) = let v = proponent.(i).vitality in if ( v < 65535 ) & ( v > 0 ) then proponent.(i).vitality <- proponent.(i).vitality + 1; id let dec (Const i) = let v = opponent.(255-i).vitality in if v>0 then opponent.(255-1).vitality <-opponent.(255-1).vitality-1; id let attack (Const i) (Const j) (Const n) = let v = proponent.(i).vitality in if v - n > 0 then proponent.(i).vitality <- proponent.(i).vitality - n else failwith "not enough life"; let w = opponent.(j).vitality in if w>0 then proponent.(j).vitality <- max(0, , let help (Const i) (Const j) (Const n) = let v = proponent.(i).vitality in if v - n > 0 then proponent.(i).vitality <- proponent.(i).vitality - n else failwith "not enough life"; let w = proponent.(j).vitality in if w>0 then proponent.(j).vitality <- min (w + n*11/10) 65535; id let copy (Const i) = opponent.(i).field let revive (Const i) = let v = proponent.(i).vitality in if v <= 0 then proponent.(i).vitality <- 1; id