summaryrefslogtreecommitdiff
blob: d2c950f58c0d81d8a6d0a022ac9e9949ca0e8cd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
module BattleMap.Struct.Map exposing
   (
      Type,
      decoder,
      empty,
      get_height,
      get_markers,
      set_markers,
      remove_marker,
      add_marker,
      get_tile_data_function,
      get_omnimods_at,
      get_tiles,
      get_width,
      new,
      set_tile_to,
      solve_tiles,
      try_getting_tile_at
   )

-- Elm -------------------------------------------------------------------------
import Array

import Set

import Dict

import Json.Decode

-- Shared ----------------------------------------------------------------------
import Util.Array

-- Battle ----------------------------------------------------------------------
import Battle.Struct.Omnimods

-- Battle Map ------------------------------------------------------------------
import BattleMap.Struct.Location
import BattleMap.Struct.Marker
import BattleMap.Struct.Tile
import BattleMap.Struct.TileInstance

-- Local Module ----------------------------------------------------------------
import Constants.Movement

--------------------------------------------------------------------------------
-- TYPES -----------------------------------------------------------------------
--------------------------------------------------------------------------------
type alias Type =
   {
      width : Int,
      height : Int,
      content : (Array.Array BattleMap.Struct.TileInstance.Type),
      markers : (Dict.Dict String BattleMap.Struct.Marker.Type)
   }

--------------------------------------------------------------------------------
-- LOCAL -----------------------------------------------------------------------
--------------------------------------------------------------------------------
location_to_index : BattleMap.Struct.Location.Type -> Type -> Int
location_to_index loc map =
   ((loc.y * map.width) + loc.x)

has_location : BattleMap.Struct.Location.Type -> Type -> Bool
has_location loc map =
   (
      (loc.x >= 0)
      && (loc.y >= 0)
      && (loc.x < map.width)
      && (loc.y < map.height)
   )

--------------------------------------------------------------------------------
-- EXPORTED --------------------------------------------------------------------
--------------------------------------------------------------------------------
get_width : Type -> Int
get_width map = map.width

get_height : Type -> Int
get_height map = map.height

get_tiles : Type -> (Array.Array BattleMap.Struct.TileInstance.Type)
get_tiles map = map.content

get_markers : Type -> (Dict.Dict String BattleMap.Struct.Marker.Type)
get_markers map = map.markers

set_markers : (Dict.Dict String BattleMap.Struct.Marker.Type) -> Type -> Type
set_markers markers map = {map | markers = markers}

remove_marker : String -> Type -> Type
remove_marker marker_name map =
   case (Dict.get marker_name map.markers) of
      Nothing -> map
      (Just marker) ->
         {map |
            markers = (Dict.remove marker_name map.markers),
            content =
               (Set.foldl
                  (\loc array ->
                     (Util.Array.update_unsafe
                        (location_to_index
                           (BattleMap.Struct.Location.from_ref loc)
                           map
                        )
                        (BattleMap.Struct.TileInstance.remove_trigger
                           marker_name
                        )
                        array
                     )
                  )
                  map.content
                  (BattleMap.Struct.Marker.get_locations marker)
               )
         }

add_marker : String -> BattleMap.Struct.Marker.Type -> Type -> Type
add_marker marker_name marker map =
   {map |
      markers = (Dict.insert marker_name marker map.markers),
      content =
         (Set.foldl
            (\loc array ->
               (Util.Array.update_unsafe
                  (location_to_index
                     (BattleMap.Struct.Location.from_ref loc)
                     map
                  )
                  (BattleMap.Struct.TileInstance.add_trigger marker_name)
                  array
               )
            )
            map.content
            (BattleMap.Struct.Marker.get_locations marker)
         )
   }

set_tile_to : BattleMap.Struct.Location.Type -> BattleMap.Struct.TileInstance.Type -> Type -> Type
set_tile_to loc tile_inst map =
   {map |
      content = (Array.set (location_to_index loc map) tile_inst map.content)
   }

