diff options
Diffstat (limited to 'engines/glk/adrift/scevents.cpp')
-rw-r--r-- | engines/glk/adrift/scevents.cpp | 1312 |
1 files changed, 622 insertions, 690 deletions
diff --git a/engines/glk/adrift/scevents.cpp b/engines/glk/adrift/scevents.cpp index 18d95b19ec..0048cd6dd9 100644 --- a/engines/glk/adrift/scevents.cpp +++ b/engines/glk/adrift/scevents.cpp @@ -43,19 +43,17 @@ static sc_bool evt_trace = FALSE; * Return TRUE if any task at all matches the given completion state. */ static sc_bool -evt_any_task_in_state (sc_gameref_t game, sc_bool state) -{ - sc_int task; - - /* Scan tasks for any whose completion matches input. */ - for (task = 0; task < gs_task_count (game); task++) - { - if (gs_task_done (game, task) == state) - return TRUE; - } - - /* No tasks matched. */ - return FALSE; +evt_any_task_in_state(sc_gameref_t game, sc_bool state) { + sc_int task; + + /* Scan tasks for any whose completion matches input. */ + for (task = 0; task < gs_task_count(game); task++) { + if (gs_task_done(game, task) == state) + return TRUE; + } + + /* No tasks matched. */ + return FALSE; } @@ -65,39 +63,37 @@ evt_any_task_in_state (sc_gameref_t game, sc_bool state) * Return TRUE if player is in the right room for event text. */ sc_bool -evt_can_see_event (sc_gameref_t game, sc_int event) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[5]; - sc_int type; - - /* Check room list for the event and return it. */ - vt_key[0].string = "Events"; - vt_key[1].integer = event; - vt_key[2].string = "Where"; - vt_key[3].string = "Type"; - type = prop_get_integer (bundle, "I<-siss", vt_key); - switch (type) - { - case ROOMLIST_NO_ROOMS: - return FALSE; - case ROOMLIST_ALL_ROOMS: - return TRUE; - - case ROOMLIST_ONE_ROOM: - vt_key[3].string = "Room"; - return prop_get_integer (bundle, "I<-siss", vt_key) - == gs_playerroom (game); - - case ROOMLIST_SOME_ROOMS: - vt_key[3].string = "Rooms"; - vt_key[4].integer = gs_playerroom (game); - return prop_get_boolean (bundle, "B<-sissi", vt_key); - - default: - sc_fatal ("evt_can_see_event: invalid type, %ld\n", type); - return FALSE; - } +evt_can_see_event(sc_gameref_t game, sc_int event) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[5]; + sc_int type; + + /* Check room list for the event and return it. */ + vt_key[0].string = "Events"; + vt_key[1].integer = event; + vt_key[2].string = "Where"; + vt_key[3].string = "Type"; + type = prop_get_integer(bundle, "I<-siss", vt_key); + switch (type) { + case ROOMLIST_NO_ROOMS: + return FALSE; + case ROOMLIST_ALL_ROOMS: + return TRUE; + + case ROOMLIST_ONE_ROOM: + vt_key[3].string = "Room"; + return prop_get_integer(bundle, "I<-siss", vt_key) + == gs_playerroom(game); + + case ROOMLIST_SOME_ROOMS: + vt_key[3].string = "Rooms"; + vt_key[4].integer = gs_playerroom(game); + return prop_get_boolean(bundle, "B<-sissi", vt_key); + + default: + sc_fatal("evt_can_see_event: invalid type, %ld\n", type); + return FALSE; + } } @@ -107,55 +103,50 @@ evt_can_see_event (sc_gameref_t game, sc_int event) * Move an object from within an event. */ static void -evt_move_object (sc_gameref_t game, sc_int object, sc_int destination) -{ - /* Ignore negative values of object. */ - if (object >= 0) - { - if (evt_trace) - { - sc_trace ("Event: moving object %ld to room %ld\n", - object, destination); - } - - /* Move object depending on destination. */ - switch (destination) - { - case -1: /* Hidden. */ - gs_object_make_hidden (game, object); - break; - - case 0: /* Held by player. */ - gs_object_player_get (game, object); - break; - - case 1: /* Same room as player. */ - gs_object_to_room (game, object, gs_playerroom (game)); - break; - - default: - if (destination < gs_room_count (game) + 2) - gs_object_to_room (game, object, destination - 2); - else - { - sc_int roomgroup, room; - - roomgroup = destination - gs_room_count (game) - 2; - room = lib_random_roomgroup_member (game, roomgroup); - gs_object_to_room (game, object, room); - } - break; - } - - /* - * If static, mark as no longer unmoved. - * - * TODO Is this the only place static objects can be moved? And just - * how static is a static object if it's moveable, anyway? - */ - if (obj_is_static (game, object)) - gs_set_object_static_unmoved (game, object, FALSE); - } +evt_move_object(sc_gameref_t game, sc_int object, sc_int destination) { + /* Ignore negative values of object. */ + if (object >= 0) { + if (evt_trace) { + sc_trace("Event: moving object %ld to room %ld\n", + object, destination); + } + + /* Move object depending on destination. */ + switch (destination) { + case -1: /* Hidden. */ + gs_object_make_hidden(game, object); + break; + + case 0: /* Held by player. */ + gs_object_player_get(game, object); + break; + + case 1: /* Same room as player. */ + gs_object_to_room(game, object, gs_playerroom(game)); + break; + + default: + if (destination < gs_room_count(game) + 2) + gs_object_to_room(game, object, destination - 2); + else { + sc_int roomgroup, room; + + roomgroup = destination - gs_room_count(game) - 2; + room = lib_random_roomgroup_member(game, roomgroup); + gs_object_to_room(game, object, room); + } + break; + } + + /* + * If static, mark as no longer unmoved. + * + * TODO Is this the only place static objects can be moved? And just + * how static is a static object if it's moveable, anyway? + */ + if (obj_is_static(game, object)) + gs_set_object_static_unmoved(game, object, FALSE); + } } @@ -168,36 +159,34 @@ evt_move_object (sc_gameref_t game, sc_int object, sc_int destination) * can do the same thing here, though it's ugly. */ static sc_bool -evt_fixup_v390_v380_immediate_restart (sc_gameref_t game, sc_int event) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[3]; - sc_int version; - - vt_key[0].string = "Version"; - version = prop_get_integer (bundle, "I<-s", vt_key); - if (version < TAF_VERSION_400) - { - sc_int time1, time2; - - if (evt_trace) - sc_trace ("Event: applying 3.9/3.8 restart fixup\n"); - - /* Set to running state. */ - gs_set_event_state (game, event, ES_RUNNING); - - /* Set up event time to be one less than a proper start. */ - vt_key[0].string = "Events"; - vt_key[1].integer = event; - vt_key[2].string = "Time1"; - time1 = prop_get_integer (bundle, "I<-sis", vt_key); - vt_key[2].string = "Time2"; - time2 = prop_get_integer (bundle, "I<-sis", vt_key); - gs_set_event_time (game, event, sc_randomint (time1, time2) - 1); - } - - /* Return TRUE if we applied the fixup. */ - return version < TAF_VERSION_400; +evt_fixup_v390_v380_immediate_restart(sc_gameref_t game, sc_int event) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[3]; + sc_int version; + + vt_key[0].string = "Version"; + version = prop_get_integer(bundle, "I<-s", vt_key); + if (version < TAF_VERSION_400) { + sc_int time1, time2; + + if (evt_trace) + sc_trace("Event: applying 3.9/3.8 restart fixup\n"); + + /* Set to running state. */ + gs_set_event_state(game, event, ES_RUNNING); + + /* Set up event time to be one less than a proper start. */ + vt_key[0].string = "Events"; + vt_key[1].integer = event; + vt_key[2].string = "Time1"; + time1 = prop_get_integer(bundle, "I<-sis", vt_key); + vt_key[2].string = "Time2"; + time2 = prop_get_integer(bundle, "I<-sis", vt_key); + gs_set_event_time(game, event, sc_randomint(time1, time2) - 1); + } + + /* Return TRUE if we applied the fixup. */ + return version < TAF_VERSION_400; } @@ -207,58 +196,55 @@ evt_fixup_v390_v380_immediate_restart (sc_gameref_t game, sc_int event) * Change an event from WAITING to RUNNING. */ static void -evt_start_event (sc_gameref_t game, sc_int event) -{ - const sc_filterref_t filter = gs_get_filter (game); - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[4]; - sc_int time1, time2, obj1, obj1dest; - - if (evt_trace) - sc_trace ("Event: starting event %ld\n", event); - - /* If event is visible, print its start text. */ - if (evt_can_see_event (game, event)) - { - const sc_char *starttext; - - /* Get and print start text. */ - vt_key[0].string = "Events"; - vt_key[1].integer = event; - vt_key[2].string = "StartText"; - starttext = prop_get_string (bundle, "S<-sis", vt_key); - if (!sc_strempty (starttext)) - { - pf_buffer_string (filter, starttext); - pf_buffer_character (filter, '\n'); - } - - /* Handle any associated resource. */ - vt_key[2].string = "Res"; - vt_key[3].integer = 0; - res_handle_resource (game, "sisi", vt_key); - } - - /* Move event object to destination. */ - vt_key[0].string = "Events"; - vt_key[1].integer = event; - vt_key[2].string = "Obj1"; - obj1 = prop_get_integer (bundle, "I<-sis", vt_key) - 1; - vt_key[2].string = "Obj1Dest"; - obj1dest = prop_get_integer (bundle, "I<-sis", vt_key) - 1; - evt_move_object (game, obj1, obj1dest); - - /* Set the event's state and time. */ - gs_set_event_state (game, event, ES_RUNNING); - - vt_key[2].string = "Time1"; - time1 = prop_get_integer (bundle, "I<-sis", vt_key); - vt_key[2].string = "Time2"; - time2 = prop_get_integer (bundle, "I<-sis", vt_key); - gs_set_event_time (game, event, sc_randomint (time1, time2)); - - if (evt_trace) - sc_trace ("Event: start event handling done, %ld\n", event); +evt_start_event(sc_gameref_t game, sc_int event) { + const sc_filterref_t filter = gs_get_filter(game); + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[4]; + sc_int time1, time2, obj1, obj1dest; + + if (evt_trace) + sc_trace("Event: starting event %ld\n", event); + + /* If event is visible, print its start text. */ + if (evt_can_see_event(game, event)) { + const sc_char *starttext; + + /* Get and print start text. */ + vt_key[0].string = "Events"; + vt_key[1].integer = event; + vt_key[2].string = "StartText"; + starttext = prop_get_string(bundle, "S<-sis", vt_key); + if (!sc_strempty(starttext)) { + pf_buffer_string(filter, starttext); + pf_buffer_character(filter, '\n'); + } + + /* Handle any associated resource. */ + vt_key[2].string = "Res"; + vt_key[3].integer = 0; + res_handle_resource(game, "sisi", vt_key); + } + + /* Move event object to destination. */ + vt_key[0].string = "Events"; + vt_key[1].integer = event; + vt_key[2].string = "Obj1"; + obj1 = prop_get_integer(bundle, "I<-sis", vt_key) - 1; + vt_key[2].string = "Obj1Dest"; + obj1dest = prop_get_integer(bundle, "I<-sis", vt_key) - 1; + evt_move_object(game, obj1, obj1dest); + + /* Set the event's state and time. */ + gs_set_event_state(game, event, ES_RUNNING); + + vt_key[2].string = "Time1"; + time1 = prop_get_integer(bundle, "I<-sis", vt_key); + vt_key[2].string = "Time2"; + time2 = prop_get_integer(bundle, "I<-sis", vt_key); + gs_set_event_time(game, event, sc_randomint(time1, time2)); + + if (evt_trace) + sc_trace("Event: start event handling done, %ld\n", event); } @@ -268,18 +254,17 @@ evt_start_event (sc_gameref_t game, sc_int event) * Return the starter type for an event. */ static sc_int -evt_get_starter_type (sc_gameref_t game, sc_int event) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[3]; - sc_int startertype; - - vt_key[0].string = "Events"; - vt_key[1].integer = event; - vt_key[2].string = "StarterType"; - startertype = prop_get_integer (bundle, "I<-sis", vt_key); - - return startertype; +evt_get_starter_type(sc_gameref_t game, sc_int event) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[3]; + sc_int startertype; + + vt_key[0].string = "Events"; + vt_key[1].integer = event; + vt_key[2].string = "StarterType"; + startertype = prop_get_integer(bundle, "I<-sis", vt_key); + + return startertype; } @@ -289,148 +274,136 @@ evt_get_starter_type (sc_gameref_t game, sc_int event) * Move an event to FINISHED, or restart it. */ static void -evt_finish_event (sc_gameref_t game, sc_int event) -{ - const sc_filterref_t filter = gs_get_filter (game); - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[4]; - sc_int obj2, obj2dest, obj3, obj3dest; - sc_int task, startertype, restarttype; - sc_bool taskdir; - - if (evt_trace) - sc_trace ("Event: finishing event %ld\n", event); - - /* Set up invariant parts of the key. */ - vt_key[0].string = "Events"; - vt_key[1].integer = event; - - /* If event is visible, print its finish text. */ - if (evt_can_see_event (game, event)) - { - const sc_char *finishtext; - - /* Get and print finish text. */ - vt_key[2].string = "FinishText"; - finishtext = prop_get_string (bundle, "S<-sis", vt_key); - if (!sc_strempty (finishtext)) - { - pf_buffer_string (filter, finishtext); - pf_buffer_character (filter, '\n'); - } - - /* Handle any associated resource. */ - vt_key[2].string = "Res"; - vt_key[3].integer = 4; - res_handle_resource (game, "sisi", vt_key); - } - - /* Move event objects to destination. */ - vt_key[2].string = "Obj2"; - obj2 = prop_get_integer (bundle, "I<-sis", vt_key) - 1; - vt_key[2].string = "Obj2Dest"; - obj2dest = prop_get_integer (bundle, "I<-sis", vt_key) - 1; - evt_move_object (game, obj2, obj2dest); - - vt_key[2].string = "Obj3"; - obj3 = prop_get_integer (bundle, "I<-sis", vt_key) - 1; - vt_key[2].string = "Obj3Dest"; - obj3dest = prop_get_integer (bundle, "I<-sis", vt_key) - 1; - evt_move_object (game, obj3, obj3dest); - - /* See if there is an affected task. */ - vt_key[2].string = "TaskAffected"; - task = prop_get_integer (bundle, "I<-sis", vt_key) - 1; - if (task >= 0) - { - vt_key[2].string = "TaskFinished"; - taskdir = !prop_get_boolean (bundle, "B<-sis", vt_key); - if (task_can_run_task_directional (game, task, taskdir)) - { - if (evt_trace) - { - sc_trace ("Event: event running task %ld, %s\n", - task, taskdir ? "forwards" : "backwards"); - } - - task_run_task (game, task, taskdir); - } - else - { - if (evt_trace) - sc_trace ("Event: event can't run task %ld\n", task); - } - } - - /* Handle possible restart. */ - vt_key[2].string = "RestartType"; - restarttype = prop_get_integer (bundle, "I<-sis", vt_key); - switch (restarttype) - { - case 0: /* Don't restart. */ - startertype = evt_get_starter_type (game, event); - switch (startertype) - { - case 1: /* Immediate. */ - case 2: /* Random delay. */ - case 3: /* After task. */ - gs_set_event_state (game, event, ES_FINISHED); - gs_set_event_time (game, event, 0); - break; - - default: - sc_fatal ("evt_finish_event:" - " unknown value for starter type, %ld\n", startertype); - } - break; - - case 1: /* Restart immediately. */ - if (evt_fixup_v390_v380_immediate_restart (game, event)) - break; - else - evt_start_event (game, event); - break; - - case 2: /* Restart after delay. */ - startertype = evt_get_starter_type (game, event); - switch (startertype) - { - case 1: /* Immediate. */ - if (evt_fixup_v390_v380_immediate_restart (game, event)) - break; - else - evt_start_event (game, event); - break; - - case 2: /* Random delay. */ - { - sc_int start, end; - - gs_set_event_state (game, event, ES_WAITING); - vt_key[2].string = "StartTime"; - start = prop_get_integer (bundle, "I<-sis", vt_key); - vt_key[2].string = "EndTime"; - end = prop_get_integer (bundle, "I<-sis", vt_key); - gs_set_event_time (game, event, sc_randomint (start, end)); - break; - } - - case 3: /* After task. */ - gs_set_event_state (game, event, ES_AWAITING); - gs_set_event_time (game, event, 0); - break; - - default: - sc_fatal ("evt_finish_event: unknown StarterType\n"); - } - break; - - default: - sc_fatal ("evt_finish_event: unknown RestartType\n"); - } - - if (evt_trace) - sc_trace ("Event: finish event handling done, %ld\n", event); +evt_finish_event(sc_gameref_t game, sc_int event) { + const sc_filterref_t filter = gs_get_filter(game); + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[4]; + sc_int obj2, obj2dest, obj3, obj3dest; + sc_int task, startertype, restarttype; + sc_bool taskdir; + + if (evt_trace) + sc_trace("Event: finishing event %ld\n", event); + + /* Set up invariant parts of the key. */ + vt_key[0].string = "Events"; + vt_key[1].integer = event; + + /* If event is visible, print its finish text. */ + if (evt_can_see_event(game, event)) { + const sc_char *finishtext; + + /* Get and print finish text. */ + vt_key[2].string = "FinishText"; + finishtext = prop_get_string(bundle, "S<-sis", vt_key); + if (!sc_strempty(finishtext)) { + pf_buffer_string(filter, finishtext); + pf_buffer_character(filter, '\n'); + } + + /* Handle any associated resource. */ + vt_key[2].string = "Res"; + vt_key[3].integer = 4; + res_handle_resource(game, "sisi", vt_key); + } + + /* Move event objects to destination. */ + vt_key[2].string = "Obj2"; + obj2 = prop_get_integer(bundle, "I<-sis", vt_key) - 1; + vt_key[2].string = "Obj2Dest"; + obj2dest = prop_get_integer(bundle, "I<-sis", vt_key) - 1; + evt_move_object(game, obj2, obj2dest); + + vt_key[2].string = "Obj3"; + obj3 = prop_get_integer(bundle, "I<-sis", vt_key) - 1; + vt_key[2].string = "Obj3Dest"; + obj3dest = prop_get_integer(bundle, "I<-sis", vt_key) - 1; + evt_move_object(game, obj3, obj3dest); + + /* See if there is an affected task. */ + vt_key[2].string = "TaskAffected"; + task = prop_get_integer(bundle, "I<-sis", vt_key) - 1; + if (task >= 0) { + vt_key[2].string = "TaskFinished"; + taskdir = !prop_get_boolean(bundle, "B<-sis", vt_key); + if (task_can_run_task_directional(game, task, taskdir)) { + if (evt_trace) { + sc_trace("Event: event running task %ld, %s\n", + task, taskdir ? "forwards" : "backwards"); + } + + task_run_task(game, task, taskdir); + } else { + if (evt_trace) + sc_trace("Event: event can't run task %ld\n", task); + } + } + + /* Handle possible restart. */ + vt_key[2].string = "RestartType"; + restarttype = prop_get_integer(bundle, "I<-sis", vt_key); + switch (restarttype) { + case 0: /* Don't restart. */ + startertype = evt_get_starter_type(game, event); + switch (startertype) { + case 1: /* Immediate. */ + case 2: /* Random delay. */ + case 3: /* After task. */ + gs_set_event_state(game, event, ES_FINISHED); + gs_set_event_time(game, event, 0); + break; + + default: + sc_fatal("evt_finish_event:" + " unknown value for starter type, %ld\n", startertype); + } + break; + + case 1: /* Restart immediately. */ + if (evt_fixup_v390_v380_immediate_restart(game, event)) + break; + else + evt_start_event(game, event); + break; + + case 2: /* Restart after delay. */ + startertype = evt_get_starter_type(game, event); + switch (startertype) { + case 1: /* Immediate. */ + if (evt_fixup_v390_v380_immediate_restart(game, event)) + break; + else + evt_start_event(game, event); + break; + + case 2: { /* Random delay. */ + sc_int start, end; + + gs_set_event_state(game, event, ES_WAITING); + vt_key[2].string = "StartTime"; + start = prop_get_integer(bundle, "I<-sis", vt_key); + vt_key[2].string = "EndTime"; + end = prop_get_integer(bundle, "I<-sis", vt_key); + gs_set_event_time(game, event, sc_randomint(start, end)); + break; + } + + case 3: /* After task. */ + gs_set_event_state(game, event, ES_AWAITING); + gs_set_event_time(game, event, 0); + break; + + default: + sc_fatal("evt_finish_event: unknown StarterType\n"); + } + break; + + default: + sc_fatal("evt_finish_event: unknown RestartType\n"); + } + + if (evt_trace) + sc_trace("Event: finish event handling done, %ld\n", event); } @@ -443,102 +416,89 @@ evt_finish_event (sc_gameref_t game, sc_int event) * Return the status of start, pause and resume states of an event. */ static sc_bool -evt_has_starter_task (sc_gameref_t game, sc_int event) -{ - sc_int startertype; +evt_has_starter_task(sc_gameref_t game, sc_int event) { + sc_int startertype; - startertype = evt_get_starter_type (game, event); - return startertype == 3; + startertype = evt_get_starter_type(game, event); + return startertype == 3; } static sc_bool -evt_starter_task_is_complete (sc_gameref_t game, sc_int event) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[3]; - sc_int task; - sc_bool start; - - vt_key[0].string = "Events"; - vt_key[1].integer = event; - vt_key[2].string = "TaskNum"; - task = prop_get_integer (bundle, "I<-sis", vt_key); - - start = FALSE; - if (task == 0) - { - if (evt_any_task_in_state (game, TRUE)) - start = TRUE; - } - else if (task > 0) - { - if (gs_task_done (game, task - 1)) - start = TRUE; - } - - return start; +evt_starter_task_is_complete(sc_gameref_t game, sc_int event) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[3]; + sc_int task; + sc_bool start; + + vt_key[0].string = "Events"; + vt_key[1].integer = event; + vt_key[2].string = "TaskNum"; + task = prop_get_integer(bundle, "I<-sis", vt_key); + + start = FALSE; + if (task == 0) { + if (evt_any_task_in_state(game, TRUE)) + start = TRUE; + } else if (task > 0) { + if (gs_task_done(game, task - 1)) + start = TRUE; + } + + return start; } static sc_bool -evt_pauser_task_is_complete (sc_gameref_t game, sc_int event) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[3]; - sc_int pausetask; - sc_bool completed, pause; - - vt_key[0].string = "Events"; - vt_key[1].integer = event; - - vt_key[2].string = "PauseTask"; - pausetask = prop_get_integer (bundle, "I<-sis", vt_key); - vt_key[2].string = "PauserCompleted"; - completed = !prop_get_boolean (bundle, "B<-sis", vt_key); - - pause = FALSE; - if (pausetask == 1) - { - if (evt_any_task_in_state (game, completed)) - pause = TRUE; - } - else if (pausetask > 1) - { - if (completed == gs_task_done (game, pausetask - 2)) - pause = TRUE; - } - - return pause; +evt_pauser_task_is_complete(sc_gameref_t game, sc_int event) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[3]; + sc_int pausetask; + sc_bool completed, pause; + + vt_key[0].string = "Events"; + vt_key[1].integer = event; + + vt_key[2].string = "PauseTask"; + pausetask = prop_get_integer(bundle, "I<-sis", vt_key); + vt_key[2].string = "PauserCompleted"; + completed = !prop_get_boolean(bundle, "B<-sis", vt_key); + + pause = FALSE; + if (pausetask == 1) { + if (evt_any_task_in_state(game, completed)) + pause = TRUE; + } else if (pausetask > 1) { + if (completed == gs_task_done(game, pausetask - 2)) + pause = TRUE; + } + + return pause; } static sc_bool -evt_resumer_task_is_complete (sc_gameref_t game, sc_int event) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[3]; - sc_int resumetask; - sc_bool completed, resume; - - vt_key[0].string = "Events"; - vt_key[1].integer = event; - - vt_key[2].string = "ResumeTask"; - resumetask = prop_get_integer (bundle, "I<-sis", vt_key); - vt_key[2].string = "ResumerCompleted"; - completed = !prop_get_boolean (bundle, "B<-sis", vt_key); - - resume = FALSE; - if (resumetask == 1) - { - if (evt_any_task_in_state (game, completed)) - resume = TRUE; - } - else if (resumetask > 1) - { - if (completed == gs_task_done (game, resumetask - 2)) - resume = TRUE; - } - - return resume; +evt_resumer_task_is_complete(sc_gameref_t game, sc_int event) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[3]; + sc_int resumetask; + sc_bool completed, resume; + + vt_key[0].string = "Events"; + vt_key[1].integer = event; + + vt_key[2].string = "ResumeTask"; + resumetask = prop_get_integer(bundle, "I<-sis", vt_key); + vt_key[2].string = "ResumerCompleted"; + completed = !prop_get_boolean(bundle, "B<-sis", vt_key); + + resume = FALSE; + if (resumetask == 1) { + if (evt_any_task_in_state(game, completed)) + resume = TRUE; + } else if (resumetask > 1) { + if (completed == gs_task_done(game, resumetask - 2)) + resume = TRUE; + } + + return resume; } @@ -549,50 +509,45 @@ evt_resumer_task_is_complete (sc_gameref_t game, sc_int event) * and getting close to some number of turns from its end. */ static void -evt_handle_preftime_notifications (sc_gameref_t game, sc_int event) -{ - const sc_filterref_t filter = gs_get_filter (game); - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[4]; - sc_int preftime1, preftime2; - const sc_char *preftext; - - vt_key[0].string = "Events"; - vt_key[1].integer = event; - - vt_key[2].string = "PrefTime1"; - preftime1 = prop_get_integer (bundle, "I<-sis", vt_key); - if (preftime1 == gs_event_time (game, event)) - { - vt_key[2].string = "PrefText1"; - preftext = prop_get_string (bundle, "S<-sis", vt_key); - if (!sc_strempty (preftext)) - { - pf_buffer_string (filter, preftext); - pf_buffer_character (filter, '\n'); - } - - vt_key[2].string = "Res"; - vt_key[3].integer = 2; - res_handle_resource (game, "sisi", vt_key); - } - - vt_key[2].string = "PrefTime2"; - preftime2 = prop_get_integer (bundle, "I<-sis", vt_key); - if (preftime2 == gs_event_time (game, event)) - { - vt_key[2].string = "PrefText2"; - preftext = prop_get_string (bundle, "S<-sis", vt_key); - if (!sc_strempty (preftext)) - { - pf_buffer_string (filter, preftext); - pf_buffer_character (filter, '\n'); - } - - vt_key[2].string = "Res"; - vt_key[3].integer = 3; - res_handle_resource (game, "sisi", vt_key); - } +evt_handle_preftime_notifications(sc_gameref_t game, sc_int event) { + const sc_filterref_t filter = gs_get_filter(game); + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[4]; + sc_int preftime1, preftime2; + const sc_char *preftext; + + vt_key[0].string = "Events"; + vt_key[1].integer = event; + + vt_key[2].string = "PrefTime1"; + preftime1 = prop_get_integer(bundle, "I<-sis", vt_key); + if (preftime1 == gs_event_time(game, event)) { + vt_key[2].string = "PrefText1"; + preftext = prop_get_string(bundle, "S<-sis", vt_key); + if (!sc_strempty(preftext)) { + pf_buffer_string(filter, preftext); + pf_buffer_character(filter, '\n'); + } + + vt_key[2].string = "Res"; + vt_key[3].integer = 2; + res_handle_resource(game, "sisi", vt_key); + } + + vt_key[2].string = "PrefTime2"; + preftime2 = prop_get_integer(bundle, "I<-sis", vt_key); + if (preftime2 == gs_event_time(game, event)) { + vt_key[2].string = "PrefText2"; + preftext = prop_get_string(bundle, "S<-sis", vt_key); + if (!sc_strempty(preftext)) { + pf_buffer_string(filter, preftext); + pf_buffer_character(filter, '\n'); + } + + vt_key[2].string = "Res"; + vt_key[3].integer = 3; + res_handle_resource(game, "sisi", vt_key); + } } @@ -602,203 +557,183 @@ evt_handle_preftime_notifications (sc_gameref_t game, sc_int event) * Attempt to advance an event by one turn. */ static void -evt_tick_event (sc_gameref_t game, sc_int event) -{ - if (evt_trace) - { - sc_trace ("Event: ticking event %ld: state %ld, time %ld\n", event, - gs_event_state (game, event), gs_event_time (game, event)); - } - - /* Handle call based on current event state. */ - switch (gs_event_state (game, event)) - { - case ES_WAITING: - { - if (evt_trace) - sc_trace ("Event: ticking waiting event %ld\n", event); - - /* - * Because we also tick an event that goes from waiting to running, - * events started here will tick through RUNNING too, and have their - * time decremented. To get around this, so that the timer for one- - * shot events doesn't look one lower than it should after this - * transition, we need to set the initial time for events that start - * as soon as the game starts to one greater than that set by - * evt_start_time(). Here's the hack to do that; if the event starts - * immediately, its time will already be zero, even before decrement, - * which is how we tell which events to apply this hack to. - * - * TODO This seems to work, but also seems very dodgy. - */ - if (gs_event_time (game, event) == 0) - { - evt_start_event (game, event); - - /* If the event time was set to zero, finish immediately. */ - if (gs_event_time (game, event) <= 0) - evt_finish_event (game, event); - else - gs_set_event_time (game, event, gs_event_time (game, event) + 1); - break; - } - - /* - * Decrement the event's time, and if it goes to zero, start running - * the event. - */ - gs_decrement_event_time (game, event); - - if (gs_event_time (game, event) <= 0) - { - evt_start_event (game, event); - - /* If the event time was set to zero, finish immediately. */ - if (gs_event_time (game, event) <= 0) - evt_finish_event (game, event); - } - } - break; - - case ES_RUNNING: - { - if (evt_trace) - sc_trace ("Event: ticking running event %ld\n", event); - - /* - * Re-check the starter task; if it's no longer completed, we need - * to set the event back to waiting on task. - */ - if (evt_has_starter_task (game, event)) - { - if (!evt_starter_task_is_complete (game, event)) - { - if (evt_trace) - sc_trace ("Event: starter task not complete\n"); - - gs_set_event_state (game, event, ES_AWAITING); - gs_set_event_time (game, event, 0); - break; - } - } - - /* If the pauser has completed, but resumer not, pause this event. */ - if (evt_pauser_task_is_complete (game, event) - && !evt_resumer_task_is_complete (game, event)) - { - if (evt_trace) - sc_trace ("Event: pause complete\n"); - - gs_set_event_state (game, event, ES_PAUSED); - break; - } - - /* - * Decrement the event's time, and print any notifications for a set - * number of turns from the event end. - */ - gs_decrement_event_time (game, event); - - if (evt_can_see_event (game, event)) - evt_handle_preftime_notifications (game, event); - - /* If the time goes to zero, finish running the event. */ - if (gs_event_time (game, event) <= 0) - evt_finish_event (game, event); - } - break; - - case ES_AWAITING: - { - if (evt_trace) - sc_trace ("Event: ticking awaiting event %ld\n", event); - - /* - * Check the starter task. If it's completed, start running the - * event. - */ - if (evt_starter_task_is_complete (game, event)) - { - evt_start_event (game, event); - - /* If the event time was set to zero, finish immediately. */ - if (gs_event_time (game, event) <= 0) - evt_finish_event (game, event); - else - { - /* - * If the pauser has completed, but resumer not, immediately - * also pause this event. - */ - if (evt_pauser_task_is_complete (game, event) - && !evt_resumer_task_is_complete (game, event)) - { - if (evt_trace) - sc_trace ("Event: pause complete, immediate pause\n"); - - gs_set_event_state (game, event, ES_PAUSED); - } - } - } - } - break; - - case ES_FINISHED: - { - if (evt_trace) - sc_trace ("Event: ticking finished event %ld\n", event); - - /* - * Check the starter task; if it's not completed, we need to set the - * event back to waiting on task. - * - * A completed event needs to go back to waiting on its task, but we - * don't want to set it there as soon as the event finishes. We need - * to wait for the starter task to first become undone, otherwise the - * event just cycles endlessly, and they don't in Adrift itself. Here - * is where we wait for starter tasks to become undone. - */ - if (evt_has_starter_task (game, event)) - { - if (!evt_starter_task_is_complete (game, event)) - { - if (evt_trace) - sc_trace ("Event: starter task not complete\n"); - - gs_set_event_state (game, event, ES_AWAITING); - gs_set_event_time (game, event, 0); - break; - } - } - } - break; - - case ES_PAUSED: - { - if (evt_trace) - sc_trace ("Event: ticking paused event %ld\n", event); - - /* If the resumer has completed, resume this event. */ - if (evt_resumer_task_is_complete (game, event)) - { - if (evt_trace) - sc_trace ("Event: resume complete\n"); - - gs_set_event_state (game, event, ES_RUNNING); - break; - } - } - break; - - default: - sc_fatal ("evt_tick: invalid event state\n"); - } - - if (evt_trace) - { - sc_trace ("Event: after ticking event %ld: state %ld, time %ld\n", event, - gs_event_state (game, event), gs_event_time (game, event)); - } +evt_tick_event(sc_gameref_t game, sc_int event) { + if (evt_trace) { + sc_trace("Event: ticking event %ld: state %ld, time %ld\n", event, + gs_event_state(game, event), gs_event_time(game, event)); + } + + /* Handle call based on current event state. */ + switch (gs_event_state(game, event)) { + case ES_WAITING: { + if (evt_trace) + sc_trace("Event: ticking waiting event %ld\n", event); + + /* + * Because we also tick an event that goes from waiting to running, + * events started here will tick through RUNNING too, and have their + * time decremented. To get around this, so that the timer for one- + * shot events doesn't look one lower than it should after this + * transition, we need to set the initial time for events that start + * as soon as the game starts to one greater than that set by + * evt_start_time(). Here's the hack to do that; if the event starts + * immediately, its time will already be zero, even before decrement, + * which is how we tell which events to apply this hack to. + * + * TODO This seems to work, but also seems very dodgy. + */ + if (gs_event_time(game, event) == 0) { + evt_start_event(game, event); + + /* If the event time was set to zero, finish immediately. */ + if (gs_event_time(game, event) <= 0) + evt_finish_event(game, event); + else + gs_set_event_time(game, event, gs_event_time(game, event) + 1); + break; + } + + /* + * Decrement the event's time, and if it goes to zero, start running + * the event. + */ + gs_decrement_event_time(game, event); + + if (gs_event_time(game, event) <= 0) { + evt_start_event(game, event); + + /* If the event time was set to zero, finish immediately. */ + if (gs_event_time(game, event) <= 0) + evt_finish_event(game, event); + } + } + break; + + case ES_RUNNING: { + if (evt_trace) + sc_trace("Event: ticking running event %ld\n", event); + + /* + * Re-check the starter task; if it's no longer completed, we need + * to set the event back to waiting on task. + */ + if (evt_has_starter_task(game, event)) { + if (!evt_starter_task_is_complete(game, event)) { + if (evt_trace) + sc_trace("Event: starter task not complete\n"); + + gs_set_event_state(game, event, ES_AWAITING); + gs_set_event_time(game, event, 0); + break; + } + } + + /* If the pauser has completed, but resumer not, pause this event. */ + if (evt_pauser_task_is_complete(game, event) + && !evt_resumer_task_is_complete(game, event)) { + if (evt_trace) + sc_trace("Event: pause complete\n"); + + gs_set_event_state(game, event, ES_PAUSED); + break; + } + + /* + * Decrement the event's time, and print any notifications for a set + * number of turns from the event end. + */ + gs_decrement_event_time(game, event); + + if (evt_can_see_event(game, event)) + evt_handle_preftime_notifications(game, event); + + /* If the time goes to zero, finish running the event. */ + if (gs_event_time(game, event) <= 0) + evt_finish_event(game, event); + } + break; + + case ES_AWAITING: { + if (evt_trace) + sc_trace("Event: ticking awaiting event %ld\n", event); + + /* + * Check the starter task. If it's completed, start running the + * event. + */ + if (evt_starter_task_is_complete(game, event)) { + evt_start_event(game, event); + + /* If the event time was set to zero, finish immediately. */ + if (gs_event_time(game, event) <= 0) + evt_finish_event(game, event); + else { + /* + * If the pauser has completed, but resumer not, immediately + * also pause this event. + */ + if (evt_pauser_task_is_complete(game, event) + && !evt_resumer_task_is_complete(game, event)) { + if (evt_trace) + sc_trace("Event: pause complete, immediate pause\n"); + + gs_set_event_state(game, event, ES_PAUSED); + } + } + } + } + break; + + case ES_FINISHED: { + if (evt_trace) + sc_trace("Event: ticking finished event %ld\n", event); + + /* + * Check the starter task; if it's not completed, we need to set the + * event back to waiting on task. + * + * A completed event needs to go back to waiting on its task, but we + * don't want to set it there as soon as the event finishes. We need + * to wait for the starter task to first become undone, otherwise the + * event just cycles endlessly, and they don't in Adrift itself. Here + * is where we wait for starter tasks to become undone. + */ + if (evt_has_starter_task(game, event)) { + if (!evt_starter_task_is_complete(game, event)) { + if (evt_trace) + sc_trace("Event: starter task not complete\n"); + + gs_set_event_state(game, event, ES_AWAITING); + gs_set_event_time(game, event, 0); + break; + } + } + } + break; + + case ES_PAUSED: { + if (evt_trace) + sc_trace("Event: ticking paused event %ld\n", event); + + /* If the resumer has completed, resume this event. */ + if (evt_resumer_task_is_complete(game, event)) { + if (evt_trace) + sc_trace("Event: resume complete\n"); + + gs_set_event_state(game, event, ES_RUNNING); + break; + } + } + break; + + default: + sc_fatal("evt_tick: invalid event state\n"); + } + + if (evt_trace) { + sc_trace("Event: after ticking event %ld: state %ld, time %ld\n", event, + gs_event_state(game, event), gs_event_time(game, event)); + } } @@ -808,35 +743,33 @@ evt_tick_event (sc_gameref_t game, sc_int event) * Attempt to advance each event by one turn. */ void -evt_tick_events (sc_gameref_t game) -{ - sc_int event; - - /* - * Tick all events. If an event transitions into a running state from a - * paused or waiting state, tick that event again. - */ - for (event = 0; event < gs_event_count (game); event++) - { - sc_int prior_state, state; - - /* Note current state, and tick event forwards. */ - prior_state = gs_event_state (game, event); - evt_tick_event (game, event); - - /* - * If the event went from paused or waiting to running, tick again. - * This looks dodgy, and probably is, but it does keep timers correct - * by only re-ticking events that have transitioned from non-running - * states to a running one, and not already-running events. This is - * in effect just adding a bit of turn processing to a tick that would - * otherwise change state alone; a bit of laziness, in other words. - */ - state = gs_event_state (game, event); - if (state == ES_RUNNING - && (prior_state == ES_PAUSED || prior_state == ES_WAITING)) - evt_tick_event (game, event); - } +evt_tick_events(sc_gameref_t game) { + sc_int event; + + /* + * Tick all events. If an event transitions into a running state from a + * paused or waiting state, tick that event again. + */ + for (event = 0; event < gs_event_count(game); event++) { + sc_int prior_state, state; + + /* Note current state, and tick event forwards. */ + prior_state = gs_event_state(game, event); + evt_tick_event(game, event); + + /* + * If the event went from paused or waiting to running, tick again. + * This looks dodgy, and probably is, but it does keep timers correct + * by only re-ticking events that have transitioned from non-running + * states to a running one, and not already-running events. This is + * in effect just adding a bit of turn processing to a tick that would + * otherwise change state alone; a bit of laziness, in other words. + */ + state = gs_event_state(game, event); + if (state == ES_RUNNING + && (prior_state == ES_PAUSED || prior_state == ES_WAITING)) + evt_tick_event(game, event); + } } @@ -846,9 +779,8 @@ evt_tick_events (sc_gameref_t game) * Set event tracing on/off. */ void -evt_debug_trace (sc_bool flag) -{ - evt_trace = flag; +evt_debug_trace(sc_bool flag) { + evt_trace = flag; } } // End of namespace Adrift |