implement wheat !

This commit is contained in:
pena 2023-01-15 02:23:14 +01:00 committed by Swrup
parent 8e2faf3b21
commit d90aa54bcf
4 changed files with 98 additions and 15 deletions

View file

@ -17,7 +17,11 @@ let get request =
let topbar = let topbar =
let mana_img = mk_img false "mana" in let mana_img = mk_img false "mana" in
let mana_lvl = span ~a:[ a_id "mana_lvl" ] [ txt "0" ] in let mana_lvl = span ~a:[ a_id "mana_lvl" ] [ txt "0" ] in
div ~a:[ a_class [ "centered" ] ] [ mana_img; mana_lvl ] let wheat_img = mk_img false "wheat" in
let wheat_lvl = span ~a:[ a_id "wheat_lvl" ] [ txt "0" ] in
div
~a:[ a_class [ "centered" ] ]
[ mana_img; mana_lvl; wheat_img; wheat_lvl ]
in in
let canvas = let canvas =
@ -32,14 +36,24 @@ let get request =
let canvas_images = let canvas_images =
div div
@@ List.map (mk_img true) @@ List.map (mk_img true)
[ "grass"; "papy_left"; "papy_right"; "papy_down"; "papy_up"; "water" ] [ "grass"
; "papy_left"
; "papy_right"
; "papy_down"
; "papy_up"
; "water"
; "wheat"
]
in in
let bottombar = let bottombar =
let medidate_button = let medidate_button =
button ~a:[ a_id "medidate_button" ] [ txt "Medidate" ] button ~a:[ a_id "medidate_button" ] [ txt "Medidate" ]
in in
div ~a:[ a_class [ "centered" ] ] [ medidate_button ] let plant_wheat_button =
button ~a:[ a_id "plant_wheat_button" ] [ txt "Plant wheat" ]
in
div ~a:[ a_class [ "centered" ] ] [ medidate_button; plant_wheat_button ]
in in
let page = div [ topbar; canvas; bottombar; canvas_images ] in let page = div [ topbar; canvas; bottombar; canvas_images ] in

View file

