Runtime support for dialogue choices.


§1. Runtime representation. Values representing choices are enumerated from 1 to NO_DIALOGUE_CHOICES. Choices have certain properties stored by Inform just as it would for any other enumerated kind, and which this kit deals with by calls to GProperty and WriteGProperty: in particular, performed and recurring.

In addition, though, the compiler (or more accurately the linker) generates a table called TableOfDialogueChoices. If dc is an enumerated value then TableOfDialogueChoices-->dc is the address of the metadata table for dc. (And TableOfDialogueChoices-->0 is set to NO_DIALOGUE_CHOICES.)

These choice data arrays occupy 3 words each, with fields as follows:

All of this must of course match what is compiled in Dialogue Choice Instances (in runtime).

Constant TYPE_DCMETADATA = 0;
Constant AVAILABILITY_DCMETADATA = 1;
Constant CONTENT_DCMETADATA = 2;
Constant STATE_DCMETADATA = 3;

                                         Flow markers:
Constant AGAIN_DSEL = 1;                 <-
Constant ANOTHER_CHOICE_DSEL = 2;        -> another choice
Constant PERFORM_DSEL = 3;               -> perform the falling beat
Constant STOP_DSEL = 4;                  -> stop
Constant ENDING_DSEL = 5;                -> end the story
Constant ENDING_SAYING_DSEL = 6;         -> end the story saying "You have succeeded"
Constant ENDING_FINALLY_DSEL = 7;        -> end the story finally
Constant ENDING_FINALLY_SAYING_DSEL = 8; -> end the story finally saying "You have failed"

                                         Offered choices:
Constant TEXTUAL_DSEL = 9;               — "Run out of the room screaming"
Constant BEFORE_DSEL = 10;               — before taking the pocket watch
Constant INSTEAD_OF_DSEL = 11;           — instead of taking something
Constant AFTER_DSEL = 12;                — after examining the rabbit hole
Constant OTHERWISE_DSEL = 13;            — otherwise
Constant CHOOSE_RANDOMLY_DSEL = 14;      — choose randomly
Constant SHUFFLE_THROUGH_DSEL = 15;      — shuffle through
Constant CYCLE_THROUGH_DSEL = 16;        — cycle through
Constant STEP_THROUGH_DSEL = 17;         — step through
Constant STEP_THROUGH_AND_STOP_DSEL = 18; — step through and stop
Constant OR_DSEL = 19;                   — or

§2. Extracting choice data.

[ DirectorChoiceStoryEnding dc chdata;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) rfalse;
    chdata = TableOfDialogueChoices-->dc;
    if (chdata-->TYPE_DCMETADATA == ENDING_DSEL or ENDING_SAYING_DSEL or
        ENDING_FINALLY_DSEL or ENDING_FINALLY_SAYING_DSEL)
        rtrue;
    rfalse;
];

[ DirectorChoiceTextContent dc text chdata;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) return text;
    chdata = TableOfDialogueChoices-->dc;
    CopyPV(text, chdata-->CONTENT_DCMETADATA);
    return text;
];

[ DirectorChoiceType dc chdata;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) return 0;
    chdata = TableOfDialogueChoices-->dc;
    return chdata-->TYPE_DCMETADATA;
];

[ DirectorReadChoiceState dc chdata;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) return 0;
    chdata = TableOfDialogueChoices-->dc;
    return chdata-->STATE_DCMETADATA;
];

[ DirectorWriteChoiceState dc val chdata;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) return;
    chdata = TableOfDialogueChoices-->dc;
    chdata-->STATE_DCMETADATA = val;
];

[ DirectorChoiceRawContent dc chdata;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) return 0;
    chdata = TableOfDialogueChoices-->dc;
    return chdata-->CONTENT_DCMETADATA;
];

[ DirectorChoiceFlowing dc chdata type;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) rfalse;
    chdata = TableOfDialogueChoices-->dc;
    type = chdata-->TYPE_DCMETADATA;
    if (type == ANOTHER_CHOICE_DSEL or AGAIN_DSEL or STOP_DSEL or PERFORM_DSEL
         or ENDING_DSEL or ENDING_SAYING_DSEL or ENDING_FINALLY_DSEL
         or ENDING_FINALLY_SAYING_DSEL)
        rtrue;
    rfalse;
];

[ DirectorChoiceAvailable dc chdata fn;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) rfalse;
    chdata = TableOfDialogueChoices-->dc;
    fn = chdata-->AVAILABILITY_DCMETADATA;
    if (fn) return fn();
    rtrue;
];

[ DirectorFollowFlowMarker dc chdata b;
    if ((dc <= 0) || (dc > NO_DIALOGUE_CHOICES)) rfalse;
    WriteGProperty(DIALOGUE_CHOICE_TY, dc, performed, true);
    chdata = TableOfDialogueChoices-->dc;
    switch (chdata-->TYPE_DCMETADATA) {
        AGAIN_DSEL:
            if (debug_dialogue >= 2) { print "-- again^"; }
            DirectorAgain();
            rtrue;
        STOP_DSEL:
            if (debug_dialogue >= 2) { print "-- stop at: "; DirectorTraceStack(); }
            DirectorStop();
            if (debug_dialogue >= 2) { print "-- after stop: "; DirectorTraceStack(); }
            rtrue;
        ENDING_DSEL, ENDING_SAYING_DSEL, ENDING_FINALLY_DSEL, ENDING_FINALLY_SAYING_DSEL:
            if (debug_dialogue >= 2) { print "-- ending at: "; DirectorTraceStack(); }
            deadflag = chdata-->CONTENT_DCMETADATA;
            if (chdata-->TYPE_DCMETADATA == ENDING_FINALLY_DSEL or ENDING_FINALLY_SAYING_DSEL)
                story_complete = true;
            rtrue;
        PERFORM_DSEL:
            b = chdata-->CONTENT_DCMETADATA;
            if (b ofclass Routine) b = b();
            DirectorPerformBeat(b); rtrue;
        default: print "*** Unimplemented choice ***^"; rfalse;
    }
    rtrue;
];