-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmap.nim
More file actions
177 lines (160 loc) · 8.39 KB
/
map.nim
File metadata and controls
177 lines (160 loc) · 8.39 KB
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
import std/strutils
import std/options
import std/tables
import questionable
# OL imports
import core/settlement
import core/entity
import kingdom
export EntityRole # exports so `addEntity` works from elsewhere
type
Routes* = tuple[L, LU, U, RU, R, RD, D, LD: int]
# route data of nearby tiles | L = left, U = up, R = right, D = down
TileBase* = enum # used for location building conditions (see proc `canExist`) and traversability (in the future/connected with roads)
LAND
WATER
LAVA
VOID
TilePrefab* = object # it's the same as Tile, but meant to be static (not have data edited) | index is kept out so duplicates are replaced
name : string
tbase : TileBase
mov_ct : int # movement cost (base modifier)
# winter data
w_ix : int
w_mv : int
# road_ac : RoadAccess # road accessibility (left, top, right, bottom)
Tile* = object
index* : int # terrain tile index
name* : string
coords* : tuple[x, y: int]
tbase* : TileBase
mov_ct* : int # movement cost (base modifier) | -1 means unpassable // todo: is modified by roads (make proc for it)
location* : ?Location
settile* : ?SettlementTile
entities : seq[Entity] # private so it can't be accessed without proper handling (adding both to Tile and Kingdom)
# winter data
wint_ix* : int # winter tile index
wint_mv* : int # winter movement cost
# road_ac* : RoadAccess # road accessibility (left, top, right, bottom)
road* : int # whether tile has road (0 - none, 1 - dirt, 2 - rock)
roadch* : bool # whether tile was checked initially by `updateRoads`
routes* : Routes # data of nearby tiles
roaddraw* : seq[int] # seq of roads that are meant to be drawn
# road_cnn* : RoadAccess # whether nearby tiles (left, top, right, bottom) have road to connect to
#[ 'singleton' fields
road | not-bool because type can be used // also road connections (that gets updated when new road is made, but set up during initial tile creation*)
| * or actually after, because initially you won't get all tiles - probably there should be second round through `mapping` that checks for all
| nearby tiles and sets up connections, picking up sprite that has the same flags
| [tile setup however could recognise if terrain allows for road, which would be good .oldata entry]
entity |
location |]#
proc getTileBase* (id: string): TileBase =
case id.toLowerAscii():
of "land": return LAND
of "water": return WATER
of "lava": return LAVA
else: return VOID
proc canExist (t: TilePrefab, r_ix: int): int =
# checker for whether the road can exist or not
# todo: check for any(route) == true
if r_ix notin [1, 2]: return 0 # check for valid road types/existence
if t.tbase != LAND: return 0
return r_ix
proc defaultTilePrefab* (): TilePrefab =
# default values; used when there's no data available
result.name = ""
result.tbase = VOID
result.mov_ct = 0
# result.road_ac = (true, true, true, true)
proc newTilePrefab* (tbase: string, mv_cost: int, w_ix: int, w_mv: int, tname: string = ""): TilePrefab = #, road_ac: RoadAccess): TilePrefab =
result.name = tname
result.tbase = getTileBase(tbase)
result.mov_ct = mv_cost
result.w_ix = w_ix
result.w_mv = w_mv
# result.road_ac = road_ac
proc newTile* (tp: TilePrefab, ix: int, coords: tuple[x, y: int], road: int = 0): Tile = #, road: int): Tile =
# converter to allow for tile to have dynamic data under exported struct
result.index = ix
result.name = tp.name
result.coords = coords
result.tbase = tp.tbase
result.mov_ct = tp.mov_ct
result.location = Location.none # set later
result.settile = SettlementTile.none # set later
result.entities = newSeq[Entity]() # empty, use `addEntity()` proc to fill
result.road = canExist(tp, road) # 0 = no road; 1 = dirt road; 2 = rock road
result.roadch = false # TODO: if this becomes axed field (e.g. because of different way to calculate), do the same
result.routes = (0, 0, 0, 0, 0, 0, 0, 0) # default value, also TODO
result.roaddraw = newSeq[int]() # empty as default to be overwritten later when `roadch` is marked, also TODO
result.wint_ix = if tp.w_ix == -1: ix else: tp.w_ix
result.wint_mv = if tp.w_mv == -1: tp.mov_ct else: tp.w_mv # TODO: MV SHOULD BE NOT THE TILE WE HAVE PREFAB OF, BUT ONE WITH tp.w_ix!! (needs Table for this)
# todo: ...but this also means we would need to run this after we initiate all tiles?
# todo: ...so maybe we would need other value to indicate temporary tile? (like -2 or whatever?)
#result.road_ac = tp.road_ac
proc newTile* (oldata: OrderedTable[int, TilePrefab], ix: int, coords: tuple[x, y: int], road: int = 0): Tile =
# converted that yields singular tile data from TilePrefab table
if ix in oldata:
return newTile(oldata[ix], ix, coords, road)#, 0) # todo: 0 is temporary
return newTile(defaultTilePrefab(), ix, coords, road)#, 0) # as above
proc hasObject* (t: Tile): bool =
# checks whether tile is occupied by location or settlement
return isSome(t.location) or isSome(t.settile)
proc canExist* (t: Tile, l: Location | LocationPrefab): bool =
# proc to see if tile can have location built (it is *not* about traversability)
if t.tbase == TileBase.VOID: return false # void can't have any location existing
# non-void cases
case l.bcond:
of BuildingConditions.LAND:
if t.tbase == TileBase.LAND: return true
of BuildingConditions.WATER:
if t.tbase == TileBase.WATER: return true
of BuildingConditions.SUBMERGED:
if t.tbase in [TileBase.LAND, TileBase.WATER]: return true
of BuildingConditions.AIR:
if t.tbase in [TileBase.LAND, TileBase.WATER, TileBase.LAVA]: return true
of BuildingConditions.ALL: return true
of BuildingConditions.NONE: return false
return false # if any catches earlier for true are not met
proc canSettlementExist* (t: Tile): bool =
# for settlements
if t.tbase == LAND: return true
return false
proc canStand* (t: Tile, er: EntityRole): bool =
# checks whether the entity can exist on particular tile (it is *not* about traversability)
case t.tbase:
of TileBase.VOID: return false # is not traversed by anything
of TileBase.LAND:
return er in LAND_ENTITY
of TileBase.WATER:
return er in WATER_ENTITY
of TileBase.LAVA: return false
#if er in []: return true | todo: uncheck when there's air/lava entities
return false # if any catches earlier for true are not met
proc addEntity* (t: var Tile, k: var Kingdom, er: EntityRole): bool =
# also works as a constructor; return false if entity can't be made
if canStand(t, er):
var e = newEntity(er, k.number)
t.entities.add(e)
k.entities.add(e)
return true
return false
proc addLocation* (t: var Tile, k: var Kingdom, l: LocationPrefab, ix: int): bool =
if not hasObject(t) and canExist(t, l):
t.location = newLocation(l, ix, k.number).some
k.locations.add(t.coords)
return true
return false
proc addSettlement* (t: var Tile, k: var Kingdom, name: string = generateRandomName()): bool =
if not hasObject(t) and canSettlementExist(t): # checks if tile is occupied + if settlement can be put
let stt = newSettlementTile(t.coords)
let stm = newSettlement(name, @[stt], k.number)
t.settile = stt.some # binds SettlementTile to Tile
k.settlems.add(stm) # binds Settlement to Kingdom
return true
return false
proc getEntityList* (t: Tile): seq[Entity] = # todo: ensure you can't add to t.entities, so that seq is read-only (and/or you can only edit its Entity refs)
return t.entities
# proc canBuildRoad* (t: Tile | TilePrefab): bool =
# # check if any of RoadAccess sides are available (none = not possible to build road)
# any(t.road_ac, proc (s: bool): bool = s == true)