Raw File
isklife.ml
(* the life game : skeleton version *)
(* 
   two neighbours alive => stay
   three neighbours alive => alive
   else => dead
*)

open Graphics;;

let n = 100;; (* the board is n by n, mesh toroidal *)

let init_board () =
  let board = Array.create_matrix n n 0 in
  for i = 0 to (n-1) do
    for j = 0 to (n-1) do 
      if ((Random.int 10) < 3) 
      then Array.set board.(i) j blue
      else Array.set board.(i) j white
    done
  done;
  board;;

let dist i j radius = 
  let c = n/2 in
  let di = (i-c)*(i-c) in
  let dj = (j-c)*(j-c) in
  if((di+dj)<(radius*radius)) then true else false;;

let c_init_board radius =
  let board = Array.create_matrix n n 0 in
  for i = 0 to (n-1) do
    for j = 0 to (n-1) do 
      if (dist i j radius)
      then
      	(if ((Random.int 10) < 2) 
      	then Array.set board.(i) j red
      	else Array.set board.(i) j white)
      else
	Array.set board.(i) j white
    done
  done;
  board;;

let first_display = ref true;;

let display board =
  if(!first_display) 
  then (open_graph (" "^(string_of_int n)^"x"^(string_of_int n));
	first_display := false);
  draw_image (make_image board) 0 0 ;;


let display_tasks t = 
  for i = 0 to (Array.length t-1) do
    begin
      clear_graph();
      display t.(i);
      Unix.sleep 3;
    end
  done;;

let init_board_user () = 
  let board = Array.create_matrix n n white in
  let fine = ref false in
  begin
    open_graph (" "^(string_of_int (n))^"x"^(string_of_int (n)));
    display board;
    while(not !fine) do
      let stat = wait_next_event [Button_down;Key_pressed] in
      if(stat.keypressed) then fine:=true
      else 
	begin
	  let i = stat.mouse_x  in
	  let j = stat.mouse_y  in
	  begin
	    Array.set board.(i) (j) blue;
	    clear_graph();
	    display board
	  end
	end
    done;
    close_graph();
    board
  end;;

let alive_stencil stencil = 
  let sum = ref 0 in
  let res = ref 0 in
  for i = 0 to 2 do
    for j = 0 to 2 do
      sum := !sum + (if(stencil.(i).(j) = white) then 0 else 1)
    done
  done;
  sum := !sum - (if (stencil.(1).(1) = white) then 0 else 1);
  if(!sum = 2) then res:= (if(stencil.(1).(1) = white) then 0 else 1);
  if(!sum = 3) then res:= 1;
  if(!res = 0) then white else blue
;;

let make_stencil m ii jj = 
  let s = Array.create_matrix 3 3 white in
  for i = 0 to 2 do
    for j = 0 to 2 do
      Array.set s.(i) (j)  m.((i+ii-1+n) mod n).((j+jj-1+n) mod n)
    done
  done;
  s
;;

let lifestep_stencil m = 
  let mm = Array.create_matrix n n white in
  for i = 0 to (n-1) do
    for j = 0 to (n-1) do
      Array.set mm.(i) j (alive_stencil (make_stencil m i j))
    done
  done;
  mm
;;


(* prepare the matrix of stencils :
   out of a matrix which is n x n
   take out k matrixes which are (n/k + 2) x n 
 *)

exception NotDivisible;;

(* get k+2 rows from m starting at ii-1 *)
let k_rows_from m ii k = 
  let res = Array.create (k+2) m.(0) in
  for i = 0 to (k+1) do
    Array.set res i m.((ii+i-1+n) mod n)
  done;
  res;;

(* prepares a vector of k slices of m (each slice has stencil rows) *)
let prepare_tasks k m  = 
  if (not ((n mod k) = 0)) then raise NotDivisible
  else
    let res = Array.create k (k_rows_from m 0 (n/k)) in
    begin
      for kk = 0 to (k-1) do
      	Array.set res kk (k_rows_from m (kk*(n/k)) (n/k))
      done;
      res
    end;;
    
(* compute a slice of the result *)
let compute_slice _ slice = 
  let k = Array.length slice - 2 in
  let res = Array.create_matrix k n red in
  for i = 0 to (k-1) do
    for j = 0 to (n-1) do
      Array.set res.(i) j (alive_stencil (make_stencil slice (i+1) j))
    done
  done;
  res
;;

let merge_slices _ slices = 
  let k = Array.length slices in
  let m = Array.length slices.(0) in
  let res = Array.create n slices.(0).(0) in
  for i = 0 to (n-1) do
    Array.set res i (slices.(i/m).(i mod m))
  done;
  res;;

let display_and_pass _ m = 
  display m; m;;

(* ok this generates a stream of random boards ... *)
let stream_generate nitems = 
  let n = ref nitems in
  (function _ -> 
    if(!n = 0)
    then raise End_of_file
    else (n:=!n-1;c_init_board 30));;

(* this the thing showing the successive steps of the board at intermediate 
   nodes ... 
let lifestep =
   (seq(fun _ ->(prepare_tasks 2))
   ||| mapvector(seq(compute_slice),5)
   ||| seq((merge_slices))
   ||| seq(display_and_pass) );;
*)

(* let's have the real one : for each board in the stream, compute 10 
   iterations then deliver the resulting board *)
let lifestep = parfun (fun () -> (seq(fun _ -> (prepare_tasks 2)) ||| mapvector(seq(compute_slice),5) ||| 
                seq((merge_slices))));;

let open_graphics () = 
  open_graph (" "^(string_of_int (n))^"x"^(string_of_int (n)));;

(* the game of life with the skeletons *)

pardo (fun () ->
       open_graphics();
       let init = P3lstream.of_fun (stream_generate 5) in
       let rec loop s =
	 function
	     0 -> ()
	   | n -> let s' = lifestep s
	          in List.iter display (P3lstream.to_list s'); loop s' (n-1)
       in loop init 4
)

back to top