mirror of
https://github.com/ganelson/inform.git
synced 2024-06-30 22:14:58 +03:00
Starting beats and required speaker lists
This commit is contained in:
parent
c78c8a5322
commit
54d9e0404a
|
@ -1,6 +1,6 @@
|
|||
# Inform 7
|
||||
|
||||
[Version](notes/versioning.md): 10.2.0-beta+6V68 'Krypton' (22 September 2022)
|
||||
[Version](notes/versioning.md): 10.2.0-beta+6V69 'Krypton' (23 September 2022)
|
||||
|
||||
## About Inform
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Prerelease: beta
|
||||
Build Date: 22 September 2022
|
||||
Build Number: 6V68
|
||||
Build Date: 23 September 2022
|
||||
Build Number: 6V69
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"is": {
|
||||
"type": "kit",
|
||||
"title": "BasicInformExtrasKit",
|
||||
"version": "10.2.0-beta+6V68"
|
||||
"version": "10.2.0-beta+6V69"
|
||||
},
|
||||
"kit-details": {
|
||||
"has-priority": 1
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"is": {
|
||||
"type": "kit",
|
||||
"title": "BasicInformKit",
|
||||
"version": "10.2.0-beta+6V68"
|
||||
"version": "10.2.0-beta+6V69"
|
||||
},
|
||||
"needs": [ {
|
||||
"unless": {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"is": {
|
||||
"type": "kit",
|
||||
"title": "CommandParserKit",
|
||||
"version": "10.2.0-beta+6V68"
|
||||
"version": "10.2.0-beta+6V69"
|
||||
},
|
||||
"needs": [ {
|
||||
"need": {
|
||||
|
|
|
@ -113,6 +113,12 @@ Array DirectorStackStart --> MAX_BEAT_PERFORMANCE_NESTING;
|
|||
}
|
||||
];
|
||||
|
||||
[ PERFORM_OPENING_BEAT_R db;
|
||||
db = InitialSituation-->START_BEAT_INIS;
|
||||
if (db) DirectorPerform(db);
|
||||
rfalse;
|
||||
];
|
||||
|
||||
[ DirectorTraceInst structure pc instruction depth;
|
||||
];
|
||||
|
||||
|
@ -609,7 +615,7 @@ Global director_is_active = false;
|
|||
if ((GProperty(DIALOGUE_BEAT_TY, db, performed) == 0) ||
|
||||
(GProperty(DIALOGUE_BEAT_TY, db, recurring))) {
|
||||
tab = TableOfDialogueBeats-->db;
|
||||
i = 3;
|
||||
i = 4;
|
||||
while (true) {
|
||||
speaker = tab-->i;
|
||||
if (speaker == nothing) rtrue;
|
||||
|
@ -620,6 +626,23 @@ Global director_is_active = false;
|
|||
rfalse;
|
||||
];
|
||||
|
||||
[ DirectorLiveRequiredList list db len i tab speaker;
|
||||
if ((list==0) || (BlkValueWeakKind(list) ~= LIST_OF_TY)) return 0;
|
||||
len = 0;
|
||||
tab = TableOfDialogueBeats-->db;
|
||||
i = 4;
|
||||
while (true) {
|
||||
speaker = tab-->i;
|
||||
if (speaker == nothing) break;
|
||||
len++;
|
||||
i++;
|
||||
}
|
||||
LIST_OF_TY_SetLength(list, len);
|
||||
for (i=0: i<len: i++)
|
||||
LIST_OF_TY_PutItem(list, i+1, tab-->(i+4));
|
||||
return list;
|
||||
];
|
||||
|
||||
[ DIALOGUE_DIRECTION_R db i topic fn tab;
|
||||
if (director_is_active == false) rfalse;
|
||||
! If nothing much has happened this turn...
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2,7 +2,7 @@
|
|||
"is": {
|
||||
"type": "kit",
|
||||
"title": "EnglishLanguageKit",
|
||||
"version": "10.2.0-beta+6V68"
|
||||
"version": "10.2.0-beta+6V69"
|
||||
},
|
||||
"needs": [ {
|
||||
"need": {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"is": {
|
||||
"type": "kit",
|
||||
"title": "WorldModelKit",
|
||||
"version": "10.2.0-beta+6V68"
|
||||
"version": "10.2.0-beta+6V69"
|
||||
},
|
||||
"needs": [ {
|
||||
"need": {
|
||||
|
|
|
@ -35,5 +35,6 @@ PM_ChoiceDashDashExpected
|
|||
PM_ChoiceLeftArrowExpected
|
||||
PM_ChoiceRightArrowExpected
|
||||
PM_InstancesExplicit
|
||||
PM_NotASpeaker
|
||||
DialogueBeats
|
||||
LBW
|
||||
|
|
7
inform7/Tests/Test Problems/PM_NotASpeaker.txt
Normal file
7
inform7/Tests/Test Problems/PM_NotASpeaker.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
The Cricket History Museum is a room.
|
||||
|
||||
Section 1 - Arrival (dialogue)
|
||||
|
||||
(This is the starting beat. Requiring Felicity Dumplings and Mike Atherton.)
|
||||
|
||||
Narration: "There is a sinister chime, as if this museum is in fact run by Spectre."
|
|
@ -0,0 +1,17 @@
|
|||
Inform 7 v10.2.0 has started.
|
||||
I've now read your source text, which is 39 words long.
|
||||
I've also read Basic Inform by Graham Nelson, which is 7691 words long.
|
||||
I've also read English Language by Graham Nelson, which is 2328 words long.
|
||||
I've also read Standard Rules by Graham Nelson, which is 32643 words long.
|
||||
Problem__ PM_NotASpeaker
|
||||
In Section 1 - Arrival:
|
||||
>--> The dialogue beat '(This is the starting beat . Requiring Felicity
|
||||
Dumplings and Mike Atherton .)' (source text, line 5) apparently requires a
|
||||
speaker (other than the player) called 'Felicity Dumplings' to be present
|
||||
in order for it to be performed, but there's nobody of that name.
|
||||
Problem__ PM_NotASpeaker
|
||||
>--> The dialogue beat '(This is the starting beat . Requiring Felicity
|
||||
Dumplings and Mike Atherton .)' (source text, line 5) apparently requires a
|
||||
speaker (other than the player) called 'Mike Atherton' to be present in
|
||||
order for it to be performed, but there's nobody of that name.
|
||||
Inform 7 has finished.
|
|
@ -1305,6 +1305,8 @@ To decide what list of objects is the live conversational subject list:
|
|||
(- DirectorLiveSubjectList({-new:list of objects}) -).
|
||||
To alter the live conversational subject list to (L - list of objects):
|
||||
(- DirectorAlterLiveSubjectList({-by-reference:L}); -).
|
||||
To decide what list of objects is the list of speakers required by (B - dialogue beat):
|
||||
(- DirectorLiveRequiredList({-new:list of objects}, {B}) -).
|
||||
|
||||
To perform (B - a dialogue beat):
|
||||
ask DialogueKit to perform B;
|
||||
|
@ -1345,6 +1347,9 @@ To make the dialogue/dialog director passive/inactive:
|
|||
The dialogue direction rule is listed in the turn sequence rulebook.
|
||||
The dialogue direction rule translates into Inter as "DIALOGUE_DIRECTION_R".
|
||||
|
||||
The performing opening dialogue beat rule is listed in the startup rulebook.
|
||||
The performing opening dialogue beat rule translates into Inter as "PERFORM_OPENING_BEAT_R".
|
||||
|
||||
Section 10 - Dialogue Fallback (not for dialogue language element)
|
||||
|
||||
To abide by dialogue before action choices:
|
||||
|
|
|
@ -145,6 +145,10 @@ wording Scenes::get_name(scene *sc) {
|
|||
return Instances::get_name(sc->as_instance, FALSE);
|
||||
}
|
||||
|
||||
instance *Scenes::get_instance(scene *sc) {
|
||||
return sc->as_instance;
|
||||
}
|
||||
|
||||
@ A feature called |xyzzy| generally has a hunk of subject data called |xyzzy_data|,
|
||||
so we would normally have a structure called |scenes_data|, but in fact that
|
||||
structure is just going to be //scene//. So:
|
||||
|
|
|
@ -83,7 +83,9 @@ typedef struct dialogue_beat {
|
|||
struct heading *under_heading;
|
||||
struct instance *as_instance;
|
||||
struct scene *as_scene;
|
||||
|
||||
struct linked_list *required; /* of |instance| */
|
||||
int starting_beat;
|
||||
|
||||
struct parse_node *immediately_after;
|
||||
struct linked_list *some_time_after; /* of |parse_node| */
|
||||
struct linked_list *some_time_before; /* of |parse_node| */
|
||||
|
@ -101,6 +103,8 @@ typedef struct dialogue_beat {
|
|||
db->under_heading = dialogue_section_being_scanned;
|
||||
db->as_instance = NULL;
|
||||
db->as_scene = NULL;
|
||||
db->required = NEW_LINKED_LIST(instance);
|
||||
db->starting_beat = FALSE;
|
||||
db->immediately_after = NULL;
|
||||
db->some_time_after = NEW_LINKED_LIST(parse_node);
|
||||
db->some_time_before = NEW_LINKED_LIST(parse_node);
|
||||
|
@ -125,6 +129,7 @@ We annotate each clause with the answer. Thus we might have:
|
|||
@e AFTER_DBC
|
||||
@e IMMEDIATELY_AFTER_DBC
|
||||
@e BEFORE_DBC
|
||||
@e REQUIRING_DBC
|
||||
@e LATER_DBC
|
||||
@e NEXT_DBC
|
||||
@e PROPERTY_DBC
|
||||
|
@ -150,10 +155,14 @@ We annotate each clause with the answer. Thus we might have:
|
|||
after ... | ==> { AFTER_DBC, - }
|
||||
immediately after ... | ==> { IMMEDIATELY_AFTER_DBC, - }
|
||||
before ... | ==> { BEFORE_DBC, - }
|
||||
requiring ... | ==> { REQUIRING_DBC, - }
|
||||
later | ==> { LATER_DBC, - }
|
||||
next | ==> { NEXT_DBC, - }
|
||||
... ==> { PROPERTY_DBC, - }
|
||||
|
||||
<dialogue-beat-starting-name> ::=
|
||||
starting beat
|
||||
|
||||
@ It's convenient to be able to read this back in the debugging log, so:
|
||||
|
||||
=
|
||||
|
@ -167,6 +176,7 @@ void DialogueBeats::write_dbc(OUTPUT_STREAM, int c) {
|
|||
case AFTER_DBC: WRITE("AFTER"); break;
|
||||
case IMMEDIATELY_AFTER_DBC: WRITE("IMMEDIATELY_AFTER"); break;
|
||||
case BEFORE_DBC: WRITE("BEFORE"); break;
|
||||
case REQUIRING_DBC: WRITE("REQUIRING"); break;
|
||||
case LATER_DBC: WRITE("LATER"); break;
|
||||
case NEXT_DBC: WRITE("NEXT"); break;
|
||||
case PROPERTY_DBC: WRITE("PROPERTY"); break;
|
||||
|
@ -191,6 +201,8 @@ but not of course both. If the latter, we construct the beat name itself as
|
|||
DialogueBeats::non_unique_instance_problem(I, K_dialogue_beat);
|
||||
} else {
|
||||
current_dialogue_beat->beat_name = NW;
|
||||
if (<dialogue-beat-starting-name>(NW))
|
||||
current_dialogue_beat->starting_beat = TRUE;
|
||||
}
|
||||
dialogue_beat_name_count++;
|
||||
break;
|
||||
|
@ -325,6 +337,14 @@ performed only after or before other beats.
|
|||
DialogueBeats::parse_beat_list(c, db, AL, &iac);
|
||||
break;
|
||||
}
|
||||
case REQUIRING_DBC: {
|
||||
<dialogue-beat-clause>(CW);
|
||||
wording A = GET_RW(<dialogue-beat-clause>, 1);
|
||||
<np-articled-list>(A);
|
||||
parse_node *AL = <<rp>>;
|
||||
DialogueBeats::parse_required_speaker_list(db, AL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iac > 1)
|
||||
|
@ -353,7 +373,7 @@ void DialogueBeats::parse_beat_list(int c, dialogue_beat *db, parse_node *AL, in
|
|||
} else if (Node::is(AL, UNPARSED_NOUN_NT)) {
|
||||
switch(c) {
|
||||
case IMMEDIATELY_AFTER_DBC: {
|
||||
wording B = GET_RW(<dialogue-beat-clause>, 1);
|
||||
wording B = Node::get_text(AL);
|
||||
parse_node *desc = DialogueBeats::parse_beat_name(B);
|
||||
if (desc) {
|
||||
(*iac)++;
|
||||
|
@ -362,13 +382,13 @@ void DialogueBeats::parse_beat_list(int c, dialogue_beat *db, parse_node *AL, in
|
|||
break;
|
||||
}
|
||||
case AFTER_DBC: {
|
||||
wording B = GET_RW(<dialogue-beat-clause>, 1);
|
||||
wording B = Node::get_text(AL);
|
||||
parse_node *desc = DialogueBeats::parse_beat_name(B);
|
||||
if (desc) ADD_TO_LINKED_LIST(desc, parse_node, db->some_time_after);
|
||||
break;
|
||||
}
|
||||
case BEFORE_DBC: {
|
||||
wording B = GET_RW(<dialogue-beat-clause>, 1);
|
||||
wording B = Node::get_text(AL);
|
||||
parse_node *desc = DialogueBeats::parse_beat_name(B);
|
||||
if (desc) ADD_TO_LINKED_LIST(desc, parse_node, db->some_time_before);
|
||||
break;
|
||||
|
@ -377,6 +397,34 @@ void DialogueBeats::parse_beat_list(int c, dialogue_beat *db, parse_node *AL, in
|
|||
}
|
||||
}
|
||||
|
||||
void DialogueBeats::parse_required_speaker_list(dialogue_beat *db, parse_node *AL) {
|
||||
if (Node::is(AL, AND_NT)) {
|
||||
DialogueBeats::parse_required_speaker_list(db, AL->down);
|
||||
DialogueBeats::parse_required_speaker_list(db, AL->down->next);
|
||||
} else if (Node::is(AL, UNPARSED_NOUN_NT)) {
|
||||
wording B = Node::get_text(AL);
|
||||
if (<s-type-expression-uncached>(B)) {
|
||||
parse_node *desc = <<rp>>;
|
||||
instance *I = Rvalues::to_instance(desc);
|
||||
if (I) {
|
||||
kind *K = Instances::to_kind(I);
|
||||
if (Kinds::Behaviour::is_object(K)) {
|
||||
ADD_TO_LINKED_LIST(I, instance, db->required);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Problems::quote_source(1, current_sentence);
|
||||
Problems::quote_wording(2, B);
|
||||
StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NotASpeaker));
|
||||
Problems::issue_problem_segment(
|
||||
"The dialogue beat %1 apparently requires a speaker (other than the player) "
|
||||
"called '%2' to be present in order for it to be performed, but there's "
|
||||
"nobody of that name.");
|
||||
Problems::issue_problem_end();
|
||||
}
|
||||
}
|
||||
|
||||
parse_node *DialogueBeats::parse_beat_name(wording CW) {
|
||||
if (<s-type-expression-uncached>(CW)) {
|
||||
parse_node *desc = <<rp>>;
|
||||
|
|
|
@ -1111,6 +1111,7 @@ void Hierarchy::establish(void) {
|
|||
@e START_OBJECT_INIS_HL
|
||||
@e START_ROOM_INIS_HL
|
||||
@e START_TIME_INIS_HL
|
||||
@e START_BEAT_INIS_HL
|
||||
@e DONE_INIS_HL
|
||||
|
||||
@e NO_DIRECTIONS_HL
|
||||
|
@ -1125,6 +1126,7 @@ void Hierarchy::establish(void) {
|
|||
H_C_T(START_OBJECT_INIS_HL, I"START_OBJECT_INIS")
|
||||
H_C_T(START_ROOM_INIS_HL, I"START_ROOM_INIS")
|
||||
H_C_T(START_TIME_INIS_HL, I"START_TIME_INIS")
|
||||
H_C_T(START_BEAT_INIS_HL, I"START_BEAT_INIS")
|
||||
H_C_T(DONE_INIS_HL, I"DONE_INIS")
|
||||
H_END
|
||||
|
||||
|
|
|
@ -93,6 +93,17 @@ void RTDialogueBeats::compile(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void RTDialogueBeats::compile_starting_beat_entry(void) {
|
||||
dialogue_beat *db, *starting_db = NULL;
|
||||
LOOP_OVER(db, dialogue_beat) {
|
||||
if (db->starting_beat) starting_db = db;
|
||||
}
|
||||
if (starting_db)
|
||||
EmitArrays::iname_entry(RTInstances::value_iname(starting_db->as_instance));
|
||||
else
|
||||
EmitArrays::numeric_entry(0);
|
||||
}
|
||||
|
||||
void RTDialogueBeats::beat_compilation_agent(compilation_subtask *ct) {
|
||||
dialogue_beat *db = RETRIEVE_POINTER_dialogue_beat(ct->data);
|
||||
current_sentence = db->compilation_data.where_created;
|
||||
|
@ -105,6 +116,7 @@ void RTDialogueBeats::beat_compilation_agent(compilation_subtask *ct) {
|
|||
@<Write the availability entry@>;
|
||||
@<Write the relevance entry@>;
|
||||
@<Write the structure entry@>;
|
||||
@<Write the scene entry@>;
|
||||
@<Write the speaker list@>;
|
||||
EmitArrays::end(save);
|
||||
|
||||
|
@ -140,9 +152,18 @@ void RTDialogueBeats::beat_compilation_agent(compilation_subtask *ct) {
|
|||
@<Write the structure entry@> =
|
||||
EmitArrays::iname_entry(RTDialogueBeats::structure_array_iname(db));
|
||||
|
||||
@<Write the scene entry@> =
|
||||
if (db->as_scene)
|
||||
EmitArrays::iname_entry(RTInstances::value_iname(Scenes::get_instance(db->as_scene)));
|
||||
else
|
||||
EmitArrays::numeric_entry(0);
|
||||
|
||||
@<Write the speaker list@> =
|
||||
linked_list *L = NEW_LINKED_LIST(instance);
|
||||
RTDialogueBeats::find_speakers_r(L, db->root);
|
||||
linked_list *L = db->required;
|
||||
if (LinkedLists::len(L) == 0) {
|
||||
L = NEW_LINKED_LIST(instance);
|
||||
RTDialogueBeats::find_speakers_r(L, db->root);
|
||||
}
|
||||
instance *I;
|
||||
LOOP_OVER_LINKED_LIST(I, instance, L)
|
||||
EmitArrays::iname_entry(RTInstances::value_iname(I));
|
||||
|
|
|
@ -8,7 +8,8 @@ void RTPlayer::compile_generic_constants(void) {
|
|||
RTPlayer::InitialSituation_define(START_OBJECT_INIS_HL, 1);
|
||||
RTPlayer::InitialSituation_define(START_ROOM_INIS_HL, 2);
|
||||
RTPlayer::InitialSituation_define(START_TIME_INIS_HL, 3);
|
||||
RTPlayer::InitialSituation_define(DONE_INIS_HL, 4);
|
||||
RTPlayer::InitialSituation_define(START_BEAT_INIS_HL, 4);
|
||||
RTPlayer::InitialSituation_define(DONE_INIS_HL, 5);
|
||||
}
|
||||
|
||||
void RTPlayer::InitialSituation(void) {
|
||||
|
@ -20,6 +21,7 @@ void RTPlayer::InitialSituation(void) {
|
|||
if (start_room == NULL) EmitArrays::numeric_entry(0);
|
||||
else EmitArrays::iname_entry(RTInstances::value_iname(start_room));
|
||||
RTVariables::initial_value_as_array_entry(time_of_day_VAR);
|
||||
RTDialogueBeats::compile_starting_beat_entry();
|
||||
EmitArrays::numeric_entry(0);
|
||||
EmitArrays::end(save);
|
||||
Hierarchy::make_available(iname);
|
||||
|
|
Loading…
Reference in a new issue