empty : Type
empty =
   {
      width = 0,
      height = 0,
      content = (Array.empty),
      markers = (Dict.empty)
   }

new : Int -> Int -> (List BattleMap.Struct.TileInstance.Type) -> Type
new width height tiles =
   {
      width = width,
      height = height,
      content = (Array.fromList tiles),
      markers = (Dict.empty)
   }

try_getting_tile_at : (
      BattleMap.Struct.Location.Type ->
      Type ->
      (Maybe BattleMap.Struct.TileInstance.Type)
   )
try_getting_tile_at loc map =
   if (has_location loc map)
   then (Array.get (location_to_index loc map) map.content)
   else Nothing

solve_tiles : (
      (Dict.Dict BattleMap.Struct.Tile.Ref BattleMap.Struct.Tile.Type) ->
      Type ->
      Type
   )
solve_tiles tiles map =
   {map |
      content =
         (Array.map
            (BattleMap.Struct.TileInstance.solve tiles) map.content
         )
   }

get_omnimods_at : (
      BattleMap.Struct.Location.Type ->
      (Dict.Dict BattleMap.Struct.Tile.Ref BattleMap.Struct.Tile.Type) ->
      Type ->
      Battle.Struct.Omnimods.Type
   )
get_omnimods_at loc tiles_solver map =
   case (try_getting_tile_at loc map) of
      Nothing -> (Battle.Struct.Omnimods.none)
      (Just tile_inst) ->
         case
            (Dict.get
               (BattleMap.Struct.TileInstance.get_class_id tile_inst)
               tiles_solver
            )
         of
            Nothing -> (Battle.Struct.Omnimods.none)
            (Just tile) -> (BattleMap.Struct.Tile.get_omnimods tile)

decoder : (Json.Decode.Decoder Type)
decoder =
   (Json.Decode.andThen
      (\width ->
         (Json.Decode.map4
            Type
            (Json.Decode.field "w" Json.Decode.int)
            (Json.Decode.field "h" Json.Decode.int)
            (Json.Decode.field
               "t"
               (Json.Decode.map
                  (Array.indexedMap
                     (BattleMap.Struct.TileInstance.set_location_from_index
                        width
                     )
                  )
                  (Json.Decode.array (BattleMap.Struct.TileInstance.decoder))
               )
            )
            (Json.Decode.field
               "m"
               (Json.Decode.map
                  (Dict.fromList)
                  (Json.Decode.keyValuePairs
                     (BattleMap.Struct.Marker.decoder)
                  )
               )
            )
         )
      )
      (Json.Decode.field "w" Json.Decode.int)
   )

get_tile_data_function : (
      Type ->
      (List BattleMap.Struct.Location.Type) ->
      BattleMap.Struct.Location.Type ->
      BattleMap.Struct.Location.Type ->
      (Int, Int)
   )
get_tile_data_function bmap occupied_tiles start_loc loc =
   if (has_location loc bmap)
   then
      case (Array.get (location_to_index loc bmap) bmap.content) of
         (Just tile) ->
            (
               (
                  if ((loc /= start_loc) && (List.member loc occupied_tiles))
                  then Constants.Movement.cost_when_occupied_tile
                  else (BattleMap.Struct.TileInstance.get_cost tile)
               ),
               (Set.foldl
                  (\trigger dangers_count ->
                     case (Dict.get trigger bmap.markers) of
                        Nothing -> dangers_count
                        (Just marker) ->
                           if (BattleMap.Struct.Marker.is_dangerous marker)
                           then (dangers_count + 1)
                           else dangers_count
                  )
                  0
                  (BattleMap.Struct.TileInstance.get_triggers tile)
               )
            )

         Nothing -> (Constants.Movement.cost_when_out_of_bounds, 0)
   else
      (Constants.Movement.cost_when_out_of_bounds, 0)