summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornsensfel <SpamShield0@noot-noot.org>2017-10-19 13:30:40 +0200
committernsensfel <SpamShield0@noot-noot.org>2017-10-19 13:30:40 +0200
commite008855086d124f0de14eacc858ecb57d23e371c (patch)
treee3fe94dcf2966d17ac970b4b9cbbf6998c1f34a6 /src/battlemap
parentab299e08cee6ee9b2b122ce87b9bdab3b0dd637c (diff)
Starting a more modular approach for the website.
Diffstat (limited to 'src/battlemap')
-rw-r--r--src/battlemap/Makefile16
-rw-r--r--src/battlemap/elm-package.json15
-rw-r--r--src/battlemap/src/Battlemap.elm142
-rw-r--r--src/battlemap/src/Battlemap/Direction.elm17
-rw-r--r--src/battlemap/src/Battlemap/Location.elm44
-rw-r--r--src/battlemap/src/Battlemap/Marker.elm5
-rw-r--r--src/battlemap/src/Battlemap/Navigator.elm141
-rw-r--r--src/battlemap/src/Battlemap/Navigator/Move.elm157
-rw-r--r--src/battlemap/src/Battlemap/Navigator/Path.elm168
-rw-r--r--src/battlemap/src/Battlemap/Navigator/RangeIndicator.elm287
-rw-r--r--src/battlemap/src/Battlemap/Tile.elm25
-rw-r--r--src/battlemap/src/Character.elm44
-rw-r--r--src/battlemap/src/Error.elm29
-rw-r--r--src/battlemap/src/Event.elm12
-rw-r--r--src/battlemap/src/Init.elm9
-rw-r--r--src/battlemap/src/Main.elm20
-rw-r--r--src/battlemap/src/Model.elm58
-rw-r--r--src/battlemap/src/Model/EndTurn.elm63
-rw-r--r--src/battlemap/src/Model/RequestDirection.elm81
-rw-r--r--src/battlemap/src/Model/SelectCharacter.elm41
-rw-r--r--src/battlemap/src/Model/SelectTile.elm62
-rw-r--r--src/battlemap/src/Shim/Battlemap.elm12
-rw-r--r--src/battlemap/src/Shim/Battlemap/Tile.elm44
-rw-r--r--src/battlemap/src/Shim/Model.elm54
-rw-r--r--src/battlemap/src/Subscriptions.elm7
-rw-r--r--src/battlemap/src/Update.elm27
-rw-r--r--src/battlemap/src/Util/Array.elm25
-rw-r--r--src/battlemap/src/Util/List.elm12
-rw-r--r--src/battlemap/src/View.elm33
-rw-r--r--src/battlemap/src/View/Battlemap.elm78
-rw-r--r--src/battlemap/src/View/Battlemap/Navigator.elm17
-rw-r--r--src/battlemap/src/View/Battlemap/Tile.elm39
-rw-r--r--src/battlemap/src/View/Controls.elm36
-rw-r--r--src/battlemap/src/View/Status.elm52
-rw-r--r--src/battlemap/www/index.html9
35 files changed, 1881 insertions, 0 deletions
diff --git a/src/battlemap/Makefile b/src/battlemap/Makefile
new file mode 100644
index 0000000..02cae24
--- /dev/null
+++ b/src/battlemap/Makefile
@@ -0,0 +1,16 @@
+ELM_CC = elm-make --warn
+
+SRC_DIR = src
+WWW_DIR = www
+WWW_SCRIPT_DIR = $(WWW_DIR)/script
+
+MAIN_MODULE = $(SRC_DIR)/Main.elm
+SUB_MODULES = $(shell find $(SRC_DIR) -type f | grep "elm$$")
+
+$(WWW_SCRIPT_DIR)/main.js: $(MAIN_MODULE) $(SUB_MODULES)
+ $(ELM_CC) $(MAIN_MODULE) --output $@
+
+build: $(WWW_SCRIPT_DIR)/main.js
+
+clean:
+ rm -f $(WWW_SCRIPT_DIR)/main.js
diff --git a/src/battlemap/elm-package.json b/src/battlemap/elm-package.json
new file mode 100644
index 0000000..7c1672e
--- /dev/null
+++ b/src/battlemap/elm-package.json
@@ -0,0 +1,15 @@
+{
+ "version": "1.0.0",
+ "summary": "helpful summary of your project, less than 80 characters",
+ "repository": "https://github.com/nsensfel/tacticians-client.git",
+ "license": "Apache 2.0",
+ "source-directories": [
+ "src"
+ ],
+ "exposed-modules": [],
+ "dependencies": {
+ "elm-lang/core": "5.1.1 <= v < 6.0.0",
+ "elm-lang/html": "2.0.0 <= v < 3.0.0"
+ },
+ "elm-version": "0.18.0 <= v < 0.19.0"
+}
diff --git a/src/battlemap/src/Battlemap.elm b/src/battlemap/src/Battlemap.elm
new file mode 100644
index 0000000..d2e4523
--- /dev/null
+++ b/src/battlemap/src/Battlemap.elm
@@ -0,0 +1,142 @@
+module Battlemap exposing
+ (
+ Type,
+ reset,
+ get_navigator_remaining_points,
+ get_tiles,
+ set_navigator,
+ try_getting_navigator_location,
+ try_getting_navigator_path_to,
+ try_getting_navigator_summary,
+ try_adding_step_to_navigator
+ )
+
+import Array
+
+import Battlemap.Navigator
+import Battlemap.Tile
+import Battlemap.Direction
+import Battlemap.Location
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias 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)
+
+has_location : Type -> Battlemap.Location.Type -> Bool
+has_location bmap loc =
+ (
+ (loc.x >= 0)
+ && (loc.y >= 0)
+ && (loc.x < bmap.width)
+ && (loc.y < bmap.height)
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_tiles : Type -> (Array.Array Battlemap.Tile.Type)
+get_tiles bmap = bmap.content
+
+reset : Type -> Type
+reset bmap =
+ {bmap |
+ navigator = Nothing
+ }
+
+try_getting_navigator_location : Type -> (Maybe Battlemap.Location.Type)
+try_getting_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 =
+ {bmap |
+ navigator =
+ (Just
+ (Battlemap.Navigator.new
+ start_loc
+ movement_points
+ attack_range
+ (\loc -> ((can_cross loc) && (has_location bmap loc)))
+ )
+ )
+ }
+
+try_adding_step_to_navigator : (
+ Type ->
+ (Battlemap.Location.Type -> Bool) ->
+ Battlemap.Direction.Type ->
+ (Maybe Type)
+ )
+try_adding_step_to_navigator bmap can_cross dir =
+ case bmap.navigator of
+ (Just navigator) ->
+ let
+ new_navigator =
+ (Battlemap.Navigator.try_adding_step
+ navigator
+ dir
+ (\loc -> ((can_cross loc) && (has_location bmap loc)))
+ (\loc ->
+ case
+ (Array.get (location_to_index bmap loc) bmap.content)
+ of
+ (Just tile) -> (Battlemap.Tile.get_cost tile)
+ Nothing -> 0
+ )
+ )
+ in
+ case new_navigator of
+ (Just _) -> (Just {bmap | navigator = new_navigator})
+ Nothing -> Nothing
+
+ _ -> Nothing
+
+try_getting_navigator_summary : Type -> (Maybe Battlemap.Navigator.Summary)
+try_getting_navigator_summary bmap =
+ case bmap.navigator of
+ (Just navigator) -> (Just (Battlemap.Navigator.get_summary navigator))
+ Nothing -> Nothing
+
+try_getting_navigator_path_to : (
+ Type ->
+ Battlemap.Location.Ref ->
+ (Maybe (List Battlemap.Direction.Type))
+ )
+try_getting_navigator_path_to bmap loc_ref =
+ case bmap.navigator of
+ (Just navigator) ->
+ (Battlemap.Navigator.try_getting_path_to navigator loc_ref)
+
+ Nothing -> Nothing
+
diff --git a/src/battlemap/src/Battlemap/Direction.elm b/src/battlemap/src/Battlemap/Direction.elm
new file mode 100644
index 0000000..5aad141
--- /dev/null
+++ b/src/battlemap/src/Battlemap/Direction.elm
@@ -0,0 +1,17 @@
+module Battlemap.Direction exposing (Type(..), opposite_of)
+
+type Type =
+ None
+ | Left
+ | Right
+ | Up
+ | Down
+
+opposite_of : Type -> Type
+opposite_of d =
+ case d of
+ Left -> Right
+ Right -> Left
+ Up -> Down
+ Down -> Up
+ None -> None
diff --git a/src/battlemap/src/Battlemap/Location.elm b/src/battlemap/src/Battlemap/Location.elm
new file mode 100644
index 0000000..36f0c4d
--- /dev/null
+++ b/src/battlemap/src/Battlemap/Location.elm
@@ -0,0 +1,44 @@
+module Battlemap.Location exposing (..)
+
+import Battlemap.Direction
+
+type alias Type =
+ {
+ x : Int,
+ y : Int
+ }
+
+type alias Ref = (Int, Int)
+
+neighbor : Type -> Battlemap.Direction.Type -> Type
+neighbor loc dir =
+ case dir of
+ Battlemap.Direction.Right -> {loc | x = (loc.x + 1)}
+ Battlemap.Direction.Left -> {loc | x = (loc.x - 1)}
+ Battlemap.Direction.Up -> {loc | y = (loc.y - 1)}
+ Battlemap.Direction.Down -> {loc | y = (loc.y + 1)}
+ Battlemap.Direction.None -> loc
+
+get_ref : Type -> Ref
+get_ref l =
+ (l.x, l.y)
+
+from_ref : Ref -> Type
+from_ref (x, y) =
+ {x = x, y = y}
+
+dist : Type -> Type -> Int
+dist loc_a loc_b =
+ if (loc_a.x > loc_b.x)
+ then
+ if (loc_a.y > loc_b.y)
+ then
+ ((loc_a.x - loc_b.x) + (loc_a.y - loc_b.y))
+ else
+ ((loc_a.x - loc_b.x) + (loc_b.y - loc_a.y))
+ else
+ if (loc_a.y > loc_b.y)
+ then
+ ((loc_b.x - loc_a.x) + (loc_a.y - loc_b.y))
+ else
+ ((loc_b.x - loc_a.x) + (loc_b.y - loc_a.y))
diff --git a/src/battlemap/src/Battlemap/Marker.elm b/src/battlemap/src/Battlemap/Marker.elm
new file mode 100644
index 0000000..ebefce6
--- /dev/null
+++ b/src/battlemap/src/Battlemap/Marker.elm
@@ -0,0 +1,5 @@
+module Battlemap.Marker exposing (Type(..))
+
+type Type =
+ CanAttack
+ | CanGoTo
diff --git a/src/battlemap/src/Battlemap/Navigator.elm b/src/battlemap/src/Battlemap/Navigator.elm
new file mode 100644
index 0000000..6687b18
--- /dev/null
+++ b/src/battlemap/src/Battlemap/Navigator.elm
@@ -0,0 +1,141 @@
+module Battlemap.Navigator exposing
+ (
+ Type,
+ Summary,
+ new,
+ get_current_location,
+ get_remaining_points,
+ get_range_markers,
+ get_summary,
+ try_adding_step,
+ try_getting_path_to
+ )
+
+import Dict
+
+import Battlemap.Location
+import Battlemap.Direction
+import Battlemap.Marker
+
+import Battlemap.Navigator.Path
+import Battlemap.Navigator.RangeIndicator
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias Type =
+ {
+ 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
+ )
+ }
+
+type alias Summary =
+ {
+ starting_location: Battlemap.Location.Type,
+ path: (List Battlemap.Direction.Type),
+ markers: (List (Battlemap.Location.Ref, Battlemap.Marker.Type))
+ }
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+new : (
+ Battlemap.Location.Type ->
+ Int ->
+ Int ->
+ (Battlemap.Location.Type -> Bool) -> Type
+ )
+new start_loc mov_dist atk_dist can_cross_fun =
+ {
+ 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)
+ )
+ }
+
+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)
+
+get_summary : Type -> Summary
+get_summary navigator =
+ {
+ starting_location = navigator.starting_location,
+ path = (Battlemap.Navigator.Path.get_summary navigator.path),
+ markers =
+ (List.map
+ (\(loc, range_indicator) ->
+ (
+ loc,
+ (Battlemap.Navigator.RangeIndicator.get_marker
+ range_indicator
+ )
+ )
+ )
+ (Dict.toList
+ navigator.range_indicators
+ )
+ )
+ }
+
+try_adding_step : (
+ Type ->
+ Battlemap.Direction.Type ->
+ (Battlemap.Location.Type -> Bool) ->
+ (Battlemap.Location.Type -> Int) ->
+ (Maybe Type)
+ )
+try_adding_step navigator dir can_cross cost_fun =
+ case
+ (Battlemap.Navigator.Path.try_following_direction
+ can_cross
+ cost_fun
+ (Just navigator.path)
+ dir
+ )
+ of
+ (Just path) -> (Just {navigator | path = path})
+ Nothing -> Nothing
+
+try_getting_path_to : (
+ Type ->
+ Battlemap.Location.Ref ->
+ (Maybe (List Battlemap.Direction.Type))
+ )
+try_getting_path_to navigator loc_ref =
+ case (Dict.get loc_ref navigator.range_indicators) of
+ (Just target) ->
+ (Just (Battlemap.Navigator.RangeIndicator.get_path target))
+ Nothing -> Nothing
+
diff --git a/src/battlemap/src/Battlemap/Navigator/Move.elm b/src/battlemap/src/Battlemap/Navigator/Move.elm
new file mode 100644
index 0000000..9d7a17b
--- /dev/null
+++ b/src/battlemap/src/Battlemap/Navigator/Move.elm
@@ -0,0 +1,157 @@
+module Battlemap.Navigator.Move exposing (to)
+
+import Set
+import List
+
+import Battlemap
+import Battlemap.Direction
+import Battlemap.Location
+import Battlemap.Tile
+import Battlemap.Navigator
+
+import Character
+
+import Util.List
+
+can_move_to_new_tile : (
+ Battlemap.Navigator.Type ->
+ Battlemap.Type ->
+ Battlemap.Location.Type ->
+ Bool
+ )
+can_move_to_new_tile nav battlemap next_location =
+ (
+ (nav.remaining_points > 0)
+ && (Battlemap.has_location battlemap next_location)
+ && (nav.current_location /= next_location)
+ &&
+ (not
+ (Set.member
+ (Battlemap.Location.get_ref next_location)
+ nav.visited_locations
+ )
+ )
+ )
+
+battlemap_move_to : (
+ Battlemap.Type ->
+ Battlemap.Location.Type ->
+ Battlemap.Direction.Type ->
+ Battlemap.Location.Type ->
+ Battlemap.Type
+ )
+battlemap_move_to battlemap current_loc dir next_loc =
+ (Battlemap.apply_to_tile_unsafe
+ (Battlemap.apply_to_tile_unsafe
+ battlemap
+ current_loc
+ (Battlemap.Tile.set_direction dir)
+ )
+ next_loc
+ (Battlemap.Tile.set_direction dir)
+ )
+
+navigator_move_to : (
+ Battlemap.Navigator.Type ->
+ Battlemap.Direction.Type ->
+ Battlemap.Location.Type ->
+ Battlemap.Navigator.Type
+ )
+navigator_move_to nav dir next_loc =
+ {nav |
+ current_location = next_loc,
+ visited_locations =
+ (Set.insert
+ (Battlemap.Location.get_ref nav.current_location)
+ nav.visited_locations
+ ),
+ previous_directions = (dir :: nav.previous_directions),
+ remaining_points = (nav.remaining_points - 1)
+ }
+
+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
+ )
+navigator_backtrack nav next_loc prev_dir_tail =
+ {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 : (
+ Battlemap.Type ->
+ Battlemap.Navigator.Type ->
+ Battlemap.Direction.Type ->
+ (List Character.Type) ->
+ (Battlemap.Type, Battlemap.Navigator.Type)
+ )
+to battlemap nav dir char_list =
+ let
+ next_location = (Battlemap.Location.neighbor nav.current_location dir)
+ is_occupied =
+ (List.any
+ (\c -> ((Character.get_location c) == next_location))
+ char_list
+ )
+ in
+ if (not is_occupied)
+ then
+ if (can_move_to_new_tile nav battlemap next_location)
+ then
+ (
+ (battlemap_move_to
+ battlemap
+ nav.current_location
+ dir
+ next_location
+ ),
+ (navigator_move_to
+ nav
+ dir
+ next_location
+ )
+ )
+ else
+ case (Util.List.pop nav.previous_directions) of
+ Nothing -> (battlemap, nav)
+ (Just (head, tail)) ->
+ if (head == (Battlemap.Direction.opposite_of dir))
+ then
+ (
+ (battlemap_backtrack
+ battlemap
+ nav.current_location
+ ),
+ (navigator_backtrack
+ nav
+ next_location
+ tail
+ )
+ )
+ else
+ (battlemap, nav)
+ else
+ (battlemap, nav)
diff --git a/src/battlemap/src/Battlemap/Navigator/Path.elm b/src/battlemap/src/Battlemap/Navigator/Path.elm
new file mode 100644
index 0000000..53e12c0
--- /dev/null
+++ b/src/battlemap/src/Battlemap/Navigator/Path.elm
@@ -0,0 +1,168 @@
+module Battlemap.Navigator.Path exposing
+ (
+ Type,
+ new,
+ get_current_location,
+ get_remaining_points,
+ get_summary,
+ try_following_direction
+ )
+
+import Set
+
+import Util.List
+
+import Battlemap.Direction
+import Battlemap.Location
+
+--------------------------------------------------------------------------------
+-- TYPES -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+type alias Type =
+ {
+ current_location : Battlemap.Location.Type,
+ visited_locations : (Set.Set Battlemap.Location.Ref),
+ previous_directions : (List Battlemap.Direction.Type),
+ previous_points : (List Int),
+ remaining_points : Int
+ }
+
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+has_been_to : (
+ Type ->
+ Battlemap.Location.Type ->
+ Bool
+ )
+has_been_to path location =
+ (
+ (path.current_location == location)
+ ||
+ (Set.member
+ (Battlemap.Location.get_ref location)
+ path.visited_locations
+ )
+ )
+
+try_moving_to : (
+ Type ->
+ Battlemap.Direction.Type ->
+ Battlemap.Location.Type ->
+ Int ->
+ (Maybe Type)
+ )
+try_moving_to path dir next_loc cost =
+ let
+ remaining_points = (path.remaining_points - cost)
+ in
+ if (remaining_points >= 0)
+ then
+ (Just
+ {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),
+ previous_points =
+ (path.remaining_points :: path.previous_points),
+ remaining_points = remaining_points
+ }
+ )
+ else
+ Nothing
+
+try_backtracking_to : (
+ Type ->
+ Battlemap.Direction.Type ->
+ Battlemap.Location.Type ->
+ (Maybe Type)
+ )
+try_backtracking_to path dir location =
+ case
+ (
+ (Util.List.pop path.previous_directions),
+ (Util.List.pop path.previous_points)
+ )
+ of
+ (
+ (Just (prev_dir_head, prev_dir_tail)),
+ (Just (prev_pts_head, prev_pts_tail))
+ ) ->
+ if (prev_dir_head == (Battlemap.Direction.opposite_of dir))
+ then
+ (Just
+ {path |
+ current_location = location,
+ visited_locations =
+ (Set.remove
+ (Battlemap.Location.get_ref location)
+ path.visited_locations
+ ),
+ previous_directions = prev_dir_tail,
+ previous_points = prev_pts_tail,
+ remaining_points = prev_pts_head
+ }
+ )
+ else
+ Nothing
+ (_, _) ->
+ Nothing
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+new : Battlemap.Location.Type -> Int -> Type
+new start points =
+ {
+ current_location = start,
+ visited_locations = Set.empty,
+ previous_directions = [],
+ previous_points = [],
+ 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
+
+get_summary : Type -> (List Battlemap.Direction.Type)
+get_summary path = path.previous_directions
+try_following_direction : (
+ (Battlemap.Location.Type -> Bool) ->
+ (Battlemap.Location.Type -> Int) ->
+ (Maybe Type) ->
+ Battlemap.Direction.Type ->
+ (Maybe Type)
+ )
+try_following_direction can_cross cost_fun maybe_path dir =
+ case maybe_path of
+ (Just path) ->
+ let
+ next_location =
+ (Battlemap.Location.neighbor
+ path.current_location
+ dir
+ )
+ in
+ if (can_cross next_location)
+ then
+ if (has_been_to path next_location)
+ then
+ (try_backtracking_to path dir next_location)
+ else
+ (try_moving_to
+ path
+ dir
+ next_location
+ (cost_fun next_location)
+ )
+ else
+ Nothing
+ Nothing -> Nothing
diff --git a/src/battlemap/src/Battlemap/Navigator/RangeIndicator.elm b/src/battlemap/src/Battlemap/Navigator/RangeIndicator.elm
new file mode 100644
index 0000000..a8cac8e
--- /dev/null
+++ b/src/battlemap/src/Battlemap/Navigator/RangeIndicator.elm
@@ -0,0 +1,287 @@
+module Battlemap.Navigator.RangeIndicator exposing
+ (
+ Type,
+ generate,
+ get_marker,
+ get_path
+ )
+
+import Dict
+import List
+
+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
+
+get_path : Type -> (List Battlemap.Direction.Type)
+get_path indicator = indicator.path
diff --git a/src/battlemap/src/Battlemap/Tile.elm b/src/battlemap/src/Battlemap/Tile.elm
new file mode 100644
index 0000000..255310a
--- /dev/null
+++ b/src/battlemap/src/Battlemap/Tile.elm
@@ -0,0 +1,25 @@
+module Battlemap.Tile exposing
+ (
+ Type,
+ get_location,
+ get_icon_id,
+ get_cost
+ )
+
+import Battlemap.Location
+
+type alias Type =
+ {
+ location : Battlemap.Location.Type,
+ icon_id : String,
+ crossing_cost : Int
+ }
+
+get_location : Type -> Battlemap.Location.Type
+get_location tile = tile.location
+
+get_icon_id : Type -> String
+get_icon_id tile = tile.icon_id
+
+get_cost : Type -> Int
+get_cost tile = tile.crossing_cost
diff --git a/src/battlemap/src/Character.elm b/src/battlemap/src/Character.elm
new file mode 100644
index 0000000..1b4d1a1
--- /dev/null
+++ b/src/battlemap/src/Character.elm
@@ -0,0 +1,44 @@
+module Character exposing
+ (
+ Type,
+ Ref,
+ get_ref,
+ get_icon_id,
+ get_location,
+ set_location,
+ get_movement_points,
+ get_attack_range
+ )
+
+import Battlemap.Location
+
+type alias Type =
+ {
+ id : String,
+ name : String,
+ icon : String,
+ portrait : String,
+ location : Battlemap.Location.Type,
+ movement_points : Int,
+ atk_dist : Int
+ }
+
+type alias Ref = String
+
+get_ref : Type -> Ref
+get_ref c = c.id
+
+get_icon_id : Type -> String
+get_icon_id c = c.icon
+
+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/src/battlemap/src/Error.elm b/src/battlemap/src/Error.elm
new file mode 100644
index 0000000..581bb24
--- /dev/null
+++ b/src/battlemap/src/Error.elm
@@ -0,0 +1,29 @@
+module Error exposing (Type, Mode(..), new, to_string)
+
+type Mode =
+ IllegalAction
+ | Programming
+
+type alias Type =
+ {
+ mode: Mode,
+ message: String
+ }
+
+new : Mode -> String -> Type
+new mode str =
+ {
+ mode = mode,
+ message = str
+ }
+
+to_string : Type -> String
+to_string e =
+ (
+ (case e.mode of
+ IllegalAction -> "Request discarded: "
+ Programming -> "Error in the program (please report): "
+ )
+ ++ e.message
+ )
+
diff --git a/src/battlemap/src/Event.elm b/src/battlemap/src/Event.elm
new file mode 100644
index 0000000..5debff1
--- /dev/null
+++ b/src/battlemap/src/Event.elm
@@ -0,0 +1,12 @@
+module Event exposing (Type(..))
+
+import Battlemap.Direction
+import Battlemap.Location
+
+import Character
+
+type Type =
+ DirectionRequested Battlemap.Direction.Type
+ | TileSelected Battlemap.Location.Ref
+ | CharacterSelected Character.Ref
+ | TurnEnded
diff --git a/src/battlemap/src/Init.elm b/src/battlemap/src/Init.elm
new file mode 100644
index 0000000..25509d1
--- /dev/null
+++ b/src/battlemap/src/Init.elm
@@ -0,0 +1,9 @@
+module Init exposing (init)
+
+import Model
+import Event
+
+import Shim.Model
+
+init : (Model.Type, (Cmd Event.Type))
+init = ((Shim.Model.generate), Cmd.none)
diff --git a/src/battlemap/src/Main.elm b/src/battlemap/src/Main.elm
new file mode 100644
index 0000000..5a9d843
--- /dev/null
+++ b/src/battlemap/src/Main.elm
@@ -0,0 +1,20 @@
+import Html
+
+import Model
+import Event
+
+import Init
+import Subscriptions
+import View
+import Update
+
+main : (Program Never Model.Type Event.Type)
+main =
+ (Html.program
+ {
+ init = Init.init,
+ view = View.view,
+ update = Update.update,
+ subscriptions = Subscriptions.subscriptions
+ }
+ )
diff --git a/src/battlemap/src/Model.elm b/src/battlemap/src/Model.elm
new file mode 100644
index 0000000..ed067d3
--- /dev/null
+++ b/src/battlemap/src/Model.elm
@@ -0,0 +1,58 @@
+module Model exposing
+ (
+ Type,
+ Selection(..),
+ State(..),
+ get_state,
+ invalidate,
+ reset,
+ clear_error
+ )
+
+import Dict
+
+import Battlemap
+import Battlemap.Location
+
+import Error
+
+import Character
+
+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: Selection
+ }
+
+get_state : Type -> State
+get_state model = model.state
+
+reset : Type -> (Dict.Dict Character.Ref Character.Type) -> Type
+reset model characters =
+ {model |
+ state = Default,
+ battlemap = (Battlemap.reset model.battlemap),
+ characters = characters,
+ error = Nothing,
+ selection = None
+ }
+
+invalidate : Type -> Error.Type -> Type
+invalidate model err = {model | error = (Just err)}
+
+clear_error : Type -> Type
+clear_error model = {model | error = Nothing}
diff --git a/src/battlemap/src/Model/EndTurn.elm b/src/battlemap/src/Model/EndTurn.elm
new file mode 100644
index 0000000..441f3b7
--- /dev/null
+++ b/src/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.try_getting_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/src/battlemap/src/Model/RequestDirection.elm b/src/battlemap/src/Model/RequestDirection.elm
new file mode 100644
index 0000000..cf600e6
--- /dev/null
+++ b/src/battlemap/src/Model/RequestDirection.elm
@@ -0,0 +1,81 @@
+module Model.RequestDirection exposing (apply_to)
+
+import Dict
+
+import Battlemap
+import Battlemap.Direction
+import Battlemap.Location
+
+
+import Character
+
+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.try_adding_step_to_navigator
+ model.battlemap
+ (\loc ->
+ (List.all
+ (\char ->
+ (
+ ((Character.get_ref char) == char_id)
+ ||
+ (
+ (Battlemap.Location.get_ref
+ (Character.get_location char)
+ )
+ /=
+ (Battlemap.Location.get_ref loc)
+ )
+ )
+ )
+ (Dict.values model.characters)
+ )
+ )
+ dir
+ )
+ in
+ case new_bmap of
+ (Just bmap) ->
+ {model |
+ state = Model.MovingCharacterWithButtons,
+ battlemap = 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/src/battlemap/src/Model/SelectCharacter.elm b/src/battlemap/src/Model/SelectCharacter.elm
new file mode 100644
index 0000000..7cc2102
--- /dev/null
+++ b/src/battlemap/src/Model/SelectCharacter.elm
@@ -0,0 +1,41 @@
+module Model.SelectCharacter exposing (apply_to)
+
+import Dict
+
+import Character
+
+import Battlemap
+
+import Model
+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/src/battlemap/src/Model/SelectTile.elm b/src/battlemap/src/Model/SelectTile.elm
new file mode 100644
index 0000000..0fe30fa
--- /dev/null
+++ b/src/battlemap/src/Model/SelectTile.elm
@@ -0,0 +1,62 @@
+module Model.SelectTile exposing (apply_to)
+
+import Battlemap
+import Battlemap.Direction
+import Battlemap.Location
+
+import Model.RequestDirection
+import Model.EndTurn
+
+import Model
+import Error
+
+autopilot : Battlemap.Direction.Type -> Model.Type -> Model.Type
+autopilot dir model =
+ (Model.RequestDirection.apply_to model dir)
+
+go_to_tile : Model.Type -> Battlemap.Location.Ref -> Model.Type
+go_to_tile model loc_ref =
+ case (Battlemap.try_getting_navigator_location model.battlemap) of
+ (Just nav_loc) ->
+ if (loc_ref == (Battlemap.Location.get_ref nav_loc))
+ then
+ -- We are already there.
+ if (model.state == Model.MovingCharacterWithClick)
+ then
+ -- And we just clicked on that tile.
+ (Model.EndTurn.apply_to model)
+ else
+ -- And we didn't just click on that tile.
+ {model | state = Model.MovingCharacterWithClick}
+ else
+ -- We have to try getting there.
+ case
+ (Battlemap.try_getting_navigator_path_to
+ model.battlemap
+ loc_ref
+ )
+ of
+ (Just path) ->
+ let
+ new_model = (List.foldr (autopilot) model path)
+ in
+ {new_model | state = Model.MovingCharacterWithClick}
+
+ Nothing -> -- Clicked outside of the range indicator
+ (Model.reset model model.characters)
+ Nothing -> -- Clicked outside of the range indicator
+ (Model.reset model model.characters)
+
+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/src/battlemap/src/Shim/Battlemap.elm b/src/battlemap/src/Shim/Battlemap.elm
new file mode 100644
index 0000000..5a2e29b
--- /dev/null
+++ b/src/battlemap/src/Shim/Battlemap.elm
@@ -0,0 +1,12 @@
+module Shim.Battlemap exposing (generate)
+
+import Shim.Battlemap.Tile
+
+--generate : Battlemap.Type
+generate =
+ {
+ width = 16,
+ height = 16,
+ content = (Shim.Battlemap.Tile.generate 16),
+ navigator = Nothing
+ }
diff --git a/src/battlemap/src/Shim/Battlemap/Tile.elm b/src/battlemap/src/Shim/Battlemap/Tile.elm
new file mode 100644
index 0000000..1e11cb5
--- /dev/null
+++ b/src/battlemap/src/Shim/Battlemap/Tile.elm
@@ -0,0 +1,44 @@
+module Shim.Battlemap.Tile exposing (generate)
+
+import Array
+import List
+
+import Battlemap.Tile
+
+from_int : Int -> Int -> (Int, Int) -> Battlemap.Tile.Type
+from_int map_width index (icon_id, cost) =
+ {
+ location =
+ {
+ x = (index % map_width),
+ y = (index // map_width)
+ },
+ icon_id = (toString icon_id),
+ crossing_cost = cost
+ }
+
+generate : Int -> (Array.Array Battlemap.Tile.Type)
+generate map_width =
+ let
+ as_int_list =
+ [
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (1, 2), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (1, 2), (1, 2), (1, 2), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (1, 2), (1, 2), (1, 2), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (1, 2), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1),
+ (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (2, 99), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1)
+ ]
+ as_list = (List.indexedMap (from_int map_width) as_int_list)
+ in
+ (Array.fromList as_list)
diff --git a/src/battlemap/src/Shim/Model.elm b/src/battlemap/src/Shim/Model.elm
new file mode 100644
index 0000000..f82a0d3
--- /dev/null
+++ b/src/battlemap/src/Shim/Model.elm
@@ -0,0 +1,54 @@
+module Shim.Model exposing (generate)
+
+import Dict
+
+import Model
+
+import Shim.Battlemap
+
+--generate : Model.Type
+generate =
+ {
+ state = Model.Default,
+ selection = Model.None,
+ error = Nothing,
+ battlemap = (Shim.Battlemap.generate),
+ characters =
+ (Dict.insert
+ "2"
+ {
+ id = "2",
+ name = "Char2",
+ icon = "Icon2",
+ portrait = "Portrait2",
+ location = {x = 0, y = 1},
+ movement_points = 5,
+ atk_dist = 1
+ }
+ (Dict.insert
+ "1"
+ {
+ id = "1",
+ name = "Char1",
+ icon = "Icon1",
+ portrait = "Portrait1",
+ location = {x = 1, y = 0},
+ movement_points = 4,
+ atk_dist = 2
+ }
+ (Dict.insert
+ "0"
+ {
+ id = "0",
+ name = "Char0",
+ icon = "Icon0",
+ portrait = "Portrait0",
+ location = {x = 0, y = 0},
+ movement_points = 3,
+ atk_dist = 1
+ }
+ Dict.empty
+ )
+ )
+ )
+ }
diff --git a/src/battlemap/src/Subscriptions.elm b/src/battlemap/src/Subscriptions.elm
new file mode 100644
index 0000000..83df587
--- /dev/null
+++ b/src/battlemap/src/Subscriptions.elm
@@ -0,0 +1,7 @@
+module Subscriptions exposing (..)
+
+import Model
+import Event
+
+subscriptions : Model.Type -> (Sub Event.Type)
+subscriptions model = Sub.none
diff --git a/src/battlemap/src/Update.elm b/src/battlemap/src/Update.elm
new file mode 100644
index 0000000..7ee61a3
--- /dev/null
+++ b/src/battlemap/src/Update.elm
@@ -0,0 +1,27 @@
+module Update exposing (update)
+
+import Event
+
+import Model
+import Model.RequestDirection
+import Model.SelectTile
+import Model.SelectCharacter
+import Model.EndTurn
+
+update : Event.Type -> Model.Type -> (Model.Type, (Cmd Event.Type))
+update event model =
+ let
+ new_model = (Model.clear_error model)
+ in
+ case event of
+ (Event.DirectionRequested d) ->
+ ((Model.RequestDirection.apply_to new_model d), Cmd.none)
+
+ (Event.TileSelected loc) ->
+ ((Model.SelectTile.apply_to new_model loc), Cmd.none)
+
+ (Event.CharacterSelected char_id) ->
+ ((Model.SelectCharacter.apply_to new_model char_id), Cmd.none)
+
+ Event.TurnEnded ->
+ ((Model.EndTurn.apply_to new_model), Cmd.none)
diff --git a/src/battlemap/src/Util/Array.elm b/src/battlemap/src/Util/Array.elm
new file mode 100644
index 0000000..69d329c
--- /dev/null
+++ b/src/battlemap/src/Util/Array.elm
@@ -0,0 +1,25 @@
+module Util.Array exposing (update, update_unsafe)
+
+import Array
+
+update : (
+ Int ->
+ ((Maybe t) -> (Maybe 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/src/battlemap/src/Util/List.elm b/src/battlemap/src/Util/List.elm
new file mode 100644
index 0000000..c4db397
--- /dev/null
+++ b/src/battlemap/src/Util/List.elm
@@ -0,0 +1,12 @@
+module Util.List exposing (pop)
+
+import List
+
+pop : List a -> (Maybe (a, List a))
+pop l =
+ case
+ ((List.head l), (List.tail l))
+ of
+ (Nothing, _) -> Nothing
+ (_ , Nothing) -> Nothing
+ ((Just head), (Just tail)) -> (Just (head, tail))
diff --git a/src/battlemap/src/View.elm b/src/battlemap/src/View.elm
new file mode 100644
index 0000000..8a956d1
--- /dev/null
+++ b/src/battlemap/src/View.elm
@@ -0,0 +1,33 @@
+module View exposing (view)
+
+import Dict
+import Html
+
+import View.Battlemap
+
+import View.Controls
+import View.Status
+
+import Event
+import Model
+
+view : Model.Type -> (Html.Html Event.Type)
+view model =
+ (Html.div
+ []
+ [
+ (Html.div
+ []
+ (View.Controls.view)
+ ),
+ (View.Battlemap.get_html
+ model.battlemap
+ 32
+ (Dict.values model.characters)
+ ),
+ (Html.div
+ []
+ [ (View.Status.view model) ]
+ )
+ ]
+ )
diff --git a/src/battlemap/src/View/Battlemap.elm b/src/battlemap/src/View/Battlemap.elm
new file mode 100644
index 0000000..efe4d1e
--- /dev/null
+++ b/src/battlemap/src/View/Battlemap.elm
@@ -0,0 +1,78 @@
+module View.Battlemap exposing (get_html)
+
+import Array
+
+import List
+
+import Html
+import Html.Attributes
+import Html.Events
+
+import Battlemap
+
+import Character
+
+import View.Battlemap.Tile
+import View.Battlemap.Navigator
+
+import Event
+--------------------------------------------------------------------------------
+-- LOCAL -----------------------------------------------------------------------
+--------------------------------------------------------------------------------
+char_on_map : Int -> Character.Type -> (Html.Html Event.Type)
+char_on_map tile_size char =
+ let
+ char_loc = (Character.get_location char)
+ in
+ (Html.div
+ [
+ (Html.Attributes.class "battlemap-character-icon"),
+ (Html.Attributes.class
+ ("asset-character-icon-" ++ (Character.get_icon_id char))
+ ),
+ (Html.Events.onClick
+ (Event.CharacterSelected (Character.get_ref char))
+ ),
+ (Html.Attributes.style
+ [
+ ("top", ((toString (char_loc.y * tile_size)) ++ "px")),
+ ("left", ((toString (char_loc.x * tile_size)) ++ "px"))
+ ]
+ )
+ ]
+ [
+ ]
+ )
+
+--------------------------------------------------------------------------------
+-- EXPORTED --------------------------------------------------------------------
+--------------------------------------------------------------------------------
+get_html : (
+ Battlemap.Type ->
+ Int ->
+ (List Character.Type) ->
+ (Html.Html Event.Type)
+ )
+get_html battlemap tile_size characters =
+ (Html.div
+ [
+ (Html.Attributes.class "battlemap-container")
+ ]
+ (
+ (List.map
+ (View.Battlemap.Tile.get_html tile_size)
+ (Array.toList (Battlemap.get_tiles battlemap))
+ )
+ ++
+ (List.map
+ (char_on_map tile_size)
+ characters
+ )
+ ++
+ case (Battlemap.try_getting_navigator_summary battlemap) of
+ (Just nav_summary) ->
+ (View.Battlemap.Navigator.get_html tile_size nav_summary)
+
+ Nothing -> [(Html.text "")]
+ )
+ )
diff --git a/src/battlemap/src/View/Battlemap/Navigator.elm b/src/battlemap/src/View/Battlemap/Navigator.elm
new file mode 100644
index 0000000..4180e6d
--- /dev/null
+++ b/src/battlemap/src/View/Battlemap/Navigator.elm
@@ -0,0 +1,17 @@
+module View.Battlemap.Navigator exposing (get_html)
+
+import Html
+--import Html.Attributes
+--import Html.Events
+
+--import Battlemap.Location
+import Battlemap.Navigator
+
+import Event
+
+get_html : (
+ Int ->
+ Battlemap.Navigator.Summary ->
+ (List (Html.Html Event.Type))
+ )
+get_html tile_size nav_summary = []
diff --git a/src/battlemap/src/View/Battlemap/Tile.elm b/src/battlemap/src/View/Battlemap/Tile.elm
new file mode 100644
index 0000000..d38d84e
--- /dev/null
+++ b/src/battlemap/src/View/Battlemap/Tile.elm
@@ -0,0 +1,39 @@
+module View.Battlemap.Tile exposing (get_html)
+
+import Html
+import Html.Attributes
+import Html.Events
+
+import Battlemap.Tile
+import Battlemap.Location
+
+import Event
+
+get_html : (
+ Int ->
+ Battlemap.Tile.Type ->
+ (Html.Html Event.Type)
+ )
+get_html tile_size tile =
+ let
+ tile_loc = (Battlemap.Tile.get_location tile)
+ in
+ (Html.div
+ [
+ (Html.Attributes.class "battlemap-tile-icon"),
+ (Html.Attributes.class
+ ("asset-tile-" ++ (toString (Battlemap.Tile.get_icon_id tile)))
+ ),
+ (Html.Events.onClick
+ (Event.TileSelected (Battlemap.Location.get_ref tile_loc))
+ ),
+ (Html.Attributes.style
+ [
+ ("top", ((toString (tile_loc.y * tile_size)) ++ "px")),
+ ("left", ((toString (tile_loc.x * tile_size)) ++ "px"))
+ ]
+ )
+ ]
+ [
+ ]
+ )
diff --git a/src/battlemap/src/View/Controls.elm b/src/battlemap/src/View/Controls.elm
new file mode 100644
index 0000000..f5851a9
--- /dev/null
+++ b/src/battlemap/src/View/Controls.elm
@@ -0,0 +1,36 @@
+module View.Controls exposing (view)
+
+import Html
+import Html.Events
+
+import Battlemap.Direction
+
+import Event
+
+direction_button : Battlemap.Direction.Type -> String -> (Html.Html Event.Type)
+direction_button dir label =
+ (Html.button
+ [
+ (Html.Events.onClick
+ (Event.DirectionRequested dir)
+ )
+ ]
+ [ (Html.text label) ]
+ )
+
+end_turn_button : (Html.Html Event.Type)
+end_turn_button =
+ (Html.button
+ [ (Html.Events.onClick Event.TurnEnded) ]
+ [ (Html.text "End Turn") ]
+ )
+
+view : (List (Html.Html Event.Type))
+view =
+ [
+ (direction_button Battlemap.Direction.Left "Left"),
+ (direction_button Battlemap.Direction.Down "Down"),
+ (direction_button Battlemap.Direction.Up "Up"),
+ (direction_button Battlemap.Direction.Right "Right"),
+ (end_turn_button)
+ ]
diff --git a/src/battlemap/src/View/Status.elm b/src/battlemap/src/View/Status.elm
new file mode 100644
index 0000000..de2a167
--- /dev/null
+++ b/src/battlemap/src/View/Status.elm
@@ -0,0 +1,52 @@
+module View.Status exposing (view)
+
+import Dict
+
+import Html
+
+import Battlemap
+import Character
+
+import Error
+import Event
+import Model
+
+moving_character_text : Model.Type -> String
+moving_character_text model =
+ case model.selection of
+ (Model.SelectedCharacter char_id) ->
+ case (Dict.get char_id model.characters) of
+ Nothing -> "Error: Unknown character selected."
+ (Just char) ->
+ (
+ "Controlling "
+ ++ char.name
+ ++ ": "
+ ++ (toString
+ (Battlemap.get_navigator_remaining_points
+ model.battlemap
+ )
+ )
+ ++ "/"
+ ++ (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 =
+ (Html.text
+ (
+ (case model.state of
+ Model.Default -> "Click on a character to control it."
+ Model.MovingCharacterWithButtons -> (moving_character_text model)
+ Model.MovingCharacterWithClick -> (moving_character_text model)
+ Model.FocusingTile -> "Error: Unimplemented."
+ )
+ ++ " " ++
+ (case model.error of
+ Nothing -> ""
+ (Just error) -> (Error.to_string error)
+ )
+ )
+ )
diff --git a/src/battlemap/www/index.html b/src/battlemap/www/index.html
new file mode 100644
index 0000000..f630b80
--- /dev/null
+++ b/src/battlemap/www/index.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ </head>
+ <body>
+ <script src="script/main.js"></script>
+ <script>Elm.Main.fullscreen();</script>
+ </body>
+</html>