DECLARE_CLASS(I6T_intervention)
@@ -109,6 +112,9 @@ which use this module:
DECLARE_CLASS(index_element)DECLARE_CLASS(index_page)DECLARE_CLASS(index_tlexicon_entry)
+DECLARE_CLASS(simplified_scene)
+DECLARE_CLASS(simplified_end)
+DECLARE_CLASS(simplified_connector)
§3. Like all modules, this one must define a start and end function:
§3.2. Register this module's memory allocation reasons3.2 =
Memory::reason_name(CODE_GENERATION_MREASON, "code generation workspace for objects");
+Memory::reason_name(SCENE_SORTING_MREASON, "scene index sorting");
§1.1. Index the rubric about quasinumerical kinds1.1 =
+
+
+
+HTML_OPEN("p");
+HTML_TAG_WITH("a", "calculator");
+HTML::begin_plain_html_table(OUT);
+HTML::first_html_column(OUT, 0);
+HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/calc2.png");
+WRITE(" ");
+WRITE("Kinds of value marked with the calculator symbol are numerical - "
+"these are values we can add, multiply and so on. The range of these "
+"numbers depends on the Format setting for the project (Glulx format "
+"supports much higher numbers than Z-code).");
+HTML::end_html_row(OUT);
+HTML::end_html_table(OUT);
+HTML_CLOSE("p");
+
diff --git a/docs/codegen-module/6-ce2.html b/docs/codegen-module/6-ce2.html
index ed4d57b71..0ba838c14 100644
--- a/docs/codegen-module/6-ce2.html
+++ b/docs/codegen-module/6-ce2.html
@@ -150,7 +150,7 @@ simplified form of the iFiction record, without the XML overhead.
}
diff --git a/docs/codegen-module/6-ee.html b/docs/codegen-module/6-ee.html
index a23ab9a71..aaa2a9f1c 100644
--- a/docs/codegen-module/6-ee.html
+++ b/docs/codegen-module/6-ee.html
@@ -150,7 +150,7 @@ function togglePopup(material_id) {
diff --git a/docs/codegen-module/6-fe.html b/docs/codegen-module/6-fe.html
index 723249dc5..6b7591ecd 100644
--- a/docs/codegen-module/6-fe.html
+++ b/docs/codegen-module/6-fe.html
@@ -353,7 +353,7 @@ to match this width, preserving the aspect ratio.
§1. The mapping of time is on the one hand simpler than the mapping of space
+since there is only one dimension, but on the other hand more complex since
+scenes can be multiply present at the same instant of time (whereas rooms
+cannot be multiply present at the same point in space). We resolve this
+with a notation which takes a little bit of on-screen explanation, but
+seems natural enough to learn in practice.
+
The structure simplified_scene is accessed in 6/ir and here.
The structure simplified_end is private to this section.
The structure simplified_connector is accessed in 2/ass and here.
+
§1.1. The sorted ordering is used as-is later on, when we get to the details, but
+for the tabulation it's refined further. First we have the start-of-play
+scenes, in sorted order; then scenes with a condition for their beginning
+(end 0), in sorted order; then scenes that don't, and which haven't been
+covered as a result of one of the earlier ones, also in sorted order. (This
+third category is usually empty except for scenes the author has forgotten
+about and created but never made use of.)
+
§1.3.1. The curious condition about end 1 here is to avoid printing "Ends: Never"
+in cases where fancier ends for the scene exist, so that the scene can, in
+fact, end.
+
§1.3.1.2. Explain the Entire Game scene1.3.1.2 =
+
+
+
+HTML::open_indented_p(OUT, 1, "tight");
+WRITE("The Entire Game scene is built-in. It is going on whenever play is "
+"going on. (It is recurring so that if the story ends, but then resumes, "
+"it too will end but then begin again.)");
+HTML_CLOSE("p");
+
§2. Table of Scenes. We finally return to the table of scenes. The following is recursive, and
+is called at the top level for each scene in turn which starts at the start
+of play (see above).
+
+
+
A scene entry can be arrived at in three ways: through one of its ends, in
+which case end is the number (0 for begins, 1 for standard ends, and so on),
+or through being already active at the start of play, or through being covered
+in the index even though it never happens in play. This means we need two
+additional end numbers. They are only ever used at the top level, that is,
+on the initial call when depth is 0.
+
§2.5. And this is where the routine recurses, so that consequent scenes are
+tabulated underneath the present one, indented one step further in (since
+indentation is coupled to depth). First we recurse to scenes which end when
+this one does; then to scenes which begin when this one ends.
+
+
+
Indent to tabulate other scenes connected to the ends of this one2.5 =
+
§4. Lastly: the following is the criterion used for sorting the scenes into
+their indexing order. The Entire Game always comes first, and then come the
+rest in ascending alphabetical order.
+
+ Plot Element -
+ To write the Plot element (Pl) in the index.
+
diff --git a/docs/if-module/3-scn.html b/docs/if-module/3-scn.html
index 564c66764..38f87bb07 100644
--- a/docs/if-module/3-scn.html
+++ b/docs/if-module/3-scn.html
@@ -196,8 +196,6 @@ which can cause it, or can be "anchored" to any number of ends of other
scenes — to express which, the scene_connector structure is used.
-
The structure activity_indexing_data is private to this section.
The structure activity_crossref is accessed in 2/ins, 2/rls, 3/pe, 4/em and here.
+
The structure activity_indexing_data is private to this section.
The structure activity_crossref is accessed in 2/ins, 2/rls, 4/em and here.
§2.
@@ -102,7 +102,7 @@
}
diff --git a/docs/index-module/2-adj.html b/docs/index-module/2-adj.html
index 6846a8c4a..9a8525290 100644
--- a/docs/index-module/2-adj.html
+++ b/docs/index-module/2-adj.html
@@ -96,7 +96,7 @@ prefaced "(of a rulebook)", "(of an activity)", and so on.
§1.1. Index the rubric about quasinumerical kinds1.1 =
-
-
-
-HTML_OPEN("p");
-HTML_TAG_WITH("a", "calculator");
-HTML::begin_plain_html_table(OUT);
-HTML::first_html_column(OUT, 0);
-HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/calc2.png");
-WRITE(" ");
-WRITE("Kinds of value marked with the <b>calculator symbol</b> are numerical - "
-"these are values we can add, multiply and so on. The range of these "
-"numbers depends on the Format setting for the project (Glulx format "
-"supports much higher numbers than Z-code).");
-HTML::end_html_row(OUT);
-HTML::end_html_table(OUT);
-HTML_CLOSE("p");
-
§1. The mapping of time is on the one hand simpler than the mapping of space
-since there is only one dimension, but on the other hand more complex since
-scenes can be multiply present at the same instant of time (whereas rooms
-cannot be multiply present at the same point in space). We resolve this
-with a notation which takes a little bit of on-screen explanation, but
-seems natural enough to learn in practice.
-
§1.2. The sorted ordering is used as-is later on, when we get to the details, but
-for the tabulation it's refined further. First we have the start-of-play
-scenes, in sorted order; then scenes with a condition for their beginning
-(end 0), in sorted order; then scenes that don't, and which haven't been
-covered as a result of one of the earlier ones, also in sorted order. (This
-third category is usually empty except for scenes the author has forgotten
-about and created but never made use of.)
-
§1.3. Show the legend for the scene table icons1.3 =
-
-
-
-HTML_OPEN("p"); WRITE("Legend: ");
-IXScenes::scene_icon_legend(OUT, "WPB", "Begins when play begins");
-WRITE("; ");
-IXScenes::scene_icon_legend(OUT, "WhenC", "can begin whenever some condition holds");
-WRITE("; ");
-IXScenes::scene_icon_legend(OUT, "Segue", "follows when a previous scene ends");
-WRITE("; ");
-IXScenes::scene_icon_legend(OUT, "Simul", "begins simultaneously");
-WRITE("; ");
-IXScenes::scene_icon_legend(OUT, "WNever", "never begins");
-WRITE("; ");
-IXScenes::scene_icon_legend(OUT, "ENever", "never ends");
-WRITE("; ");
-IXScenes::scene_icon_legend(OUT, "Recurring", "recurring (can happen more than once)");
-WRITE(". <i>Scene names are italicised when and if they appear for a second "
-"or subsequent time because the scene can begin in more than one way</i>.");
-HTML_CLOSE("p");
-
§1.4.1. The curious condition about end 1 here is to avoid printing "Ends: Never"
-in cases where fancier ends for the scene exist, so that the scene can, in
-fact, end.
-
§1.4.1.2. Explain the Entire Game scene1.4.1.2 =
-
-
-
-HTML::open_indented_p(OUT, 1, "tight");
-WRITE("The Entire Game scene is built-in. It is going on whenever play is "
-"going on. (It is recurring so that if the story ends, but then resumes, "
-"it too will end but then begin again.)");
-HTML_CLOSE("p");
-
§2. Table of Scenes. We finally return to the table of scenes. The following is recursive, and
-is called at the top level for each scene in turn which starts at the start
-of play (see above).
-
-
-
A scene entry can be arrived at in three ways: through one of its ends, in
-which case end is the number (0 for begins, 1 for standard ends, and so on),
-or through being already active at the start of play, or through being covered
-in the index even though it never happens in play. This means we need two
-additional end numbers. They are only ever used at the top level, that is,
-on the initial call when depth is 0.
-
§2.5. And this is where the routine recurses, so that consequent scenes are
-tabulated underneath the present one, indented one step further in (since
-indentation is coupled to depth). First we recurse to scenes which end when
-this one does; then to scenes which begin when this one ends.
-
-
-
Indent to tabulate other scenes connected to the ends of this one2.5 =
-
§4. Lastly: the following is the criterion used for sorting the scenes into
-their indexing order. The Entire Game always comes first, and then come the
-rest in ascending alphabetical order.
-
@@ -164,11 +159,6 @@
The Map -
Indexing the player's initial position.
-
-
- Plot Element -
- Parallel to the World index of space is the Scenes index of time, and in this section we render it as HTML.
-
Actions -
diff --git a/docs/runtime-module/2-ec.html b/docs/runtime-module/2-ec.html
index dd6f4bc59..a749d40d3 100644
--- a/docs/runtime-module/2-ec.html
+++ b/docs/runtime-module/2-ec.html
@@ -108,10 +108,10 @@ instruction last emitted, not after it.
● EmitCode::up then returns us back to where we were.
@@ -255,7 +255,7 @@ this can be achieved with an Inter
-voidEmitCode::cast(kind *F, kind *T) {
+voidEmitCode::cast(kind *F, kind *T) {Produce::cast(Emit::tree(), F, T);}
@@ -322,11 +322,11 @@ in such cases, this function must exist in the kits somewhere.
-voidEmitCode::inv(inter_tibip) {
+voidEmitCode::inv(inter_tibip) {Produce::inv_primitive(Emit::tree(), bip);}
-voidEmitCode::call(inter_name *fn_iname) {
+voidEmitCode::call(inter_name *fn_iname) {Produce::inv_call_iname(Emit::tree(), fn_iname);}
diff --git a/docs/runtime-module/2-hrr.html b/docs/runtime-module/2-hrr.html
index d12571141..000ceedc4 100644
--- a/docs/runtime-module/2-hrr.html
+++ b/docs/runtime-module/2-hrr.html
@@ -953,6 +953,11 @@ that the compiler can refer to it.
enumINSTANCE_INDEX_KIND_MD_HLenumINSTANCE_IS_OBJECT_MD_HLenumINSTANCE_IS_SCENE_MD_HL
+enumINSTANCE_IS_ENTIRE_GAME_MD_HL
+enumINSTANCE_SCENE_STARTS_MD_HL
+enumINSTANCE_SCENE_STARTS_ON_CONDITION_MD_HL
+enumINSTANCE_SCENE_RECURS_MD_HL
+enumINSTANCE_SCENE_NEVER_ENDS_MD_HLenumINSTANCE_IS_EXF_MD_HLenumINSTANCE_FILE_VALUE_MD_HLenumINSTANCE_FILE_IS_BINARY_MD_HL
@@ -968,6 +973,15 @@ that the compiler can refer to it.
enumINSTANCE_SOUND_ID_MD_HLenumINSTANCE_SSF_MD_HLenumINSTANCE_SCF_MD_HL
+enumSCENE_ENDS_HAP
+enumSCENE_END_NAME_MD_HL
+enumSCENE_END_AT_MD_HL
+enumSCENE_END_CONDITION_MD_HL
+enumSCENE_END_RULEBOOK_MD_HL
+enumSCENE_CONNECTORS_HAP
+enumSCENE_CONNECTOR_TO_MD_HL
+enumSCENE_CONNECTOR_END_MD_HL
+enumSCENE_CONNECTOR_AT_MD_HLenumINST_SHOWME_MD_HLenumINST_SHOWME_FN_HLenumINSTANCE_HL
@@ -998,8 +1012,24 @@ that the compiler can refer to it.
H_C_U(INSTANCE_INDEX_KIND_MD_HL, I"^index_kind")H_C_U(INSTANCE_IS_OBJECT_MD_HL, I"^is_object")H_C_U(INSTANCE_IS_SCENE_MD_HL, I"^is_scene")
+H_C_U(INSTANCE_IS_ENTIRE_GAME_MD_HL, I"^is_entire_game")
+H_C_U(INSTANCE_SCENE_STARTS_MD_HL, I"^starts")
+H_C_U(INSTANCE_SCENE_STARTS_ON_CONDITION_MD_HL, I"^starts_on_condition")
+H_C_U(INSTANCE_SCENE_RECURS_MD_HL, I"^recurs")
+H_C_U(INSTANCE_SCENE_NEVER_ENDS_MD_HL, I"^never_ends")H_C_U(INSTANCE_SSF_MD_HL, I"^scene_status_fn")H_C_U(INSTANCE_SCF_MD_HL, I"^scene_change_fn")
+H_BEGIN_AP(SCENE_ENDS_HAP, I"scene_end", I"_scene_end")
+H_C_U(SCENE_END_NAME_MD_HL, I"^name")
+H_C_U(SCENE_END_AT_MD_HL, I"^at")
+H_C_U(SCENE_END_CONDITION_MD_HL, I"^condition")
+H_C_U(SCENE_END_RULEBOOK_MD_HL, I"^rulebook")
+H_BEGIN_AP(SCENE_CONNECTORS_HAP, I"scene_connector", I"_scene_connector")
+H_C_U(SCENE_CONNECTOR_TO_MD_HL, I"^to")
+H_C_U(SCENE_CONNECTOR_END_MD_HL, I"^end")
+H_C_U(SCENE_CONNECTOR_AT_MD_HL, I"^at")
+H_END
+H_ENDH_C_U(INSTANCE_IS_EXF_MD_HL, I"^is_file")H_C_U(INSTANCE_FILE_VALUE_MD_HL, I"^file_value")H_C_U(INSTANCE_FILE_OWNED_MD_HL, I"^file_owned")
@@ -1090,6 +1120,9 @@ that the compiler can refer to it.
enumKIND_DSIZE_MD_HLenumKIND_DOCUMENTATION_MD_HLenumRUCKSACK_CLASS_MD_HL
+enumMIN_VAL_INDEX_MD_HL
+enumMAX_VAL_INDEX_MD_HL
+enumDIMENSIONS_INDEX_MD_HLenumWEAK_ID_HLenumICOUNT_HLenumILIST_HL
@@ -1127,6 +1160,14 @@ that the compiler can refer to it.
enumDK_DEFAULT_VALUE_HLenumKIND_USAGE_HAPenumKIND_CLASS_HL
+enumMULTIPLICATION_RULE_HAP
+enumSET_AT_MD_HL
+enumLEFT_OPERAND_MD_HL
+enumRIGHT_OPERAND_MD_HL
+enumRESULT_MD_HL
+enumLEFT_OPERAND_BM_MD_HL
+enumRIGHT_OPERAND_BM_MD_HL
+enumRESULT_BM_MD_HL
§8.1.28. Establish kinds8.1.28 =
@@ -1161,6 +1202,9 @@ that the compiler can refer to it.
H_C_U(KIND_MKDEF_FN_MD_HL, I"^mkdef_fn")H_C_U(KIND_DSIZE_MD_HL, I"^domain_size")H_C_U(RUCKSACK_CLASS_MD_HL, I"^rucksack_class")
+H_C_U(MIN_VAL_INDEX_MD_HL, I"^min_value")
+H_C_U(MAX_VAL_INDEX_MD_HL, I"^max_value")
+H_C_U(DIMENSIONS_INDEX_MD_HL, I"^dimensions")H_C_U(KIND_DOCUMENTATION_MD_HL, I"^documentation")H_C_I(WEAK_ID_HL)H_C_I(ICOUNT_HL)
@@ -1195,7 +1239,7 @@ that the compiler can refer to it.
H_ENDH_ENDH_BEGIN_AP(DERIVED_KIND_HAP, I"derived_kind", I"_derived_kind")
-H_C_U(DK_NEEDED_MD_HL, I"^default_value_needed")
+H_C_U(DK_NEEDED_MD_HL, I"^default_value_needed")H_C_U(DK_STRONG_ID_HL, I"strong_id")H_C_G(DK_KIND_HL, I"DK")H_C_U(DK_DEFAULT_VALUE_HL, I"default_value")
@@ -1207,6 +1251,15 @@ that the compiler can refer to it.
H_BEGIN(HierarchyLocations::completion_submodule(I, kinds))H_BEGIN_AP(KIND_USAGE_HAP, I"kind_usage", I"_kind_usage")H_END
+H_BEGIN_AP(MULTIPLICATION_RULE_HAP, I"multiplication_rule", I"_multiplication_rule")
+H_C_U(SET_AT_MD_HL, I"^at")
+H_C_U(LEFT_OPERAND_MD_HL, I"^left_operand")
+H_C_U(RIGHT_OPERAND_MD_HL, I"^right_operand")
+H_C_U(RESULT_MD_HL, I"^result")
+H_C_U(LEFT_OPERAND_BM_MD_HL, I"^left_operand_benchmark")
+H_C_U(RIGHT_OPERAND_BM_MD_HL, I"^right_operand_benchmark")
+H_C_U(RESULT_BM_MD_HL, I"^result_benchmark")
+H_ENDH_END
§10.3.1. A slightly bogus case first. If the source text declares a kind but never
+
§10.7.1. A slightly bogus case first. If the source text declares a kind but never
gives any enumerated values or literal patterns, then such values will never
appear at run-time; but we need the printing routine to exist to avoid
compilation errors.
-
Compile I6 printing routine for a vacant but named kind10.3.1 =
+
Compile I6 printing routine for a vacant but named kind10.7.1 =
§10.7.2. A unit is printed back with its earliest-defined literal pattern used as
notation. If it had no literal patterns, it would come out as decimal numbers,
but at present this can't happen.
-
Compile I6 printing routine for a unit kind10.3.2 =
+
Compile I6 printing routine for a unit kind10.7.2 =
@@ -825,8 +915,8 @@ but at present this can't happen.
Functions::end(save); }
§10.7.4. The suite of standard routines provided for enumerative types is a little
like the one in Ada (T'Succ, T'Pred, and so on).
@@ -895,7 +985,7 @@ wrapping around to the first from the last;
wrapping around to the last from the first, so that it is the inverse function
to A_T1_colour(v).
-
Compile the A and B routines for an enumerated kind10.3.4 =
+
Compile the A and B routines for an enumerated kind10.7.4 =
§10.7.4.1. There should be a blue historical plaque on the wall here: this was the
first function ever implemented by emitting Inter code, on 12 November 2017.
-
Implement the A routine10.3.4.1 =
+
Implement the A routine10.7.4.1 =
@@ -951,11 +1041,11 @@ first function ever implemented by emitting Inter code, on 12 November 2017.
EmitCode::up();
diff --git a/docs/runtime-module/6-pp.html b/docs/runtime-module/6-pp.html
index c88de3ab2..4c4d095c1 100644
--- a/docs/runtime-module/6-pp.html
+++ b/docs/runtime-module/6-pp.html
@@ -100,7 +100,7 @@ function togglePopup(material_id) {
-voidRTPropertyPermissions::emit_kind_permissions(kind *K) {
+voidRTPropertyPermissions::emit_kind_permissions(kind *K) {inference_subject *subj = KindSubjects::from_kind(K);intc = 0;property_permission *pp;
diff --git a/docs/runtime-module/6-pv.html b/docs/runtime-module/6-pv.html
index 4a0978511..5a8b7a58f 100644
--- a/docs/runtime-module/6-pv.html
+++ b/docs/runtime-module/6-pv.html
@@ -82,7 +82,7 @@ function togglePopup(material_id) {
RTPropertyValues::emit_subject(Instances::as_subject(I));}
-voidRTPropertyValues::compile_values_for_kind(kind *K) {
+voidRTPropertyValues::compile_values_for_kind(kind *K) {RTPropertyValues::emit_subject(KindSubjects::from_kind(K));RTPropertyValues::check_kind_can_have_property(K);}
diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt
index f9f8006d0..753e95662 100644
--- a/inform7/Figures/memory-diagnostics.txt
+++ b/inform7/Figures/memory-diagnostics.txt
@@ -1,12 +1,12 @@
-Total memory consumption was 331729K = 324 MB
+Total memory consumption was 331079K = 323 MB
-62.2% was used for 1658916 objects, in 326919 frames in 258 x 800K = 206400K = 201 MB:
+62.0% was used for 1660986 objects, in 326976 frames in 257 x 800K = 205600K = 200 MB:
9.7% inter_tree_node_array 46 x 8192 = 376832 objects, 33162688 bytes
- 6.6% text_stream_array 4027 x 100 = 402700 objects, 22680064 bytes
+ 6.7% text_stream_array 4036 x 100 = 403600 objects, 22730752 bytes
4.8% linked_list 29551 objects, 16548560 bytes
3.0% parse_node 129396 objects, 10351680 bytes
- 3.0% inter_symbol_array 104 x 1024 = 106496 objects, 10226944 bytes
+ 3.0% inter_symbol_array 105 x 1024 = 107520 objects, 10325280 bytes
2.1% verb_conjugation 160 objects, 7425280 bytes
1.6% parse_node_annotation_array 345 x 500 = 172500 objects, 5531040 bytes
1.0% pcalc_prop_array 25 x 1000 = 25000 objects, 3400800 bytes
@@ -18,13 +18,13 @@ Total memory consumption was 331729K = 324 MB
0.4% inter_name_generator_array 38 x 1000 = 38000 objects, 1521216 bytes
0.4% match_trie_array 11 x 1000 = 11000 objects, 1496352 bytes
0.4% i6_schema_array 23 x 100 = 2300 objects, 1380736 bytes
- 0.3% inter_package 16417 objects, 1182024 bytes
- 0.3% dictionary 22491 objects, 1079568 bytes
+ 0.3% inter_package 16419 objects, 1182168 bytes
+ 0.3% dictionary 22495 objects, 1079760 bytes
0.3% id_body 940 objects, 1075360 bytes
- 0.3% inter_symbols_table 16417 objects, 1050688 bytes
- 0.3% dict_entry_array 316 x 100 = 31600 objects, 1021312 bytes
+ 0.3% inter_symbols_table 16419 objects, 1050816 bytes
+ 0.3% dict_entry_array 317 x 100 = 31700 objects, 1024544 bytes
0.2% adjective_meaning 202 objects, 1000304 bytes
- 0.2% package_request 10993 objects, 967384 bytes
+ 0.2% package_request 10995 objects, 967560 bytes
0.2% excerpt_meaning 3098 objects, 966576 bytes
0.2% production 3871 objects, 898072 bytes
0.2% ptoken 8379 objects, 871416 bytes
@@ -43,7 +43,7 @@ Total memory consumption was 331729K = 324 MB
---- inter_annotation_array 1 x 8192 objects, 196640 bytes
---- binary_predicate 321 objects, 169488 bytes
---- linguistic_stock_item 3315 objects, 159120 bytes
- ---- hierarchy_location 982 objects, 149264 bytes
+ ---- hierarchy_location 1004 objects, 152608 bytes
---- rule_family_data 400 objects, 147200 bytes
---- nonterminal 759 objects, 139656 bytes
---- nascent_array 1948 objects, 124672 bytes
@@ -52,7 +52,7 @@ Total memory consumption was 331729K = 324 MB
---- imperative_defn 1376 objects, 99072 bytes
---- anl_entry_array 2 x 1000 = 2000 objects, 96064 bytes
---- noun_usage 2401 objects, 96040 bytes
- ---- inter_tree 6 objects, 91392 bytes
+ ---- inter_tree 6 objects, 92592 bytes
---- preposition 273 objects, 87360 bytes
---- lexical_cluster 2516 objects, 80512 bytes
---- pcalc_term_array 2 x 1000 = 2000 objects, 80064 bytes
@@ -109,14 +109,14 @@ Total memory consumption was 331729K = 324 MB
---- booking_list 407 objects, 13024 bytes
---- adjective_iname_holder 320 objects, 12800 bytes
---- pathname 292 objects, 11680 bytes
- ---- uniqueness_count 382 objects, 9168 bytes
+ ---- uniqueness_count 391 objects, 9384 bytes
---- stopwatch_timer 109 objects, 8720 bytes
---- filename 208 objects, 8320 bytes
---- equation_node 68 objects, 7616 bytes
---- understanding_item_array 3 x 100 = 300 objects, 7296 bytes
---- shared_variable_array 1 x 100 objects, 7232 bytes
---- determiner 22 objects, 7216 bytes
- ---- hierarchy_attachment_point 64 objects, 6144 bytes
+ ---- hierarchy_attachment_point 67 objects, 6432 bytes
---- verb 108 objects, 6048 bytes
---- text_literal_holder 144 objects, 5760 bytes
---- heading_tree 20 objects, 5440 bytes
@@ -156,14 +156,14 @@ Total memory consumption was 331729K = 324 MB
---- cached_kind_declaration 39 objects, 1560 bytes
---- noun_filter_token 22 objects, 1408 bytes
---- inter_annotation_form 35 objects, 1400 bytes
- ---- inter_tree_location_list 33 objects, 1320 bytes
+ ---- inter_tree_location_list 34 objects, 1360 bytes
---- special_meaning_holder 33 objects, 1320 bytes
---- constant_phrase 20 objects, 1280 bytes
---- build_script 40 objects, 1280 bytes
---- table_column 16 objects, 1280 bytes
---- invocation_options_array 1 x 100 objects, 1224 bytes
---- direction_inference_data 30 objects, 1200 bytes
- ---- tree_inventory_item 27 objects, 1080 bytes
+ ---- tree_inventory_item 28 objects, 1120 bytes
---- runtime_kind_structure 13 objects, 1040 bytes
---- quantifier 16 objects, 1024 bytes
---- named_rulebook_outcome 15 objects, 960 bytes
@@ -198,13 +198,13 @@ Total memory consumption was 331729K = 324 MB
---- door_dir_notice 5 objects, 320 bytes
---- pronoun 8 objects, 320 bytes
---- grammatical_category 8 objects, 320 bytes
- ---- tree_inventory 1 object, 304 bytes
+ ---- tree_inventory 1 object, 312 bytes
---- up_family 9 objects, 288 bytes
---- build_step 4 objects, 288 bytes
---- explicit_bp_data 5 objects, 280 bytes
- ---- door_to_notice 5 objects, 280 bytes
---- compilation_unit 5 objects, 280 bytes
---- contents_entry 7 objects, 280 bytes
+ ---- door_to_notice 5 objects, 280 bytes
---- inform_pipeline 4 objects, 256 bytes
---- verb_usage_tier 5 objects, 240 bytes
---- adjective_meaning_family 7 objects, 224 bytes
@@ -214,46 +214,46 @@ Total memory consumption was 331729K = 324 MB
---- kit_dependency 4 objects, 192 bytes
---- plural_dictionary_entry 4 objects, 192 bytes
---- inform_project 1 object, 176 bytes
- ---- code_generation_target 4 objects, 160 bytes
- ---- inter_architecture 4 objects, 160 bytes
---- imperative_defn_family 4 objects, 160 bytes
---- link_instruction 4 objects, 160 bytes
+ ---- code_generation_target 4 objects, 160 bytes
---- inference_subject_family 5 objects, 160 bytes
- ---- element_activation 4 objects, 128 bytes
+ ---- inter_architecture 4 objects, 160 bytes
---- codegen_pipeline 1 object, 128 bytes
+ ---- element_activation 4 objects, 128 bytes
---- inbuild_nest 3 objects, 120 bytes
---- local_block_value 2 objects, 112 bytes
---- inform_kit_ittt 2 objects, 96 bytes
- ---- article 2 objects, 80 bytes
- ---- group_together_function 2 objects, 80 bytes
---- compile_task_data 1 object, 80 bytes
+ ---- group_together_function 2 objects, 80 bytes
+ ---- article 2 objects, 80 bytes
---- build_methodology 1 object, 56 bytes
- ---- inter_warehouse 1 object, 56 bytes
---- figures_data 1 object, 56 bytes
- ---- HTML_file_state 1 object, 48 bytes
+ ---- inter_warehouse 1 object, 56 bytes
---- star_invention 1 object, 48 bytes
- ---- kind_template_definition 1 object, 40 bytes
+ ---- HTML_file_state 1 object, 48 bytes
---- loop_over_scope 1 object, 40 bytes
---- by_function_bp_data 1 object, 40 bytes
+ ---- kind_template_definition 1 object, 40 bytes
-37.7% was used for memory not allocated for objects:
+37.9% was used for memory not allocated for objects:
- 17.6% text stream storage 59833332 bytes in 416693 claims
- 3.6% dictionary storage 12430336 bytes in 22491 claims
+ 17.6% text stream storage 59984268 bytes in 417738 claims
+ 3.6% dictionary storage 12432384 bytes in 22495 claims
---- sorting 720 bytes in 3 claims
2.1% source text 7200000 bytes in 3 claims
3.1% source text details 10800000 bytes in 2 claims
---- linguistic stock array 81920 bytes in 2 claims
---- small word set array 105600 bytes in 22 claims
- 0.8% inter symbols storage 2820576 bytes in 17432 claims
+ 0.8% inter symbols storage 2820832 bytes in 17434 claims
4.9% inter bytecode storage 16802796 bytes in 14 claims
4.7% inter links storage 16174208 bytes in 266 claims
---- inter tree location list storage 191232 bytes in 32 claims
- 0.4% instance-of-kind counting 1695204 bytes in 1 claim
+ 0.5% instance-of-kind counting 1695204 bytes in 1 claim
---- compilation workspace for objects 21856 bytes in 25 claims
---- lists for type-checking invocations 16000 bytes in 1 claim
---- code generation workspace for objects 9648 bytes in 9 claims
---- emitter array storage 154432 bytes in 2037 claims
-19.3% was overhead - 65735600 bytes = 64194K = 62 MB
+19.1% was overhead - 64758368 bytes = 63240K = 61 MB
diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt
index df374d729..e78c3f41e 100644
--- a/inform7/Figures/timings-diagnostics.txt
+++ b/inform7/Figures/timings-diagnostics.txt
@@ -1,26 +1,25 @@
100.0% in inform7 run
53.4% in compilation to Inter
- 39.4% in //Sequence::undertake_queued_tasks//
- 3.9% in //MajorNodes::pre_pass//
- 2.8% in //MajorNodes::pass_1//
+ 39.7% in //Sequence::undertake_queued_tasks//
+ 3.8% in //MajorNodes::pre_pass//
+ 2.9% in //MajorNodes::pass_1//
1.5% in //ImperativeDefinitions::assess_all//
0.5% in //MajorNodes::pass_2//
0.5% in //RTKindConstructors::compile//
0.5% in //World::stage_V//
+ 0.3% in //CompletionModule::compile//
0.3% in //ImperativeDefinitions::compile_first_block//
0.3% in //Sequence::undertake_queued_tasks//
- 0.1% in //CompletionModule::compile//
0.1% in //InferenceSubjects::emit_all//
0.1% in //RTKindConstructors::compile_permissions//
0.1% in //Task::make_built_in_kind_constructors//
- 0.1% in //World::stages_II_and_III//
- 2.6% not specifically accounted for
- 44.3% in running Inter pipeline
- 11.2% in inter step 7/14: consolidate-text
- 10.8% in step preparation
- 9.0% in inter step 2/14: link
+ 2.2% not specifically accounted for
+ 44.4% in running Inter pipeline
+ 11.0% in inter step 7/14: consolidate-text
+ 11.0% in step preparation
+ 9.1% in inter step 2/14: link
7.4% in inter step 14/14: generate inform6 -> auto.inf
- 1.1% in inter step 10/14: make-identifiers-unique
+ 1.2% in inter step 10/14: make-identifiers-unique
0.3% in inter step 11/14: reconcile-verbs
0.3% in inter step 13/14: eliminate-redundant-operations
0.3% in inter step 6/14: assimilate
@@ -29,6 +28,6 @@
0.1% in inter step 5/14: resolve-conditional-compilation
0.1% in inter step 8/14: resolve-external-symbols
0.1% in inter step 9/14: inspect-plugs
- 2.7% not specifically accounted for
- 1.8% in supervisor
- 0.4% not specifically accounted for
+ 2.6% not specifically accounted for
+ 1.9% in supervisor
+ 0.2% not specifically accounted for
diff --git a/inform7/Tests/Test Internals/Index-Plot.txt b/inform7/Tests/Test Internals/Index-Plot.txt
new file mode 100644
index 000000000..6ba292a96
--- /dev/null
+++ b/inform7/Tests/Test Internals/Index-Plot.txt
@@ -0,0 +1,23 @@
+Hypothesis Junction is a room. The Waiting Room is east of Hypothesis Junction.
+
+Arrival is a scene. "There's a flourish of trumpets."
+
+When Arrival begins: say "There's a flourish of trumpets."
+
+Arrival begins when the player is in the Hypothesis Junction for the third turn.
+
+Luggage Trouble is a scene. Luggage Trouble begins when Railway Meeting begins.
+
+Railway Meeting is a scene. Railway Meeting begins when play begins.
+
+Railway Meeting ends when Luggage Trouble ends.
+
+Train Stop is a recurring scene. Train Wait is a recurring scene.
+Train Wait begins when play begins.
+Train Stop begins when Train Wait ends.
+Train Wait begins when Train Stop ends.
+
+Railway Meeting ends happily when the time of day is 11:00 PM.
+Railway Meeting ends wisely but sadly when the player is in the Waiting Room.
+
+Test index (internal) with Pl.
diff --git a/inform7/Tests/Test Internals/_Results_Ideal/Index-Plot.txt b/inform7/Tests/Test Internals/_Results_Ideal/Index-Plot.txt
new file mode 100644
index 000000000..3f76a1c37
--- /dev/null
+++ b/inform7/Tests/Test Internals/_Results_Ideal/Index-Plot.txt
@@ -0,0 +1,41 @@
+1. Pl
+
entire game
+
railway meeting
+
luggage trouble
+
train wait
+
train stop
+
train wait
+
arrival
+
Legend: Begins when play begins; can begin whenever some condition holds; follows when a previous scene ends; begins simultaneously; never begins; never ends; recurring (can happen more than once). Scene names are italicised when and if they appear for a second or subsequent time because the scene can begin in more than one way.
+
+
The entire game scenerecurring
+
The Entire Game scene is built-in. It is going on whenever play is going on. (It is recurring so that if the story ends, but then resumes, it too will end but then begin again.)
+
Begins when: the story has not ended
+
Ends when: the story has ended
+
+
The arrival scene
+
Begins when: the player is in the Hypothesis Junction
+
What happens:
+
(say "There's a flourish of trumpets.")
+
+
Ends when:never
+
+
The luggage trouble scene
+
Begins when:railway meetingbegins
+
Ends when:never
+
+
The railway meeting scene
+
Begins when:play begins
+
Ends when:luggage troubleends
+
Ends happily when: the time of day is 11:00 PM
+
Ends wisely but sadly when: the player is in the Waiting Room
+
+
The train stop scenerecurring
+
Begins when:train waitends
+
Ends when:never
+
+
The train wait scenerecurring
+
Begins when:play begins
+or when:train stopends
+
Ends when:never
+
diff --git a/inform7/if-module/Chapter 3/Scenes.w b/inform7/if-module/Chapter 3/Scenes.w
index e7b885221..4ff487bdf 100644
--- a/inform7/if-module/Chapter 3/Scenes.w
+++ b/inform7/if-module/Chapter 3/Scenes.w
@@ -111,8 +111,6 @@ triumphantly", for instance, might be ends 2 and 3). Each end has a condition
which can cause it, or can be "anchored" to any number of ends of other
scenes -- to express which, the //scene_connector// structure is used.
-@d MAX_SCENE_ENDS 32 /* this must exceed 31 */
-
=
typedef struct scene {
struct instance *as_instance; /* the constant for the name of the scene */
@@ -202,6 +200,12 @@ scene *Scenes::from_named_constant(instance *I) {
return NULL;
}
+int Scenes::is_entire_game(instance *I) {
+ if ((SC_entire_game) && (Scenes::from_named_constant(I) == SC_entire_game))
+ return TRUE;
+ return FALSE;
+}
+
@h Creating and parsing ends.
=
diff --git a/inform7/index-module/Chapter 3/Plot Element.w b/inform7/index-module/Chapter 3/Plot Element.w
deleted file mode 100644
index 331de229c..000000000
--- a/inform7/index-module/Chapter 3/Plot Element.w
+++ /dev/null
@@ -1,313 +0,0 @@
-[IXScenes::] Plot Element.
-
-Parallel to the World index of space is the Scenes index of time,
-and in this section we render it as HTML.
-
-@ The mapping of time is on the one hand simpler than the mapping of space
-since there is only one dimension, but on the other hand more complex since
-scenes can be multiply present at the same instant of time (whereas rooms
-cannot be multiply present at the same point in space). We resolve this
-with a notation which takes a little bit of on-screen explanation, but
-seems natural enough to learn in practice.
-
-=
-void IXScenes::render(OUTPUT_STREAM) {
- int nr = NUMBER_CREATED(scene);
- scene **sorted = Memory::calloc(nr, sizeof(scene *), INDEX_SORTING_MREASON);
- @;
-
- @;
- @;
- @;
-
- Memory::I7_array_free(sorted, INDEX_SORTING_MREASON, nr, sizeof(scene *));
-}
-
-@ As usual, we sort with the C library's |qsort|.
-
-@ =
- int i = 0;
- scene *sc;
- LOOP_OVER(sc, scene) sorted[i++] = sc;
- qsort(sorted, (size_t) nr, sizeof(scene *), IXScenes::compare_scenes);
-
-@ The sorted ordering is used as-is later on, when we get to the details, but
-for the tabulation it's refined further. First we have the start-of-play
-scenes, in sorted order; then scenes with a condition for their beginning
-(end 0), in sorted order; then scenes that don't, and which haven't been
-covered as a result of one of the earlier ones, also in sorted order. (This
-third category is usually empty except for scenes the author has forgotten
-about and created but never made use of.)
-
-@ =
- for (int i=0; istart_of_play) || (sc == SC_entire_game))
- IXScenes::index_from_scene(OUT, sc, 0, START_OF_PLAY_END, NULL, sorted, nr);
- }
- for (int i=0; iends[0].anchor_condition) && (sc != SC_entire_game))
- IXScenes::index_from_scene(OUT, sc, 0, START_OF_PLAY_END, NULL, sorted, nr);
- }
- for (int i=0; iindexed == FALSE)
- IXScenes::index_from_scene(OUT, sc, 0, NEVER_HAPPENS_END, NULL, sorted, nr);
- }
-
-
-@ =
- HTML_OPEN("p"); WRITE("Legend: ");
- IXScenes::scene_icon_legend(OUT, "WPB", "Begins when play begins");
- WRITE("; ");
- IXScenes::scene_icon_legend(OUT, "WhenC", "can begin whenever some condition holds");
- WRITE("; ");
- IXScenes::scene_icon_legend(OUT, "Segue", "follows when a previous scene ends");
- WRITE("; ");
- IXScenes::scene_icon_legend(OUT, "Simul", "begins simultaneously");
- WRITE("; ");
- IXScenes::scene_icon_legend(OUT, "WNever", "never begins");
- WRITE("; ");
- IXScenes::scene_icon_legend(OUT, "ENever", "never ends");
- WRITE("; ");
- IXScenes::scene_icon_legend(OUT, "Recurring", "recurring (can happen more than once)");
- WRITE(". Scene names are italicised when and if they appear for a second "
- "or subsequent time because the scene can begin in more than one way.");
- HTML_CLOSE("p");
-
-
-@ =
- Index::anchor(OUT, I"SDETAILS");
- for (int i=0; i;
- }
-
-@ The curious condition about end 1 here is to avoid printing "Ends: Never"
-in cases where fancier ends for the scene exist, so that the scene can, in
-fact, end.
-
-@ =
- @;
- if (sc == SC_entire_game) @;
-
- for (int end=0; endno_ends; end++) {
- if ((end == 1) && (sc->no_ends > 2) &&
- (sc->ends[1].anchor_condition==NULL) && (sc->ends[1].anchor_connectors==NULL))
- continue;
- @;
- @;
- if (end == 0) @;
- }
-
-@ =
- HTML::open_indented_p(OUT, 1, "hanging");
- Index::anchor_numbered(OUT, sc->allocation_id);
- WRITE("The %+W scene", Scenes::get_name(sc));
- Index::link(OUT, Wordings::first_wn(Node::get_text(Instances::get_creating_sentence(sc->as_instance))));
- if (PropertyInferences::either_or_state(
- Instances::as_subject(sc->as_instance), P_recurring) > 0)
- WRITE(" recurring");
- HTML_CLOSE("p");
-
-@ =
- HTML::open_indented_p(OUT, 1, "tight");
- WRITE("The Entire Game scene is built-in. It is going on whenever play is "
- "going on. (It is recurring so that if the story ends, but then resumes, "
- "it too will end but then begin again.)");
- HTML_CLOSE("p");
-
-@ =
- int rbc = 0;
- rulebook *rb;
- LOOP_OVER(rb, rulebook) {
- if (Rulebooks::is_contextually_empty(rb, IXRules::scene_context(sc)) == FALSE) {
- if (rbc++ == 0) {
- HTML::open_indented_p(OUT, 1, "hanging");
- WRITE("During this scene:");
- HTML_CLOSE("p");
- }
- HTML::open_indented_p(OUT, 2, "hanging");
- WRITE("%+W", rb->primary_name); HTML_CLOSE("p");
- int ignore_me = 0;
- IXRules::index_rulebook(OUT, rb, "", IXRules::scene_context(sc), &ignore_me);
- }
- }
-
-@ =
- HTML::open_indented_p(OUT, 1, "hanging");
- WRITE("%s ", (end==0)?"Begins":"Ends");
- if (end >= 2) WRITE("%+W ", sc->ends[end].end_names);
- WRITE("when: ");
- int count = 0;
- @;
- @;
- @;
- if (count == 0) WRITE("never");
- HTML_CLOSE("p");
-
-@ =
- if ((end==0) && (sc->start_of_play)) {
- if (count > 0) {
- HTML_TAG("br");
- WRITE("or when: ");
- }
- WRITE("play begins");
- count++;
- }
-
-@ =
- if (sc->ends[end].anchor_condition) {
- if (count > 0) {
- HTML_TAG("br");
- WRITE("or when: ");
- }
- WRITE("%+W", Node::get_text(sc->ends[end].anchor_condition));
- Index::link(OUT, Wordings::first_wn(Node::get_text(sc->ends[end].anchor_condition_set)));
- count++;
- }
-
-@ =
- for (scene_connector *scon = sc->ends[end].anchor_connectors; scon; scon=scon->next) {
- if (count > 0) {
- HTML_TAG("br");
- WRITE("or when: ");
- }
- wording NW = Instances::get_name(scon->connect_to->as_instance, FALSE);
- WRITE("%+W%s", NW, (scon->end==0)?"begins":"ends");
- if (scon->end >= 2) WRITE(" %+W", scon->connect_to->ends[scon->end].end_names);
- Index::link(OUT, Wordings::first_wn(Node::get_text(scon->where_said)));
- count++;
- }
-
-@ =
- if (Rulebooks::is_empty(sc->ends[end].end_rulebook) == FALSE) {
- HTML::open_indented_p(OUT, 1, "hanging");
- WRITE("What happens:"); HTML_CLOSE("p");
- int ignore_me = 0;
- IXRules::index_rulebook(OUT, sc->ends[end].end_rulebook, "",
- IXRules::no_rule_context(), &ignore_me);
- }
-
-@h Table of Scenes.
-We finally return to the table of scenes. The following is recursive, and
-is called at the top level for each scene in turn which starts at the start
-of play (see above).
-
-A scene entry can be arrived at in three ways: through one of its ends, in
-which case |end| is the number (0 for begins, 1 for standard ends, and so on),
-or through being already active at the start of play, or through being covered
-in the index even though it never happens in play. This means we need two
-additional |end| numbers. They are only ever used at the top level, that is,
-on the initial call when |depth| is 0.
-
-@d START_OF_PLAY_END -1
-@d NEVER_HAPPENS_END -2
-
-=
-void IXScenes::index_from_scene(OUTPUT_STREAM, scene *sc, int depth,
- int end, scene *sc_from, scene **sorted, int nr) {
- HTML::open_indented_p(OUT, depth+1, "tight");
- @;
- @;
- if (sc->indexed == FALSE) {
- @;
- @;
- }
- HTML_CLOSE("p");
- if (sc->indexed) return;
- sc->indexed = TRUE;
- @;
-}
-
-@ =
- switch(end) {
- case 0: IXScenes::scene_icon(OUT, "Simul"); break;
- case 1: IXScenes::scene_icon(OUT, "Segue"); break;
- case START_OF_PLAY_END: break;
- case NEVER_HAPPENS_END: IXScenes::scene_icon(OUT, "WNever"); break;
- default:
- IXScenes::scene_icon(OUT, "Segue");
- WRITE("[ends %+W] ", sc_from->ends[end].end_names); break;
- }
- if ((sc->indexed == FALSE) || (depth == 0)) {
- if (sc == SC_entire_game) IXScenes::scene_icon(OUT, "WPB");
- else if (sc->ends[0].anchor_condition) IXScenes::scene_icon(OUT, "WhenC");
- if (sc->start_of_play) IXScenes::scene_icon(OUT, "WPB");
- }
-
-@ =
- if (sc->indexed) WRITE("");
- WRITE("%+W", Instances::get_name(sc->as_instance, FALSE));
- if (sc->indexed) WRITE("");
- else Index::below_link_numbered(OUT, sc->allocation_id);
-
-@ =
- int ways_to_end = 0;
- for (int e=1; eno_ends; e++) {
- if (sc->ends[e].anchor_connectors) ways_to_end++;
- if (sc->ends[e].anchor_condition) ways_to_end++;
- }
- if (ways_to_end == 0) IXScenes::scene_icon_append(OUT, "ENever");
-
-@ =
- inference_subject *subj = Instances::as_subject(sc->as_instance);
- if (PropertyInferences::either_or_state(subj, P_recurring) > UNKNOWN_CE)
- IXScenes::scene_icon_append(OUT, "Recurring");
-
-@ And this is where the routine recurses, so that consequent scenes are
-tabulated underneath the present one, indented one step further in (since
-indentation is coupled to |depth|). First we recurse to scenes which end when
-this one does; then to scenes which begin when this one ends.
-
-@ =
- for (int i=0; iends[0].anchor_connectors; scon; scon=scon->next)
- if ((scon->connect_to == sc) && (scon->end >= 1))
- IXScenes::index_from_scene(OUT, sc2, depth + 1, scon->end, sc, sorted, nr);
- }
- for (int i=0; iends[0].anchor_connectors; scon; scon=scon->next)
- if ((scon->connect_to == sc) && (scon->end == 0))
- IXScenes::index_from_scene(OUT, sc2, depth, scon->end, sc, sorted, nr);
- }
-
-@ We have been using:
-
-=
-void IXScenes::scene_icon(OUTPUT_STREAM, char *si) {
- IXScenes::scene_icon_unspaced(OUT, si); WRITE(" ");
-}
-
-void IXScenes::scene_icon_append(OUTPUT_STREAM, char *si) {
- WRITE(" "); IXScenes::scene_icon_unspaced(OUT, si);
-}
-
-void IXScenes::scene_icon_legend(OUTPUT_STREAM, char *si, char *gloss) {
- IXScenes::scene_icon_unspaced(OUT, si); WRITE(" %s", gloss);
-}
-
-void IXScenes::scene_icon_unspaced(OUTPUT_STREAM, char *si) {
- HTML_TAG_WITH("img", "border=0 src=inform:/scene_icons/%s.png", si);
-}
-
-@ Lastly: the following is the criterion used for sorting the scenes into
-their indexing order. The Entire Game always comes first, and then come the
-rest in ascending alphabetical order.
-
-=
-int IXScenes::compare_scenes(const void *ent1, const void *ent2) {
- const scene *sc1 = *((const scene **) ent1);
- const scene *sc2 = *((const scene **) ent2);
- if ((sc1 == SC_entire_game) && (sc2 != SC_entire_game)) return -1;
- if ((sc1 != SC_entire_game) && (sc2 == SC_entire_game)) return 1;
- wording SW1 = Instances::get_name(sc1->as_instance, FALSE);
- wording SW2 = Instances::get_name(sc2->as_instance, FALSE);
- return Wordings::strcmp(SW1, SW2);
-}
diff --git a/inform7/index-module/Contents.w b/inform7/index-module/Contents.w
index 114f4c835..8c44d4b84 100644
--- a/inform7/index-module/Contents.w
+++ b/inform7/index-module/Contents.w
@@ -26,7 +26,6 @@ Chapter 3: Indexing for Plugins
Backdrops
Regions
The Map
- Plot Element
Actions
Commands Index
diff --git a/inform7/runtime-module/Chapter 2/Hierarchy.w b/inform7/runtime-module/Chapter 2/Hierarchy.w
index 225f7a933..6434d65b1 100644
--- a/inform7/runtime-module/Chapter 2/Hierarchy.w
+++ b/inform7/runtime-module/Chapter 2/Hierarchy.w
@@ -820,6 +820,11 @@ void Hierarchy::establish(void) {
@e INSTANCE_INDEX_KIND_MD_HL
@e INSTANCE_IS_OBJECT_MD_HL
@e INSTANCE_IS_SCENE_MD_HL
+@e INSTANCE_IS_ENTIRE_GAME_MD_HL
+@e INSTANCE_SCENE_STARTS_MD_HL
+@e INSTANCE_SCENE_STARTS_ON_CONDITION_MD_HL
+@e INSTANCE_SCENE_RECURS_MD_HL
+@e INSTANCE_SCENE_NEVER_ENDS_MD_HL
@e INSTANCE_IS_EXF_MD_HL
@e INSTANCE_FILE_VALUE_MD_HL
@e INSTANCE_FILE_IS_BINARY_MD_HL
@@ -835,6 +840,15 @@ void Hierarchy::establish(void) {
@e INSTANCE_SOUND_ID_MD_HL
@e INSTANCE_SSF_MD_HL
@e INSTANCE_SCF_MD_HL
+@e SCENE_ENDS_HAP
+@e SCENE_END_NAME_MD_HL
+@e SCENE_END_AT_MD_HL
+@e SCENE_END_CONDITION_MD_HL
+@e SCENE_END_RULEBOOK_MD_HL
+@e SCENE_CONNECTORS_HAP
+@e SCENE_CONNECTOR_TO_MD_HL
+@e SCENE_CONNECTOR_END_MD_HL
+@e SCENE_CONNECTOR_AT_MD_HL
@e INST_SHOWME_MD_HL
@e INST_SHOWME_FN_HL
@e INSTANCE_HL
@@ -862,8 +876,24 @@ void Hierarchy::establish(void) {
H_C_U(INSTANCE_INDEX_KIND_MD_HL, I"^index_kind")
H_C_U(INSTANCE_IS_OBJECT_MD_HL, I"^is_object")
H_C_U(INSTANCE_IS_SCENE_MD_HL, I"^is_scene")
+ H_C_U(INSTANCE_IS_ENTIRE_GAME_MD_HL, I"^is_entire_game")
+ H_C_U(INSTANCE_SCENE_STARTS_MD_HL, I"^starts")
+ H_C_U(INSTANCE_SCENE_STARTS_ON_CONDITION_MD_HL, I"^starts_on_condition")
+ H_C_U(INSTANCE_SCENE_RECURS_MD_HL, I"^recurs")
+ H_C_U(INSTANCE_SCENE_NEVER_ENDS_MD_HL, I"^never_ends")
H_C_U(INSTANCE_SSF_MD_HL, I"^scene_status_fn")
H_C_U(INSTANCE_SCF_MD_HL, I"^scene_change_fn")
+ H_BEGIN_AP(SCENE_ENDS_HAP, I"scene_end", I"_scene_end")
+ H_C_U(SCENE_END_NAME_MD_HL, I"^name")
+ H_C_U(SCENE_END_AT_MD_HL, I"^at")
+ H_C_U(SCENE_END_CONDITION_MD_HL, I"^condition")
+ H_C_U(SCENE_END_RULEBOOK_MD_HL, I"^rulebook")
+ H_BEGIN_AP(SCENE_CONNECTORS_HAP, I"scene_connector", I"_scene_connector")
+ H_C_U(SCENE_CONNECTOR_TO_MD_HL, I"^to")
+ H_C_U(SCENE_CONNECTOR_END_MD_HL, I"^end")
+ H_C_U(SCENE_CONNECTOR_AT_MD_HL, I"^at")
+ H_END
+ H_END
H_C_U(INSTANCE_IS_EXF_MD_HL, I"^is_file")
H_C_U(INSTANCE_FILE_VALUE_MD_HL, I"^file_value")
H_C_U(INSTANCE_FILE_OWNED_MD_HL, I"^file_owned")
diff --git a/inform7/runtime-module/Chapter 5/Instances.w b/inform7/runtime-module/Chapter 5/Instances.w
index e4173b36c..d725d7fbc 100644
--- a/inform7/runtime-module/Chapter 5/Instances.w
+++ b/inform7/runtime-module/Chapter 5/Instances.w
@@ -87,9 +87,6 @@ void RTInstances::compilation_agent(compilation_subtask *t) {
if (Kinds::Behaviour::is_subkind_of_object(K))
Hierarchy::apply_metadata_from_number(pack,
INSTANCE_IS_OBJECT_MD_HL, 1);
- if ((K_scene) && (Kinds::eq(K, K_scene)))
- Hierarchy::apply_metadata_from_number(pack,
- INSTANCE_IS_SCENE_MD_HL, 1);
if ((K_sound_name) && (Kinds::eq(K, K_sound_name)))
Hierarchy::apply_metadata_from_number(pack,
INSTANCE_IS_SOUND_MD_HL, 1);
diff --git a/inform7/runtime-module/Chapter 5/Rulebooks.w b/inform7/runtime-module/Chapter 5/Rulebooks.w
index a22ac7e2f..21c1da8d6 100644
--- a/inform7/runtime-module/Chapter 5/Rulebooks.w
+++ b/inform7/runtime-module/Chapter 5/Rulebooks.w
@@ -149,7 +149,7 @@ void RTRulebooks::compilation_agent(compilation_subtask *t) {
Hierarchy::apply_metadata_from_raw_wording(EP, RULE_INDEX_NAME_MD_HL,
R->indexing_data.italicised_text);
if (R->defn_as_I7_source) {
- parse_node *pn = R->defn_as_I7_source->at->down;
+ parse_node *pn = R->defn_as_I7_source->at->down->down;
if ((pn) && (Wordings::nonempty(Node::get_text(pn)))) {
TEMPORARY_TEXT(OUT)
WRITE("%+W", Node::get_text(pn));
diff --git a/inform7/runtime-module/Chapter 5/Scene Instances.w b/inform7/runtime-module/Chapter 5/Scene Instances.w
index 3433ac1cd..2bd01ff2b 100644
--- a/inform7/runtime-module/Chapter 5/Scene Instances.w
+++ b/inform7/runtime-module/Chapter 5/Scene Instances.w
@@ -10,13 +10,50 @@ the current |location| or not.
void RTScenes::compile_extra(instance *I) {
if ((K_scene) && (Instances::of_kind(I, K_scene))) {
scene *sc = Scenes::from_named_constant(I);
- if (sc == NULL) internal_error("sceneless");
+ package_request *pack = RTInstances::package(I);
+ Hierarchy::apply_metadata_from_number(pack, INSTANCE_IS_SCENE_MD_HL, 1);
+ if (Scenes::is_entire_game(I))
+ Hierarchy::apply_metadata_from_number(pack,
+ INSTANCE_IS_ENTIRE_GAME_MD_HL, 1);
+ if (sc->start_of_play)
+ Hierarchy::apply_metadata_from_number(pack,
+ INSTANCE_SCENE_STARTS_MD_HL, 1);
+ else if (sc->ends[0].anchor_condition)
+ Hierarchy::apply_metadata_from_number(pack,
+ INSTANCE_SCENE_STARTS_ON_CONDITION_MD_HL, 1);
+ inference_subject *subj = Instances::as_subject(sc->as_instance);
+ if (PropertyInferences::either_or_state(subj, P_recurring) > UNKNOWN_CE)
+ Hierarchy::apply_metadata_from_number(pack,
+ INSTANCE_SCENE_RECURS_MD_HL, 1);
+ int ways_to_end = 0;
+ for (int e=1; eno_ends; e++) {
+ if (sc->ends[e].anchor_connectors) ways_to_end++;
+ if (sc->ends[e].anchor_condition) ways_to_end++;
+ }
+ if (ways_to_end == 0)
+ Hierarchy::apply_metadata_from_number(pack,
+ INSTANCE_SCENE_NEVER_ENDS_MD_HL, 1);
+
text_stream *desc = Str::new();
WRITE_TO(desc, "scene change fn for "); Instances::write(desc, I);
Sequence::queue(&RTScenes::change_compilation_agent, STORE_POINTER_scene(sc), desc);
text_stream *desc2 = Str::new();
WRITE_TO(desc2, "scene status fn for "); Instances::write(desc, I);
Sequence::queue(&RTScenes::status_compilation_agent, STORE_POINTER_scene(sc), desc2);
+
+ for (int e=0; eno_ends; e++) {
+ package_request *EP = Hierarchy::package_within(SCENE_ENDS_HAP, pack);
+ Hierarchy::apply_metadata_from_raw_wording(EP, SCENE_END_NAME_MD_HL, sc->ends[e].end_names);
+ Hierarchy::apply_metadata_from_number(EP, SCENE_END_AT_MD_HL, (inter_ti) Wordings::first_wn(Node::get_text(sc->ends[e].anchor_condition_set)));
+ Hierarchy::apply_metadata_from_raw_wording(EP, SCENE_END_CONDITION_MD_HL, Node::get_text(sc->ends[e].anchor_condition));
+ Hierarchy::apply_metadata_from_iname(EP, SCENE_END_RULEBOOK_MD_HL, RTRulebooks::id_iname(sc->ends[e].end_rulebook));
+ for (scene_connector *scon = sc->ends[e].anchor_connectors; scon; scon=scon->next) {
+ package_request *CP = Hierarchy::package_within(SCENE_CONNECTORS_HAP, EP);
+ Hierarchy::apply_metadata_from_iname(CP, SCENE_CONNECTOR_TO_MD_HL, RTInstances::value_iname(scon->connect_to->as_instance));
+ Hierarchy::apply_metadata_from_number(CP, SCENE_CONNECTOR_END_MD_HL, (inter_ti) scon->end);
+ Hierarchy::apply_metadata_from_number(CP, SCENE_CONNECTOR_AT_MD_HL, (inter_ti) Wordings::first_wn(Node::get_text(scon->where_said)));
+ }
+ }
}
}
diff --git a/inter/codegen-module/Chapter 1/Codegen Module.w b/inter/codegen-module/Chapter 1/Codegen Module.w
index 7e565ef0c..a0803b712 100644
--- a/inter/codegen-module/Chapter 1/Codegen Module.w
+++ b/inter/codegen-module/Chapter 1/Codegen Module.w
@@ -27,6 +27,9 @@ which use this module:
@e index_page_CLASS
@e index_element_CLASS
@e index_tlexicon_entry_CLASS
+@e simplified_scene_CLASS
+@e simplified_end_CLASS
+@e simplified_connector_CLASS
=
DECLARE_CLASS(I6T_intervention)
@@ -46,6 +49,9 @@ DECLARE_CLASS(tree_inventory_item)
DECLARE_CLASS(index_element)
DECLARE_CLASS(index_page)
DECLARE_CLASS(index_tlexicon_entry)
+DECLARE_CLASS(simplified_scene)
+DECLARE_CLASS(simplified_end)
+DECLARE_CLASS(simplified_connector)
@ Like all modules, this one must define a |start| and |end| function:
@@ -62,9 +68,11 @@ void CodegenModule::end(void) {
@
@e CODE_GENERATION_MREASON
+@e SCENE_SORTING_MREASON
@ =
Memory::reason_name(CODE_GENERATION_MREASON, "code generation workspace for objects");
+ Memory::reason_name(SCENE_SORTING_MREASON, "scene index sorting");
@ =
;
diff --git a/inter/codegen-module/Chapter 6/Index File Services.w b/inter/codegen-module/Chapter 6/Index File Services.w
index a84375018..1834efcde 100644
--- a/inter/codegen-module/Chapter 6/Index File Services.w
+++ b/inter/codegen-module/Chapter 6/Index File Services.w
@@ -660,12 +660,9 @@ void Index::index_actual_element(OUTPUT_STREAM, text_stream *elt) {
if (Str::eq_wide_string(elt, L"Vb")) { VerbsElement::render(OUT); return; }
if (Str::eq_wide_string(elt, L"Vl")) { ValuesElement::render(OUT); return; }
if (Str::eq_wide_string(elt, L"Xt")) { ExtrasElement::render(OUT); return; }
+ if (Str::eq_wide_string(elt, L"Pl")) { PlotElement::render(OUT); return; }
#ifdef CORE_MODULE
- if (Str::eq_wide_string(elt, L"Pl")) {
- IXScenes::render(OUT);
- return;
- }
if (Str::eq_wide_string(elt, L"Mp")) {
IXPhysicalWorld::render(OUT);
return;
diff --git a/inter/codegen-module/Chapter 6/Index Rules.w b/inter/codegen-module/Chapter 6/Index Rules.w
index d4ba283ab..00990f2f9 100644
--- a/inter/codegen-module/Chapter 6/Index Rules.w
+++ b/inter/codegen-module/Chapter 6/Index Rules.w
@@ -25,7 +25,7 @@ inter_package *IndexRules::find_activity(tree_inventory *inv, text_stream *marke
typedef struct ix_rule_context {
struct inter_package *action_context;
- struct inter_symbol *scene_context;
+ struct simplified_scene *scene_context;
} ix_rule_context;
ix_rule_context IndexRules::action_context(inter_package *an) {
@@ -34,7 +34,7 @@ ix_rule_context IndexRules::action_context(inter_package *an) {
rc.scene_context = NULL;
return rc;
}
-ix_rule_context IndexRules::scene_context(inter_symbol *s) {
+ix_rule_context IndexRules::scene_context(simplified_scene *s) {
ix_rule_context rc;
rc.action_context = NULL;
rc.scene_context = s;
@@ -58,7 +58,8 @@ int IndexRules::phrase_fits_rule_context(inter_package *entry, ix_rule_context r
}
if (rc.scene_context) {
inter_symbol *scene_symbol = Metadata::read_optional_symbol(entry, I"^during");
- if (scene_symbol != rc.scene_context) return FALSE;
+ if (scene_symbol == NULL) return FALSE;
+ if (Inter::Packages::container(scene_symbol->definition) != rc.scene_context->pack) return FALSE;
}
return TRUE;
}
@@ -270,10 +271,8 @@ int IndexRules::index_rule(OUTPUT_STREAM, inter_tree *I, inter_package *R, inter
@ =
WRITE("%S", italicised_text);
- if (rc.scene_context) {
- inter_package *scene_pack = Inter::Packages::container(rc.scene_context->definition);
- WRITE(" during %S", Metadata::read_optional_textual(scene_pack, I"^name"));
- }
+ if (rc.scene_context)
+ WRITE(" during %S", PlotElement::scene_name(rc.scene_context));
WRITE(" ");
@
diff --git a/inter/codegen-module/Chapter 6/Plot Element.w b/inter/codegen-module/Chapter 6/Plot Element.w
new file mode 100644
index 000000000..4ff3b4641
--- /dev/null
+++ b/inter/codegen-module/Chapter 6/Plot Element.w
@@ -0,0 +1,445 @@
+[PlotElement::] Plot Element.
+
+To write the Plot element (Pl) in the index.
+
+@ The mapping of time is on the one hand simpler than the mapping of space
+since there is only one dimension, but on the other hand more complex since
+scenes can be multiply present at the same instant of time (whereas rooms
+cannot be multiply present at the same point in space). We resolve this
+with a notation which takes a little bit of on-screen explanation, but
+seems natural enough to learn in practice.
+
+@d MAX_SCENE_ENDS 32 /* this must exceed 31 */
+
+=
+typedef struct simplified_scene {
+ struct inter_package *pack;
+ int no_ends;
+ struct simplified_end *ends[MAX_SCENE_ENDS];
+ int indexed_already;
+ CLASS_DEFINITION
+} simplified_scene;
+
+typedef struct simplified_end {
+ struct inter_package *end_pack;
+ struct simplified_connector *anchor_connectors; /* linked list */
+ CLASS_DEFINITION
+} simplified_end;
+
+typedef struct simplified_connector {
+ struct inter_package *con_pack;
+ struct simplified_scene *connect_to;
+ struct simplified_connector *next; /* next in list of connectors for a scene end */
+ CLASS_DEFINITION
+} simplified_connector;
+
+simplified_scene *PlotElement::simplified(inter_tree *I, inter_package *sc_pack) {
+ simplified_scene *ssc = CREATE(simplified_scene);
+ ssc->pack = sc_pack;
+ ssc->no_ends = 0;
+ ssc->indexed_already = FALSE;
+ inter_symbol *wanted = PackageTypes::get(I, I"_scene_end");
+ inter_symbol *wanted_within = PackageTypes::get(I, I"_scene_connector");
+ inter_tree_node *D = Inter::Packages::definition(sc_pack);
+ LOOP_THROUGH_INTER_CHILDREN(C, D) {
+ if (C->W.data[ID_IFLD] == PACKAGE_IST) {
+ inter_package *entry = Inter::Package::defined_by_frame(C);
+ if (Inter::Packages::type(entry) == wanted) {
+ simplified_end *se = CREATE(simplified_end);
+ se->end_pack = entry;
+ se->anchor_connectors = NULL;
+ LOOP_THROUGH_INTER_CHILDREN(B, C) {
+ if (B->W.data[ID_IFLD] == PACKAGE_IST) {
+ inter_package *inner_entry = Inter::Package::defined_by_frame(B);
+ if (Inter::Packages::type(inner_entry) == wanted_within) {
+ simplified_connector *scon = CREATE(simplified_connector);
+ scon->con_pack = inner_entry;
+ scon->next = NULL;
+ if (se->anchor_connectors == NULL) {
+ se->anchor_connectors = scon;
+ } else {
+ simplified_connector *last = se->anchor_connectors;
+ while ((last) && (last->next)) last = last->next;
+ last->next = scon;
+ }
+ scon->connect_to = NULL;
+ }
+ }
+ }
+ if (ssc->no_ends >= MAX_SCENE_ENDS) internal_error("too many scene ends");
+ ssc->ends[ssc->no_ends++] = se;
+ }
+ }
+ }
+ return ssc;
+}
+
+int PlotElement::is_entire_game(simplified_scene *ssc) {
+ if (Metadata::read_optional_numeric(ssc->pack, I"^is_entire_game")) return TRUE;
+ return FALSE;
+}
+
+int PlotElement::recurs(simplified_scene *ssc) {
+ if (Metadata::read_optional_numeric(ssc->pack, I"^recurs")) return TRUE;
+ return FALSE;
+}
+
+int PlotElement::never_ends(simplified_scene *ssc) {
+ if (Metadata::read_optional_numeric(ssc->pack, I"^never_ends")) return TRUE;
+ return FALSE;
+}
+
+int PlotElement::starts_at_start_of_play(simplified_scene *ssc) {
+ if (Metadata::read_optional_numeric(ssc->pack, I"^starts")) return TRUE;
+ return FALSE;
+}
+
+int PlotElement::starts_on_condition(simplified_scene *ssc) {
+ if (Metadata::read_optional_numeric(ssc->pack, I"^starts_on_condition")) return TRUE;
+ return FALSE;
+}
+
+int PlotElement::no_ends(simplified_scene *ssc) {
+ return ssc->no_ends;
+}
+
+text_stream *PlotElement::scene_name(simplified_scene *ssc) {
+ return Metadata::read_textual(ssc->pack, I"^name");
+}
+
+text_stream *PlotElement::end_name(simplified_end *se) {
+ return Metadata::read_textual(se->end_pack, I"^name");
+}
+
+text_stream *PlotElement::anchor_condition(simplified_end *se) {
+ return Metadata::read_textual(se->end_pack, I"^condition");
+}
+
+int PlotElement::has_anchor_condition(simplified_end *se) {
+ if (Str::len(PlotElement::anchor_condition(se)) > 0) return TRUE;
+ return FALSE;
+}
+
+int PlotElement::anchor_condition_set_at(simplified_end *se) {
+ return (int) Metadata::read_optional_numeric(se->end_pack, I"^at");
+}
+
+inter_symbol *PlotElement::end_rulebook(simplified_end *se) {
+ return Metadata::read_optional_symbol(se->end_pack, I"^rulebook");
+}
+
+simplified_scene *PlotElement::connects_to(simplified_connector *scon) {
+ if (scon->connect_to) return scon->connect_to;
+ inter_symbol *sc_symbol = Metadata::read_optional_symbol(scon->con_pack, I"^to");
+ if (sc_symbol) {
+ inter_package *to_pack = Inter::Packages::container(sc_symbol->definition);
+ simplified_scene *ssc;
+ LOOP_OVER(ssc, simplified_scene)
+ if (ssc->pack == to_pack) {
+ scon->connect_to = ssc;
+ return ssc;
+ }
+ }
+ internal_error("scene metadata broken: bad connector");
+ return NULL;
+}
+
+int PlotElement::scon_end(simplified_connector *scon) {
+ return (int) Metadata::read_numeric(scon->con_pack, I"^end");
+}
+
+int PlotElement::scon_at(simplified_connector *scon) {
+ return (int) Metadata::read_numeric(scon->con_pack, I"^at");
+}
+
+void PlotElement::render(OUTPUT_STREAM) {
+ inter_tree *I = Index::get_tree();
+ tree_inventory *inv = Synoptic::inv(I);
+ TreeLists::sort(inv->scene_nodes, PlotElement::scene_order);
+ TreeLists::sort(inv->rulebook_nodes, Synoptic::module_order);
+
+ int no_scenes = TreeLists::len(inv->scene_nodes);
+ simplified_scene **plot = Memory::calloc(no_scenes, sizeof(simplified_scene *), SCENE_SORTING_MREASON);
+ for (int i=0; iscene_nodes->list[i].node));
+
+ @;
+ @;
+ @;
+ Memory::I7_array_free(plot, SCENE_SORTING_MREASON, no_scenes, sizeof(simplified_scene *));
+}
+
+@ The sorted ordering is used as-is later on, when we get to the details, but
+for the tabulation it's refined further. First we have the start-of-play
+scenes, in sorted order; then scenes with a condition for their beginning
+(end 0), in sorted order; then scenes that don't, and which haven't been
+covered as a result of one of the earlier ones, also in sorted order. (This
+third category is usually empty except for scenes the author has forgotten
+about and created but never made use of.)
+
+@ =
+ simplified_scene *ssc;
+ LOOP_OVER(ssc, simplified_scene)
+ if ((PlotElement::starts_at_start_of_play(ssc)) || (PlotElement::is_entire_game(ssc)))
+ PlotElement::index_from_scene(OUT, plot, ssc, 0, START_OF_PLAY_END, NULL);
+ LOOP_OVER(ssc, simplified_scene)
+ if ((PlotElement::starts_on_condition(ssc)) && (PlotElement::is_entire_game(ssc) == FALSE))
+ PlotElement::index_from_scene(OUT, plot, ssc, 0, START_OF_PLAY_END, NULL);
+ LOOP_OVER(ssc, simplified_scene)
+ if (ssc->indexed_already == FALSE)
+ PlotElement::index_from_scene(OUT, plot, ssc, 0, NEVER_HAPPENS_END, NULL);
+
+@ =
+ HTML_OPEN("p"); WRITE("Legend: ");
+ PlotElement::scene_icon_legend(OUT, "WPB", "Begins when play begins");
+ WRITE("; ");
+ PlotElement::scene_icon_legend(OUT, "WhenC", "can begin whenever some condition holds");
+ WRITE("; ");
+ PlotElement::scene_icon_legend(OUT, "Segue", "follows when a previous scene ends");
+ WRITE("; ");
+ PlotElement::scene_icon_legend(OUT, "Simul", "begins simultaneously");
+ WRITE("; ");
+ PlotElement::scene_icon_legend(OUT, "WNever", "never begins");
+ WRITE("; ");
+ PlotElement::scene_icon_legend(OUT, "ENever", "never ends");
+ WRITE("; ");
+ PlotElement::scene_icon_legend(OUT, "Recurring", "recurring (can happen more than once)");
+ WRITE(". Scene names are italicised when and if they appear for a second "
+ "or subsequent time because the scene can begin in more than one way.");
+ HTML_CLOSE("p");
+
+
+@ =
+ Index::anchor(OUT, I"SDETAILS");
+ simplified_scene *ssc;
+ LOOP_OVER(ssc, simplified_scene) {
+ HTML_TAG("hr");
+ @;
+ }
+
+@ The curious condition about end 1 here is to avoid printing "Ends: Never"
+in cases where fancier ends for the scene exist, so that the scene can, in
+fact, end.
+
+@ =
+ @;
+ if (PlotElement::is_entire_game(ssc)) @;
+
+ for (int end=0; end 2) &&
+ (PlotElement::has_anchor_condition(ssc->ends[1]) == FALSE) &&
+ (ssc->ends[1]->anchor_connectors==NULL))
+ continue;
+ @;
+ @;
+ if (end == 0) @;
+ }
+
+@ =
+ HTML::open_indented_p(OUT, 1, "hanging");
+ Index::anchor_numbered(OUT, ssc->allocation_id);
+ WRITE("The %S scene", Metadata::read_textual(ssc->pack, I"^name"));
+ int at = (int) Metadata::read_optional_numeric(ssc->pack, I"^at");
+ if (at > 0) Index::link(OUT, at);
+ if (PlotElement::recurs(ssc)) WRITE(" recurring");
+ HTML_CLOSE("p");
+
+@ =
+ HTML::open_indented_p(OUT, 1, "tight");
+ WRITE("The Entire Game scene is built-in. It is going on whenever play is "
+ "going on. (It is recurring so that if the story ends, but then resumes, "
+ "it too will end but then begin again.)");
+ HTML_CLOSE("p");
+
+@ =
+ int rbc = 0;
+ for (int i=0; irulebook_nodes); i++) {
+ inter_package *pack = Inter::Package::defined_by_frame(inv->rulebook_nodes->list[i].node);
+ if (IndexRules::is_contextually_empty(I, pack, IndexRules::scene_context(ssc)) == FALSE) {
+ if (rbc++ == 0) {
+ HTML::open_indented_p(OUT, 1, "hanging");
+ WRITE("During this scene:");
+ HTML_CLOSE("p");
+ }
+ HTML::open_indented_p(OUT, 2, "hanging");
+ WRITE("%S", Metadata::read_textual(pack, I"^printed_name")); HTML_CLOSE("p");
+ int ignore_me = 0;
+ IndexRules::index_rulebook(OUT, I, pack, I"", IndexRules::scene_context(ssc), &ignore_me);
+ }
+ }
+
+@ =
+ HTML::open_indented_p(OUT, 1, "hanging");
+ WRITE("%s ", (end==0)?"Begins":"Ends");
+ if (end >= 2) WRITE("%S ", PlotElement::end_name(ssc->ends[end]));
+ WRITE("when: ");
+ int count = 0;
+ @;
+ @;
+ @;
+ if (count == 0) WRITE("never");
+ HTML_CLOSE("p");
+
+@ =
+ if ((end==0) && (PlotElement::starts_at_start_of_play(ssc))) {
+ if (count > 0) {
+ HTML_TAG("br");
+ WRITE("or when: ");
+ }
+ WRITE("play begins");
+ count++;
+ }
+
+@ =
+ if (PlotElement::has_anchor_condition(ssc->ends[end])) {
+ if (count > 0) {
+ HTML_TAG("br");
+ WRITE("or when: ");
+ }
+ WRITE("%S", PlotElement::anchor_condition(ssc->ends[end]));
+ int at = PlotElement::anchor_condition_set_at(ssc->ends[end]);
+ if (at > 0) Index::link(OUT, at);
+ count++;
+ }
+
+@ =
+ for (simplified_connector *scon = ssc->ends[end]->anchor_connectors; scon; scon=scon->next) {
+ if (count > 0) {
+ HTML_TAG("br");
+ WRITE("or when: ");
+ }
+ simplified_scene *to_ssc = PlotElement::connects_to(scon);
+ text_stream *NW = PlotElement::scene_name(to_ssc);
+ WRITE("%S%s", NW, (PlotElement::scon_end(scon)==0)?"begins":"ends");
+ if (PlotElement::scon_end(scon) >= 2) WRITE(" %S", PlotElement::end_name(to_ssc->ends[PlotElement::scon_end(scon)]));
+ Index::link(OUT, PlotElement::scon_at(scon));
+ count++;
+ }
+
+@ =
+ inter_symbol *rb = PlotElement::end_rulebook(ssc->ends[end]);
+ inter_package *rb_pack = Inter::Packages::container(rb->definition);
+ if (IndexRules::no_rules(I, rb_pack) > 0) {
+ HTML::open_indented_p(OUT, 1, "hanging");
+ WRITE("What happens:"); HTML_CLOSE("p");
+ int ignore_me = 0;
+ IndexRules::index_rulebook(OUT, I, rb_pack, I"", IndexRules::no_rule_context(), &ignore_me);
+ }
+
+@h Table of Scenes.
+We finally return to the table of scenes. The following is recursive, and
+is called at the top level for each scene in turn which starts at the start
+of play (see above).
+
+A scene entry can be arrived at in three ways: through one of its ends, in
+which case |end| is the number (0 for begins, 1 for standard ends, and so on),
+or through being already active at the start of play, or through being covered
+in the index even though it never happens in play. This means we need two
+additional |end| numbers. They are only ever used at the top level, that is,
+on the initial call when |depth| is 0.
+
+@d START_OF_PLAY_END -1
+@d NEVER_HAPPENS_END -2
+
+=
+void PlotElement::index_from_scene(OUTPUT_STREAM, simplified_scene **plot,
+ simplified_scene *ssc, int depth, int end, simplified_scene *sc_from) {
+ HTML::open_indented_p(OUT, depth+1, "tight");
+ @;
+ @;
+ if (ssc->indexed_already == FALSE) {
+ @;
+ @;
+ }
+ HTML_CLOSE("p");
+ if (ssc->indexed_already) return;
+ ssc->indexed_already = TRUE;
+ @;
+}
+
+@ =
+ switch(end) {
+ case 0: PlotElement::scene_icon(OUT, "Simul"); break;
+ case 1: PlotElement::scene_icon(OUT, "Segue"); break;
+ case START_OF_PLAY_END: break;
+ case NEVER_HAPPENS_END: PlotElement::scene_icon(OUT, "WNever"); break;
+ default:
+ PlotElement::scene_icon(OUT, "Segue");
+ WRITE("[ends %S] ", PlotElement::end_name(sc_from->ends[end])); break;
+ }
+ if ((ssc->indexed_already == FALSE) || (depth == 0)) {
+ if (PlotElement::is_entire_game(ssc)) PlotElement::scene_icon(OUT, "WPB");
+ else if (PlotElement::starts_on_condition(ssc)) PlotElement::scene_icon(OUT, "WhenC");
+ if (PlotElement::starts_at_start_of_play(ssc)) PlotElement::scene_icon(OUT, "WPB");
+ }
+
+@ =
+ if (ssc->indexed_already) WRITE("");
+ WRITE("%S", Metadata::read_textual(ssc->pack, I"^name"));
+ if (ssc->indexed_already) WRITE("");
+ else Index::below_link_numbered(OUT, ssc->allocation_id);
+
+@ =
+ if (PlotElement::never_ends(ssc))
+ PlotElement::scene_icon_append(OUT, "ENever");
+
+@ =
+ if (PlotElement::recurs(ssc))
+ PlotElement::scene_icon_append(OUT, "Recurring");
+
+@ And this is where the routine recurses, so that consequent scenes are
+tabulated underneath the present one, indented one step further in (since
+indentation is coupled to |depth|). First we recurse to scenes which end when
+this one does; then to scenes which begin when this one ends.
+
+@ =
+ simplified_scene *ssc2;
+ LOOP_OVER(ssc2, simplified_scene) {
+ for (simplified_connector *scon = ssc2->ends[0]->anchor_connectors; scon; scon=scon->next)
+ if ((PlotElement::connects_to(scon) == ssc) && (PlotElement::scon_end(scon) >= 1))
+ PlotElement::index_from_scene(OUT, plot, ssc2, depth + 1, PlotElement::scon_end(scon), ssc);
+ }
+ LOOP_OVER(ssc2, simplified_scene) {
+ for (simplified_connector *scon = ssc2->ends[0]->anchor_connectors; scon; scon=scon->next)
+ if ((PlotElement::connects_to(scon) == ssc) && (PlotElement::scon_end(scon) == 0))
+ PlotElement::index_from_scene(OUT, plot, ssc2, depth, PlotElement::scon_end(scon), ssc);
+ }
+
+@ We have been using:
+
+=
+void PlotElement::scene_icon(OUTPUT_STREAM, char *si) {
+ PlotElement::scene_icon_unspaced(OUT, si); WRITE(" ");
+}
+
+void PlotElement::scene_icon_append(OUTPUT_STREAM, char *si) {
+ WRITE(" "); PlotElement::scene_icon_unspaced(OUT, si);
+}
+
+void PlotElement::scene_icon_legend(OUTPUT_STREAM, char *si, char *gloss) {
+ PlotElement::scene_icon_unspaced(OUT, si); WRITE(" %s", gloss);
+}
+
+void PlotElement::scene_icon_unspaced(OUTPUT_STREAM, char *si) {
+ HTML_TAG_WITH("img", "border=0 src=inform:/scene_icons/%s.png", si);
+}
+
+@ Lastly: the following is the criterion used for sorting the scenes into
+their indexing order. The Entire Game always comes first, and then come the
+rest in ascending alphabetical order.
+
+=
+int PlotElement::scene_order(const void *ent1, const void *ent2) {
+ itl_entry *E1 = (itl_entry *) ent1;
+ itl_entry *E2 = (itl_entry *) ent2;
+ if (E1 == E2) return 0;
+ inter_tree_node *P1 = E1->node;
+ inter_tree_node *P2 = E2->node;
+ inter_package *sc1 = Inter::Package::defined_by_frame(P1);
+ inter_package *sc2 = Inter::Package::defined_by_frame(P2);
+ if (Metadata::read_optional_numeric(sc1, I"^is_entire_game")) return -1;
+ if (Metadata::read_optional_numeric(sc2, I"^is_entire_game")) return 1;
+ text_stream *SW1 = Metadata::read_textual(sc1, I"^name");
+ text_stream *SW2 = Metadata::read_textual(sc2, I"^name");
+ return Str::cmp(SW1, SW2);
+}
diff --git a/inter/codegen-module/Contents.w b/inter/codegen-module/Contents.w
index 3a73f7012..a1fbaa866 100644
--- a/inter/codegen-module/Contents.w
+++ b/inter/codegen-module/Contents.w
@@ -81,3 +81,4 @@ Chapter 6: Index
Gazetteer Element
Lexicon Element
Arithmetic Element
+ Plot Element