4 (* ------------------------------------------------------------------------- *
6 * ------------------------------------------------------------------------- *)
7 let f = 0.01 (* Probability of spontaneous ignition *)
8 let p = 1.0 (* Probability of spontaneous growth *)
15 let char_burning = '#'
17 let ansi_color_tree = "\027[0;32m" (* Green *)
18 let ansi_color_burning = "\027[1;31m" (* Red *)
19 let ansi_color_off = "\027[0m"
21 let ansi_code_clear = "\027[2J" (* Clear screen *)
22 let ansi_code_reset = "\027[1;1H" (* Reset cursor position *)
25 (* ------------------------------------------------------------------------- *
27 * ------------------------------------------------------------------------- *)
29 | Empty | Tree | Burning
33 | N | NE | E | SE | S | SW | W | NW
41 (* ------------------------------------------------------------------------- *
43 * ------------------------------------------------------------------------- *)
45 (* Hack to sleep less than 1 sec *)
46 let minisleep subsec =
47 ignore (Unix.select [] [] [] subsec)
51 print_string ansi_code_clear
55 print_string ansi_code_reset
62 and y = ref default_y in
64 let speclist = Arg.align [
65 ("-x", Arg.Set_int x, " X.");
66 ("-y", Arg.Set_int y, " Y.");
69 Arg.parse speclist (fun _ -> ()) usage;
75 (* ------------------------------------------------------------------------- *
77 * ------------------------------------------------------------------------- *)
79 [N; NE; E; SE; S; SW; W; NW]
82 let offset_of_direction = function
83 (* Direction -> x, y *)
95 List.map (offset_of_direction) directions
98 let is_probable = function
99 | probability when (Random.float 1.0) <= probability -> true
103 let init_cell_state = function
104 | () when is_probable p -> Tree
108 let init_forest (x, y) =
109 Array.map (Array.map (init_cell_state)) (Array.make_matrix y x ())
112 let string_of_state = function
113 | Empty -> sprintf "%c" char_empty
114 | Tree -> sprintf "%s%c%s" ansi_color_tree char_tree ansi_color_off
115 | Burning -> sprintf "%s%c%s" ansi_color_burning char_burning ansi_color_off
118 let new_state = function
119 | Burning, _ -> Empty
120 | Tree, 0 when is_probable f -> Burning
121 | Tree, neighbors_burning when neighbors_burning > 0 -> Burning
122 | Empty, _ when is_probable p -> Tree
126 let print_forest forest =
133 print_string (string_of_state state)
141 let is_onside width height (x, y) =
142 x >= 0 && y >= 0 && x < width && y < height
145 let next_generation forest (width, height) =
152 let neighbors = List.map (fun (ox, oy) -> ox + ix, oy + iy) offsets in
153 let neighbors = List.filter (is_onside width height) neighbors in
154 let neighbor_states = List.map (fun (x, y) -> forest.(y).(x)) neighbors in
155 let burning_states = List.filter (fun s -> s == Burning) neighbor_states in
156 new_state (state, (List.length burning_states))
163 let rec burn forest size =
167 burn (next_generation forest size) size
173 let opts = get_opts argv in
174 let forest = init_forest opts.size in
177 burn forest opts.size
180 let () = main Sys.argv