1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/inter/index-module/Chapter 2/Faux Scenes.w
2022-01-04 23:10:34 +00:00

189 lines
6.1 KiB
OpenEdge ABL

[FauxScenes::] Faux Scenes.
Creating a simple graph of scenes, ends and connectors.
@ As with //Faux Instances//, we need to make faux scenes: these more or less
reconstruct the original data structures in Inform, though they are much less
annotated.
@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;
@ This three-deck structure of objects matches a similar hiersrchy of Inter
packages, where |_scene_connector| packages are inside |_scene_end| packages
which are inside |_scene| packages.
=
void FauxScenes::list_of_faux_scenes(index_session *session) {
linked_list *L = NEW_LINKED_LIST(simplified_scene);
session->list_of_scenes = L;
inter_tree *I = Indexing::get_tree(session);
tree_inventory *inv = Indexing::get_inventory(session);
TreeLists::sort(inv->scene_nodes, FauxScenes::scene_order);
TreeLists::sort(inv->rulebook_nodes, MakeSynopticModuleStage::module_order);
inter_package *scene_pack;
LOOP_OVER_INVENTORY_PACKAGES(scene_pack, i, inv->scene_nodes)
ADD_TO_LINKED_LIST(FauxScenes::simplified(I, scene_pack), simplified_scene, L);
}
@ 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 FauxScenes::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);
}
@ The following returns a valid |simplified_scene| for each |_scene| package,
tpgether with its connectors and ends.
=
simplified_scene *FauxScenes::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_package *end_pack;
LOOP_THROUGH_SUBPACKAGES(end_pack, sc_pack, I"_scene_end") {
simplified_end *se = CREATE(simplified_end);
se->end_pack = end_pack;
se->anchor_connectors = NULL;
inter_package *con_pack;
LOOP_THROUGH_SUBPACKAGES(con_pack, end_pack, I"_scene_connector") {
simplified_connector *scon = CREATE(simplified_connector);
scon->con_pack = con_pack;
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 FauxScenes::is_entire_game(simplified_scene *ssc) {
if (Metadata::read_optional_numeric(ssc->pack, I"^is_entire_game")) return TRUE;
return FALSE;
}
int FauxScenes::recurs(simplified_scene *ssc) {
if (Metadata::read_optional_numeric(ssc->pack, I"^recurs")) return TRUE;
return FALSE;
}
int FauxScenes::never_ends(simplified_scene *ssc) {
if (Metadata::read_optional_numeric(ssc->pack, I"^never_ends")) return TRUE;
return FALSE;
}
int FauxScenes::starts_at_start_of_play(simplified_scene *ssc) {
if (Metadata::read_optional_numeric(ssc->pack, I"^starts")) return TRUE;
return FALSE;
}
int FauxScenes::starts_on_condition(simplified_scene *ssc) {
if (Metadata::read_optional_numeric(ssc->pack, I"^starts_on_condition")) return TRUE;
return FALSE;
}
int FauxScenes::no_ends(simplified_scene *ssc) {
return ssc->no_ends;
}
text_stream *FauxScenes::scene_name(simplified_scene *ssc) {
return Metadata::read_textual(ssc->pack, I"^name");
}
@ =
text_stream *FauxScenes::end_name(simplified_end *se) {
return Metadata::read_textual(se->end_pack, I"^name");
}
text_stream *FauxScenes::anchor_condition(simplified_end *se) {
return Metadata::read_textual(se->end_pack, I"^condition");
}
int FauxScenes::has_anchor_condition(simplified_end *se) {
if (Str::len(FauxScenes::anchor_condition(se)) > 0) return TRUE;
return FALSE;
}
int FauxScenes::anchor_condition_set_at(simplified_end *se) {
return (int) Metadata::read_optional_numeric(se->end_pack, I"^at");
}
inter_symbol *FauxScenes::end_rulebook(simplified_end *se) {
return Metadata::read_optional_symbol(se->end_pack, I"^rulebook");
}
@ A connector leads, of course, to another scene. Determiming that is quite
slow, but ww cache the result so that it must only be done once.
=
simplified_scene *FauxScenes::connects_to(simplified_connector *scon, index_session *session) {
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);
linked_list *L = Indexing::get_list_of_scenes(session);
simplified_scene *ssc;
LOOP_OVER_LINKED_LIST(ssc, simplified_scene, L)
if (ssc->pack == to_pack) {
scon->connect_to = ssc;
return ssc;
}
}
internal_error("scene metadata broken: bad connector");
return NULL;
}
int FauxScenes::scon_end(simplified_connector *scon) {
return (int) Metadata::read_numeric(scon->con_pack, I"^end");
}
int FauxScenes::scon_at(simplified_connector *scon) {
return (int) Metadata::read_numeric(scon->con_pack, I"^at");
}