A special condition for testing against action patterns.

§1. The actions feature introduces a special form of condition: authors can write "if taking or dropping something", for example, and this is implicitly a test of what the current action is.

This is represented in the parse tree as the twig:

    TEST_VALUE_NT
        CONSTANT_NT

where the constant below is the action seen as a noun — linguistically, a "gerund". It will always have the kind K_stored_action or K_description_of_action, depending on whether the test is against an explicit action or something vaguer.

Here we create and test for such twigs:

parse_node *AConditions::new_action_TEST_VALUE(action_pattern *ap, wording W) {
    if (ap == NULL) internal_error("null action pattern");
    parse_node *spec = Node::new_with_words(TEST_VALUE_NT, W);
    spec->down = ARvalues::from_action_pattern(ap);
    Node::set_text(spec->down, W);
    return spec;
}

parse_node *AConditions::new_past_action_TEST_VALUE(action_pattern *ap, wording W) {
    parse_node *spec = AConditions::new_action_TEST_VALUE(ap, W);
    if (ActionPatterns::makes_callings(ap)) {
        StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_PastActionCalled),
            "a description of an action cannot both refer to past history and also "
            "use '(called ...)'",
            "because that would require Inform in general to remember too much "
            "information about past events.");
    } else {
        spec = Conditions::attach_tense(spec, HASBEEN_TENSE);
    }
    return spec;
}

int AConditions::is_action_TEST_VALUE(parse_node *spec) {
    if ((Node::is(spec, TEST_VALUE_NT)) &&
        ((ARvalues::to_action_pattern(spec->down)) ||
        (ARvalues::to_explicit_action(spec->down)))) return TRUE;
    return FALSE;
}

§2. As noted above, the gerund is just the child node, and from that we can reconstruct the original action pattern which led to this condition:

parse_node *AConditions::gerund_from_TEST_VALUE(parse_node *spec) {
    if (AConditions::is_action_TEST_VALUE(spec) == FALSE)
        internal_error("gerund improperly extracted");
    return spec->down;
}

action_pattern *AConditions::pattern_from_action_TEST_VALUE(parse_node *spec) {
    if (AConditions::is_action_TEST_VALUE(spec)) {
        parse_node *gerund = AConditions::gerund_from_TEST_VALUE(spec);
        action_pattern *ap = ARvalues::to_action_pattern(gerund);
        if (ap == NULL) {
            explicit_action *ea = Node::get_constant_explicit_action(gerund);
            if (ea) ap = ea->as_described;
        }
        return ap;
    }
    return NULL;
}

§3. Which we can then compile a test against:

int AConditions::compile_condition(value_holster *VH, parse_node *spec) {
    if (AConditions::is_action_TEST_VALUE(spec)) {
        action_pattern *ap = AConditions::pattern_from_action_TEST_VALUE(spec);
        RTActionPatterns::compile_pattern_match(ap);
        return TRUE;
    }
    return FALSE;
}