Freeciv-3.1: /fast/freeciv/nightly/S3_1/common/extras.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
extras.c
Go to the documentation of this file.
1/****************************************************************************
2 Freeciv - Copyright (C) 2004 - The Freeciv Team
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 "rand.h"
20#include "string_vector.h"
21
22/* common */
23#include "base.h"
24#include "game.h"
25#include "map.h"
26#include "research.h"
27#include "road.h"
28
29#include "extras.h"
30
31 static struct extra_type extras[MAX_EXTRA_TYPES];
32
33 static struct user_flag user_extra_flags[MAX_NUM_USER_EXTRA_FLAGS];
34
35 static struct extra_type_list *caused_by[EC_LAST];
36 static struct extra_type_list *removed_by[ERM_COUNT];
37 static struct extra_type_list *unit_hidden;
38 static struct extra_type_list *terr_claimer;
39
40/************************************************************************/
43 void extras_init(void)
44{
45 int i;
46
47 for (i = 0; i < EC_LAST; i++) {
48 caused_by[i] = extra_type_list_new();
49 }
50 for (i = 0; i < ERM_COUNT; i++) {
51 removed_by[i] = extra_type_list_new();
52 }
53 unit_hidden = extra_type_list_new();
54 terr_claimer = extra_type_list_new();
55
56 for (i = 0; i < MAX_EXTRA_TYPES; i++) {
57 requirement_vector_init(&(extras[i].reqs));
58 requirement_vector_init(&(extras[i].rmreqs));
59 requirement_vector_init(&(extras[i].appearance_reqs));
60 requirement_vector_init(&(extras[i].disappearance_reqs));
61 extras[i].id = i;
62 extras[i].hiders = NULL;
63 extras[i].bridged = NULL;
64 extras[i].data.special_idx = -1;
65 extras[i].data.base = NULL;
66 extras[i].data.road = NULL;
67 extras[i].data.resource = NULL;
68 extras[i].causes = 0;
69 extras[i].rmcauses = 0;
70 extras[i].helptext = NULL;
71 extras[i].ruledit_disabled = FALSE;
72 extras[i].ruledit_dlg = NULL;
73 extras[i].visibility_req = A_NONE;
74 }
75}
76
77/************************************************************************/
80 void extras_free(void)
81{
82 int i;
83
84 base_types_free();
85 road_types_free();
86 resource_types_free();
87
88 for (i = 0; i < game.control.num_extra_types; i++) {
89 if (extras[i].data.base != NULL) {
90 FC_FREE(extras[i].data.base);
91 extras[i].data.base = NULL;
92 }
93 if (extras[i].data.road != NULL) {
94 FC_FREE(extras[i].data.road);
95 extras[i].data.road = NULL;
96 }
97 if (extras[i].data.resource != NULL) {
98 FC_FREE(extras[i].data.resource);
99 extras[i].data.resource = NULL;
100 }
101 }
102
103 for (i = 0; i < EC_LAST; i++) {
104 extra_type_list_destroy(caused_by[i]);
105 caused_by[i] = NULL;
106 }
107
108 for (i = 0; i < ERM_COUNT; i++) {
109 extra_type_list_destroy(removed_by[i]);
110 removed_by[i] = NULL;
111 }
112
113 extra_type_list_destroy(unit_hidden);
114 unit_hidden = NULL;
115 extra_type_list_destroy(terr_claimer);
116 terr_claimer = NULL;
117
118 for (i = 0; i < MAX_EXTRA_TYPES; i++) {
119 requirement_vector_free(&(extras[i].reqs));
120 requirement_vector_free(&(extras[i].rmreqs));
121 requirement_vector_free(&(extras[i].appearance_reqs));
122 requirement_vector_free(&(extras[i].disappearance_reqs));
123
124 if (NULL != extras[i].helptext) {
125 strvec_destroy(extras[i].helptext);
126 extras[i].helptext = NULL;
127 }
128 }
129
130 extra_type_iterate(pextra) {
131 if (pextra->hiders != NULL) {
132 extra_type_list_destroy(pextra->hiders);
133 pextra->hiders = NULL;
134 }
135 if (pextra->bridged != NULL) {
136 extra_type_list_destroy(pextra->bridged);
137 pextra->bridged = NULL;
138 }
139 } extra_type_iterate_end;
140}
141
142/************************************************************************/
145 int extra_count(void)
146{
147 return game.control.num_extra_types;
148}
149
150/************************************************************************/
153 int extra_number(const struct extra_type *pextra)
154{
155 fc_assert_ret_val(NULL != pextra, -1);
156
157 return pextra->id;
158}
159
160#ifndef extra_index
161/************************************************************************/
164int extra_index(const struct extra_type *pextra)
165{
166 fc_assert_ret_val(NULL != pextra, -1);
167
168 return pextra - extras;
169}
170#endif /* extra_index */
171
172/************************************************************************/
175 struct extra_type *extra_by_number(int id)
176{
177 fc_assert_ret_val(id >= 0 && id < MAX_EXTRA_TYPES, NULL);
178
179 return &extras[id];
180}
181
182/************************************************************************/
186 const char *extra_name_translation(const struct extra_type *pextra)
187{
188 return name_translation_get(&pextra->name);
189}
190
191/************************************************************************/
195 const char *extra_rule_name(const struct extra_type *pextra)
196{
197 return rule_name_get(&pextra->name);
198}
199
200/************************************************************************/
204 struct extra_type *extra_type_by_rule_name(const char *name)
205{
206 const char *qs;
207
208 if (name == NULL) {
209 return NULL;
210 }
211
212 qs = Qn_(name);
213
214 extra_type_iterate(pextra) {
215 if (!fc_strcasecmp(extra_rule_name(pextra), qs)) {
216 return pextra;
217 }
218 } extra_type_iterate_end;
219
220 return NULL;
221}
222
223/************************************************************************/
227 struct extra_type *extra_type_by_translated_name(const char *name)
228{
229 extra_type_iterate(pextra) {
230 if (0 == strcmp(extra_name_translation(pextra), name)) {
231 return pextra;
232 }
233 } extra_type_iterate_end;
234
235 return NULL;
236}
237
238/************************************************************************/
241 struct extra_type_list *extra_type_list_by_cause(enum extra_cause cause)
242{
243 fc_assert(cause < EC_LAST);
244
245 return caused_by[cause];
246}
247
248/************************************************************************/
251 struct extra_type_list *extra_type_list_of_unit_hiders(void)
252{
253 return unit_hidden;
254}
255
256/************************************************************************/
259 struct extra_type_list *extra_type_list_of_terr_claimers(void)
260{
261 return terr_claimer;
262}
263
264/************************************************************************/
267 struct extra_type *rand_extra_for_tile(struct tile *ptile, enum extra_cause cause,
268 bool generated)
269{
270 struct extra_type_list *full_list = extra_type_list_by_cause(cause);
271 struct extra_type_list *potential = extra_type_list_new();
272 int options;
273 struct extra_type *selected = NULL;
274
275 extra_type_list_iterate(full_list, pextra) {
276 if ((!generated || pextra->generated)
277 && is_native_tile_to_extra(pextra, ptile)) {
278 extra_type_list_append(potential, pextra);
279 }
280 } extra_type_list_iterate_end;
281
282 options = extra_type_list_size(potential);
283
284 if (options > 0) {
285 selected = extra_type_list_get(potential, fc_rand(options));
286 }
287
288 extra_type_list_destroy(potential);
289
290 return selected;
291}
292
293/************************************************************************/
296 void extra_to_caused_by_list(struct extra_type *pextra, enum extra_cause cause)
297{
298 fc_assert(cause < EC_LAST);
299
300 extra_type_list_append(caused_by[cause], pextra);
301}
302
303/************************************************************************/
306 struct extra_type_list *extra_type_list_by_rmcause(enum extra_rmcause rmcause)
307{
308 fc_assert(rmcause < ERM_COUNT);
309
310 return removed_by[rmcause];
311}
312
313/************************************************************************/
316 void extra_to_removed_by_list(struct extra_type *pextra,
317 enum extra_rmcause rmcause)
318{
319 fc_assert(rmcause < ERM_COUNT);
320
321 extra_type_list_append(removed_by[rmcause], pextra);
322}
323
324/************************************************************************/
327 bool is_extra_removed_by(const struct extra_type *pextra,
328 enum extra_rmcause rmcause)
329{
330 return (pextra->rmcauses & (1 << rmcause));
331}
332
333/************************************************************************/
337 bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile,
338 const struct extra_type *pextra)
339{
340 cardinal_adjc_iterate(nmap, ptile, adjc_tile) {
341 if (tile_has_extra(adjc_tile, pextra)) {
342 return TRUE;
343 }
344 } cardinal_adjc_iterate_end;
345
346 return FALSE;
347}
348
349/************************************************************************/
353 bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile,
354 const struct extra_type *pextra)
355{
356 adjc_iterate(nmap, ptile, adjc_tile) {
357 if (tile_has_extra(adjc_tile, pextra)) {
358 return TRUE;
359 }
360 } adjc_iterate_end;
361
362 return FALSE;
363}
364
365/************************************************************************/
368 bool extra_can_be_built(const struct extra_type *pextra,
369 const struct tile *ptile)
370{
371 if (!pextra->buildable) {
372 /* Extra type not buildable */
373 return FALSE;
374 }
375
376 if (tile_has_extra(ptile, pextra)) {
377 /* Extra exist already */
378 return FALSE;
379 }
380
381 return TRUE;
382}
383
384/************************************************************************/
387 bool can_build_extra_base(const struct extra_type *pextra,
388 const struct player *pplayer,
389 const struct tile *ptile)
390{
391 struct terrain *pterr;
392
393 if (!extra_can_be_built(pextra, ptile)) {
394 return FALSE;
395 }
396
397 pterr = tile_terrain(ptile);
398
399 if (is_extra_caused_by(pextra, EC_BASE)) {
400 if (pterr->base_time == 0) {
401 return FALSE;
402 }
403 if (tile_city(ptile) != NULL && extra_base_get(pextra)->border_sq >= 0) {
404 return FALSE;
405 }
406 }
407
408 /* Even if it's a multi-cause extra, just having Build Road as one of the
409 * causes makes it to require that road_time != 0.
410 * Correct functioning of EC_PLACE extras depend on this. */
411 if (is_extra_caused_by(pextra, EC_ROAD)
412 && pterr->road_time == 0) {
413 return FALSE;
414 }
415
416 if (is_extra_caused_by(pextra, EC_IRRIGATION)
417 && pterr->irrigation_time == 0) {
418 return FALSE;
419 }
420
421 if (is_extra_caused_by(pextra, EC_MINE)
422 && pterr->mining_time == 0) {
423 return FALSE;
424 }
425
426 if (pplayer != NULL && !player_knows_techs_with_flag(pplayer, TF_BRIDGE)) {
427 /* Player does not know technology to bridge over extras that require it. */
428 extra_type_list_iterate(pextra->bridged, pbridged) {
429 if (tile_has_extra(ptile, pbridged)) {
430 /* Tile has extra that would require bridging over. */
431 return FALSE;
432 }
433 } extra_type_list_iterate_end;
434 }
435
436 return TRUE;
437}
438
439/************************************************************************/
442 bool player_can_build_extra(const struct extra_type *pextra,
443 const struct player *pplayer,
444 const struct tile *ptile)
445{
446 if (!can_build_extra_base(pextra, pplayer, ptile)) {
447 return FALSE;
448 }
449
450 return are_reqs_active(&(const struct req_context) {
451 .player = pplayer,
452 .tile = ptile,
453 },
454 tile_owner(ptile),
455 &pextra->reqs,
456 RPT_POSSIBLE);
457}
458
459/************************************************************************/
462 bool player_can_place_extra(const struct extra_type *pextra,
463 const struct player *pplayer,
464 const struct tile *ptile)
465{
466 if (pextra->infracost == 0) {
467 return FALSE;
468 }
469
470 if (ptile->placing != NULL) {
471 /* Already placing something */
472 return FALSE;
473 }
474
475 if (tile_terrain(ptile)->placing_time <= 0) {
476 /* Can't place to this terrain */
477 return FALSE;
478 }
479
480 if (game.info.borders != BORDERS_DISABLED) {
481 if (tile_owner(ptile) != pplayer) {
482 return FALSE;
483 }
484 } else {
485 struct city *pcity = tile_worked(ptile);
486
487 if (pcity == NULL || city_owner(pcity) != pplayer) {
488 return FALSE;
489 }
490 }
491
492 /* Placing extras is not allowed to tiles where also workers do changes. */
493 unit_list_iterate(ptile->units, punit) {
494 tile_changing_activities_iterate(act) {
495 if (punit->activity == act) {
496 return FALSE;
497 }
498 } tile_changing_activities_iterate_end;
499 } unit_list_iterate_end;
500
501 return player_can_build_extra(pextra, pplayer, ptile);
502}
503
504/************************************************************************/
507 bool can_build_extra(const struct extra_type *pextra,
508 const struct unit *punit,
509 const struct tile *ptile)
510{
511 struct player *pplayer = unit_owner(punit);
512
513 if (!can_build_extra_base(pextra, pplayer, ptile)) {
514 return FALSE;
515 }
516
517 return are_reqs_active(&(const struct req_context) {
518 .player = pplayer,
519 .tile = ptile,
520 .unit = punit,
521 .unittype = unit_type_get(punit),
522 },
523 tile_owner(ptile),
524 &pextra->reqs,
525 RPT_CERTAIN);
526}
527
528/************************************************************************/
531 static bool can_extra_be_removed(const struct extra_type *pextra,
532 const struct tile *ptile)
533{
534 struct city *pcity = tile_city(ptile);
535
536 /* Cannot remove EF_ALWAYS_ON_CITY_CENTER extras from city center. */
537 if (pcity != NULL) {
538 if (extra_has_flag(pextra, EF_ALWAYS_ON_CITY_CENTER)) {
539 return FALSE;
540 }
541 if (extra_has_flag(pextra, EF_AUTO_ON_CITY_CENTER)) {
542 struct tile *vtile = tile_virtual_new(ptile);
543
544 /* Would extra get rebuilt if removed */
545 tile_remove_extra(vtile, pextra);
546 if (player_can_build_extra(pextra, city_owner(pcity), vtile)) {
547 /* No need to worry about conflicting extras - extra would had
548 * not been here if conflicting one is. */
549 tile_virtual_destroy(vtile);
550
551 return FALSE;
552 }
553
554 tile_virtual_destroy(vtile);
555 }
556 }
557
558 return TRUE;
559}
560
561/************************************************************************/
564 bool player_can_remove_extra(const struct extra_type *pextra,
565 const struct player *pplayer,
566 const struct tile *ptile)
567{
568 if (!can_extra_be_removed(pextra, ptile)) {
569 return FALSE;
570 }
571
572 /* For huts, it's not checked if player has any non-HUT_NOTHING units */
573 return are_reqs_active(&(const struct req_context) {
574 .player = pplayer,
575 .tile = ptile,
576 },
577 tile_owner(ptile),
578 &pextra->rmreqs,
579 RPT_POSSIBLE);
580}
581
582/************************************************************************/
586 bool can_remove_extra(const struct extra_type *pextra,
587 const struct unit *punit,
588 const struct tile *ptile)
589{
590
591 if (!can_extra_be_removed(pextra, ptile)) {
592 return FALSE;
593 }
594
595 return are_reqs_active(&(const struct req_context) {
596 .player = unit_owner(punit),
597 .tile = ptile,
598 .unit = punit,
599 .unittype = unit_type_get(punit),
600 },
601 tile_owner(ptile),
602 &pextra->rmreqs, RPT_CERTAIN);
603}
604
605/************************************************************************/
608 bool is_native_tile_to_extra(const struct extra_type *pextra,
609 const struct tile *ptile)
610{
611 struct terrain *pterr = tile_terrain(ptile);
612
613 if (terrain_has_resource(pterr, pextra)) {
614 return TRUE;
615 }
616
617 if (is_extra_caused_by(pextra, EC_IRRIGATION)
618 && pterr->irrigation_time == 0) {
619 return FALSE;
620 }
621
622 if (is_extra_caused_by(pextra, EC_MINE)
623 && pterr->mining_time == 0) {
624 return FALSE;
625 }
626
627 if (is_extra_caused_by(pextra, EC_BASE)) {
628 if (pterr->base_time == 0) {
629 return FALSE;
630 }
631 if (tile_city(ptile) != NULL && extra_base_get(pextra)->border_sq >= 0) {
632 return FALSE;
633 }
634 }
635
636 if (is_extra_caused_by(pextra, EC_ROAD)) {
637 struct road_type *proad = extra_road_get(pextra);
638
639 if (road_has_flag(proad, RF_RIVER)) {
640 if (!terrain_has_flag(pterr, TER_CAN_HAVE_RIVER)) {
641 return FALSE;
642 }
643 } else if (pterr->road_time == 0) {
644 return FALSE;
645 }
646 }
647
648 return are_reqs_active(&(const struct req_context) { .tile = ptile },
649 NULL, &pextra->reqs, RPT_POSSIBLE);
650}
651
652/************************************************************************/
655 bool extra_conflicting_on_tile(const struct extra_type *pextra,
656 const struct tile *ptile)
657{
658 extra_type_iterate(old_extra) {
659 if (tile_has_extra(ptile, old_extra)
660 && !can_extras_coexist(old_extra, pextra)) {
661 return TRUE;
662 }
663 } extra_type_iterate_end;
664
665 return FALSE;
666}
667
668/************************************************************************/
672 bool hut_on_tile(const struct tile *ptile)
673{
674 extra_type_by_rmcause_iterate(ERM_ENTER, extra) {
675 if (tile_has_extra(ptile, extra)) {
676 return TRUE;
677 }
678 } extra_type_by_rmcause_iterate_end;
679
680 return FALSE;
681}
682
683/************************************************************************/
687 bool unit_can_enter_hut(const struct unit *punit,
688 const struct tile *ptile)
689{
690 const struct req_context context = {
691 .player = unit_owner(punit),
692 .tile = ptile,
693 };
694
695 if (!(unit_can_do_action_result(punit, ACTRES_HUT_ENTER)
696 || unit_can_do_action_sub_result(punit, ACT_SUB_RES_HUT_ENTER))) {
697 return FALSE;
698 }
699 extra_type_by_rmcause_iterate(ERM_ENTER, extra) {
700 if (tile_has_extra(ptile, extra)
701 && are_reqs_active(&context, tile_owner(ptile), &extra->rmreqs,
702 RPT_POSSIBLE)) {
703 return TRUE;
704 }
705 } extra_type_by_rmcause_iterate_end;
706 return FALSE;
707}
708
709/************************************************************************/
713 bool unit_can_displace_hut(const struct unit *punit,
714 const struct tile *ptile)
715{
716 const struct req_context context = {
717 .player = unit_owner(punit),
718 .tile = ptile,
719 };
720
721 if (!(unit_can_do_action_result(punit, ACTRES_HUT_FRIGHTEN)
722 || unit_can_do_action_sub_result(punit, ACT_SUB_RES_HUT_FRIGHTEN)
723 || unit_can_do_action_result(punit, ACTRES_HUT_ENTER)
724 || unit_can_do_action_sub_result(punit, ACT_SUB_RES_HUT_ENTER))) {
725 return FALSE;
726 }
727 extra_type_by_rmcause_iterate(ERM_ENTER, extra) {
728 if (tile_has_extra(ptile, extra)
729 && are_reqs_active(&context, tile_owner(ptile), &extra->rmreqs,
730 RPT_POSSIBLE)) {
731 return TRUE;
732 }
733 } extra_type_by_rmcause_iterate_end;
734 return FALSE;
735}
736
737/************************************************************************/
740 struct extra_type *next_extra_for_tile(const struct tile *ptile, enum extra_cause cause,
741 const struct player *pplayer,
742 const struct unit *punit)
743{
744 extra_type_by_cause_iterate(cause, pextra) {
745 if (!tile_has_extra(ptile, pextra)) {
746 if (punit != NULL) {
747 if (can_build_extra(pextra, punit, ptile)) {
748 return pextra;
749 }
750 } else {
751 /* punit is certainly NULL, pplayer can be too */
752 if (player_can_build_extra(pextra, pplayer, ptile)) {
753 return pextra;
754 }
755 }
756 }
757 } extra_type_by_cause_iterate_end;
758
759 return NULL;
760}
761
762/************************************************************************/
765 struct extra_type *prev_extra_in_tile(const struct tile *ptile,
766 enum extra_rmcause rmcause,
767 const struct player *pplayer,
768 const struct unit *punit)
769{
770 fc_assert(punit != NULL || pplayer != NULL);
771
772 extra_type_by_rmcause_iterate(rmcause, pextra) {
773 if (tile_has_extra(ptile, pextra)) {
774 if (punit != NULL) {
775 if (can_remove_extra(pextra, punit, ptile)) {
776 return pextra;
777 }
778 } else {
779 if (player_can_remove_extra(pextra, pplayer, ptile)) {
780 return pextra;
781 }
782 }
783 }
784 } extra_type_by_rmcause_iterate_end;
785
786 return NULL;
787}
788
789/************************************************************************/
792 bool is_native_extra_to_uclass(const struct extra_type *pextra,
793 const struct unit_class *pclass)
794{
795 return BV_ISSET(pextra->native_to, uclass_index(pclass));
796}
797
798/************************************************************************/
801 bool is_native_extra_to_utype(const struct extra_type *pextra,
802 const struct unit_type *punittype)
803{
804 return is_native_extra_to_uclass(pextra, utype_class(punittype));
805}
806
807/************************************************************************/
810 bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
811{
812 return BV_ISSET(pextra->flags, flag);
813}
814
815/************************************************************************/
819 bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile,
820 enum extra_flag_id flag)
821{
822 extra_type_iterate(pextra) {
823 if (extra_has_flag(pextra, flag)) {
824 cardinal_adjc_iterate(nmap, ptile, adjc_tile) {
825 if (tile_has_extra(adjc_tile, pextra)) {
826 return TRUE;
827 }
828 } cardinal_adjc_iterate_end;
829 }
830 } extra_type_iterate_end;
831
832 return FALSE;
833}
834
835/************************************************************************/
839 bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile,
840 enum extra_flag_id flag)
841{
842 extra_type_iterate(pextra) {
843 if (extra_has_flag(pextra, flag)) {
844 adjc_iterate(nmap, ptile, adjc_tile) {
845 if (tile_has_extra(adjc_tile, pextra)) {
846 return TRUE;
847 }
848 } adjc_iterate_end;
849 }
850 } extra_type_iterate_end;
851
852 return FALSE;
853}
854
855/************************************************************************/
858 void user_extra_flags_init(void)
859{
860 int i;
861
862 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
863 user_flag_init(&user_extra_flags[i]);
864 }
865}
866
867/************************************************************************/
870 void extra_flags_free(void)
871{
872 int i;
873
874 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
875 user_flag_free(&user_extra_flags[i]);
876 }
877}
878
879/************************************************************************/
882 void set_user_extra_flag_name(enum extra_flag_id id, const char *name,
883 const char *helptxt)
884{
885 int efid = id - EF_USER_FLAG_1;
886
887 fc_assert_ret(id >= EF_USER_FLAG_1 && id <= EF_LAST_USER_FLAG);
888
889 if (user_extra_flags[efid].name != NULL) {
890 FC_FREE(user_extra_flags[efid].name);
891 user_extra_flags[efid].name = NULL;
892 }
893
894 if (name && name[0] != '\0') {
895 user_extra_flags[efid].name = fc_strdup(name);
896 }
897
898 if (user_extra_flags[efid].helptxt != NULL) {
899 free(user_extra_flags[efid].helptxt);
900 user_extra_flags[efid].helptxt = NULL;
901 }
902
903 if (helptxt && helptxt[0] != '\0') {
904 user_extra_flags[efid].helptxt = fc_strdup(helptxt);
905 }
906}
907
908/************************************************************************/
911 const char *extra_flag_id_name_cb(enum extra_flag_id flag)
912{
913 if (flag < EF_USER_FLAG_1 || flag > EF_LAST_USER_FLAG) {
914 return NULL;
915 }
916
917 return user_extra_flags[flag - EF_USER_FLAG_1].name;
918}
919
920/************************************************************************/
923 const char *extra_flag_helptxt(enum extra_flag_id id)
924{
925 fc_assert(id >= EF_USER_FLAG_1 && id <= EF_LAST_USER_FLAG);
926
927 return user_extra_flags[id - EF_USER_FLAG_1].helptxt;
928}
929
930/**********************************************************************/
936 bool extra_flag_is_in_use(enum extra_flag_id id)
937{
938 extra_type_re_active_iterate(pextra) {
939 if (extra_has_flag(pextra, id)) {
940 /* Found a user. */
941 return TRUE;
942 }
943 } extra_type_re_active_iterate_end;
944
945 /* No users detected. */
946 return FALSE;
947}
948
949/************************************************************************/
952 bool can_extras_coexist(const struct extra_type *pextra1,
953 const struct extra_type *pextra2)
954{
955 if (pextra1 == pextra2) {
956 return TRUE;
957 }
958
959 return !BV_ISSET(pextra1->conflicts, extra_index(pextra2));
960}
961
962/************************************************************************/
965 bool extra_causes_env_upset(struct extra_type *pextra,
966 enum environment_upset_type upset)
967{
968 switch (upset) {
969 case EUT_GLOBAL_WARMING:
970 return extra_has_flag(pextra, EF_GLOBAL_WARMING);
971 case EUT_NUCLEAR_WINTER:
972 return extra_has_flag(pextra, EF_NUCLEAR_WINTER);
973 }
974
975 return FALSE;
976}
977
978/************************************************************************/
981 bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
982{
983 /* Is any of the worker build action bits set? */
984 return (pextra->causes
985 & (1 << EC_IRRIGATION
986 | 1 << EC_MINE
987 | 1 << EC_BASE
988 | 1 << EC_ROAD));
989}
990
991/************************************************************************/
994 bool is_extra_removed_by_worker_action(const struct extra_type *pextra)
995{
996 /* Is any of the worker remove action bits set? */
997 return (pextra->rmcauses
998 & (1 << ERM_CLEANPOLLUTION
999 | 1 << ERM_CLEANFALLOUT
1000 | 1 << ERM_PILLAGE));
1001}
1002
1003/************************************************************************/
1006 bool is_extra_caused_by_action(const struct extra_type *pextra,
1007 const struct action *paction)
1008{
1009 enum unit_activity act = actres_get_activity(paction->result);
1010
1011 return is_extra_caused_by(pextra, activity_to_extra_cause(act));
1012}
1013
1014/************************************************************************/
1017 bool is_extra_removed_by_action(const struct extra_type *pextra,
1018 const struct action *paction)
1019{
1020 enum unit_activity act = actres_get_activity(paction->result);
1021
1022 return is_extra_removed_by(pextra, activity_to_extra_rmcause(act));
1023}
1024
1025/************************************************************************/
1028 enum extra_cause activity_to_extra_cause(enum unit_activity act)
1029{
1030 switch (act) {
1031 case ACTIVITY_IRRIGATE:
1032 return EC_IRRIGATION;
1033 case ACTIVITY_MINE:
1034 return EC_MINE;
1035 case ACTIVITY_BASE:
1036 return EC_BASE;
1037 case ACTIVITY_GEN_ROAD:
1038 return EC_ROAD;
1039 default:
1040 break;
1041 }
1042
1043 return EC_NONE;
1044}
1045
1046/************************************************************************/
1049 enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
1050{
1051 switch (act) {
1052 case ACTIVITY_PILLAGE:
1053 return ERM_PILLAGE;
1054 case ACTIVITY_POLLUTION:
1055 return ERM_CLEANPOLLUTION;
1056 case ACTIVITY_FALLOUT:
1057 return ERM_CLEANFALLOUT;
1058 default:
1059 break;
1060 }
1061
1062 return ERM_NONE;
1063}
1064
1065/************************************************************************/
1068 struct player *extra_owner(const struct tile *ptile)
1069{
1070 return ptile->extras_owner;
1071}
1072
1073/************************************************************************/
1076 bool can_extra_appear(const struct extra_type *pextra, const struct tile *ptile)
1077{
1078 return !tile_has_extra(ptile, pextra)
1079 && is_extra_caused_by(pextra, EC_APPEARANCE)
1080 && is_native_tile_to_extra(pextra, ptile)
1081 && !extra_conflicting_on_tile(pextra, ptile)
1082 && are_reqs_active(&(const struct req_context) { .tile = ptile },
1083 tile_owner(ptile),
1084 &pextra->appearance_reqs, RPT_CERTAIN);
1085}
1086
1087/************************************************************************/
1090 bool can_extra_disappear(const struct extra_type *pextra, const struct tile *ptile)
1091{
1092 return tile_has_extra(ptile, pextra)
1093 && is_extra_removed_by(pextra, ERM_DISAPPEARANCE)
1094 && can_extra_be_removed(pextra, ptile)
1095 && are_reqs_active(&(const struct req_context) { .tile = ptile },
1096 tile_owner(ptile),
1097 &pextra->disappearance_reqs, RPT_CERTAIN);
1098}
1099
1100/************************************************************************/
1103 bool player_knows_extra_exist(const struct player *pplayer,
1104 const struct extra_type *pextra,
1105 const struct tile *ptile)
1106{
1107 if (!tile_has_extra(ptile, pextra)) {
1108 return FALSE;
1109 }
1110
1111 return research_invention_state(research_get(pplayer),
1112 pextra->visibility_req) == TECH_KNOWN;
1113}
actres_get_activity
enum unit_activity actres_get_activity(enum action_result result)
Definition actions.c:2136
base_types_free
void base_types_free(void)
Definition base.c:132
base.h
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
city_owner
#define city_owner(_pcity_)
Definition city.h:543
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
id
int int id
Definition editgui_g.h:28
reqs
struct @21::@22 reqs
is_extra_removed_by_worker_action
bool is_extra_removed_by_worker_action(const struct extra_type *pextra)
Definition extras.c:994
next_extra_for_tile
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:740
extra_type_by_rule_name
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:204
extra_causes_env_upset
bool extra_causes_env_upset(struct extra_type *pextra, enum environment_upset_type upset)
Definition extras.c:965
can_build_extra_base
bool can_build_extra_base(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:387
unit_can_displace_hut
bool unit_can_displace_hut(const struct unit *punit, const struct tile *ptile)
Definition extras.c:713
rand_extra_for_tile
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Definition extras.c:267
player_can_place_extra
bool player_can_place_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:462
user_extra_flags_init
void user_extra_flags_init(void)
Definition extras.c:858
extra_owner
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1068
extra_flag_is_in_use
bool extra_flag_is_in_use(enum extra_flag_id id)
Definition extras.c:936
extra_flag_helptxt
const char * extra_flag_helptxt(enum extra_flag_id id)
Definition extras.c:923
extra_type_by_translated_name
struct extra_type * extra_type_by_translated_name(const char *name)
Definition extras.c:227
set_user_extra_flag_name
void set_user_extra_flag_name(enum extra_flag_id id, const char *name, const char *helptxt)
Definition extras.c:882
is_extra_flag_near_tile
bool is_extra_flag_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:839
removed_by
static struct extra_type_list * removed_by[ERM_COUNT]
Definition extras.c:36
terr_claimer
static struct extra_type_list * terr_claimer
Definition extras.c:38
unit_can_enter_hut
bool unit_can_enter_hut(const struct unit *punit, const struct tile *ptile)
Definition extras.c:687
is_extra_caused_by_worker_action
bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
Definition extras.c:981
is_extra_flag_card_near
bool is_extra_flag_card_near(const struct civ_map *nmap, const struct tile *ptile, enum extra_flag_id flag)
Definition extras.c:819
extras_free
void extras_free(void)
Definition extras.c:80
can_extra_appear
bool can_extra_appear(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:1076
is_extra_near_tile
bool is_extra_near_tile(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:353
extra_number
int extra_number(const struct extra_type *pextra)
Definition extras.c:153
extra_has_flag
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:810
caused_by
static struct extra_type_list * caused_by[EC_LAST]
Definition extras.c:35
is_native_tile_to_extra
bool is_native_tile_to_extra(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:608
extra_type_list_by_cause
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:241
extra_type_list_by_rmcause
struct extra_type_list * extra_type_list_by_rmcause(enum extra_rmcause rmcause)
Definition extras.c:306
prev_extra_in_tile
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:765
hut_on_tile
bool hut_on_tile(const struct tile *ptile)
Definition extras.c:672
is_extra_card_near
bool is_extra_card_near(const struct civ_map *nmap, const struct tile *ptile, const struct extra_type *pextra)
Definition extras.c:337
extra_to_caused_by_list
void extra_to_caused_by_list(struct extra_type *pextra, enum extra_cause cause)
Definition extras.c:296
player_can_build_extra
bool player_can_build_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:442
extra_by_number
struct extra_type * extra_by_number(int id)
Definition extras.c:175
activity_to_extra_cause
enum extra_cause activity_to_extra_cause(enum unit_activity act)
Definition extras.c:1028
extras
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
extra_can_be_built
bool extra_can_be_built(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:368
is_native_extra_to_utype
bool is_native_extra_to_utype(const struct extra_type *pextra, const struct unit_type *punittype)
Definition extras.c:801
extra_flag_id_name_cb
const char * extra_flag_id_name_cb(enum extra_flag_id flag)
Definition extras.c:911
extra_conflicting_on_tile
bool extra_conflicting_on_tile(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:655
user_extra_flags
static struct user_flag user_extra_flags[MAX_NUM_USER_EXTRA_FLAGS]
Definition extras.c:33
extra_to_removed_by_list
void extra_to_removed_by_list(struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:316
can_extras_coexist
bool can_extras_coexist(const struct extra_type *pextra1, const struct extra_type *pextra2)
Definition extras.c:952
extra_flags_free
void extra_flags_free(void)
Definition extras.c:870
can_remove_extra
bool can_remove_extra(const struct extra_type *pextra, const struct unit *punit, const struct tile *ptile)
Definition extras.c:586
unit_hidden
static struct extra_type_list * unit_hidden
Definition extras.c:37
extra_type_list_of_terr_claimers
struct extra_type_list * extra_type_list_of_terr_claimers(void)
Definition extras.c:259
is_extra_caused_by_action
bool is_extra_caused_by_action(const struct extra_type *pextra, const struct action *paction)
Definition extras.c:1006
extra_rule_name
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:195
is_extra_removed_by
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:327
is_extra_removed_by_action
bool is_extra_removed_by_action(const struct extra_type *pextra, const struct action *paction)
Definition extras.c:1017
activity_to_extra_rmcause
enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
Definition extras.c:1049
player_can_remove_extra
bool player_can_remove_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:564
extra_type_list_of_unit_hiders
struct extra_type_list * extra_type_list_of_unit_hiders(void)
Definition extras.c:251
extras_init
void extras_init(void)
Definition extras.c:43
can_extra_be_removed
static bool can_extra_be_removed(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:531
extra_count
int extra_count(void)
Definition extras.c:145
player_knows_extra_exist
bool player_knows_extra_exist(const struct player *pplayer, const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:1103
can_build_extra
bool can_build_extra(const struct extra_type *pextra, const struct unit *punit, const struct tile *ptile)
Definition extras.c:507
is_native_extra_to_uclass
bool is_native_extra_to_uclass(const struct extra_type *pextra, const struct unit_class *pclass)
Definition extras.c:792
extra_name_translation
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:186
can_extra_disappear
bool can_extra_disappear(const struct extra_type *pextra, const struct tile *ptile)
Definition extras.c:1090
extras.h
extra_type_iterate
#define extra_type_iterate(_p)
Definition extras.h:291
extra_type_list_iterate
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:159
extra_type_iterate_end
#define extra_type_iterate_end
Definition extras.h:297
extra_type_by_rmcause_iterate_end
#define extra_type_by_rmcause_iterate_end
Definition extras.h:334
is_extra_caused_by
#define is_extra_caused_by(e, c)
Definition extras.h:196
extra_index
#define extra_index(_e_)
Definition extras.h:177
extra_type_by_rmcause_iterate
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:329
extra_type_re_active_iterate_end
#define extra_type_re_active_iterate_end
Definition extras.h:305
extra_type_list_iterate_end
#define extra_type_list_iterate_end
Definition extras.h:161
extra_base_get
#define extra_base_get(_e_)
Definition extras.h:184
extra_road_get
#define extra_road_get(_e_)
Definition extras.h:185
extra_type_re_active_iterate
#define extra_type_re_active_iterate(_p)
Definition extras.h:301
extra_type_by_cause_iterate_end
#define extra_type_by_cause_iterate_end
Definition extras.h:315
EF_LAST_USER_FLAG
#define EF_LAST_USER_FLAG
Definition extras.h:79
MAX_NUM_USER_EXTRA_FLAGS
#define MAX_NUM_USER_EXTRA_FLAGS
Definition extras.h:80
extra_type_by_cause_iterate
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:309
EC_LAST
#define EC_LAST
Definition fc_types.h:972
environment_upset_type
environment_upset_type
Definition fc_types.h:1129
EUT_NUCLEAR_WINTER
@ EUT_NUCLEAR_WINTER
Definition fc_types.h:1131
EUT_GLOBAL_WARMING
@ EUT_GLOBAL_WARMING
Definition fc_types.h:1130
RPT_CERTAIN
@ RPT_CERTAIN
Definition fc_types.h:586
RPT_POSSIBLE
@ RPT_POSSIBLE
Definition fc_types.h:585
EC_NONE
#define EC_NONE
Definition fc_types.h:967
MAX_EXTRA_TYPES
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
ERM_NONE
#define ERM_NONE
Definition fc_types.h:992
BORDERS_DISABLED
@ BORDERS_DISABLED
Definition fc_types.h:891
Qn_
#define Qn_(String)
Definition fcintl.h:89
user_flag_init
void user_flag_init(struct user_flag *flag)
Definition game.c:804
user_flag_free
void user_flag_free(struct user_flag *flag)
Definition game.c:813
game
struct civ_game game
Definition game.c:57
game.h
name
const char * name
Definition inputfile.c:127
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
map.h
adjc_iterate_end
#define adjc_iterate_end
Definition map.h:427
cardinal_adjc_iterate_end
#define cardinal_adjc_iterate_end
Definition map.h:453
adjc_iterate
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:422
cardinal_adjc_iterate
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:449
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_strdup
#define fc_strdup(str)
Definition mem.h:43
rule_name_get
static const char * rule_name_get(const struct name_translation *ptrans)
Definition name_translation.h:112
name_translation_get
static const char * name_translation_get(const struct name_translation *ptrans)
Definition name_translation.h:121
player_knows_techs_with_flag
bool player_knows_techs_with_flag(const struct player *pplayer, enum tech_flag_id flag)
Definition player.c:1304
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:34
are_reqs_active
bool are_reqs_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
Definition requirements.c:4361
research_get
struct research * research_get(const struct player *pplayer)
Definition research.c:126
research_invention_state
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:616
research.h
road_has_flag
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:410
road_types_free
void road_types_free(void)
Definition road.c:134
road.h
strvec_destroy
void strvec_destroy(struct strvec *psv)
Definition string_vector.c:71
string_vector.h
action
Definition actions.h:379
action::result
enum action_result result
Definition actions.h:382
city
Definition city.h:309
civ_game::control
struct packet_ruleset_control control
Definition game.h:83
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_map
Definition map_types.h:71
extra_type
Definition extras.h:85
extra_type::native_to
bv_unit_classes native_to
Definition extras.h:126
extra_type::conflicts
bv_extras conflicts
Definition extras.h:129
extra_type::rmcauses
uint8_t rmcauses
Definition extras.h:92
extra_type::appearance_reqs
struct requirement_vector appearance_reqs
Definition extras.h:104
extra_type::helptext
struct strvec * helptext
Definition extras.h:143
extra_type::flags
bv_extra_flags flags
Definition extras.h:128
extra_type::hiders
struct extra_type_list * hiders
Definition extras.h:138
extra_type::causes
uint16_t causes
Definition extras.h:91
extra_type::road
struct road_type * road
Definition extras.h:149
extra_type::resource
struct resource_type * resource
Definition extras.h:150
extra_type::bridged
struct extra_type_list * bridged
Definition extras.h:141
extra_type::ruledit_disabled
bool ruledit_disabled
Definition extras.h:88
extra_type::disappearance_reqs
struct requirement_vector disappearance_reqs
Definition extras.h:105
extra_type::generated
bool generated
Definition extras.h:113
extra_type::special_idx
int special_idx
Definition extras.h:147
extra_type::rmreqs
struct requirement_vector rmreqs
Definition extras.h:103
extra_type::data
struct extra_type::@24 data
extra_type::visibility_req
Tech_type_id visibility_req
Definition extras.h:133
extra_type::id
int id
Definition extras.h:86
extra_type::ruledit_dlg
void * ruledit_dlg
Definition extras.h:89
extra_type::reqs
struct requirement_vector reqs
Definition extras.h:102
extra_type::buildable
bool buildable
Definition extras.h:112
extra_type::infracost
int infracost
Definition extras.h:118
extra_type::name
struct name_translation name
Definition extras.h:87
extra_type::base
struct base_type * base
Definition extras.h:148
packet_game_info::borders
enum borders_mode borders
Definition packets_gen.h:133
packet_ruleset_control::num_extra_types
int num_extra_types
Definition packets_gen.h:1460
player
Definition player.h:249
req_context
Definition requirements.h:99
req_context::player
const struct player * player
Definition requirements.h:100
road_type
Definition road.h:75
terrain
Definition terrain.h:176
terrain::placing_time
int placing_time
Definition terrain.h:215
terrain::road_time
int road_time
Definition terrain.h:201
terrain::mining_time
int mining_time
Definition terrain.h:213
terrain::irrigation_time
int irrigation_time
Definition terrain.h:210
terrain::base_time
int base_time
Definition terrain.h:200
tile
Definition tile.h:49
tile::units
struct unit_list * units
Definition tile.h:57
tile::extras_owner
struct player * extras_owner
Definition tile.h:62
tile::placing
struct extra_type * placing
Definition tile.h:60
unit_class
Definition unittype.h:136
unit_type
Definition unittype.h:481
unit
Definition unit.h:138
unit::activity
enum unit_activity activity
Definition unit.h:157
user_flag
Definition game.h:73
user_flag::name
char * name
Definition game.h:74
user_flag::helptxt
char * helptxt
Definition game.h:75
fc_strcasecmp
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
A_NONE
#define A_NONE
Definition tech.h:43
resource_types_free
void resource_types_free(void)
Definition terrain.c:276
terrain_has_resource
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:243
terrain_has_flag
#define terrain_has_flag(terr, flag)
Definition terrain.h:269
tile_virtual_destroy
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1018
tile_remove_extra
void tile_remove_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:950
tile_virtual_new
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:966
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_worked
#define tile_worked(_tile)
Definition tile.h:113
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:109
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:146
tile_owner
#define tile_owner(_tile)
Definition tile.h:95
unit_can_do_action_sub_result
bool unit_can_do_action_sub_result(const struct unit *punit, enum action_sub_result sub_result)
Definition unit.c:350
unit_can_do_action_result
bool unit_can_do_action_result(const struct unit *punit, enum action_result result)
Definition unit.c:340
tile_changing_activities_iterate_end
#define tile_changing_activities_iterate_end
Definition unit.h:302
unit_owner
#define unit_owner(_pu)
Definition unit.h:387
tile_changing_activities_iterate
#define tile_changing_activities_iterate(_act_)
Definition unit.h:298
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
utype_class
#define utype_class(_t_)
Definition unittype.h:736
uclass_index
#define uclass_index(_c_)
Definition unittype.h:729