Freeciv-3.3: /fast/freeciv/nightly/main/common/oblig_reqs.c Source File

Freeciv-3.3

Loading...
Searching...
No Matches
oblig_reqs.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 "mem.h"
20
21/* common */
22#include "actres.h"
23#include "nation.h"
24#include "player.h"
25
26#include "oblig_reqs.h"
27
28
29/* Hard requirements relates to action result. */
30 static struct obligatory_req_vector oblig_hard_reqs_r[ACTRES_NONE];
31 static struct obligatory_req_vector oblig_hard_reqs_sr[ACT_SUB_RES_COUNT];
32
33
34/**********************************************************************/
46 static struct ae_contra_or *req_contradiction_or(int alternatives, ...)
47{
48 struct ae_contra_or *out;
49 int i;
50 va_list args;
51
52 fc_assert_ret_val(alternatives > 0, NULL);
53 out = fc_malloc(sizeof(*out));
54 out->users = 0;
55 out->alternatives = alternatives;
56 out->alternative = fc_malloc(sizeof(out->alternative[0]) * alternatives);
57
58 va_start(args, alternatives);
59 for (i = 0; i < alternatives; i++) {
60 struct requirement contradiction = va_arg(args, struct requirement);
61 bool is_target = va_arg(args, int);
62
63 out->alternative[i].req = contradiction;
64 out->alternative[i].is_target = is_target;
65 }
66 va_end(args);
67
68 return out;
69}
70
71/**********************************************************************/
76 static void ae_contra_close(struct ae_contra_or *contra)
77{
78 contra->users--;
79
80 if (contra->users < 1) {
81 /* No users left. Delete. */
82 FC_FREE(contra->alternative);
83 FC_FREE(contra);
84 }
85}
86
87/**********************************************************************/
97 static void voblig_hard_req_reg_sub_res(struct ae_contra_or *contras,
98 const char *error_message,
99 va_list args)
100{
101 struct obligatory_req oreq;
102 enum action_sub_result res;
103
104 /* A non null action message is used to indicate that an obligatory hard
105 * requirement is missing. */
106 fc_assert_ret(error_message);
107
108 /* Pack the obligatory hard requirement. */
109 oreq.contras = contras;
110 oreq.error_msg = error_message;
111
112 /* Add the obligatory hard requirement to each action sub result it
113 * applies to. */
114 while (ACT_SUB_RES_COUNT != (res = va_arg(args,
115 enum action_sub_result))) {
116 /* Any invalid action sub result should terminate the loop before this
117 * assertion. */
118 fc_assert_ret_msg(action_sub_result_is_valid(res),
119 "Invalid action result %d", res);
120
121 /* Add to list for action result */
122 obligatory_req_vector_append(&oblig_hard_reqs_sr[res], oreq);
123
124 /* Register the new user. */
125 oreq.contras->users++;
126 }
127}
128
129/**********************************************************************/
140 static void oblig_hard_req_reg_sub_res(struct ae_contra_or *contras,
141 const char *error_message,
142 ...)
143{
144 va_list args;
145
146 /* Add the obligatory hard requirement to each action result it applies
147 * to. */
148 va_start(args, error_message);
149 voblig_hard_req_reg_sub_res(contras, error_message, args);
150 va_end(args);
151}
152
153/**********************************************************************/
162 static void voblig_hard_req_reg(struct ae_contra_or *contras,
163 const char *error_message,
164 va_list args)
165{
166 struct obligatory_req oreq;
167 enum action_result res;
168 int users = 0;
169
170 /* A non null action message is used to indicate that an obligatory hard
171 * requirement is missing. */
172 fc_assert_ret(error_message);
173
174 /* Pack the obligatory hard requirement. */
175 oreq.contras = contras;
176 oreq.error_msg = error_message;
177
178 /* Add the obligatory hard requirement to each action result it applies
179 * to. */
180 while (ACTRES_NONE != (res = va_arg(args, enum action_result))) {
181 /* Any invalid action result should terminate the loop before this
182 * assertion. */
183 fc_assert_ret_msg(action_result_is_valid(res),
184 "Invalid action result %d", res);
185
186 /* Add to list for action result */
187 obligatory_req_vector_append(&oblig_hard_reqs_r[res], oreq);
188
189 /* Register the new user. */
190 users++;
191 }
192
193 fc_assert(users > 0);
194
195 oreq.contras->users += users;
196}
197
198/**********************************************************************/
207 static void oblig_hard_req_reg(struct ae_contra_or *contras,
208 const char *error_message,
209 ...)
210{
211 va_list args;
212
213 /* Add the obligatory hard requirement to each action result it applies
214 * to. */
215 va_start(args, error_message);
216 voblig_hard_req_reg(contras, error_message, args);
217 va_end(args);
218}
219
220/**********************************************************************/
227 static void oblig_hard_req_register(struct requirement contradiction,
228 bool is_target,
229 const char *error_message,
230 ...)
231{
232 struct ae_contra_or *contra;
233 va_list args;
234
235 /* Pack the obligatory hard requirement. */
236 contra = req_contradiction_or(1, contradiction, is_target);
237
238 /* Add the obligatory hard requirement to each action result it applies
239 * to. */
240 va_start(args, error_message);
241 voblig_hard_req_reg(contra, error_message, args);
242 va_end(args);
243}
244
245/**********************************************************************/
250 void hard_code_oblig_hard_reqs(void)
251{
252 /* Why this is a hard requirement: There is currently no point in
253 * allowing the listed actions against domestic targets.
254 * (Possible counter argument: crazy hack involving the Lua
255 * callback action_started_callback() to use an action to do
256 * something else. */
257 /* TODO: Unhardcode as a part of false flag operation support. */
258 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
259 FALSE, FALSE, TRUE, DRO_FOREIGN),
260 FALSE,
261 N_("All action enablers for %s must require a "
262 "foreign target."),
263 ACTRES_ESTABLISH_EMBASSY,
264 ACTRES_SPY_INVESTIGATE_CITY,
265 ACTRES_SPY_STEAL_GOLD,
266 ACTRES_STEAL_MAPS,
267 ACTRES_SPY_STEAL_TECH,
268 ACTRES_SPY_TARGETED_STEAL_TECH,
269 ACTRES_SPY_INCITE_CITY,
270 ACTRES_SPY_BRIBE_UNIT,
271 ACTRES_CAPTURE_UNITS,
272 ACTRES_CONQUER_CITY,
273 ACTRES_SPY_ESCAPE,
274 ACTRES_NONE);
275 /* The same for tile targeted actions that also can be done to unclaimed
276 * tiles. */
277 oblig_hard_req_reg(req_contradiction_or(
278 2,
279 req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
280 FALSE, FALSE, TRUE, DRO_FOREIGN),
281 FALSE,
282 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
283 FALSE, TRUE, TRUE,
284 CITYT_CLAIMED),
285 TRUE),
286 /* TRANS: error message for ruledit */
287 N_("All action enablers for %s must require a "
288 "non domestic target."),
289 ACTRES_PARADROP_CONQUER,
290 ACTRES_NONE);
291 /* The same for tile extras targeted actions that also can be done to
292 * unowned extras. */
293 oblig_hard_req_reg(req_contradiction_or(
294 2,
295 req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
296 FALSE, FALSE, TRUE, DRO_FOREIGN),
297 FALSE,
298 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
299 FALSE, TRUE, TRUE,
300 CITYT_EXTRAS_OWNED),
301 TRUE),
302 /* TRANS: error message for ruledit */
303 N_("All action enablers for %s must require a "
304 "non domestic target."),
305 ACTRES_CONQUER_EXTRAS,
306 ACTRES_NONE);
307
308 /* Why this is a hard requirement: There is currently no point in
309 * establishing an embassy when a real embassy already exists.
310 * (Possible exception: crazy hack using the Lua callback
311 * action_started_callback() to make establish embassy do something
312 * else even if the UI still call the action Establish Embassy) */
313 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
314 FALSE, TRUE, TRUE,
315 DRO_HAS_REAL_EMBASSY),
316 FALSE,
317 N_("All action enablers for %s must require the"
318 " absence of a real embassy."),
319 ACTRES_ESTABLISH_EMBASSY,
320 ACTRES_NONE);
321
322 /* Why this is a hard requirement: There is currently no point in
323 * fortifying an already fortified unit. */
324 oblig_hard_req_register(req_from_values(VUT_ACTIVITY, REQ_RANGE_LOCAL,
325 FALSE, TRUE, TRUE,
326 ACTIVITY_FORTIFIED),
327 FALSE,
328 N_("All action enablers for %s must require that"
329 " the actor unit isn't already fortified."),
330 ACTRES_FORTIFY,
331 ACTRES_NONE);
332
333 /* Why this is a hard requirement: Keep the old rules. Need to work
334 * out corner cases. */
335 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
336 FALSE, TRUE, TRUE, DRO_FOREIGN),
337 FALSE,
338 N_("All action enablers for %s must require"
339 " a domestic target."),
340 ACTRES_UPGRADE_UNIT, ACTRES_NONE);
341
342 /* Why this is a hard requirement: The code expects that only domestic and
343 * allied transports can be boarded. */
344 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
345 FALSE, TRUE, TRUE, DS_ARMISTICE),
346 FALSE,
347 N_("All action enablers for %s must require"
348 " a domestic or allied target."),
349 ACTRES_TRANSPORT_EMBARK,
350 ACTRES_TRANSPORT_BOARD,
351 ACTRES_TRANSPORT_LOAD,
352 ACTRES_NONE);
353 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
354 FALSE, TRUE, TRUE, DS_WAR),
355 FALSE,
356 N_("All action enablers for %s must require"
357 " a domestic or allied target."),
358 ACTRES_TRANSPORT_EMBARK,
359 ACTRES_TRANSPORT_BOARD,
360 ACTRES_TRANSPORT_LOAD,
361 ACTRES_NONE);
362 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
363 FALSE, TRUE, TRUE, DS_CEASEFIRE),
364 FALSE,
365 N_("All action enablers for %s must require"
366 " a domestic or allied target."),
367 ACTRES_TRANSPORT_EMBARK,
368 ACTRES_TRANSPORT_BOARD,
369 ACTRES_TRANSPORT_LOAD,
370 ACTRES_NONE);
371 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
372 FALSE, TRUE, TRUE, DS_PEACE),
373 FALSE,
374 N_("All action enablers for %s must require"
375 " a domestic or allied target."),
376 ACTRES_TRANSPORT_EMBARK,
377 ACTRES_TRANSPORT_BOARD,
378 ACTRES_TRANSPORT_LOAD,
379 ACTRES_NONE);
380 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
381 FALSE, TRUE, TRUE, DS_NO_CONTACT),
382 FALSE,
383 N_("All action enablers for %s must require"
384 " a domestic or allied target."),
385 ACTRES_TRANSPORT_EMBARK,
386 ACTRES_TRANSPORT_BOARD,
387 ACTRES_TRANSPORT_LOAD,
388 ACTRES_NONE);
389
390 /* Why this is a hard requirement: Preserve semantics of the Settlers
391 * unit type flag. */
392 oblig_hard_req_register(req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
393 FALSE, FALSE, TRUE,
394 UTYF_WORKERS),
395 FALSE,
396 N_("All action enablers for %s must require"
397 " that the actor has"
398 " the Workers utype flag."),
399 ACTRES_TRANSFORM_TERRAIN,
400 ACTRES_CULTIVATE,
401 ACTRES_PLANT,
402 ACTRES_ROAD,
403 ACTRES_MINE,
404 ACTRES_IRRIGATE,
405 ACTRES_CLEAN,
406 ACTRES_NONE);
407
408 /* Why this is a hard requirement: Preserve semantics of the rule that a
409 * *_time of 0 disables the action. */
410 oblig_hard_req_register(req_from_values(VUT_TERRAINALTER, REQ_RANGE_TILE,
411 FALSE, FALSE, FALSE,
412 TA_CAN_IRRIGATE),
413 TRUE,
414 N_("All action enablers for %s must require"
415 " that the target"
416 " tile's terrain's irrigation_time"
417 " is above 0. (See \"TerrainAlter\"'s"
418 " \"CanIrrigate\")"),
419 ACTRES_IRRIGATE,
420 ACTRES_NONE);
421 oblig_hard_req_register(req_from_values(VUT_TERRAINALTER, REQ_RANGE_TILE,
422 FALSE, FALSE, FALSE,
423 TA_CAN_MINE),
424 TRUE,
425 N_("All action enablers for %s must require"
426 " that the target"
427 " tile's terrain's mining_time"
428 " is above 0. (See \"TerrainAlter\"'s"
429 " \"CanMine\")"),
430 ACTRES_MINE,
431 ACTRES_NONE);
432 oblig_hard_req_register(req_from_values(VUT_TERRAINALTER, REQ_RANGE_TILE,
433 FALSE, FALSE, FALSE,
434 TA_CAN_ROAD),
435 TRUE,
436 N_("All action enablers for %s must require"
437 " that the target"
438 " tile's terrain's road_time"
439 " is above 0. (See \"TerrainAlter\"'s"
440 " \"CanRoad\")"),
441 ACTRES_ROAD,
442 ACTRES_NONE);
443 oblig_hard_req_register(req_from_values(VUT_TERRAINALTER, REQ_RANGE_TILE,
444 FALSE, FALSE, FALSE,
445 TA_CAN_BASE),
446 TRUE,
447 N_("All action enablers for %s must require"
448 " that the target"
449 " tile's terrain's base_time"
450 " is above 0. (See \"TerrainAlter\"'s"
451 " \"CanBase\")"),
452 ACTRES_BASE,
453 ACTRES_NONE);
454
455 /* Why this is a hard requirement: Preserve semantics of the NoCities
456 * terrain flag. */
457 oblig_hard_req_register(req_from_values(VUT_TERRFLAG, REQ_RANGE_TILE,
458 FALSE, TRUE, TRUE,
459 TER_NO_CITIES),
460 TRUE,
461 N_("All action enablers for %s must require that"
462 " the target doesn't have"
463 " the NoCities terrain flag."),
464 ACTRES_FOUND_CITY,
465 ACTRES_NONE);
466
467 /* It isn't possible to establish a trade route from a non existing
468 * city. The Freeciv code assumes this applies to Enter Marketplace
469 * too. */
470 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
471 FALSE, FALSE, TRUE,
472 USP_HAS_HOME_CITY),
473 FALSE,
474 N_("All action enablers for %s must require"
475 " that the actor has a home city."),
476 ACTRES_TRADE_ROUTE,
477 ACTRES_MARKETPLACE,
478 ACTRES_NONE);
479
480 /* Why this is a hard requirement:
481 * - preserve the semantics of the NonMil unit type flag. */
482 oblig_hard_req_reg(req_contradiction_or(
483 3,
484 req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
485 FALSE, FALSE, TRUE,
486 UTYF_CIVILIAN),
487 FALSE,
488 req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
489 FALSE, TRUE, TRUE, DS_PEACE),
490 FALSE,
491 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
492 FALSE, TRUE, TRUE,
493 CITYT_CLAIMED),
494 TRUE),
495 /* TRANS: error message for ruledit */
496 N_("All action enablers for %s must require"
497 " that the actor has the NonMil utype flag"
498 " or that the target tile is unclaimed"
499 " or that the diplomatic relation to"
500 " the target tile owner isn't peace."),
501 ACTRES_PARADROP,
502 ACTRES_PARADROP_CONQUER,
503 ACTRES_NONE);
504
505 /* Why this is a hard requirement: Preserve semantics of NonMil
506 * flag. Need to replace other uses in game engine before this can
507 * be demoted to a regular unit flag. */
508 oblig_hard_req_register(req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
509 FALSE, TRUE, TRUE, UTYF_CIVILIAN),
510 FALSE,
511 N_("All action enablers for %s must require"
512 " that the actor doesn't have"
513 " the NonMil utype flag."),
514 ACTRES_ATTACK,
515 ACTRES_CONQUER_CITY,
516 ACTRES_WIPE_UNITS,
517 ACTRES_NONE);
518 oblig_hard_req_reg(req_contradiction_or(
519 2,
520 req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
521 FALSE, TRUE, TRUE, UTYF_CIVILIAN),
522 FALSE,
523 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
524 FALSE, TRUE, TRUE,
525 CITYT_CENTER),
526 TRUE),
527 /* TRANS: error message for ruledit */
528 N_("All action enablers for %s must require"
529 " no city at the target tile or"
530 " that the actor doesn't have"
531 " the NonMil utype flag."),
532 ACTRES_PARADROP_CONQUER,
533 ACTRES_NONE);
534
535 /* Why this is a hard requirement: Preserve semantics of
536 * CanOccupyCity unit class flag. */
537 oblig_hard_req_register(req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
538 FALSE, FALSE, TRUE,
539 UCF_CAN_OCCUPY_CITY),
540 FALSE,
541 N_("All action enablers for %s must require"
542 " that the actor has"
543 " the CanOccupyCity uclass flag."),
544 ACTRES_CONQUER_CITY,
545 ACTRES_NONE);
546 oblig_hard_req_reg(req_contradiction_or(
547 2,
548 req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
549 FALSE, FALSE, TRUE,
550 UCF_CAN_OCCUPY_CITY),
551 FALSE,
552 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
553 FALSE, TRUE, TRUE,
554 CITYT_CENTER),
555 TRUE),
556 /* TRANS: error message for ruledit */
557 N_("All action enablers for %s must require"
558 " no city at the target tile or"
559 " that the actor has"
560 " the CanOccupyCity uclass flag."),
561 ACTRES_PARADROP_CONQUER,
562 ACTRES_NONE);
563
564 /* Why this is a hard requirement: Consistency with ACTRES_ATTACK.
565 * Assumed by other locations in the Freeciv code. Examples:
566 * unit_move_to_tile_test(), unit_conquer_city() and do_paradrop(). */
567 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
568 FALSE, FALSE, TRUE, DS_WAR),
569 FALSE,
570 N_("All action enablers for %s must require"
571 " that the actor is at war with the target."),
572 ACTRES_CONQUER_CITY,
573 ACTRES_NONE);
574 oblig_hard_req_reg(req_contradiction_or(
575 2,
576 req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
577 FALSE, FALSE, TRUE, DS_WAR),
578 FALSE,
579 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
580 FALSE, TRUE, TRUE,
581 CITYT_CENTER),
582 TRUE),
583 /* TRANS: error message for ruledit */
584 N_("All action enablers for %s must require"
585 " no city at the target tile or"
586 " that the actor is at war with the target."),
587 ACTRES_PARADROP_CONQUER,
588 ACTRES_NONE);
589
590 /* Why this is a hard requirement: a unit must move into a city to
591 * conquer it, move into a transport to embark, move out of a transport
592 * to disembark from it, move into an extra to conquer it and move into a
593 * hut to enter/frighten it. */
594 oblig_hard_req_register(req_from_values(VUT_MINMOVES, REQ_RANGE_LOCAL,
595 FALSE, FALSE, TRUE, 1),
596 FALSE,
597 N_("All action enablers for %s must require"
598 " that the actor has a movement point left."),
599 ACTRES_CONQUER_CITY,
600 ACTRES_TRANSPORT_DISEMBARK,
601 ACTRES_TRANSPORT_EMBARK,
602 ACTRES_CONQUER_EXTRAS,
603 ACTRES_HUT_ENTER,
604 ACTRES_HUT_FRIGHTEN,
605 ACTRES_UNIT_MOVE,
606 ACTRES_NONE);
607
608 /* Why this is a hard requirement: this eliminates the need to
609 * check if units transported by the actor unit can exist at the
610 * same tile as all the units in the occupied city.
611 *
612 * This makes an implicit rule explicit:
613 * 1. A unit must move into a city to conquer it.
614 * 2. It can't move into the city if the tile contains a non-allied
615 * unit (see unit_move_to_tile_test()).
616 * 3. A city could, at the time this rule was made explicit, only
617 * contain units allied to its owner.
618 * 3. A player could, at the time this rule was made explicit, not
619 * be allied to a player that is at war with another ally.
620 * 4. A player could, at the time this rule was made explicit, only
621 * conquer a city belonging to someone they were at war with.
622 * Conclusion: the conquered city had to be empty.
623 */
624 oblig_hard_req_register(req_from_values(VUT_MAXTILEUNITS, REQ_RANGE_TILE,
625 FALSE, FALSE, TRUE, 0),
626 TRUE,
627 N_("All action enablers for %s must require"
628 " that the target city is empty."),
629 ACTRES_CONQUER_CITY,
630 ACTRES_NONE);
631
632 /* Why this is a hard requirement: Assumed in the code. Corner case
633 * where diplomacy prevents a transported unit to go to the target
634 * tile. The paradrop code doesn't check if transported units can
635 * coexist with the target tile city and units. */
636 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
637 FALSE, TRUE, TRUE,
638 USP_TRANSPORTING),
639 FALSE,
640 N_("All action enablers for %s must require"
641 " that the actor isn't transporting"
642 " another unit."),
643 ACTRES_PARADROP,
644 ACTRES_PARADROP_CONQUER,
645 ACTRES_AIRLIFT,
646 ACTRES_NONE);
647
648 /* Why this is a hard requirement: sanity. */
649 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
650 FALSE, FALSE, FALSE,
651 USP_HAS_HOME_CITY),
652 FALSE,
653 N_("All action enablers for %s must require"
654 " that the actor has a home city."),
655 ACTRES_HOMELESS, ACTRES_NONE);
656
657 /* Why this is a hard requirement: Assumed in the code.
658 * See hrm Bug #772516 - https://www.hostedredmine.com/issues/772516 */
659 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
660 FALSE, TRUE, TRUE,
661 USP_TRANSPORTING),
662 TRUE,
663 N_("All action enablers for %s must require"
664 " that the target isn't transporting another"
665 " unit."),
666 ACTRES_CAPTURE_UNITS, ACTRES_NONE);
667
668 /* Why this is a hard requirement: sanity. */
669 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
670 FALSE, FALSE, TRUE,
671 USP_TRANSPORTING),
672 TRUE,
673 N_("All action enablers for %s must require"
674 " that the target is transporting a unit."),
675 ACTRES_TRANSPORT_DEBOARD, ACTRES_NONE);
676 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
677 FALSE, FALSE, TRUE,
678 USP_TRANSPORTED),
679 FALSE,
680 N_("All action enablers for %s must require"
681 " that the actor is transported."),
682 ACTRES_TRANSPORT_DEBOARD,
683 ACTRES_TRANSPORT_DISEMBARK,
684 ACTRES_NONE);
685 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
686 FALSE, FALSE, TRUE,
687 USP_LIVABLE_TILE),
688 FALSE,
689 N_("All action enablers for %s must require"
690 " that the actor is on a livable tile."),
691 ACTRES_TRANSPORT_DEBOARD, ACTRES_NONE);
692
693 /* Why this is a hard requirement: sanity. */
694 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
695 FALSE, FALSE, TRUE,
696 USP_TRANSPORTING),
697 FALSE,
698 N_("All action enablers for %s must require"
699 " that the actor is transporting a unit."),
700 ACTRES_TRANSPORT_UNLOAD, ACTRES_NONE);
701 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
702 FALSE, FALSE, TRUE,
703 USP_TRANSPORTED),
704 TRUE,
705 N_("All action enablers for %s must require"
706 " that the target is transported."),
707 ACTRES_TRANSPORT_UNLOAD, ACTRES_NONE);
708 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
709 FALSE, FALSE, TRUE,
710 USP_LIVABLE_TILE),
711 TRUE,
712 N_("All action enablers for %s must require"
713 " that the target is on a livable tile."),
714 ACTRES_TRANSPORT_UNLOAD, ACTRES_NONE);
715
716 /* Why this is a hard requirement: Use ACTRES_TRANSPORT_DISEMBARK to
717 * disembark. Assumed by the Freeciv code. */
718 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
719 FALSE, TRUE, TRUE,
720 USP_TRANSPORTED),
721 FALSE,
722 N_("All action enablers for %s must require"
723 " that the actor isn't transported."),
724 ACTRES_UNIT_MOVE,
725 ACTRES_TELEPORT, ACTRES_TELEPORT_CONQUER,
726 ACTRES_NONE);
727
728 /* Why this is a hard requirement: assumed by the Freeciv code. */
729 oblig_hard_req_register(req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
730 FALSE, FALSE, TRUE,
731 CITYT_CENTER),
732 FALSE,
733 N_("All action enablers for %s must require"
734 " that the actor unit is in a city."),
735 ACTRES_AIRLIFT,
736 ACTRES_NONE);
737
738 /* Why this is a hard requirement: Give meaning to the HutFrighten unit
739 * class flag. The point of it is to keep our options open for how both
740 * entering and frightening a hut at the same tile should be handled.
741 * See hrm Feature #920427 */
742 oblig_hard_req_reg_sub_res(req_contradiction_or(
743 1,
744 req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
745 FALSE, TRUE, FALSE,
746 UCF_HUT_FRIGHTEN),
747 FALSE),
748 N_("All action enablers for %s must require"
749 " that the actor unit doesn't have the"
750 " HutFrighten unit class flag."),
751 ACT_SUB_RES_HUT_ENTER,
752 ACT_SUB_RES_COUNT);
753 oblig_hard_req_reg_sub_res(req_contradiction_or(
754 1,
755 req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
756 FALSE, FALSE, FALSE,
757 UCF_HUT_FRIGHTEN),
758 FALSE),
759 N_("All action enablers for %s must require"
760 " that the actor unit has the HutFrighten"
761 " unit class flag."),
762 ACT_SUB_RES_HUT_FRIGHTEN,
763 ACT_SUB_RES_COUNT);
764}
765
766/**********************************************************************/
770 void hard_code_oblig_hard_reqs_ruleset(void)
771{
772 /* Why this is a hard requirement: the "animal can't conquer a city"
773 * rule. Assumed in unit_can_take_over(). */
774 nations_iterate(pnation) {
775 if (nation_barbarian_type(pnation) == ANIMAL_BARBARIAN) {
776 oblig_hard_req_register(req_from_values(VUT_NATION, REQ_RANGE_PLAYER,
777 FALSE, TRUE, TRUE,
778 nation_number(pnation)),
779 FALSE,
780 N_("All action enablers for %s must require"
781 " a non animal player actor."),
782 ACTRES_CONQUER_CITY,
783 ACTRES_NONE);
784 oblig_hard_req_reg(req_contradiction_or(
785 2,
786 req_from_values(VUT_NATION, REQ_RANGE_PLAYER,
787 FALSE, TRUE, TRUE,
788 nation_number(pnation)),
789 FALSE,
790 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
791 FALSE, TRUE, TRUE,
792 CITYT_CENTER),
793 TRUE),
794 /* TRANS: error message for ruledit */
795 N_("All action enablers for %s must require"
796 " no city at the target tile or"
797 " a non animal player actor."),
798 ACTRES_PARADROP_CONQUER,
799 ACTRES_NONE);
800 }
801 } nations_iterate_end;
802}
803
804/**********************************************************************/
807 void oblig_hard_reqs_init(void)
808{
809 int i;
810
811 /* Obligatory hard requirements sorted by action result in memory. */
812 for (i = 0; i < ACTRES_NONE; i++) {
813 /* Prepare each action result's storage area. */
814 obligatory_req_vector_init(&oblig_hard_reqs_r[i]);
815 }
816
817 /* Obligatory hard requirements sorted by action sub result in memory. */
818 for (i = 0; i < ACT_SUB_RES_COUNT; i++) {
819 /* Prepare each action sub result's storage area. */
820 obligatory_req_vector_init(&oblig_hard_reqs_sr[i]);
821 }
822}
823
824/**********************************************************************/
827 void oblig_hard_reqs_free(void)
828{
829 int i;
830
831 for (i = 0; i < ACTRES_NONE; i++) {
832 obligatory_req_vector_iterate(&oblig_hard_reqs_r[i], oreq) {
833 ae_contra_close(oreq->contras);
834 } obligatory_req_vector_iterate_end;
835 obligatory_req_vector_free(&oblig_hard_reqs_r[i]);
836 }
837
838 for (i = 0; i < ACT_SUB_RES_COUNT; i++) {
839 obligatory_req_vector_iterate(&oblig_hard_reqs_sr[i], oreq) {
840 ae_contra_close(oreq->contras);
841 } obligatory_req_vector_iterate_end;
842 obligatory_req_vector_free(&oblig_hard_reqs_sr[i]);
843 }
844}
845
846/**********************************************************************/
852 struct obligatory_req_vector *oblig_hard_reqs_get(enum action_result res)
853{
854 return &(oblig_hard_reqs_r[res]);
855}
856
857/**********************************************************************/
863 struct obligatory_req_vector *oblig_hard_reqs_get_sub(enum action_sub_result res)
864{
865 return &(oblig_hard_reqs_sr[res]);
866}
actres.h
incite_cost
char * incite_cost
Definition comments.c:74
ACTRES_NONE
#define ACTRES_NONE
Definition fc_types.h:331
N_
#define N_(String)
Definition fcintl.h:69
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_msg
#define fc_assert_ret_msg(condition, message,...)
Definition log.h:205
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
mem.h
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
nation_number
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
nation_barbarian_type
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:211
nation.h
nations_iterate_end
#define nations_iterate_end
Definition nation.h:336
nations_iterate
#define nations_iterate(NAME_pnation)
Definition nation.h:333
oblig_hard_req_reg
static void oblig_hard_req_reg(struct ae_contra_or *contras, const char *error_message,...)
Definition oblig_reqs.c:207
voblig_hard_req_reg
static void voblig_hard_req_reg(struct ae_contra_or *contras, const char *error_message, va_list args)
Definition oblig_reqs.c:162
oblig_hard_reqs_r
static struct obligatory_req_vector oblig_hard_reqs_r[ACTRES_NONE]
Definition oblig_reqs.c:30
oblig_hard_reqs_init
void oblig_hard_reqs_init(void)
Definition oblig_reqs.c:807
req_contradiction_or
static struct ae_contra_or * req_contradiction_or(int alternatives,...)
Definition oblig_reqs.c:46
oblig_hard_reqs_free
void oblig_hard_reqs_free(void)
Definition oblig_reqs.c:827
ae_contra_close
static void ae_contra_close(struct ae_contra_or *contra)
Definition oblig_reqs.c:76
oblig_hard_reqs_sr
static struct obligatory_req_vector oblig_hard_reqs_sr[ACT_SUB_RES_COUNT]
Definition oblig_reqs.c:31
oblig_hard_req_reg_sub_res
static void oblig_hard_req_reg_sub_res(struct ae_contra_or *contras, const char *error_message,...)
Definition oblig_reqs.c:140
voblig_hard_req_reg_sub_res
static void voblig_hard_req_reg_sub_res(struct ae_contra_or *contras, const char *error_message, va_list args)
Definition oblig_reqs.c:97
hard_code_oblig_hard_reqs_ruleset
void hard_code_oblig_hard_reqs_ruleset(void)
Definition oblig_reqs.c:770
hard_code_oblig_hard_reqs
void hard_code_oblig_hard_reqs(void)
Definition oblig_reqs.c:250
oblig_hard_reqs_get
struct obligatory_req_vector * oblig_hard_reqs_get(enum action_result res)
Definition oblig_reqs.c:852
oblig_hard_reqs_get_sub
struct obligatory_req_vector * oblig_hard_reqs_get_sub(enum action_sub_result res)
Definition oblig_reqs.c:863
oblig_hard_req_register
static void oblig_hard_req_register(struct requirement contradiction, bool is_target, const char *error_message,...)
Definition oblig_reqs.c:227
oblig_reqs.h
obligatory_req_vector_iterate_end
#define obligatory_req_vector_iterate_end
Definition oblig_reqs.h:48
obligatory_req_vector_iterate
#define obligatory_req_vector_iterate(obreq_vec, pobreq)
Definition oblig_reqs.h:46
player.h
req_from_values
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
Definition requirements.c:1425
ae_contra_or
Definition oblig_reqs.h:51
ae_contra_or::alternatives
int alternatives
Definition oblig_reqs.h:52
obligatory_req
Definition oblig_reqs.h:33
obligatory_req::contras
struct ae_contra_or * contras
Definition oblig_reqs.h:36
requirement
Definition requirements.h:81
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47