Freeciv-3.2
Loading...
Searching...
No Matches
metaknowledge.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2013 - Freeciv Development 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/* common */
19#include "diptreaty.h"
20#include "game.h"
21#include "map.h"
22#include "metaknowledge.h"
23#include "tile.h"
24#include "traderoutes.h"
25
26/**********************************************************************/
30static bool is_tile_seen_cadj(const struct player *pow_player,
31 const struct tile *target_tile)
32{
33 /* The tile it self is unseen. */
35 return FALSE;
36 }
37
38 /* A cardinally adjacent tile is unseen. */
40 if (!tile_is_seen(ptile, pow_player)) {
41 return FALSE;
42 }
44
45 /* They are all seen. */
46 return TRUE;
47}
48
49/**********************************************************************/
53static bool is_tile_seen_adj(const struct player *pow_player,
54 const struct tile *target_tile)
55{
56 /* The tile it self is unseen. */
58 return FALSE;
59 }
60
61 /* An adjacent tile is unseen. */
62 adjc_iterate(&(wld.map), target_tile, ptile) {
63 if (!tile_is_seen(ptile, pow_player)) {
64 return FALSE;
65 }
67
68 /* They are all seen. */
69 return TRUE;
70}
71
72/**********************************************************************/
75static bool is_tile_seen_city(const struct player *pow_player,
76 const struct city *target_city)
77{
78 const struct civ_map *nmap = &(wld.map);
79
80 /* Don't know the city radius. */
82 return FALSE;
83 }
84
85 /* A tile of the city is unseen */
87 city_tile(target_city), ptile) {
88 if (!tile_is_seen(ptile, pow_player)) {
89 return FALSE;
90 }
92
93 /* They are all seen. */
94 return TRUE;
95}
96
97/**********************************************************************/
102 const struct city *target_city)
103{
104 /* Don't know who the trade routes will go to. */
106 return FALSE;
107 }
108
109 /* A tile of the city is unseen */
111 return FALSE;
112 }
113
114 /* A tile of a trade parter is unseen */
117 return FALSE;
118 }
120
121 /* They are all seen. */
122 return TRUE;
123}
124
125/**********************************************************************/
129static bool can_plr_see_all_sym_diplrels_of(const struct player *pplayer,
130 const struct player *tplayer)
131{
132 if (pplayer == tplayer) {
133 /* Can see own relationships. */
134 return TRUE;
135 }
136
137 if (team_has_embassy(pplayer->team, tplayer)) {
138 /* Gets reports from the embassy. */
139 return TRUE;
140 }
141
142 if (player_diplstate_get(pplayer, tplayer)->contact_turns_left > 0) {
143 /* Can see relationships during contact turns. */
144 return TRUE;
145 }
146
147 return FALSE;
148}
149
150/**********************************************************************/
160static bool is_req_knowable(const struct player *pov_player,
161 const struct req_context *context,
162 const struct player *other_player,
163 const struct requirement *req,
164 const enum req_problem_type prob_type)
165{
166 fc_assert_ret_val_msg(NULL != pov_player, FALSE, "No point of view");
167
168 if (context == NULL) {
170 }
171
172 if (req->source.kind == VUT_UTFLAG
173 || req->source.kind == VUT_UTYPE
174 || req->source.kind == VUT_UCLASS
175 || req->source.kind == VUT_UCFLAG
176 || req->source.kind == VUT_MINVETERAN
177 || req->source.kind == VUT_MINHP) {
178 switch (req->range) {
179 case REQ_RANGE_LOCAL:
180 if (context->unit == NULL) {
181 /* The unit may exist but not be passed when the problem type is
182 * RPT_POSSIBLE. */
183 return prob_type == RPT_CERTAIN;
184 }
185
187 case REQ_RANGE_TILE:
191 case REQ_RANGE_CITY:
193 case REQ_RANGE_PLAYER:
194 case REQ_RANGE_TEAM:
196 case REQ_RANGE_WORLD:
197 case REQ_RANGE_COUNT:
198 return FALSE;
199 }
200 }
201
202 if (req->source.kind == VUT_UNITSTATE) {
203 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, FALSE, "Wrong range");
204
205 if (context->unit == NULL) {
206 /* The unit may exist but not be passed when the problem type is
207 * RPT_POSSIBLE. */
208 return prob_type == RPT_CERTAIN;
209 }
210
211 switch (req->source.value.unit_state) {
212 case USP_TRANSPORTED:
213 case USP_LIVABLE_TILE:
214 case USP_TRANSPORTING:
215 case USP_NATIVE_TILE:
216 case USP_NATIVE_EXTRA:
217 /* Known if the unit is seen by the player. */
221 /* Known to the unit's owner. */
222 return unit_owner(context->unit) == pov_player;
223 case USP_COUNT:
225 "Invalid unit state property.");
226 /* Invalid property is unknowable. */
227 return FALSE;
228 }
229 }
230
231 if (req->source.kind == VUT_MINMOVES) {
232 fc_assert_ret_val_msg(req->range == REQ_RANGE_LOCAL, FALSE, "Wrong range");
233
234 if (context->unit == NULL) {
235 /* The unit may exist but not be passed when the problem type is
236 * RPT_POSSIBLE. */
237 return prob_type == RPT_CERTAIN;
238 }
239
240 switch (req->range) {
241 case REQ_RANGE_LOCAL:
242 /* The owner can see if their unit has move fragments left. */
243 return unit_owner(context->unit) == pov_player;
244 case REQ_RANGE_TILE:
247 case REQ_RANGE_CITY:
250 case REQ_RANGE_PLAYER:
251 case REQ_RANGE_TEAM:
253 case REQ_RANGE_WORLD:
254 case REQ_RANGE_COUNT:
255 /* Invalid range */
256 return FALSE;
257 }
258 }
259
260 if (req->source.kind == VUT_ACTIVITY) {
262 FALSE, "Wrong range");
263
264 if (context->unit == NULL) {
265 /* The unit may exist but not be passed when the problem type is
266 * RPT_POSSIBLE. */
267 return prob_type == RPT_CERTAIN;
268 }
269
270 if (unit_owner(context->unit) == pov_player) {
271 return TRUE;
272 }
273
274 /* Sent in package_short_unit() */
276 }
277
278 if (req->source.kind == VUT_DIPLREL
279 || req->source.kind == VUT_DIPLREL_TILE
282 || req->source.kind == VUT_DIPLREL_UNITANY_O) {
283 switch (req->range) {
284 case REQ_RANGE_LOCAL:
285 if (other_player == NULL
286 || context->player == NULL) {
287 /* The two players may exist but not be passed when the problem
288 * type is RPT_POSSIBLE. */
289 return prob_type == RPT_CERTAIN;
290 }
291
292 if (pov_player == context->player
293 || pov_player == other_player) {
294 return TRUE;
295 }
296
299 return TRUE;
300 }
301
302 /* TODO: Non symmetric diplomatic relationships. */
303 break;
304 case REQ_RANGE_PLAYER:
305 if (context->player == NULL) {
306 /* The target player may exist but not be passed when the problem
307 * type is RPT_POSSIBLE. */
308 return prob_type == RPT_CERTAIN;
309 }
310
311 if (pov_player == context->player) {
312 return TRUE;
313 }
314
316 return TRUE;
317 }
318
319 /* TODO: Non symmetric diplomatic relationships. */
320 break;
321 case REQ_RANGE_TEAM:
322 /* TODO */
323 break;
325 /* TODO */
326 break;
327 case REQ_RANGE_WORLD:
328 /* TODO */
329 break;
330 case REQ_RANGE_TILE:
333 case REQ_RANGE_CITY:
336 case REQ_RANGE_COUNT:
337 /* Invalid range */
338 return FALSE;
339 break;
340 }
341 }
342
343 if (req->source.kind == VUT_MINSIZE) {
344 if (context->city == NULL) {
345 /* The city may exist but not be passed when the problem type is
346 * RPT_POSSIBLE. */
347 return prob_type == RPT_CERTAIN;
348 }
349
351 return TRUE;
352 }
353 }
354
355 if (req->source.kind == VUT_CITYTILE) {
356 struct city *pcity;
357
358 if (context->city == NULL) {
359 switch (req->source.value.citytile) {
360 case CITYT_CENTER:
363 /* Require the city, not passed */
364 return prob_type == RPT_CERTAIN;
365 case CITYT_CLAIMED:
366 case CITYT_WORKED:
368 /* Do not require a city passed */
369 break;
370 case CITYT_LAST:
371 /* Invalid */
373 "Invalid city tile property.");
374 return FALSE;
375 }
376 }
377
378 if (context->tile == NULL) {
379 /* The tile may exist but not be passed when the problem type is
380 * RPT_POSSIBLE. */
381 return prob_type == RPT_CERTAIN;
382 }
383
384 switch (req->range) {
385 case REQ_RANGE_TILE:
386 /* Known because the tile is seen */
387 if (tile_is_seen(context->tile, pov_player)) {
388 return TRUE;
389 }
390
391 /* The player knows their city even if they can't see it */
392 pcity = tile_city(context->tile);
393 return pcity && city_owner(pcity) == pov_player;
395 /* Known because the tile is seen */
397 return TRUE;
398 }
399
400 /* The player knows their city even if they can't see it */
401 cardinal_adjc_iterate(&(wld.map), context->tile, ptile) {
402 pcity = tile_city(ptile);
403 if (pcity && city_owner(pcity) == pov_player) {
404 return TRUE;
405 }
407
408 /* Unknown */
409 return FALSE;
411 /* Known because the tile is seen */
412 if (is_tile_seen_adj(pov_player, context->tile)) {
413 return TRUE;
414 }
415
416 /* The player knows their city even if they can't see it */
417 adjc_iterate(&(wld.map), context->tile, ptile) {
418 pcity = tile_city(ptile);
419 if (pcity && city_owner(pcity) == pov_player) {
420 return TRUE;
421 }
423
424 /* Unknown */
425 return FALSE;
426 case REQ_RANGE_CITY:
429 case REQ_RANGE_PLAYER:
430 case REQ_RANGE_TEAM:
432 case REQ_RANGE_WORLD:
433 case REQ_RANGE_LOCAL:
434 case REQ_RANGE_COUNT:
435 /* Invalid range */
436 return FALSE;
437 }
438 }
439
440 if (req->source.kind == VUT_IMPR_GENUS) {
441 /* The only legal range when this was written was local. */
443
444 if (context->city == NULL) {
445 /* RPT_CERTAIN: Can't be. No city to contain it.
446 * RPT_POSSIBLE: A city like that may exist but not be passed. */
447 return prob_type == RPT_CERTAIN;
448 }
449
450 /* Local BuildingGenus could be about city production. */
452 }
453
454 if (req->source.kind == VUT_IMPROVEMENT) {
455 switch (req->range) {
456 case REQ_RANGE_WORLD:
458 case REQ_RANGE_TEAM:
459 case REQ_RANGE_PLAYER:
461 /* Only wonders (great or small) can be required in those ranges.
462 * Wonders are always visible. */
463 return TRUE;
465 /* Could be known for trade routes to cities owned by pov_player as
466 * long as the requirement is present. Not present requirements would
467 * require knowledge that no trade routes to another foreign city
468 * exists (since all possible trade routes are to a city owned by
469 * pov_player). Not worth the complexity, IMHO. */
470 return FALSE;
471 case REQ_RANGE_CITY:
472 case REQ_RANGE_LOCAL:
473 if (context->city == NULL) {
474 /* RPT_CERTAIN: Can't be. No city to contain it.
475 * RPT_POSSIBLE: A city like that may exist but not be passed. */
476 return prob_type == RPT_CERTAIN;
477 }
478
480 /* Anyone that can see city internals (like the owner) known all
481 * its improvements. */
482 return TRUE;
483 }
484
487 /* Can see visible improvements when the outside of the city is
488 * seen. */
489 return TRUE;
490 }
491
492 /* No way to know if a city has an improvement */
493 return FALSE;
494 case REQ_RANGE_TILE:
495 if (context->tile == NULL) {
496 /* RPT_CERTAIN: Can't be. No tile to contain it.
497 * RPT_POSSIBLE: A tile city like that may exist but not be passed. */
498 return prob_type == RPT_CERTAIN;
499 }
500
501 {
502 const struct city *tcity = tile_city(context->tile);
503
504 if (!tcity) {
505 /* No building can be in no city if it's known
506 * there is no city */
508 const struct city *wcity
510
511 if (!wcity
513 /* Player can be sure the wonder is not here */
514 return TRUE;
515 /* FIXME: deducing from known borders aside, the player
516 * may have seen wcity before and cities don't move */
517 }
518 }
519
520 return tile_is_seen(context->tile, pov_player);
521 }
522
524 /* Anyone that can see city internals (like the owner) known all
525 * its improvements. */
526 return TRUE;
527 }
528
531 /* Can see visible improvements when the outside of the city is
532 * seen. */
533 return TRUE;
534 }
535 }
536
537 /* No way to know if a city has an improvement */
538 return FALSE;
541 case REQ_RANGE_COUNT:
542 /* Not supported by the requirement type. */
543 return FALSE;
544 }
545 }
546
547 if (req->source.kind == VUT_NATION
548 || req->source.kind == VUT_NATIONGROUP) {
549 if (context->player == NULL
550 && (req->range == REQ_RANGE_PLAYER
551 || req->range == REQ_RANGE_TEAM
552 || req->range == REQ_RANGE_ALLIANCE)) {
553 /* The player (that can have a nationality or be allied to someone
554 * with the nationality) may exist but not be passed when the problem
555 * type is RPT_POSSIBLE. */
556 return prob_type == RPT_CERTAIN;
557 }
558
559 return TRUE;
560 }
561
562 if (req->source.kind == VUT_ADVANCE || req->source.kind == VUT_TECHFLAG) {
563 if (req->range == REQ_RANGE_PLAYER) {
564 if (context->player == NULL) {
565 /* The player (that may or may not possess the tech) may exist but
566 * not be passed when the problem type is RPT_POSSIBLE. */
567 return prob_type == RPT_CERTAIN;
568 }
569
571 } else if (req->range == REQ_RANGE_WORLD && req->survives) {
572 /* game.info.global_advances is sent to each player */
573 return TRUE;
574 }
575 }
576
577 if (req->source.kind == VUT_GOVERNMENT) {
578 if (req->range == REQ_RANGE_PLAYER) {
579 if (context->player == NULL) {
580 /* The player (that may or may not possess the tech) may exist but
581 * not be passed when the problem type is RPT_POSSIBLE. */
582 return prob_type == RPT_CERTAIN;
583 }
584
585 return (pov_player == context->player
587 }
588 }
589
590 if (req->source.kind == VUT_MAXTILEUNITS) {
591 if (context->tile == NULL) {
592 /* The tile may exist but not be passed when the problem type is
593 * RPT_POSSIBLE. */
594 return prob_type == RPT_CERTAIN;
595 }
596
597 switch (req->range) {
598 case REQ_RANGE_TILE:
602 return FALSE;
603 }
606 return FALSE;
607 }
609
610 return TRUE;
613 return FALSE;
614 }
615 adjc_iterate(&(wld.map), context->tile, adjc_tile) {
617 return FALSE;
618 }
620
621 return TRUE;
623 case REQ_RANGE_CITY:
625 case REQ_RANGE_PLAYER:
626 case REQ_RANGE_TEAM:
628 case REQ_RANGE_WORLD:
629 case REQ_RANGE_LOCAL:
630 case REQ_RANGE_COUNT:
631 /* Non existing. */
632 return FALSE;
633 }
634 }
635
636 if (req->source.kind == VUT_EXTRA
637 || req->source.kind == VUT_EXTRAFLAG
638 || req->source.kind == VUT_ROADFLAG) {
639 if (req->range == REQ_RANGE_LOCAL) {
640 if (context->extra == NULL) {
641 /* The extra may exist but not be passed when the problem type is
642 * RPT_POSSIBLE. */
643 return prob_type == RPT_CERTAIN;
644 }
645 /* The extra is given; we can figure out whether it matches. */
646 return TRUE;
647 }
648 /* Other ranges handled below */
649 }
650
651 if (req->source.kind == VUT_TERRAIN
652 || req->source.kind == VUT_TERRFLAG
653 || req->source.kind == VUT_TERRAINCLASS
654 || req->source.kind == VUT_TERRAINALTER
655 || req->source.kind == VUT_EXTRA
656 || req->source.kind == VUT_EXTRAFLAG
657 || req->source.kind == VUT_ROADFLAG) {
658 if (context->tile == NULL) {
659 /* The tile may exist but not be passed when the problem type is
660 * RPT_POSSIBLE. */
661 return prob_type == RPT_CERTAIN;
662 }
663
664 switch (req->range) {
665 case REQ_RANGE_TILE:
666 return tile_is_seen(context->tile, pov_player);
668 /* TODO: The answer is known when the universal is located on a seen
669 * tile. Is returning TRUE in those cases worth the added complexity
670 * and the extra work for the computer? */
671 return is_tile_seen_cadj(pov_player, context->tile);
673 /* TODO: The answer is known when the universal is located on a seen
674 * tile. Is returning TRUE in those cases worth the added complexity
675 * and the extra work for the computer? */
676 return is_tile_seen_adj(pov_player, context->tile);
677 case REQ_RANGE_CITY:
678 /* TODO: The answer is known when the universal is located on a seen
679 * tile. Is returning TRUE in those cases worth the added complexity
680 * and the extra work for the computer? */
681 return is_tile_seen_city(pov_player, context->city);
683 /* TODO: The answer is known when the universal is located on a seen
684 * tile. Is returning TRUE in those cases worth the added complexity
685 * and the extra work for the computer? */
688 case REQ_RANGE_PLAYER:
690 case REQ_RANGE_TEAM:
691 case REQ_RANGE_WORLD:
692 case REQ_RANGE_LOCAL:
693 case REQ_RANGE_COUNT:
694 /* Non existing range for requirement types. */
695 return FALSE;
696 }
697 }
698
699 if (req->source.kind == VUT_ACTION
700 || req->source.kind == VUT_OTYPE) {
701 /* This requirement type is intended to specify the situation. */
702 return TRUE;
703 }
704
705 if (req->source.kind == VUT_SERVERSETTING) {
706 /* Only visible server settings can be requirements. */
707 return TRUE;
708 }
709
710 /* Uncertain or no support added yet. */
711 return FALSE;
712}
713
714/**********************************************************************/
721enum fc_tristate
723 const struct req_context *context,
724 const struct player *other_player,
725 const struct requirement *req,
726 const enum req_problem_type prob_type)
727{
728 if (!is_req_knowable(pov_player, context, other_player,
729 req, prob_type)) {
730 return TRI_MAYBE;
731 }
732
733 if (is_req_active(context, other_player, req, prob_type)) {
734 return TRI_YES;
735 } else {
736 return TRI_NO;
737 }
738}
739
740/**********************************************************************/
747enum fc_tristate
749 const struct req_context *context,
750 const struct player *other_player,
751 const struct requirement_vector *reqs,
752 const enum req_problem_type prob_type)
753{
754 enum fc_tristate current;
755 enum fc_tristate result;
756
757 result = TRI_YES;
759 current = mke_eval_req(pov_player, context, other_player,
760 preq, prob_type);
761 if (current == TRI_NO) {
762 return TRI_NO;
763 } else if (current == TRI_MAYBE) {
764 result = TRI_MAYBE;
765 }
767
768 return result;
769}
770
771/**********************************************************************/
775 const struct player *target_player)
776{
777 return pow_player == target_player
779}
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
#define city_tile(_pcity_)
Definition city.h:564
#define city_owner(_pcity_)
Definition city.h:563
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:230
#define city_tile_iterate_end
Definition city.h:238
char * incite_cost
Definition comments.c:75
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
struct unit struct city * target_city
Definition dialogs_g.h:56
bool could_intel_with_player(const struct player *pplayer, const struct player *aplayer)
Definition diptreaty.c:84
struct @21::@22 reqs
req_problem_type
Definition fc_types.h:699
@ RPT_CERTAIN
Definition fc_types.h:701
struct world wld
Definition game.c:63
bool is_improvement_visible(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
struct city * city_from_great_wonder(const struct impr_type *pimprove)
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:208
#define adjc_iterate_end
Definition map.h:433
#define cardinal_adjc_iterate_end
Definition map.h:459
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:428
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:455
static bool is_tile_seen_cadj(const struct player *pow_player, const struct tile *target_tile)
bool can_see_techs_of_target(const struct player *pow_player, const struct player *target_player)
static bool is_tile_seen_city(const struct player *pow_player, const struct city *target_city)
static bool can_plr_see_all_sym_diplrels_of(const struct player *pplayer, const struct player *tplayer)
enum fc_tristate mke_eval_reqs(const struct player *pov_player, const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static bool is_tile_seen_trade_route(const struct player *pow_player, const struct city *target_city)
static bool is_req_knowable(const struct player *pov_player, const struct req_context *context, const struct player *other_player, const struct requirement *req, const enum req_problem_type prob_type)
enum fc_tristate mke_eval_req(const struct player *pov_player, const struct req_context *context, const struct player *other_player, const struct requirement *req, const enum req_problem_type prob_type)
static bool is_tile_seen_adj(const struct player *pow_player, const struct tile *target_tile)
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Definition player.c:1104
bool team_has_embassy(const struct team *pteam, const struct player *tgt_player)
Definition player.c:220
bool player_can_see_city_externals(const struct player *pow_player, const struct city *target_city)
Definition player.c:1164
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
bool can_player_see_hypotetic_units_at(const struct player *pplayer, const struct tile *ptile)
Definition player.c:993
bool can_player_see_city_internals(const struct player *pplayer, const struct city *pcity)
Definition player.c:1149
const struct req_context * req_context_empty(void)
bool is_req_active(const struct req_context *context, const struct player *other_player, const struct requirement *req, const enum req_problem_type prob_type)
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
Definition city.h:320
struct team * team
Definition player.h:259
enum req_range range
struct universal source
Definition tile.h:50
enum universals_n kind
Definition fc_types.h:902
universals_u value
Definition fc_types.h:901
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
bool tile_is_seen(const struct tile *target_tile, const struct player *pow_player)
Definition tile.c:407
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define trade_partners_iterate_end
#define trade_partners_iterate(c, p)
enum citytile_type citytile
Definition fc_types.h:730
const struct impr_type * building
Definition fc_types.h:714
enum ustate_prop unit_state
Definition fc_types.h:749
#define unit_owner(_pu)
Definition unit.h:396