* License: BSD New, see LICENSE for details.

-type t = elt array array

+type t = Grid.t * count * score

+let init x y = Grid.init x y, 0, 0

-(* Note: matrix created by make_matrix is transposed, that's why y, x here *)

-let init x y = Array.make_matrix y x empty

-let get x y board = board.(y).(x)

-let set x y e board = board.(y).(x) <- e; board

-let size board = Array.length board.(0), Array.length board

+let move_and_score move (grid, count, score) =

+ let sum = List.fold_left (+) 0 in

+ let grid', removed = move grid in

+ let score' = List.flatten removed |> sum in

+ let is_changed = score' <> 0 || grid' <> grid in

+ grid', (if is_changed then succ count else count), score + score'

- |> Array.map Array.to_list

+let move_left = move_and_score Grid.move_left

+let move_right = move_and_score Grid.move_right

+let move_up = move_and_score Grid.move_up

+let move_down = move_and_score Grid.move_down

-let has_empty_cell = contains empty

-let empty_cells_to_index =

- Array.mapi (fun x cell ->

- if cell = empty then Some (x, y) else None))

- let rec loop acc = function

- | None :: tl -> loop acc tl

- | Some e :: tl -> loop (e :: acc) tl

- |> empty_cells_to_index

-let rec merge = function

- | x :: y :: t when x = y -> x + y :: merge t

- | h :: t -> h :: merge t

-let remove_empty = List.filter ((<>) empty)

-let take n row = Array.sub row 0 n

- let orig_len = Array.length row in

- let padding = Array.make orig_len empty in

- let add_padding = fun row -> Array.append row padding in

- let reverse r = r |> Array.to_list |> List.rev |> Array.of_list in

- row |> reverse |> merge_left |> reverse

- let dim_x, dim_y = size board in

- let board' = init dim_y dim_x in

- for x = 0 to pred dim_x do

- for y = 0 to pred dim_y do

- set y x (get x y board) board' |> ignore

-let move_left = Array.map merge_left

-let move_right = Array.map merge_right

- board |> transpose |> move_left |> transpose

- board |> transpose |> move_right |> transpose

-let move_available board =

- has_empty_cell board ||

- move_up board <> board ||

- move_down board <> board ||

- move_left board <> board ||

- move_right board <> board

+let spawn (grid, count, score) =

+ let empty_cells = Grid.empty_cells grid in

+ let num_of_empty_cells = List.length empty_cells in

+ if num_of_empty_cells <> 0 then

+ let n = Random.int num_of_empty_cells in

+ let x, y = List.nth empty_cells n in

+ let num = if (Random.int 10 = 0) then 4 else 2 in

+ (Grid.set x y num grid, count, score)