diff options
Diffstat (limited to 'engines/glk/adrift/screstrs.cpp')
-rw-r--r-- | engines/glk/adrift/screstrs.cpp | 1688 |
1 files changed, 805 insertions, 883 deletions
diff --git a/engines/glk/adrift/screstrs.cpp b/engines/glk/adrift/screstrs.cpp index 549ae5a50d..3f1db887f4 100644 --- a/engines/glk/adrift/screstrs.cpp +++ b/engines/glk/adrift/screstrs.cpp @@ -41,29 +41,27 @@ static sc_bool restr_trace = FALSE; * Return the index of the n'th integer found. */ static sc_int -restr_integer_variable (sc_gameref_t game, sc_int n) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[3]; - sc_int var_count, var, count; - - /* Get the count of variables. */ - vt_key[0].string = "Variables"; - var_count = prop_get_child_count (bundle, "I<-s", vt_key); - - /* Progress through variables until n integers found. */ - count = n; - for (var = 0; var < var_count && count >= 0; var++) - { - sc_int type; - - vt_key[1].integer = var; - vt_key[2].string = "Type"; - type = prop_get_integer (bundle, "I<-sis", vt_key); - if (type == TAFVAR_NUMERIC) - count--; - } - return var - 1; +restr_integer_variable(sc_gameref_t game, sc_int n) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[3]; + sc_int var_count, var, count; + + /* Get the count of variables. */ + vt_key[0].string = "Variables"; + var_count = prop_get_child_count(bundle, "I<-s", vt_key); + + /* Progress through variables until n integers found. */ + count = n; + for (var = 0; var < var_count && count >= 0; var++) { + sc_int type; + + vt_key[1].integer = var; + vt_key[2].string = "Type"; + type = prop_get_integer(bundle, "I<-sis", vt_key); + if (type == TAFVAR_NUMERIC) + count--; + } + return var - 1; } @@ -73,87 +71,84 @@ restr_integer_variable (sc_gameref_t game, sc_int n) * Is object in a certain place, state, or condition. */ static sc_bool -restr_object_in_place (sc_gameref_t game, - sc_int object, sc_int var2, sc_int var3) -{ - const sc_var_setref_t vars = gs_get_vars (game); - sc_int npc; - - if (restr_trace) - { - sc_trace ("Restr: checking" - " object in place, %ld, %ld, %ld\n", object, var2, var3); - } - - /* Var2 controls what we do. */ - switch (var2) - { - case 0: - case 6: /* In room */ - if (var3 == 0) - return gs_object_position (game, object) == OBJ_HIDDEN; - else - return gs_object_position (game, object) == var3; - - case 1: - case 7: /* Held by */ - if (var3 == 0) /* Player */ - return gs_object_position (game, object) == OBJ_HELD_PLAYER; - else if (var3 == 1) /* Ref character */ - npc = var_get_ref_character (vars); - else - npc = var3 - 2; - - return gs_object_position (game, object) == OBJ_HELD_NPC - && gs_object_parent (game, object) == npc; - - case 2: - case 8: /* Worn by */ - if (var3 == 0) /* Player */ - return gs_object_position (game, object) == OBJ_WORN_PLAYER; - else if (var3 == 1) /* Ref character */ - npc = var_get_ref_character (vars); - else - npc = var3 - 2; - - return gs_object_position (game, object) == OBJ_WORN_NPC - && gs_object_parent (game, object) == npc; - - case 3: - case 9: /* Visible to */ - if (var3 == 0) /* Player */ - return obj_indirectly_in_room (game, - object, gs_playerroom (game)); - else if (var3 == 1) /* Ref character */ - npc = var_get_ref_character (vars); - else - npc = var3 - 2; - - return obj_indirectly_in_room (game, object, - gs_npc_location (game, npc) - 1); - - case 4: - case 10: /* Inside */ - if (var3 == 0) /* Nothing? */ - return gs_object_position (game, object) != OBJ_IN_OBJECT; - - return gs_object_position (game, object) == OBJ_IN_OBJECT - && gs_object_parent (game, object) == obj_container_object (game, - var3 - 1); - - case 5: - case 11: /* On top of */ - if (var3 == 0) /* Nothing? */ - return gs_object_position (game, object) != OBJ_ON_OBJECT; - - return gs_object_position (game, object) == OBJ_ON_OBJECT - && gs_object_parent (game, object) == obj_surface_object (game, - var3 - 1); - - default: - sc_fatal ("restr_object_in_place: bad var2, %ld\n", var2); - return FALSE; - } +restr_object_in_place(sc_gameref_t game, + sc_int object, sc_int var2, sc_int var3) { + const sc_var_setref_t vars = gs_get_vars(game); + sc_int npc; + + if (restr_trace) { + sc_trace("Restr: checking" + " object in place, %ld, %ld, %ld\n", object, var2, var3); + } + + /* Var2 controls what we do. */ + switch (var2) { + case 0: + case 6: /* In room */ + if (var3 == 0) + return gs_object_position(game, object) == OBJ_HIDDEN; + else + return gs_object_position(game, object) == var3; + + case 1: + case 7: /* Held by */ + if (var3 == 0) /* Player */ + return gs_object_position(game, object) == OBJ_HELD_PLAYER; + else if (var3 == 1) /* Ref character */ + npc = var_get_ref_character(vars); + else + npc = var3 - 2; + + return gs_object_position(game, object) == OBJ_HELD_NPC + && gs_object_parent(game, object) == npc; + + case 2: + case 8: /* Worn by */ + if (var3 == 0) /* Player */ + return gs_object_position(game, object) == OBJ_WORN_PLAYER; + else if (var3 == 1) /* Ref character */ + npc = var_get_ref_character(vars); + else + npc = var3 - 2; + + return gs_object_position(game, object) == OBJ_WORN_NPC + && gs_object_parent(game, object) == npc; + + case 3: + case 9: /* Visible to */ + if (var3 == 0) /* Player */ + return obj_indirectly_in_room(game, + object, gs_playerroom(game)); + else if (var3 == 1) /* Ref character */ + npc = var_get_ref_character(vars); + else + npc = var3 - 2; + + return obj_indirectly_in_room(game, object, + gs_npc_location(game, npc) - 1); + + case 4: + case 10: /* Inside */ + if (var3 == 0) /* Nothing? */ + return gs_object_position(game, object) != OBJ_IN_OBJECT; + + return gs_object_position(game, object) == OBJ_IN_OBJECT + && gs_object_parent(game, object) == obj_container_object(game, + var3 - 1); + + case 5: + case 11: /* On top of */ + if (var3 == 0) /* Nothing? */ + return gs_object_position(game, object) != OBJ_ON_OBJECT; + + return gs_object_position(game, object) == OBJ_ON_OBJECT + && gs_object_parent(game, object) == obj_surface_object(game, + var3 - 1); + + default: + sc_fatal("restr_object_in_place: bad var2, %ld\n", var2); + return FALSE; + } } @@ -163,78 +158,70 @@ restr_object_in_place (sc_gameref_t game, * Evaluate restrictions relating to object location. */ static sc_bool -restr_pass_task_object_location (sc_gameref_t game, - sc_int var1, sc_int var2, sc_int var3) -{ - const sc_var_setref_t vars = gs_get_vars (game); - sc_bool should_be; - sc_int object; - - if (restr_trace) - { - sc_trace ("Restr: running object" - " location restriction, %ld, %ld, %ld\n", var1, var2, var3); - } - - /* Initialize variables to avoid gcc warnings. */ - should_be = FALSE; - object = -1; - - /* See how things should look. */ - if (var2 >= 0 && var2 < 6) - should_be = TRUE; - else if (var2 >= 6 && var2 < 12) - should_be = FALSE; - else - sc_fatal ("restr_pass_task_object_location: bad var2, %ld\n", var2); - - /* Now find the addressed object. */ - if (var1 == 0) - { - object = -1; /* No object */ - should_be = !should_be; - } - else if (var1 == 1) - object = -1; /* Any object */ - else if (var1 == 2) - object = var_get_ref_object (vars); - else if (var1 >= 3) - object = obj_dynamic_object (game, var1 - 3); - else - sc_fatal ("restr_pass_task_object_location: bad var1, %ld\n", var1); - - /* - * Here it seems that we have to special case static objects that may have - * crept in through the referenced object. The object in place function - * isn't built to handle these. - * - * TODO What is the meaning of applying object restrictions to static - * objects? - */ - if (var1 == 2 && object != -1 && obj_is_static (game, object)) - { - if (restr_trace) - { - sc_trace ("Restr:" - " restriction object %ld is static, rejecting\n", object); - } - - return FALSE; - } - - /* Try to put it all together. */ - if (object == -1) - { - sc_int target; - - for (target = 0; target < gs_object_count (game); target++) - { - if (restr_object_in_place (game, target, var2, var3)) - return should_be; - } - return !should_be; - } - return should_be == restr_object_in_place (game, object, var2, var3); +restr_pass_task_object_location(sc_gameref_t game, + sc_int var1, sc_int var2, sc_int var3) { + const sc_var_setref_t vars = gs_get_vars(game); + sc_bool should_be; + sc_int object; + + if (restr_trace) { + sc_trace("Restr: running object" + " location restriction, %ld, %ld, %ld\n", var1, var2, var3); + } + + /* Initialize variables to avoid gcc warnings. */ + should_be = FALSE; + object = -1; + + /* See how things should look. */ + if (var2 >= 0 && var2 < 6) + should_be = TRUE; + else if (var2 >= 6 && var2 < 12) + should_be = FALSE; + else + sc_fatal("restr_pass_task_object_location: bad var2, %ld\n", var2); + + /* Now find the addressed object. */ + if (var1 == 0) { + object = -1; /* No object */ + should_be = !should_be; + } else if (var1 == 1) + object = -1; /* Any object */ + else if (var1 == 2) + object = var_get_ref_object(vars); + else if (var1 >= 3) + object = obj_dynamic_object(game, var1 - 3); + else + sc_fatal("restr_pass_task_object_location: bad var1, %ld\n", var1); + + /* + * Here it seems that we have to special case static objects that may have + * crept in through the referenced object. The object in place function + * isn't built to handle these. + * + * TODO What is the meaning of applying object restrictions to static + * objects? + */ + if (var1 == 2 && object != -1 && obj_is_static(game, object)) { + if (restr_trace) { + sc_trace("Restr:" + " restriction object %ld is static, rejecting\n", object); + } + + return FALSE; + } + + /* Try to put it all together. */ + if (object == -1) { + sc_int target; + + for (target = 0; target < gs_object_count(game); target++) { + if (restr_object_in_place(game, target, var2, var3)) + return should_be; + } + return !should_be; + } + return should_be == restr_object_in_place(game, object, var2, var3); } @@ -245,52 +232,45 @@ restr_pass_task_object_location (sc_gameref_t game, * from the library by lib_pass_alt_room(), so cannot be static. */ sc_bool -restr_pass_task_object_state (sc_gameref_t game, sc_int var1, sc_int var2) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - const sc_var_setref_t vars = gs_get_vars (game); - sc_vartype_t vt_key[3]; - sc_int object, openable, key; - - if (restr_trace) - { - sc_trace ("Restr:" - " running object state restriction, %ld, %ld\n", var1, var2); - } - - /* Find the object being addressed. */ - if (var1 == 0) - object = var_get_ref_object (vars); - else - object = obj_stateful_object (game, var1 - 1); - - /* We're interested only in openable objects. */ - vt_key[0].string = "Objects"; - vt_key[1].integer = object; - vt_key[2].string = "Openable"; - openable = prop_get_integer (bundle, "I<-sis", vt_key); - if (openable > 0) - { - /* Is this object lockable? */ - vt_key[2].string = "Key"; - key = prop_get_integer (bundle, "I<-sis", vt_key); - if (key >= 0) - { - if (var2 <= 2) - return gs_object_openness (game, object) == var2 + 5; - else - return gs_object_state (game, object) == var2 - 2; - } - else - { - if (var2 <= 1) - return gs_object_openness (game, object) == var2 + 5; - else - return gs_object_state (game, object) == var2 - 1; - } - } - else - return gs_object_state (game, object) == var2 + 1; +restr_pass_task_object_state(sc_gameref_t game, sc_int var1, sc_int var2) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + const sc_var_setref_t vars = gs_get_vars(game); + sc_vartype_t vt_key[3]; + sc_int object, openable, key; + + if (restr_trace) { + sc_trace("Restr:" + " running object state restriction, %ld, %ld\n", var1, var2); + } + + /* Find the object being addressed. */ + if (var1 == 0) + object = var_get_ref_object(vars); + else + object = obj_stateful_object(game, var1 - 1); + + /* We're interested only in openable objects. */ + vt_key[0].string = "Objects"; + vt_key[1].integer = object; + vt_key[2].string = "Openable"; + openable = prop_get_integer(bundle, "I<-sis", vt_key); + if (openable > 0) { + /* Is this object lockable? */ + vt_key[2].string = "Key"; + key = prop_get_integer(bundle, "I<-sis", vt_key); + if (key >= 0) { + if (var2 <= 2) + return gs_object_openness(game, object) == var2 + 5; + else + return gs_object_state(game, object) == var2 - 2; + } else { + if (var2 <= 1) + return gs_object_openness(game, object) == var2 + 5; + else + return gs_object_state(game, object) == var2 - 1; + } + } else + return gs_object_state(game, object) == var2 + 1; } @@ -300,39 +280,36 @@ restr_pass_task_object_state (sc_gameref_t game, sc_int var1, sc_int var2) * Evaluate restrictions relating to task states. */ static sc_bool -restr_pass_task_task_state (sc_gameref_t game, sc_int var1, sc_int var2) -{ - sc_bool should_be; - - if (restr_trace) - sc_trace ("Restr: running task restriction, %ld, %ld\n", var1, var2); - - /* Initialize variables to avoid gcc warnings. */ - should_be = FALSE; - - /* See if the task should be done or not done. */ - if (var2 == 0) - should_be = TRUE; - else if (var2 == 1) - should_be = FALSE; - else - sc_fatal ("restr_pass_task_task_state: bad var2, %ld\n", var2); - - /* Check all tasks? */ - if (var1 == 0) - { - sc_int task; - - for (task = 0; task < gs_task_count (game); task++) - { - if (gs_task_done (game, task) == should_be) - return FALSE; - } - return TRUE; - } - - /* Check just the given task. */ - return gs_task_done (game, var1 - 1) == should_be; +restr_pass_task_task_state(sc_gameref_t game, sc_int var1, sc_int var2) { + sc_bool should_be; + + if (restr_trace) + sc_trace("Restr: running task restriction, %ld, %ld\n", var1, var2); + + /* Initialize variables to avoid gcc warnings. */ + should_be = FALSE; + + /* See if the task should be done or not done. */ + if (var2 == 0) + should_be = TRUE; + else if (var2 == 1) + should_be = FALSE; + else + sc_fatal("restr_pass_task_task_state: bad var2, %ld\n", var2); + + /* Check all tasks? */ + if (var1 == 0) { + sc_int task; + + for (task = 0; task < gs_task_count(game); task++) { + if (gs_task_done(game, task) == should_be) + return FALSE; + } + return TRUE; + } + + /* Check just the given task. */ + return gs_task_done(game, var1 - 1) == should_be; } @@ -342,123 +319,116 @@ restr_pass_task_task_state (sc_gameref_t game, sc_int var1, sc_int var2) * Evaluate restrictions relating to player and NPCs. */ static sc_bool -restr_pass_task_char (sc_gameref_t game, sc_int var1, sc_int var2, sc_int var3) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - const sc_var_setref_t vars = gs_get_vars (game); - sc_int npc1, npc2; - - if (restr_trace) - { - sc_trace ("Restr:" - " running char restriction, %ld, %ld, %ld\n", var1, var2, var3); - } - - /* Handle var2 types 1 and 2. */ - if (var2 == 1) /* Not in same room as */ - return !restr_pass_task_char (game, var1, 0, var3); - else if (var2 == 2) /* Alone */ - return !restr_pass_task_char (game, var1, 3, var3); - - /* Decode NPC number, -1 if none. */ - npc1 = npc2 = -1; - if (var1 == 1) - npc1 = var_get_ref_character (vars); - else if (var1 > 1) - npc1 = var1 - 2; - - /* Player or NPC? */ - if (var1 == 0) - { - sc_vartype_t vt_key[2]; - sc_int gender; - - /* Player -- decode based on var2. */ - switch (var2) - { - case 0: /* In same room as */ - if (var3 == 1) - npc2 = var_get_ref_character (vars); - else if (var3 > 1) - npc2 = var3 - 2; - if (var3 == 0) /* Player */ - return TRUE; - else - return npc_in_room (game, npc2, gs_playerroom (game)); - - case 3: /* Not alone */ - return npc_count_in_room (game, gs_playerroom (game)) > 1; - - case 4: /* Standing on */ - return gs_playerposition (game) == 0 - && gs_playerparent (game) == obj_standable_object (game, - var3 - 1); - - case 5: /* Sitting on */ - return gs_playerposition (game) == 1 - && gs_playerparent (game) == obj_standable_object (game, - var3 - 1); - - case 6: /* Lying on */ - return gs_playerposition (game) == 2 - && gs_playerparent (game) == obj_lieable_object (game, - var3 - 1); - - case 7: /* Player gender */ - vt_key[0].string = "Globals"; - vt_key[1].string = "PlayerGender"; - gender = prop_get_integer (bundle, "I<-ss", vt_key); - return gender == var3; - - default: - sc_fatal ("restr_pass_task_char: invalid type, %ld\n", var2); - return FALSE; - } - } - else - { - sc_vartype_t vt_key[3]; - sc_int gender; - - /* NPC -- decode based on var2. */ - switch (var2) - { - case 0: /* In same room as */ - if (var3 == 0) - return npc_in_room (game, npc1, gs_playerroom (game)); - if (var3 == 1) - npc2 = var_get_ref_character (vars); - else if (var3 > 1) - npc2 = var3 - 2; - return npc_in_room (game, npc1, gs_npc_location (game, npc2) - 1); - - case 3: /* Not alone */ - return npc_count_in_room (game, gs_npc_location (game, npc1) - 1) > 1; - - case 4: /* Standing on */ - return gs_npc_position (game, npc1) == 0 - && gs_playerparent (game) == obj_standable_object (game, var3); - - case 5: /* Sitting on */ - return gs_npc_position (game, npc1) == 1 - && gs_playerparent (game) == obj_standable_object (game, var3); - - case 6: /* Lying on */ - return gs_npc_position (game, npc1) == 2 - && gs_playerparent (game) == obj_lieable_object (game, var3); - - case 7: /* NPC gender */ - vt_key[0].string = "NPCs"; - vt_key[1].integer = npc1; - vt_key[2].string = "Gender"; - gender = prop_get_integer (bundle, "I<-sis", vt_key); - return gender == var3; - - default: - sc_fatal ("restr_pass_task_char: invalid type, %ld\n", var2); - return FALSE; - } - } +restr_pass_task_char(sc_gameref_t game, sc_int var1, sc_int var2, sc_int var3) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + const sc_var_setref_t vars = gs_get_vars(game); + sc_int npc1, npc2; + + if (restr_trace) { + sc_trace("Restr:" + " running char restriction, %ld, %ld, %ld\n", var1, var2, var3); + } + + /* Handle var2 types 1 and 2. */ + if (var2 == 1) /* Not in same room as */ + return !restr_pass_task_char(game, var1, 0, var3); + else if (var2 == 2) /* Alone */ + return !restr_pass_task_char(game, var1, 3, var3); + + /* Decode NPC number, -1 if none. */ + npc1 = npc2 = -1; + if (var1 == 1) + npc1 = var_get_ref_character(vars); + else if (var1 > 1) + npc1 = var1 - 2; + + /* Player or NPC? */ + if (var1 == 0) { + sc_vartype_t vt_key[2]; + sc_int gender; + + /* Player -- decode based on var2. */ + switch (var2) { + case 0: /* In same room as */ + if (var3 == 1) + npc2 = var_get_ref_character(vars); + else if (var3 > 1) + npc2 = var3 - 2; + if (var3 == 0) /* Player */ + return TRUE; + else + return npc_in_room(game, npc2, gs_playerroom(game)); + + case 3: /* Not alone */ + return npc_count_in_room(game, gs_playerroom(game)) > 1; + + case 4: /* Standing on */ + return gs_playerposition(game) == 0 + && gs_playerparent(game) == obj_standable_object(game, + var3 - 1); + + case 5: /* Sitting on */ + return gs_playerposition(game) == 1 + && gs_playerparent(game) == obj_standable_object(game, + var3 - 1); + + case 6: /* Lying on */ + return gs_playerposition(game) == 2 + && gs_playerparent(game) == obj_lieable_object(game, + var3 - 1); + + case 7: /* Player gender */ + vt_key[0].string = "Globals"; + vt_key[1].string = "PlayerGender"; + gender = prop_get_integer(bundle, "I<-ss", vt_key); + return gender == var3; + + default: + sc_fatal("restr_pass_task_char: invalid type, %ld\n", var2); + return FALSE; + } + } else { + sc_vartype_t vt_key[3]; + sc_int gender; + + /* NPC -- decode based on var2. */ + switch (var2) { + case 0: /* In same room as */ + if (var3 == 0) + return npc_in_room(game, npc1, gs_playerroom(game)); + if (var3 == 1) + npc2 = var_get_ref_character(vars); + else if (var3 > 1) + npc2 = var3 - 2; + return npc_in_room(game, npc1, gs_npc_location(game, npc2) - 1); + + case 3: /* Not alone */ + return npc_count_in_room(game, gs_npc_location(game, npc1) - 1) > 1; + + case 4: /* Standing on */ + return gs_npc_position(game, npc1) == 0 + && gs_playerparent(game) == obj_standable_object(game, var3); + + case 5: /* Sitting on */ + return gs_npc_position(game, npc1) == 1 + && gs_playerparent(game) == obj_standable_object(game, var3); + + case 6: /* Lying on */ + return gs_npc_position(game, npc1) == 2 + && gs_playerparent(game) == obj_lieable_object(game, var3); + + case 7: /* NPC gender */ + vt_key[0].string = "NPCs"; + vt_key[1].integer = npc1; + vt_key[2].string = "Gender"; + gender = prop_get_integer(bundle, "I<-sis", vt_key); + return gender == var3; + + default: + sc_fatal("restr_pass_task_char: invalid type, %ld\n", var2); + return FALSE; + } + } } @@ -468,88 +438,82 @@ restr_pass_task_char (sc_gameref_t game, sc_int var1, sc_int var2, sc_int var3) * Helper for restr_pass_task_var(), handles integer variable restrictions. */ static sc_bool -restr_pass_task_int_var (sc_gameref_t game, - sc_int var2, sc_int var3, sc_int value) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - const sc_var_setref_t vars = gs_get_vars (game); - sc_vartype_t vt_key[3]; - sc_int value2; - - if (restr_trace) - { - sc_trace ("Restr: running" - " integer var restriction, %ld, %ld, %ld\n", var2, var3, value); - } - - /* Compare against var3 if that's what var2 says. */ - switch (var2) - { - case 0: - return value < var3; - case 1: - return value <= var3; - case 2: - return value == var3; - case 3: - return value >= var3; - case 4: - return value > var3; - case 5: - return value != var3; - - default: - /* - * Compare against the integer var numbered in var3 - 1, or the - * referenced number if var3 is zero. Make sure that we're comparing - * integer variables. - */ - if (var3 == 0) - value2 = var_get_ref_number (vars); - else - { - const sc_char *name; - sc_int ivar, type; - - ivar = restr_integer_variable (game, var3 - 1); - vt_key[0].string = "Variables"; - vt_key[1].integer = ivar; - vt_key[2].string = "Name"; - name = prop_get_string (bundle, "S<-sis", vt_key); - vt_key[2].string = "Type"; - type = prop_get_integer (bundle, "I<-sis", vt_key); - - if (type != TAFVAR_NUMERIC) - { - sc_fatal ("restr_pass_task_int_var:" - " non-integer in comparison, %s\n", name); - } - - /* Get the value in variable numbered in var3 - 1. */ - value2 = var_get_integer (vars, name); - } - - switch (var2) - { - case 10: - return value < value2; - case 11: - return value <= value2; - case 12: - return value == value2; - case 13: - return value >= value2; - case 14: - return value > value2; - case 15: - return value != value2; - - default: - sc_fatal ("restr_pass_task_int_var:" - " unknown int comparison, %ld\n", var2); - return FALSE; - } - } +restr_pass_task_int_var(sc_gameref_t game, + sc_int var2, sc_int var3, sc_int value) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + const sc_var_setref_t vars = gs_get_vars(game); + sc_vartype_t vt_key[3]; + sc_int value2; + + if (restr_trace) { + sc_trace("Restr: running" + " integer var restriction, %ld, %ld, %ld\n", var2, var3, value); + } + + /* Compare against var3 if that's what var2 says. */ + switch (var2) { + case 0: + return value < var3; + case 1: + return value <= var3; + case 2: + return value == var3; + case 3: + return value >= var3; + case 4: + return value > var3; + case 5: + return value != var3; + + default: + /* + * Compare against the integer var numbered in var3 - 1, or the + * referenced number if var3 is zero. Make sure that we're comparing + * integer variables. + */ + if (var3 == 0) + value2 = var_get_ref_number(vars); + else { + const sc_char *name; + sc_int ivar, type; + + ivar = restr_integer_variable(game, var3 - 1); + vt_key[0].string = "Variables"; + vt_key[1].integer = ivar; + vt_key[2].string = "Name"; + name = prop_get_string(bundle, "S<-sis", vt_key); + vt_key[2].string = "Type"; + type = prop_get_integer(bundle, "I<-sis", vt_key); + + if (type != TAFVAR_NUMERIC) { + sc_fatal("restr_pass_task_int_var:" + " non-integer in comparison, %s\n", name); + } + + /* Get the value in variable numbered in var3 - 1. */ + value2 = var_get_integer(vars, name); + } + + switch (var2) { + case 10: + return value < value2; + case 11: + return value <= value2; + case 12: + return value == value2; + case 13: + return value >= value2; + case 14: + return value > value2; + case 15: + return value != value2; + + default: + sc_fatal("restr_pass_task_int_var:" + " unknown int comparison, %ld\n", var2); + return FALSE; + } + } } @@ -559,28 +523,25 @@ restr_pass_task_int_var (sc_gameref_t game, * Helper for restr_pass_task_var(), handles string variable restrictions. */ static sc_bool -restr_pass_task_string_var (sc_int var2, - const sc_char *var4, const sc_char *value) -{ - if (restr_trace) - { - sc_trace ("Restr: running string" - " var restriction, %ld, \"%s\", \"%s\"\n", var2, var4, value); - } - - /* Make comparison against var4 based on var2 value. */ - switch (var2) - { - case 0: - return strcmp (value, var4) == 0; /* == */ - case 1: - return strcmp (value, var4) != 0; /* != */ - - default: - sc_fatal ("restr_pass_task_string_var:" - " unknown string comparison, %ld\n", var2); - return FALSE; - } +restr_pass_task_string_var(sc_int var2, + const sc_char *var4, const sc_char *value) { + if (restr_trace) { + sc_trace("Restr: running string" + " var restriction, %ld, \"%s\", \"%s\"\n", var2, var4, value); + } + + /* Make comparison against var4 based on var2 value. */ + switch (var2) { + case 0: + return strcmp(value, var4) == 0; /* == */ + case 1: + return strcmp(value, var4) != 0; /* != */ + + default: + sc_fatal("restr_pass_task_string_var:" + " unknown string comparison, %ld\n", var2); + return FALSE; + } } @@ -590,60 +551,54 @@ restr_pass_task_string_var (sc_int var2, * Evaluate restrictions relating to variables. */ static sc_bool -restr_pass_task_var (sc_gameref_t game, - sc_int var1, sc_int var2, sc_int var3, - const sc_char *var4) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - const sc_var_setref_t vars = gs_get_vars (game); - sc_vartype_t vt_key[3]; - sc_int type, value; - const sc_char *name, *string; - - if (restr_trace) - { - sc_trace ("Restr: running var restriction," - " %ld, %ld, %ld, \"%s\"\n", var1, var2, var3, var4); - } - - /* - * For var1=0, compare against referenced number. For var1=1, compare - * against referenced text. - */ - if (var1 == 0) - { - value = var_get_ref_number (vars); - return restr_pass_task_int_var (game, var2, var3, value); - } - else if (var1 == 1) - { - string = var_get_ref_text (vars); - return restr_pass_task_string_var (var2, var4, string); - } - - /* Get the name and type of the variable being addressed. */ - vt_key[0].string = "Variables"; - vt_key[1].integer = var1 - 2; - vt_key[2].string = "Name"; - name = prop_get_string (bundle, "S<-sis", vt_key); - vt_key[2].string = "Type"; - type = prop_get_integer (bundle, "I<-sis", vt_key); - - /* Select first based on variable type. */ - switch (type) - { - case TAFVAR_NUMERIC: - value = var_get_integer (vars, name); - return restr_pass_task_int_var (game, var2, var3, value); - - case TAFVAR_STRING: - string = var_get_string (vars, name); - return restr_pass_task_string_var (var2, var4, string); - - default: - sc_fatal ("restr_pass_task_var: invalid variable type, %ld\n", type); - return FALSE; - } +restr_pass_task_var(sc_gameref_t game, + sc_int var1, sc_int var2, sc_int var3, + const sc_char *var4) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + const sc_var_setref_t vars = gs_get_vars(game); + sc_vartype_t vt_key[3]; + sc_int type, value; + const sc_char *name, *string; + + if (restr_trace) { + sc_trace("Restr: running var restriction," + " %ld, %ld, %ld, \"%s\"\n", var1, var2, var3, var4); + } + + /* + * For var1=0, compare against referenced number. For var1=1, compare + * against referenced text. + */ + if (var1 == 0) { + value = var_get_ref_number(vars); + return restr_pass_task_int_var(game, var2, var3, value); + } else if (var1 == 1) { + string = var_get_ref_text(vars); + return restr_pass_task_string_var(var2, var4, string); + } + + /* Get the name and type of the variable being addressed. */ + vt_key[0].string = "Variables"; + vt_key[1].integer = var1 - 2; + vt_key[2].string = "Name"; + name = prop_get_string(bundle, "S<-sis", vt_key); + vt_key[2].string = "Type"; + type = prop_get_integer(bundle, "I<-sis", vt_key); + + /* Select first based on variable type. */ + switch (type) { + case TAFVAR_NUMERIC: + value = var_get_integer(vars, name); + return restr_pass_task_int_var(game, var2, var3, value); + + case TAFVAR_STRING: + string = var_get_string(vars, name); + return restr_pass_task_string_var(var2, var4, string); + + default: + sc_fatal("restr_pass_task_var: invalid variable type, %ld\n", type); + return FALSE; + } } @@ -653,102 +608,98 @@ restr_pass_task_var (sc_gameref_t game, * Demultiplexer for task restrictions. */ static sc_bool -restr_pass_task_restriction (sc_gameref_t game, sc_int task, sc_int restriction) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[5]; - sc_int type, var1, var2, var3; - const sc_char *var4; - sc_bool result = FALSE; - - if (restr_trace) - { - sc_trace ("Restr:" - " evaluating task %ld restriction %ld\n", task, restriction); - } - - /* Get the task restriction type. */ - vt_key[0].string = "Tasks"; - vt_key[1].integer = task; - vt_key[2].string = "Restrictions"; - vt_key[3].integer = restriction; - vt_key[4].string = "Type"; - type = prop_get_integer (bundle, "I<-sisis", vt_key); - - /* Demultiplex depending on type. */ - switch (type) - { - case 0: /* Object location. */ - vt_key[4].string = "Var1"; - var1 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var2"; - var2 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var3"; - var3 = prop_get_integer (bundle, "I<-sisis", vt_key); - result = restr_pass_task_object_location (game, var1, var2, var3); - break; - - case 1: /* Object state. */ - vt_key[4].string = "Var1"; - var1 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var2"; - var2 = prop_get_integer (bundle, "I<-sisis", vt_key); - result = restr_pass_task_object_state (game, var1, var2); - break; - - case 2: /* Task state. */ - vt_key[4].string = "Var1"; - var1 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var2"; - var2 = prop_get_integer (bundle, "I<-sisis", vt_key); - result = restr_pass_task_task_state (game, var1, var2); - break; - - case 3: /* Player and NPCs. */ - vt_key[4].string = "Var1"; - var1 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var2"; - var2 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var3"; - var3 = prop_get_integer (bundle, "I<-sisis", vt_key); - result = restr_pass_task_char (game, var1, var2, var3); - break; - - case 4: /* Variable. */ - vt_key[4].string = "Var1"; - var1 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var2"; - var2 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var3"; - var3 = prop_get_integer (bundle, "I<-sisis", vt_key); - vt_key[4].string = "Var4"; - var4 = prop_get_string (bundle, "S<-sisis", vt_key); - result = restr_pass_task_var (game, var1, var2, var3, var4); - break; - - default: - sc_fatal ("restr_pass_task_restriction:" - " unknown restriction type %ld\n", type); - } - - if (restr_trace) - { - sc_trace ("Restr: task %ld restriction" - " %ld is %s\n", task, restriction, result ? "PASS" : "FAIL"); - } - - return result; +restr_pass_task_restriction(sc_gameref_t game, sc_int task, sc_int restriction) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[5]; + sc_int type, var1, var2, var3; + const sc_char *var4; + sc_bool result = FALSE; + + if (restr_trace) { + sc_trace("Restr:" + " evaluating task %ld restriction %ld\n", task, restriction); + } + + /* Get the task restriction type. */ + vt_key[0].string = "Tasks"; + vt_key[1].integer = task; + vt_key[2].string = "Restrictions"; + vt_key[3].integer = restriction; + vt_key[4].string = "Type"; + type = prop_get_integer(bundle, "I<-sisis", vt_key); + + /* Demultiplex depending on type. */ + switch (type) { + case 0: /* Object location. */ + vt_key[4].string = "Var1"; + var1 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var2"; + var2 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var3"; + var3 = prop_get_integer(bundle, "I<-sisis", vt_key); + result = restr_pass_task_object_location(game, var1, var2, var3); + break; + + case 1: /* Object state. */ + vt_key[4].string = "Var1"; + var1 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var2"; + var2 = prop_get_integer(bundle, "I<-sisis", vt_key); + result = restr_pass_task_object_state(game, var1, var2); + break; + + case 2: /* Task state. */ + vt_key[4].string = "Var1"; + var1 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var2"; + var2 = prop_get_integer(bundle, "I<-sisis", vt_key); + result = restr_pass_task_task_state(game, var1, var2); + break; + + case 3: /* Player and NPCs. */ + vt_key[4].string = "Var1"; + var1 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var2"; + var2 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var3"; + var3 = prop_get_integer(bundle, "I<-sisis", vt_key); + result = restr_pass_task_char(game, var1, var2, var3); + break; + + case 4: /* Variable. */ + vt_key[4].string = "Var1"; + var1 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var2"; + var2 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var3"; + var3 = prop_get_integer(bundle, "I<-sisis", vt_key); + vt_key[4].string = "Var4"; + var4 = prop_get_string(bundle, "S<-sisis", vt_key); + result = restr_pass_task_var(game, var1, var2, var3, var4); + break; + + default: + sc_fatal("restr_pass_task_restriction:" + " unknown restriction type %ld\n", type); + } + + if (restr_trace) { + sc_trace("Restr: task %ld restriction" + " %ld is %s\n", task, restriction, result ? "PASS" : "FAIL"); + } + + return result; } /* Enumeration of restrictions combination string tokens. */ -enum -{ TOK_RESTRICTION = '#', - TOK_AND = 'A', - TOK_OR = 'O', - TOK_LPAREN = '(', - TOK_RPAREN = ')', - TOK_EOS = '\0' +enum { + TOK_RESTRICTION = '#', + TOK_AND = 'A', + TOK_OR = 'O', + TOK_LPAREN = '(', + TOK_RPAREN = ')', + TOK_EOS = '\0' }; /* #O#A(#O#)-style expression, for tokenizing. */ @@ -762,18 +713,16 @@ static sc_int restr_index = 0; * Start and wrap up restrictions combinations string tokenization. */ static void -restr_tokenize_start (const sc_char *expression) -{ - /* Save expression, and restart index. */ - restr_expression = expression; - restr_index = 0; +restr_tokenize_start(const sc_char *expression) { + /* Save expression, and restart index. */ + restr_expression = expression; + restr_index = 0; } static void -restr_tokenize_end (void) -{ - restr_expression = NULL; - restr_index = 0; +restr_tokenize_end(void) { + restr_expression = NULL; + restr_index = 0; } @@ -783,25 +732,23 @@ restr_tokenize_end (void) * Simple tokenizer for restrictions combination expressions. */ static sc_char -restr_next_token (void) -{ - assert (restr_expression); - - /* Find the next non-space, and return it. */ - while (TRUE) - { - /* Return NUL if at string end. */ - if (restr_expression[restr_index] == NUL) - return restr_expression[restr_index]; - - /* Spin on whitespace. */ - restr_index++; - if (sc_isspace (restr_expression[restr_index - 1])) - continue; - - /* Return the character just passed. */ - return restr_expression[restr_index - 1]; - } +restr_next_token(void) { + assert(restr_expression); + + /* Find the next non-space, and return it. */ + while (TRUE) { + /* Return NUL if at string end. */ + if (restr_expression[restr_index] == NUL) + return restr_expression[restr_index]; + + /* Spin on whitespace. */ + restr_index++; + if (sc_isspace(restr_expression[restr_index - 1])) + continue; + + /* Return the character just passed. */ + return restr_expression[restr_index - 1]; + } } @@ -829,18 +776,17 @@ static sc_int restr_lowest_fail = -1; * to note for when we need to evaluate a restriction. */ static void -restr_eval_start (sc_gameref_t game, sc_int task) -{ - /* Clear stack. */ - restr_eval_stack = 0; - restr_eval_restriction = 0; - - /* Note evaluation details. */ - restr_eval_game = game; - restr_eval_task = task; - - /* Clear lowest indexed failing restriction. */ - restr_lowest_fail = -1; +restr_eval_start(sc_gameref_t game, sc_int task) { + /* Clear stack. */ + restr_eval_stack = 0; + restr_eval_restriction = 0; + + /* Note evaluation details. */ + restr_eval_game = game; + restr_eval_task = task; + + /* Clear lowest indexed failing restriction. */ + restr_lowest_fail = -1; } @@ -850,12 +796,11 @@ restr_eval_start (sc_gameref_t game, sc_int task) * Push a value onto the values stack. */ static void -restr_eval_push (sc_bool value) -{ - if (restr_eval_stack >= MAX_NESTING_DEPTH) - sc_fatal ("restr_eval_push: stack overflow\n"); +restr_eval_push(sc_bool value) { + if (restr_eval_stack >= MAX_NESTING_DEPTH) + sc_fatal("restr_eval_push: stack overflow\n"); - restr_eval_values[restr_eval_stack++] = value; + restr_eval_values[restr_eval_stack++] = value; } @@ -865,68 +810,63 @@ restr_eval_push (sc_bool value) * Evaluate the effect of an and/or into the values stack. */ static void -restr_eval_action (sc_char token) -{ - /* Select action based on parsed token. */ - switch (token) - { - /* Handle evaluating and pushing a restriction result. */ - case TOK_RESTRICTION: - { - sc_bool result; - - /* Evaluate and push the next restriction. */ - result = restr_pass_task_restriction (restr_eval_game, - restr_eval_task, - restr_eval_restriction); - restr_eval_push (result); - - /* - * If the restriction failed, and there isn't yet a first failing one - * set, note this one as the first to fail. - */ - if (restr_lowest_fail == -1 && !result) - restr_lowest_fail = restr_eval_restriction; - - /* Increment restriction sequence identifier. */ - restr_eval_restriction++; - break; - } - - /* Handle cases of or-ing/and-ing restrictions. */ - case TOK_OR: - case TOK_AND: - { - sc_bool val1, val2, result = FALSE; - assert (restr_eval_stack >= 2); - - /* Get the top two stack values. */ - val1 = restr_eval_values[restr_eval_stack - 2]; - val2 = restr_eval_values[restr_eval_stack - 1]; - - /* Or, or and, into result. */ - switch (token) - { - case TOK_OR: - result = val1 || val2; - break; - case TOK_AND: - result = val1 && val2; - break; - - default: - sc_fatal ("restr_eval_action: bad token, '%c'\n", token); - } - - /* Put result back at top of stack. */ - restr_eval_stack--; - restr_eval_values[restr_eval_stack - 1] = result; - break; - } - - default: - sc_fatal ("restr_eval_action: bad token, '%c'\n", token); - } +restr_eval_action(sc_char token) { + /* Select action based on parsed token. */ + switch (token) { + /* Handle evaluating and pushing a restriction result. */ + case TOK_RESTRICTION: { + sc_bool result; + + /* Evaluate and push the next restriction. */ + result = restr_pass_task_restriction(restr_eval_game, + restr_eval_task, + restr_eval_restriction); + restr_eval_push(result); + + /* + * If the restriction failed, and there isn't yet a first failing one + * set, note this one as the first to fail. + */ + if (restr_lowest_fail == -1 && !result) + restr_lowest_fail = restr_eval_restriction; + + /* Increment restriction sequence identifier. */ + restr_eval_restriction++; + break; + } + + /* Handle cases of or-ing/and-ing restrictions. */ + case TOK_OR: + case TOK_AND: { + sc_bool val1, val2, result = FALSE; + assert(restr_eval_stack >= 2); + + /* Get the top two stack values. */ + val1 = restr_eval_values[restr_eval_stack - 2]; + val2 = restr_eval_values[restr_eval_stack - 1]; + + /* Or, or and, into result. */ + switch (token) { + case TOK_OR: + result = val1 || val2; + break; + case TOK_AND: + result = val1 && val2; + break; + + default: + sc_fatal("restr_eval_action: bad token, '%c'\n", token); + } + + /* Put result back at top of stack. */ + restr_eval_stack--; + restr_eval_values[restr_eval_stack - 1] = result; + break; + } + + default: + sc_fatal("restr_eval_action: bad token, '%c'\n", token); + } } @@ -936,13 +876,12 @@ restr_eval_action (sc_char token) * Return the top of the values stack as the evaluation result. */ static sc_int -restr_eval_result (sc_int *lowest_fail) -{ - if (restr_eval_stack != 1) - sc_fatal ("restr_eval_result: values stack not completed\n"); +restr_eval_result(sc_int *lowest_fail) { + if (restr_eval_stack != 1) + sc_fatal("restr_eval_result: values stack not completed\n"); - *lowest_fail = restr_lowest_fail; - return restr_eval_values[0]; + *lowest_fail = restr_lowest_fail; + return restr_eval_values[0]; } @@ -958,21 +897,19 @@ static sc_char restr_lookahead = '\0'; * Match a token with an expectation. */ static void -restr_match (sc_char c) -{ - if (restr_lookahead == c) - restr_lookahead = restr_next_token (); - else - { - sc_error ("restr_match:" - " syntax error, expected %d, got %d\n", c, restr_lookahead); - longjmp (restr_parse_error, 1); - } +restr_match(sc_char c) { + if (restr_lookahead == c) + restr_lookahead = restr_next_token(); + else { + sc_error("restr_match:" + " syntax error, expected %d, got %d\n", c, restr_lookahead); + longjmp(restr_parse_error, 1); + } } /* Forward declaration for recursion. */ -static void restr_bexpr (void); +static void restr_bexpr(void); /* * restr_andexpr() @@ -982,49 +919,43 @@ static void restr_bexpr (void); * Expression parsers. Here we go again... */ static void -restr_andexpr (void) -{ - restr_bexpr (); - while (restr_lookahead == TOK_AND) - { - restr_match (TOK_AND); - restr_bexpr (); - restr_eval_action (TOK_AND); - } +restr_andexpr(void) { + restr_bexpr(); + while (restr_lookahead == TOK_AND) { + restr_match(TOK_AND); + restr_bexpr(); + restr_eval_action(TOK_AND); + } } static void -restr_orexpr (void) -{ - restr_andexpr (); - while (restr_lookahead == TOK_OR) - { - restr_match (TOK_OR); - restr_andexpr (); - restr_eval_action (TOK_OR); - } +restr_orexpr(void) { + restr_andexpr(); + while (restr_lookahead == TOK_OR) { + restr_match(TOK_OR); + restr_andexpr(); + restr_eval_action(TOK_OR); + } } static void -restr_bexpr (void) -{ - switch (restr_lookahead) - { - case TOK_RESTRICTION: - restr_match (TOK_RESTRICTION); - restr_eval_action (TOK_RESTRICTION); - break; - - case TOK_LPAREN: - restr_match (TOK_LPAREN); - restr_orexpr (); - restr_match (TOK_RPAREN); - break; - - default: - sc_error ("restr_bexpr: syntax error, unexpected %d\n", restr_lookahead); - longjmp (restr_parse_error, 1); - } +restr_bexpr(void) { + switch (restr_lookahead) { + case TOK_RESTRICTION: + restr_match(TOK_RESTRICTION); + restr_eval_action(TOK_RESTRICTION); + break; + + case TOK_LPAREN: + restr_match(TOK_LPAREN); + restr_orexpr(); + restr_match(TOK_RPAREN); + break; + + default: + sc_error("restr_bexpr: syntax error, unexpected %d\n", restr_lookahead); + longjmp(restr_parse_error, 1); + } } @@ -1034,22 +965,21 @@ restr_bexpr (void) * Get the FailMessage for the given task restriction; NULL if none. */ static const sc_char * -restr_get_fail_message (sc_gameref_t game, sc_int task, sc_int restriction) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[5]; - const sc_char *message; - - /* Get the restriction message. */ - vt_key[0].string = "Tasks"; - vt_key[1].integer = task; - vt_key[2].string = "Restrictions"; - vt_key[3].integer = restriction; - vt_key[4].string = "FailMessage"; - message = prop_get_string (bundle, "S<-sisis", vt_key); - - /* Return it, or NULL if empty. */ - return !sc_strempty (message) ? message : NULL; +restr_get_fail_message(sc_gameref_t game, sc_int task, sc_int restriction) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[5]; + const sc_char *message; + + /* Get the restriction message. */ + vt_key[0].string = "Tasks"; + vt_key[1].integer = task; + vt_key[2].string = "Restrictions"; + vt_key[3].integer = restriction; + vt_key[4].string = "FailMessage"; + message = prop_get_string(bundle, "S<-sisis", vt_key); + + /* Return it, or NULL if empty. */ + return !sc_strempty(message) ? message : NULL; } @@ -1059,9 +989,8 @@ restr_get_fail_message (sc_gameref_t game, sc_int task, sc_int restriction) * Set restrictions tracing on/off. */ void -restr_debug_trace (sc_bool flag) -{ - restr_trace = flag; +restr_debug_trace(sc_bool flag) { + restr_trace = flag; } @@ -1076,87 +1005,80 @@ restr_debug_trace (sc_bool flag) * value is TRUE if restrictions parsed successfully, FALSE otherwise. */ sc_bool -restr_eval_task_restrictions (sc_gameref_t game, - sc_int task, sc_bool *pass, - const sc_char **fail_message) -{ - const sc_prop_setref_t bundle = gs_get_bundle (game); - sc_vartype_t vt_key[3]; - sc_int restr_count, lowest_fail; - const sc_char *pattern; - sc_bool result; - assert (pass && fail_message); - - /* Get the count of restrictions on the task. */ - vt_key[0].string = "Tasks"; - vt_key[1].integer = task; - vt_key[2].string = "Restrictions"; - restr_count = prop_get_child_count (bundle, "I<-sis", vt_key); - - /* If none, stop now, acting as if all passed. */ - if (restr_count == 0) - { - if (restr_trace) - sc_trace ("Restr: task %ld has no restrictions\n", task); - - *pass = TRUE; - *fail_message = NULL; - return TRUE; - } - - /* Get the task's restriction combination pattern. */ - vt_key[2].string = "RestrMask"; - pattern = prop_get_string (bundle, "S<-sis", vt_key); - - if (restr_trace) - { - sc_trace ("Restr: task %ld" - " has %ld restrictions, %s\n", task, restr_count, pattern); - } - - /* Set up the evaluation stack and tokenizer. */ - restr_eval_start (game, task); - restr_tokenize_start (pattern); - - /* Try parsing the pattern, and catch errors. */ - if (setjmp (restr_parse_error) == 0) - { - /* Parse the pattern, and ensure it ends at string end. */ - restr_lookahead = restr_next_token (); - restr_orexpr (); - restr_match (TOK_EOS); - } - else - { - /* Parse error -- clean up tokenizer and return fail. */ - restr_tokenize_end (); - return FALSE; - } - - /* Clean up tokenizer and get the evaluation result. */ - restr_tokenize_end (); - result = restr_eval_result (&lowest_fail); - - if (restr_trace) - { - sc_trace ("Restr: task %ld" - " restrictions %s\n", task, result ? "PASS" : "FAIL"); - } - - /* - * Return the result, and if a restriction fails, then return the - * FailMessage of the lowest indexed failing restriction (or NULL if this - * restriction has no FailMessage). - * - * Then return TRUE since parsing and running the restrictions succeeded - * (even if the restrictions themselves didn't). - */ - *pass = result; - if (result) - *fail_message = NULL; - else - *fail_message = restr_get_fail_message (game, task, lowest_fail); - return TRUE; +restr_eval_task_restrictions(sc_gameref_t game, + sc_int task, sc_bool *pass, + const sc_char **fail_message) { + const sc_prop_setref_t bundle = gs_get_bundle(game); + sc_vartype_t vt_key[3]; + sc_int restr_count, lowest_fail; + const sc_char *pattern; + sc_bool result; + assert(pass && fail_message); + + /* Get the count of restrictions on the task. */ + vt_key[0].string = "Tasks"; + vt_key[1].integer = task; + vt_key[2].string = "Restrictions"; + restr_count = prop_get_child_count(bundle, "I<-sis", vt_key); + + /* If none, stop now, acting as if all passed. */ + if (restr_count == 0) { + if (restr_trace) + sc_trace("Restr: task %ld has no restrictions\n", task); + + *pass = TRUE; + *fail_message = NULL; + return TRUE; + } + + /* Get the task's restriction combination pattern. */ + vt_key[2].string = "RestrMask"; + pattern = prop_get_string(bundle, "S<-sis", vt_key); + + if (restr_trace) { + sc_trace("Restr: task %ld" + " has %ld restrictions, %s\n", task, restr_count, pattern); + } + + /* Set up the evaluation stack and tokenizer. */ + restr_eval_start(game, task); + restr_tokenize_start(pattern); + + /* Try parsing the pattern, and catch errors. */ + if (setjmp(restr_parse_error) == 0) { + /* Parse the pattern, and ensure it ends at string end. */ + restr_lookahead = restr_next_token(); + restr_orexpr(); + restr_match(TOK_EOS); + } else { + /* Parse error -- clean up tokenizer and return fail. */ + restr_tokenize_end(); + return FALSE; + } + + /* Clean up tokenizer and get the evaluation result. */ + restr_tokenize_end(); + result = restr_eval_result(&lowest_fail); + + if (restr_trace) { + sc_trace("Restr: task %ld" + " restrictions %s\n", task, result ? "PASS" : "FAIL"); + } + + /* + * Return the result, and if a restriction fails, then return the + * FailMessage of the lowest indexed failing restriction (or NULL if this + * restriction has no FailMessage). + * + * Then return TRUE since parsing and running the restrictions succeeded + * (even if the restrictions themselves didn't). + */ + *pass = result; + if (result) + *fail_message = NULL; + else + *fail_message = restr_get_fail_message(game, task, lowest_fail); + return TRUE; } } // End of namespace Adrift |