1 #include "road_access.h"
2
3 #include "building/building.h"
4 #include "building/roadblock.h"
5 #include "building/rotation.h"
6 #include "core/config.h"
7 #include "city/map.h"
8 #include "map/building.h"
9 #include "map/grid.h"
10 #include "map/property.h"
11 #include "map/road_network.h"
12 #include "map/routing.h"
13 #include "map/routing_terrain.h"
14 #include "map/terrain.h"
15
find_minimum_road_tile(int x,int y,int size,int * min_value,int * min_grid_offset)16 static void find_minimum_road_tile(int x, int y, int size, int *min_value, int *min_grid_offset)
17 {
18 int base_offset = map_grid_offset(x, y);
19 for (const int *tile_delta = map_grid_adjacent_offsets(size); *tile_delta; tile_delta++) {
20 int grid_offset = base_offset + *tile_delta;
21 if (!map_terrain_is(grid_offset, TERRAIN_BUILDING) ||
22 building_get(map_building_at(grid_offset))->type != BUILDING_GATEHOUSE) {
23 if (map_terrain_is(grid_offset, TERRAIN_ROAD)) {
24 if (building_type_is_roadblock(building_get(map_building_at(grid_offset))->type)) {
25 continue;
26 }
27 int road_index = city_map_road_network_index(map_road_network_get(grid_offset));
28 if (road_index < *min_value) {
29 *min_value = road_index;
30 *min_grid_offset = grid_offset;
31 }
32 }
33 }
34 }
35 }
36
map_has_road_access(int x,int y,int size,map_point * road)37 int map_has_road_access(int x, int y, int size, map_point *road)
38 {
39 return map_has_road_access_rotation(0, x, y, size, road);
40 }
41
map_has_road_access_rotation(int rotation,int x,int y,int size,map_point * road)42 int map_has_road_access_rotation(int rotation, int x, int y, int size, map_point *road)
43 {
44 switch (rotation) {
45 case 3:
46 x = x - size + 1;
47 break;
48 case 2:
49 x = x - size + 1;
50 y = y - size + 1;
51 break;
52 case 1:
53 y = y - size + 1;
54 break;
55 default:
56 break;
57 }
58 int min_value = 12;
59 int min_grid_offset = map_grid_offset(x, y);
60 find_minimum_road_tile(x, y, size, &min_value, &min_grid_offset);
61 if (min_value < 12) {
62 if (road) {
63 map_point_store_result(map_grid_offset_to_x(min_grid_offset),
64 map_grid_offset_to_y(min_grid_offset), road);
65 }
66 return 1;
67 }
68 return 0;
69 }
70
map_has_road_access_hippodrome_rotation(int x,int y,map_point * road,int rotation)71 int map_has_road_access_hippodrome_rotation(int x, int y, map_point *road, int rotation)
72 {
73 int min_value = 12;
74 int min_grid_offset = map_grid_offset(x, y);
75 int x_offset, y_offset;
76 building_rotation_get_offset_with_rotation(5, rotation, &x_offset, &y_offset);
77 find_minimum_road_tile(x, y, 5, &min_value, &min_grid_offset);
78 find_minimum_road_tile(x + x_offset, y + y_offset, 5, &min_value, &min_grid_offset);
79 building_rotation_get_offset_with_rotation(10, rotation, &x_offset, &y_offset);
80 find_minimum_road_tile(x + x_offset, y + y_offset, 5, &min_value, &min_grid_offset);
81 if (min_value < 12) {
82 if (road) {
83 map_point_store_result(map_grid_offset_to_x(min_grid_offset), map_grid_offset_to_y(min_grid_offset), road);
84 }
85 return 1;
86 }
87 return 0;
88 }
89
map_has_road_access_hippodrome(int x,int y,map_point * road)90 int map_has_road_access_hippodrome(int x, int y, map_point *road)
91 {
92 return map_has_road_access_hippodrome_rotation(x, y, road, building_rotation_get_rotation());
93 }
94
map_has_road_access_granary(int x,int y,map_point * road)95 int map_has_road_access_granary(int x, int y, map_point *road)
96 {
97 int rx = -1, ry = -1;
98 if (map_terrain_is(map_grid_offset(x + 1, y - 1), TERRAIN_ROAD) &&
99 (!building_type_is_roadblock(building_get(map_building_at(map_grid_offset(x + 1, y - 1)))->type))) {
100 rx = x + 1;
101 ry = y - 1;
102 } else if (map_terrain_is(map_grid_offset(x + 3, y + 1), TERRAIN_ROAD) &&
103 (!building_type_is_roadblock(building_get(map_building_at(map_grid_offset(x + 3, y + 1)))->type ))) {
104 rx = x + 3;
105 ry = y + 1;
106 } else if (map_terrain_is(map_grid_offset(x + 1, y + 3), TERRAIN_ROAD) &&
107 (!building_type_is_roadblock(building_get(map_building_at(map_grid_offset(x + 1, y + 3)))->type))) {
108 rx = x + 1;
109 ry = y + 3;
110 } else if (map_terrain_is(map_grid_offset(x - 1, y + 1), TERRAIN_ROAD) &&
111 (!building_type_is_roadblock(building_get(map_building_at(map_grid_offset(x - 1, y + 1)))->type))) {
112 rx = x - 1;
113 ry = y + 1;
114 }
115 if (rx >= 0 && ry >= 0) {
116 if (road) {
117 map_point_store_result(rx, ry, road);
118 }
119 return 1;
120 }
121 return 0;
122 }
123
map_has_road_access_monument_size7(int x,int y,map_point * road)124 int map_has_road_access_monument_size7(int x, int y, map_point *road)
125 {
126 int min_value = 12;
127 int min_grid_offset = map_grid_offset(x, y);
128 find_minimum_road_tile(x, y + 3, 1, &min_value, &min_grid_offset);
129 find_minimum_road_tile(x + 3, y, 1, &min_value, &min_grid_offset);
130 find_minimum_road_tile(x + 3, y + 6, 1, &min_value, &min_grid_offset);
131 find_minimum_road_tile(x + 6, y + 3, 1, &min_value, &min_grid_offset);
132
133 if (min_value < 12) {
134 if (road) {
135 map_point_store_result(map_grid_offset_to_x(min_grid_offset), map_grid_offset_to_y(min_grid_offset), road);
136 }
137 return 1;
138 }
139 return 0;
140 }
141
map_has_road_access_monument_size5(int x,int y,map_point * road)142 int map_has_road_access_monument_size5(int x, int y, map_point *road)
143 {
144 int min_value = 12;
145 int min_grid_offset = map_grid_offset(x, y);
146 find_minimum_road_tile(x, y + 2, 1, &min_value, &min_grid_offset);
147 find_minimum_road_tile(x + 2, y, 1, &min_value, &min_grid_offset);
148 find_minimum_road_tile(x + 2, y + 4, 1, &min_value, &min_grid_offset);
149 find_minimum_road_tile(x + 4, y + 2, 1, &min_value, &min_grid_offset);
150 if (min_value < 12) {
151 if (road) {
152 map_point_store_result(map_grid_offset_to_x(min_grid_offset), map_grid_offset_to_y(min_grid_offset), road);
153 }
154 return 1;
155 }
156 return 0;
157 }
158
map_has_road_access_monument_size3(int x,int y,map_point * road)159 int map_has_road_access_monument_size3(int x, int y, map_point *road)
160 {
161 int min_value = 12;
162 int min_grid_offset = map_grid_offset(x, y);
163 find_minimum_road_tile(x, y + 1, 1, &min_value, &min_grid_offset);
164 find_minimum_road_tile(x + 1, y, 1, &min_value, &min_grid_offset);
165 find_minimum_road_tile(x + 1, y + 2, 1, &min_value, &min_grid_offset);
166 find_minimum_road_tile(x + 2, y + 1, 1, &min_value, &min_grid_offset);
167 if (min_value < 12) {
168 if (road) {
169 map_point_store_result(map_grid_offset_to_x(min_grid_offset), map_grid_offset_to_y(min_grid_offset), road);
170 }
171 return 1;
172 }
173 return 0;
174 }
175
map_has_road_access_monument_size4(int x,int y,map_point * road)176 int map_has_road_access_monument_size4(int x, int y, map_point *road)
177 {
178 int min_value = 12;
179 int min_grid_offset = map_grid_offset(x, y);
180 find_minimum_road_tile(x + 1, y + 3, 1, &min_value, &min_grid_offset);
181 find_minimum_road_tile(x + 2, y + 3, 1, &min_value, &min_grid_offset);
182 find_minimum_road_tile(x + 3, y + 1, 1, &min_value, &min_grid_offset);
183 find_minimum_road_tile(x + 3, y + 2, 1, &min_value, &min_grid_offset);
184 find_minimum_road_tile(x, y + 1, 1, &min_value, &min_grid_offset);
185 find_minimum_road_tile(x, y + 2, 1, &min_value, &min_grid_offset);
186 find_minimum_road_tile(x + 1, y, 1, &min_value, &min_grid_offset);
187 find_minimum_road_tile(x + 2, y, 1, &min_value, &min_grid_offset);
188
189
190 if (min_value < 12) {
191 if (road) {
192 map_point_store_result(map_grid_offset_to_x(min_grid_offset), map_grid_offset_to_y(min_grid_offset), road);
193 }
194 return 1;
195 }
196 return 0;
197 }
198
road_within_radius(int x,int y,int size,int radius,int * x_road,int * y_road)199 static int road_within_radius(int x, int y, int size, int radius, int *x_road, int *y_road)
200 {
201 int x_min, y_min, x_max, y_max;
202 map_grid_get_area(x, y, size, radius, &x_min, &y_min, &x_max, &y_max);
203
204 for (int yy = y_min; yy <= y_max; yy++) {
205 for (int xx = x_min; xx <= x_max; xx++) {
206 if (map_terrain_is(map_grid_offset(xx, yy), TERRAIN_ROAD)) {
207 // Don't spawn walkers on roadblocks
208 if (building_type_is_roadblock(building_get(map_building_at(map_grid_offset(xx, yy)))->type)) {
209 continue;
210 }
211 if (x_road && y_road) {
212 *x_road = xx;
213 *y_road = yy;
214 }
215 return 1;
216 }
217 }
218 }
219 return 0;
220 }
221
map_closest_road_within_radius(int x,int y,int size,int radius,int * x_road,int * y_road)222 int map_closest_road_within_radius(int x, int y, int size, int radius, int *x_road, int *y_road)
223 {
224 for (int r = 1; r <= radius; r++) {
225 if (road_within_radius(x, y, size, r, x_road, y_road)) {
226 return 1;
227 }
228 }
229 return 0;
230 }
231
reachable_road_within_radius(int x,int y,int size,int radius,int * x_road,int * y_road)232 static int reachable_road_within_radius(int x, int y, int size, int radius, int *x_road, int *y_road)
233 {
234 int x_min, y_min, x_max, y_max;
235 map_grid_get_area(x, y, size, radius, &x_min, &y_min, &x_max, &y_max);
236
237 for (int yy = y_min; yy <= y_max; yy++) {
238 for (int xx = x_min; xx <= x_max; xx++) {
239 int grid_offset = map_grid_offset(xx, yy);
240 if (map_terrain_is(grid_offset, TERRAIN_ROAD)) {
241 if (map_routing_distance(grid_offset) > 0) {
242 if (x_road && y_road) {
243 *x_road = xx;
244 *y_road = yy;
245 }
246 return 1;
247 }
248 }
249 }
250 }
251 return 0;
252 }
253
map_closest_reachable_road_within_radius(int x,int y,int size,int radius,int * x_road,int * y_road)254 int map_closest_reachable_road_within_radius(int x, int y, int size, int radius, int *x_road, int *y_road)
255 {
256 for (int r = 1; r <= radius; r++) {
257 if (reachable_road_within_radius(x, y, size, r, x_road, y_road)) {
258 return 1;
259 }
260 }
261 return 0;
262 }
263
map_road_to_largest_network_rotation(int rotation,int x,int y,int size,int * x_road,int * y_road)264 int map_road_to_largest_network_rotation(int rotation, int x, int y, int size, int *x_road, int *y_road)
265 {
266 switch (rotation) {
267 case 1:
268 x = x - size + 1;
269 break;
270 case 2:
271 x = x - size + 1;
272 y = y - size + 1;
273 break;
274 case 3:
275 y = y - size + 1;
276 break;
277 default:
278 break;
279 }
280 int min_index = 12;
281 int min_grid_offset = -1;
282 int base_offset = map_grid_offset(x, y);
283 for (const int *tile_delta = map_grid_adjacent_offsets(size); *tile_delta; tile_delta++) {
284 int grid_offset = base_offset + *tile_delta;
285 if (map_terrain_is(grid_offset, TERRAIN_ROAD) && map_routing_distance(grid_offset) > 0) {
286 int index = city_map_road_network_index(map_road_network_get(grid_offset));
287 if (index < min_index) {
288 min_index = index;
289 min_grid_offset = grid_offset;
290 }
291 }
292 }
293 if (min_index < 12) {
294 *x_road = map_grid_offset_to_x(min_grid_offset);
295 *y_road = map_grid_offset_to_y(min_grid_offset);
296 return min_grid_offset;
297 }
298 int min_dist = 100000;
299 min_grid_offset = -1;
300 for (const int *tile_delta = map_grid_adjacent_offsets(size); *tile_delta; tile_delta++) {
301 int grid_offset = base_offset + *tile_delta;
302 int dist = map_routing_distance(grid_offset);
303 if (dist > 0 && dist < min_dist) {
304 min_dist = dist;
305 min_grid_offset = grid_offset;
306 }
307 }
308 if (min_grid_offset >= 0) {
309 *x_road = map_grid_offset_to_x(min_grid_offset);
310 *y_road = map_grid_offset_to_y(min_grid_offset);
311 return min_grid_offset;
312 }
313 return -1;
314 }
map_road_to_largest_network(int x,int y,int size,int * x_road,int * y_road)315 int map_road_to_largest_network(int x, int y, int size, int *x_road, int *y_road)
316 {
317 return map_road_to_largest_network_rotation(0, x, y, size, x_road, y_road);
318 }
319
check_road_to_largest_network_hippodrome(int x,int y,int * min_index,int * min_grid_offset)320 static void check_road_to_largest_network_hippodrome(int x, int y, int *min_index, int *min_grid_offset)
321 {
322 int base_offset = map_grid_offset(x, y);
323 for (const int *tile_delta = map_grid_adjacent_offsets(5); *tile_delta; tile_delta++) {
324 int grid_offset = base_offset + *tile_delta;
325 if (map_terrain_is(grid_offset, TERRAIN_ROAD) && map_routing_distance(grid_offset) > 0) {
326 int index = city_map_road_network_index(map_road_network_get(grid_offset));
327 if (index < *min_index) {
328 *min_index = index;
329 *min_grid_offset = grid_offset;
330 }
331 }
332 }
333 }
334
335
check_min_dist_hippodrome(int base_offset,int x_offset,int * min_dist,int * min_grid_offset,int * min_x_offset)336 static void check_min_dist_hippodrome(int base_offset, int x_offset,
337 int *min_dist, int *min_grid_offset, int *min_x_offset)
338 {
339 for (const int *tile_delta = map_grid_adjacent_offsets(5); *tile_delta; tile_delta++) {
340 int grid_offset = base_offset + *tile_delta;
341 int dist = map_routing_distance(grid_offset);
342 if (dist > 0 && dist < *min_dist) {
343 *min_dist = dist;
344 *min_grid_offset = grid_offset;
345 *min_x_offset = x_offset;
346 }
347 }
348 }
349
map_road_to_largest_network_hippodrome(int x,int y,int * x_road,int * y_road,int rotated)350 int map_road_to_largest_network_hippodrome(int x, int y, int *x_road, int *y_road, int rotated)
351 {
352 int min_index = 12;
353 int min_grid_offset = -1;
354 if (rotated) {
355 check_road_to_largest_network_hippodrome(x, y, &min_index, &min_grid_offset);
356 check_road_to_largest_network_hippodrome(x, y + 5, &min_index, &min_grid_offset);
357 check_road_to_largest_network_hippodrome(x, y + 10, &min_index, &min_grid_offset);
358 } else {
359 check_road_to_largest_network_hippodrome(x, y, &min_index, &min_grid_offset);
360 check_road_to_largest_network_hippodrome(x + 5, y, &min_index, &min_grid_offset);
361 check_road_to_largest_network_hippodrome(x + 10, y, &min_index, &min_grid_offset);
362 }
363
364 if (min_index < 12) {
365 *x_road = map_grid_offset_to_x(min_grid_offset);
366 *y_road = map_grid_offset_to_y(min_grid_offset);
367 return min_grid_offset;
368 }
369
370 int min_dist = 100000;
371 min_grid_offset = -1;
372 int min_x_offset = -1;
373 if (rotated) {
374 check_min_dist_hippodrome(map_grid_offset(x, y), 0, &min_dist, &min_grid_offset, &min_x_offset);
375 check_min_dist_hippodrome(map_grid_offset(x, y + 5), 5, &min_dist, &min_grid_offset, &min_x_offset);
376 check_min_dist_hippodrome(map_grid_offset(x, y + 10), 10, &min_dist, &min_grid_offset, &min_x_offset);
377 } else {
378 check_min_dist_hippodrome(map_grid_offset(x, y), 0, &min_dist, &min_grid_offset, &min_x_offset);
379 check_min_dist_hippodrome(map_grid_offset(x + 5, y), 5, &min_dist, &min_grid_offset, &min_x_offset);
380 check_min_dist_hippodrome(map_grid_offset(x + 10, y), 10, &min_dist, &min_grid_offset, &min_x_offset);
381 }
382 if (min_grid_offset >= 0) {
383 *x_road = map_grid_offset_to_x(min_grid_offset) + min_x_offset;
384 *y_road = map_grid_offset_to_y(min_grid_offset);
385 return min_grid_offset + min_x_offset;
386 }
387 return -1;
388 }
389
check_road_to_largest_network_monument(int x,int y,int * min_index,int * min_grid_offset)390 static void check_road_to_largest_network_monument(int x, int y, int *min_index, int *min_grid_offset)
391 {
392 int base_offset = map_grid_offset(x, y);
393 for (const int *tile_delta = map_grid_adjacent_offsets(1); *tile_delta; tile_delta++) {
394 int grid_offset = base_offset + *tile_delta;
395 if (map_terrain_is(grid_offset, TERRAIN_ROAD) && map_routing_distance(grid_offset) > 0) {
396 int index = city_map_road_network_index(map_road_network_get(grid_offset));
397 if (index < *min_index) {
398 *min_index = index;
399 *min_grid_offset = grid_offset;
400 }
401 }
402 }
403 }
404
map_road_to_largest_network_grand_temple(int x,int y,int * x_road,int * y_road)405 int map_road_to_largest_network_grand_temple(int x, int y, int *x_road, int *y_road)
406 {
407 int min_index = 12;
408 int min_grid_offset = -1;
409 check_road_to_largest_network_monument(x + 3, y + 6, &min_index, &min_grid_offset);
410 check_road_to_largest_network_monument(x + 6, y + 3, &min_index, &min_grid_offset);
411 check_road_to_largest_network_monument(x + 3, y, &min_index, &min_grid_offset);
412 check_road_to_largest_network_monument(x, y + 3, &min_index, &min_grid_offset);
413
414 if (min_index < 12) {
415 *x_road = map_grid_offset_to_x(min_grid_offset);
416 *y_road = map_grid_offset_to_y(min_grid_offset);
417 return min_grid_offset;
418 }
419
420 return -1;
421 }
422
map_road_to_largest_network_colosseum(int x,int y,int * x_road,int * y_road)423 int map_road_to_largest_network_colosseum(int x, int y, int *x_road, int *y_road)
424 {
425 int min_index = 12;
426 int min_grid_offset = -1;
427 check_road_to_largest_network_monument(x + 2, y + 4, &min_index, &min_grid_offset);
428 check_road_to_largest_network_monument(x + 4, y + 2, &min_index, &min_grid_offset);
429 check_road_to_largest_network_monument(x + 2, y, &min_index, &min_grid_offset);
430 check_road_to_largest_network_monument(x, y + 2, &min_index, &min_grid_offset);
431
432 if (min_index < 12) {
433 *x_road = map_grid_offset_to_x(min_grid_offset);
434 *y_road = map_grid_offset_to_y(min_grid_offset);
435 return min_grid_offset;
436 }
437
438 return -1;
439 }
440
map_road_to_largest_network_lighthouse(int x,int y,int * x_road,int * y_road)441 int map_road_to_largest_network_lighthouse(int x, int y, int *x_road, int *y_road)
442 {
443 int min_index = 12;
444 int min_grid_offset = -1;
445 check_road_to_largest_network_monument(x + 1, y, &min_index, &min_grid_offset);
446 check_road_to_largest_network_monument(x, y + 1, &min_index, &min_grid_offset);
447 check_road_to_largest_network_monument(x + 2, y + 1, &min_index, &min_grid_offset);
448 check_road_to_largest_network_monument(x + 1, y + 2, &min_index, &min_grid_offset);
449
450 if (min_index < 12) {
451 *x_road = map_grid_offset_to_x(min_grid_offset);
452 *y_road = map_grid_offset_to_y(min_grid_offset);
453 return min_grid_offset;
454 }
455
456 return -1;
457 }
458
map_road_to_largest_network_caravanserai(int x,int y,int * x_road,int * y_road)459 int map_road_to_largest_network_caravanserai(int x, int y, int *x_road, int *y_road)
460 {
461 int min_index = 12;
462 int min_grid_offset = -1;
463 check_road_to_largest_network_monument(x + 1, y + 3, &min_index, &min_grid_offset);
464 check_road_to_largest_network_monument(x + 2, y + 3, &min_index, &min_grid_offset);
465 check_road_to_largest_network_monument(x + 3, y + 1, &min_index, &min_grid_offset);
466 check_road_to_largest_network_monument(x + 3, y + 2, &min_index, &min_grid_offset);
467 check_road_to_largest_network_monument(x + 1, y, &min_index, &min_grid_offset);
468 check_road_to_largest_network_monument(x + 2, y, &min_index, &min_grid_offset);
469 check_road_to_largest_network_monument(x, y + 1, &min_index, &min_grid_offset);
470 check_road_to_largest_network_monument(x, y + 2, &min_index, &min_grid_offset);
471
472 if (min_index < 12) {
473 *x_road = map_grid_offset_to_x(min_grid_offset);
474 *y_road = map_grid_offset_to_y(min_grid_offset);
475 return min_grid_offset;
476 }
477
478 return -1;
479 }
480
terrain_is_road_like(int grid_offset)481 static int terrain_is_road_like(int grid_offset)
482 {
483 return map_terrain_is(grid_offset, TERRAIN_ROAD | TERRAIN_ACCESS_RAMP) ? 1 : 0;
484 }
485
get_adjacent_road_tile_for_roaming(int grid_offset,roadblock_permission perm)486 static int get_adjacent_road_tile_for_roaming(int grid_offset, roadblock_permission perm)
487 {
488 int is_road = terrain_is_road_like(grid_offset);
489 if (map_terrain_is(grid_offset, TERRAIN_BUILDING)) {
490 building *b = building_get(map_building_at(grid_offset));
491 if (b->type == BUILDING_GATEHOUSE) {
492 is_road = 0;
493 } else if (building_type_is_roadblock(b->type)) {
494 if (!building_roadblock_get_permission(perm, b)) {
495 is_road = 0;
496 }
497 } else if (b->type == BUILDING_GRANARY) {
498 if (map_routing_citizen_is_road(grid_offset)) {
499 if (map_property_multi_tile_xy(grid_offset) == EDGE_X1Y1 ||
500 map_has_adjacent_road_tiles(grid_offset) || map_has_adjacent_granary_road(grid_offset)) {
501 is_road = 1;
502 }
503 }
504 } else if (b->type == BUILDING_TRIUMPHAL_ARCH) {
505 if (map_routing_citizen_is_road(grid_offset)) {
506 is_road = 1;
507 }
508 }
509 }
510 return is_road;
511 }
512
map_get_adjacent_road_tiles_for_roaming(int grid_offset,int * road_tiles,int perm)513 int map_get_adjacent_road_tiles_for_roaming(int grid_offset, int *road_tiles, int perm)
514 {
515 road_tiles[1] = road_tiles[3] = road_tiles[5] = road_tiles[7] = 0;
516
517 road_tiles[0] = get_adjacent_road_tile_for_roaming(grid_offset + map_grid_delta(0, -1), perm);
518 road_tiles[2] = get_adjacent_road_tile_for_roaming(grid_offset + map_grid_delta(1, 0), perm);
519 road_tiles[4] = get_adjacent_road_tile_for_roaming(grid_offset + map_grid_delta(0, 1), perm);
520 road_tiles[6] = get_adjacent_road_tile_for_roaming(grid_offset + map_grid_delta(-1, 0), perm);
521
522 return road_tiles[0] + road_tiles[2] + road_tiles[4] + road_tiles[6];
523 }
524
map_get_diagonal_road_tiles_for_roaming(int grid_offset,int * road_tiles)525 int map_get_diagonal_road_tiles_for_roaming(int grid_offset, int *road_tiles)
526 {
527 road_tiles[1] = terrain_is_road_like(grid_offset + map_grid_delta(1, -1));
528 road_tiles[3] = terrain_is_road_like(grid_offset + map_grid_delta(1, 1));
529 road_tiles[5] = terrain_is_road_like(grid_offset + map_grid_delta(-1, 1));
530 road_tiles[7] = terrain_is_road_like(grid_offset + map_grid_delta(-1, -1));
531
532 int max_stretch = 0;
533 int stretch = 0;
534 for (int i = 0; i < 16; i++) {
535 if (road_tiles[i % 8]) {
536 stretch++;
537 if (stretch > max_stretch) {
538 max_stretch = stretch;
539 }
540 } else {
541 stretch = 0;
542 }
543 }
544 return max_stretch;
545 }
546
map_has_adjacent_road_tiles(int grid_offset)547 int map_has_adjacent_road_tiles(int grid_offset)
548 {
549 int tiles[4];
550 tiles[0] = grid_offset + map_grid_delta(0, -1);
551 tiles[1] = grid_offset + map_grid_delta(1, 0);
552 tiles[2] = grid_offset + map_grid_delta(0, 1);
553 tiles[3] = grid_offset + map_grid_delta(-1, 0);
554 int adjacent_roads = 0;
555 for (int i = 0; i < 4; i++) {
556 building *b = building_get(map_building_at(tiles[i]));
557 if (!building_type_is_roadblock(b->type)) {
558 adjacent_roads += terrain_is_road_like(tiles[i]);
559 }
560 }
561 return adjacent_roads;
562 }
563
map_has_adjacent_granary_road(int grid_offset)564 int map_has_adjacent_granary_road(int grid_offset)
565 {
566 int tiles[4];
567 tiles[0] = grid_offset + map_grid_delta(0, -1);
568 tiles[1] = grid_offset + map_grid_delta(1, 0);
569 tiles[2] = grid_offset + map_grid_delta(0, 1);
570 tiles[3] = grid_offset + map_grid_delta(-1, 0);
571 for (int i = 0; i < 4; i++) {
572 if (building_get(map_building_at(tiles[i]))->type != BUILDING_GRANARY) {
573 continue;
574 }
575 switch (map_property_multi_tile_xy(tiles[i])) {
576 case EDGE_X1Y0:
577 case EDGE_X0Y1:
578 case EDGE_X2Y1:
579 case EDGE_X1Y2:
580 return 1;
581 }
582 }
583 return 0;
584 }
585