From 159ce9b08e32e250e00003775d9f837fdfd7371f Mon Sep 17 00:00:00 2001 From: Sveinung Kvilhaugsvik Date: Wed, 28 Apr 2021 18:21:40 +0200 Subject: [PATCH] Use universal fulfills in contradiction detection. The functions in universal_found_function have knowledge about if a universal fulfills a requirement. This knowledge can be used to detect the contradiction where the presence of something is required but the absence of something implied by what was required to be present also is required. Use this in are_requirements_contradictions(). See osdn #42100 --- common/requirements.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/common/requirements.c b/common/requirements.c index 82ae09abc9..b812fd1886 100644 --- a/common/requirements.c +++ b/common/requirements.c @@ -1119,6 +1119,49 @@ static bool nation_contra_group(const struct requirement *nation_req, return FALSE; } +/**********************************************************************//** + Returns TRUE if req1 and req2 contradicts each other because a present + requirement implies the presence of a !present requirement according to + the knowledge about implications in universal_found_function. +**************************************************************************/ +static bool present_implies_not_present(const struct requirement *req1, + const struct requirement *req2) +{ + const struct requirement *absent, *present; + + if (req1->present == req2->present) { + /* Can't use the knowledge in universal_found_function when both are + * required to be absent or when both are required to be present. + * It is no contradiction to require !Spy unit and !Missile unit class. + * It is no contradiction to require River and Irrigation at the same + * tile. */ + return FALSE; + } + + if (req1->present) { + absent = req2; + present = req1; + } else { + absent = req1; + present = req2; + } + + if (!universal_found_function[present->source.kind]) { + /* No knowledge to exploit. */ + return FALSE; + } + + if (present->range != absent->range) { + /* Larger ranges are not always strict supersets of smaller ranges. + * Example: Traderoute > CAdjacent but something may be in CAdjacent + * but not in Traderoute. */ + return FALSE; + } + + return ITF_YES == universal_fulfills_requirement(absent, + &present->source); +} + /**********************************************************************//** Returns TRUE if req1 and req2 contradicts each other. @@ -1134,6 +1177,10 @@ bool are_requirements_contradictions(const struct requirement *req1, return TRUE; } + if (present_implies_not_present(req1, req2)) { + return TRUE; + } + switch (req1->source.kind) { case VUT_IMPROVEMENT: if (req2->source.kind == VUT_IMPR_GENUS) { -- 2.30.2