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_BASE,
404 ACTRES_MINE,
405 ACTRES_IRRIGATE,
406 ACTRES_CLEAN,
407 ACTRES_NONE);
408
409 /* Why this is a hard requirement: Preserve semantics of the rule that a
410 * *_time of 0 disables the action. */
411 oblig_hard_req_register(req_from_values(VUT_TERRAINALTER, REQ_RANGE_TILE,
412 FALSE, FALSE, FALSE,
413 TA_CAN_IRRIGATE),
414 TRUE,
415 N_("All action enablers for %s must require"
416 " that the target"
417 " tile's terrain's irrigation_time"
418 " is above 0. (See \"TerrainAlter\"'s"
419 " \"CanIrrigate\")"),
420 ACTRES_IRRIGATE,
421 ACTRES_NONE);
422 oblig_hard_req_register(req_from_values(VUT_TERRAINALTER, REQ_RANGE_TILE,
423 FALSE, FALSE, FALSE,
424 TA_CAN_MINE),
425 TRUE,
426 N_("All action enablers for %s must require"
427 " that the target"
428 " tile's terrain's mining_time"
429 " is above 0. (See \"TerrainAlter\"'s"
430 " \"CanMine\")"),
431 ACTRES_MINE,
432 ACTRES_NONE);
433 oblig_hard_req_register(req_from_values(VUT_TERRAINALTER, REQ_RANGE_TILE,
434 FALSE, FALSE, FALSE,
435 TA_CAN_ROAD),
436 TRUE,
437 N_("All action enablers for %s must require"
438 " that the target"
439 " tile's terrain's road_time"
440 " is above 0. (See \"TerrainAlter\"'s"
441 " \"CanRoad\")"),
442 ACTRES_ROAD,
443 ACTRES_NONE);
444 oblig_hard_req_register(req_from_values(VUT_TERRAINALTER, REQ_RANGE_TILE,
445 FALSE, FALSE, FALSE,
446 TA_CAN_BASE),
447 TRUE,
448 N_("All action enablers for %s must require"
449 " that the target"
450 " tile's terrain's base_time"
451 " is above 0. (See \"TerrainAlter\"'s"
452 " \"CanBase\")"),
453 ACTRES_BASE,
454 ACTRES_NONE);
455
456 /* Why this is a hard requirement: Preserve semantics of the NoCities
457 * terrain flag. */
458 oblig_hard_req_register(req_from_values(VUT_TERRFLAG, REQ_RANGE_TILE,
459 FALSE, TRUE, TRUE,
460 TER_NO_CITIES),
461 TRUE,
462 N_("All action enablers for %s must require that"
463 " the target doesn't have"
464 " the NoCities terrain flag."),
465 ACTRES_FOUND_CITY,
466 ACTRES_NONE);
467
468 /* It isn't possible to establish a trade route from a non existing
469 * city. The Freeciv code assumes this applies to Enter Marketplace
470 * too. */
471 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
472 FALSE, FALSE, TRUE,
473 USP_HAS_HOME_CITY),
474 FALSE,
475 N_("All action enablers for %s must require"
476 " that the actor has a home city."),
477 ACTRES_TRADE_ROUTE,
478 ACTRES_MARKETPLACE,
479 ACTRES_NONE);
480
481 /* Why this is a hard requirement:
482 * - preserve the semantics of the NonMil unit type flag. */
483 oblig_hard_req_reg(req_contradiction_or(
484 3,
485 req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
486 FALSE, FALSE, TRUE,
487 UTYF_CIVILIAN),
488 FALSE,
489 req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
490 FALSE, TRUE, TRUE, DS_PEACE),
491 FALSE,
492 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
493 FALSE, TRUE, TRUE,
494 CITYT_CLAIMED),
495 TRUE),
496 /* TRANS: error message for ruledit */
497 N_("All action enablers for %s must require"
498 " that the actor has the NonMil utype flag"
499 " or that the target tile is unclaimed"
500 " or that the diplomatic relation to"
501 " the target tile owner isn't peace."),
502 ACTRES_PARADROP,
503 ACTRES_PARADROP_CONQUER,
504 ACTRES_NONE);
505
506 /* Why this is a hard requirement: Preserve semantics of NonMil
507 * flag. Need to replace other uses in game engine before this can
508 * be demoted to a regular unit flag. */
509 oblig_hard_req_register(req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
510 FALSE, TRUE, TRUE, UTYF_CIVILIAN),
511 FALSE,
512 N_("All action enablers for %s must require"
513 " that the actor doesn't have"
514 " the NonMil utype flag."),
515 ACTRES_ATTACK,
516 ACTRES_CONQUER_CITY,
517 ACTRES_WIPE_UNITS,
518 ACTRES_NONE);
519 oblig_hard_req_reg(req_contradiction_or(
520 2,
521 req_from_values(VUT_UTFLAG, REQ_RANGE_LOCAL,
522 FALSE, TRUE, TRUE, UTYF_CIVILIAN),
523 FALSE,
524 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
525 FALSE, TRUE, TRUE,
526 CITYT_CENTER),
527 TRUE),
528 /* TRANS: error message for ruledit */
529 N_("All action enablers for %s must require"
530 " no city at the target tile or"
531 " that the actor doesn't have"
532 " the NonMil utype flag."),
533 ACTRES_PARADROP_CONQUER,
534 ACTRES_NONE);
535
536 /* Why this is a hard requirement: Preserve semantics of
537 * CanOccupyCity unit class flag. */
538 oblig_hard_req_register(req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
539 FALSE, FALSE, TRUE,
540 UCF_CAN_OCCUPY_CITY),
541 FALSE,
542 N_("All action enablers for %s must require"
543 " that the actor has"
544 " the CanOccupyCity uclass flag."),
545 ACTRES_CONQUER_CITY,
546 ACTRES_NONE);
547 oblig_hard_req_reg(req_contradiction_or(
548 2,
549 req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
550 FALSE, FALSE, TRUE,
551 UCF_CAN_OCCUPY_CITY),
552 FALSE,
553 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
554 FALSE, TRUE, TRUE,
555 CITYT_CENTER),
556 TRUE),
557 /* TRANS: error message for ruledit */
558 N_("All action enablers for %s must require"
559 " no city at the target tile or"
560 " that the actor has"
561 " the CanOccupyCity uclass flag."),
562 ACTRES_PARADROP_CONQUER,
563 ACTRES_NONE);
564
565 /* Why this is a hard requirement: Consistency with ACTRES_ATTACK.
566 * Assumed by other locations in the Freeciv code. Examples:
567 * unit_move_to_tile_test(), unit_conquer_city() and do_paradrop(). */
568 oblig_hard_req_register(req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
569 FALSE, FALSE, TRUE, DS_WAR),
570 FALSE,
571 N_("All action enablers for %s must require"
572 " that the actor is at war with the target."),
573 ACTRES_CONQUER_CITY,
574 ACTRES_NONE);
575 oblig_hard_req_reg(req_contradiction_or(
576 2,
577 req_from_values(VUT_DIPLREL, REQ_RANGE_LOCAL,
578 FALSE, FALSE, TRUE, DS_WAR),
579 FALSE,
580 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
581 FALSE, TRUE, TRUE,
582 CITYT_CENTER),
583 TRUE),
584 /* TRANS: error message for ruledit */
585 N_("All action enablers for %s must require"
586 " no city at the target tile or"
587 " that the actor is at war with the target."),
588 ACTRES_PARADROP_CONQUER,
589 ACTRES_NONE);
590
591 /* Why this is a hard requirement: a unit must move into a city to
592 * conquer it, move into a transport to embark, move out of a transport
593 * to disembark from it, move into an extra to conquer it and move into a
594 * hut to enter/frighten it. */
595 oblig_hard_req_register(req_from_values(VUT_MINMOVES, REQ_RANGE_LOCAL,
596 FALSE, FALSE, TRUE, 1),
597 FALSE,
598 N_("All action enablers for %s must require"
599 " that the actor has a movement point left."),
600 ACTRES_CONQUER_CITY,
601 ACTRES_TRANSPORT_DISEMBARK,
602 ACTRES_TRANSPORT_EMBARK,
603 ACTRES_CONQUER_EXTRAS,
604 ACTRES_HUT_ENTER,
605 ACTRES_HUT_FRIGHTEN,
606 ACTRES_UNIT_MOVE,
607 ACTRES_NONE);
608
609 /* Why this is a hard requirement: this eliminates the need to
610 * check if units transported by the actor unit can exist at the
611 * same tile as all the units in the occupied city.
612 *
613 * This makes an implicit rule explicit:
614 * 1. A unit must move into a city to conquer it.
615 * 2. It can't move into the city if the tile contains a non-allied
616 * unit (see unit_move_to_tile_test()).
617 * 3. A city could, at the time this rule was made explicit, only
618 * contain units allied to its owner.
619 * 3. A player could, at the time this rule was made explicit, not
620 * be allied to a player that is at war with another ally.
621 * 4. A player could, at the time this rule was made explicit, only
622 * conquer a city belonging to someone they were at war with.
623 * Conclusion: the conquered city had to be empty.
624 */
625 oblig_hard_req_register(req_from_values(VUT_MAXTILEUNITS, REQ_RANGE_TILE,
626 FALSE, FALSE, TRUE, 0),
627 TRUE,
628 N_("All action enablers for %s must require"
629 " that the target city is empty."),
630 ACTRES_CONQUER_CITY,
631 ACTRES_NONE);
632
633 /* Why this is a hard requirement: Assumed in the code. Corner case
634 * where diplomacy prevents a transported unit to go to the target
635 * tile. The paradrop code doesn't check if transported units can
636 * coexist with the target tile city and units. */
637 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
638 FALSE, TRUE, TRUE,
639 USP_TRANSPORTING),
640 FALSE,
641 N_("All action enablers for %s must require"
642 " that the actor isn't transporting"
643 " another unit."),
644 ACTRES_PARADROP,
645 ACTRES_PARADROP_CONQUER,
646 ACTRES_AIRLIFT,
647 ACTRES_NONE);
648
649 /* Why this is a hard requirement: sanity. */
650 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
651 FALSE, FALSE, FALSE,
652 USP_HAS_HOME_CITY),
653 FALSE,
654 N_("All action enablers for %s must require"
655 " that the actor has a home city."),
656 ACTRES_HOMELESS, ACTRES_NONE);
657
658 /* Why this is a hard requirement: Assumed in the code.
659 * See hrm Bug #772516 - https://www.hostedredmine.com/issues/772516 */
660 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
661 FALSE, TRUE, TRUE,
662 USP_TRANSPORTING),
663 TRUE,
664 N_("All action enablers for %s must require"
665 " that the target isn't transporting another"
666 " unit."),
667 ACTRES_CAPTURE_UNITS, ACTRES_NONE);
668
669 /* Why this is a hard requirement: sanity. */
670 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
671 FALSE, FALSE, TRUE,
672 USP_TRANSPORTING),
673 TRUE,
674 N_("All action enablers for %s must require"
675 " that the target is transporting a unit."),
676 ACTRES_TRANSPORT_DEBOARD, ACTRES_NONE);
677 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
678 FALSE, FALSE, TRUE,
679 USP_TRANSPORTED),
680 FALSE,
681 N_("All action enablers for %s must require"
682 " that the actor is transported."),
683 ACTRES_TRANSPORT_DEBOARD,
684 ACTRES_TRANSPORT_DISEMBARK,
685 ACTRES_NONE);
686 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
687 FALSE, FALSE, TRUE,
688 USP_LIVABLE_TILE),
689 FALSE,
690 N_("All action enablers for %s must require"
691 " that the actor is on a livable tile."),
692 ACTRES_TRANSPORT_DEBOARD, ACTRES_NONE);
693
694 /* Why this is a hard requirement: sanity. */
695 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
696 FALSE, FALSE, TRUE,
697 USP_TRANSPORTING),
698 FALSE,
699 N_("All action enablers for %s must require"
700 " that the actor is transporting a unit."),
701 ACTRES_TRANSPORT_UNLOAD, ACTRES_NONE);
702 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
703 FALSE, FALSE, TRUE,
704 USP_TRANSPORTED),
705 TRUE,
706 N_("All action enablers for %s must require"
707 " that the target is transported."),
708 ACTRES_TRANSPORT_UNLOAD, ACTRES_NONE);
709 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
710 FALSE, FALSE, TRUE,
711 USP_LIVABLE_TILE),
712 TRUE,
713 N_("All action enablers for %s must require"
714 " that the target is on a livable tile."),
715 ACTRES_TRANSPORT_UNLOAD, ACTRES_NONE);
716
717 /* Why this is a hard requirement: Use ACTRES_TRANSPORT_DISEMBARK to
718 * disembark. Assumed by the Freeciv code. */
719 oblig_hard_req_register(req_from_values(VUT_UNITSTATE, REQ_RANGE_LOCAL,
720 FALSE, TRUE, TRUE,
721 USP_TRANSPORTED),
722 FALSE,
723 N_("All action enablers for %s must require"
724 " that the actor isn't transported."),
725 ACTRES_UNIT_MOVE,
726 ACTRES_TELEPORT, ACTRES_TELEPORT_CONQUER,
727 ACTRES_NONE);
728
729 /* Why this is a hard requirement: assumed by the Freeciv code. */
730 oblig_hard_req_register(req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
731 FALSE, FALSE, TRUE,
732 CITYT_CENTER),
733 FALSE,
734 N_("All action enablers for %s must require"
735 " that the actor unit is in a city."),
736 ACTRES_AIRLIFT,
737 ACTRES_NONE);
738
739 /* Why this is a hard requirement: Give meaning to the HutFrighten unit
740 * class flag. The point of it is to keep our options open for how both
741 * entering and frightening a hut at the same tile should be handled.
742 * See hrm Feature #920427 */
743 oblig_hard_req_reg_sub_res(req_contradiction_or(
744 1,
745 req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
746 FALSE, TRUE, FALSE,
747 UCF_HUT_FRIGHTEN),
748 FALSE),
749 N_("All action enablers for %s must require"
750 " that the actor unit doesn't have the"
751 " HutFrighten unit class flag."),
752 ACT_SUB_RES_HUT_ENTER,
753 ACT_SUB_RES_COUNT);
754 oblig_hard_req_reg_sub_res(req_contradiction_or(
755 1,
756 req_from_values(VUT_UCFLAG, REQ_RANGE_LOCAL,
757 FALSE, FALSE, FALSE,
758 UCF_HUT_FRIGHTEN),
759 FALSE),
760 N_("All action enablers for %s must require"
761 " that the actor unit has the HutFrighten"
762 " unit class flag."),
763 ACT_SUB_RES_HUT_FRIGHTEN,
764 ACT_SUB_RES_COUNT);
765}
766
767/**********************************************************************/
771 void hard_code_oblig_hard_reqs_ruleset(void)
772{
773 /* Why this is a hard requirement: the "animal can't conquer a city"
774 * rule. Assumed in unit_can_take_over(). */
775 nations_iterate(pnation) {
776 if (nation_barbarian_type(pnation) == ANIMAL_BARBARIAN) {
777 oblig_hard_req_register(req_from_values(VUT_NATION, REQ_RANGE_PLAYER,
778 FALSE, TRUE, TRUE,
779 nation_number(pnation)),
780 FALSE,
781 N_("All action enablers for %s must require"
782 " a non animal player actor."),
783 ACTRES_CONQUER_CITY,
784 ACTRES_NONE);
785 oblig_hard_req_reg(req_contradiction_or(
786 2,
787 req_from_values(VUT_NATION, REQ_RANGE_PLAYER,
788 FALSE, TRUE, TRUE,
789 nation_number(pnation)),
790 FALSE,
791 req_from_values(VUT_CITYTILE, REQ_RANGE_TILE,
792 FALSE, TRUE, TRUE,
793 CITYT_CENTER),
794 TRUE),
795 /* TRANS: error message for ruledit */
796 N_("All action enablers for %s must require"
797 " no city at the target tile or"
798 " a non animal player actor."),
799 ACTRES_PARADROP_CONQUER,
800 ACTRES_NONE);
801 }
802 } nations_iterate_end;
803}
804
805/**********************************************************************/
808 void oblig_hard_reqs_init(void)
809{
810 int i;
811
812 /* Obligatory hard requirements sorted by action result in memory. */
813 for (i = 0; i < ACTRES_NONE; i++) {
814 /* Prepare each action result's storage area. */
815 obligatory_req_vector_init(&oblig_hard_reqs_r[i]);
816 }
817
818 /* Obligatory hard requirements sorted by action sub result in memory. */
819 for (i = 0; i < ACT_SUB_RES_COUNT; i++) {
820 /* Prepare each action sub result's storage area. */
821 obligatory_req_vector_init(&oblig_hard_reqs_sr[i]);
822 }
823}
824
825/**********************************************************************/
828 void oblig_hard_reqs_free(void)
829{
830 int i;
831
832 for (i = 0; i < ACTRES_NONE; i++) {
833 obligatory_req_vector_iterate(&oblig_hard_reqs_r[i], oreq) {
834 ae_contra_close(oreq->contras);
835 } obligatory_req_vector_iterate_end;
836 obligatory_req_vector_free(&oblig_hard_reqs_r[i]);
837 }
838
839 for (i = 0; i < ACT_SUB_RES_COUNT; i++) {
840 obligatory_req_vector_iterate(&oblig_hard_reqs_sr[i], oreq) {
841 ae_contra_close(oreq->contras);
842 } obligatory_req_vector_iterate_end;
843 obligatory_req_vector_free(&oblig_hard_reqs_sr[i]);
844 }
845}
846
847/**********************************************************************/
853 struct obligatory_req_vector *oblig_hard_reqs_get(enum action_result res)
854{
855 return &(oblig_hard_reqs_r[res]);
856}
857
858/**********************************************************************/
864 struct obligatory_req_vector *oblig_hard_reqs_get_sub(enum action_sub_result res)
865{
866 return &(oblig_hard_reqs_sr[res]);
867}
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:808
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:828
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:771
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:853
oblig_hard_reqs_get_sub
struct obligatory_req_vector * oblig_hard_reqs_get_sub(enum action_sub_result res)
Definition oblig_reqs.c:864
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:1422
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