aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/adrift/scnpcs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/adrift/scnpcs.cpp')
-rw-r--r--engines/glk/adrift/scnpcs.cpp950
1 files changed, 453 insertions, 497 deletions
diff --git a/engines/glk/adrift/scnpcs.cpp b/engines/glk/adrift/scnpcs.cpp
index ab11acc5ae..b9b60d5259 100644
--- a/engines/glk/adrift/scnpcs.cpp
+++ b/engines/glk/adrift/scnpcs.cpp
@@ -37,15 +37,13 @@ static sc_bool npc_trace = FALSE;
* Return TRUE if a given NPC is currently in a given room.
*/
sc_bool
-npc_in_room (sc_gameref_t game, sc_int npc, sc_int room)
-{
- if (npc_trace)
- {
- sc_trace ("NPC: checking NPC %ld in room %ld (NPC is in %ld)\n",
- npc, room, gs_npc_location (game, npc));
- }
-
- return gs_npc_location (game, npc) - 1 == room;
+npc_in_room(sc_gameref_t game, sc_int npc, sc_int room) {
+ if (npc_trace) {
+ sc_trace("NPC: checking NPC %ld in room %ld (NPC is in %ld)\n",
+ npc, room, gs_npc_location(game, npc));
+ }
+
+ return gs_npc_location(game, npc) - 1 == room;
}
@@ -55,20 +53,18 @@ npc_in_room (sc_gameref_t game, sc_int npc, sc_int room)
* Return the count of characters in the room, including the player.
*/
sc_int
-npc_count_in_room (sc_gameref_t game, sc_int room)
-{
- sc_int count, npc;
-
- /* Start with the player. */
- count = gs_player_in_room (game, room) ? 1 : 0;
-
- /* Total up other NPCs inhabiting the room. */
- for (npc = 0; npc < gs_npc_count (game); npc++)
- {
- if (gs_npc_location (game, npc) - 1 == room)
- count++;
- }
- return count;
+npc_count_in_room(sc_gameref_t game, sc_int room) {
+ sc_int count, npc;
+
+ /* Start with the player. */
+ count = gs_player_in_room(game, room) ? 1 : 0;
+
+ /* Total up other NPCs inhabiting the room. */
+ for (npc = 0; npc < gs_npc_count(game); npc++) {
+ if (gs_npc_location(game, npc) - 1 == room)
+ count++;
+ }
+ return count;
}
@@ -78,23 +74,22 @@ npc_count_in_room (sc_gameref_t game, sc_int room)
* Start the given walk for the given NPC.
*/
void
-npc_start_npc_walk (sc_gameref_t game, sc_int npc, sc_int walk)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[6];
- sc_int movetime;
-
- /* Retrieve movetime 0 for the NPC walk. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Walks";
- vt_key[3].integer = walk;
- vt_key[4].string = "MoveTimes";
- vt_key[5].integer = 0;
- movetime = prop_get_integer (bundle, "I<-sisisi", vt_key) + 1;
-
- /* Set up walkstep. */
- gs_set_npc_walkstep (game, npc, walk, movetime);
+npc_start_npc_walk(sc_gameref_t game, sc_int npc, sc_int walk) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[6];
+ sc_int movetime;
+
+ /* Retrieve movetime 0 for the NPC walk. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Walks";
+ vt_key[3].integer = walk;
+ vt_key[4].string = "MoveTimes";
+ vt_key[5].integer = 0;
+ movetime = prop_get_integer(bundle, "I<-sisisi", vt_key) + 1;
+
+ /* Set up walkstep. */
+ gs_set_npc_walkstep(game, npc, walk, movetime);
}
@@ -105,52 +100,47 @@ npc_start_npc_walk (sc_gameref_t game, sc_int npc, sc_int walk)
* Set initial values for NPC states, and update on turns.
*/
void
-npc_turn_update (sc_gameref_t game)
-{
- sc_int index_;
-
- /* Set current values for NPC seen states. */
- for (index_ = 0; index_ < gs_npc_count (game); index_++)
- {
- if (!gs_npc_seen (game, index_)
- && npc_in_room (game, index_, gs_playerroom (game)))
- gs_set_npc_seen (game, index_, TRUE);
- }
+npc_turn_update(sc_gameref_t game) {
+ sc_int index_;
+
+ /* Set current values for NPC seen states. */
+ for (index_ = 0; index_ < gs_npc_count(game); index_++) {
+ if (!gs_npc_seen(game, index_)
+ && npc_in_room(game, index_, gs_playerroom(game)))
+ gs_set_npc_seen(game, index_, TRUE);
+ }
}
void
-npc_setup_initial (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int index_;
-
- /* Start any walks that do not depend on a StartTask */
- vt_key[0].string = "NPCs";
- for (index_ = 0; index_ < gs_npc_count (game); index_++)
- {
- sc_int walk;
-
- /* Set up invariant parts of the properties key. */
- vt_key[1].integer = index_;
- vt_key[2].string = "Walks";
-
- /* Process each walk, starting at the last and working backwards. */
- for (walk = gs_npc_walkstep_count (game, index_) - 1; walk >= 0; walk--)
- {
- sc_int starttask;
-
- /* If StartTask is zero, start walk at game start. */
- vt_key[3].integer = walk;
- vt_key[4].string = "StartTask";
- starttask = prop_get_integer (bundle, "I<-sisis", vt_key);
- if (starttask == 0)
- npc_start_npc_walk (game, index_, walk);
- }
- }
-
- /* Update seen flags for initial states. */
- npc_turn_update (game);
+npc_setup_initial(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int index_;
+
+ /* Start any walks that do not depend on a StartTask */
+ vt_key[0].string = "NPCs";
+ for (index_ = 0; index_ < gs_npc_count(game); index_++) {
+ sc_int walk;
+
+ /* Set up invariant parts of the properties key. */
+ vt_key[1].integer = index_;
+ vt_key[2].string = "Walks";
+
+ /* Process each walk, starting at the last and working backwards. */
+ for (walk = gs_npc_walkstep_count(game, index_) - 1; walk >= 0; walk--) {
+ sc_int starttask;
+
+ /* If StartTask is zero, start walk at game start. */
+ vt_key[3].integer = walk;
+ vt_key[4].string = "StartTask";
+ starttask = prop_get_integer(bundle, "I<-sisis", vt_key);
+ if (starttask == 0)
+ npc_start_npc_walk(game, index_, walk);
+ }
+ }
+
+ /* Update seen flags for initial states. */
+ npc_turn_update(game);
}
@@ -160,33 +150,32 @@ npc_setup_initial (sc_gameref_t game)
* Return TRUE if a given room is in a given group.
*/
static sc_bool
-npc_room_in_roomgroup (sc_gameref_t game, sc_int room, sc_int group)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[4];
- sc_int member;
-
- /* Check roomgroup membership. */
- vt_key[0].string = "RoomGroups";
- vt_key[1].integer = group;
- vt_key[2].string = "List";
- vt_key[3].integer = room;
- member = prop_get_integer (bundle, "I<-sisi", vt_key);
- return member != 0;
+npc_room_in_roomgroup(sc_gameref_t game, sc_int room, sc_int group) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[4];
+ sc_int member;
+
+ /* Check roomgroup membership. */
+ vt_key[0].string = "RoomGroups";
+ vt_key[1].integer = group;
+ vt_key[2].string = "List";
+ vt_key[3].integer = room;
+ member = prop_get_integer(bundle, "I<-sisi", vt_key);
+ return member != 0;
}
/* List of direction names, for printing entry/exit messages. */
static const sc_char *const DIRNAMES_4[] = {
- "the north", "the east", "the south", "the west", "above", "below",
- "inside", "outside",
- NULL
+ "the north", "the east", "the south", "the west", "above", "below",
+ "inside", "outside",
+ NULL
};
static const sc_char *const DIRNAMES_8[] = {
- "the north", "the east", "the south", "the west", "above", "below",
- "inside", "outside",
- "the north-east", "the south-east", "the south-west", "the north-west",
- NULL
+ "the north", "the east", "the south", "the west", "above", "below",
+ "inside", "outside",
+ "the north-east", "the south-east", "the south-west", "the north-west",
+ NULL
};
/*
@@ -195,49 +184,46 @@ static const sc_char *const DIRNAMES_8[] = {
* Return a random member of group adjacent to given room.
*/
static sc_int
-npc_random_adjacent_roomgroup_member (sc_gameref_t game,
- sc_int room, sc_int group)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_bool eightpointcompass;
- sc_int roomlist[12], count, length, index_;
-
- /* If given room is "hidden", return nothing. */
- if (room == -1)
- return -1;
-
- /* How many exits to consider? */
- vt_key[0].string = "Globals";
- vt_key[1].string = "EightPointCompass";
- eightpointcompass = prop_get_boolean (bundle, "B<-ss", vt_key);
- if (eightpointcompass)
- length = sizeof (DIRNAMES_8) / sizeof (DIRNAMES_8[0]) - 1;
- else
- length = sizeof (DIRNAMES_4) / sizeof (DIRNAMES_4[0]) - 1;
-
- /* Poll adjacent rooms. */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Exits";
- count = 0;
- for (index_ = 0; index_ < length; index_++)
- {
- sc_int adjacent;
-
- vt_key[3].integer = index_;
- vt_key[4].string = "Dest";
- adjacent = prop_get_child_count (bundle, "I<-sisis", vt_key);
-
- if (adjacent > 0 && npc_room_in_roomgroup (game, adjacent - 1, group))
- {
- roomlist[count] = adjacent - 1;
- count++;
- }
- }
-
- /* Return a random adjacent room, or -1 if nothing is adjacent. */
- return (count > 0) ? roomlist[sc_randomint (0, count - 1)] : -1;
+npc_random_adjacent_roomgroup_member(sc_gameref_t game,
+ sc_int room, sc_int group) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_bool eightpointcompass;
+ sc_int roomlist[12], count, length, index_;
+
+ /* If given room is "hidden", return nothing. */
+ if (room == -1)
+ return -1;
+
+ /* How many exits to consider? */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "EightPointCompass";
+ eightpointcompass = prop_get_boolean(bundle, "B<-ss", vt_key);
+ if (eightpointcompass)
+ length = sizeof(DIRNAMES_8) / sizeof(DIRNAMES_8[0]) - 1;
+ else
+ length = sizeof(DIRNAMES_4) / sizeof(DIRNAMES_4[0]) - 1;
+
+ /* Poll adjacent rooms. */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Exits";
+ count = 0;
+ for (index_ = 0; index_ < length; index_++) {
+ sc_int adjacent;
+
+ vt_key[3].integer = index_;
+ vt_key[4].string = "Dest";
+ adjacent = prop_get_child_count(bundle, "I<-sisis", vt_key);
+
+ if (adjacent > 0 && npc_room_in_roomgroup(game, adjacent - 1, group)) {
+ roomlist[count] = adjacent - 1;
+ count++;
+ }
+ }
+
+ /* Return a random adjacent room, or -1 if nothing is adjacent. */
+ return (count > 0) ? roomlist[sc_randomint(0, count - 1)] : -1;
}
@@ -247,82 +233,77 @@ npc_random_adjacent_roomgroup_member (sc_gameref_t game,
* Helper for npc_tick_npc().
*/
static void
-npc_announce (sc_gameref_t game, sc_int npc,
- sc_int room, sc_bool is_exit, sc_int npc_room)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5], vt_rvalue;
- const sc_char *text, *name, *const *dirnames;
- sc_int dir, dir_match;
- sc_bool eightpointcompass, showenterexit, found;
-
- /* If no announcement required, return immediately. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "ShowEnterExit";
- showenterexit = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (!showenterexit)
- return;
-
- /* Get exit or entry text, and NPC name. */
- vt_key[2].string = is_exit ? "ExitText" : "EnterText";
- text = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- /* Decide on four or eight point compass names list. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "EightPointCompass";
- eightpointcompass = prop_get_boolean (bundle, "B<-ss", vt_key);
- dirnames = eightpointcompass ? DIRNAMES_8 : DIRNAMES_4;
-
- /* Set invariant key for room exit search. */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Exits";
-
- /* Find the room exit that matches the NPC room. */
- found = FALSE;
- dir_match = 0;
- for (dir = 0; dirnames[dir]; dir++)
- {
- vt_key[3].integer = dir;
- if (prop_get (bundle, "I<-sisi", &vt_rvalue, vt_key))
- {
- sc_int dest;
-
- /* Get room's direction destination, and compare. */
- vt_key[4].string = "Dest";
- dest = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if (dest == npc_room)
- {
- dir_match = dir;
- found = TRUE;
- break;
- }
- }
- }
-
- /* Print NPC exit/entry details. */
- pf_buffer_character (filter, '\n');
- pf_new_sentence (filter);
- pf_buffer_string (filter, name);
- pf_buffer_character (filter, ' ');
- pf_buffer_string (filter, text);
- if (found)
- {
- pf_buffer_string (filter, is_exit ? " to " : " from ");
- pf_buffer_string (filter, dirnames[dir_match]);
- }
- pf_buffer_string (filter, ".\n");
-
- /* Handle any associated resource. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Res";
- vt_key[3].integer = is_exit ? 3 : 2;
- res_handle_resource (game, "sisi", vt_key);
+npc_announce(sc_gameref_t game, sc_int npc,
+ sc_int room, sc_bool is_exit, sc_int npc_room) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5], vt_rvalue;
+ const sc_char *text, *name, *const *dirnames;
+ sc_int dir, dir_match;
+ sc_bool eightpointcompass, showenterexit, found;
+
+ /* If no announcement required, return immediately. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "ShowEnterExit";
+ showenterexit = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (!showenterexit)
+ return;
+
+ /* Get exit or entry text, and NPC name. */
+ vt_key[2].string = is_exit ? "ExitText" : "EnterText";
+ text = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ /* Decide on four or eight point compass names list. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "EightPointCompass";
+ eightpointcompass = prop_get_boolean(bundle, "B<-ss", vt_key);
+ dirnames = eightpointcompass ? DIRNAMES_8 : DIRNAMES_4;
+
+ /* Set invariant key for room exit search. */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Exits";
+
+ /* Find the room exit that matches the NPC room. */
+ found = FALSE;
+ dir_match = 0;
+ for (dir = 0; dirnames[dir]; dir++) {
+ vt_key[3].integer = dir;
+ if (prop_get(bundle, "I<-sisi", &vt_rvalue, vt_key)) {
+ sc_int dest;
+
+ /* Get room's direction destination, and compare. */
+ vt_key[4].string = "Dest";
+ dest = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if (dest == npc_room) {
+ dir_match = dir;
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* Print NPC exit/entry details. */
+ pf_buffer_character(filter, '\n');
+ pf_new_sentence(filter);
+ pf_buffer_string(filter, name);
+ pf_buffer_character(filter, ' ');
+ pf_buffer_string(filter, text);
+ if (found) {
+ pf_buffer_string(filter, is_exit ? " to " : " from ");
+ pf_buffer_string(filter, dirnames[dir_match]);
+ }
+ pf_buffer_string(filter, ".\n");
+
+ /* Handle any associated resource. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Res";
+ vt_key[3].integer = is_exit ? 3 : 2;
+ res_handle_resource(game, "sisi", vt_key);
}
@@ -332,123 +313,113 @@ npc_announce (sc_gameref_t game, sc_int npc,
* Helper for npc_tick_npc().
*/
static void
-npc_tick_npc_walk (sc_gameref_t game, sc_int npc, sc_int walk)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[6];
- sc_int roomgroups, movetimes, walkstep, start, dest, destnum;
- sc_int chartask, objecttask;
-
- if (npc_trace)
- {
- sc_trace ("NPC: ticking NPC %ld, walk %ld: step %ld\n",
- npc, walk, gs_npc_walkstep (game, npc, walk));
- }
-
- /* Count roomgroups for later use. */
- vt_key[0].string = "RoomGroups";
- roomgroups = prop_get_child_count (bundle, "I<-s", vt_key);
-
- /* Get move times array length. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Walks";
- vt_key[3].integer = walk;
- vt_key[4].string = "MoveTimes";
- movetimes = prop_get_child_count (bundle, "I<-sisis", vt_key);
-
- /* Find a step to match the movetime. */
- for (walkstep = 0; walkstep < movetimes - 1; walkstep++)
- {
- sc_int movetime;
-
- vt_key[5].integer = walkstep + 1;
- movetime = prop_get_integer (bundle, "I<-sisisi", vt_key);
- if (gs_npc_walkstep (game, npc, walk) > movetime)
- break;
- }
-
- /* Sort out a destination. */
- dest = start = gs_npc_location (game, npc) - 1;
-
- vt_key[4].string = "Rooms";
- vt_key[5].integer = walkstep;
- destnum = prop_get_integer (bundle, "I<-sisisi", vt_key);
-
- if (destnum == 0) /* Hidden. */
- dest = -1;
- else if (destnum == 1) /* Follow player. */
- dest = gs_playerroom (game);
- else if (destnum < gs_room_count (game) + 2)
- dest = destnum - 2; /* To room. */
- else if (destnum < gs_room_count (game) + 2 + roomgroups)
- {
- sc_int initial;
-
- /* For roomgroup walks, move only if walksteps has just refreshed. */
- vt_key[4].string = "MoveTimes";
- vt_key[5].integer = 0;
- initial = prop_get_integer (bundle, "I<-sisisi", vt_key);
- if (gs_npc_walkstep (game, npc, walk) == initial)
- {
- sc_int group;
-
- group = destnum - 2 - gs_room_count (game);
- dest = npc_random_adjacent_roomgroup_member (game, start, group);
- if (dest == -1)
- dest = lib_random_roomgroup_member (game, group);
- }
- }
-
- /* See if the NPC actually moved. */
- if (start != dest)
- {
- if (npc_trace)
- sc_trace ("NPC: walking NPC %ld moved to %ld\n", npc, dest);
-
- /* Move NPC to destination. */
- gs_set_npc_location (game, npc, dest + 1);
-
- /* Announce NPC movements, and handle meeting characters and objects. */
- if (gs_player_in_room (game, start))
- npc_announce (game, npc, start, TRUE, dest);
- else if (gs_player_in_room (game, dest))
- npc_announce (game, npc, dest, FALSE, start);
- }
-
- /* Handle meeting characters and objects. */
- vt_key[4].string = "CharTask";
- chartask = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if (chartask >= 0)
- {
- sc_int meetchar;
-
- /* Run meetchar task if appropriate. */
- vt_key[4].string = "MeetChar";
- meetchar = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if ((meetchar == -1 && gs_player_in_room (game, dest))
- || (meetchar >= 0 && dest == gs_npc_location (game, meetchar) - 1))
- {
- if (task_can_run_task (game, chartask))
- task_run_task (game, chartask, TRUE);
- }
- }
-
- vt_key[4].string = "ObjectTask";
- objecttask = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if (objecttask >= 0)
- {
- sc_int meetobject;
-
- /* Run meetobject task if appropriate. */
- vt_key[4].string = "MeetObject";
- meetobject = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if (meetobject >= 0 && obj_directly_in_room (game, meetobject, dest))
- {
- if (task_can_run_task (game, objecttask))
- task_run_task (game, objecttask, TRUE);
- }
- }
+npc_tick_npc_walk(sc_gameref_t game, sc_int npc, sc_int walk) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[6];
+ sc_int roomgroups, movetimes, walkstep, start, dest, destnum;
+ sc_int chartask, objecttask;
+
+ if (npc_trace) {
+ sc_trace("NPC: ticking NPC %ld, walk %ld: step %ld\n",
+ npc, walk, gs_npc_walkstep(game, npc, walk));
+ }
+
+ /* Count roomgroups for later use. */
+ vt_key[0].string = "RoomGroups";
+ roomgroups = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ /* Get move times array length. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Walks";
+ vt_key[3].integer = walk;
+ vt_key[4].string = "MoveTimes";
+ movetimes = prop_get_child_count(bundle, "I<-sisis", vt_key);
+
+ /* Find a step to match the movetime. */
+ for (walkstep = 0; walkstep < movetimes - 1; walkstep++) {
+ sc_int movetime;
+
+ vt_key[5].integer = walkstep + 1;
+ movetime = prop_get_integer(bundle, "I<-sisisi", vt_key);
+ if (gs_npc_walkstep(game, npc, walk) > movetime)
+ break;
+ }
+
+ /* Sort out a destination. */
+ dest = start = gs_npc_location(game, npc) - 1;
+
+ vt_key[4].string = "Rooms";
+ vt_key[5].integer = walkstep;
+ destnum = prop_get_integer(bundle, "I<-sisisi", vt_key);
+
+ if (destnum == 0) /* Hidden. */
+ dest = -1;
+ else if (destnum == 1) /* Follow player. */
+ dest = gs_playerroom(game);
+ else if (destnum < gs_room_count(game) + 2)
+ dest = destnum - 2; /* To room. */
+ else if (destnum < gs_room_count(game) + 2 + roomgroups) {
+ sc_int initial;
+
+ /* For roomgroup walks, move only if walksteps has just refreshed. */
+ vt_key[4].string = "MoveTimes";
+ vt_key[5].integer = 0;
+ initial = prop_get_integer(bundle, "I<-sisisi", vt_key);
+ if (gs_npc_walkstep(game, npc, walk) == initial) {
+ sc_int group;
+
+ group = destnum - 2 - gs_room_count(game);
+ dest = npc_random_adjacent_roomgroup_member(game, start, group);
+ if (dest == -1)
+ dest = lib_random_roomgroup_member(game, group);
+ }
+ }
+
+ /* See if the NPC actually moved. */
+ if (start != dest) {
+ if (npc_trace)
+ sc_trace("NPC: walking NPC %ld moved to %ld\n", npc, dest);
+
+ /* Move NPC to destination. */
+ gs_set_npc_location(game, npc, dest + 1);
+
+ /* Announce NPC movements, and handle meeting characters and objects. */
+ if (gs_player_in_room(game, start))
+ npc_announce(game, npc, start, TRUE, dest);
+ else if (gs_player_in_room(game, dest))
+ npc_announce(game, npc, dest, FALSE, start);
+ }
+
+ /* Handle meeting characters and objects. */
+ vt_key[4].string = "CharTask";
+ chartask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if (chartask >= 0) {
+ sc_int meetchar;
+
+ /* Run meetchar task if appropriate. */
+ vt_key[4].string = "MeetChar";
+ meetchar = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if ((meetchar == -1 && gs_player_in_room(game, dest))
+ || (meetchar >= 0 && dest == gs_npc_location(game, meetchar) - 1)) {
+ if (task_can_run_task(game, chartask))
+ task_run_task(game, chartask, TRUE);
+ }
+ }
+
+ vt_key[4].string = "ObjectTask";
+ objecttask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if (objecttask >= 0) {
+ sc_int meetobject;
+
+ /* Run meetobject task if appropriate. */
+ vt_key[4].string = "MeetObject";
+ meetobject = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if (meetobject >= 0 && obj_directly_in_room(game, meetobject, dest)) {
+ if (task_can_run_task(game, objecttask))
+ task_run_task(game, objecttask, TRUE);
+ }
+ }
}
@@ -458,99 +429,91 @@ npc_tick_npc_walk (sc_gameref_t game, sc_int npc, sc_int walk)
* Move an NPC one step along current walk.
*/
static void
-npc_tick_npc (sc_gameref_t game, sc_int npc)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[6];
- sc_int walk;
- sc_bool has_moved = FALSE;
-
- if (npc_trace)
- sc_trace ("NPC: ticking NPC %ld\n", npc);
-
- /* Set up invariant key parts. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Walks";
-
- /* Find active walk, and if any found, make a step along it. */
- for (walk = gs_npc_walkstep_count (game, npc) - 1; walk >= 0; walk--)
- {
- sc_int starttask, stoppingtask;
-
- /* Ignore finished walks. */
- if (gs_npc_walkstep (game, npc, walk) <= 0)
- continue;
-
- /* Get start task. */
- vt_key[3].integer = walk;
- vt_key[4].string = "StartTask";
- starttask = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
-
- /*
- * Check that the starter is still complete, and if not, stop walk.
- * Then keep on looking for an active walk.
- */
- if (starttask >= 0 && !gs_task_done (game, starttask))
- {
- if (npc_trace)
- sc_trace ("NPC: stopping NPC %ld walk, start task undone\n", npc);
-
- gs_set_npc_walkstep (game, npc, walk, -1);
- continue;
- }
-
- /* Get stopping task. */
- vt_key[4].string = "StoppingTask";
- stoppingtask = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
-
- /*
- * If any stopping task has completed, ignore this walk but don't
- * actually finish it; more like an event pauser, then.
- *
- * TODO Is this right?
- */
- if (stoppingtask >= 0 && gs_task_done (game, stoppingtask))
- {
- if (npc_trace)
- sc_trace ("NPC: ignoring NPC %ld walk, stop task done\n", npc);
-
- continue;
- }
-
- /* Decrement steps. */
- gs_decrement_npc_walkstep (game, npc, walk);
-
- /* If we just hit a walk end, loop if called for. */
- if (gs_npc_walkstep (game, npc, walk) == 0)
- {
- sc_bool is_loop;
-
- /* If walk is a loop, restart it. */
- vt_key[4].string = "Loop";
- is_loop = prop_get_boolean (bundle, "B<-sisis", vt_key);
- if (is_loop)
- {
- vt_key[4].string = "MoveTimes";
- vt_key[5].integer = 0;
- gs_set_npc_walkstep (game, npc, walk,
- prop_get_integer (bundle,
- "I<-sisisi", vt_key));
- }
- else
- gs_set_npc_walkstep (game, npc, walk, -1);
- }
-
- /*
- * If not yet made a move on this walk, make one, and once made, make
- * no other
- */
- if (!has_moved)
- {
- npc_tick_npc_walk (game, npc, walk);
- has_moved = TRUE;
- }
- }
+npc_tick_npc(sc_gameref_t game, sc_int npc) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[6];
+ sc_int walk;
+ sc_bool has_moved = FALSE;
+
+ if (npc_trace)
+ sc_trace("NPC: ticking NPC %ld\n", npc);
+
+ /* Set up invariant key parts. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Walks";
+
+ /* Find active walk, and if any found, make a step along it. */
+ for (walk = gs_npc_walkstep_count(game, npc) - 1; walk >= 0; walk--) {
+ sc_int starttask, stoppingtask;
+
+ /* Ignore finished walks. */
+ if (gs_npc_walkstep(game, npc, walk) <= 0)
+ continue;
+
+ /* Get start task. */
+ vt_key[3].integer = walk;
+ vt_key[4].string = "StartTask";
+ starttask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+
+ /*
+ * Check that the starter is still complete, and if not, stop walk.
+ * Then keep on looking for an active walk.
+ */
+ if (starttask >= 0 && !gs_task_done(game, starttask)) {
+ if (npc_trace)
+ sc_trace("NPC: stopping NPC %ld walk, start task undone\n", npc);
+
+ gs_set_npc_walkstep(game, npc, walk, -1);
+ continue;
+ }
+
+ /* Get stopping task. */
+ vt_key[4].string = "StoppingTask";
+ stoppingtask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+
+ /*
+ * If any stopping task has completed, ignore this walk but don't
+ * actually finish it; more like an event pauser, then.
+ *
+ * TODO Is this right?
+ */
+ if (stoppingtask >= 0 && gs_task_done(game, stoppingtask)) {
+ if (npc_trace)
+ sc_trace("NPC: ignoring NPC %ld walk, stop task done\n", npc);
+
+ continue;
+ }
+
+ /* Decrement steps. */
+ gs_decrement_npc_walkstep(game, npc, walk);
+
+ /* If we just hit a walk end, loop if called for. */
+ if (gs_npc_walkstep(game, npc, walk) == 0) {
+ sc_bool is_loop;
+
+ /* If walk is a loop, restart it. */
+ vt_key[4].string = "Loop";
+ is_loop = prop_get_boolean(bundle, "B<-sisis", vt_key);
+ if (is_loop) {
+ vt_key[4].string = "MoveTimes";
+ vt_key[5].integer = 0;
+ gs_set_npc_walkstep(game, npc, walk,
+ prop_get_integer(bundle,
+ "I<-sisisi", vt_key));
+ } else
+ gs_set_npc_walkstep(game, npc, walk, -1);
+ }
+
+ /*
+ * If not yet made a move on this walk, make one, and once made, make
+ * no other
+ */
+ if (!has_moved) {
+ npc_tick_npc_walk(game, npc, walk);
+ has_moved = TRUE;
+ }
+ }
}
@@ -560,68 +523,62 @@ npc_tick_npc (sc_gameref_t game, sc_int npc)
* Move each NPC one step along current walk.
*/
void
-npc_tick_npcs (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- const sc_gameref_t undo = game->undo;
- sc_int npc;
-
- /*
- * Compare the player location to last turn, to see if the player has moved
- * this turn. If moved, look for meetings with NPCs.
- *
- * TODO Is this the right place to do this. After ticking each NPC, rather
- * than before, seems more appropriate. But the messages come out in the
- * right order by putting it here.
- *
- * Also, note that we take the shortcut of using the undo gamestate here,
- * rather than properly recording the prior location of the player, and
- * perhaps also NPCs, in the live gamestate.
- */
- if (undo && !gs_player_in_room (undo, gs_playerroom (game)))
- {
- for (npc = 0; npc < gs_npc_count (game); npc++)
- {
- sc_int walk;
-
- /* Iterate each NPC's walks. */
- for (walk = gs_npc_walkstep_count (game, npc) - 1; walk >= 0; walk--)
- {
- sc_vartype_t vt_key[5];
- sc_int chartask;
-
- /* Ignore finished walks. */
- if (gs_npc_walkstep (game, npc, walk) <= 0)
- continue;
-
- /* Retrieve any character meeting task for the NPC. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Walks";
- vt_key[3].integer = walk;
- vt_key[4].string = "CharTask";
- chartask = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if (chartask >= 0)
- {
- sc_int meetchar;
-
- /* Run meetchar task if appropriate. */
- vt_key[4].string = "MeetChar";
- meetchar = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if (meetchar == -1 &&
- gs_player_in_room (game, gs_npc_location (game, npc) - 1))
- {
- if (task_can_run_task (game, chartask))
- task_run_task (game, chartask, TRUE);
- }
- }
- }
- }
- }
-
- /* Iterate and tick each individual NPC. */
- for (npc = 0; npc < gs_npc_count (game); npc++)
- npc_tick_npc (game, npc);
+npc_tick_npcs(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ const sc_gameref_t undo = game->undo;
+ sc_int npc;
+
+ /*
+ * Compare the player location to last turn, to see if the player has moved
+ * this turn. If moved, look for meetings with NPCs.
+ *
+ * TODO Is this the right place to do this. After ticking each NPC, rather
+ * than before, seems more appropriate. But the messages come out in the
+ * right order by putting it here.
+ *
+ * Also, note that we take the shortcut of using the undo gamestate here,
+ * rather than properly recording the prior location of the player, and
+ * perhaps also NPCs, in the live gamestate.
+ */
+ if (undo && !gs_player_in_room(undo, gs_playerroom(game))) {
+ for (npc = 0; npc < gs_npc_count(game); npc++) {
+ sc_int walk;
+
+ /* Iterate each NPC's walks. */
+ for (walk = gs_npc_walkstep_count(game, npc) - 1; walk >= 0; walk--) {
+ sc_vartype_t vt_key[5];
+ sc_int chartask;
+
+ /* Ignore finished walks. */
+ if (gs_npc_walkstep(game, npc, walk) <= 0)
+ continue;
+
+ /* Retrieve any character meeting task for the NPC. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Walks";
+ vt_key[3].integer = walk;
+ vt_key[4].string = "CharTask";
+ chartask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if (chartask >= 0) {
+ sc_int meetchar;
+
+ /* Run meetchar task if appropriate. */
+ vt_key[4].string = "MeetChar";
+ meetchar = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if (meetchar == -1 &&
+ gs_player_in_room(game, gs_npc_location(game, npc) - 1)) {
+ if (task_can_run_task(game, chartask))
+ task_run_task(game, chartask, TRUE);
+ }
+ }
+ }
+ }
+ }
+
+ /* Iterate and tick each individual NPC. */
+ for (npc = 0; npc < gs_npc_count(game); npc++)
+ npc_tick_npc(game, npc);
}
@@ -631,9 +588,8 @@ npc_tick_npcs (sc_gameref_t game)
* Set NPC tracing on/off.
*/
void
-npc_debug_trace (sc_bool flag)
-{
- npc_trace = flag;
+npc_debug_trace(sc_bool flag) {
+ npc_trace = flag;
}
} // End of namespace Adrift