I6 Template Layer

Inform 7 6M62ContentsIntroductionFunction IndexRules Index

Activities.i6t

Activities contents

The Activities Stack.

Activities are more like nested function calls than independent processes; they finish in reverse order of starting, and are placed on a stack. This needs only very limited size in practice: 20 might seem a bit low, but making it much higher simply means that oddball bugs in the user's code – where activities recursively cause themselves ad infinitum – will be caught less efficiently.

16Constant MAX_NESTED_ACTIVITIES = 20; 17Global activities_sp = 0; 18Array activities_stack --> MAX_NESTED_ACTIVITIES; 19Array activity_parameters_stack --> MAX_NESTED_ACTIVITIES;

Rule Debugging Inhibition.

The output from RULES or RULES ALL becomes totally illegible if it is applied even to the activities printing names of objects, so this is inhibited when any such activity is running. FixInhibitFlag is called each time the stack changes and ensures that inhibit_flag has exactly this meaning.

28Global inhibit_flag = 0; 29Global saved_debug_rules = 0; 30[ FixInhibitFlag n act inhibit_rule_debugging; 31    for (n=0:n<activities_sp:n++) { 32        act = activities_stack-->n; 33        if (act == PRINTING_THE_NAME_ACT or PRINTING_THE_PLURAL_NAME_ACT or 34            PRINTING_ROOM_DESC_DETAILS_ACT or PRINTING_INVENTORY_DETAILS_ACT or 35            LISTING_CONTENTS_ACT or GROUPING_TOGETHER_ACT or PRINTING_RESPONSE_ACT) 36                inhibit_rule_debugging = true; 37    } 38    if ((inhibit_flag == false) && (inhibit_rule_debugging)) { 39        saved_debug_rules = debug_rules; 40        debug_rules = 0; 41    } 42    if ((inhibit_flag) && (inhibit_rule_debugging == false)) { 43        debug_rules = saved_debug_rules; 44    } 45    inhibit_flag = inhibit_rule_debugging; 46];

Testing Activities.

The following tests whether a given activity A is currently running whose parameter-object matches description desc, where as usual the description is represented by a routine testing membership, and where zero desc means that any parameter is valid. Alternatively, we can require a specific parameter value of val.

56[ TestActivity A desc val i; 57    for (i=0:i<activities_sp:i++) 58        if (activities_stack-->i == A) { 59            if (desc) { 60                if ((desc)(activity_parameters_stack-->i)) rtrue; 61            } else if (val) { 62                if (val == activity_parameters_stack-->i) rtrue; 63            } else rtrue; 64        } 65    rfalse; 66];

Emptiness.

An activity is defined by its three rulebooks: it is empty if they are all empty.

73[ ActivityEmpty A x; 74    x = Activity_before_rulebooks-->A; 75    if (rulebooks_array-->x ~= EMPTY_RULEBOOK) rfalse; 76    x = Activity_for_rulebooks-->A; 77    if (rulebooks_array-->x ~= EMPTY_RULEBOOK) rfalse; 78    x = Activity_after_rulebooks-->A; 79    if (rulebooks_array-->x ~= EMPTY_RULEBOOK) rfalse; 80    rtrue; 81]; 82 83[ RulebookEmpty rb; 84    if (rulebooks_array-->rb ~= EMPTY_RULEBOOK) rfalse; 85    rtrue; 86];

Process Activity Rulebook.

This is really much like processing any rulebook, except that self is temporarily set to the parameter, and is preserved by the process.

93[ ProcessActivityRulebook rulebook parameter rv; 94    @push self; 95    if (parameter) self = parameter; 96    rv = FollowRulebook(rulebook, parameter, true); 97    @pull self; 98    if (rv) rtrue; 99    rfalse; 100];

Carrying Out Activities.

This is a three-stage process; most activities are run by calling the following simple routine, but some are run by calling the three subroutines independently.

107[ CarryOutActivity A o rv; 108    BeginActivity(A, o); 109    rv = ForActivity(A, o); 110    EndActivity(A, o); 111    return rv; 112];

Begin.

Note that when an activity based on the conjectural "future action" is being run – in a few parser-related cases, that is – the identity of this action is put temporarily into action, and the current value saved while this takes place. That allows rules in the activity rulebooks to have preambles based on the current action, and yet be tested against what is not yet the current action.

123[ BeginActivity A o x; 124    if (activities_sp == MAX_NESTED_ACTIVITIES) return RunTimeProblem(RTP_TOOMANYACTS); 125    activity_parameters_stack-->activities_sp = o; 126    activities_stack-->(activities_sp++) = A; 127    FixInhibitFlag(); 128    MStack_CreateAVVars(A); 129    if (Activity_atb_rulebooks->A) { x = action; action = action_to_be; } 130    o = ProcessActivityRulebook(Activity_before_rulebooks-->A, o); 131    if (Activity_atb_rulebooks->A) action = x; 132    return o; 133];

For.

138[ ForActivity A o x; 139    if (Activity_atb_rulebooks->A) { x = action; action = action_to_be; } 140    o = ProcessActivityRulebook(Activity_for_rulebooks-->A, o); 141    if (Activity_atb_rulebooks->A) action = x; 142    return o; 143];

End.

148[ EndActivity A o rv x; 149    if ((activities_sp > 0) && (activities_stack-->(activities_sp-1) == A)) { 150        if (Activity_atb_rulebooks->A) { x = action; action = action_to_be; } 151        rv = ProcessActivityRulebook(Activity_after_rulebooks-->A, o); 152        if (Activity_atb_rulebooks->A) action = x; 153        activities_sp--; FixInhibitFlag(); 154        MStack_DestroyAVVars(A); 155        return rv; 156    } 157    return RunTimeProblem(RTP_CANTABANDON); 158];

Abandon.

For (very) rare cases where an activity must be abandoned midway; such an activity must be being run by calling the three stages individually, and EndActivity must not have been called yet.

166[ AbandonActivity A o; 167    if ((activities_sp > 0) && (activities_stack-->(activities_sp-1) == A)) { 168        activities_sp--; FixInhibitFlag(); 169        MStack_DestroyAVVars(A); 170        return; 171    } 172    return RunTimeProblem(RTP_CANTEND); 173];