diff --git a/docs/if-module/1-im.html b/docs/if-module/1-im.html index ef4a18a98..73c6e3f32 100644 --- a/docs/if-module/1-im.html +++ b/docs/if-module/1-im.html @@ -169,7 +169,7 @@ nothing except to be a parent to them; it has no activation function. map_plugin = PluginManager::new(&PL::Map::start, I"mapping", ifp); persons_plugin = PluginManager::new(&PL::Persons::start, I"persons", ifp); player_plugin = PluginManager::new(&Player::start, I"player", ifp); - regions_plugin = PluginManager::new(&PL::Regions::start, I"regions", ifp); + regions_plugin = PluginManager::new(&Regions::start, I"regions", ifp); scenes_plugin = PluginManager::new(&PL::Scenes::start, I"scenes", ifp); scoring_plugin = PluginManager::new(&PL::Score::start, I"scoring", ifp); showme_plugin = PluginManager::new(&PL::Showme::start, I"showme", ifp); diff --git a/docs/if-module/3-em.html b/docs/if-module/3-em.html index 432ae083a..ccb40df74 100644 --- a/docs/if-module/3-em.html +++ b/docs/if-module/3-em.html @@ -290,7 +290,7 @@ If all are null, then the global scope is used. if (scope_I) { if (Spatial::object_is_a_room(scope_I)) scope = PL::EPSMap::scope_for_single_room(scope_I); - else if (PL::Regions::object_is_a_region(scope_I)) { + else if (Regions::object_is_a_region(scope_I)) { instance *rm; LOOP_OVER_INSTANCES(rm, K_room) if (PL::EPSMap::obj_in_region(rm, scope_I)) @@ -321,8 +321,8 @@ If all are null, then the global scope is used. int PL::EPSMap::obj_in_region(instance *I, instance *reg) { if ((I == NULL) || (reg == NULL)) return FALSE; - if (PL::Regions::enclosing(I) == reg) return TRUE; - return PL::EPSMap::obj_in_region(PL::Regions::enclosing(I), reg); + if (Regions::enclosing(I) == reg) return TRUE; + return PL::EPSMap::obj_in_region(Regions::enclosing(I), reg); }

§11. String parameters. @@ -872,7 +872,7 @@ the following: break; case INSTANCE_MAP_SCOPE: if ((Spatial::object_is_a_room(<<instance:iscope>>)) || - (PL::Regions::object_is_a_region(<<instance:iscope>>))) + (Regions::object_is_a_region(<<instance:iscope>>))) scope_I = <<instance:iscope>>; if (scope_I) { LOGIF(SPATIAL_MAP, "Setting for object $O\n", scope_I); diff --git a/docs/if-module/3-hm.html b/docs/if-module/3-hm.html index 8bc115ec8..c49f190c0 100644 --- a/docs/if-module/3-hm.html +++ b/docs/if-module/3-hm.html @@ -607,7 +607,7 @@ from each other.) instance *R; LOOP_OVER_ROOMS(R) if (MAP_DATA(R)->world_index_colour == NULL) { - instance *reg = PL::Regions::enclosing(R); + instance *reg = Regions::enclosing(R); if (reg) MAP_DATA(R)->world_index_colour = MAP_DATA(reg)->world_index_colour; else @@ -1284,7 +1284,7 @@ This is the chip shown on the "details" box for a room in the World Index.

-void PL::HTMLMap::colour_chip(OUTPUT_STREAM, instance *I, instance *Reg, parse_node *at) {
+void PL::HTMLMap::colour_chip(OUTPUT_STREAM, instance *I, instance *Reg, parse_node *at) {
     HTML_OPEN_WITH("table",
         "border=\"%d\" cellpadding=\"0\" cellspacing=\"0\" "
         "bordercolor=\"#%s\" height=\"%d\"",
@@ -1319,7 +1319,7 @@ that nothing is shown if all of the rooms are outside of regions.
     int count = 0;
     instance *R;
     LOOP_OVER_ROOMS(R) {
-        if (PL::Regions::enclosing(R) == reg) {
+        if (Regions::enclosing(R) == reg) {
             if (count++ == 0) {
                 Start the region key table for this region13.1;
             } else {
diff --git a/docs/if-module/3-rgn.html b/docs/if-module/3-rgn.html
index 09e286ccc..8c39b9b6d 100644
--- a/docs/if-module/3-rgn.html
+++ b/docs/if-module/3-rgn.html
@@ -73,115 +73,80 @@ function togglePopup(material_id) {
     
 

A plugin providing support for grouping rooms together into named and nestable regions.

-
- -

§1. The relation "R in S" behaves so differently for regions that we need to -define it separately, even though there's no difference in English syntax. So: +

§1. "Region" is in fact one of the four top-level kinds in the standard I7 +world model, alongside thing, room and direction. What makes it complicated +is that it can contain rooms and other regions, but that this form of +containment is implemented differently from spatial containment: as a +result, a new "regional containment" relation is needed.

-binary_predicate *R_regional_containment = NULL;
+void Regions::start(void) {
+    PluginManager::plug(CREATE_INFERENCE_SUBJECTS_PLUG, Regions::create_inference_subjects);
+    PluginManager::plug(NEW_BASE_KIND_NOTIFY_PLUG, Regions::new_base_kind_notify);
+    PluginManager::plug(SET_SUBKIND_NOTIFY_PLUG, Regions::set_subkind_notify);
+    PluginManager::plug(NEW_SUBJECT_NOTIFY_PLUG, Regions::new_subject_notify);
+    PluginManager::plug(NEW_PROPERTY_NOTIFY_PLUG, Regions::new_property_notify);
+    PluginManager::plug(COMPLETE_MODEL_PLUG, Regions::complete_model);
+    PluginManager::plug(MORE_SPECIFIC_PLUG, Regions::more_specific);
+    PluginManager::plug(INTERVENE_IN_ASSERTION_PLUG, Regions::intervene_in_assertion);
+    PluginManager::plug(NAME_TO_EARLY_INFS_PLUG, Regions::name_to_early_infs);
+    PluginManager::plug(ADD_TO_WORLD_INDEX_PLUG, IXRegions::add_to_World_index);
+    PluginManager::plug(PRODUCTION_LINE_PLUG, Regions::production_line);
+}
+
+int Regions::production_line(int stage, int debugging,
+    stopwatch_timer *sequence_timer) {
+    if (stage == INTER1_CSEQ) {
+        BENCH(RTRegions::write_found_in_functions);
+    }
+    return FALSE;
+}
 
-

§2. "Region" is in fact one of the four top-level kinds in the standard I7 -hierarchy, alongside thing, room and direction. +

§2. There is one kind of interest: "region", of course. It is recognised by the English +name in the Standard Rules. (So there is no need to translate this to other languages.)

 kind *K_region = NULL;
 inference_subject *infs_region = NULL;
-property *P_map_region = NULL;  a value property giving the region of a room
-property *P_regional_found_in = NULL;  an I6-only property used for implementation
 
-

§3. Every inference subject contains a pointer to its own unique copy of the -following minimal structure, though it will only be relevant for instances of -"room": -

- -
define REGIONS_DATA(I) PLUGIN_DATA_ON_INSTANCE(regions, I)
-
-
-typedef struct regions_data {
-    struct instance *in_region;  smallest region containing me (rooms only)
-    struct parse_node *in_region_set_at;  where this is decided
-    struct inter_name *in_region_iname;  for testing regional containment found-ins
-    CLASS_DEFINITION
-} regions_data;
-
- -

§4. Initialising.

- -
-void PL::Regions::start(void) {
-    PluginManager::plug(CREATE_INFERENCE_SUBJECTS_PLUG, PL::Regions::create_inference_subjects);
-    PluginManager::plug(NEW_BASE_KIND_NOTIFY_PLUG, PL::Regions::regions_new_base_kind_notify);
-    PluginManager::plug(SET_SUBKIND_NOTIFY_PLUG, PL::Regions::regions_set_subkind_notify);
-    PluginManager::plug(NEW_SUBJECT_NOTIFY_PLUG, PL::Regions::regions_new_subject_notify);
-    PluginManager::plug(NEW_PROPERTY_NOTIFY_PLUG, PL::Regions::regions_new_property_notify);
-    PluginManager::plug(COMPLETE_MODEL_PLUG, PL::Regions::regions_complete_model);
-    PluginManager::plug(MORE_SPECIFIC_PLUG, PL::Regions::regions_more_specific);
-    PluginManager::plug(INTERVENE_IN_ASSERTION_PLUG, PL::Regions::regions_intervene_in_assertion);
-    PluginManager::plug(NAME_TO_EARLY_INFS_PLUG, PL::Regions::regions_name_to_early_infs);
-    PluginManager::plug(ADD_TO_WORLD_INDEX_PLUG, PL::Regions::regions_add_to_World_index);
-    PluginManager::plug(PRODUCTION_LINE_PLUG, PL::Regions::production_line);
-}
-
-int PL::Regions::production_line(int stage, int debugging,
-    stopwatch_timer *sequence_timer) {
-    if (stage == INTER1_CSEQ) {
-        BENCH(PL::Regions::write_regional_found_in_routines);
-    }
-    return FALSE;
-}
-
-int PL::Regions::create_inference_subjects(void) {
-    infs_region = InferenceSubjects::new_fundamental(global_constants, "region(early)");
-    return FALSE;
-}
-
-regions_data *PL::Regions::new_data(inference_subject *subj) {
-    regions_data *rd = CREATE(regions_data);
-    rd->in_region = NULL;
-    rd->in_region_set_at = NULL;
-    rd->in_region_iname = NULL;
-    return rd;
-}
-
-inter_name *PL::Regions::found_in_iname(instance *I) {
-    if (REGIONS_DATA(I)->in_region_iname == NULL)
-        REGIONS_DATA(I)->in_region_iname = Hierarchy::make_iname_in(REGION_FOUND_IN_FN_HL, RTInstances::package(I));
-    return REGIONS_DATA(I)->in_region_iname;
-}
-
-

§5. Kinds. This a kind name to do with regions which Inform provides special support -for; it recognises the English name when defined by the Standard Rules. (So -there is no need to translate this to other languages.) -

+

§3.

 <notable-regions-kinds> ::=
     region
 
-

§6.

+

§4.

-int PL::Regions::regions_new_base_kind_notify(kind *new_base, char *text_stream, wording W) {
+int Regions::new_base_kind_notify(kind *new_base, char *text_stream, wording W) {
     if (<notable-regions-kinds>(W)) {
         K_region = new_base; return TRUE;
     }
     return FALSE;
 }
-
-int PL::Regions::regions_new_subject_notify(inference_subject *subj) {
-    ATTACH_PLUGIN_DATA_TO_SUBJECT(regions, subj, PL::Regions::new_data(subj));
-    return FALSE;
-}
 
-

§7. Region needs to be an abstract object, not a thing or a room, so: +

§5. As with the handling of the main spatial kinds, we need a placeholder for the +"region" subject until K_region is ready to be created.

-int PL::Regions::regions_set_subkind_notify(kind *sub, kind *super) {
+int Regions::create_inference_subjects(void) {
+    infs_region = InferenceSubjects::new_fundamental(global_constants, "region(early)");
+    return FALSE;
+}
+int Regions::name_to_early_infs(wording W, inference_subject **infs) {
+    if ((<notable-regions-kinds>(W)) && (K_region == NULL)) *infs = infs_region;
+    return FALSE;
+}
+
+

§6. Region is not allowed to be made a subkind of anything else: +

+ +
+int Regions::set_subkind_notify(kind *sub, kind *super) {
     if ((sub == K_region) && (super != K_object)) {
         if (problem_count == 0)
             StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RegionAdrift),
@@ -194,22 +159,28 @@ there is no need to translate this to other languages.)
     return FALSE;
 }
 
-

§8.

+

§7. Note that because we use regular parentage_inf inferences to remember +that one region is inside another, it follows that the progenitor of a +region is either the next broadest region containing it, or else NULL. +

-int PL::Regions::object_is_a_region(instance *I) {
-    if ((K_region) && (I) && (Instances::of_kind(I, K_region))) return TRUE;
-    return FALSE;
+instance *Regions::enclosing(instance *reg) {
+    instance *P = NULL;
+    if (Spatial::object_is_a_room(reg)) P = REGIONS_DATA(reg)->in_region;
+    if (Regions::object_is_a_region(reg)) P = Spatial::progenitor(reg);
+    if (Regions::object_is_a_region(P) == FALSE) return NULL;
+    return P;
 }
 
-

§9. Rooms are always more specific than regions; if region X is within +

§8. Rooms are always more specific than regions; if region X is within region Y, then X is more specific than Y; otherwise any two regions are equally specific. (This is used in sorting rules by the specificity of their domains.)

-int PL::Regions::regions_more_specific(instance *I1, instance *I2) {
+int Regions::more_specific(instance *I1, instance *I2) {
     int r1 = Instances::of_kind(I1, K_room);
     int r2 = Instances::of_kind(I2, K_room);
     int reg1 = Instances::of_kind(I1, K_region);
@@ -223,7 +194,42 @@ domains.)
     return 0;
 }
 
-

§10. Properties. This is a property name to do with regions which Inform provides special +

§9. Detecting regions is easy. Note that if this plugin is inactive then +K_region will be null, and this will always return false. +

+ +
+int Regions::object_is_a_region(instance *I) {
+    if ((K_region) && (I) && (Instances::of_kind(I, K_region))) return TRUE;
+    return FALSE;
+}
+
+

§10. Every inference subject contains a pointer to its own unique copy of the +following minimal structure, though it will only be relevant for instances of +"region": +

+ +
define REGIONS_DATA(I) PLUGIN_DATA_ON_INSTANCE(regions, I)
+
+
+typedef struct regions_data {
+    struct instance *in_region;  smallest region containing me (rooms only)
+    struct parse_node *in_region_set_at;  where this is decided
+    struct inter_name *in_region_iname;  for testing regional containment found-ins
+    CLASS_DEFINITION
+} regions_data;
+
+int Regions::new_subject_notify(inference_subject *subj) {
+    regions_data *rd = CREATE(regions_data);
+    rd->in_region = NULL;
+    rd->in_region_set_at = NULL;
+    rd->in_region_iname = NULL;
+    ATTACH_PLUGIN_DATA_TO_SUBJECT(regions, subj, rd);
+    return FALSE;
+}
+
+ +

§11. This is a property name to do with regions which Inform provides special support for; it recognises the English name when it is defined by the Standard Rules. (So there is no need to translate this to other languages.)

@@ -233,21 +239,22 @@ Standard Rules. (So there is no need to translate this to other languages.) map region
-

§11.

+

§12.

-int PL::Regions::regions_new_property_notify(property *prn) {
+property *P_map_region = NULL;  a value property giving the region of a room
+int Regions::new_property_notify(property *prn) {
     if (<notable-regions-properties>(prn->name))
         P_map_region = prn;
     return FALSE;
 }
 
-

§12. Assertions. The following doesn't really intervene at all: it simply produces two problem +

§13. The following doesn't really intervene at all: it simply produces two problem messages which would have been less helpful if core Inform had produced them.

-int PL::Regions::regions_intervene_in_assertion(parse_node *px, parse_node *py) {
+int Regions::intervene_in_assertion(parse_node *px, parse_node *py) {
     if ((Node::get_type(px) == PROPER_NOUN_NT) &&
         (Node::get_type(py) == COMMON_NOUN_NT)) {
         inference_subject *left_subject = Node::get_subject(px);
@@ -285,140 +292,24 @@ messages which would have been less helpful if core Inform had produced them.
     return FALSE;
 }
 
-

§13. Relations.

+

§14. Model completion: +

-int PL::Regions::regions_name_to_early_infs(wording W, inference_subject **infs) {
-    if ((<notable-regions-kinds>(W)) && (K_region == NULL)) *infs = infs_region;
+int Regions::complete_model(int stage) {
+    if (stage == WORLD_STAGE_II) Assert map-region properties of rooms and regions14.1;
+    if (stage == WORLD_STAGE_III) Assert regional-found-in properties of regions14.2;
     return FALSE;
 }
 
-

§14.

- -
-void PL::Regions::create_relations(void) {
-    R_regional_containment =
-        BinaryPredicates::make_pair(spatial_bp_family,
-            BPTerms::new(infs_region),
-            BPTerms::new(KindSubjects::from_kind(K_object)),
-            I"region-contains", I"in-region",
-            NULL, Calculus::Schemas::new("TestRegionalContainment(*2,*1)"),
-            PreformUtilities::wording(<relation-names>,
-                REGIONAL_CONTAINMENT_RELATION_NAME));
-    BinaryPredicates::set_index_details(R_regional_containment, NULL, "room/region");
-}
-
-

§15. We intervene only in limited cases: X contains Y, X regionally contains Y, -or X incorporates Y; and only when X is a region. (This of course only -applies to the built-in spatial relationships; regions are entirely free -to participate in nonspatial relations.) -

- -
-int PL::Regions::assert_relations(binary_predicate *relation,
-    instance *I0, instance *I1) {
-    int I0_is_region = FALSE;
-    if (Instances::of_kind(I0, K_region)) I0_is_region = TRUE;
-    int I1_is_region = FALSE;
-    if (Instances::of_kind(I1, K_region)) I1_is_region = TRUE;
-
-    if (I0_is_region) {
-        if ((relation == R_incorporation) ||
-            (relation == R_containment) ||
-            (relation == R_regional_containment)) {
-            You can only be declared as in one region15.1;
-            if (I1_is_region) A region is being put inside a region15.2
-            else A room is being put inside a region15.3;
-        } else {
-            StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RegionRelation),
-                "regions can only contain rooms",
-                "and have no other relationships.");
-        }
-        return TRUE;
-    } else if (I1_is_region) {
-        if ((relation == R_incorporation) ||
-            (relation == R_containment) ||
-            (relation == R_regional_containment)) {
-            StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RegionRelation2),
-                "regions can only be contained in other regions",
-                "and not for example in rooms.");
-        }
-    }
-
-    return FALSE;
-}
-
-

§15.1. You can only be declared as in one region15.1 = -

- -
-    if ((REGIONS_DATA(I1)->in_region) &&
-        (REGIONS_DATA(I1)->in_region != I0)) {
-        StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RegionInTwoRegions),
-            "each region can only be declared to be inside a single "
-            "other region",
-            "since although regions can be placed inside each other, "
-            "they are not permitted to overlap.");
-        return TRUE;
-    }
-    REGIONS_DATA(I1)->in_region = I0;
-    REGIONS_DATA(I1)->in_region_set_at = current_sentence;
-
- -

§15.2. A region is being put inside a region15.2 = -

- -
-    inference_subject *inner = Instances::as_subject(I1);
-    inference_subject *outer = Instances::as_subject(I0);
-    SpatialInferences::infer_parentage(inner, CERTAIN_CE, outer);
-
- -

§15.3. Anything in or part of a region is necessarily a room, if it isn't known -to be a region already: -

- -

A room is being put inside a region15.3 = -

- -
-    inference_subject *rm = Instances::as_subject(I1);
-    parse_node *spec = Rvalues::from_instance(I0);
-    Propositions::Abstract::assert_kind_of_instance(I1, K_room);
-    PropertyInferences::draw(rm, P_map_region, spec);
-
- -

§16. Note that because we use regular PARENTAGE_INF inferences to remember -that one region is inside another, it follows that the progenitor of a -region is either the next broadest region containing it, or else NULL. -

- -
-instance *PL::Regions::enclosing(instance *reg) {
-    instance *P = NULL;
-    if (Spatial::object_is_a_room(reg)) P = REGIONS_DATA(reg)->in_region;
-    if (PL::Regions::object_is_a_region(reg)) P = Spatial::progenitor(reg);
-    if (PL::Regions::object_is_a_region(P) == FALSE) return NULL;
-    return P;
-}
-
-

§17. Model completion.

- -
-int PL::Regions::regions_complete_model(int stage) {
-    if (stage == WORLD_STAGE_II) Assert map-region properties of rooms and regions17.1;
-    if (stage == WORLD_STAGE_III) Assert regional-found-in properties of regions17.2;
-    return FALSE;
-}
-
-

§17.1. The following is needed in case somebody does something like this: +

§14.1. The following is needed in case somebody does something like this:

A desert room is a kind of room. The map region of a desert room is usually Sahara.

-

Assert map-region properties of rooms and regions17.1 = +

Assert map-region properties of rooms and regions14.1 =

@@ -437,59 +328,127 @@ region is either the next broadest region containing it, or else             }
         }
 
- -

§17.2. Assert regional-found-in properties of regions17.2 = +

+

§14.2. Assert regional-found-in properties of regions14.2 =

-    P_regional_found_in = ValueProperties::new_nameless(
+    property *P_regional_found_in = ValueProperties::new_nameless(
         I"regional_found_in", K_text);
     instance *I;
     LOOP_OVER_INSTANCES(I, K_object)
         if (Instances::of_kind(I, K_region)) {
-            inter_name *iname = PL::Regions::found_in_iname(I);
+            inter_name *iname = RTRegions::found_in_iname(I);
             ValueProperties::assert(P_regional_found_in, Instances::as_subject(I),
                 Rvalues::from_iname(iname), CERTAIN_CE);
         }
 
- -

§18.

+ +

§15. The relation "R in S" behaves so differently for regions that we need to +define it separately, even though there's no difference in English syntax. So: +

-void PL::Regions::write_regional_found_in_routines(void) {
-    instance *I;
-    LOOP_OVER_INSTANCES(I, K_object)
-        if (Instances::of_kind(I, K_region)) {
-            inter_name *iname = PL::Regions::found_in_iname(I);
-            packaging_state save = Routines::begin(iname);
-            Produce::inv_primitive(Emit::tree(), IF_BIP);
-            Produce::down(Emit::tree());
-                    Produce::inv_call_iname(Emit::tree(), Hierarchy::find(TESTREGIONALCONTAINMENT_HL));
-                    Produce::down(Emit::tree());
-                        Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(LOCATION_HL));
-                        Produce::val_iname(Emit::tree(), K_object, RTInstances::iname(I));
-                    Produce::up(Emit::tree());
-                Produce::code(Emit::tree());
-                Produce::down(Emit::tree());
-                    Produce::rtrue(Emit::tree());
-                Produce::up(Emit::tree());
-            Produce::up(Emit::tree());
-            Produce::rfalse(Emit::tree());
-            Routines::end(save);
-        }
+binary_predicate *R_regional_containment = NULL;
+
+

§16.

+ +
+void Regions::create_relations(void) {
+    R_regional_containment =
+        BinaryPredicates::make_pair(spatial_bp_family,
+            BPTerms::new(infs_region),
+            BPTerms::new(KindSubjects::from_kind(K_object)),
+            I"region-contains", I"in-region",
+            NULL, Calculus::Schemas::new("TestRegionalContainment(*2,*1)"),
+            PreformUtilities::wording(<relation-names>,
+                REGIONAL_CONTAINMENT_RELATION_NAME));
+    BinaryPredicates::set_index_details(R_regional_containment, NULL, "room/region");
 }
 
-

§19.

+

§17. We intervene only in limited cases: X contains Y, X regionally contains Y, +or X incorporates Y; and only when X is a region. (This of course only +applies to the built-in spatial relationships; regions are entirely free +to participate in nonspatial relations.) +

-int PL::Regions::regions_add_to_World_index(OUTPUT_STREAM, instance *O) {
-    if ((O) && (Instances::of_kind(O, K_room))) {
-        instance *R = PL::Regions::enclosing(O);
-        if (R) PL::HTMLMap::colour_chip(OUT, O, R, REGIONS_DATA(O)->in_region_set_at);
+int Regions::assert_relations(binary_predicate *relation,
+    instance *I0, instance *I1) {
+    int I0_is_region = FALSE;
+    if (Instances::of_kind(I0, K_region)) I0_is_region = TRUE;
+    int I1_is_region = FALSE;
+    if (Instances::of_kind(I1, K_region)) I1_is_region = TRUE;
+
+    if (I0_is_region) {
+        if ((relation == R_incorporation) ||
+            (relation == R_containment) ||
+            (relation == R_regional_containment)) {
+            You can only be declared as in one region17.1;
+            if (I1_is_region) A region is being put inside a region17.2
+            else A room is being put inside a region17.3;
+        } else {
+            StandardProblems::sentence_problem(Task::syntax_tree(),
+                _p_(PM_RegionRelation),
+                "regions can only contain rooms",
+                "and have no other relationships.");
+        }
+        return TRUE;
+    } else if (I1_is_region) {
+        if ((relation == R_incorporation) ||
+            (relation == R_containment) ||
+            (relation == R_regional_containment)) {
+            StandardProblems::sentence_problem(Task::syntax_tree(),
+                _p_(PM_RegionRelation2),
+                "regions can only be contained in other regions",
+                "and not for example in rooms.");
+        }
     }
+
     return FALSE;
 }
 
+

§17.1. You can only be declared as in one region17.1 = +

+ +
+    if ((REGIONS_DATA(I1)->in_region) &&
+        (REGIONS_DATA(I1)->in_region != I0)) {
+        StandardProblems::sentence_problem(Task::syntax_tree(),
+            _p_(PM_RegionInTwoRegions),
+            "each region can only be declared to be inside a single "
+            "other region",
+            "since although regions can be placed inside each other, "
+            "they are not permitted to overlap.");
+        return TRUE;
+    }
+    REGIONS_DATA(I1)->in_region = I0;
+    REGIONS_DATA(I1)->in_region_set_at = current_sentence;
+
+ +

§17.2. A region is being put inside a region17.2 = +

+ +
+    inference_subject *inner = Instances::as_subject(I1);
+    inference_subject *outer = Instances::as_subject(I0);
+    SpatialInferences::infer_parentage(inner, CERTAIN_CE, outer);
+
+ +

§17.3. Anything in or part of a region is necessarily a room, if it isn't known +to be a region already: +

+ +

A room is being put inside a region17.3 = +

+ +
+    inference_subject *rm = Instances::as_subject(I1);
+    parse_node *spec = Rvalues::from_instance(I0);
+    Propositions::Abstract::assert_kind_of_instance(I1, K_room);
+    PropertyInferences::draw(rm, P_map_region, spec);
+
+ diff --git a/docs/if-module/3-si.html b/docs/if-module/3-si.html index b3ca30c1a..9b4d0da38 100644 --- a/docs/if-module/3-si.html +++ b/docs/if-module/3-si.html @@ -149,7 +149,7 @@ indications of spatial structure: CLASS_DEFINITION } parentage_inference_data; -void SpatialInferences::infer_parentage(inference_subject *inner, int certitude, +void SpatialInferences::infer_parentage(inference_subject *inner, int certitude, inference_subject *outer) { parentage_inference_data *data = CREATE(parentage_inference_data); data->parent = InferenceSubjects::divert(outer); diff --git a/docs/if-module/3-sm.html b/docs/if-module/3-sm.html index 6d69f29e1..a7c759b33 100644 --- a/docs/if-module/3-sm.html +++ b/docs/if-module/3-sm.html @@ -209,7 +209,7 @@ of vehicle, and so on, but this would cause mayhem in the model world. So:

-int Spatial::object_is_a_room(instance *I) {
+int Spatial::object_is_a_room(instance *I) {
     if ((K_room) && (I) && (Instances::of_kind(I, K_room))) return TRUE;
     return FALSE;
 }
@@ -809,7 +809,7 @@ provide access routines to read and write:
 

-instance *Spatial::progenitor(instance *I) {
+instance *Spatial::progenitor(instance *I) {
     if (I == NULL) return NULL;
     if (PluginManager::active(spatial_plugin) == FALSE) return NULL;
     return SPATIAL_DATA(I)->progenitor;
@@ -877,7 +877,7 @@ the kind of here-objects.
         if ((Spatial::progenitor(I)) &&
             (Instances::of_kind(I, K_thing) == FALSE) &&
             (Instances::of_kind(I, K_room) == FALSE) &&
-            (PL::Regions::object_is_a_region(I) == FALSE)) {
+            (Regions::object_is_a_region(I) == FALSE)) {
             Problems::quote_source(1, Instances::get_creating_sentence(I));
             Problems::quote_object(2, I);
             Problems::quote_object(3, Spatial::progenitor(I));
@@ -1139,7 +1139,7 @@ which depend on Spatial whether or not one object spatially contains another:
 

-int Spatial::encloses(instance *I1, instance *I2) {
+int Spatial::encloses(instance *I1, instance *I2) {
     while (I1) {
         I1 = Spatial::progenitor(I1);
         if (I1 == I2) return TRUE;
diff --git a/docs/if-module/3-sm2.html b/docs/if-module/3-sm2.html
index cd9887d02..ac1171d9f 100644
--- a/docs/if-module/3-sm2.html
+++ b/docs/if-module/3-sm2.html
@@ -2880,8 +2880,8 @@ contain.
         instance *R1 = mc1->first_room_in_submap;
         instance *R2 = mc2->first_room_in_submap;
         if ((R1) && (R2)) {  which should always happen, but just in case of an error
-            instance *reg1 = PL::Regions::enclosing(R1);
-            instance *reg2 = PL::Regions::enclosing(R2);
+            instance *reg1 = Regions::enclosing(R1);
+            instance *reg2 = Regions::enclosing(R2);
             if ((reg1) && (reg2 == NULL)) return -1;
             if ((reg1 == NULL) && (reg2)) return 1;
             if (reg1) {
@@ -3013,12 +3013,12 @@ running time in check.
     if (sub->bounds.population == 1) {
         instance *R = sub->first_room_in_submap;
         if (R) {  which should always happen, but just in case of an error
-            instance *reg = PL::Regions::enclosing(R);
+            instance *reg = Regions::enclosing(R);
             if (reg) {
                 instance *S, *closest_S = NULL;
                 int closest = 0;
                 LOOP_OVER_ROOMS(S)
-                    if ((S != R) && (PL::Regions::enclosing(S) == reg))
+                    if ((S != R) && (Regions::enclosing(S) == reg))
                         if ((posnd == FALSE) || (MAP_DATA(S)->submap->positioned)) {
                             int diff = 2*(R->allocation_id - S->allocation_id);
                             if (diff < 0) diff = 1-diff;
@@ -3167,7 +3167,7 @@ can make use of the following:
     if (Instances::of_kind(R, K_room)) {
         wording RW = Instances::get_name(R, FALSE);
         LOG("%+W is a room.\n", RW);
-        instance *reg = PL::Regions::enclosing(R);
+        instance *reg = Regions::enclosing(R);
         if (reg) {
             wording RGW = Instances::get_name(reg, FALSE);
             if (MAP_DATA(reg)->zone == 1) {
diff --git a/docs/if-module/3-sr.html b/docs/if-module/3-sr.html
index df813a219..78581ad9d 100644
--- a/docs/if-module/3-sr.html
+++ b/docs/if-module/3-sr.html
@@ -124,7 +124,7 @@ MathJax = {
         Make built-in spatial relationships2.1;
         Make built-in indirect spatial relationships2.2;
         PL::MapDirections::create_relations();
-        PL::Regions::create_relations();
+        Regions::create_relations();
     }
 }
 
@@ -311,7 +311,7 @@ way which isn't symmetrical between the two, and this way round is cleanest.
     if (Backdrops::assert_relations(bp, I0, I1)) return TRUE;
     if (PL::MapDirections::assert_relations(bp, I0, I1)) return TRUE;
-    if (PL::Regions::assert_relations(bp, I0, I1)) return TRUE;
+    if (Regions::assert_relations(bp, I0, I1)) return TRUE;
 

§4.2. This is the point at which non-assertable relations are thrown out. diff --git a/docs/index-module/2-ipw.html b/docs/index-module/2-ipw.html index 71209e32a..ae4ba7858 100644 --- a/docs/index-module/2-ipw.html +++ b/docs/index-module/2-ipw.html @@ -153,13 +153,13 @@ instance) Spatial.

     instance *reg;
     LOOP_OVER_INSTANCES(reg, K_object)
-        if (PL::Regions::object_is_a_region(reg)) {
+        if (Regions::object_is_a_region(reg)) {
             int subheaded = FALSE;
             IXInstances::increment_indexing_count(reg);
             instance *rm;
             LOOP_OVER_INSTANCES(rm, K_object)
                 if ((Spatial::object_is_a_room(rm)) &&
-                    (PL::Regions::enclosing(rm) == reg)) {
+                    (Regions::enclosing(rm) == reg)) {
                     if (subheaded == FALSE) {
                         Start a new details panel on the World index2.2.2;
                         Index the name and super-region of the region2.2.1;
@@ -178,7 +178,7 @@ instance) Spatial.
 
 
     WRITE("<b>The <i>%+W</i> region", Instances::get_name(reg, FALSE));
-    instance *within = PL::Regions::enclosing(reg);
+    instance *within = Regions::enclosing(reg);
     if (within) WRITE(" within the <i>%+W</i> region", Instances::get_name(within, FALSE));
     WRITE("</b>");
 
diff --git a/docs/index-module/3-bck.html b/docs/index-module/3-bck.html index 07d8d04ec..5e0923356 100644 --- a/docs/index-module/3-bck.html +++ b/docs/index-module/3-bck.html @@ -119,7 +119,7 @@ adds backdrop contents to a room called
  • This code is used in §1.
  • diff --git a/docs/index-module/3-bd.html b/docs/index-module/3-bd.html index 5526f7053..bf28478a1 100644 --- a/docs/index-module/3-bd.html +++ b/docs/index-module/3-bd.html @@ -167,7 +167,7 @@ Contents listing, so: }
    diff --git a/docs/index-module/3-ef.html b/docs/index-module/3-ef.html index 1de046be1..ef821e60f 100644 --- a/docs/index-module/3-ef.html +++ b/docs/index-module/3-ef.html @@ -119,7 +119,7 @@ function togglePopup(material_id) { }
    diff --git a/docs/index-module/3-fgr.html b/docs/index-module/3-fgr.html index 1711ccf37..db57af468 100644 --- a/docs/index-module/3-fgr.html +++ b/docs/index-module/3-fgr.html @@ -165,7 +165,7 @@ to match this width, preserving the aspect ratio. }
    diff --git a/docs/index-module/3-rgn.html b/docs/index-module/3-rgn.html new file mode 100644 index 000000000..1a49090d5 --- /dev/null +++ b/docs/index-module/3-rgn.html @@ -0,0 +1,85 @@ + + + + Regions + + + + + + + + + + + + + + + +
    + + +

    Indexing the player's initial position.

    + +

    §1.

    + +
    +int IXRegions::add_to_World_index(OUTPUT_STREAM, instance *O) {
    +    if ((O) && (Instances::of_kind(O, K_room))) {
    +        instance *R = Regions::enclosing(O);
    +        if (R) PL::HTMLMap::colour_chip(OUT, O, R, REGIONS_DATA(O)->in_region_set_at);
    +    }
    +    return FALSE;
    +}
    +
    + + +
    + + + diff --git a/docs/index-module/3-se.html b/docs/index-module/3-se.html index b956d687b..2019ae71c 100644 --- a/docs/index-module/3-se.html +++ b/docs/index-module/3-se.html @@ -191,7 +191,7 @@ function togglePopup(material_id) { } diff --git a/docs/index-module/3-spt.html b/docs/index-module/3-spt.html index b19a89774..444ac27da 100644 --- a/docs/index-module/3-spt.html +++ b/docs/index-module/3-spt.html @@ -165,7 +165,7 @@ it already turns up under its owner. } diff --git a/docs/index-module/3-tp.html b/docs/index-module/3-tp.html index 5649263e2..1c17e0ab3 100644 --- a/docs/index-module/3-tp.html +++ b/docs/index-module/3-tp.html @@ -93,7 +93,7 @@ usually appear anywhere. } diff --git a/docs/index-module/index.html b/docs/index-module/index.html index fa33ab67a..c9752abb3 100644 --- a/docs/index-module/index.html +++ b/docs/index-module/index.html @@ -179,6 +179,11 @@ Backdrops - Indexing the player's initial position.

    +
  • +

    + Regions - + Indexing the player's initial position.

    +
  • diff --git a/docs/runtime-module/2-emt.html b/docs/runtime-module/2-emt.html index 91fc9b9af..f3c1f42eb 100644 --- a/docs/runtime-module/2-emt.html +++ b/docs/runtime-module/2-emt.html @@ -84,7 +84,7 @@ function togglePopup(material_id) { inter_tree *I7_generation_tree = NULL; -inter_tree *Emit::tree(void) { +inter_tree *Emit::tree(void) { return I7_generation_tree; } diff --git a/docs/runtime-module/2-hrr.html b/docs/runtime-module/2-hrr.html index 93f0cdb9e..2ffefae58 100644 --- a/docs/runtime-module/2-hrr.html +++ b/docs/runtime-module/2-hrr.html @@ -1723,7 +1723,7 @@ function togglePopup(material_id) {

    §4.

    -inter_name *Hierarchy::find(int id) {
    +inter_name *Hierarchy::find(int id) {
         return HierarchyLocations::find(Emit::tree(), id);
     }
     
    @@ -1755,7 +1755,7 @@ function togglePopup(material_id) {
         return HierarchyLocations::attach_new_package(Emit::tree(), NULL, super, hap_id);
     }
     
    -inter_name *Hierarchy::make_iname_in(int id, package_request *P) {
    +inter_name *Hierarchy::make_iname_in(int id, package_request *P) {
         return HierarchyLocations::find_in_package(Emit::tree(), id, P, EMPTY_WORDING, NULL, -1, NULL);
     }
     
    diff --git a/docs/runtime-module/4-ins.html b/docs/runtime-module/4-ins.html
    index a6c399818..ebdfbb961 100644
    --- a/docs/runtime-module/4-ins.html
    +++ b/docs/runtime-module/4-ins.html
    @@ -91,7 +91,7 @@ function togglePopup(material_id) {
         I->icd.instance_emitted = FALSE;
     }
     
    -inter_name *RTInstances::iname(instance *I) {
    +inter_name *RTInstances::iname(instance *I) {
         if (I == NULL) return NULL;
         return I->icd.instance_iname;
     }
    @@ -154,7 +154,7 @@ declarations) and finally return     return iname;
     }
     
    -package_request *RTInstances::package(instance *I) {
    +package_request *RTInstances::package(instance *I) {
         RTInstances::iname(I);  Thus forcing this to exist...
         return I->icd.instance_package;
     }
    diff --git a/docs/runtime-module/4-rtn.html b/docs/runtime-module/4-rtn.html
    index cb68f47b7..72c0a8df9 100644
    --- a/docs/runtime-module/4-rtn.html
    +++ b/docs/runtime-module/4-rtn.html
    @@ -81,7 +81,7 @@ already been set up, or not. Here's not:
     

    -packaging_state Routines::begin(inter_name *name) {
    +packaging_state Routines::begin(inter_name *name) {
         return Routines::begin_framed(name, NULL);
     }
     
    @@ -140,7 +140,7 @@ did not.

    -void Routines::end(packaging_state save) {
    +void Routines::end(packaging_state save) {
         kind *R_kind = LocalVariables::deduced_function_kind(currently_compiling_in_frame);
     
         inter_name *kernel_name = NULL, *public_name = currently_compiling_iname;
    diff --git a/docs/runtime-module/5-bck.html b/docs/runtime-module/5-bck.html
    index 9db33529f..8d191dc55 100644
    --- a/docs/runtime-module/5-bck.html
    +++ b/docs/runtime-module/5-bck.html
    @@ -142,7 +142,7 @@
     
    • This code is used in §2.
    diff --git a/docs/runtime-module/5-bd.html b/docs/runtime-module/5-bd.html index 18f9c7c59..e52b3db8c 100644 --- a/docs/runtime-module/5-bd.html +++ b/docs/runtime-module/5-bd.html @@ -211,7 +211,7 @@ around it, in byte-accessible memory. }
    diff --git a/docs/runtime-module/5-ef.html b/docs/runtime-module/5-ef.html index e15641294..3c9600fc9 100644 --- a/docs/runtime-module/5-ef.html +++ b/docs/runtime-module/5-ef.html @@ -129,7 +129,7 @@ diff --git a/docs/runtime-module/5-fgr.html b/docs/runtime-module/5-fgr.html index 14a4bea82..5144230dc 100644 --- a/docs/runtime-module/5-fgr.html +++ b/docs/runtime-module/5-fgr.html @@ -77,7 +77,7 @@ } diff --git a/docs/runtime-module/5-nmn.html b/docs/runtime-module/5-nmn.html index 2a92e8654..568400d18 100644 --- a/docs/runtime-module/5-nmn.html +++ b/docs/runtime-module/5-nmn.html @@ -186,7 +186,7 @@ function togglePopup(material_id) { diff --git a/docs/runtime-module/5-prs.html b/docs/runtime-module/5-prs.html index 0c965cd6c..248511a91 100644 --- a/docs/runtime-module/5-prs.html +++ b/docs/runtime-module/5-prs.html @@ -148,7 +148,7 @@ for the kinds we inherit from. } diff --git a/docs/runtime-module/5-rgn.html b/docs/runtime-module/5-rgn.html new file mode 100644 index 000000000..4db728449 --- /dev/null +++ b/docs/runtime-module/5-rgn.html @@ -0,0 +1,117 @@ + + + + Regions + + + + + + + + + + + + + + + + + + +
    + + +

    §1.

    + +
    +inter_name *RTRegions::found_in_iname(instance *I) {
    +    if (REGIONS_DATA(I)->in_region_iname == NULL)
    +        REGIONS_DATA(I)->in_region_iname =
    +            Hierarchy::make_iname_in(REGION_FOUND_IN_FN_HL, RTInstances::package(I));
    +    return REGIONS_DATA(I)->in_region_iname;
    +}
    +
    +

    §2.

    + +
    +void RTRegions::write_found_in_functions(void) {
    +    instance *I;
    +    LOOP_OVER_INSTANCES(I, K_object)
    +        if (Instances::of_kind(I, K_region)) {
    +            inter_name *iname = RTRegions::found_in_iname(I);
    +            packaging_state save = Routines::begin(iname);
    +            Produce::inv_primitive(Emit::tree(), IF_BIP);
    +            Produce::down(Emit::tree());
    +                    Produce::inv_call_iname(Emit::tree(),
    +                        Hierarchy::find(TESTREGIONALCONTAINMENT_HL));
    +                    Produce::down(Emit::tree());
    +                        Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(LOCATION_HL));
    +                        Produce::val_iname(Emit::tree(), K_object, RTInstances::iname(I));
    +                    Produce::up(Emit::tree());
    +                Produce::code(Emit::tree());
    +                Produce::down(Emit::tree());
    +                    Produce::rtrue(Emit::tree());
    +                Produce::up(Emit::tree());
    +            Produce::up(Emit::tree());
    +            Produce::rfalse(Emit::tree());
    +            Routines::end(save);
    +        }
    +}
    +
    + + +
    + + + diff --git a/docs/runtime-module/5-se.html b/docs/runtime-module/5-se.html index f7e188158..77c3a136d 100644 --- a/docs/runtime-module/5-se.html +++ b/docs/runtime-module/5-se.html @@ -77,7 +77,7 @@ } diff --git a/docs/runtime-module/5-spt.html b/docs/runtime-module/5-spt.html index 96598fbd2..4bd08d380 100644 --- a/docs/runtime-module/5-spt.html +++ b/docs/runtime-module/5-spt.html @@ -142,7 +142,7 @@ be compiled, so this code is never used. } diff --git a/docs/runtime-module/5-tp.html b/docs/runtime-module/5-tp.html index 6374e0686..4680cd41f 100644 --- a/docs/runtime-module/5-tp.html +++ b/docs/runtime-module/5-tp.html @@ -114,7 +114,7 @@ the function ChangePlayer} diff --git a/docs/runtime-module/index.html b/docs/runtime-module/index.html index 9fe09e7b3..45080a3f7 100644 --- a/docs/runtime-module/index.html +++ b/docs/runtime-module/index.html @@ -344,6 +344,11 @@ Backdrops -

    +
  • +

    + Regions - +

    +
  • diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt index c9d62b2a8..3755f9377 100644 --- a/inform7/Figures/memory-diagnostics.txt +++ b/inform7/Figures/memory-diagnostics.txt @@ -228,7 +228,7 @@ Total memory consumption was 258576K = 253 MB 37.5% was used for memory not allocated for objects: - 15.9% text stream storage 42248412 bytes in 265816 claims + 15.9% text stream storage 42248372 bytes in 265816 claims 3.5% dictionary storage 9278976 bytes in 16372 claims ---- sorting 1064 bytes in 3 claims 2.7% source text 7200000 bytes in 3 claims diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt index b03a3a521..afede8724 100644 --- a/inform7/Figures/timings-diagnostics.txt +++ b/inform7/Figures/timings-diagnostics.txt @@ -1,15 +1,15 @@ 100.0% in inform7 run - 67.0% in compilation to Inter - 25.7% in //Phrases::Manager::compile_first_block// + 67.8% in compilation to Inter + 25.8% in //Phrases::Manager::compile_first_block// 8.9% in //Phrases::Manager::compile_as_needed// - 7.0% in //Strings::compile_responses// - 6.1% in //InferenceSubjects::emit_all// - 4.1% in //MajorNodes::pre_pass// - 3.2% in //MajorNodes::pass_1// - 1.9% in //Phrases::Manager::RulePrintingRule_routine// - 1.7% in //Phrases::Manager::rulebooks_array// - 1.0% in //RTVerbs::ConjugateVerb// - 0.8% in //Phrases::Manager::traverse// + 6.7% in //Strings::compile_responses// + 6.4% in //InferenceSubjects::emit_all// + 4.4% in //MajorNodes::pre_pass// + 3.4% in //MajorNodes::pass_1// + 2.0% in //Phrases::Manager::RulePrintingRule_routine// + 1.8% in //Phrases::Manager::rulebooks_array// + 0.9% in //Phrases::Manager::traverse// + 0.9% in //RTVerbs::ConjugateVerb// 0.5% in //Phrases::Manager::parse_rule_parameters// 0.5% in //World::stage_V// 0.3% in //MajorNodes::pass_2// @@ -19,11 +19,11 @@ 0.1% in //RTKinds::compile_data_type_support_routines// 0.1% in //Task::make_built_in_kind_constructors// 0.1% in //World::stages_II_and_III// - 3.2% not specifically accounted for - 30.5% in running Inter pipeline - 10.2% in step preparation - 9.7% in inter step 2/12: link - 7.0% in inter step 12/12: generate inform6 -> auto.inf + 3.3% not specifically accounted for + 29.7% in running Inter pipeline + 9.7% in step preparation + 9.5% in inter step 2/12: link + 6.9% in inter step 12/12: generate inform6 -> auto.inf 0.3% in inter step 9/12: make-identifiers-unique 0.1% in inter step 10/12: reconcile-verbs 0.1% in inter step 11/12: eliminate-redundant-labels @@ -31,6 +31,6 @@ 0.1% in inter step 6/12: assimilate 0.1% in inter step 7/12: resolve-external-symbols 0.1% in inter step 8/12: inspect-plugs - 2.1% not specifically accounted for - 1.9% in supervisor + 2.0% not specifically accounted for + 2.0% in supervisor 0.4% not specifically accounted for diff --git a/inform7/if-module/Chapter 1/IF Module.w b/inform7/if-module/Chapter 1/IF Module.w index bb971b380..c7751f9d3 100644 --- a/inform7/if-module/Chapter 1/IF Module.w +++ b/inform7/if-module/Chapter 1/IF Module.w @@ -83,7 +83,7 @@ void IFModule::create_plugins(void) { map_plugin = PluginManager::new(&PL::Map::start, I"mapping", ifp); persons_plugin = PluginManager::new(&PL::Persons::start, I"persons", ifp); player_plugin = PluginManager::new(&Player::start, I"player", ifp); - regions_plugin = PluginManager::new(&PL::Regions::start, I"regions", ifp); + regions_plugin = PluginManager::new(&Regions::start, I"regions", ifp); scenes_plugin = PluginManager::new(&PL::Scenes::start, I"scenes", ifp); scoring_plugin = PluginManager::new(&PL::Score::start, I"scoring", ifp); showme_plugin = PluginManager::new(&PL::Showme::start, I"showme", ifp); diff --git a/inform7/if-module/Chapter 3/EPS Map.w b/inform7/if-module/Chapter 3/EPS Map.w index 4e05e7c85..02455c89f 100644 --- a/inform7/if-module/Chapter 3/EPS Map.w +++ b/inform7/if-module/Chapter 3/EPS Map.w @@ -190,7 +190,7 @@ void PL::EPSMap::put_mp(wchar_t *name, map_parameter_scope *scope, instance *sco if (scope_I) { if (Spatial::object_is_a_room(scope_I)) scope = PL::EPSMap::scope_for_single_room(scope_I); - else if (PL::Regions::object_is_a_region(scope_I)) { + else if (Regions::object_is_a_region(scope_I)) { instance *rm; LOOP_OVER_INSTANCES(rm, K_room) if (PL::EPSMap::obj_in_region(rm, scope_I)) @@ -221,8 +221,8 @@ map_parameter_scope *PL::EPSMap::scope_for_single_room(instance *rm) { int PL::EPSMap::obj_in_region(instance *I, instance *reg) { if ((I == NULL) || (reg == NULL)) return FALSE; - if (PL::Regions::enclosing(I) == reg) return TRUE; - return PL::EPSMap::obj_in_region(PL::Regions::enclosing(I), reg); + if (Regions::enclosing(I) == reg) return TRUE; + return PL::EPSMap::obj_in_region(Regions::enclosing(I), reg); } @ String parameters. @@ -684,7 +684,7 @@ void PL::EPSMap::new_map_hint_sentence(int pass, parse_node *p) { break; case INSTANCE_MAP_SCOPE: if ((Spatial::object_is_a_room(<>)) || - (PL::Regions::object_is_a_region(<>))) + (Regions::object_is_a_region(<>))) scope_I = <>; if (scope_I) { LOGIF(SPATIAL_MAP, "Setting for object $O\n", scope_I); diff --git a/inform7/if-module/Chapter 3/HTML Map.w b/inform7/if-module/Chapter 3/HTML Map.w index 41b72aba2..3dc65ca5f 100644 --- a/inform7/if-module/Chapter 3/HTML Map.w +++ b/inform7/if-module/Chapter 3/HTML Map.w @@ -433,7 +433,7 @@ from each other.) instance *R; LOOP_OVER_ROOMS(R) if (MAP_DATA(R)->world_index_colour == NULL) { - instance *reg = PL::Regions::enclosing(R); + instance *reg = Regions::enclosing(R); if (reg) MAP_DATA(R)->world_index_colour = MAP_DATA(reg)->world_index_colour; else @@ -1045,7 +1045,7 @@ int PL::HTMLMap::add_key_for(OUTPUT_STREAM, instance *reg) { int count = 0; instance *R; LOOP_OVER_ROOMS(R) { - if (PL::Regions::enclosing(R) == reg) { + if (Regions::enclosing(R) == reg) { if (count++ == 0) { @; } else { diff --git a/inform7/if-module/Chapter 3/Regions.w b/inform7/if-module/Chapter 3/Regions.w index d8cec8472..3244a1cbf 100644 --- a/inform7/if-module/Chapter 3/Regions.w +++ b/inform7/if-module/Chapter 3/Regions.w @@ -1,107 +1,73 @@ -[PL::Regions::] Regions. +[Regions::] Regions. A plugin providing support for grouping rooms together into named and nestable regions. -@ The relation "R in S" behaves so differently for regions that we need to -define it separately, even though there's no difference in English syntax. So: - -= (early code) -binary_predicate *R_regional_containment = NULL; - @ "Region" is in fact one of the four top-level kinds in the standard I7 -hierarchy, alongside thing, room and direction. - -= (early code) -kind *K_region = NULL; -inference_subject *infs_region = NULL; -property *P_map_region = NULL; /* a value property giving the region of a room */ -property *P_regional_found_in = NULL; /* an I6-only property used for implementation */ - -@ Every inference subject contains a pointer to its own unique copy of the -following minimal structure, though it will only be relevant for instances of -"room": - -@d REGIONS_DATA(I) PLUGIN_DATA_ON_INSTANCE(regions, I) +world model, alongside thing, room and direction. What makes it complicated +is that it can contain rooms and other regions, but that this form of +containment is implemented differently from spatial containment: as a +result, a new "regional containment" relation is needed. = -typedef struct regions_data { - struct instance *in_region; /* smallest region containing me (rooms only) */ - struct parse_node *in_region_set_at; /* where this is decided */ - struct inter_name *in_region_iname; /* for testing regional containment found-ins */ - CLASS_DEFINITION -} regions_data; - -@h Initialising. - -= -void PL::Regions::start(void) { - PluginManager::plug(CREATE_INFERENCE_SUBJECTS_PLUG, PL::Regions::create_inference_subjects); - PluginManager::plug(NEW_BASE_KIND_NOTIFY_PLUG, PL::Regions::regions_new_base_kind_notify); - PluginManager::plug(SET_SUBKIND_NOTIFY_PLUG, PL::Regions::regions_set_subkind_notify); - PluginManager::plug(NEW_SUBJECT_NOTIFY_PLUG, PL::Regions::regions_new_subject_notify); - PluginManager::plug(NEW_PROPERTY_NOTIFY_PLUG, PL::Regions::regions_new_property_notify); - PluginManager::plug(COMPLETE_MODEL_PLUG, PL::Regions::regions_complete_model); - PluginManager::plug(MORE_SPECIFIC_PLUG, PL::Regions::regions_more_specific); - PluginManager::plug(INTERVENE_IN_ASSERTION_PLUG, PL::Regions::regions_intervene_in_assertion); - PluginManager::plug(NAME_TO_EARLY_INFS_PLUG, PL::Regions::regions_name_to_early_infs); - PluginManager::plug(ADD_TO_WORLD_INDEX_PLUG, PL::Regions::regions_add_to_World_index); - PluginManager::plug(PRODUCTION_LINE_PLUG, PL::Regions::production_line); +void Regions::start(void) { + PluginManager::plug(CREATE_INFERENCE_SUBJECTS_PLUG, Regions::create_inference_subjects); + PluginManager::plug(NEW_BASE_KIND_NOTIFY_PLUG, Regions::new_base_kind_notify); + PluginManager::plug(SET_SUBKIND_NOTIFY_PLUG, Regions::set_subkind_notify); + PluginManager::plug(NEW_SUBJECT_NOTIFY_PLUG, Regions::new_subject_notify); + PluginManager::plug(NEW_PROPERTY_NOTIFY_PLUG, Regions::new_property_notify); + PluginManager::plug(COMPLETE_MODEL_PLUG, Regions::complete_model); + PluginManager::plug(MORE_SPECIFIC_PLUG, Regions::more_specific); + PluginManager::plug(INTERVENE_IN_ASSERTION_PLUG, Regions::intervene_in_assertion); + PluginManager::plug(NAME_TO_EARLY_INFS_PLUG, Regions::name_to_early_infs); + PluginManager::plug(ADD_TO_WORLD_INDEX_PLUG, IXRegions::add_to_World_index); + PluginManager::plug(PRODUCTION_LINE_PLUG, Regions::production_line); } -int PL::Regions::production_line(int stage, int debugging, +int Regions::production_line(int stage, int debugging, stopwatch_timer *sequence_timer) { if (stage == INTER1_CSEQ) { - BENCH(PL::Regions::write_regional_found_in_routines); + BENCH(RTRegions::write_found_in_functions); } return FALSE; } -int PL::Regions::create_inference_subjects(void) { - infs_region = InferenceSubjects::new_fundamental(global_constants, "region(early)"); - return FALSE; -} +@ There is one kind of interest: "region", of course. It is recognised by the English +name in the Standard Rules. (So there is no need to translate this to other languages.) -regions_data *PL::Regions::new_data(inference_subject *subj) { - regions_data *rd = CREATE(regions_data); - rd->in_region = NULL; - rd->in_region_set_at = NULL; - rd->in_region_iname = NULL; - return rd; -} += (early code) +kind *K_region = NULL; +inference_subject *infs_region = NULL; -inter_name *PL::Regions::found_in_iname(instance *I) { - if (REGIONS_DATA(I)->in_region_iname == NULL) - REGIONS_DATA(I)->in_region_iname = Hierarchy::make_iname_in(REGION_FOUND_IN_FN_HL, RTInstances::package(I)); - return REGIONS_DATA(I)->in_region_iname; -} - -@h Kinds. -This a kind name to do with regions which Inform provides special support -for; it recognises the English name when defined by the Standard Rules. (So -there is no need to translate this to other languages.) - -= +@ = ::= region @ = -int PL::Regions::regions_new_base_kind_notify(kind *new_base, char *text_stream, wording W) { +int Regions::new_base_kind_notify(kind *new_base, char *text_stream, wording W) { if ((W)) { K_region = new_base; return TRUE; } return FALSE; } -int PL::Regions::regions_new_subject_notify(inference_subject *subj) { - ATTACH_PLUGIN_DATA_TO_SUBJECT(regions, subj, PL::Regions::new_data(subj)); +@ As with the handling of the main spatial kinds, we need a placeholder for the +"region" subject until |K_region| is ready to be created. + += +int Regions::create_inference_subjects(void) { + infs_region = InferenceSubjects::new_fundamental(global_constants, "region(early)"); + return FALSE; +} +int Regions::name_to_early_infs(wording W, inference_subject **infs) { + if (((W)) && (K_region == NULL)) *infs = infs_region; return FALSE; } -@ Region needs to be an abstract object, not a thing or a room, so: +@ Region is not allowed to be made a subkind of anything else: = -int PL::Regions::regions_set_subkind_notify(kind *sub, kind *super) { +int Regions::set_subkind_notify(kind *sub, kind *super) { if ((sub == K_region) && (super != K_object)) { if (problem_count == 0) StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RegionAdrift), @@ -114,10 +80,17 @@ int PL::Regions::regions_set_subkind_notify(kind *sub, kind *super) { return FALSE; } -@ = -int PL::Regions::object_is_a_region(instance *I) { - if ((K_region) && (I) && (Instances::of_kind(I, K_region))) return TRUE; - return FALSE; +@ Note that because we use regular |parentage_inf| inferences to remember +that one region is inside another, it follows that the progenitor of a +region is either the next broadest region containing it, or else |NULL|. + += +instance *Regions::enclosing(instance *reg) { + instance *P = NULL; + if (Spatial::object_is_a_room(reg)) P = REGIONS_DATA(reg)->in_region; + if (Regions::object_is_a_region(reg)) P = Spatial::progenitor(reg); + if (Regions::object_is_a_region(P) == FALSE) return NULL; + return P; } @ Rooms are always more specific than regions; if region X is within @@ -126,7 +99,7 @@ equally specific. (This is used in sorting rules by the specificity of their domains.) = -int PL::Regions::regions_more_specific(instance *I1, instance *I2) { +int Regions::more_specific(instance *I1, instance *I2) { int r1 = Instances::of_kind(I1, K_room); int r2 = Instances::of_kind(I2, K_room); int reg1 = Instances::of_kind(I1, K_region); @@ -140,8 +113,39 @@ int PL::Regions::regions_more_specific(instance *I1, instance *I2) { return 0; } -@h Properties. -This is a property name to do with regions which Inform provides special +@ Detecting regions is easy. Note that if this plugin is inactive then +|K_region| will be null, and this will always return false. + += +int Regions::object_is_a_region(instance *I) { + if ((K_region) && (I) && (Instances::of_kind(I, K_region))) return TRUE; + return FALSE; +} + +@ Every inference subject contains a pointer to its own unique copy of the +following minimal structure, though it will only be relevant for instances of +"region": + +@d REGIONS_DATA(I) PLUGIN_DATA_ON_INSTANCE(regions, I) + += +typedef struct regions_data { + struct instance *in_region; /* smallest region containing me (rooms only) */ + struct parse_node *in_region_set_at; /* where this is decided */ + struct inter_name *in_region_iname; /* for testing regional containment found-ins */ + CLASS_DEFINITION +} regions_data; + +int Regions::new_subject_notify(inference_subject *subj) { + regions_data *rd = CREATE(regions_data); + rd->in_region = NULL; + rd->in_region_set_at = NULL; + rd->in_region_iname = NULL; + ATTACH_PLUGIN_DATA_TO_SUBJECT(regions, subj, rd); + return FALSE; +} + +@ This is a property name to do with regions which Inform provides special support for; it recognises the English name when it is defined by the Standard Rules. (So there is no need to translate this to other languages.) @@ -150,18 +154,18 @@ Standard Rules. (So there is no need to translate this to other languages.) map region @ = -int PL::Regions::regions_new_property_notify(property *prn) { +property *P_map_region = NULL; /* a value property giving the region of a room */ +int Regions::new_property_notify(property *prn) { if ((prn->name)) P_map_region = prn; return FALSE; } -@h Assertions. -The following doesn't really intervene at all: it simply produces two problem +@ The following doesn't really intervene at all: it simply produces two problem messages which would have been less helpful if core Inform had produced them. = -int PL::Regions::regions_intervene_in_assertion(parse_node *px, parse_node *py) { +int Regions::intervene_in_assertion(parse_node *px, parse_node *py) { if ((Node::get_type(px) == PROPER_NOUN_NT) && (Node::get_type(py) == COMMON_NOUN_NT)) { inference_subject *left_subject = Node::get_subject(px); @@ -199,110 +203,10 @@ int PL::Regions::regions_intervene_in_assertion(parse_node *px, parse_node *py) return FALSE; } -@h Relations. +@ Model completion: = -int PL::Regions::regions_name_to_early_infs(wording W, inference_subject **infs) { - if (((W)) && (K_region == NULL)) *infs = infs_region; - return FALSE; -} - -@ = -void PL::Regions::create_relations(void) { - R_regional_containment = - BinaryPredicates::make_pair(spatial_bp_family, - BPTerms::new(infs_region), - BPTerms::new(KindSubjects::from_kind(K_object)), - I"region-contains", I"in-region", - NULL, Calculus::Schemas::new("TestRegionalContainment(*2,*1)"), - PreformUtilities::wording(, - REGIONAL_CONTAINMENT_RELATION_NAME)); - BinaryPredicates::set_index_details(R_regional_containment, NULL, "room/region"); -} - -@ We intervene only in limited cases: X contains Y, X regionally contains Y, -or X incorporates Y; and only when X is a region. (This of course only -applies to the built-in spatial relationships; regions are entirely free -to participate in nonspatial relations.) - -= -int PL::Regions::assert_relations(binary_predicate *relation, - instance *I0, instance *I1) { - int I0_is_region = FALSE; - if (Instances::of_kind(I0, K_region)) I0_is_region = TRUE; - int I1_is_region = FALSE; - if (Instances::of_kind(I1, K_region)) I1_is_region = TRUE; - - if (I0_is_region) { - if ((relation == R_incorporation) || - (relation == R_containment) || - (relation == R_regional_containment)) { - @; - if (I1_is_region) @ - else @; - } else { - StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RegionRelation), - "regions can only contain rooms", - "and have no other relationships."); - } - return TRUE; - } else if (I1_is_region) { - if ((relation == R_incorporation) || - (relation == R_containment) || - (relation == R_regional_containment)) { - StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RegionRelation2), - "regions can only be contained in other regions", - "and not for example in rooms."); - } - } - - return FALSE; -} - -@ = - if ((REGIONS_DATA(I1)->in_region) && - (REGIONS_DATA(I1)->in_region != I0)) { - StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RegionInTwoRegions), - "each region can only be declared to be inside a single " - "other region", - "since although regions can be placed inside each other, " - "they are not permitted to overlap."); - return TRUE; - } - REGIONS_DATA(I1)->in_region = I0; - REGIONS_DATA(I1)->in_region_set_at = current_sentence; - -@ = - inference_subject *inner = Instances::as_subject(I1); - inference_subject *outer = Instances::as_subject(I0); - SpatialInferences::infer_parentage(inner, CERTAIN_CE, outer); - -@ Anything in or part of a region is necessarily a room, if it isn't known -to be a region already: - -@ = - inference_subject *rm = Instances::as_subject(I1); - parse_node *spec = Rvalues::from_instance(I0); - Propositions::Abstract::assert_kind_of_instance(I1, K_room); - PropertyInferences::draw(rm, P_map_region, spec); - -@ Note that because we use regular |PARENTAGE_INF| inferences to remember -that one region is inside another, it follows that the progenitor of a -region is either the next broadest region containing it, or else |NULL|. - -= -instance *PL::Regions::enclosing(instance *reg) { - instance *P = NULL; - if (Spatial::object_is_a_room(reg)) P = REGIONS_DATA(reg)->in_region; - if (PL::Regions::object_is_a_region(reg)) P = Spatial::progenitor(reg); - if (PL::Regions::object_is_a_region(P) == FALSE) return NULL; - return P; -} - -@h Model completion. - -= -int PL::Regions::regions_complete_model(int stage) { +int Regions::complete_model(int stage) { if (stage == WORLD_STAGE_II) @; if (stage == WORLD_STAGE_III) @; return FALSE; @@ -329,45 +233,101 @@ int PL::Regions::regions_complete_model(int stage) { } @ = - P_regional_found_in = ValueProperties::new_nameless( + property *P_regional_found_in = ValueProperties::new_nameless( I"regional_found_in", K_text); instance *I; LOOP_OVER_INSTANCES(I, K_object) if (Instances::of_kind(I, K_region)) { - inter_name *iname = PL::Regions::found_in_iname(I); + inter_name *iname = RTRegions::found_in_iname(I); ValueProperties::assert(P_regional_found_in, Instances::as_subject(I), Rvalues::from_iname(iname), CERTAIN_CE); } -@ = -void PL::Regions::write_regional_found_in_routines(void) { - instance *I; - LOOP_OVER_INSTANCES(I, K_object) - if (Instances::of_kind(I, K_region)) { - inter_name *iname = PL::Regions::found_in_iname(I); - packaging_state save = Routines::begin(iname); - Produce::inv_primitive(Emit::tree(), IF_BIP); - Produce::down(Emit::tree()); - Produce::inv_call_iname(Emit::tree(), Hierarchy::find(TESTREGIONALCONTAINMENT_HL)); - Produce::down(Emit::tree()); - Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(LOCATION_HL)); - Produce::val_iname(Emit::tree(), K_object, RTInstances::iname(I)); - Produce::up(Emit::tree()); - Produce::code(Emit::tree()); - Produce::down(Emit::tree()); - Produce::rtrue(Emit::tree()); - Produce::up(Emit::tree()); - Produce::up(Emit::tree()); - Produce::rfalse(Emit::tree()); - Routines::end(save); - } -} +@ The relation "R in S" behaves so differently for regions that we need to +define it separately, even though there's no difference in English syntax. So: + += (early code) +binary_predicate *R_regional_containment = NULL; @ = -int PL::Regions::regions_add_to_World_index(OUTPUT_STREAM, instance *O) { - if ((O) && (Instances::of_kind(O, K_room))) { - instance *R = PL::Regions::enclosing(O); - if (R) PL::HTMLMap::colour_chip(OUT, O, R, REGIONS_DATA(O)->in_region_set_at); +void Regions::create_relations(void) { + R_regional_containment = + BinaryPredicates::make_pair(spatial_bp_family, + BPTerms::new(infs_region), + BPTerms::new(KindSubjects::from_kind(K_object)), + I"region-contains", I"in-region", + NULL, Calculus::Schemas::new("TestRegionalContainment(*2,*1)"), + PreformUtilities::wording(, + REGIONAL_CONTAINMENT_RELATION_NAME)); + BinaryPredicates::set_index_details(R_regional_containment, NULL, "room/region"); +} + +@ We intervene only in limited cases: X contains Y, X regionally contains Y, +or X incorporates Y; and only when X is a region. (This of course only +applies to the built-in spatial relationships; regions are entirely free +to participate in nonspatial relations.) + += +int Regions::assert_relations(binary_predicate *relation, + instance *I0, instance *I1) { + int I0_is_region = FALSE; + if (Instances::of_kind(I0, K_region)) I0_is_region = TRUE; + int I1_is_region = FALSE; + if (Instances::of_kind(I1, K_region)) I1_is_region = TRUE; + + if (I0_is_region) { + if ((relation == R_incorporation) || + (relation == R_containment) || + (relation == R_regional_containment)) { + @; + if (I1_is_region) @ + else @; + } else { + StandardProblems::sentence_problem(Task::syntax_tree(), + _p_(PM_RegionRelation), + "regions can only contain rooms", + "and have no other relationships."); + } + return TRUE; + } else if (I1_is_region) { + if ((relation == R_incorporation) || + (relation == R_containment) || + (relation == R_regional_containment)) { + StandardProblems::sentence_problem(Task::syntax_tree(), + _p_(PM_RegionRelation2), + "regions can only be contained in other regions", + "and not for example in rooms."); + } } + return FALSE; } + +@ = + if ((REGIONS_DATA(I1)->in_region) && + (REGIONS_DATA(I1)->in_region != I0)) { + StandardProblems::sentence_problem(Task::syntax_tree(), + _p_(PM_RegionInTwoRegions), + "each region can only be declared to be inside a single " + "other region", + "since although regions can be placed inside each other, " + "they are not permitted to overlap."); + return TRUE; + } + REGIONS_DATA(I1)->in_region = I0; + REGIONS_DATA(I1)->in_region_set_at = current_sentence; + +@ = + inference_subject *inner = Instances::as_subject(I1); + inference_subject *outer = Instances::as_subject(I0); + SpatialInferences::infer_parentage(inner, CERTAIN_CE, outer); + +@ Anything in or part of a region is necessarily a room, if it isn't known +to be a region already: + +@ = + inference_subject *rm = Instances::as_subject(I1); + parse_node *spec = Rvalues::from_instance(I0); + Propositions::Abstract::assert_kind_of_instance(I1, K_room); + PropertyInferences::draw(rm, P_map_region, spec); + diff --git a/inform7/if-module/Chapter 3/Spatial Map.w b/inform7/if-module/Chapter 3/Spatial Map.w index e6715bef7..da1c0f412 100644 --- a/inform7/if-module/Chapter 3/Spatial Map.w +++ b/inform7/if-module/Chapter 3/Spatial Map.w @@ -2498,8 +2498,8 @@ int PL::SpatialMap::compare_components(const void *ent1, const void *ent2) { instance *R1 = mc1->first_room_in_submap; instance *R2 = mc2->first_room_in_submap; if ((R1) && (R2)) { /* which should always happen, but just in case of an error */ - instance *reg1 = PL::Regions::enclosing(R1); - instance *reg2 = PL::Regions::enclosing(R2); + instance *reg1 = Regions::enclosing(R1); + instance *reg2 = Regions::enclosing(R2); if ((reg1) && (reg2 == NULL)) return -1; if ((reg1 == NULL) && (reg2)) return 1; if (reg1) { @@ -2622,12 +2622,12 @@ running time in check. if (sub->bounds.population == 1) { instance *R = sub->first_room_in_submap; if (R) { /* which should always happen, but just in case of an error */ - instance *reg = PL::Regions::enclosing(R); + instance *reg = Regions::enclosing(R); if (reg) { instance *S, *closest_S = NULL; int closest = 0; LOOP_OVER_ROOMS(S) - if ((S != R) && (PL::Regions::enclosing(S) == reg)) + if ((S != R) && (Regions::enclosing(S) == reg)) if ((posnd == FALSE) || (MAP_DATA(S)->submap->positioned)) { int diff = 2*(R->allocation_id - S->allocation_id); if (diff < 0) diff = 1-diff; @@ -2759,7 +2759,7 @@ void PL::SpatialMap::log_precis_of_map(void) { if (Instances::of_kind(R, K_room)) { wording RW = Instances::get_name(R, FALSE); LOG("%+W is a room.\n", RW); - instance *reg = PL::Regions::enclosing(R); + instance *reg = Regions::enclosing(R); if (reg) { wording RGW = Instances::get_name(reg, FALSE); if (MAP_DATA(reg)->zone == 1) { diff --git a/inform7/if-module/Chapter 3/Spatial Model.w b/inform7/if-module/Chapter 3/Spatial Model.w index 865a4bbaa..eb77542a5 100644 --- a/inform7/if-module/Chapter 3/Spatial Model.w +++ b/inform7/if-module/Chapter 3/Spatial Model.w @@ -703,7 +703,7 @@ int Spatial::spatial_stage_II(void) { if ((Spatial::progenitor(I)) && (Instances::of_kind(I, K_thing) == FALSE) && (Instances::of_kind(I, K_room) == FALSE) && - (PL::Regions::object_is_a_region(I) == FALSE)) { + (Regions::object_is_a_region(I) == FALSE)) { Problems::quote_source(1, Instances::get_creating_sentence(I)); Problems::quote_object(2, I); Problems::quote_object(3, Spatial::progenitor(I)); diff --git a/inform7/if-module/Chapter 3/Spatial Relations.w b/inform7/if-module/Chapter 3/Spatial Relations.w index 9c2a311e7..2683b5f9e 100644 --- a/inform7/if-module/Chapter 3/Spatial Relations.w +++ b/inform7/if-module/Chapter 3/Spatial Relations.w @@ -36,7 +36,7 @@ void SpatialRelations::stock(bp_family *self, int n) { @; @; PL::MapDirections::create_relations(); - PL::Regions::create_relations(); + Regions::create_relations(); } } @@ -207,7 +207,7 @@ way which isn't symmetrical between the two, and this way round is cleanest. @ = if (Backdrops::assert_relations(bp, I0, I1)) return TRUE; if (PL::MapDirections::assert_relations(bp, I0, I1)) return TRUE; - if (PL::Regions::assert_relations(bp, I0, I1)) return TRUE; + if (Regions::assert_relations(bp, I0, I1)) return TRUE; @ This is the point at which non-assertable relations are thrown out. diff --git a/inform7/index-module/Chapter 2/Index Physical World.w b/inform7/index-module/Chapter 2/Index Physical World.w index 98c93c358..e9b72d080 100644 --- a/inform7/index-module/Chapter 2/Index Physical World.w +++ b/inform7/index-module/Chapter 2/Index Physical World.w @@ -72,13 +72,13 @@ void Data::Objects::page_World(OUTPUT_STREAM) { @ = instance *reg; LOOP_OVER_INSTANCES(reg, K_object) - if (PL::Regions::object_is_a_region(reg)) { + if (Regions::object_is_a_region(reg)) { int subheaded = FALSE; IXInstances::increment_indexing_count(reg); instance *rm; LOOP_OVER_INSTANCES(rm, K_object) if ((Spatial::object_is_a_room(rm)) && - (PL::Regions::enclosing(rm) == reg)) { + (Regions::enclosing(rm) == reg)) { if (subheaded == FALSE) { @; @; @@ -93,7 +93,7 @@ void Data::Objects::page_World(OUTPUT_STREAM) { @ = WRITE("The %+W region", Instances::get_name(reg, FALSE)); - instance *within = PL::Regions::enclosing(reg); + instance *within = Regions::enclosing(reg); if (within) WRITE(" within the %+W region", Instances::get_name(within, FALSE)); WRITE(""); diff --git a/inform7/index-module/Chapter 3/Regions.w b/inform7/index-module/Chapter 3/Regions.w new file mode 100644 index 000000000..edfbaf668 --- /dev/null +++ b/inform7/index-module/Chapter 3/Regions.w @@ -0,0 +1,14 @@ +[IXRegions::] Regions. + +Indexing the player's initial position. + +@ + += +int IXRegions::add_to_World_index(OUTPUT_STREAM, instance *O) { + if ((O) && (Instances::of_kind(O, K_room))) { + instance *R = Regions::enclosing(O); + if (R) PL::HTMLMap::colour_chip(OUT, O, R, REGIONS_DATA(O)->in_region_set_at); + } + return FALSE; +} diff --git a/inform7/index-module/Contents.w b/inform7/index-module/Contents.w index 0d54f7b20..409d23fa6 100644 --- a/inform7/index-module/Contents.w +++ b/inform7/index-module/Contents.w @@ -30,3 +30,4 @@ Chapter 3: Indexing for Plugins Spatial The Player Backdrops + Regions diff --git a/inform7/runtime-module/Chapter 5/Regions.w b/inform7/runtime-module/Chapter 5/Regions.w new file mode 100644 index 000000000..d02a43ee9 --- /dev/null +++ b/inform7/runtime-module/Chapter 5/Regions.w @@ -0,0 +1,37 @@ +[RTRegions::] Regions. + +@ + += +inter_name *RTRegions::found_in_iname(instance *I) { + if (REGIONS_DATA(I)->in_region_iname == NULL) + REGIONS_DATA(I)->in_region_iname = + Hierarchy::make_iname_in(REGION_FOUND_IN_FN_HL, RTInstances::package(I)); + return REGIONS_DATA(I)->in_region_iname; +} + +@ = +void RTRegions::write_found_in_functions(void) { + instance *I; + LOOP_OVER_INSTANCES(I, K_object) + if (Instances::of_kind(I, K_region)) { + inter_name *iname = RTRegions::found_in_iname(I); + packaging_state save = Routines::begin(iname); + Produce::inv_primitive(Emit::tree(), IF_BIP); + Produce::down(Emit::tree()); + Produce::inv_call_iname(Emit::tree(), + Hierarchy::find(TESTREGIONALCONTAINMENT_HL)); + Produce::down(Emit::tree()); + Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(LOCATION_HL)); + Produce::val_iname(Emit::tree(), K_object, RTInstances::iname(I)); + Produce::up(Emit::tree()); + Produce::code(Emit::tree()); + Produce::down(Emit::tree()); + Produce::rtrue(Emit::tree()); + Produce::up(Emit::tree()); + Produce::up(Emit::tree()); + Produce::rfalse(Emit::tree()); + Routines::end(save); + } +} + diff --git a/inform7/runtime-module/Contents.w b/inform7/runtime-module/Contents.w index 01cb0abc3..038289604 100644 --- a/inform7/runtime-module/Contents.w +++ b/inform7/runtime-module/Contents.w @@ -68,3 +68,4 @@ Chapter 5: Plugin Support Spatial The Player Backdrops + Regions