From 5a75000ec7b961ad5fe93814e5b7905cacbdba49 Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Thu, 12 Oct 2017 19:46:36 +0200 Subject: Started a rather large reorganization. --- elm/battlemap/Makefile | 2 +- elm/battlemap/src/Battlemap.elm | 121 ++++++++- elm/battlemap/src/Battlemap/Html.elm | 4 +- elm/battlemap/src/Battlemap/Marker.elm | 5 + elm/battlemap/src/Battlemap/Navigator.elm | 105 ++++++-- elm/battlemap/src/Battlemap/Navigator/Path.elm | 170 ++++++++++++ .../src/Battlemap/Navigator/RangeIndicator.elm | 284 +++++++++++++++++++++ elm/battlemap/src/Battlemap/RangeIndicator.elm | 260 ------------------- elm/battlemap/src/Battlemap/Tile.elm | 27 +- elm/battlemap/src/Character.elm | 20 +- elm/battlemap/src/Event.elm | 8 +- elm/battlemap/src/Model.elm | 35 +-- elm/battlemap/src/Model/EndTurn.elm | 63 +++++ elm/battlemap/src/Model/RequestDirection.elm | 60 +++++ elm/battlemap/src/Model/SelectCharacter.elm | 42 +++ elm/battlemap/src/Model/SelectTile.elm | 93 +++++++ elm/battlemap/src/Update.elm | 25 +- elm/battlemap/src/Update/DirectionRequest.elm | 51 ---- elm/battlemap/src/Update/EndTurn.elm | 81 ------ elm/battlemap/src/Update/SelectCharacter.elm | 95 ------- elm/battlemap/src/Update/SelectTile.elm | 95 ------- elm/battlemap/src/Util/Array.elm | 17 +- elm/battlemap/src/View/Controls.elm | 4 +- elm/battlemap/src/View/Status.elm | 17 +- 24 files changed, 994 insertions(+), 690 deletions(-) create mode 100644 elm/battlemap/src/Battlemap/Marker.elm create mode 100644 elm/battlemap/src/Battlemap/Navigator/Path.elm create mode 100644 elm/battlemap/src/Battlemap/Navigator/RangeIndicator.elm delete mode 100644 elm/battlemap/src/Battlemap/RangeIndicator.elm create mode 100644 elm/battlemap/src/Model/EndTurn.elm create mode 100644 elm/battlemap/src/Model/RequestDirection.elm create mode 100644 elm/battlemap/src/Model/SelectCharacter.elm create mode 100644 elm/battlemap/src/Model/SelectTile.elm delete mode 100644 elm/battlemap/src/Update/DirectionRequest.elm delete mode 100644 elm/battlemap/src/Update/EndTurn.elm delete mode 100644 elm/battlemap/src/Update/SelectCharacter.elm delete mode 100644 elm/battlemap/src/Update/SelectTile.elm diff --git a/elm/battlemap/Makefile b/elm/battlemap/Makefile index 54b52d8..97d7b0b 100644 --- a/elm/battlemap/Makefile +++ b/elm/battlemap/Makefile @@ -1,4 +1,4 @@ -ELM_CC = elm-make +ELM_CC = elm-make --warn SRC_DIR = src MAIN_MODULE = $(SRC_DIR)/Main.elm diff --git a/elm/battlemap/src/Battlemap.elm b/elm/battlemap/src/Battlemap.elm index 309b538..e07ae2d 100644 --- a/elm/battlemap/src/Battlemap.elm +++ b/elm/battlemap/src/Battlemap.elm @@ -1,25 +1,36 @@ module Battlemap exposing ( Type, - apply_to_tile, - apply_to_tile_unsafe, - has_location, - apply_to_all_tiles + reset, + get_navigator_location, + get_navigator_remaining_points, + set_navigator, + add_step_to_navigator ) import Array +import Battlemap.Navigator +import Battlemap.Navigator.RangeIndicator import Battlemap.Tile import Battlemap.Direction import Battlemap.Location +import Util.Array +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- type alias Type = { - width : Int, - height : Int, - content : (Array.Array Battlemap.Tile.Type) + width: Int, + height: Int, + content: (Array.Array Battlemap.Tile.Type), + navigator: (Maybe Battlemap.Navigator.Type) } +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- location_to_index : Type -> Battlemap.Location.Type -> Int location_to_index bmap loc = ((loc.y * bmap.width) + loc.x) @@ -33,6 +44,102 @@ has_location bmap loc = && (loc.y < bmap.height) ) +add_marker_to_tiles : ( + Type -> + (Battlemap.Location.Ref, Battlemap.Navigator.RangeIndicator.Type) -> + (Array.Array Battlemap.Tile.Type) -> + (Array.Array Battlemap.Tile.Type) + ) +add_marker_to_tiles bmap (location, indicator) tiles = + (Util.Array.update_unsafe + (location_to_index bmap (Battlemap.Location.from_ref location)) + ( + (Battlemap.Tile.set_marker + (Just + (Battlemap.Navigator.RangeIndicator.get_marker indicator) + ) + ) + ) + tiles + ) +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +reset : Type -> Type +reset bmap = + {bmap | + content = (Array.map (Battlemap.Tile.reset) bmap.content), + navigator = Nothing + } + +get_navigator_location : Type -> (Maybe Battlemap.Location.Type) +get_navigator_location bmap = + case bmap.navigator of + (Just navigator) -> + (Just + (Battlemap.Navigator.get_current_location navigator) + ) + + Nothing -> Nothing + +get_navigator_remaining_points : Type -> Int +get_navigator_remaining_points bmap = + case bmap.navigator of + (Just navigator) -> (Battlemap.Navigator.get_remaining_points navigator) + Nothing -> -1 + +set_navigator : ( + Battlemap.Location.Type -> + Int -> + Int -> + (Battlemap.Location.Type -> Bool) -> + Type -> + Type + ) +set_navigator start_loc movement_points attack_range can_cross bmap = + let + new_navigator = + (Battlemap.Navigator.new + start_loc + movement_points + attack_range + (\loc -> ((can_cross loc) && (has_location bmap loc))) + ) + new_range_markers = (Battlemap.Navigator.get_range_markers new_navigator) + in + {bmap | + content = + (List.foldr + (add_marker_to_tiles bmap) + bmap.content + new_range_markers + ), + navigator = (Just new_navigator) + } + +add_step_to_navigator : ( + Type -> + Battlemap.Direction.Type -> + (Battlemap.Location.Type -> Bool) -> + (Maybe Type) +add_step_to_navigator bmap dir can_cross = + case bmap.navigator of + (Just navigator) -> + let + new_navigator = + (Battlemap.Navigator.add_step + navigator + (\loc -> ((can_cross loc) && (has_location bmap loc))) + dir + ) + in + case new_navigator of + (Just _) -> {bmap | navigator = new_navigator} + Nothing -> Nothing + + _ -> Nothing +-------------------------------------------------------------------------------- + apply_to_all_tiles : ( Type -> (Battlemap.Tile.Type -> Battlemap.Tile.Type) -> Type ) diff --git a/elm/battlemap/src/Battlemap/Html.elm b/elm/battlemap/src/Battlemap/Html.elm index 6506c0f..d7cfc63 100644 --- a/elm/battlemap/src/Battlemap/Html.elm +++ b/elm/battlemap/src/Battlemap/Html.elm @@ -33,7 +33,7 @@ view_battlemap_cell t = case t.char_level of Nothing -> (Html.td - [ (Html.Events.onClick (Event.SelectTile t.location)) ] + [ (Html.Events.onClick (Event.TileSelected t.location)) ] [ (Html.text (case t.mod_level of @@ -47,7 +47,7 @@ view_battlemap_cell t = ) (Just char_id) -> (Html.td - [ (Html.Events.onClick (Event.SelectCharacter char_id)) ] + [ (Html.Events.onClick (Event.CharacterSelected char_id)) ] [ (Html.text ("[" ++ char_id ++ "]")), (Html.text (nav_level_to_text t)) diff --git a/elm/battlemap/src/Battlemap/Marker.elm b/elm/battlemap/src/Battlemap/Marker.elm new file mode 100644 index 0000000..ebefce6 --- /dev/null +++ b/elm/battlemap/src/Battlemap/Marker.elm @@ -0,0 +1,5 @@ +module Battlemap.Marker exposing (Type(..)) + +type Type = + CanAttack + | CanGoTo diff --git a/elm/battlemap/src/Battlemap/Navigator.elm b/elm/battlemap/src/Battlemap/Navigator.elm index b040013..9cdfc1f 100644 --- a/elm/battlemap/src/Battlemap/Navigator.elm +++ b/elm/battlemap/src/Battlemap/Navigator.elm @@ -2,43 +2,94 @@ module Battlemap.Navigator exposing ( Type, new, - reset + get_current_location, + get_remaining_points, + get_range_markers, + add_step ) -import Set +import Dict -import Battlemap -import Battlemap.Direction import Battlemap.Location -import Battlemap.Tile +import Battlemap.Navigator.Path +import Battlemap.Navigator.RangeIndicator +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- type alias Type = { - current_location : Battlemap.Location.Type, - visited_locations : (Set.Set Battlemap.Location.Ref), - previous_directions : (List Battlemap.Direction.Type), - remaining_points : Int, - starting_location : Battlemap.Location.Type, - starting_points : Int + starting_location: Battlemap.Location.Type, + movement_dist: Int, + attack_dist: Int, + path: Battlemap.Navigator.Path.Type, + range_indicators: + (Dict.Dict + Battlemap.Location.Ref + Battlemap.Navigator.RangeIndicator.Type + ) } -new : Battlemap.Location.Type -> Int -> Type -new start points = +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +new : ( + Battlemap.Location.Type -> + Int -> + Int -> + (Battlemap.Location.Type -> Bool) -> Type + ) +new start_loc mov_dist atk_dist can_cross_fun = { - current_location = start, - visited_locations = Set.empty, - previous_directions = [], - remaining_points = points, - starting_location = start, - starting_points = points + starting_location = start_loc, + movement_dist = mov_dist, + attack_dist = atk_dist, + path = (Battlemap.Navigator.Path.new start_loc mov_dist), + range_indicators = + (Battlemap.Navigator.RangeIndicator.generate + start_loc + mov_dist + atk_dist + (can_cross_fun) + ) } -reset : Type -> Type -reset nav = - {nav | - current_location = nav.starting_location, - visited_locations = Set.empty, - previous_directions = [], - remaining_points = nav.starting_points - } +get_current_location : Type -> Battlemap.Location.Type +get_current_location navigator = + (Battlemap.Navigator.Path.get_current_location navigator.path) + +get_remaining_points : Type -> Int +get_remaining_points navigator = + (Battlemap.Navigator.Path.get_remaining_points navigator.path) + +get_range_markers : ( + Type -> + (List + (Battlemap.Location.Ref, Battlemap.Navigator.RangeIndicator.Type) + ) + ) +get_range_markers navigator = (Dict.toList navigator.range_indicators) + +add_step : ( + Type -> + Battlemap.Direction.Type -> + (Battlemap.Location.Type -> Bool) -> + (Maybe Type) + ) +add_step navigator dir can_cross = + case + (Battlemap.Navigator.Path.follow_direction + can_cross + (Just navigator.path) + dir + ) + of + (Just path) -> (Just {navigator | path = path} + Nothing -> Nothing diff --git a/elm/battlemap/src/Battlemap/Navigator/Path.elm b/elm/battlemap/src/Battlemap/Navigator/Path.elm new file mode 100644 index 0000000..5ce2d4c --- /dev/null +++ b/elm/battlemap/src/Battlemap/Navigator/Path.elm @@ -0,0 +1,170 @@ +module Battlemap.Navigator.Path exposing + ( + Type, + new, + get_current_location, + get_remaining_points, + follow_directions + ) + +import Set + +import Battlemap.Direction +import Battlemap.Location +import Battlemap.Tile + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + current_location : Battlemap.Location.Type, + visited_locations : (Set.Set Battlemap.Location.Ref), + previous_directions : (List Battlemap.Direction.Type), + remaining_points : Int + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +has_not_been_to : ( + Type -> + Battlemap.Location.Type -> + Bool + ) +has_not_been_to path location = + ( + (path.current_location /= location) + && + (not + (Set.member + (Battlemap.Location.get_ref location) + path.visited_locations + ) + ) + ) + +move_to : ( + Type -> + Battlemap.Direction.Type -> + Battlemap.Location.Type -> + Int -> + Type + ) +move_to path dir next_loc cost = + {path | + current_location = next_loc, + visited_locations = + (Set.insert + (Battlemap.Location.get_ref path.current_location) + path.visited_locations + ), + previous_directions = (dir :: path.previous_directions), + remaining_points = (path.remaining_points - cost) + } + +battlemap_backtrack : ( + Battlemap.Type -> + Battlemap.Location.Type -> + Battlemap.Type + ) +battlemap_backtrack battlemap current_loc = + (Battlemap.apply_to_tile_unsafe + battlemap + current_loc + (Battlemap.Tile.set_direction + Battlemap.Direction.None + ) + ) + +navigator_backtrack : ( + Battlemap.Navigator.Type -> + Battlemap.Location.Type -> + (List Battlemap.Direction.Type) -> + Battlemap.Navigator.Type + ) +try_backtracking_to path location dir = + case (Util.List.pop nav.previous_directions) of + (Just (head, tail)) -> + if (head == (Battlemap.Direction.opposite_of dir)) + then + (backtrack_to + nav + next_location + tail + ) + ) + else + (battlemap, nav) + Nothing -> (battlemap, nav) + move_to path next_location + if (can_move_to_new_tile path next_location) + then + else + {nav | + current_location = next_loc, + visited_locations = + (Set.remove + (Battlemap.Location.get_ref next_loc) + nav.visited_locations + ), + previous_directions = prev_dir_tail, + remaining_points = (nav.remaining_points + 1) + } + + +to : ( + Type -> + Battlemap.Direction.Type -> + (Battlemap.Type, Battlemap.Navigator.Type) + ) +to battlemap nav dir char_list = + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +new : Battlemap.Location.Type -> Int -> Type +new start points = + { + current_location = start, + visited_locations = Set.empty, + previous_directions = [], + remaining_points = points + } + +get_current_location : Type -> Battlemap.Location.Type +get_current_location path = path.current_location + +get_remaining_points : Type -> Int +get_remaining_points path = path.remaining_points + +follow_direction : ( + (Battlemap.Location.Type -> Bool) -> + (Maybe Type) -> + Battlemap.Direction.Type -> + (Maybe Type) + ) +follow_direction can_cross cost_fun maybe_path dir = + case maybe_path of + (Just path) -> + let + next_location = + (Battlemap.Location.neighbor + nav.current_location + dir + ) + in + if (can_cross path next_location) + then + if (has_not_been_to path next_location) + then + (Just (move_to path next_location dir)) + else + (try_backtracking_to path next_location dir) + else + Nothing + else + (battlemap, nav) + + Nothing -> Nothing diff --git a/elm/battlemap/src/Battlemap/Navigator/RangeIndicator.elm b/elm/battlemap/src/Battlemap/Navigator/RangeIndicator.elm new file mode 100644 index 0000000..c370d03 --- /dev/null +++ b/elm/battlemap/src/Battlemap/Navigator/RangeIndicator.elm @@ -0,0 +1,284 @@ +module Battlemap.Navigator.RangeIndicator exposing + ( + Type, + generate, + get_marker + ) + +import Dict +import List +import Debug + +import Battlemap.Direction +import Battlemap.Location +import Battlemap.Marker + +import Util.List + +type alias Type = + { + distance: Int, + path: (List Battlemap.Direction.Type), + node_cost: Int, + marker: Battlemap.Marker.Type + } + +generate_row : ( + Battlemap.Location.Type -> + Int -> + Int -> + Int -> + (List Battlemap.Location.Type) -> + (List Battlemap.Location.Type) + ) +generate_row src max_x_mod curr_y curr_x_mod curr_row = + if (curr_x_mod > max_x_mod) + then + curr_row + else + (generate_row + src + max_x_mod + curr_y + (curr_x_mod + 1) + ({x = (src.x + curr_x_mod), y = curr_y} :: curr_row) + ) + +generate_grid : ( + Battlemap.Location.Type -> + Int -> + Int -> + (List Battlemap.Location.Type) -> + (List Battlemap.Location.Type) + ) +generate_grid src dist curr_y_mod curr_list = + if (curr_y_mod > dist) + then + curr_list + else + let + new_limit = (dist - (abs curr_y_mod)) + in + (generate_grid + src + dist + (curr_y_mod + 1) + ( + (generate_row + src + new_limit + (src.y + curr_y_mod) + (-new_limit) + [] + ) + ++ curr_list + ) + ) + +get_closest : ( + Battlemap.Location.Ref -> + Type -> + (Battlemap.Location.Ref, Type) -> + (Battlemap.Location.Ref, Type) + ) +get_closest ref indicator (prev_ref, prev_indicator) = + if (indicator.distance < prev_indicator.distance) + then + (ref, indicator) + else + (prev_ref, prev_indicator) + +handle_neighbors : ( + Battlemap.Location.Type -> + Int -> + Int -> + Type -> + (Dict.Dict Battlemap.Location.Ref Type) -> + (List Battlemap.Direction.Type) -> + (Dict.Dict Battlemap.Location.Ref Type) + ) +handle_neighbors loc dist atk_dist indicator remaining directions = + case (Util.List.pop directions) of + Nothing -> remaining + (Just (head, tail)) -> + let + neighbor_loc = (Battlemap.Location.neighbor loc head) + neighbor_indicator = + (Dict.get + (Battlemap.Location.get_ref neighbor_loc) + remaining + ) + in + case neighbor_indicator of + Nothing -> + (handle_neighbors + loc + dist + atk_dist + indicator + remaining + tail + ) + (Just neighbor) -> + let + is_attack_range = (indicator.distance >= dist) + new_dist = + ( + if (is_attack_range) + then + (indicator.distance + 1) + else + (indicator.distance + neighbor.node_cost) + ) + in + (handle_neighbors + loc + dist + atk_dist + indicator + ( + if + ( + (new_dist < neighbor.distance) + && (new_dist <= atk_dist) + ) + then + (Dict.insert + (Battlemap.Location.get_ref neighbor_loc) + {neighbor | + distance = new_dist, + path = (head :: indicator.path) + } + remaining + ) + else + remaining + ) + tail + ) + +search : ( + (Dict.Dict Battlemap.Location.Ref Type) -> + (Dict.Dict Battlemap.Location.Ref Type) -> + Int -> + Int -> + (Dict.Dict Battlemap.Location.Ref Type) + ) +search result remaining dist atk_dist = + if (Dict.isEmpty remaining) + then + result + else + let + (min_loc_ref, min) = + (Dict.foldl + (get_closest) + ( + (-1,-1), + { + distance = (atk_dist + 1), + path = [], + node_cost = 99, + marker = Battlemap.Marker.CanAttack + } + ) + remaining + ) + in + (search + (Dict.insert + min_loc_ref + {min | + marker = + ( + if (min.distance > dist) + then + Battlemap.Marker.CanAttack + else + Battlemap.Marker.CanGoTo + ) + } + result + ) + (handle_neighbors + (Battlemap.Location.from_ref min_loc_ref) + dist + atk_dist + min + (Dict.remove min_loc_ref remaining) + [ + Battlemap.Direction.Left, + Battlemap.Direction.Right, + Battlemap.Direction.Up, + Battlemap.Direction.Down + ] + ) + dist + atk_dist + ) + +grid_to_range_indicators : ( + (Battlemap.Location.Type -> Bool) -> + Battlemap.Location.Type -> + Int -> + (List Battlemap.Location.Type) -> + (Dict.Dict Battlemap.Location.Ref Type) -> + (Dict.Dict Battlemap.Location.Ref Type) + ) +grid_to_range_indicators can_cross_fun location dist grid result = + case (Util.List.pop grid) of + Nothing -> result + (Just (head, tail)) -> + if (can_cross_fun head) + then + -- TODO: test if the current char can cross that tile. + -- TODO: get tile cost. + (grid_to_range_indicators + (can_cross_fun) + location + dist + tail + (Dict.insert + (Battlemap.Location.get_ref head) + { + distance = + ( + if ((location.x == head.x) && (location.y == head.y)) + then + 0 + else + (dist + 1) + ), + path = [], + node_cost = 1, + marker = Battlemap.Marker.CanGoTo + } + result + ) + ) + else + (grid_to_range_indicators (can_cross_fun) location dist tail result) + +generate : ( + Battlemap.Location.Type -> + Int -> + Int -> + (Battlemap.Location.Type -> Bool) -> + (Dict.Dict Battlemap.Location.Ref Type) + ) +generate location dist atk_dist can_cross_fun = + (search + Dict.empty + (grid_to_range_indicators + (can_cross_fun) + location + atk_dist + (generate_grid location atk_dist (-atk_dist) []) + Dict.empty + ) + dist + atk_dist + ) + +get_marker : Type -> Battlemap.Marker.Type +get_marker indicator = indicator.marker diff --git a/elm/battlemap/src/Battlemap/RangeIndicator.elm b/elm/battlemap/src/Battlemap/RangeIndicator.elm deleted file mode 100644 index 9276e49..0000000 --- a/elm/battlemap/src/Battlemap/RangeIndicator.elm +++ /dev/null @@ -1,260 +0,0 @@ -module Battlemap.RangeIndicator exposing (Type, generate) - -import Dict -import List -import Debug - -import Battlemap -import Battlemap.Direction -import Battlemap.Location - -import Util.List - -type alias Type = - { - distance: Int, - path: (List Battlemap.Direction.Type), - node_cost: Int - } - -generate_row : ( - Battlemap.Location.Type -> - Int -> - Int -> - Int -> - (List Battlemap.Location.Type) -> - (List Battlemap.Location.Type) - ) -generate_row src max_x_mod curr_y curr_x_mod curr_row = - if (curr_x_mod > max_x_mod) - then - curr_row - else - (generate_row - src - max_x_mod - curr_y - (curr_x_mod + 1) - ({x = (src.x + curr_x_mod), y = curr_y} :: curr_row) - ) - -generate_grid : ( - Battlemap.Location.Type -> - Int -> - Int -> - (List Battlemap.Location.Type) -> - (List Battlemap.Location.Type) - ) -generate_grid src dist curr_y_mod curr_list = - if (curr_y_mod > dist) - then - curr_list - else - let - new_limit = (dist - (abs curr_y_mod)) - in - (generate_grid - src - dist - (curr_y_mod + 1) - ( - (generate_row - src - new_limit - (src.y + curr_y_mod) - (-new_limit) - [] - ) - ++ curr_list - ) - ) - -get_closest : ( - Battlemap.Location.Ref -> - Type -> - (Battlemap.Location.Ref, Type) -> - (Battlemap.Location.Ref, Type) - ) -get_closest ref indicator (prev_ref, prev_indicator) = - if (indicator.distance < prev_indicator.distance) - then - (ref, indicator) - else - (prev_ref, prev_indicator) - -handle_neighbors : ( - Battlemap.Location.Type -> - Int -> - Int -> - Type -> - (Dict.Dict Battlemap.Location.Ref Type) -> - (List Battlemap.Direction.Type) -> - (Dict.Dict Battlemap.Location.Ref Type) - ) -handle_neighbors loc dist atk_dist indicator remaining directions = - case (Util.List.pop directions) of - Nothing -> remaining - (Just (head, tail)) -> - let - neighbor_loc = (Battlemap.Location.neighbor loc head) - neighbor_indicator = - (Dict.get - (Battlemap.Location.get_ref neighbor_loc) - remaining - ) - in - case neighbor_indicator of - Nothing -> - (handle_neighbors - loc - dist - atk_dist - indicator - remaining - tail - ) - (Just neighbor) -> - let - is_attack_range = (indicator.distance >= dist) - new_dist = - ( - if (is_attack_range) - then - (indicator.distance + 1) - else - (indicator.distance + neighbor.node_cost) - ) - in - (handle_neighbors - loc - dist - atk_dist - indicator - ( - if - ( - (new_dist < neighbor.distance) - && (new_dist <= atk_dist) - ) - then - (Dict.insert - (Battlemap.Location.get_ref neighbor_loc) - {neighbor | - distance = new_dist, - path = (head :: indicator.path) - } - remaining - ) - else - remaining - ) - tail - ) - -search : ( - (Dict.Dict Battlemap.Location.Ref Type) -> - (Dict.Dict Battlemap.Location.Ref Type) -> - Int -> - Int -> - (Dict.Dict Battlemap.Location.Ref Type) - ) -search result remaining dist atk_dist = - if (Dict.isEmpty remaining) - then - result - else - let - (min_loc_ref, min) = - (Dict.foldl - (get_closest) - ( - (-1,-1), - { - distance = (atk_dist + 1), - path = [], - node_cost = 99 - } - ) - remaining - ) - in - (search - (Dict.insert min_loc_ref min result) - (handle_neighbors - (Battlemap.Location.from_ref min_loc_ref) - dist - atk_dist - min - (Dict.remove min_loc_ref remaining) - [ - Battlemap.Direction.Left, - Battlemap.Direction.Right, - Battlemap.Direction.Up, - Battlemap.Direction.Down - ] - ) - dist - atk_dist - ) - -grid_to_range_indicators : ( - Battlemap.Type -> - Battlemap.Location.Type -> - Int -> - (List Battlemap.Location.Type) -> - (Dict.Dict Battlemap.Location.Ref Type) -> - (Dict.Dict Battlemap.Location.Ref Type) - ) -grid_to_range_indicators battlemap location dist grid result = - case (Util.List.pop grid) of - Nothing -> result - (Just (head, tail)) -> - if (Battlemap.has_location battlemap head) - then - -- TODO: test if the current char can cross that tile. - -- TODO: get tile cost. - (grid_to_range_indicators - battlemap - location - dist - tail - (Dict.insert - (Battlemap.Location.get_ref head) - { - distance = - ( - if ((location.x == head.x) && (location.y == head.y)) - then - 0 - else - (dist + 1) - ), - path = [], - node_cost = 1 - } - result - ) - ) - else - (grid_to_range_indicators battlemap location dist tail result) - -generate : ( - Battlemap.Type -> - Battlemap.Location.Type -> - Int -> - Int -> - (Dict.Dict Battlemap.Location.Ref Type) - ) -generate battlemap location dist atk_dist = - (search - Dict.empty - (grid_to_range_indicators - battlemap - location - atk_dist - (generate_grid location atk_dist (-atk_dist) []) - Dict.empty - ) - dist - atk_dist - ) diff --git a/elm/battlemap/src/Battlemap/Tile.elm b/elm/battlemap/src/Battlemap/Tile.elm index 7e0ae68..d761225 100644 --- a/elm/battlemap/src/Battlemap/Tile.elm +++ b/elm/battlemap/src/Battlemap/Tile.elm @@ -1,38 +1,25 @@ module Battlemap.Tile exposing ( Type, - TileModifier(..), - set_direction, - reset + set_character, + get_character ) import Battlemap.Direction +import Battlemap.Marker import Battlemap.Location import Character -type TileModifier = - CanBeReached - | CanBeAttacked - type alias Type = { location : Battlemap.Location.Ref, floor_level : Int, - nav_level : Battlemap.Direction.Type, char_level : (Maybe Character.Ref), - mod_level : (Maybe TileModifier) } -set_direction : Battlemap.Direction.Type -> Type -> Type -set_direction d t = - {t | - nav_level = d - } +set_character : (Maybe Character.Ref) -> Type -> Type +set_character char_ref tile = {tile | char_level = char_ref} -reset: Type -> Type -reset t = - {t | - nav_level = Battlemap.Direction.None, - mod_level = Nothing - } +get_character : Type -> (Maybe Character.Ref) +get_character tile = tile.char_level diff --git a/elm/battlemap/src/Character.elm b/elm/battlemap/src/Character.elm index f98dfd9..b0be220 100644 --- a/elm/battlemap/src/Character.elm +++ b/elm/battlemap/src/Character.elm @@ -1,4 +1,13 @@ -module Character exposing (Type, Ref, get_ref, get_location) +module Character exposing + ( + Type, + Ref, + get_ref, + get_location, + set_location, + get_movement_points, + get_attack_range + ) import Battlemap.Location @@ -21,3 +30,12 @@ get_ref c = get_location : Type -> Battlemap.Location.Type get_location t = t.location + +set_location : Battlemap.Location.Type -> Type -> Type +set_location location char = {char | location = location} + +get_movement_points : Type -> Int +get_movement_points char = char.movement_points + +get_attack_range : Type -> Int +get_attack_range char = char.atk_dist diff --git a/elm/battlemap/src/Event.elm b/elm/battlemap/src/Event.elm index 2c46360..b591bf4 100644 --- a/elm/battlemap/src/Event.elm +++ b/elm/battlemap/src/Event.elm @@ -7,7 +7,7 @@ import Battlemap.Location import Character type Type = - DirectionRequest Battlemap.Direction.Type - | SelectTile Battlemap.Location.Ref - | SelectCharacter Character.Ref - | EndTurn + DirectionRequested Battlemap.Direction.Type + | TileSelected Battlemap.Location.Ref + | CharacterSelected Character.Ref + | TurnEnded diff --git a/elm/battlemap/src/Model.elm b/elm/battlemap/src/Model.elm index 437d118..80a4c2e 100644 --- a/elm/battlemap/src/Model.elm +++ b/elm/battlemap/src/Model.elm @@ -1,7 +1,7 @@ module Model exposing ( Type, - CharacterSelection, + Selection(..), State(..), get_state, invalidate, @@ -12,55 +12,44 @@ module Model exposing import Dict import Battlemap -import Battlemap.Navigator import Battlemap.Location import Battlemap.Tile -import Battlemap.RangeIndicator import Error import Character -type alias CharacterSelection = - { - character: Character.Ref, - navigator: Battlemap.Navigator.Type, - range_indicator: - (Dict.Dict - Battlemap.Location.Ref - Battlemap.RangeIndicator.Type - ) - } - type State = Default | MovingCharacterWithButtons | MovingCharacterWithClick | FocusingTile +type Selection = + None + | SelectedCharacter Character.Ref + | SelectedTile Battlemap.Location.Ref + type alias Type = { state: State, battlemap: Battlemap.Type, characters: (Dict.Dict Character.Ref Character.Type), error: (Maybe Error.Type), - selection: (Maybe CharacterSelection) + selection: Selection } get_state : Type -> State get_state model = model.state -reset : Type -> Type -reset model = +reset : Type -> (Dict.Dict Character.Ref Character.Type) -> Type +reset model characters = {model | state = Default, - selection = Nothing, + battlemap = (Battlemap.reset model.battlemap), + characters = characters, error = Nothing, - battlemap = - (Battlemap.apply_to_all_tiles - model.battlemap - (Battlemap.Tile.reset) - ) + selection = None } invalidate : Type -> Error.Type -> Type diff --git a/elm/battlemap/src/Model/EndTurn.elm b/elm/battlemap/src/Model/EndTurn.elm new file mode 100644 index 0000000..788c3a1 --- /dev/null +++ b/elm/battlemap/src/Model/EndTurn.elm @@ -0,0 +1,63 @@ +module Model.EndTurn exposing (apply_to) + +import Dict + +import Battlemap + +import Character + +import Error + +import Model + +make_it_so : Model.Type -> Model.Type +make_it_so model = + case model.selection of + (Model.SelectedCharacter char_id) -> + case (Battlemap.get_navigator_location model.battlemap) of + (Just location) -> + (Model.reset + model + (Dict.update + char_id + (\maybe_char -> + case maybe_char of + (Just char) -> + (Just + (Character.set_location location char) + ) + Nothing -> Nothing + ) + model.characters + ) + ) + Nothing -> + (Model.invalidate + model + (Error.new + Error.Programming + "EndTurn: model moving char, no navigator location." + ) + ) + _ -> + (Model.invalidate + model + (Error.new + Error.Programming + "EndTurn: model moving char, no char selected." + ) + ) + +apply_to : Model.Type -> Model.Type +apply_to model = + case (Model.get_state model) of + Model.MovingCharacterWithButtons -> (make_it_so model) + Model.MovingCharacterWithClick -> (make_it_so model) + _ -> + (Model.invalidate + model + (Error.new + Error.IllegalAction + "This can only be done while moving a character." + ) + ) diff --git a/elm/battlemap/src/Model/RequestDirection.elm b/elm/battlemap/src/Model/RequestDirection.elm new file mode 100644 index 0000000..f47a902 --- /dev/null +++ b/elm/battlemap/src/Model/RequestDirection.elm @@ -0,0 +1,60 @@ +module Model.RequestDirection exposing (apply_to) + +import Dict + +import Battlemap +import Battlemap.Direction + +import Model +import Error + +make_it_so : Model.Type -> Battlemap.Direction.Type -> Model.Type +make_it_so model dir = + case model.selection of + (Model.SelectedCharacter char_id) -> + let + new_bmap = + (Battlemap.add_step_to_navigator + model.battlemap + dir + (Dict.values model.characters) + ) + in + case new_bmap of + (Just bmap) -> + {model | + state = Model.MovingCharacterWithButtons, + battlemap = new_bmap + } + + Nothing -> + (Model.invalidate + model + (Error.new + Error.IllegalAction + "Unreachable/occupied tile." + ) + ) + + _ -> + (Model.invalidate + model + (Error.new + Error.Programming + "DirectionRequest: model moving char, no char selected." + ) + ) + +apply_to : Model.Type -> Battlemap.Direction.Type -> Model.Type +apply_to model dir = + case (Model.get_state model) of + Model.MovingCharacterWithButtons -> (make_it_so model dir) + Model.MovingCharacterWithClick -> (make_it_so model dir) + _ -> + (Model.invalidate + model + (Error.new + Error.IllegalAction + "This can only be done while moving a character." + ) + ) diff --git a/elm/battlemap/src/Model/SelectCharacter.elm b/elm/battlemap/src/Model/SelectCharacter.elm new file mode 100644 index 0000000..942e84d --- /dev/null +++ b/elm/battlemap/src/Model/SelectCharacter.elm @@ -0,0 +1,42 @@ +module Model.SelectCharacter exposing (apply_to) + +import Dict + +import Character + +import Battlemap + +import Model +import Event +import Error + +make_it_so : Model.Type -> Character.Ref -> Model.Type +make_it_so model char_id = + case (Dict.get char_id model.characters) of + (Just char) -> + {model | + state = Model.MovingCharacterWithClick, + selection = (Model.SelectedCharacter char_id), + battlemap = + (Battlemap.set_navigator + (Character.get_location char) + (Character.get_movement_points char) + (Character.get_attack_range char) + (\e -> True) -- TODO: check for characters. + model.battlemap + ) + } + + Nothing -> + (Model.invalidate + model + (Error.new + Error.Programming + "SelectCharacter: Unknown char selected." + ) + ) + +apply_to : Model.Type -> Character.Ref -> Model.Type +apply_to model char_id = + case (Model.get_state model) of + _ -> (make_it_so model char_id) diff --git a/elm/battlemap/src/Model/SelectTile.elm b/elm/battlemap/src/Model/SelectTile.elm new file mode 100644 index 0000000..9a01e77 --- /dev/null +++ b/elm/battlemap/src/Model/SelectTile.elm @@ -0,0 +1,93 @@ +module Model.SelectTile exposing (apply_to) + +import Dict + +import Character + +import Battlemap +import Battlemap.Direction +import Battlemap.Location +import Battlemap.Tile + +import Model.RequestDirection +import Model.EndTurn + +import Model +import Error + +autopilot : Battlemap.Direction.Type -> Model.Type -> Model.Type +autopilot dir model = + (Update.DirectionRequest.apply_to model dir) + +go_to_tile : Model.Type -> Battlemap.Location.Ref -> Model.Type +go_to_tile model loc_ref = + case model.selection of + Nothing -> + (Model.invalidate + model + (Error.new + Error.Programming + "SelectTile: model moving char, no selection." + ) + ) + (Just selection) -> + case (Dict.get loc_ref selection.range_indicator) of + Nothing -> -- Clicked outside of the range indicator + (Model.reset model) + (Just indicator) -> + let + new_model = + (List.foldr + (autopilot) + {model | + battlemap = + (Battlemap.apply_to_all_tiles + model.battlemap + (Battlemap.Tile.set_direction + Battlemap.Direction.None + ) + ), + selection = + (Just + { + selection | + navigator = + (Battlemap.Navigator.reset + selection.navigator + ) + } + ) + } + indicator.path + ) + in + if + ( + (model.state == Model.MovingCharacterWithClick) + && + ( + (Battlemap.Location.get_ref + selection.navigator.current_location + ) + == loc_ref + ) + ) + then + (Model.EndTurn.apply_to new_model) + else + {new_model | state = Model.MovingCharacterWithClick} + + +apply_to : Model.Type -> Battlemap.Location.Ref -> Model.Type +apply_to model loc_ref = + case (Model.get_state model) of + Model.MovingCharacterWithButtons -> (go_to_tile model loc_ref) + Model.MovingCharacterWithClick -> (go_to_tile model loc_ref) + _ -> + (Model.invalidate + model + (Error.new + Error.IllegalAction + "This can only be done while moving a character." + ) + ) diff --git a/elm/battlemap/src/Update.elm b/elm/battlemap/src/Update.elm index 0947e99..c6146e1 100644 --- a/elm/battlemap/src/Update.elm +++ b/elm/battlemap/src/Update.elm @@ -3,11 +3,10 @@ module Update exposing (update) import Event import Model - -import Update.DirectionRequest -import Update.SelectTile -import Update.SelectCharacter -import Update.EndTurn +import Model.RequestDirection +import Model.SelectTile +import Model.SelectCharacter +import Model.EndTurn update : Event.Type -> Model.Type -> Model.Type update event model = @@ -15,14 +14,14 @@ update event model = new_model = (Model.clear_error model) in case event of - (Event.DirectionRequest d) -> - (Update.DirectionRequest.apply_to new_model d) + (Event.DirectionRequested d) -> + (Model.DirectionRequest.apply_to new_model d) - (Event.SelectTile loc) -> - (Update.SelectTile.apply_to new_model loc) + (Event.TileSelected loc) -> + (Model.SelectTile.apply_to new_model loc) - (Event.SelectCharacter char_id) -> - (Update.SelectCharacter.apply_to new_model char_id) + (Event.CharacterSelected char_id) -> + (Model.SelectCharacter.apply_to new_model char_id) - Event.EndTurn -> - (Update.EndTurn.apply_to new_model) + Event.TurnEnded -> + (Model.EndTurn.apply_to new_model) diff --git a/elm/battlemap/src/Update/DirectionRequest.elm b/elm/battlemap/src/Update/DirectionRequest.elm deleted file mode 100644 index e069439..0000000 --- a/elm/battlemap/src/Update/DirectionRequest.elm +++ /dev/null @@ -1,51 +0,0 @@ -module Update.DirectionRequest exposing (apply_to) - -import Dict - -import Battlemap.Direction -import Battlemap.Navigator.Move - -import Model -import Error - -make_it_so : Model.Type -> Battlemap.Direction.Type -> Model.Type -make_it_so model dir = - case model.selection of - Nothing -> - (Model.invalidate - model - (Error.new - Error.Programming - "DirectionRequest: model moving char, no selection." - ) - ) - (Just selection) -> - let - (new_bmap, new_nav) = - (Battlemap.Navigator.Move.to - model.battlemap - selection.navigator - dir - (Dict.values model.characters) - ) - in - {model | - state = Model.MovingCharacterWithButtons, - battlemap = new_bmap, - selection = (Just {selection | navigator = new_nav}) - } - - -apply_to : Model.Type -> Battlemap.Direction.Type -> Model.Type -apply_to model dir = - case (Model.get_state model) of - Model.MovingCharacterWithButtons -> (make_it_so model dir) - Model.MovingCharacterWithClick -> (make_it_so model dir) - _ -> - (Model.invalidate - model - (Error.new - Error.IllegalAction - "This can only be done while moving a character." - ) - ) diff --git a/elm/battlemap/src/Update/EndTurn.elm b/elm/battlemap/src/Update/EndTurn.elm deleted file mode 100644 index ce9da28..0000000 --- a/elm/battlemap/src/Update/EndTurn.elm +++ /dev/null @@ -1,81 +0,0 @@ -module Update.EndTurn exposing (apply_to) - -import Dict - -import Battlemap -import Battlemap.Direction -import Battlemap.Navigator -import Battlemap.Tile - -import Model - -import Error - -make_it_so : Model.Type -> Model.Type -make_it_so model = - case model.selection of - Nothing -> - (Model.invalidate - model - (Error.new - Error.Programming - "EndTurn: model moving char, no selection." - ) - ) - (Just selection) -> - case (Dict.get selection.character model.characters) of - Nothing -> - (Model.invalidate - model - (Error.new - Error.Programming - "EndTurn: model moving char, unknown char selected." - ) - ) - (Just char) -> - {model | - state = Model.Default, - selection = Nothing, - battlemap = - (Battlemap.apply_to_all_tiles - (Battlemap.apply_to_tile_unsafe - (Battlemap.apply_to_tile_unsafe - model.battlemap - char.location - (\t -> {t | char_level = Nothing}) - ) - selection.navigator.current_location - (\t -> {t | char_level = (Just selection.character)}) - ) - (Battlemap.Tile.reset) - ), - characters = - (Dict.update - selection.character - (\mc -> - case mc of - Nothing -> Nothing - (Just c) -> - (Just - {c | - location = selection.navigator.current_location - } - ) - ) - model.characters - ) - } - -apply_to : Model.Type -> Model.Type -apply_to model = - case (Model.get_state model) of - Model.MovingCharacterWithButtons -> (make_it_so model) - Model.MovingCharacterWithClick -> (make_it_so model) - _ -> - (Model.invalidate - model - (Error.new - Error.IllegalAction - "This can only be done while moving a character." - ) - ) diff --git a/elm/battlemap/src/Update/SelectCharacter.elm b/elm/battlemap/src/Update/SelectCharacter.elm deleted file mode 100644 index 570f82c..0000000 --- a/elm/battlemap/src/Update/SelectCharacter.elm +++ /dev/null @@ -1,95 +0,0 @@ -module Update.SelectCharacter exposing (apply_to) - -import Dict - -import Character - -import Battlemap -import Battlemap.Direction -import Battlemap.Location -import Battlemap.Navigator -import Battlemap.Tile -import Battlemap.RangeIndicator - -import Model -import Event -import Error - -display_range : ( - Int -> - Battlemap.Location.Ref -> - Battlemap.RangeIndicator.Type -> - Battlemap.Type -> - Battlemap.Type - ) -display_range dist loc_ref indicator bmap = - (Battlemap.apply_to_tile_unsafe - bmap - (Battlemap.Location.from_ref loc_ref) - (\e -> - {e | - mod_level = - ( - if (indicator.distance <= dist) - then - (Just Battlemap.Tile.CanBeReached) - else - (Just Battlemap.Tile.CanBeAttacked) - ) - } - ) - ) - - -make_it_so : Model.Type -> Character.Ref -> Model.Type -make_it_so model char_id = - case (Dict.get char_id model.characters) of - Nothing -> - (Model.invalidate - model - (Error.new - Error.Programming - "SelectCharacter: Unknown char selected." - ) - ) - (Just char) -> - let - new_range_indicator = - (Battlemap.RangeIndicator.generate - model.battlemap - char.location - char.movement_points - (char.movement_points + char.atk_dist) - ) - in - {model | - state = Model.MovingCharacterWithClick, - battlemap = - ( - (Dict.foldl - (display_range char.movement_points) - (Battlemap.apply_to_all_tiles - model.battlemap - (Battlemap.Tile.reset) - ) - new_range_indicator - ) - ), - selection = - (Just - { - character = char_id, - navigator = - (Battlemap.Navigator.new - char.location - char.movement_points - ), - range_indicator = new_range_indicator - } - ) - } - -apply_to : Model.Type -> Character.Ref -> Model.Type -apply_to model char_id = - case (Model.get_state model) of - _ -> (make_it_so model char_id) diff --git a/elm/battlemap/src/Update/SelectTile.elm b/elm/battlemap/src/Update/SelectTile.elm deleted file mode 100644 index cc2af35..0000000 --- a/elm/battlemap/src/Update/SelectTile.elm +++ /dev/null @@ -1,95 +0,0 @@ -module Update.SelectTile exposing (apply_to) - -import Dict - -import Character - -import Battlemap -import Battlemap.Direction -import Battlemap.Location -import Battlemap.Navigator -import Battlemap.Tile -import Battlemap.RangeIndicator - -import Update.DirectionRequest -import Update.EndTurn - -import Model -import Error - -autopilot : Battlemap.Direction.Type -> Model.Type -> Model.Type -autopilot dir model = - (Update.DirectionRequest.apply_to model dir) - -go_to_tile : Model.Type -> Battlemap.Location.Ref -> Model.Type -go_to_tile model loc_ref = - case model.selection of - Nothing -> - (Model.invalidate - model - (Error.new - Error.Programming - "SelectTile: model moving char, no selection." - ) - ) - (Just selection) -> - case (Dict.get loc_ref selection.range_indicator) of - Nothing -> -- Clicked outside of the range indicator - (Model.reset model) - (Just indicator) -> - let - new_model = - (List.foldr - (autopilot) - {model | - battlemap = - (Battlemap.apply_to_all_tiles - model.battlemap - (Battlemap.Tile.set_direction - Battlemap.Direction.None - ) - ), - selection = - (Just - { - selection | - navigator = - (Battlemap.Navigator.reset - selection.navigator - ) - } - ) - } - indicator.path - ) - in - if - ( - (model.state == Model.MovingCharacterWithClick) - && - ( - (Battlemap.Location.get_ref - selection.navigator.current_location - ) - == loc_ref - ) - ) - then - (Update.EndTurn.apply_to new_model) - else - {new_model | state = Model.MovingCharacterWithClick} - - -apply_to : Model.Type -> Battlemap.Location.Ref -> Model.Type -apply_to model loc_ref = - case (Model.get_state model) of - Model.MovingCharacterWithButtons -> (go_to_tile model loc_ref) - Model.MovingCharacterWithClick -> (go_to_tile model loc_ref) - _ -> - (Model.invalidate - model - (Error.new - Error.IllegalAction - "This can only be done while moving a character." - ) - ) diff --git a/elm/battlemap/src/Util/Array.elm b/elm/battlemap/src/Util/Array.elm index 8088244..69d329c 100644 --- a/elm/battlemap/src/Util/Array.elm +++ b/elm/battlemap/src/Util/Array.elm @@ -1,14 +1,25 @@ -module Util.Array exposing (update) +module Util.Array exposing (update, update_unsafe) import Array update : ( Int -> ((Maybe t) -> (Maybe t)) -> - (Array t) -> - (Array t) + (Array.Array t) -> + (Array.Array t) ) update index fun array = case (fun (Array.get index array)) of Nothing -> array (Just e) -> (Array.set index e array) + +update_unsafe : ( + Int -> + (t -> t) -> + (Array.Array t) -> + (Array.Array t) + ) +update_unsafe index fun array = + case (Array.get index array) of + Nothing -> array + (Just e) -> (Array.set index (fun e) array) diff --git a/elm/battlemap/src/View/Controls.elm b/elm/battlemap/src/View/Controls.elm index be698bf..f5851a9 100644 --- a/elm/battlemap/src/View/Controls.elm +++ b/elm/battlemap/src/View/Controls.elm @@ -12,7 +12,7 @@ direction_button dir label = (Html.button [ (Html.Events.onClick - (Event.DirectionRequest dir) + (Event.DirectionRequested dir) ) ] [ (Html.text label) ] @@ -21,7 +21,7 @@ direction_button dir label = end_turn_button : (Html.Html Event.Type) end_turn_button = (Html.button - [ (Html.Events.onClick Event.EndTurn) ] + [ (Html.Events.onClick Event.TurnEnded) ] [ (Html.text "End Turn") ] ) diff --git a/elm/battlemap/src/View/Status.elm b/elm/battlemap/src/View/Status.elm index 5fcc663..de2a167 100644 --- a/elm/battlemap/src/View/Status.elm +++ b/elm/battlemap/src/View/Status.elm @@ -4,6 +4,9 @@ import Dict import Html +import Battlemap +import Character + import Error import Event import Model @@ -11,20 +14,24 @@ import Model moving_character_text : Model.Type -> String moving_character_text model = case model.selection of - Nothing -> "Error: no model.selection." - (Just selection) -> - case (Dict.get selection.character model.characters) of + (Model.SelectedCharacter char_id) -> + case (Dict.get char_id model.characters) of Nothing -> "Error: Unknown character selected." (Just char) -> ( "Controlling " ++ char.name ++ ": " - ++ (toString selection.navigator.remaining_points) + ++ (toString + (Battlemap.get_navigator_remaining_points + model.battlemap + ) + ) ++ "/" - ++ (toString char.movement_points) + ++ (toString (Character.get_movement_points char)) ++ " movement points remaining." ) + _ -> "Error: model.selection does not match its state." view : Model.Type -> (Html.Html Event.Type) view model = -- cgit v0.12-29-g3973