Rules can be set to run only if the action matches a given pattern.

§1. Many rules are predicated on action patterns: "Instead of opening a closed door", say, is a rule in the "instead of opening" rulebook which is predicated on the action applying to "a closed door". This is stored in the following actions-feature corner of the Runtime Context Data (in assertions) for the rule.

typedef struct actions_rcd_data {
    int always_test_actor;  ...even if no AP was given, test that actor is player?
    int never_test_actor;  ...for instance, for a parametrised rather than action rulebook
    int marked_for_anyone;  any actor is allowed to perform this action
    CLASS_DEFINITION
} actions_rcd_data;

actions_rcd_data *ActionRules::new_rcd_data(id_runtime_context_data *idrcd) {
    actions_rcd_data *ard = CREATE(actions_rcd_data);
    ard->always_test_actor = FALSE;
    ard->never_test_actor = FALSE;
    ard->marked_for_anyone = FALSE;
    return ard;
}

§2. Note that if the actions feature is inactive, then this never runs...

int ActionRules::new_rcd(id_runtime_context_data *idrcd) {
    CREATE_RCD_FEATURE_DATA(actions, idrcd, ActionRules::new_rcd_data)
    return FALSE;
}

§3. ...with the result that arcd is always null in the function below.

void ActionRules::set_always_test_actor(id_runtime_context_data *idrcd) {
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if (arcd) arcd->always_test_actor = TRUE;
}

int ActionRules::get_always_test_actor(id_runtime_context_data *idrcd) {
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if (arcd) return arcd->always_test_actor;
    return FALSE;
}

void ActionRules::clear_always_test_actor(id_runtime_context_data *idrcd) {
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if (arcd) arcd->always_test_actor = FALSE;
}

void ActionRules::set_never_test_actor(id_runtime_context_data *idrcd) {
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if (arcd) arcd->never_test_actor = TRUE;
}

int ActionRules::get_never_test_actor(id_runtime_context_data *idrcd) {
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if (arcd) return arcd->never_test_actor;
    return TRUE;
}

void ActionRules::set_marked_for_anyone(id_runtime_context_data *idrcd, int to) {
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if (arcd) arcd->marked_for_anyone = to;
}

int ActionRules::get_marked_for_anyone(id_runtime_context_data *idrcd) {
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if (arcd) return arcd->marked_for_anyone;
    return FALSE;
}

§4. The following all make use the action pattern idrcd->ap in the RCD. This seems a little odd: why isn't it in the actions_rcd_data? The answer is that it needs to exist even when the actions feature is inactive, because it's still used for parsing predicates for non-action-based rulebooks.

void ActionRules::set_ap(id_runtime_context_data *idrcd, action_pattern *ap) {
    if (idrcd) idrcd->ap = ap;
}

action_pattern *ActionRules::get_ap(id_runtime_context_data *idrcd) {
    if (idrcd) return idrcd->ap;
    return NULL;
}

int ActionRules::within_action_context(id_runtime_context_data *idrcd, action_name *an) {
    if (idrcd == NULL) return FALSE;
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if (arcd) return ActionPatterns::covers_action(idrcd->ap, an);
    return FALSE;
}

action_name *ActionRules::required_action(id_runtime_context_data *idrcd) {
    if (idrcd == NULL) return FALSE;
    actions_rcd_data *arcd = RCD_FEATURE_DATA(actions, idrcd);
    if ((arcd) && (idrcd->ap)) return ActionPatterns::single_positive_action(idrcd->ap);
    return NULL;
}

action_name *ActionRules::required_action_for_booking(booking *br) {
    imperative_defn *id = Rules::get_imperative_definition(br->rule_being_booked);
    if (id) return ActionRules::required_action(&(id->body_of_defn->runtime_context_data));
    return NULL;
}

void ActionRules::suppress_action_testing(id_runtime_context_data *idrcd) {
    if (idrcd->ap) ActionPatterns::suppress_action_testing(idrcd->ap);
}