To create and manage activities, which are bundles of rules for carrying out tasks.
§1. Introduction. An activity is just a triple of rulebooks with related names, a common focus and a shared set of variables, so this will not be a long section of code.
typedef struct activity { struct wording name; text of the name of the activity struct rulebook *before_rules; rulebooks for when this is followed struct rulebook *for_rules; struct rulebook *after_rules; struct kind *activity_on_what_kind; or null struct shared_variable_set *activity_variables; activity variables owned here struct activity_compilation_data compilation_data; CLASS_DEFINITION } activity;
- The structure activity is accessed in 3/nuor, 3/dbtr, 3/rpr, 4/ass, 5/id, 5/idf, 5/adf, 5/tpf, 5/po, 5/rf, 5/rcd, 6/rls, 6/rlb, 6/fao, 6/sv, 7/tc, 7/tbl, 7/eqt and here.
§2. Whereas rulebooks can turn values into other values, activities are more like void functions: they work on a value, but produce nothing.
kind *Activities::to_kind(activity *av) { return Kinds::unary_con(CON_activity, av->activity_on_what_kind); }
§3. Activities are much simpler to create than actions. For example,
Announcing something is an activity on numbers.
The object phrase (here "an activity on numbers") matches <k-kind> and needs no special Preform of its own; here is the subject phrase:
<activity-sentence-subject> ::= <activity-noted> ( <documentation-symbol> ) | ==> { R[1], -, <<ds>> = R[2] } <activity-noted> -- <documentation-symbol> -- | ==> { R[1], -, <<ds>> = R[2] } <activity-noted> ==> { R[1], -, <<ds>> = -1 } <activity-noted> ::= <activity-new-name> ( future action ) | ==> { TRUE, -, <<future>> = TRUE } <activity-new-name> ( ... ) | ==> Issue PM_ActivityNoteUnknown problem3.1 <activity-new-name> ==> { TRUE, -, <<future>> = FALSE } <activity-new-name> ::= ... of/for something/anything | ==> { 0, -, <<any>> = TRUE } ... something/anything | ==> { 0, -, <<any>> = TRUE } ... ==> { 0, -, <<any>> = FALSE }
- This is Preform grammar, not regular C code.
§3.1. Issue PM_ActivityNoteUnknown problem3.1 =
StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_ActivityNoteUnknown), "one of the notes about this activity makes no sense", "and should be either 'documented at SYMBOL' or 'future action'."); ==> { FALSE, - };
- This code is used in §3.
activity *Activities::new(kind *K, wording W) { kind *on_kind = Kinds::unary_construction_material(K); int kind_given = TRUE; if (Kinds::eq(on_kind, K_nil)) { kind_given = FALSE; on_kind = K_object; } <activity-sentence-subject>(W); W = GET_RW(<activity-new-name>, 1); wording doc_symbol = Wordings::one_word(<<ds>>); int future_action_flag = <<future>>; The name can't have been used before4.1; The kind the activity is performed on, if there is one, must be definite4.2; If it is not of or for something, then it cannot have a kind4.3; activity *av = CREATE(activity); av->name = W; av->compilation_data = RTActivities::new_compilation_data(av, doc_symbol); av->activity_on_what_kind = on_kind; LOGIF(ACTIVITY_CREATIONS, "Created activity '%W'\n", av->name); Make proper nouns for the activity name4.5; av->activity_variables = SharedVariables::new_set(av->compilation_data.variables_id); av->before_rules = Activities::make_rulebook(av, 0, future_action_flag); av->for_rules = Activities::make_rulebook(av, 1, future_action_flag); av->after_rules = Activities::make_rulebook(av, 2, future_action_flag); Activities::set_std(av); return av; }
§4.1. The name can't have been used before4.1 =
if (<s-value>(W)) { parse_node *spec = <<rp>>; if (!(Node::is(spec, UNKNOWN_NT)) && (!(Node::is(spec, PROPERTY_VALUE_NT)))) { StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_BadActivityName), "this already has a meaning", "and so cannot be the name of a newly created activity."); return NULL; } }
- This code is used in §4.
§4.2. The kind the activity is performed on, if there is one, must be definite4.2 =
if (Kinds::Behaviour::definite(on_kind) == FALSE) { LOG("I'm reading the kind as: %u\n", on_kind); StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_ActivityIndefinite), "this is an activity on a kind which isn't definite", "and doesn't tell me enough about what sort of value the activity should work " "on. For example, 'Divining is an activity on numbers' is fine because " "'numbers' is definite, but 'Divining is an activity on values' is not " "allowed."); return NULL; }
- This code is used in §4.
§4.3. If it is not of or for something, then it cannot have a kind4.3 =
if ((<<any>> == FALSE) && (kind_given)) { StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_ActivityMisnamed), "the name of this activity implies that it acts on nothing", "which doesn't fit with what you say about it. For example, 'Painting is an " "activity on brushes' isn't allowed because the activity's name doesn't end " "with 'something': it should be 'Painting something is an activity on brushes'."); return NULL; }
- This code is used in §4.
§4.4. Once a new activity has been created, the following is used to make a noun for it; actually two — for example, both "announcing" and "announcing activity".
<activity-name-construction> ::= ... activity
- This is Preform grammar, not regular C code.
§4.5. Make proper nouns for the activity name4.5 =
Nouns::new_proper_noun(W, NEUTER_GENDER, ADD_TO_LEXICON_NTOPT, ACTIVITY_MC, Rvalues::from_activity(av), Task::language_of_syntax()); word_assemblage wa = PreformUtilities::merge(<activity-name-construction>, 0, WordAssemblages::from_wording(av->name)); wording AW = WordAssemblages::to_wording(&wa); Nouns::new_proper_noun(AW, NEUTER_GENDER, ADD_TO_LEXICON_NTOPT, ACTIVITY_MC, Rvalues::from_activity(av), Task::language_of_syntax());
- This code is used in §4.
§5. And its rulebooks are named with these constructions:
<activity-rulebook-construction> ::= before ... | for ... | after ...
- This is Preform grammar, not regular C code.
rulebook *Activities::make_rulebook(activity *av, int N, int future_action_flag) { int def = NO_OUTCOME; if (N == 1) def = SUCCESS_OUTCOME; word_assemblage wa = PreformUtilities::merge(<activity-rulebook-construction>, N, WordAssemblages::from_wording(av->name)); wording RW = WordAssemblages::to_wording(&wa); rulebook *R = Rulebooks::new_automatic(RW, av->activity_on_what_kind, def, FALSE, future_action_flag, TRUE, 0, RTActivities::rulebook_package(av, N)); Rulebooks::grant_access_to_variables(R, av->activity_variables); return R; }
§7. And this nonterminal parses individual activity names.
<activity-name> internal { parse_node *p = Lexicon::retrieve(ACTIVITY_MC, W); if (Rvalues::is_CONSTANT_construction(p, CON_activity)) { ==> { -, Rvalues::to_activity(p) }; return TRUE; } ==> { fail nonterminal } }
- This is Preform grammar, not regular C code.
§8. Activity variables. Any new activity variable name is vetted by being run through this:
void Activities::add_variable(activity *av, parse_node *cnode) { if (Node::get_type(cnode) == UNPARSED_NOUN_NT) { Problems::quote_source(1, current_sentence); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ActivityVariableNameless)); Problems::issue_problem_segment( "You wrote %1, which I am reading as a request to make a new named variable " "for an activity - a value associated with a activity and which has a name. " "Here, though, there seems to be no name for the variable as such, only an " "indication of its kind. Try something like 'The printing the banner text " "activity has a number called the accumulated vanity'."); Problems::issue_problem_end(); return; } wording SW = Node::get_text(cnode->down); wording VW = Node::get_text(cnode->down->next); parse_node *spec = NULL; if (<s-type-expression>(SW)) spec = <<rp>>; The name of the variable must be fortunate8.1; The specification must not be qualified8.2; The specification must be just a kind8.3; That kind must be definite8.4; SharedVariables::new(av->activity_variables, VW, Specifications::to_kind(spec), FALSE); }
§8.1. The name of the variable must be fortunate8.1 =
if (<unfortunate-name>(VW)) { Problems::quote_source(1, current_sentence); Problems::quote_wording(2, VW); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ActivityVarAnd)); Problems::issue_problem_segment( "You wrote %1, which I am reading as a request to make a new named variable " "for an activity - a value associated with a activity and which has a name. " "The request seems to say that the name in question is '%2', but I'd prefer " "to avoid 'and', 'or', 'with', or 'having' in such names, please."); Problems::issue_problem_end(); return; }
- This code is used in §8.
§8.2. The specification must not be qualified8.2 =
if ((Specifications::is_kind_like(spec) == FALSE) && (Specifications::is_description(spec))) { Problems::quote_source(1, current_sentence); Problems::quote_wording(2, SW); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ActivityVarOverspecific)); Problems::issue_problem_segment( "You wrote %1, which I am reading as a request to make a new named variable " "for an activity - a value associated with a activity and which has a name. " "The request seems to say that the value in question is '%2', but this is too " "specific a description. (Instead, a kind of value (such as 'number') or a " "kind of object (such as 'room' or 'thing') should be given. To get a property " "whose contents can be any kind of object, use 'object'.)"); Problems::issue_problem_end(); return; }
- This code is used in §8.
§8.3. The specification must be just a kind8.3 =
if (Specifications::is_kind_like(spec) == FALSE) { LOG("Offending SP: $T", spec); Problems::quote_source(1, current_sentence); Problems::quote_wording(2, SW); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ActivityVarUnknownKOV)); Problems::issue_problem_segment( "You wrote %1, but '%2' is not the name of a kind of value which I know " "(such as 'number' or 'text')."); Problems::issue_problem_end(); return; }
- This code is used in §8.
§8.4. That kind must be definite8.4 =
if (Kinds::Behaviour::definite(Specifications::to_kind(spec)) == FALSE) { Problems::quote_source(1, current_sentence); Problems::quote_wording(2, SW); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ActivityVarValue)); Problems::issue_problem_segment( "You wrote %1, but this does not give me a clear enough idea what it will hold. " "You need to say what kind of value: for instance, 'A door has a number called " "street address.' is allowed because 'number' is specific about the kind of " "value."); Problems::issue_problem_end(); return; }
- This code is used in §8.
§9. Standard activities. As with rulebooks — see the similar discussion at Rulebooks::std — a few activities are special to the compiler, though in fact purely for indexing purposes.
These are recognised by the order in which they are declared, which makes it crucial not to change that order in Miscellaneous Definitions (in basic_inform) and Physical World Model (in standard_rules) without making matching changes both here and in BasicInformKit and WorldModelKit. So: don't casually change the following numbers.
Note that in the world of Basic Inform only, none of these will exist except for the first five.
define STARTING_VIRTUAL_MACHINE_ACT 0 define PRINTING_THE_NAME_ACT 1 define PRINTING_THE_PLURAL_NAME_ACT 2 define PRINTING_RESPONSE_ACT 3 define PRINTING_A_NUMBER_OF_ACT 4 define PRINTING_ROOM_DESC_DETAILS_ACT 5 define PRINTING_INVENTORY_DETAILS_ACT 6 define LISTING_CONTENTS_ACT 7 define GROUPING_TOGETHER_ACT 8 define WRITING_A_PARAGRAPH_ABOUT_ACT 9 define LISTING_NONDESCRIPT_ITEMS_ACT 10 define PRINTING_NAME_OF_DARK_ROOM_ACT 11 define PRINTING_DESC_OF_DARK_ROOM_ACT 12 define PRINTING_NEWS_OF_DARKNESS_ACT 13 define PRINTING_NEWS_OF_LIGHT_ACT 14 define REFUSAL_TO_ACT_IN_DARK_ACT 15 define CONSTRUCTING_STATUS_LINE_ACT 16 define PRINTING_BANNER_TEXT_ACT 17 define READING_A_COMMAND_ACT 18 define DECIDING_SCOPE_ACT 19 define DECIDING_CONCEALED_POSSESS_ACT 20 define DECIDING_WHETHER_ALL_INC_ACT 21 define CLARIFYING_PARSERS_CHOICE_ACT 22 define ASKING_WHICH_DO_YOU_MEAN_ACT 23 define PRINTING_A_PARSER_ERROR_ACT 24 define SUPPLYING_A_MISSING_NOUN_ACT 25 define SUPPLYING_A_MISSING_SECOND_ACT 26 define IMPLICITLY_TAKING_ACT 27 define AMUSING_A_VICTORIOUS_PLAYER_ACT 28 define PRINTING_PLAYERS_OBITUARY_ACT 29 define DEALING_WITH_FINAL_QUESTION_ACT 30 define PRINTING_LOCALE_DESCRIPTION_ACT 31 define CHOOSING_NOTABLE_LOCALE_OBJ_ACT 32 define PRINTING_LOCALE_PARAGRAPH_ACT 33
§10. The rest of the compiler should call Activities::std(N) to obtain activity N.
define MAX_BUILT_IN_ACTIVITIES 64
int built_in_activities_initialised = FALSE; activity *built_in_activities[MAX_BUILT_IN_ACTIVITIES]; activity *Activities::std(int N) { if ((N < 0) || (N >= MAX_BUILT_IN_ACTIVITIES)) internal_error("N out of range"); if (built_in_activities_initialised == FALSE) { built_in_activities_initialised = TRUE; for (int i=0; i<MAX_BUILT_IN_ACTIVITIES; i++) built_in_activities[i] = NULL; } return built_in_activities[N]; } void Activities::set_std(activity *Av) { if (built_in_activities_initialised == FALSE) { built_in_activities_initialised = TRUE; for (int i=0; i<MAX_BUILT_IN_ACTIVITIES; i++) built_in_activities[i] = NULL; } if (Av->allocation_id < MAX_BUILT_IN_ACTIVITIES) built_in_activities[Av->allocation_id] = Av; }