Freeciv-3.3
Loading...
Searching...
No Matches
terrain.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2003 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "fcintl.h"
20#include "log.h" /* fc_assert */
21#include "mem.h" /* free */
22#include "rand.h"
23#include "shared.h"
24#include "string_vector.h"
25#include "support.h"
26
27/* common */
28#include "extras.h"
29#include "game.h"
30#include "map.h"
31#include "rgbcolor.h"
32#include "road.h"
33
34#include "terrain.h"
35
38
39/**********************************************************************/
42void terrains_init(void)
43{
44 int i;
45
46 for (i = 0; i < ARRAY_SIZE(civ_terrains); i++) {
47 int j;
48
49 /* Can't use terrain_by_number here because it does a bounds check. */
55
56 for (j = 0; j < MAX_EXTRA_TYPES; j++) {
58 }
59 }
60}
61
62/**********************************************************************/
65void terrains_free(void)
66{
67 terrain_type_iterate(pterrain) {
68 if (NULL != pterrain->helptext) {
69 strvec_destroy(pterrain->helptext);
70 pterrain->helptext = NULL;
71 }
72 if (pterrain->resources != NULL) {
73 /* Server allocates this on ruleset loading, client when
74 * ruleset packet is received. */
75 free(pterrain->resources);
76 pterrain->resources = NULL;
77 }
78 if (pterrain->resource_freq != NULL) {
79 /* Server allocates this on ruleset loading, client when
80 * ruleset packet is received. */
81 free(pterrain->resource_freq);
82 pterrain->resource_freq = NULL;
83 }
84 if (pterrain->rgb != NULL) {
85 /* Server allocates this on ruleset loading, client when
86 * ruleset packet is received. */
87 rgbcolor_destroy(pterrain->rgb);
88 pterrain->rgb = NULL;
89 }
91}
92
93/**********************************************************************/
97{
98 if (game.control.terrain_count > 0) {
99 return civ_terrains;
100 }
101 return NULL;
102}
103
104/**********************************************************************/
107const struct terrain *terrain_array_last(void)
108{
109 if (game.control.terrain_count > 0) {
111 }
112 return NULL;
113}
114
115/**********************************************************************/
122
123/**********************************************************************/
126char terrain_identifier(const struct terrain *pterrain)
127{
128 fc_assert_ret_val(pterrain, '\0');
129 return pterrain->identifier;
130}
131
132/**********************************************************************/
138Terrain_type_id terrain_index(const struct terrain *pterrain)
139{
140 fc_assert_ret_val(pterrain, -1);
141 return pterrain - civ_terrains;
142}
143
144/**********************************************************************/
148{
149 fc_assert_ret_val(pterrain, -1);
150 return pterrain->item_number;
151}
152
153/**********************************************************************/
157{
159 /* This isn't an error; some T_UNKNOWN callers depend on it. */
160 return NULL;
161 }
162 return &civ_terrains[type];
163}
164
165/**********************************************************************/
170{
172 return T_UNKNOWN;
173 }
174 terrain_type_iterate(pterrain) {
175 if (pterrain->identifier == identifier) {
176 return pterrain;
177 }
179
180 return T_UNKNOWN;
181}
182
183/**********************************************************************/
187{
188 const char *qname = Qn_(name);
189
190 terrain_type_iterate(pterrain) {
191 if (0 == fc_strcasecmp(terrain_rule_name(pterrain), qname)) {
192 return pterrain;
193 }
195
196 return T_UNKNOWN;
197}
198
199/**********************************************************************/
203{
204 terrain_type_iterate(pterrain) {
205 if (0 == strcmp(terrain_name_translation(pterrain), name)) {
206 return pterrain;
207 }
209
210 return T_UNKNOWN;
211}
212
213/**********************************************************************/
218{
219 int num = 0;
220 struct terrain *terr = NULL;
221
223 if (terrain_has_flag(pterr, flag)) {
224 num++;
225 if (fc_rand(num) == 1) {
226 terr = pterr;
227 }
228 }
230
231 return terr;
232}
233
234/**********************************************************************/
238const char *terrain_name_translation(const struct terrain *pterrain)
239{
240 return name_translation_get(&pterrain->name);
241}
242
243/**********************************************************************/
247const char *terrain_rule_name(const struct terrain *pterrain)
248{
249 return rule_name_get(&pterrain->name);
250}
251
252/**********************************************************************/
255bool terrain_has_resource(const struct terrain *pterrain,
256 const struct extra_type *presource)
257{
258 struct extra_type **r = pterrain->resources;
259
260 while (NULL != *r) {
261 if (*r == presource) {
262 return TRUE;
263 }
264 r++;
265 }
266 return FALSE;
267}
268
269/**********************************************************************/
273{
274 struct resource_type *presource;
275
276 presource = fc_malloc(sizeof(*presource));
277
278 pextra->data.resource = presource;
279
280 presource->self = pextra;
281
282 return presource;
283}
284
285/**********************************************************************/
289{
290 /* Resource structure itself is freed as part of extras destruction. */
291}
292
293/**********************************************************************/
296struct extra_type *resource_extra_get(const struct resource_type *presource)
297{
298 return presource->self;
299}
300
301/**********************************************************************/
305#define variable_adjc_iterate(nmap, center_tile, _tile, card_only) \
306{ \
307 enum direction8 *_tile##_list; \
308 int _tile##_count; \
309 \
310 if (card_only) { \
311 _tile##_list = MAP_CARDINAL_DIRS; \
312 _tile##_count = MAP_NUM_CARDINAL_DIRS; \
313 } else { \
314 _tile##_list = MAP_VALID_DIRS; \
315 _tile##_count = MAP_NUM_VALID_DIRS; \
316 } \
317 adjc_dirlist_iterate(nmap, center_tile, _tile, _tile##_dir, \
318 _tile##_list, _tile##_count) {
319
320#define variable_adjc_iterate_end \
321 } adjc_dirlist_iterate_end; \
322}
323
324/**********************************************************************/
328 const struct tile *ptile,
329 const struct terrain *pterrain,
330 bool check_self)
331{
332 if (pterrain == NULL) {
333 return FALSE;
334 }
335
337 if (tile_terrain(adjc_tile) == pterrain) {
338 return TRUE;
339 }
341
342 return check_self && ptile->terrain == pterrain;
343}
344
345/**********************************************************************/
349 const struct tile *ptile,
350 const struct terrain *pterrain,
351 bool check_self)
352{
353 if (pterrain == NULL) {
354 return FALSE;
355 }
356
357 adjc_iterate(nmap, ptile, adjc_tile) {
358 if (tile_terrain(adjc_tile) == pterrain) {
359 return TRUE;
360 }
362
363 return check_self && ptile->terrain == pterrain;
364}
365
366/**********************************************************************/
370 const struct tile *ptile,
371 bool cardinal_only, bool percentage,
373{
374 int count = 0, total = 0;
375
377 struct terrain *pterrain = tile_terrain(adjc_tile);
378
379 if (pterrain->property[prop] > 0) {
380 count++;
381 }
382 total++;
384
385 if (percentage && count > 0) { /* Latter condition avoids div by zero */
386 count = count * 100 / total;
387 }
388
389 return count;
390}
391
392/**********************************************************************/
396 const struct tile *ptile,
397 const struct extra_type *pres,
398 bool check_self)
399{
400 if (pres == NULL) {
401 return FALSE;
402 }
403
405 if (tile_resource(adjc_tile) == pres) {
406 return TRUE;
407 }
409
410 return check_self && tile_resource(ptile) == pres;
411}
412
413/**********************************************************************/
417 const struct tile *ptile,
418 const struct extra_type *pres,
419 bool check_self)
420{
421 if (pres == NULL) {
422 return FALSE;
423 }
424
425 adjc_iterate(nmap, ptile, adjc_tile) {
426 if (tile_resource(adjc_tile) == pres) {
427 return TRUE;
428 }
430
431 return check_self && tile_resource(ptile) == pres;
432}
433
434/**********************************************************************/
439 const struct tile *ptile,
440 enum terrain_flag_id flag)
441{
443 struct terrain* pterrain = tile_terrain(adjc_tile);
444
445 if (T_UNKNOWN != pterrain
446 && terrain_has_flag(pterrain, flag)) {
447 return TRUE;
448 }
450
451 return FALSE;
452}
453
454/**********************************************************************/
459 const struct tile *ptile,
460 enum terrain_flag_id flag)
461{
462 adjc_iterate(nmap, ptile, adjc_tile) {
463 struct terrain* pterrain = tile_terrain(adjc_tile);
464
465 if (T_UNKNOWN != pterrain
466 && terrain_has_flag(pterrain, flag)) {
467 return TRUE;
468 }
470
471 return FALSE;
472}
473
474/**********************************************************************/
479 const struct tile *ptile,
480 bool cardinal_only, bool percentage,
481 enum terrain_flag_id flag)
482{
483 int count = 0, total = 0;
484
486 struct terrain *pterrain = tile_terrain(adjc_tile);
487
488 if (T_UNKNOWN != pterrain
489 && terrain_has_flag(pterrain, flag)) {
490 count++;
491 }
492 total++;
494
495 if (percentage && count > 0) { /* Latter condition avoids div by zero */
496 count = count * 100 / total;
497 }
498
499 return count;
500}
501
502/**********************************************************************/
509{
510 static char s[256];
511 char *p;
512 int len;
513
514 s[0] = '\0';
515
516 extra_type_iterate(pextra) {
517 if (pextra->category == ECAT_INFRA
518 && BV_ISSET(extras, extra_index(pextra))) {
519 bool hidden = FALSE;
520
521 extra_type_iterate(top) {
522 int topi = extra_index(top);
523
524 if (BV_ISSET(pextra->hidden_by, topi)
525 && BV_ISSET(extras, topi)) {
526 hidden = TRUE;
527 break;
528 }
530
531 if (!hidden) {
532 cat_snprintf(s, sizeof(s), "%s/", extra_name_translation(pextra));
533 }
534 }
536
537 len = strlen(s);
538 p = s + len - 1;
539 if (len > 0 && *p == '/') {
540 *p = '\0';
541 }
542
543 return s;
544}
545
546/**********************************************************************/
551{
552 /* Semi-arbitrary preference order reflecting previous behavior */
553 static const enum extra_cause prefs[] = {
555 EC_MINE,
556 EC_BASE,
557 EC_ROAD,
558 EC_HUT,
563 EC_NONE
564 };
565 int i;
566
567 for (i = 0; i < ARRAY_SIZE(prefs); i++) {
570 && BV_ISSET(extras, extra_index(pextra))) {
571 return pextra;
572 }
574 }
575
576 return NULL;
577}
578
579/**********************************************************************/
583{
584 return pterrain->tclass;
585}
586
587/**********************************************************************/
592 const struct tile *ptile,
593 enum terrain_class tclass)
594{
596 struct terrain* pterrain = tile_terrain(adjc_tile);
597
598 if (pterrain != T_UNKNOWN) {
599 if (terrain_type_terrain_class(pterrain) == tclass) {
600 return TRUE;
601 }
602 }
604
605 return FALSE;
606}
607
608/**********************************************************************/
613 const struct tile *ptile,
615{
616 adjc_iterate(nmap, ptile, adjc_tile) {
617 struct terrain* pterrain = tile_terrain(adjc_tile);
618
619 if (pterrain != T_UNKNOWN) {
620 if (terrain_type_terrain_class(pterrain) == tclass) {
621 return TRUE;
622 }
623 }
625
626 return FALSE;
627}
628
629/**********************************************************************/
634 const struct tile *ptile,
635 bool cardinal_only, bool percentage,
637{
638 int count = 0, total = 0;
639
641 struct terrain *pterrain = tile_terrain(adjc_tile);
642
643 if (T_UNKNOWN != pterrain
644 && terrain_type_terrain_class(pterrain) == tclass) {
645 count++;
646 }
647 total++;
649
650 if (percentage && count > 0) { /* Latter condition avoids div by zero */
651 count = count * 100 / total;
652 }
653
654 return count;
655}
656
657/**********************************************************************/
662{
664 return NULL;
665 }
666
667 return _(terrain_class_name(tclass));
668}
669
670/**********************************************************************/
673bool terrain_can_support_alteration(const struct terrain *pterrain,
675{
676 switch (alter) {
677 case TA_CAN_IRRIGATE:
678 return (pterrain->irrigation_time > 0);
679 case TA_CAN_MINE:
680 return (pterrain->mining_time > 0);
681 case TA_CAN_ROAD:
682 return (pterrain->road_time > 0);
683 case TA_CAN_BASE:
684 return (pterrain->base_time > 0);
685 case TA_CAN_PLACE:
686 return (pterrain->placing_time > 0);
687 default:
688 break;
689 }
690
692
693 return FALSE;
694}
695
696/**********************************************************************/
699int terrain_extra_build_time(const struct terrain *pterrain,
700 enum unit_activity activity,
701 const struct extra_type *tgt)
702{
703 int factor;
704
705 if (tgt != NULL && tgt->build_time != 0) {
706 /* Extra specific build time */
707 return tgt->build_time;
708 }
709
710 if (tgt == NULL) {
711 factor = 1;
712 } else {
713 factor = tgt->build_time_factor;
714 }
715
716 /* Terrain and activity specific build time */
717 switch (activity) {
718 case ACTIVITY_BASE:
719 return pterrain->base_time * factor;
721 return pterrain->road_time * factor;
723 return pterrain->irrigation_time * factor;
724 case ACTIVITY_MINE:
725 return pterrain->mining_time * factor;
726 default:
728 return 0;
729 }
730}
731
732/**********************************************************************/
735int terrain_extra_removal_time(const struct terrain *pterrain,
736 enum unit_activity activity,
737 const struct extra_type *tgt)
738{
739 int factor;
740
741 if (tgt->removal_time != 0) {
742 /* Extra specific removal time */
743 return tgt->removal_time;
744 }
745
746 factor = tgt->removal_time_factor;
747
748 /* Terrain and activity specific removal time */
749 switch (activity) {
750 case ACTIVITY_CLEAN:
751 return pterrain->extra_removal_times[extra_index(tgt)] * factor;
752 case ACTIVITY_PILLAGE:
753 return pterrain->pillage_time * factor;
754 default:
756
757 return 0;
758 }
759}
760
761/**********************************************************************/
765{
766 int i;
767
768 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
770 }
771}
772
773/**********************************************************************/
777{
778 int i;
779
780 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
782 }
783}
784
785/**********************************************************************/
789 const char *helptxt)
790{
791 int tfid = id - TER_USER_1;
792
793 fc_assert_ret(id >= TER_USER_1 && id <= TER_USER_LAST);
794
798 }
799
800 if (name && name[0] != '\0') {
802 }
803
804 if (user_terrain_flags[tfid].helptxt != NULL) {
807 }
808
809 if (helptxt && helptxt[0] != '\0') {
811 }
812}
813
814/**********************************************************************/
818{
820 return NULL;
821 }
822
824}
825
826/**********************************************************************/
830{
831 fc_assert(id >= TER_USER_1 && id <= TER_USER_LAST);
832
834}
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
char * incite_cost
Definition comments.c:76
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:353
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_type_by_cause_iterate_rev(_cause, _extra)
Definition extras.h:344
#define extra_type_by_cause_iterate_rev_end
Definition extras.h:349
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define extra_index(_e_)
Definition extras.h:183
int Terrain_type_id
Definition fc_types.h:232
#define EC_NONE
Definition fc_types.h:821
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
#define _(String)
Definition fcintl.h:67
#define Qn_(String)
Definition fcintl.h:89
void user_flag_init(struct user_flag *flag)
Definition game.c:829
void user_flag_free(struct user_flag *flag)
Definition game.c:838
struct civ_game game
Definition game.c:61
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define adjc_iterate_end
Definition map.h:430
#define cardinal_adjc_iterate_end
Definition map.h:456
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:452
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * name_translation_get(const struct name_translation *ptrans)
int len
Definition packhand.c:127
#define fc_rand(_size)
Definition rand.h:56
void rgbcolor_destroy(struct rgbcolor *prgbcolor)
Definition rgbcolor.c:74
#define ARRAY_SIZE(x)
Definition shared.h:85
void strvec_destroy(struct strvec *psv)
struct packet_ruleset_control control
Definition game.h:83
struct resource_type * resource
Definition extras.h:156
int removal_time
Definition extras.h:120
int build_time_factor
Definition extras.h:119
struct extra_type::@26 data
int removal_time_factor
Definition extras.h:121
int build_time
Definition extras.h:118
struct extra_type * self
Definition terrain.h:56
int placing_time
Definition terrain.h:120
int property[MG_COUNT]
Definition terrain.h:146
struct extra_type ** resources
Definition terrain.h:97
int item_number
Definition terrain.h:76
int road_time
Definition terrain.h:106
struct name_translation name
Definition terrain.h:77
const struct unit_type * animal
Definition terrain.h:130
int pillage_time
Definition terrain.h:125
int mining_time
Definition terrain.h:118
struct rgbcolor * rgb
Definition terrain.h:154
enum terrain_class tclass
Definition terrain.h:90
int extra_removal_times[MAX_EXTRA_TYPES]
Definition terrain.h:128
int irrigation_time
Definition terrain.h:115
int base_time
Definition terrain.h:105
void * ruledit_dlg
Definition terrain.h:79
char identifier
Definition terrain.h:84
bool ruledit_disabled
Definition terrain.h:78
Definition tile.h:50
struct terrain * terrain
Definition tile.h:57
char * name
Definition game.h:74
char * helptxt
Definition game.h:75
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
int terrain_extra_removal_time(const struct terrain *pterrain, enum unit_activity activity, const struct extra_type *tgt)
Definition terrain.c:735
void user_terrain_flags_init(void)
Definition terrain.c:764
void terrains_free(void)
Definition terrain.c:65
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:612
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:126
Terrain_type_id terrain_count(void)
Definition terrain.c:118
void terrains_init(void)
Definition terrain.c:42
struct extra_type * resource_extra_get(const struct resource_type *presource)
Definition terrain.c:296
int count_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, bool cardinal_only, bool percentage, enum terrain_class tclass)
Definition terrain.c:633
bool is_terrain_class_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:591
struct terrain * terrain_by_translated_name(const char *name)
Definition terrain.c:202
const char * terrain_class_name_translation(enum terrain_class tclass)
Definition terrain.c:661
int count_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, bool cardinal_only, bool percentage, enum terrain_flag_id flag)
Definition terrain.c:478
const char * get_infrastructure_text(bv_extras extras)
Definition terrain.c:508
const char * terrain_flag_id_name_cb(enum terrain_flag_id flag)
Definition terrain.c:817
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:138
bool is_resource_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pres, bool check_self)
Definition terrain.c:395
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
#define variable_adjc_iterate(nmap, center_tile, _tile, card_only)
Definition terrain.c:305
struct terrain * terrain_array_first(void)
Definition terrain.c:96
struct terrain * rand_terrain_by_flag(enum terrain_flag_id flag)
Definition terrain.c:217
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:156
bool terrain_can_support_alteration(const struct terrain *pterrain, enum terrain_alteration alter)
Definition terrain.c:673
bool is_terrain_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:327
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
bool is_resource_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pres, bool check_self)
Definition terrain.c:416
void resource_types_free(void)
Definition terrain.c:288
void user_terrain_flags_free(void)
Definition terrain.c:776
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:582
const char * terrain_flag_helptxt(enum terrain_flag_id id)
Definition terrain.c:829
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:255
struct resource_type * resource_type_init(struct extra_type *pextra)
Definition terrain.c:272
bool is_terrain_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:458
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:550
void set_user_terrain_flag_name(enum terrain_flag_id id, const char *name, const char *helptxt)
Definition terrain.c:788
const struct terrain * terrain_array_last(void)
Definition terrain.c:107
static struct terrain civ_terrains[MAX_NUM_TERRAINS]
Definition terrain.c:36
int terrain_extra_build_time(const struct terrain *pterrain, enum unit_activity activity, const struct extra_type *tgt)
Definition terrain.c:699
static struct user_flag user_terrain_flags[MAX_NUM_USER_TER_FLAGS]
Definition terrain.c:37
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:147
struct terrain * terrain_by_identifier(const char identifier)
Definition terrain.c:169
bool is_terrain_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum terrain_flag_id flag)
Definition terrain.c:438
int count_terrain_property_near_tile(const struct civ_map *nmap, const struct tile *ptile, bool cardinal_only, bool percentage, enum mapgen_terrain_property prop)
Definition terrain.c:369
#define variable_adjc_iterate_end
Definition terrain.c:320
bool is_terrain_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain, bool check_self)
Definition terrain.c:348
#define terrain_type_iterate(_p)
Definition terrain.h:266
#define T_UNKNOWN
Definition terrain.h:62
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:272
#define MAX_NUM_TERRAINS
Definition terrain.h:69
#define terrain_has_flag(terr, flag)
Definition terrain.h:176
#define MAX_NUM_USER_TER_FLAGS
Definition terrain.h:32
#define tile_resource(_tile)
Definition tile.h:103
#define tile_terrain(_tile)
Definition tile.h:111