@ -51,6 +51,8 @@ let papy_up = C2d.image_src_of_el (get_el "papy_up")
let water = C2d.image_src_of_el (get_el "water") let water = C2d.image_src_of_el (get_el "water")
let wheat = C2d.image_src_of_el (get_el "wheat")
let draw_canvas = let draw_canvas =
let offset_conv = let offset_conv =
let m = float_of_int @@ (tile_size / 2) in let m = float_of_int @@ (tile_size / 2) in
@ -78,6 +80,7 @@ let draw_canvas =
| Grass -> grass | Grass -> grass
| Water -> water | Water -> water
| Black -> water | Black -> water
| Wheat -> wheat
in in
C2d.draw_image context tile_img ~x:tile_x ~y:tile_y C2d.draw_image context tile_img ~x:tile_x ~y:tile_y
done done
@ -92,9 +95,13 @@ let draw_canvas =
C2d.draw_image context papy ~x:papy_x ~y:papy_y C2d.draw_image context papy ~x:papy_x ~y:papy_y
let draw_topbar state = let draw_topbar state =
(* draw mana level *)
let mana_lvl = Jv.get Jv.global "mana_lvl" in let mana_lvl = Jv.get Jv.global "mana_lvl" in
Jv.set mana_lvl "innerHTML" Jv.set mana_lvl "innerHTML"
(Jv.of_string @@ string_of_int state.Shared.State.mana) (Jv.of_string @@ string_of_int state.Shared.State.mana);
(* draw wheat level *)
let wheat_lvl = Jv.get Jv.global "wheat_lvl" in
Jv.set wheat_lvl "innerHTML" (Jv.of_string @@ string_of_int state.wheat)
(* queue for action to be done *) (* queue for action to be done *)
let input_queue = Queue.create () let input_queue = Queue.create ()
@ -104,15 +111,17 @@ let to_apply_queue : State.action' Queue.t = Queue.create ()
let send_action state = function let send_action state = function
(* actions we don't need to send to the server *) (* actions we don't need to send to the server *)
| (State.Move_offset _ | Move _) as action -> begin (*
| (State.Move_offset _ | Move _) as action -> begin
match State.check_action state action with match State.check_action state action with
| Error e -> | Error e ->
(* TODO: display this in the window *) (* TODO: display this in the window *)
Log.debug "invalid action: %s@\n" e Log.debug "invalid action: %s@\n" e
| Ok actions -> List.iter (fun a -> Queue.add a to_apply_queue) actions | Ok actions -> List.iter (fun a -> Queue.add a to_apply_queue) actions
end end
*)
(* actions we want to send to the server *) (* actions we want to send to the server *)
| Meditate as action -> ( | (State.Move_offset _ | Move _ | Meditate | Plant_wheat) as action -> (
match State.check_action state action with match State.check_action state action with
| Error e -> | Error e ->
(* TODO: display this in the window *) (* TODO: display this in the window *)
@ -160,7 +169,7 @@ let keypress_handler =
; "KeyW" ; "KeyW"
|]; |];
let keys = Hashtbl.create 512 in let keys = Hashtbl.create 512 in
Array.iter (fun key -> Hashtbl.add keys key ()) [| "m" |]; Array.iter (fun key -> Hashtbl.add keys key ()) [| "m"; "p" |];
(* TODO: I'm not sure the Hashtbl business is worth it. (* TODO: I'm not sure the Hashtbl business is worth it.
Before, we were matching on values instead of calling Hashtbl.mem. Before, we were matching on values instead of calling Hashtbl.mem.
It should be better with Hashtbl but it wasn't benchmarked. *) It should be better with Hashtbl but it wasn't benchmarked. *)
@ -190,6 +199,7 @@ let apply_last_key () =
| "KeyS" | "ArrowDown" -> Move_offset Down | "KeyS" | "ArrowDown" -> Move_offset Down
| "KeyD" | "ArrowRight" -> Move_offset Right | "KeyD" | "ArrowRight" -> Move_offset Right
| "m" -> Meditate | "m" -> Meditate
| "p" -> Plant_wheat
| _ -> | _ ->
(* if this happen, it means we're adding (* if this happen, it means we're adding
bad values in `keypress_handler` bad values in `keypress_handler`
@ -270,6 +280,15 @@ let () =
meditate_button meditate_button
in in
let _e : Ev.listener =
let plant_wheat_button =
Jv.get Jv.global "plant_wheat_button" |> Ev.target_of_jv
in
Ev.listen Ev.click
(fun _ev -> Queue.add (State.Plant_wheat : State.action) input_queue)
plant_wheat_button
in
Fut.await initial_state_fut (fun msg -> Fut.await initial_state_fut (fun msg ->
match Ws_client.to_server_msg msg with match Ws_client.to_server_msg msg with
| Update_result _res_msg -> | Update_result _res_msg ->

View file

@ -8,6 +8,7 @@ type background =
| Grass | Grass
| Water | Water
| Black | Black
| Wheat
let pp_dir fmt dir = let pp_dir fmt dir =
let s = let s =
@ -21,7 +22,11 @@ let pp_dir fmt dir =
let pp_background fmt b = let pp_background fmt b =
let s = let s =
match b with Grass -> "Grass" | Water -> "Water" | Black -> "Black" match b with
| Grass -> "Grass"
| Water -> "Water"
| Black -> "Black"
| Wheat -> "Wheat"
in in
Format.pp_print_string fmt s Format.pp_print_string fmt s
@ -53,6 +58,19 @@ let init () =
let get_tile_kind ~x ~y map = let get_tile_kind ~x ~y map =
try map.tiles.(x).(y) with Invalid_argument _ -> Black try map.tiles.(x).(y) with Invalid_argument _ -> Black
let count_wheat map =
Array.fold_left
(fun count a ->
let count' =
Array.fold_left
(fun count -> function
| Wheat -> succ count
| Black | Grass | Water -> count )
0 a
in
count + count' )
0 map
let check_move map ({ x; y; _ } as pos) movement_dir = let check_move map ({ x; y; _ } as pos) movement_dir =
let x, y = let x, y =
match movement_dir with match movement_dir with
@ -64,4 +82,4 @@ let check_move map ({ x; y; _ } as pos) movement_dir =
match get_tile_kind ~x ~y map with match get_tile_kind ~x ~y map with
| (Black | Water) as bg -> | (Black | Water) as bg ->
Error (Format.asprintf "can't move on %a" pp_background bg) Error (Format.asprintf "can't move on %a" pp_background bg)
| Grass -> Ok { pos with x; y } | Grass | Wheat -> Ok { pos with x; y }

View file

@ -40,6 +40,7 @@ end
type t = type t =
{ map : Map.t { map : Map.t
; mana : int ; mana : int
; wheat : int
; player_pos : Map.position ; player_pos : Map.position
; offset_x : float ; offset_x : float
; offset_y : float ; offset_y : float
@ -48,6 +49,7 @@ type t =
let init () = let init () =
{ map = Map.init () { map = Map.init ()
; mana = 0 ; mana = 0
; wheat = 0
; player_pos = { x = 0; y = 0; dir = Down } ; player_pos = { x = 0; y = 0; dir = Down }
; offset_x = 0. ; offset_x = 0.
; offset_y = 0. ; offset_y = 0.
@ -58,23 +60,30 @@ type action =
(* TODO some action do not needs to be checked by server *) (* TODO some action do not needs to be checked by server *)
| Move_offset of Map.dir | Move_offset of Map.dir
| Move of Map.dir | Move of Map.dir
| Plant_wheat
(* TODO: we don't need dir so we should change the type of Map.position *)
(* type for result of action send to the client by the server *) (* type for result of action send to the client by the server *)
type action' = type action' =
| Add_mana of int | Add_mana of int
| Set_player_position of Map.position | Set_player_position of Map.position
| Set_offset of float * float | Set_offset of float * float
| Plant_wheat of int * int
let pp_action fmt = function let pp_action fmt = function
| Meditate -> Format.pp_print_string fmt "Meditate" | Meditate -> Format.pp_print_string fmt "Meditate"
| Move_offset dir -> Format.fprintf fmt "Move_offset %a" Map.pp_dir dir | Move_offset dir -> Format.fprintf fmt "Move_offset %a" Map.pp_dir dir
| Move dir -> Format.fprintf fmt "Move %a" Map.pp_dir dir | Move dir -> Format.fprintf fmt "Move %a" Map.pp_dir dir
| Plant_wheat -> Format.fprintf fmt "Plant_wheat"
let pp_action' fmt = function let pp_action' fmt = function
| Add_mana n -> Format.fprintf fmt "Add_mana %d" n | Add_mana n -> Format.fprintf fmt "Add_mana %d" n
| Set_player_position pos -> | Set_player_position pos ->
Format.fprintf fmt "Set_player_position (%a)" Map.pp_position pos Format.fprintf fmt "Set_player_position (%a)" Map.pp_position pos
| Set_offset (x, y) -> Format.fprintf fmt "Set_offset (%f, %f)" x y | Set_offset (x, y) -> Format.fprintf fmt "Set_offset (%f, %f)" x y
| Plant_wheat (x, y) -> Format.fprintf fmt "Plant_wheat (%d, %d)" x y
let plant_wheat_cost = 10
let rec check_action state = function let rec check_action state = function
| Meditate -> | Meditate ->
@ -104,21 +113,44 @@ let rec check_action state = function
| Ok actions -> Ok (offset_action @ actions) | Ok actions -> Ok (offset_action @ actions)
end end
end end
| Plant_wheat -> (
let { Map.x; y; dir } = state.player_pos in
let x, y =
match dir with
| Down -> (x, y + 1)
| Left -> (x - 1, y)
| Right -> (x + 1, y)
| Up -> (x, y - 1)
in
match Map.get_tile_kind ~x ~y state.map with
| Map.Black -> Error "can't plant wheat in space !"
| Water -> Error "can't plant wheat in water !"
| Wheat -> Error "there's already some wheat there !"
| Grass ->
if state.mana >= plant_wheat_cost then Ok [ Plant_wheat (x, y) ]
else Error "not enough mana..." )
let perform_action state = function let perform_action state = function
| Add_mana n -> { state with mana = state.mana + n } | Add_mana n -> { state with mana = state.mana + n }
| Set_player_position player_pos -> { state with player_pos } | Set_player_position player_pos -> { state with player_pos }
| Set_offset (offset_x, offset_y) -> { state with offset_x; offset_y } | Set_offset (offset_x, offset_y) -> { state with offset_x; offset_y }
| Plant_wheat (x, y) ->
state.map.tiles.(x).(y) <- Map.Wheat;
{ state with mana = state.mana - plant_wheat_cost }
let auto_update state = let auto_update state =
match check_action state Meditate with let state =
| Error _e -> state match check_action state Meditate with
| Ok actions -> List.fold_left perform_action state actions | Error _e -> state
| Ok actions -> List.fold_left perform_action state actions
in
let count_wheat = Map.count_wheat state.map.tiles in
{ state with wheat = state.wheat + count_wheat }
let auto_update_rate = Time.mk_s 1 let auto_update_rate = Time.mk_s 1
let pp fmt { mana; player_pos; map; offset_x; offset_y } = let pp fmt { mana; wheat; player_pos; map; offset_x; offset_y } =
let bg = Map.get_tile_kind ~x:player_pos.x ~y:player_pos.y map in let bg = Map.get_tile_kind ~x:player_pos.x ~y:player_pos.y map in
Format.fprintf fmt Format.fprintf fmt
"mana = %d; player_pos = %a; %a; offset_x = %f; offset_y = %f" mana "mana = %d; wheat = %d; player_pos = %a; %a; offset_x = %f; offset_y = %f"
Map.pp_position player_pos Map.pp_background bg offset_x offset_y mana wheat Map.pp_position player_pos Map.pp_background bg offset_x offset_y