aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordreammaster2019-09-08 22:36:19 +0100
committerPaul Gilbert2019-09-25 20:13:27 -0700
commitac9b8fd43d75aca937a32e581e06019833776248 (patch)
treecf48cd66bf6e3c4e96a96e9ab0dd995bf78053bc
parentfc410a88a0e8840f7d3cf3522ac4a33460bed761 (diff)
downloadscummvm-rg350-ac9b8fd43d75aca937a32e581e06019833776248.tar.gz
scummvm-rg350-ac9b8fd43d75aca937a32e581e06019833776248.tar.bz2
scummvm-rg350-ac9b8fd43d75aca937a32e581e06019833776248.zip
GLK: ADRIFT: Formatting
-rw-r--r--engines/glk/adrift/detection_tables.h2
-rw-r--r--engines/glk/adrift/os_glk.cpp4306
-rw-r--r--engines/glk/adrift/scare.h104
-rw-r--r--engines/glk/adrift/scdebug.cpp4295
-rw-r--r--engines/glk/adrift/scevents.cpp1312
-rw-r--r--engines/glk/adrift/scexpr.cpp2557
-rw-r--r--engines/glk/adrift/scgamest.cpp1580
-rw-r--r--engines/glk/adrift/scgamest.h6
-rw-r--r--engines/glk/adrift/scinterf.cpp1136
-rw-r--r--engines/glk/adrift/sclibrar.cpp16531
-rw-r--r--engines/glk/adrift/sclocale.cpp546
-rw-r--r--engines/glk/adrift/scmemos.cpp737
-rw-r--r--engines/glk/adrift/scnpcs.cpp950
-rw-r--r--engines/glk/adrift/scobjcts.cpp1362
-rw-r--r--engines/glk/adrift/scparser.cpp3170
-rw-r--r--engines/glk/adrift/scprintf.cpp2213
-rw-r--r--engines/glk/adrift/scprops.cpp1404
-rw-r--r--engines/glk/adrift/scprotos.h1311
-rw-r--r--engines/glk/adrift/scresour.cpp469
-rw-r--r--engines/glk/adrift/screstrs.cpp1688
-rw-r--r--engines/glk/adrift/scrunner.cpp3469
-rw-r--r--engines/glk/adrift/scserial.cpp1277
-rw-r--r--engines/glk/adrift/sctaffil.cpp944
-rw-r--r--engines/glk/adrift/sctafpar.cpp5840
-rw-r--r--engines/glk/adrift/sctasks.cpp2237
-rw-r--r--engines/glk/adrift/scutils.cpp440
-rw-r--r--engines/glk/adrift/scvars.cpp2887
-rw-r--r--engines/glk/adrift/sxfile.cpp236
-rw-r--r--engines/glk/adrift/sxglob.cpp409
-rw-r--r--engines/glk/adrift/sxmain.cpp225
-rw-r--r--engines/glk/adrift/sxprotos.h87
-rw-r--r--engines/glk/adrift/sxscript.cpp714
-rw-r--r--engines/glk/adrift/sxstubs.cpp484
-rw-r--r--engines/glk/adrift/sxtester.cpp84
-rw-r--r--engines/glk/adrift/sxutils.cpp182
35 files changed, 31010 insertions, 34184 deletions
diff --git a/engines/glk/adrift/detection_tables.h b/engines/glk/adrift/detection_tables.h
index c824905722..3f0bbdebcc 100644
--- a/engines/glk/adrift/detection_tables.h
+++ b/engines/glk/adrift/detection_tables.h
@@ -190,7 +190,7 @@ const PlainGameDescriptor ADRIFT_GAME_LIST[] = {
{ "amcthorn", "Thorn" },
{ "amcneighbours", "Neighbours From Hell" },
{ "amcmonsters", "Monsters" },
- { "amcdiarystrip", "Diary of a Stripper" },
+ { "amcdiarystrip", "Diary of a Stripper" },
// ADRIFT One-Hour Game Competition 1
{ "1hgamonkeytoomany", "" },
diff --git a/engines/glk/adrift/os_glk.cpp b/engines/glk/adrift/os_glk.cpp
index 33253802a2..37ac07f941 100644
--- a/engines/glk/adrift/os_glk.cpp
+++ b/engines/glk/adrift/os_glk.cpp
@@ -89,9 +89,9 @@ static const sc_int GSC_CONF_SUBTLE_HINT = INT_MAX,
GSC_CONF_CONTINUE_HINTS = INT_MAX - 2;
/* Forward declaration of event wait functions, and a short delay. */
-static void gsc_event_wait_2 (glui32 wait_type_1,
- glui32 wait_type_2, event_t *event);
-static void gsc_event_wait (glui32 wait_type, event_t *event);
+static void gsc_event_wait_2(glui32 wait_type_1,
+ glui32 wait_type_2, event_t *event);
+static void gsc_event_wait(glui32 wait_type, event_t *event);
static void gsc_short_delay();
@@ -106,29 +106,28 @@ static void gsc_short_delay();
* abort() or otherwise handle the error.
*/
static void
-gsc_fatal (const char *string)
-{
- /*
- * If the failure happens too early for us to have a window, print
- * the message to stderr.
- */
- if (!gsc_main_window) {
- error("\n\nINTERNAL ERROR: %s\n", string);
- }
+gsc_fatal(const char *string) {
+ /*
+ * If the failure happens too early for us to have a window, print
+ * the message to stderr.
+ */
+ if (!gsc_main_window) {
+ error("\n\nINTERNAL ERROR: %s\n", string);
+ }
- /* Cancel all possible pending window input events. */
- g_vm->glk_cancel_line_event (gsc_main_window, nullptr);
- g_vm->glk_cancel_char_event (gsc_main_window);
+ /* Cancel all possible pending window input events. */
+ g_vm->glk_cancel_line_event(gsc_main_window, nullptr);
+ g_vm->glk_cancel_char_event(gsc_main_window);
- /* Print a message indicating the error, and exit. */
- g_vm->glk_set_window (gsc_main_window);
- g_vm->glk_set_style (style_Normal);
- g_vm->glk_put_string ("\n\nINTERNAL ERROR: ");
- g_vm->glk_put_string ((char *) string);
+ /* Print a message indicating the error, and exit. */
+ g_vm->glk_set_window(gsc_main_window);
+ g_vm->glk_set_style(style_Normal);
+ g_vm->glk_put_string("\n\nINTERNAL ERROR: ");
+ g_vm->glk_put_string((char *) string);
- g_vm->glk_put_string ("\n\nPlease record the details of this error, try to"
- " note down everything you did to cause it, and email"
- " this information to simon_baldwin@yahoo.com.\n\n");
+ g_vm->glk_put_string("\n\nPlease record the details of this error, try to"
+ " note down everything you did to cause it, and email"
+ " this information to simon_baldwin@yahoo.com.\n\n");
}
@@ -138,18 +137,16 @@ gsc_fatal (const char *string)
* Non-failing malloc; call gsc_fatal and exit if memory allocation fails.
*/
static void *
-gsc_malloc (size_t size)
-{
- void *pointer;
+gsc_malloc(size_t size) {
+ void *pointer;
- pointer = malloc (size > 0 ? size : 1);
- if (!pointer)
- {
- gsc_fatal ("GLK: Out of system memory");
- g_vm->glk_exit ();
- }
+ pointer = malloc(size > 0 ? size : 1);
+ if (!pointer) {
+ gsc_fatal("GLK: Out of system memory");
+ g_vm->glk_exit();
+ }
- return pointer;
+ return pointer;
}
@@ -170,8 +167,8 @@ static const glui32 GSC_ISO_8859_EQUIVALENCE = 256;
*/
enum { GSC_TABLE_SIZE = 256 };
typedef struct {
- const glui32 unicode[GSC_TABLE_SIZE];
- const sc_char *const ascii[GSC_TABLE_SIZE];
+ const glui32 unicode[GSC_TABLE_SIZE];
+ const sc_char *const ascii[GSC_TABLE_SIZE];
} gsc_codepages_t;
/*
@@ -179,9 +176,9 @@ typedef struct {
* an alternate. The latter is intended for monospaced output.
*/
typedef struct {
- const sc_char *const name;
- const gsc_codepages_t main;
- const gsc_codepages_t alternate;
+ const sc_char *const name;
+ const gsc_codepages_t main;
+ const gsc_codepages_t alternate;
} gsc_locale_t;
@@ -195,117 +192,127 @@ typedef struct {
* character that might be recognizable as what it's trying to emulate.
*/
static const gsc_locale_t GSC_LATIN1_LOCALE = {
- "Latin1",
- /* cp1252 to unicode. */
-{ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
- 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
- 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
- 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
- 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
- 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
- 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
- 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
- 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
- 0x007e, 0x0000, 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020,
- 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000,
- 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc,
- 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178, 0x00a0, 0x00a1,
- 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa,
- 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3,
- 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc,
- 0x00bd, 0x00be, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5,
- 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce,
- 0x00cf, 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
- 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, 0x00e0,
- 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
- 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2,
- 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb,
- 0x00fc, 0x00fd, 0x00fe, 0x00ff },
- /* cp1252 to ascii. */
- { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
- "\n", nullptr, nullptr, "\n", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
- "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
- "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@",
- "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
- "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
- "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a",
- "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
- "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
- "x", "y", "z", "{", "|", "}", "~", nullptr, "E", nullptr, ",",
- "f", ",,", "...", "+", "#", "^", "%", "S", "<", "OE", nullptr,
- "Z", nullptr, nullptr, "'", "'", "\"", "\"", "*", "-", "-", "~",
- "[TM]","s", ">", "oe", nullptr, "z", "Y", " ", "!", "c", "GBP",
- "*", "Y", "|", "S", "\"", "(C)", "a", "<<", "-", "-", "(R)",
- "-", "o", "+/-", "2", "3", "'", "u", "P", "*", ",", "1",
- "o", ">>", "1/4", "1/2", "3/4", "?", "A", "A", "A", "A", "A",
- "A", "AE", "C", "E", "E", "E", "E", "I", "I", "I", "I",
- "D", "N", "O", "O", "O", "O", "O", "x", "O", "U", "U",
- "U", "U", "Y", "p", "ss", "a", "a", "a", "a", "a", "a",
- "ae", "c", "e", "e", "e", "e", "i", "i", "i", "i", "d",
- "n", "o", "o", "o", "o", "o", "/", "o", "u", "u", "u",
- "u", "y", "P", "y" } },
- /* cp850 to unicode. */
-{ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
- 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
- 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
- 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
- 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
- 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
- 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
- 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
- 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
- 0x007e, 0x0000, 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5,
- 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
- 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff,
- 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192, 0x00e1, 0x00ed,
- 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x00ae, 0x00ac,
- 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, 0x2591, 0x2592, 0x2593, 0x2502,
- 0x2524, 0x00c1, 0x00c2, 0x00c0, 0x00a9, 0x2563, 0x2551, 0x2557, 0x255d,
- 0x00a2, 0x00a5, 0x2510, 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c,
- 0x00e3, 0x00c3, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c,
- 0x00a4, 0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce,
- 0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, 0x00d3,
- 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe, 0x00de, 0x00da,
- 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4, 0x00ad, 0x00b1, 0x2017,
- 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, 0x00b0, 0x00a8, 0x00b7, 0x00b9,
- 0x00b3, 0x00b2, 0x25a0, 0x00a0 },
- /* cp850 to ascii. */
- { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
- "\n", nullptr, nullptr, "\n", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
- "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
- "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@",
- "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
- "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
- "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a",
- "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
- "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
- "x", "y", "z", "{", "|", "}", "~", nullptr, "C", "u", "e",
- "a", "a", "a", "a", "c", "e", "e", "e", "i", "i", "i",
- "A", "A", "E", "ae", "AE", "o", "o", "o", "u", "u", "y",
- "O", "U", "o", "GBP", "O", "x", "f", "a", "i", "o", "u",
- "n", "N", "a", "o", "?", "(R)", "-", "1/2", "1/4", "i", "<<",
- ">>", "#", "#", "#", "|", "+", "A", "A", "A", "(C)", "+",
- "|", "+", "+", "c", "Y", "+", "+", "+", "+", "+", "-",
- "+", "a", "A", "+", "+", "+", "+", "+", "=", "+", "*",
- "d", "D", "E", "E", "E", "i", "I", "I", "I", "+", "+",
- ".", ".", "|", "I", ".", "O", "ss", "O", "O", "o", "O",
- "u", "p", "P", "U", "U", "U", "y", "Y", "-", "'", "-",
- "+/-", "=", "3/4", "P", "S", "/", ",", "deg", "\"", "*", "1",
- "3", "2", ".", " " } }
+ "Latin1",
+ /* cp1252 to unicode. */
+ { {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023,
+ 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
+ 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
+ 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
+ 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
+ 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
+ 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
+ 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
+ 0x007e, 0x0000, 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020,
+ 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc,
+ 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178, 0x00a0, 0x00a1,
+ 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa,
+ 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc,
+ 0x00bd, 0x00be, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5,
+ 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce,
+ 0x00cf, 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, 0x00e0,
+ 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2,
+ 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb,
+ 0x00fc, 0x00fd, 0x00fe, 0x00ff
+ },
+ /* cp1252 to ascii. */
+ {
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
+ "\n", nullptr, nullptr, "\n", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
+ "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@",
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
+ "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
+ "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a",
+ "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
+ "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
+ "x", "y", "z", "{", "|", "}", "~", nullptr, "E", nullptr, ",",
+ "f", ",,", "...", "+", "#", "^", "%", "S", "<", "OE", nullptr,
+ "Z", nullptr, nullptr, "'", "'", "\"", "\"", "*", "-", "-", "~",
+ "[TM]", "s", ">", "oe", nullptr, "z", "Y", " ", "!", "c", "GBP",
+ "*", "Y", "|", "S", "\"", "(C)", "a", "<<", "-", "-", "(R)",
+ "-", "o", "+/-", "2", "3", "'", "u", "P", "*", ",", "1",
+ "o", ">>", "1/4", "1/2", "3/4", "?", "A", "A", "A", "A", "A",
+ "A", "AE", "C", "E", "E", "E", "E", "I", "I", "I", "I",
+ "D", "N", "O", "O", "O", "O", "O", "x", "O", "U", "U",
+ "U", "U", "Y", "p", "ss", "a", "a", "a", "a", "a", "a",
+ "ae", "c", "e", "e", "e", "e", "i", "i", "i", "i", "d",
+ "n", "o", "o", "o", "o", "o", "/", "o", "u", "u", "u",
+ "u", "y", "P", "y"
+ }
+ },
+ /* cp850 to unicode. */
+ { {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023,
+ 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
+ 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
+ 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
+ 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
+ 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
+ 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
+ 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
+ 0x007e, 0x0000, 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5,
+ 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+ 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff,
+ 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192, 0x00e1, 0x00ed,
+ 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x00ae, 0x00ac,
+ 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, 0x2591, 0x2592, 0x2593, 0x2502,
+ 0x2524, 0x00c1, 0x00c2, 0x00c0, 0x00a9, 0x2563, 0x2551, 0x2557, 0x255d,
+ 0x00a2, 0x00a5, 0x2510, 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c,
+ 0x00e3, 0x00c3, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c,
+ 0x00a4, 0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce,
+ 0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, 0x00d3,
+ 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe, 0x00de, 0x00da,
+ 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4, 0x00ad, 0x00b1, 0x2017,
+ 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, 0x00b0, 0x00a8, 0x00b7, 0x00b9,
+ 0x00b3, 0x00b2, 0x25a0, 0x00a0
+ },
+ /* cp850 to ascii. */
+ {
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
+ "\n", nullptr, nullptr, "\n", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
+ "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@",
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
+ "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
+ "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a",
+ "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
+ "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
+ "x", "y", "z", "{", "|", "}", "~", nullptr, "C", "u", "e",
+ "a", "a", "a", "a", "c", "e", "e", "e", "i", "i", "i",
+ "A", "A", "E", "ae", "AE", "o", "o", "o", "u", "u", "y",
+ "O", "U", "o", "GBP", "O", "x", "f", "a", "i", "o", "u",
+ "n", "N", "a", "o", "?", "(R)", "-", "1/2", "1/4", "i", "<<",
+ ">>", "#", "#", "#", "|", "+", "A", "A", "A", "(C)", "+",
+ "|", "+", "+", "c", "Y", "+", "+", "+", "+", "+", "-",
+ "+", "a", "A", "+", "+", "+", "+", "+", "=", "+", "*",
+ "d", "D", "E", "E", "E", "i", "I", "I", "I", "+", "+",
+ ".", ".", "|", "I", ".", "O", "ss", "O", "O", "o", "O",
+ "u", "p", "P", "U", "U", "U", "y", "Y", "-", "'", "-",
+ "+/-", "=", "3/4", "P", "S", "/", ",", "deg", "\"", "*", "1",
+ "3", "2", ".", " "
+ }
+ }
};
@@ -321,117 +328,127 @@ static const gsc_locale_t GSC_LATIN1_LOCALE = {
* the general appearance and shape of the character being emulated is used.
*/
static const gsc_locale_t GSC_CYRILLIC_LOCALE = {
- "Cyrillic",
- /* cp1251 to unicode. */
-{ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
- 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
- 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
- 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
- 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
- 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
- 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
- 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
- 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
- 0x007e, 0x0000, 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020,
- 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
- 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000,
- 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, 0x00a0, 0x040e,
- 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404,
- 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, 0x00b0, 0x00b1, 0x0406, 0x0456,
- 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458,
- 0x0405, 0x0455, 0x0457, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
- 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
- 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
- 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x0430,
- 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439,
- 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442,
- 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b,
- 0x044c, 0x044d, 0x044e, 0x044f },
- /* cp1251 to gost 16876-71 ascii. */
- { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
- "\n", nullptr, nullptr, "\n", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
- "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
- "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@",
- "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
- "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
- "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a",
- "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
- "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
- "x", "y", "z", "{", "|", "}", "~", nullptr, nullptr, nullptr, ",",
- nullptr, ",,", "...", "+", "#", "E", "%", nullptr, "<", nullptr, nullptr,
- nullptr, nullptr, nullptr, "'", "'", "\"", "\"", "*", "-", "-", nullptr,
- "[TM]",nullptr, ">", nullptr, nullptr, nullptr, nullptr, " ", nullptr, nullptr, nullptr,
- "*", "G", "|", "S", "Jo", "(C)", "Je", "<<", "-", "-", "(R)",
- "Ji", "o", "+/-", "I", "i", "g", "u", "P", "*", "jo", nullptr,
- "je", ">>", "j", "S", "s", "ji", "A", "B", "V", "G", "D",
- "E", "Zh", "Z", "I", "Jj", "K", "L", "M", "N", "O", "P",
- "R", "S", "T", "U", "F", "Kh", "C", "Ch", "Sh", "Shh", "\"",
- "Y", "'", "Eh", "Ju", "Ja", "a", "b", "v", "g", "d", "e",
- "zh", "z", "i", "jj", "k", "l", "m", "n", "o", "p", "r",
- "s", "t", "u", "f", "kh", "c", "ch", "sh", "shh", "\"", "y",
- "'", "eh", "ju", "ja" } },
- /* cp866 to unicode. */
-{ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
- 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
- 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
- 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
- 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
- 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
- 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
- 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
- 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
- 0x007e, 0x0000, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416,
- 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
- 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428,
- 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x0430, 0x0431,
- 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a,
- 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x2591, 0x2592, 0x2593, 0x2502,
- 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d,
- 0x255c, 0x255b, 0x2510, 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c,
- 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c,
- 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
- 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, 0x0440,
- 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
- 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0x0401, 0x0451, 0x0404,
- 0x0454, 0x0407, 0x0457, 0x040e, 0x045e, 0x00b0, 0x2022, 0x00b7, 0x221a,
- 0x2116, 0x00a4, 0x25a0, 0x00a0 },
- /* cp866 to gost 16876-71 ascii. */
- { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
- "\n", nullptr, nullptr, "\n", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
- "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
- "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@",
- "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
- "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
- "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a",
- "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
- "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
- "x", "y", "z", "{", "|", "}", "~", nullptr, "A", "B", "V",
- "G", "D", "E", "Zh", "Z", "I", "Jj", "K", "L", "M", "N",
- "O", "P", "R", "S", "T", "U", "F", "Kh", "C", "Ch", "Sh",
- "Shh", "\"", "Y", "'", "Eh", "Ju", "Ja", "a", "b", "v", "g",
- "d", "e", "zh", "z", "i", "jj", "k", "l", "m", "n", "o",
- "p", "#", "#", "#", "|", "+", "+", "+", "+", "+", "+",
- "|", "+", "+", "+", "+", "+", "+", "+", "+", "+", "-",
- "+", "+", "+", "+", "+", "+", "+", "+", "|", "+", "+",
- "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+",
- "+", ".", ".", ".", ".", "r", "s", "t", "u", "f", "kh",
- "c", "ch", "sh", "shh", "\"", "y", "'", "eh", "ju", "ja", "Jo",
- "jo", "Je", "je", "Ji", "ji", nullptr, nullptr, "deg", "*", "*", nullptr,
- nullptr, "*", ".", " " } }
+ "Cyrillic",
+ /* cp1251 to unicode. */
+ { {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023,
+ 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
+ 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
+ 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
+ 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
+ 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
+ 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
+ 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
+ 0x007e, 0x0000, 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020,
+ 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
+ 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000,
+ 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, 0x00a0, 0x040e,
+ 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404,
+ 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, 0x00b0, 0x00b1, 0x0406, 0x0456,
+ 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458,
+ 0x0405, 0x0455, 0x0457, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
+ 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
+ 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x0430,
+ 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439,
+ 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442,
+ 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b,
+ 0x044c, 0x044d, 0x044e, 0x044f
+ },
+ /* cp1251 to gost 16876-71 ascii. */
+ {
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
+ "\n", nullptr, nullptr, "\n", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
+ "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@",
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
+ "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
+ "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a",
+ "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
+ "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
+ "x", "y", "z", "{", "|", "}", "~", nullptr, nullptr, nullptr, ",",
+ nullptr, ",,", "...", "+", "#", "E", "%", nullptr, "<", nullptr, nullptr,
+ nullptr, nullptr, nullptr, "'", "'", "\"", "\"", "*", "-", "-", nullptr,
+ "[TM]", nullptr, ">", nullptr, nullptr, nullptr, nullptr, " ", nullptr, nullptr, nullptr,
+ "*", "G", "|", "S", "Jo", "(C)", "Je", "<<", "-", "-", "(R)",
+ "Ji", "o", "+/-", "I", "i", "g", "u", "P", "*", "jo", nullptr,
+ "je", ">>", "j", "S", "s", "ji", "A", "B", "V", "G", "D",
+ "E", "Zh", "Z", "I", "Jj", "K", "L", "M", "N", "O", "P",
+ "R", "S", "T", "U", "F", "Kh", "C", "Ch", "Sh", "Shh", "\"",
+ "Y", "'", "Eh", "Ju", "Ja", "a", "b", "v", "g", "d", "e",
+ "zh", "z", "i", "jj", "k", "l", "m", "n", "o", "p", "r",
+ "s", "t", "u", "f", "kh", "c", "ch", "sh", "shh", "\"", "y",
+ "'", "eh", "ju", "ja"
+ }
+ },
+ /* cp866 to unicode. */
+ { {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023,
+ 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
+ 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
+ 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
+ 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
+ 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
+ 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
+ 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
+ 0x007e, 0x0000, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416,
+ 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428,
+ 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x0430, 0x0431,
+ 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a,
+ 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x2591, 0x2592, 0x2593, 0x2502,
+ 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d,
+ 0x255c, 0x255b, 0x2510, 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c,
+ 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c,
+ 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
+ 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, 0x0440,
+ 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0x0401, 0x0451, 0x0404,
+ 0x0454, 0x0407, 0x0457, 0x040e, 0x045e, 0x00b0, 0x2022, 0x00b7, 0x221a,
+ 0x2116, 0x00a4, 0x25a0, 0x00a0
+ },
+ /* cp866 to gost 16876-71 ascii. */
+ {
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
+ "\n", nullptr, nullptr, "\n", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
+ "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@",
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
+ "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
+ "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a",
+ "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
+ "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
+ "x", "y", "z", "{", "|", "}", "~", nullptr, "A", "B", "V",
+ "G", "D", "E", "Zh", "Z", "I", "Jj", "K", "L", "M", "N",
+ "O", "P", "R", "S", "T", "U", "F", "Kh", "C", "Ch", "Sh",
+ "Shh", "\"", "Y", "'", "Eh", "Ju", "Ja", "a", "b", "v", "g",
+ "d", "e", "zh", "z", "i", "jj", "k", "l", "m", "n", "o",
+ "p", "#", "#", "#", "|", "+", "+", "+", "+", "+", "+",
+ "|", "+", "+", "+", "+", "+", "+", "+", "+", "+", "-",
+ "+", "+", "+", "+", "+", "+", "+", "+", "|", "+", "+",
+ "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+",
+ "+", ".", ".", ".", ".", "r", "s", "t", "u", "f", "kh",
+ "c", "ch", "sh", "shh", "\"", "y", "'", "eh", "ju", "ja", "Jo",
+ "jo", "Je", "je", "Ji", "ji", nullptr, nullptr, "deg", "*", "*", nullptr,
+ nullptr, "*", ".", " "
+ }
+ }
};
@@ -447,24 +464,22 @@ static const sc_bool gsc_has_unicode = FALSE;
/* Gestalt selector and stubs for non-unicode capable libraries. */
static const glui32 gestalt_Unicode = 15;
-static void glk_put_char_uni (glui32 ch)
-{
- glui32 unused;
- unused = ch;
- gsc_fatal ("GLK: Stub unicode function called");
+static void glk_put_char_uni(glui32 ch) {
+ glui32 unused;
+ unused = ch;
+ gsc_fatal("GLK: Stub unicode function called");
}
-static void glk_request_line_event_uni (winid_t win,
- glui32 *buf, glui32 maxlen, glui32 initlen)
-{
- winid_t unused1;
- glui32 *unused2;
- glui32 unused3, unused4;
- unused1 = win;
- unused2 = buf;
- unused3 = maxlen;
- unused4 = initlen;
- gsc_fatal ("GLK: Stub unicode function called");
+static void glk_request_line_event_uni(winid_t win,
+ glui32 *buf, glui32 maxlen, glui32 initlen) {
+ winid_t unused1;
+ glui32 *unused2;
+ glui32 unused3, unused4;
+ unused1 = win;
+ unused2 = buf;
+ unused3 = maxlen;
+ unused4 = initlen;
+ gsc_fatal("GLK: Stub unicode function called");
}
#endif
@@ -480,9 +495,9 @@ static const glui32 GSC_MIN_PRINTABLE = ' ',
/* List of pointers to supported and available locales, nullptr terminated. */
static const gsc_locale_t *const GSC_AVAILABLE_LOCALES[] = {
- &GSC_LATIN1_LOCALE,
- &GSC_CYRILLIC_LOCALE,
- nullptr
+ &GSC_LATIN1_LOCALE,
+ &GSC_CYRILLIC_LOCALE,
+ nullptr
};
/*
@@ -499,30 +514,27 @@ static const gsc_locale_t *const gsc_fallback_locale = &GSC_LATIN1_LOCALE;
* Set a locale explicitly from the name passed in.
*/
static void
-gsc_set_locale (const sc_char *name)
-{
- const gsc_locale_t *matched = nullptr;
- const gsc_locale_t *const *iterator;
- assert (name);
+gsc_set_locale(const sc_char *name) {
+ const gsc_locale_t *matched = nullptr;
+ const gsc_locale_t *const *iterator;
+ assert(name);
- /*
- * Search locales for a matching name, abbreviated if necessary. Stop on
- * the first match found.
- */
- for (iterator = GSC_AVAILABLE_LOCALES; *iterator; iterator++)
- {
- const gsc_locale_t *const locale = *iterator;
+ /*
+ * Search locales for a matching name, abbreviated if necessary. Stop on
+ * the first match found.
+ */
+ for (iterator = GSC_AVAILABLE_LOCALES; *iterator; iterator++) {
+ const gsc_locale_t *const locale = *iterator;
- if (sc_strncasecmp (name, locale->name, strlen (name)) == 0)
- {
- matched = locale;
- break;
- }
- }
+ if (sc_strncasecmp(name, locale->name, strlen(name)) == 0) {
+ matched = locale;
+ break;
+ }
+ }
- /* If matched, set the global locale. */
- if (matched)
- gsc_locale = matched;
+ /* If matched, set the global locale. */
+ if (matched)
+ gsc_locale = matched;
}
@@ -533,24 +545,22 @@ gsc_set_locale (const sc_char *name)
* having to write transcripts as ascii.
*/
static void
-gsc_put_char_uni (glui32 unicode, const char *ascii)
-{
- /* If there is an transcript stream, temporarily disconnect it. */
- if (gsc_transcript_stream)
- g_vm->glk_window_set_echo_stream (gsc_main_window, nullptr);
+gsc_put_char_uni(glui32 unicode, const char *ascii) {
+ /* If there is an transcript stream, temporarily disconnect it. */
+ if (gsc_transcript_stream)
+ g_vm->glk_window_set_echo_stream(gsc_main_window, nullptr);
- g_vm->glk_put_char_uni (unicode);
+ g_vm->glk_put_char_uni(unicode);
- /* Print ascii to the transcript, then reattach it. */
- if (gsc_transcript_stream)
- {
- if (ascii)
- g_vm->glk_put_string_stream (gsc_transcript_stream, (char *) ascii);
- else
- g_vm->glk_put_char_stream (gsc_transcript_stream, '?');
+ /* Print ascii to the transcript, then reattach it. */
+ if (gsc_transcript_stream) {
+ if (ascii)
+ g_vm->glk_put_string_stream(gsc_transcript_stream, (char *) ascii);
+ else
+ g_vm->glk_put_char_stream(gsc_transcript_stream, '?');
- g_vm->glk_window_set_echo_stream (gsc_main_window, gsc_transcript_stream);
- }
+ g_vm->glk_window_set_echo_stream(gsc_main_window, gsc_transcript_stream);
+ }
}
@@ -561,86 +571,79 @@ gsc_put_char_uni (glui32 unicode, const char *ascii)
* main or the alternate codepage depending on the flag passed in.
*/
static void
-gsc_put_char_locale (sc_char ch,
- const gsc_locale_t *locale, sc_bool is_alternate)
-{
- const gsc_codepages_t *codepage;
- unsigned char character;
- glui32 unicode;
- const char *ascii;
-
- /*
- * Select either the main or the alternate codepage for this locale, and
- * retrieve the unicode and ascii representations of the character.
- */
- codepage = is_alternate ? &locale->alternate : &locale->main;
- character = (unsigned char) ch;
- unicode = codepage->unicode[character];
- ascii = codepage->ascii[character];
-
- /*
- * If a unicode representation exists, use for either iso 8859-1 or, if
- * possible, direct unicode output.
- */
- if (unicode > 0)
- {
- /*
- * If unicode is in the range 1-255, this value is directly equivalent
- * to the iso 8859-1 representation; otherwise the character has no
- * direct iso 8859-1 glyph.
- */
- if (unicode < GSC_ISO_8859_EQUIVALENCE)
- {
- /*
- * If the iso 8859-1 character is one that this Glk library will
- * print exactly, print and return. We add a check here for the
- * guaranteed printable characters, since some Glk libraries don't
- * return the correct values for gestalt_CharOutput for these.
- */
- if (unicode == '\n'
- || (unicode >= GSC_MIN_PRINTABLE && unicode <= GSC_MAX_PRINTABLE)
- || g_vm->glk_gestalt (gestalt_CharOutput,
- unicode) == gestalt_CharOutput_ExactPrint)
- {
- g_vm->glk_put_char ((unsigned char) unicode);
- return;
- }
- }
-
- /*
- * If no usable iso 8859-1 representation, see if unicode is enabled and
- * if the Glk library can print the character exactly. If yes, output
- * the character that way.
- *
- * TODO Using unicode output currently disrupts transcript output. Any
- * echo stream connected for a transcript here will be a text rather than
- * a unicode stream, so probably won't output the character correctly.
- * For now, if there's a transcript, we try to write ascii output.
- */
- if (gsc_unicode_enabled)
- {
- if (g_vm->glk_gestalt (gestalt_CharOutput,
- unicode) == gestalt_CharOutput_ExactPrint)
- {
- gsc_put_char_uni (unicode, ascii);
- return;
- }
- }
- }
-
- /*
- * No success with iso 8859-1 or unicode, so try for an ascii substitute.
- * Substitute strings use only 7-bit ascii, and so all are safe to print
- * directly with Glk.
- */
- if (ascii)
- {
- g_vm->glk_put_string ((char *) ascii);
- return;
- }
-
- /* No apparent way to output this character, so print a '?'. */
- g_vm->glk_put_char ('?');
+gsc_put_char_locale(sc_char ch,
+ const gsc_locale_t *locale, sc_bool is_alternate) {
+ const gsc_codepages_t *codepage;
+ unsigned char character;
+ glui32 unicode;
+ const char *ascii;
+
+ /*
+ * Select either the main or the alternate codepage for this locale, and
+ * retrieve the unicode and ascii representations of the character.
+ */
+ codepage = is_alternate ? &locale->alternate : &locale->main;
+ character = (unsigned char) ch;
+ unicode = codepage->unicode[character];
+ ascii = codepage->ascii[character];
+
+ /*
+ * If a unicode representation exists, use for either iso 8859-1 or, if
+ * possible, direct unicode output.
+ */
+ if (unicode > 0) {
+ /*
+ * If unicode is in the range 1-255, this value is directly equivalent
+ * to the iso 8859-1 representation; otherwise the character has no
+ * direct iso 8859-1 glyph.
+ */
+ if (unicode < GSC_ISO_8859_EQUIVALENCE) {
+ /*
+ * If the iso 8859-1 character is one that this Glk library will
+ * print exactly, print and return. We add a check here for the
+ * guaranteed printable characters, since some Glk libraries don't
+ * return the correct values for gestalt_CharOutput for these.
+ */
+ if (unicode == '\n'
+ || (unicode >= GSC_MIN_PRINTABLE && unicode <= GSC_MAX_PRINTABLE)
+ || g_vm->glk_gestalt(gestalt_CharOutput,
+ unicode) == gestalt_CharOutput_ExactPrint) {
+ g_vm->glk_put_char((unsigned char) unicode);
+ return;
+ }
+ }
+
+ /*
+ * If no usable iso 8859-1 representation, see if unicode is enabled and
+ * if the Glk library can print the character exactly. If yes, output
+ * the character that way.
+ *
+ * TODO Using unicode output currently disrupts transcript output. Any
+ * echo stream connected for a transcript here will be a text rather than
+ * a unicode stream, so probably won't output the character correctly.
+ * For now, if there's a transcript, we try to write ascii output.
+ */
+ if (gsc_unicode_enabled) {
+ if (g_vm->glk_gestalt(gestalt_CharOutput,
+ unicode) == gestalt_CharOutput_ExactPrint) {
+ gsc_put_char_uni(unicode, ascii);
+ return;
+ }
+ }
+ }
+
+ /*
+ * No success with iso 8859-1 or unicode, so try for an ascii substitute.
+ * Substitute strings use only 7-bit ascii, and so all are safe to print
+ * directly with Glk.
+ */
+ if (ascii) {
+ g_vm->glk_put_string((char *) ascii);
+ return;
+ }
+
+ /* No apparent way to output this character, so print a '?'. */
+ g_vm->glk_put_char('?');
}
@@ -655,55 +658,49 @@ gsc_put_char_locale (sc_char ch,
* Public functions for writing using the current or fallback locale.
*/
static void
-gsc_put_char (const sc_char character)
-{
- const gsc_locale_t *locale;
+gsc_put_char(const sc_char character) {
+ const gsc_locale_t *locale;
- locale = gsc_locale ? gsc_locale : gsc_fallback_locale;
- gsc_put_char_locale (character, locale, FALSE);
+ locale = gsc_locale ? gsc_locale : gsc_fallback_locale;
+ gsc_put_char_locale(character, locale, FALSE);
}
static void
-gsc_put_char_alternate (const sc_char character)
-{
- const gsc_locale_t *locale;
+gsc_put_char_alternate(const sc_char character) {
+ const gsc_locale_t *locale;
- locale = gsc_locale ? gsc_locale : gsc_fallback_locale;
- gsc_put_char_locale (character, locale, TRUE);
+ locale = gsc_locale ? gsc_locale : gsc_fallback_locale;
+ gsc_put_char_locale(character, locale, TRUE);
}
static void
-gsc_put_buffer_using (const sc_char *buffer,
- sc_int length, void (*putchar_function) (sc_char))
-{
- sc_int index_;
+gsc_put_buffer_using(const sc_char *buffer,
+ sc_int length, void (*putchar_function)(sc_char)) {
+ sc_int index_;
- for (index_ = 0; index_ < length; index_++)
- putchar_function (buffer[index_]);
+ for (index_ = 0; index_ < length; index_++)
+ putchar_function(buffer[index_]);
}
static void
-gsc_put_buffer (const sc_char *buffer, sc_int length)
-{
- assert (buffer);
+gsc_put_buffer(const sc_char *buffer, sc_int length) {
+ assert(buffer);
- gsc_put_buffer_using (buffer, length, gsc_put_char);
+ gsc_put_buffer_using(buffer, length, gsc_put_char);
}
static void
-gsc_put_string (const sc_char *string)
-{
- assert (string);
+gsc_put_string(const sc_char *string) {
+ assert(string);
- gsc_put_buffer_using (string, strlen (string), gsc_put_char);
+ gsc_put_buffer_using(string, strlen(string), gsc_put_char);
}
static void
-gsc_put_string_alternate (const sc_char *string)
-{
- assert (string);
+gsc_put_string_alternate(const sc_char *string) {
+ assert(string);
- gsc_put_buffer_using (string, strlen (string), gsc_put_char_alternate);
+ gsc_put_buffer_using(string, strlen(string), gsc_put_char_alternate);
}
@@ -716,36 +713,33 @@ gsc_put_string_alternate (const sc_char *string)
* available.
*/
static sc_char
-gsc_unicode_to_locale (glui32 unicode, const gsc_locale_t *locale)
-{
- const gsc_codepages_t *codepage;
- sc_int character;
+gsc_unicode_to_locale(glui32 unicode, const gsc_locale_t *locale) {
+ const gsc_codepages_t *codepage;
+ sc_int character;
- /* Always use the main codepage for input. */
- codepage = &locale->main;
+ /* Always use the main codepage for input. */
+ codepage = &locale->main;
- /*
- * Search the unicode table sequentially for the input character. This is
- * inefficient, but because game input is usually not copious, excusable.
- */
- for (character = 0; character < GSC_TABLE_SIZE; character++)
- {
- if (codepage->unicode[character] == unicode)
- break;
- }
+ /*
+ * Search the unicode table sequentially for the input character. This is
+ * inefficient, but because game input is usually not copious, excusable.
+ */
+ for (character = 0; character < GSC_TABLE_SIZE; character++) {
+ if (codepage->unicode[character] == unicode)
+ break;
+ }
- /* Return the character translation, or '?' if none. */
- return character < GSC_TABLE_SIZE ? (sc_char) character : '?';
+ /* Return the character translation, or '?' if none. */
+ return character < GSC_TABLE_SIZE ? (sc_char) character : '?';
}
static void
-gsc_unicode_buffer_to_locale (const glui32 *unicode, sc_int length,
- sc_char *buffer, const gsc_locale_t *locale)
-{
- sc_int index_;
+gsc_unicode_buffer_to_locale(const glui32 *unicode, sc_int length,
+ sc_char *buffer, const gsc_locale_t *locale) {
+ sc_int index_;
- for (index_ = 0; index_ < length; index_++)
- buffer[index_] = gsc_unicode_to_locale (unicode[index_], locale);
+ for (index_ = 0; index_ < length; index_++)
+ buffer[index_] = gsc_unicode_to_locale(unicode[index_], locale);
}
@@ -756,41 +750,39 @@ gsc_unicode_buffer_to_locale (const glui32 *unicode, sc_int length,
* of characters placed in the buffer.
*/
static sc_int
-gsc_read_line_locale (sc_char *buffer,
- sc_int length, const gsc_locale_t *locale)
-{
- event_t event;
+gsc_read_line_locale(sc_char *buffer,
+ sc_int length, const gsc_locale_t *locale) {
+ event_t event;
- /*
- * If we have unicode, we have to use it to ensure that characters not in
- * the Latin1 locale are properly translated.
- */
- if (gsc_unicode_enabled)
- {
- glui32 *unicode;
+ /*
+ * If we have unicode, we have to use it to ensure that characters not in
+ * the Latin1 locale are properly translated.
+ */
+ if (gsc_unicode_enabled) {
+ glui32 *unicode;
- /*
- * Allocate a unicode buffer long enough to hold all the characters,
- * then read in a unicode line.
- */
- unicode = (glui32 *)gsc_malloc (length * sizeof (*unicode));
- g_vm->glk_request_line_event_uni (gsc_main_window, unicode, length, 0);
- gsc_event_wait (evtype_LineInput, &event);
+ /*
+ * Allocate a unicode buffer long enough to hold all the characters,
+ * then read in a unicode line.
+ */
+ unicode = (glui32 *)gsc_malloc(length * sizeof(*unicode));
+ g_vm->glk_request_line_event_uni(gsc_main_window, unicode, length, 0);
+ gsc_event_wait(evtype_LineInput, &event);
- /* Convert the unicode buffer out, then free it. */
- gsc_unicode_buffer_to_locale (unicode, event.val1, buffer, locale);
- free (unicode);
+ /* Convert the unicode buffer out, then free it. */
+ gsc_unicode_buffer_to_locale(unicode, event.val1, buffer, locale);
+ free(unicode);
- /* Return the count of characters placed in the buffer. */
- return event.val1;
- }
+ /* Return the count of characters placed in the buffer. */
+ return event.val1;
+ }
- /* No success with unicode, so fall back to standard line input. */
- g_vm->glk_request_line_event (gsc_main_window, buffer, length, 0);
- gsc_event_wait (evtype_LineInput, &event);
+ /* No success with unicode, so fall back to standard line input. */
+ g_vm->glk_request_line_event(gsc_main_window, buffer, length, 0);
+ gsc_event_wait(evtype_LineInput, &event);
- /* Return the count of characters placed in the buffer. */
- return event.val1;
+ /* Return the count of characters placed in the buffer. */
+ return event.val1;
}
@@ -800,12 +792,11 @@ gsc_read_line_locale (sc_char *buffer,
* Public function for reading using the current or fallback locale.
*/
static sc_int
-gsc_read_line (sc_char *buffer, sc_int length)
-{
- const gsc_locale_t *locale;
+gsc_read_line(sc_char *buffer, sc_int length) {
+ const gsc_locale_t *locale;
- locale = gsc_locale ? gsc_locale : gsc_fallback_locale;
- return gsc_read_line_locale (buffer, length, locale);
+ locale = gsc_locale ? gsc_locale : gsc_fallback_locale;
+ return gsc_read_line_locale(buffer, length, locale);
}
@@ -834,22 +825,19 @@ static const sc_char *const GSC_WHITESPACE = "\t\n\v\f\r ";
* other than whitespace.
*/
static sc_bool
-gsc_is_string_usable (const sc_char *string)
-{
- /* If non-null, scan for any non-space character. */
- if (string)
- {
- sc_int index_;
-
- for (index_ = 0; string[index_] != '\0'; index_++)
- {
- if (!strchr (GSC_WHITESPACE, string[index_]))
- return TRUE;
- }
- }
+gsc_is_string_usable(const sc_char *string) {
+ /* If non-null, scan for any non-space character. */
+ if (string) {
+ sc_int index_;
+
+ for (index_ = 0; string[index_] != '\0'; index_++) {
+ if (!strchr(GSC_WHITESPACE, string[index_]))
+ return TRUE;
+ }
+ }
- /* nullptr, or no characters other than whitespace. */
- return FALSE;
+ /* nullptr, or no characters other than whitespace. */
+ return FALSE;
}
@@ -860,69 +848,62 @@ gsc_is_string_usable (const sc_char *string)
* Glk libraries.
*/
static void
-gsc_status_update()
-{
- glui32 width, height;
- uint index;
- assert (gsc_status_window);
-
- g_vm->glk_window_get_size (gsc_status_window, &width, &height);
- if (height > 0)
- {
- const sc_char *room;
-
- g_vm->glk_window_clear (gsc_status_window);
- g_vm->glk_window_move_cursor (gsc_status_window, 0, 0);
- g_vm->glk_set_window (gsc_status_window);
-
- g_vm->glk_set_style(style_User1);
- for (index = 0; index < width; index++)
- g_vm->glk_put_char (' ');
- g_vm->glk_window_move_cursor (gsc_status_window, 0, 0);
-
- /* See if the game is indicating any current player room. */
- room = sc_get_game_room (gsc_game);
- if (!gsc_is_string_usable (room))
- {
- /*
- * Player location is indeterminate, so print out a generic status,
- * showing the game name and author.
- */
- g_vm->glk_window_move_cursor (gsc_status_window, 1, 0);
- gsc_put_string (sc_get_game_name (gsc_game));
- g_vm->glk_put_string (" | ");
- gsc_put_string (sc_get_game_author (gsc_game));
- }
- else
- {
- const sc_char *status;
- char score[64];
-
- /* Print the player location. */
- g_vm->glk_window_move_cursor (gsc_status_window, 1, 0);
- gsc_put_string (room);
-
- /* Get the game's status line, or if none, format score. */
- status = sc_get_game_status_line (gsc_game);
- if (!gsc_is_string_usable (status))
- {
- sprintf (score, "Score: %ld", sc_get_game_score (gsc_game));
- status = score;
- }
-
- /* Print the status line or score at window right, if it fits. */
- if (width > strlen (status) + GSC_STATUS_SLOP + 1)
- {
- glui32 position;
-
- position = width - strlen (status) - GSC_STATUS_SLOP;
- g_vm->glk_window_move_cursor (gsc_status_window, position - 1, 0);
- gsc_put_string (status);
- }
- }
-
- g_vm->glk_set_window (gsc_main_window);
- }
+gsc_status_update() {
+ glui32 width, height;
+ uint index;
+ assert(gsc_status_window);
+
+ g_vm->glk_window_get_size(gsc_status_window, &width, &height);
+ if (height > 0) {
+ const sc_char *room;
+
+ g_vm->glk_window_clear(gsc_status_window);
+ g_vm->glk_window_move_cursor(gsc_status_window, 0, 0);
+ g_vm->glk_set_window(gsc_status_window);
+
+ g_vm->glk_set_style(style_User1);
+ for (index = 0; index < width; index++)
+ g_vm->glk_put_char(' ');
+ g_vm->glk_window_move_cursor(gsc_status_window, 0, 0);
+
+ /* See if the game is indicating any current player room. */
+ room = sc_get_game_room(gsc_game);
+ if (!gsc_is_string_usable(room)) {
+ /*
+ * Player location is indeterminate, so print out a generic status,
+ * showing the game name and author.
+ */
+ g_vm->glk_window_move_cursor(gsc_status_window, 1, 0);
+ gsc_put_string(sc_get_game_name(gsc_game));
+ g_vm->glk_put_string(" | ");
+ gsc_put_string(sc_get_game_author(gsc_game));
+ } else {
+ const sc_char *status;
+ char score[64];
+
+ /* Print the player location. */
+ g_vm->glk_window_move_cursor(gsc_status_window, 1, 0);
+ gsc_put_string(room);
+
+ /* Get the game's status line, or if none, format score. */
+ status = sc_get_game_status_line(gsc_game);
+ if (!gsc_is_string_usable(status)) {
+ sprintf(score, "Score: %ld", sc_get_game_score(gsc_game));
+ status = score;
+ }
+
+ /* Print the status line or score at window right, if it fits. */
+ if (width > strlen(status) + GSC_STATUS_SLOP + 1) {
+ glui32 position;
+
+ position = width - strlen(status) - GSC_STATUS_SLOP;
+ g_vm->glk_window_move_cursor(gsc_status_window, position - 1, 0);
+ gsc_put_string(status);
+ }
+ }
+
+ g_vm->glk_set_window(gsc_main_window);
+ }
}
@@ -933,15 +914,14 @@ gsc_status_update()
* available length.
*/
static void
-gsc_status_safe_strcat (char *dest, size_t length, const char *src)
-{
- size_t available, src_length;
+gsc_status_safe_strcat(char *dest, size_t length, const char *src) {
+ size_t available, src_length;
- /* Append only as many characters as will fit. */
- src_length = strlen (src);
- available = length - strlen (dest) - 1;
- if (available > 0)
- strncat (dest, src, src_length < available ? src_length : available);
+ /* Append only as many characters as will fit. */
+ src_length = strlen(src);
+ available = length - strlen(dest) - 1;
+ if (available > 0)
+ strncat(dest, src, src_length < available ? src_length : available);
}
@@ -953,48 +933,44 @@ gsc_status_safe_strcat (char *dest, size_t length, const char *src)
* windowing Glk libraries.
*/
static void
-gsc_status_print()
-{
- static char current_status[GSC_STATUS_BUFFER_LENGTH + 1];
-
- const sc_char *room;
-
- /* Do nothing if the game isn't indicating any current player room. */
- room = sc_get_game_room (gsc_game);
- if (gsc_is_string_usable (room))
- {
- char buffer[GSC_STATUS_BUFFER_LENGTH + 1];
- const sc_char *status;
- char score[64];
-
- /* Make an attempt at a status line, starting with player location. */
- strcpy (buffer, "");
- gsc_status_safe_strcat (buffer, sizeof (buffer), room);
-
- /* Get the game's status line, or if none, format score. */
- status = sc_get_game_status_line (gsc_game);
- if (!gsc_is_string_usable (status))
- {
- sprintf (score, "Score: %ld", sc_get_game_score (gsc_game));
- status = score;
- }
+gsc_status_print() {
+ static char current_status[GSC_STATUS_BUFFER_LENGTH + 1];
+
+ const sc_char *room;
+
+ /* Do nothing if the game isn't indicating any current player room. */
+ room = sc_get_game_room(gsc_game);
+ if (gsc_is_string_usable(room)) {
+ char buffer[GSC_STATUS_BUFFER_LENGTH + 1];
+ const sc_char *status;
+ char score[64];
+
+ /* Make an attempt at a status line, starting with player location. */
+ strcpy(buffer, "");
+ gsc_status_safe_strcat(buffer, sizeof(buffer), room);
+
+ /* Get the game's status line, or if none, format score. */
+ status = sc_get_game_status_line(gsc_game);
+ if (!gsc_is_string_usable(status)) {
+ sprintf(score, "Score: %ld", sc_get_game_score(gsc_game));
+ status = score;
+ }
- /* Append the status line or score. */
- gsc_status_safe_strcat (buffer, sizeof (buffer), " | ");
- gsc_status_safe_strcat (buffer, sizeof (buffer), status);
+ /* Append the status line or score. */
+ gsc_status_safe_strcat(buffer, sizeof(buffer), " | ");
+ gsc_status_safe_strcat(buffer, sizeof(buffer), status);
- /* If this matches the current saved status line, do nothing more. */
- if (strcmp (buffer, current_status) != 0)
- {
- /* Bracket, and output the status line buffer. */
- g_vm->glk_put_string ("[ ");
- gsc_put_string (buffer);
- g_vm->glk_put_string (" ]\n");
+ /* If this matches the current saved status line, do nothing more. */
+ if (strcmp(buffer, current_status) != 0) {
+ /* Bracket, and output the status line buffer. */
+ g_vm->glk_put_string("[ ");
+ gsc_put_string(buffer);
+ g_vm->glk_put_string(" ]\n");
- /* Save the details of the printed status buffer. */
- strcpy (current_status, buffer);
- }
- }
+ /* Save the details of the printed status buffer. */
+ strcpy(current_status, buffer);
+ }
+ }
}
@@ -1005,12 +981,11 @@ gsc_status_print()
* or prints the status line to the main window.
*/
static void
-gsc_status_notify()
-{
- if (gsc_status_window)
- gsc_status_update ();
- else
- gsc_status_print ();
+gsc_status_notify() {
+ if (gsc_status_window)
+ gsc_status_update();
+ else
+ gsc_status_print();
}
@@ -1022,27 +997,25 @@ gsc_status_notify()
* arrange events.
*/
static void
-gsc_status_redraw()
-{
- if (gsc_status_window)
- {
- winid_t parent;
-
- /*
- * Rearrange the status window, without changing its actual arrangement
- * in any way. This is a hack to work round incorrect window repainting
- * in Xglk; it forces a complete repaint of affected windows on Glk
- * window resize and arrange events, and works in part because Xglk
- * doesn't check for actual arrangement changes in any way before
- * invalidating its windows. The hack should be harmless to Glk
- * libraries other than Xglk, moreover, we're careful to activate it
- * only on resize and arrange events.
- */
- parent = g_vm->glk_window_get_parent (gsc_status_window);
- g_vm->glk_window_set_arrangement (parent,
- winmethod_Above | winmethod_Fixed, 1, nullptr);
- gsc_status_update ();
- }
+gsc_status_redraw() {
+ if (gsc_status_window) {
+ winid_t parent;
+
+ /*
+ * Rearrange the status window, without changing its actual arrangement
+ * in any way. This is a hack to work round incorrect window repainting
+ * in Xglk; it forces a complete repaint of affected windows on Glk
+ * window resize and arrange events, and works in part because Xglk
+ * doesn't check for actual arrangement changes in any way before
+ * invalidating its windows. The hack should be harmless to Glk
+ * libraries other than Xglk, moreover, we're careful to activate it
+ * only on resize and arrange events.
+ */
+ parent = g_vm->glk_window_get_parent(gsc_status_window);
+ g_vm->glk_window_set_arrangement(parent,
+ winmethod_Above | winmethod_Fixed, 1, nullptr);
+ gsc_status_update();
+ }
}
@@ -1059,8 +1032,8 @@ static int gsc_help_requested = FALSE,
/* Font descriptor type, encapsulating size and monospaced boolean. */
typedef struct {
- sc_bool is_monospaced;
- sc_int size;
+ sc_bool is_monospaced;
+ sc_int size;
} gsc_font_size_t;
/* Font stack and attributes for nesting tags. */
@@ -1098,29 +1071,25 @@ static const glui32 GSC_CANCEL_WAIT_1 = ' ',
* help from the interpreter unless silenced.
*/
static void
-gsc_output_register_help_request()
-{
- gsc_help_requested = TRUE;
+gsc_output_register_help_request() {
+ gsc_help_requested = TRUE;
}
static void
-gsc_output_silence_help_hints()
-{
- gsc_help_hints_silenced = TRUE;
+gsc_output_silence_help_hints() {
+ gsc_help_hints_silenced = TRUE;
}
static void
-gsc_output_provide_help_hint()
-{
- if (gsc_help_requested && !gsc_help_hints_silenced)
- {
- g_vm->glk_set_style (style_Emphasized);
- g_vm->glk_put_string ("[Try 'glk help' for help on special interpreter"
- " commands]\n");
+gsc_output_provide_help_hint() {
+ if (gsc_help_requested && !gsc_help_hints_silenced) {
+ g_vm->glk_set_style(style_Emphasized);
+ g_vm->glk_put_string("[Try 'glk help' for help on special interpreter"
+ " commands]\n");
- gsc_help_requested = FALSE;
- g_vm->glk_set_style (style_Normal);
- }
+ gsc_help_requested = FALSE;
+ g_vm->glk_set_style(style_Normal);
+ }
}
@@ -1129,67 +1098,58 @@ gsc_output_provide_help_hint()
*
* Set a Glk style based on the top of the font stack and attributes.
*/
-static void gsc_set_glk_style()
-{
- sc_bool is_monospaced;
- sc_int font_size;
-
- /* Get the current font stack top, or default value. */
- if (gsc_font_index > 0)
- {
- is_monospaced = gsc_font_stack[gsc_font_index - 1].is_monospaced;
- font_size = gsc_font_stack[gsc_font_index - 1].size;
- }
- else
- {
- is_monospaced = FALSE;
- font_size = GSC_DEFAULT_FONT_SIZE;
- }
-
- /*
- * Map the font and current attributes into a Glk style. Because Glk styles
- * aren't cumulative this has to be done by precedences.
- */
- if (is_monospaced)
- {
- /*
- * No matter the size or attributes, if monospaced use Preformatted
- * style, as it's all we have.
- */
- g_vm->glk_set_style (style_Preformatted);
- }
- else
- {
- /*
- * For large and medium point sizes, use Header or Subheader styles
- * respectively.
- */
- if (font_size >= GSC_LARGE_FONT_SIZE)
- g_vm->glk_set_style (style_Header);
- else if (font_size >= GSC_MEDIUM_FONT_SIZE)
- g_vm->glk_set_style (style_Subheader);
- else
- {
- /*
- * For bold, use Subheader; for italics, underline, or secondary
- * color, use Emphasized.
- */
- if (gsc_attribute_bold > 0)
- g_vm->glk_set_style (style_Subheader);
- else if (gsc_attribute_italic > 0
- || gsc_attribute_underline > 0
- || gsc_attribute_secondary_color > 0)
- g_vm->glk_set_style (style_Emphasized);
- else
- {
- /*
- * There's nothing special about this text, so drop down to
- * Normal style.
- */
- g_vm->glk_set_style (style_Normal);
- }
- }
- }
+static void gsc_set_glk_style() {
+ sc_bool is_monospaced;
+ sc_int font_size;
+
+ /* Get the current font stack top, or default value. */
+ if (gsc_font_index > 0) {
+ is_monospaced = gsc_font_stack[gsc_font_index - 1].is_monospaced;
+ font_size = gsc_font_stack[gsc_font_index - 1].size;
+ } else {
+ is_monospaced = FALSE;
+ font_size = GSC_DEFAULT_FONT_SIZE;
+ }
+
+ /*
+ * Map the font and current attributes into a Glk style. Because Glk styles
+ * aren't cumulative this has to be done by precedences.
+ */
+ if (is_monospaced) {
+ /*
+ * No matter the size or attributes, if monospaced use Preformatted
+ * style, as it's all we have.
+ */
+ g_vm->glk_set_style(style_Preformatted);
+ } else {
+ /*
+ * For large and medium point sizes, use Header or Subheader styles
+ * respectively.
+ */
+ if (font_size >= GSC_LARGE_FONT_SIZE)
+ g_vm->glk_set_style(style_Header);
+ else if (font_size >= GSC_MEDIUM_FONT_SIZE)
+ g_vm->glk_set_style(style_Subheader);
+ else {
+ /*
+ * For bold, use Subheader; for italics, underline, or secondary
+ * color, use Emphasized.
+ */
+ if (gsc_attribute_bold > 0)
+ g_vm->glk_set_style(style_Subheader);
+ else if (gsc_attribute_italic > 0
+ || gsc_attribute_underline > 0
+ || gsc_attribute_secondary_color > 0)
+ g_vm->glk_set_style(style_Emphasized);
+ else {
+ /*
+ * There's nothing special about this text, so drop down to
+ * Normal style.
+ */
+ g_vm->glk_set_style(style_Normal);
+ }
+ }
+ }
}
@@ -1201,83 +1161,74 @@ static void gsc_set_glk_style()
* font tag. Set the appropriate Glk style.
*/
static void
-gsc_handle_font_tag (const sc_char *argument)
-{
- /* Ignore the call on stack overrun. */
- if (gsc_font_index < GSC_MAX_STYLE_NESTING)
- {
- sc_char *lower, *face, *size;
- sc_bool is_monospaced;
- sc_int index_, font_size;
-
- /* Get the current top of stack, or default on empty stack. */
- if (gsc_font_index > 0)
- {
- is_monospaced = gsc_font_stack[gsc_font_index - 1].is_monospaced;
- font_size = gsc_font_stack[gsc_font_index - 1].size;
- }
- else
- {
- is_monospaced = FALSE;
- font_size = GSC_DEFAULT_FONT_SIZE;
- }
-
- /* Copy and convert argument to all lowercase. */
- lower = (sc_char *)gsc_malloc (strlen (argument) + 1);
- strcpy (lower, argument);
- for (index_ = 0; lower[index_] != '\0'; index_++)
- lower[index_] = g_vm->glk_char_to_lower (lower[index_]);
-
- /* Find any face= portion of the tag argument. */
- face = strstr (lower, "face=");
- if (face)
- {
- /*
- * There may be plenty of monospaced fonts, but we do only courier
- * and terminal.
- */
- is_monospaced = strncmp (face, "face=\"courier\"", 14) == 0
- || strncmp (face, "face=\"terminal\"", 15) == 0;
- }
-
- /* Find the size= portion of the tag argument. */
- size = strstr (lower, "size=");
- if (size)
- {
- sc_uint value;
-
- /* Deal with incremental and absolute sizes. */
- if (strncmp (size, "size=+", 6) == 0
- && sscanf (size, "size=+%lu", &value) == 1)
- font_size += value;
- else if (strncmp (size, "size=-", 6) == 0
- && sscanf (size, "size=-%lu", &value) == 1)
- font_size -= value;
- else if (sscanf (size, "size=%lu", &value) == 1)
- font_size = value;
- }
-
- /* Done with tag argument copy. */
- free (lower);
-
- /*
- * Push the new font setting onto the font stack, and set Glk style.
- */
- gsc_font_stack[gsc_font_index].is_monospaced = is_monospaced;
- gsc_font_stack[gsc_font_index++].size = font_size;
- gsc_set_glk_style();
- }
+gsc_handle_font_tag(const sc_char *argument) {
+ /* Ignore the call on stack overrun. */
+ if (gsc_font_index < GSC_MAX_STYLE_NESTING) {
+ sc_char *lower, *face, *size;
+ sc_bool is_monospaced;
+ sc_int index_, font_size;
+
+ /* Get the current top of stack, or default on empty stack. */
+ if (gsc_font_index > 0) {
+ is_monospaced = gsc_font_stack[gsc_font_index - 1].is_monospaced;
+ font_size = gsc_font_stack[gsc_font_index - 1].size;
+ } else {
+ is_monospaced = FALSE;
+ font_size = GSC_DEFAULT_FONT_SIZE;
+ }
+
+ /* Copy and convert argument to all lowercase. */
+ lower = (sc_char *)gsc_malloc(strlen(argument) + 1);
+ strcpy(lower, argument);
+ for (index_ = 0; lower[index_] != '\0'; index_++)
+ lower[index_] = g_vm->glk_char_to_lower(lower[index_]);
+
+ /* Find any face= portion of the tag argument. */
+ face = strstr(lower, "face=");
+ if (face) {
+ /*
+ * There may be plenty of monospaced fonts, but we do only courier
+ * and terminal.
+ */
+ is_monospaced = strncmp(face, "face=\"courier\"", 14) == 0
+ || strncmp(face, "face=\"terminal\"", 15) == 0;
+ }
+
+ /* Find the size= portion of the tag argument. */
+ size = strstr(lower, "size=");
+ if (size) {
+ sc_uint value;
+
+ /* Deal with incremental and absolute sizes. */
+ if (strncmp(size, "size=+", 6) == 0
+ && sscanf(size, "size=+%lu", &value) == 1)
+ font_size += value;
+ else if (strncmp(size, "size=-", 6) == 0
+ && sscanf(size, "size=-%lu", &value) == 1)
+ font_size -= value;
+ else if (sscanf(size, "size=%lu", &value) == 1)
+ font_size = value;
+ }
+
+ /* Done with tag argument copy. */
+ free(lower);
+
+ /*
+ * Push the new font setting onto the font stack, and set Glk style.
+ */
+ gsc_font_stack[gsc_font_index].is_monospaced = is_monospaced;
+ gsc_font_stack[gsc_font_index++].size = font_size;
+ gsc_set_glk_style();
+ }
}
static void
-gsc_handle_endfont_tag()
-{
- /* Unless underrun, pop the font stack and set Glk style. */
- if (gsc_font_index > 0)
- {
- gsc_font_index--;
- gsc_set_glk_style();
- }
+gsc_handle_endfont_tag() {
+ /* Unless underrun, pop the font stack and set Glk style. */
+ if (gsc_font_index > 0) {
+ gsc_font_index--;
+ gsc_set_glk_style();
+ }
}
@@ -1288,60 +1239,56 @@ gsc_handle_endfont_tag()
* tag. Set the appropriate Glk style.
*/
static void
-gsc_handle_attribute_tag (sc_int tag)
-{
- /*
- * Increment the required attribute nesting counter, and set Glk style.
- */
- switch (tag)
- {
- case SC_TAG_BOLD:
- gsc_attribute_bold++;
- break;
- case SC_TAG_ITALICS:
- gsc_attribute_italic++;
- break;
- case SC_TAG_UNDERLINE:
- gsc_attribute_underline++;
- break;
- case SC_TAG_COLOR:
- gsc_attribute_secondary_color++;
- break;
- default:
- break;
- }
- gsc_set_glk_style();
+gsc_handle_attribute_tag(sc_int tag) {
+ /*
+ * Increment the required attribute nesting counter, and set Glk style.
+ */
+ switch (tag) {
+ case SC_TAG_BOLD:
+ gsc_attribute_bold++;
+ break;
+ case SC_TAG_ITALICS:
+ gsc_attribute_italic++;
+ break;
+ case SC_TAG_UNDERLINE:
+ gsc_attribute_underline++;
+ break;
+ case SC_TAG_COLOR:
+ gsc_attribute_secondary_color++;
+ break;
+ default:
+ break;
+ }
+ gsc_set_glk_style();
}
static void
-gsc_handle_endattribute_tag (sc_int tag)
-{
- /*
- * Decrement the required attribute nesting counter, unless underrun, and
- * set Glk style.
- */
- switch (tag)
- {
- case SC_TAG_ENDBOLD:
- if (gsc_attribute_bold > 0)
- gsc_attribute_bold--;
- break;
- case SC_TAG_ENDITALICS:
- if (gsc_attribute_italic > 0)
- gsc_attribute_italic--;
- break;
- case SC_TAG_ENDUNDERLINE:
- if (gsc_attribute_underline > 0)
- gsc_attribute_underline--;
- break;
- case SC_TAG_ENDCOLOR:
- if (gsc_attribute_secondary_color > 0)
- gsc_attribute_secondary_color--;
- break;
- default:
- break;
- }
- gsc_set_glk_style();
+gsc_handle_endattribute_tag(sc_int tag) {
+ /*
+ * Decrement the required attribute nesting counter, unless underrun, and
+ * set Glk style.
+ */
+ switch (tag) {
+ case SC_TAG_ENDBOLD:
+ if (gsc_attribute_bold > 0)
+ gsc_attribute_bold--;
+ break;
+ case SC_TAG_ENDITALICS:
+ if (gsc_attribute_italic > 0)
+ gsc_attribute_italic--;
+ break;
+ case SC_TAG_ENDUNDERLINE:
+ if (gsc_attribute_underline > 0)
+ gsc_attribute_underline--;
+ break;
+ case SC_TAG_ENDCOLOR:
+ if (gsc_attribute_secondary_color > 0)
+ gsc_attribute_secondary_color--;
+ break;
+ default:
+ break;
+ }
+ gsc_set_glk_style();
}
@@ -1351,62 +1298,55 @@ gsc_handle_endattribute_tag (sc_int tag)
* If Glk offers timers, delay for the requested period. Otherwise, this
* function does nothing.
*/
-static void gsc_handle_wait_tag(const sc_char *argument)
-{
- double delay = 0.0;
-
- /* Ignore the wait tag if the Glk doesn't have timers. */
- if (!g_vm->glk_gestalt (gestalt_Timer, 0))
- return;
-
- /* Determine the delay time, and convert to milliseconds. */
- if (sscanf (argument, "%lf", &delay) == 1 && delay > 0.0)
- {
- glui32 milliseconds, timeout;
-
- /*
- * Work with timeouts at 1/10 of the wait period, to minimize Glk
- * timer jitter. Allow the timeout to be canceled by keypress, as a
- * user convenience.
- */
- milliseconds = (glui32) (delay * GSC_MILLISECONDS_PER_SECOND);
- timeout = milliseconds / GSC_TIMEOUTS_COUNT;
- if (timeout > 0)
- {
- glui32 delayed;
- sc_bool is_completed;
-
- /* Request timer events, and let a keypress cancel the wait. */
- g_vm->glk_request_char_event (gsc_main_window);
- g_vm->glk_request_timer_events (timeout);
-
- /* Loop until delay completed or canceled by a keypress. */
- is_completed = TRUE;
- for (delayed = 0; delayed < milliseconds; delayed += timeout)
- {
- event_t event;
-
- gsc_event_wait_2 (evtype_CharInput, evtype_Timer, &event);
- if (event.type == evtype_CharInput)
- {
- /* Cancel the delay, or reissue the input request. */
- if (event.val1 == GSC_CANCEL_WAIT_1
- || event.val1 == GSC_CANCEL_WAIT_2)
- {
- is_completed = FALSE;
- break;
- }
- else
- g_vm->glk_request_char_event (gsc_main_window);
- }
- }
-
- /* Cancel any pending character input, and stop timers. */
- if (is_completed)
- g_vm->glk_cancel_char_event (gsc_main_window);
- g_vm->glk_request_timer_events (0);
- }
- }
+static void gsc_handle_wait_tag(const sc_char *argument) {
+ double delay = 0.0;
+
+ /* Ignore the wait tag if the Glk doesn't have timers. */
+ if (!g_vm->glk_gestalt(gestalt_Timer, 0))
+ return;
+
+ /* Determine the delay time, and convert to milliseconds. */
+ if (sscanf(argument, "%lf", &delay) == 1 && delay > 0.0) {
+ glui32 milliseconds, timeout;
+
+ /*
+ * Work with timeouts at 1/10 of the wait period, to minimize Glk
+ * timer jitter. Allow the timeout to be canceled by keypress, as a
+ * user convenience.
+ */
+ milliseconds = (glui32)(delay * GSC_MILLISECONDS_PER_SECOND);
+ timeout = milliseconds / GSC_TIMEOUTS_COUNT;
+ if (timeout > 0) {
+ glui32 delayed;
+ sc_bool is_completed;
+
+ /* Request timer events, and let a keypress cancel the wait. */
+ g_vm->glk_request_char_event(gsc_main_window);
+ g_vm->glk_request_timer_events(timeout);
+
+ /* Loop until delay completed or canceled by a keypress. */
+ is_completed = TRUE;
+ for (delayed = 0; delayed < milliseconds; delayed += timeout) {
+ event_t event;
+
+ gsc_event_wait_2(evtype_CharInput, evtype_Timer, &event);
+ if (event.type == evtype_CharInput) {
+ /* Cancel the delay, or reissue the input request. */
+ if (event.val1 == GSC_CANCEL_WAIT_1
+ || event.val1 == GSC_CANCEL_WAIT_2) {
+ is_completed = FALSE;
+ break;
+ } else
+ g_vm->glk_request_char_event(gsc_main_window);
+ }
+ }
+
+ /* Cancel any pending character input, and stop timers. */
+ if (is_completed)
+ g_vm->glk_cancel_char_event(gsc_main_window);
+ g_vm->glk_request_timer_events(0);
+ }
+ }
}
@@ -1417,15 +1357,14 @@ static void gsc_handle_wait_tag(const sc_char *argument)
* style.
*/
static void
-gsc_reset_glk_style()
-{
- /* Reset the font stack and attributes, and set a normal style. */
- gsc_font_index = 0;
- gsc_attribute_bold = 0;
- gsc_attribute_italic = 0;
- gsc_attribute_underline = 0;
- gsc_attribute_secondary_color = 0;
- gsc_set_glk_style();
+gsc_reset_glk_style() {
+ /* Reset the font stack and attributes, and set a normal style. */
+ gsc_font_index = 0;
+ gsc_attribute_bold = 0;
+ gsc_attribute_italic = 0;
+ gsc_attribute_underline = 0;
+ gsc_attribute_secondary_color = 0;
+ gsc_set_glk_style();
}
@@ -1436,88 +1375,84 @@ gsc_reset_glk_style()
* here; several are ignored.
*/
void
-os_print_tag (sc_int tag, const sc_char *argument)
-{
- event_t event;
- assert (argument);
-
- switch (tag)
- {
- case SC_TAG_CLS:
- /* Clear the main text display window. */
- g_vm->glk_window_clear (gsc_main_window);
- break;
-
- case SC_TAG_FONT:
- /* Handle with specific tag handler function. */
- gsc_handle_font_tag (argument);
- break;
-
- case SC_TAG_ENDFONT:
- /* Handle with specific endtag handler function. */
- gsc_handle_endfont_tag ();
- break;
-
- case SC_TAG_BOLD:
- case SC_TAG_ITALICS:
- case SC_TAG_UNDERLINE:
- case SC_TAG_COLOR:
- /* Handle with common attribute tag handler function. */
- gsc_handle_attribute_tag (tag);
- break;
-
- case SC_TAG_ENDBOLD:
- case SC_TAG_ENDITALICS:
- case SC_TAG_ENDUNDERLINE:
- case SC_TAG_ENDCOLOR:
- /* Handle with common attribute endtag handler function. */
- gsc_handle_endattribute_tag (tag);
- break;
-
- case SC_TAG_CENTER:
- case SC_TAG_RIGHT:
- case SC_TAG_ENDCENTER:
- case SC_TAG_ENDRIGHT:
- /*
- * We don't center or justify text, but so that things look right we do
- * want a newline on starting or ending such a section.
- */
- g_vm->glk_put_char ('\n');
- break;
-
- case SC_TAG_WAIT:
- /*
- * Update the status line now only if it has its own window, then
- * handle with a specialized handler.
- */
- if (gsc_status_window)
- gsc_status_notify ();
- gsc_handle_wait_tag (argument);
- break;
-
- case SC_TAG_WAITKEY:
- /*
- * If reading an input log, ignore; it disrupts replay. Write a newline
- * to separate off any unterminated game output instead.
- */
- if (!gsc_readlog_stream)
- {
- /* Update the status line now only if it has its own window. */
- if (gsc_status_window)
- gsc_status_notify ();
-
- /* Request a character event, and wait for it to be filled. */
- g_vm->glk_request_char_event (gsc_main_window);
- gsc_event_wait (evtype_CharInput, &event);
- }
- else
- g_vm->glk_put_char ('\n');
- break;
-
- default:
- /* Ignore unimplemented and unknown tags. */
- break;
- }
+os_print_tag(sc_int tag, const sc_char *argument) {
+ event_t event;
+ assert(argument);
+
+ switch (tag) {
+ case SC_TAG_CLS:
+ /* Clear the main text display window. */
+ g_vm->glk_window_clear(gsc_main_window);
+ break;
+
+ case SC_TAG_FONT:
+ /* Handle with specific tag handler function. */
+ gsc_handle_font_tag(argument);
+ break;
+
+ case SC_TAG_ENDFONT:
+ /* Handle with specific endtag handler function. */
+ gsc_handle_endfont_tag();
+ break;
+
+ case SC_TAG_BOLD:
+ case SC_TAG_ITALICS:
+ case SC_TAG_UNDERLINE:
+ case SC_TAG_COLOR:
+ /* Handle with common attribute tag handler function. */
+ gsc_handle_attribute_tag(tag);
+ break;
+
+ case SC_TAG_ENDBOLD:
+ case SC_TAG_ENDITALICS:
+ case SC_TAG_ENDUNDERLINE:
+ case SC_TAG_ENDCOLOR:
+ /* Handle with common attribute endtag handler function. */
+ gsc_handle_endattribute_tag(tag);
+ break;
+
+ case SC_TAG_CENTER:
+ case SC_TAG_RIGHT:
+ case SC_TAG_ENDCENTER:
+ case SC_TAG_ENDRIGHT:
+ /*
+ * We don't center or justify text, but so that things look right we do
+ * want a newline on starting or ending such a section.
+ */
+ g_vm->glk_put_char('\n');
+ break;
+
+ case SC_TAG_WAIT:
+ /*
+ * Update the status line now only if it has its own window, then
+ * handle with a specialized handler.
+ */
+ if (gsc_status_window)
+ gsc_status_notify();
+ gsc_handle_wait_tag(argument);
+ break;
+
+ case SC_TAG_WAITKEY:
+ /*
+ * If reading an input log, ignore; it disrupts replay. Write a newline
+ * to separate off any unterminated game output instead.
+ */
+ if (!gsc_readlog_stream) {
+ /* Update the status line now only if it has its own window. */
+ if (gsc_status_window)
+ gsc_status_notify();
+
+ /* Request a character event, and wait for it to be filled. */
+ g_vm->glk_request_char_event(gsc_main_window);
+ gsc_event_wait(evtype_CharInput, &event);
+ } else
+ g_vm->glk_put_char('\n');
+ break;
+
+ default:
+ /* Ignore unimplemented and unknown tags. */
+ break;
+ }
}
@@ -1527,30 +1462,30 @@ os_print_tag (sc_int tag, const sc_char *argument)
* Print a text string to the main output window.
*/
void os_print_string(const sc_char *string) {
- sc_bool is_monospaced;
- assert (string);
- assert (g_vm->glk_stream_get_current ());
-
- /*
- * Get the monospace font setting from the current top of stack, or
- * default on empty stack. If set, we may need to use an alternative
- * function to write this string.
- */
- if (gsc_font_index > 0)
- is_monospaced = gsc_font_stack[gsc_font_index - 1].is_monospaced;
- else
- is_monospaced = FALSE;
-
- /*
- * The main window should always be the currently set window at this point,
- * so we never be attempting monospaced output to the status window.
- * Nevertheless, check anyway.
- */
- if (is_monospaced
- && g_vm->glk_stream_get_current () == g_vm->glk_window_get_stream (gsc_main_window))
- gsc_put_string_alternate (string);
- else
- gsc_put_string (string);
+ sc_bool is_monospaced;
+ assert(string);
+ assert(g_vm->glk_stream_get_current());
+
+ /*
+ * Get the monospace font setting from the current top of stack, or
+ * default on empty stack. If set, we may need to use an alternative
+ * function to write this string.
+ */
+ if (gsc_font_index > 0)
+ is_monospaced = gsc_font_stack[gsc_font_index - 1].is_monospaced;
+ else
+ is_monospaced = FALSE;
+
+ /*
+ * The main window should always be the currently set window at this point,
+ * so we never be attempting monospaced output to the status window.
+ * Nevertheless, check anyway.
+ */
+ if (is_monospaced
+ && g_vm->glk_stream_get_current() == g_vm->glk_window_get_stream(gsc_main_window))
+ gsc_put_string_alternate(string);
+ else
+ gsc_put_string(string);
}
@@ -1561,12 +1496,11 @@ void os_print_string(const sc_char *string) {
* dedicated debugging window attempted.
*/
void
-os_print_string_debug (const sc_char *string)
-{
- assert (string);
- assert (g_vm->glk_stream_get_current ());
+os_print_string_debug(const sc_char *string) {
+ assert(string);
+ assert(g_vm->glk_stream_get_current());
- gsc_put_string (string);
+ gsc_put_string(string);
}
@@ -1583,53 +1517,46 @@ os_print_string_debug (const sc_char *string)
* string is one that hints that it's from the interpreter, not the game.
*/
static void
-gsc_styled_string (glui32 style, const char *message)
-{
- assert (message);
+gsc_styled_string(glui32 style, const char *message) {
+ assert(message);
- g_vm->glk_set_style (style);
- g_vm->glk_put_string ((char *) message);
- g_vm->glk_set_style (style_Normal);
+ g_vm->glk_set_style(style);
+ g_vm->glk_put_string((char *) message);
+ g_vm->glk_set_style(style_Normal);
}
static void
-gsc_styled_char (glui32 style, char c)
-{
- char buffer[2];
+gsc_styled_char(glui32 style, char c) {
+ char buffer[2];
- buffer[0] = c;
- buffer[1] = '\0';
- gsc_styled_string (style, buffer);
+ buffer[0] = c;
+ buffer[1] = '\0';
+ gsc_styled_string(style, buffer);
}
static void
-gsc_standout_string (const char *message)
-{
- gsc_styled_string (style_Emphasized, message);
+gsc_standout_string(const char *message) {
+ gsc_styled_string(style_Emphasized, message);
}
static void
-gsc_standout_char (char c)
-{
- gsc_styled_char (style_Emphasized, c);
+gsc_standout_char(char c) {
+ gsc_styled_char(style_Emphasized, c);
}
static void
-gsc_normal_string (const char *message)
-{
- gsc_styled_string (style_Normal, message);
+gsc_normal_string(const char *message) {
+ gsc_styled_string(style_Normal, message);
}
static void
-gsc_normal_char (char c)
-{
- gsc_styled_char (style_Normal, c);
+gsc_normal_char(char c) {
+ gsc_styled_char(style_Normal, c);
}
static void
-gsc_header_string (const char *message)
-{
- gsc_styled_string (style_Header, message);
+gsc_header_string(const char *message) {
+ gsc_styled_string(style_Header, message);
}
@@ -1641,60 +1568,53 @@ gsc_header_string (const char *message)
* it's sort of good enough for the moment.
*/
void
-os_display_hints (sc_game game)
-{
- sc_game_hint hint;
- sc_int refused;
-
- /* For each hint, print the question, and confirm hint display. */
- refused = 0;
- for (hint = sc_get_first_game_hint (game);
- hint; hint = sc_get_next_game_hint (game, hint))
- {
- const sc_char *hint_question, *hint_text;
-
- /* If enough refusals, offer a way out of the loop. */
- if (refused >= GSC_HINT_REFUSAL_LIMIT)
- {
- if (!os_confirm (GSC_CONF_CONTINUE_HINTS))
- break;
- refused = 0;
- }
-
- /* Pop the question. */
- hint_question = sc_get_game_hint_question (game, hint);
- gsc_normal_char ('\n');
- gsc_standout_string (hint_question);
- gsc_normal_char ('\n');
-
- /* Print the subtle hint, or on to the next hint. */
- hint_text = sc_get_game_subtle_hint (game, hint);
- if (hint_text)
- {
- if (!os_confirm (GSC_CONF_SUBTLE_HINT))
- {
- refused++;
- continue;
- }
- gsc_normal_char ('\n');
- gsc_standout_string (hint_text);
- gsc_normal_string ("\n\n");
- }
-
- /* Print the less than subtle hint, or on to the next hint. */
- hint_text = sc_get_game_unsubtle_hint (game, hint);
- if (hint_text)
- {
- if (!os_confirm (GSC_CONF_UNSUBTLE_HINT))
- {
- refused++;
- continue;
- }
- gsc_normal_char ('\n');
- gsc_standout_string (hint_text);
- gsc_normal_string ("\n\n");
- }
- }
+os_display_hints(sc_game game) {
+ sc_game_hint hint;
+ sc_int refused;
+
+ /* For each hint, print the question, and confirm hint display. */
+ refused = 0;
+ for (hint = sc_get_first_game_hint(game);
+ hint; hint = sc_get_next_game_hint(game, hint)) {
+ const sc_char *hint_question, *hint_text;
+
+ /* If enough refusals, offer a way out of the loop. */
+ if (refused >= GSC_HINT_REFUSAL_LIMIT) {
+ if (!os_confirm(GSC_CONF_CONTINUE_HINTS))
+ break;
+ refused = 0;
+ }
+
+ /* Pop the question. */
+ hint_question = sc_get_game_hint_question(game, hint);
+ gsc_normal_char('\n');
+ gsc_standout_string(hint_question);
+ gsc_normal_char('\n');
+
+ /* Print the subtle hint, or on to the next hint. */
+ hint_text = sc_get_game_subtle_hint(game, hint);
+ if (hint_text) {
+ if (!os_confirm(GSC_CONF_SUBTLE_HINT)) {
+ refused++;
+ continue;
+ }
+ gsc_normal_char('\n');
+ gsc_standout_string(hint_text);
+ gsc_normal_string("\n\n");
+ }
+
+ /* Print the less than subtle hint, or on to the next hint. */
+ hint_text = sc_get_game_unsubtle_hint(game, hint);
+ if (hint_text) {
+ if (!os_confirm(GSC_CONF_UNSUBTLE_HINT)) {
+ refused++;
+ continue;
+ }
+ gsc_normal_char('\n');
+ gsc_standout_string(hint_text);
+ gsc_normal_string("\n\n");
+ }
+ }
}
@@ -1709,21 +1629,19 @@ os_display_hints (sc_game game)
* Stub functions. The unused variables defeat gcc warnings.
*/
void
-os_play_sound (const sc_char *filepath,
- sc_int offset, sc_int length, sc_bool is_looping)
-{
- const sc_char *unused1;
- sc_int unused2, unused3;
- sc_bool unused4;
- unused1 = filepath;
- unused2 = offset;
- unused3 = length;
- unused4 = is_looping;
+os_play_sound(const sc_char *filepath,
+ sc_int offset, sc_int length, sc_bool is_looping) {
+ const sc_char *unused1;
+ sc_int unused2, unused3;
+ sc_bool unused4;
+ unused1 = filepath;
+ unused2 = offset;
+ unused3 = length;
+ unused4 = is_looping;
}
void
-os_stop_sound()
-{
+os_stop_sound() {
}
@@ -1742,43 +1660,40 @@ os_stop_sound()
static int gsclinux_graphics_enabled = TRUE;
static char *gsclinux_game_file = nullptr;
void
-os_show_graphic (const sc_char *filepath, sc_int offset, sc_int length)
-{
- const sc_char *unused1;
- unused1 = filepath;
-
- if (length > 0
- && gsclinux_graphics_enabled && g_vm->glk_gestalt (gestalt_Graphics, 0))
- {
- sc_char *buffer;
-
- /*
- * Try to extract data with dd. Assuming that works, background xv to
- * display the image, then background a job to delay ten seconds and
- * then delete the temporary file containing the image. Systems lacking
- * xv can usually use a small script, named xv, to invoke eog or an
- * alternative image display binary. Not exactly finessed.
- */
- assert (gsclinux_game_file);
- buffer = gsc_malloc (strlen (gsclinux_game_file) + 128);
- sprintf (buffer, "dd if=%s ibs=1c skip=%ld count=%ld obs=100k"
- " of=/tmp/scare.jpg 2>/dev/null",
- gsclinux_game_file, offset, length);
- system (buffer);
- free (buffer);
- system ("xv /tmp/scare.jpg >/dev/null 2>&1 &");
- system ("( sleep 10; rm /tmp/scare.jpg ) >/dev/null 2>&1 &");
- }
+os_show_graphic(const sc_char *filepath, sc_int offset, sc_int length) {
+ const sc_char *unused1;
+ unused1 = filepath;
+
+ if (length > 0
+ && gsclinux_graphics_enabled && g_vm->glk_gestalt(gestalt_Graphics, 0)) {
+ sc_char *buffer;
+
+ /*
+ * Try to extract data with dd. Assuming that works, background xv to
+ * display the image, then background a job to delay ten seconds and
+ * then delete the temporary file containing the image. Systems lacking
+ * xv can usually use a small script, named xv, to invoke eog or an
+ * alternative image display binary. Not exactly finessed.
+ */
+ assert(gsclinux_game_file);
+ buffer = gsc_malloc(strlen(gsclinux_game_file) + 128);
+ sprintf(buffer, "dd if=%s ibs=1c skip=%ld count=%ld obs=100k"
+ " of=/tmp/scare.jpg 2>/dev/null",
+ gsclinux_game_file, offset, length);
+ system(buffer);
+ free(buffer);
+ system("xv /tmp/scare.jpg >/dev/null 2>&1 &");
+ system("( sleep 10; rm /tmp/scare.jpg ) >/dev/null 2>&1 &");
+ }
}
#else
void
-os_show_graphic (const sc_char *filepath, sc_int offset, sc_int length)
-{
- const sc_char *unused1;
- sc_int unused2, unused3;
- unused1 = filepath;
- unused2 = offset;
- unused3 = length;
+os_show_graphic(const sc_char *filepath, sc_int offset, sc_int length) {
+ const sc_char *unused1;
+ sc_int unused2, unused3;
+ unused1 = filepath;
+ unused2 = offset;
+ unused3 = length;
}
#endif
@@ -1793,74 +1708,65 @@ os_show_graphic (const sc_char *filepath, sc_int offset, sc_int length)
* Turn game output scripting (logging) on and off.
*/
static void
-gsc_command_script (const char *argument)
-{
- assert (argument);
-
- if (sc_strcasecmp (argument, "on") == 0)
- {
- frefid_t fileref;
-
- if (gsc_transcript_stream)
- {
- gsc_normal_string ("Glk transcript is already on.\n");
- return;
- }
-
- fileref = g_vm->glk_fileref_create_by_prompt (fileusage_Transcript
- | fileusage_TextMode,
- filemode_WriteAppend, 0);
- if (!fileref)
- {
- gsc_standout_string ("Glk transcript failed.\n");
- return;
- }
-
- gsc_transcript_stream = g_vm->glk_stream_open_file (fileref,
- filemode_WriteAppend, 0);
- g_vm->glk_fileref_destroy (fileref);
- if (!gsc_transcript_stream)
- {
- gsc_standout_string ("Glk transcript failed.\n");
- return;
- }
-
- g_vm->glk_window_set_echo_stream (gsc_main_window, gsc_transcript_stream);
-
- gsc_normal_string ("Glk transcript is now on.\n");
- }
-
- else if (sc_strcasecmp (argument, "off") == 0)
- {
- if (!gsc_transcript_stream)
- {
- gsc_normal_string ("Glk transcript is already off.\n");
- return;
- }
-
- g_vm->glk_stream_close (gsc_transcript_stream, nullptr);
- gsc_transcript_stream = nullptr;
-
- g_vm->glk_window_set_echo_stream (gsc_main_window, nullptr);
-
- gsc_normal_string ("Glk transcript is now off.\n");
- }
-
- else if (strlen (argument) == 0)
- {
- gsc_normal_string ("Glk transcript is ");
- gsc_normal_string (gsc_transcript_stream ? "on" : "off");
- gsc_normal_string (".\n");
- }
-
- else
- {
- gsc_normal_string ("Glk transcript can be ");
- gsc_standout_string ("on");
- gsc_normal_string (", or ");
- gsc_standout_string ("off");
- gsc_normal_string (".\n");
- }
+gsc_command_script(const char *argument) {
+ assert(argument);
+
+ if (sc_strcasecmp(argument, "on") == 0) {
+ frefid_t fileref;
+
+ if (gsc_transcript_stream) {
+ gsc_normal_string("Glk transcript is already on.\n");
+ return;
+ }
+
+ fileref = g_vm->glk_fileref_create_by_prompt(fileusage_Transcript
+ | fileusage_TextMode,
+ filemode_WriteAppend, 0);
+ if (!fileref) {
+ gsc_standout_string("Glk transcript failed.\n");
+ return;
+ }
+
+ gsc_transcript_stream = g_vm->glk_stream_open_file(fileref,
+ filemode_WriteAppend, 0);
+ g_vm->glk_fileref_destroy(fileref);
+ if (!gsc_transcript_stream) {
+ gsc_standout_string("Glk transcript failed.\n");
+ return;
+ }
+
+ g_vm->glk_window_set_echo_stream(gsc_main_window, gsc_transcript_stream);
+
+ gsc_normal_string("Glk transcript is now on.\n");
+ }
+
+ else if (sc_strcasecmp(argument, "off") == 0) {
+ if (!gsc_transcript_stream) {
+ gsc_normal_string("Glk transcript is already off.\n");
+ return;
+ }
+
+ g_vm->glk_stream_close(gsc_transcript_stream, nullptr);
+ gsc_transcript_stream = nullptr;
+
+ g_vm->glk_window_set_echo_stream(gsc_main_window, nullptr);
+
+ gsc_normal_string("Glk transcript is now off.\n");
+ }
+
+ else if (strlen(argument) == 0) {
+ gsc_normal_string("Glk transcript is ");
+ gsc_normal_string(gsc_transcript_stream ? "on" : "off");
+ gsc_normal_string(".\n");
+ }
+
+ else {
+ gsc_normal_string("Glk transcript can be ");
+ gsc_standout_string("on");
+ gsc_normal_string(", or ");
+ gsc_standout_string("off");
+ gsc_normal_string(".\n");
+ }
}
@@ -1870,70 +1776,61 @@ gsc_command_script (const char *argument)
* Turn game input logging on and off.
*/
static void
-gsc_command_inputlog (const char *argument)
-{
- assert (argument);
-
- if (sc_strcasecmp (argument, "on") == 0)
- {
- frefid_t fileref;
-
- if (gsc_inputlog_stream)
- {
- gsc_normal_string ("Glk input logging is already on.\n");
- return;
- }
-
- fileref = g_vm->glk_fileref_create_by_prompt (fileusage_InputRecord
- | fileusage_BinaryMode,
- filemode_WriteAppend, 0);
- if (!fileref)
- {
- gsc_standout_string ("Glk input logging failed.\n");
- return;
- }
-
- gsc_inputlog_stream = g_vm->glk_stream_open_file (fileref,
- filemode_WriteAppend, 0);
- g_vm->glk_fileref_destroy (fileref);
- if (!gsc_inputlog_stream)
- {
- gsc_standout_string ("Glk input logging failed.\n");
- return;
- }
-
- gsc_normal_string ("Glk input logging is now on.\n");
- }
-
- else if (sc_strcasecmp (argument, "off") == 0)
- {
- if (!gsc_inputlog_stream)
- {
- gsc_normal_string ("Glk input logging is already off.\n");
- return;
- }
-
- g_vm->glk_stream_close (gsc_inputlog_stream, nullptr);
- gsc_inputlog_stream = nullptr;
-
- gsc_normal_string ("Glk input log is now off.\n");
- }
-
- else if (strlen (argument) == 0)
- {
- gsc_normal_string ("Glk input logging is ");
- gsc_normal_string (gsc_inputlog_stream ? "on" : "off");
- gsc_normal_string (".\n");
- }
-
- else
- {
- gsc_normal_string ("Glk input logging can be ");
- gsc_standout_string ("on");
- gsc_normal_string (", or ");
- gsc_standout_string ("off");
- gsc_normal_string (".\n");
- }
+gsc_command_inputlog(const char *argument) {
+ assert(argument);
+
+ if (sc_strcasecmp(argument, "on") == 0) {
+ frefid_t fileref;
+
+ if (gsc_inputlog_stream) {
+ gsc_normal_string("Glk input logging is already on.\n");
+ return;
+ }
+
+ fileref = g_vm->glk_fileref_create_by_prompt(fileusage_InputRecord
+ | fileusage_BinaryMode,
+ filemode_WriteAppend, 0);
+ if (!fileref) {
+ gsc_standout_string("Glk input logging failed.\n");
+ return;
+ }
+
+ gsc_inputlog_stream = g_vm->glk_stream_open_file(fileref,
+ filemode_WriteAppend, 0);
+ g_vm->glk_fileref_destroy(fileref);
+ if (!gsc_inputlog_stream) {
+ gsc_standout_string("Glk input logging failed.\n");
+ return;
+ }
+
+ gsc_normal_string("Glk input logging is now on.\n");
+ }
+
+ else if (sc_strcasecmp(argument, "off") == 0) {
+ if (!gsc_inputlog_stream) {
+ gsc_normal_string("Glk input logging is already off.\n");
+ return;
+ }
+
+ g_vm->glk_stream_close(gsc_inputlog_stream, nullptr);
+ gsc_inputlog_stream = nullptr;
+
+ gsc_normal_string("Glk input log is now off.\n");
+ }
+
+ else if (strlen(argument) == 0) {
+ gsc_normal_string("Glk input logging is ");
+ gsc_normal_string(gsc_inputlog_stream ? "on" : "off");
+ gsc_normal_string(".\n");
+ }
+
+ else {
+ gsc_normal_string("Glk input logging can be ");
+ gsc_standout_string("on");
+ gsc_normal_string(", or ");
+ gsc_standout_string("off");
+ gsc_normal_string(".\n");
+ }
}
@@ -1943,76 +1840,66 @@ gsc_command_inputlog (const char *argument)
* Set the game input log, to read input from a file.
*/
static void
-gsc_command_readlog (const char *argument)
-{
- assert (argument);
-
- if (sc_strcasecmp (argument, "on") == 0)
- {
- frefid_t fileref;
-
- if (gsc_readlog_stream)
- {
- gsc_normal_string ("Glk read log is already on.\n");
- return;
- }
-
- fileref = g_vm->glk_fileref_create_by_prompt (fileusage_InputRecord
- | fileusage_BinaryMode,
- filemode_Read, 0);
- if (!fileref)
- {
- gsc_standout_string ("Glk read log failed.\n");
- return;
- }
-
- if (!g_vm->glk_fileref_does_file_exist (fileref))
- {
- g_vm->glk_fileref_destroy (fileref);
- gsc_standout_string ("Glk read log failed.\n");
- return;
- }
-
- gsc_readlog_stream = g_vm->glk_stream_open_file (fileref, filemode_Read, 0);
- g_vm->glk_fileref_destroy (fileref);
- if (!gsc_readlog_stream)
- {
- gsc_standout_string ("Glk read log failed.\n");
- return;
- }
-
- gsc_normal_string ("Glk read log is now on.\n");
- }
-
- else if (sc_strcasecmp (argument, "off") == 0)
- {
- if (!gsc_readlog_stream)
- {
- gsc_normal_string ("Glk read log is already off.\n");
- return;
- }
-
- g_vm->glk_stream_close (gsc_readlog_stream, nullptr);
- gsc_readlog_stream = nullptr;
-
- gsc_normal_string ("Glk read log is now off.\n");
- }
-
- else if (strlen (argument) == 0)
- {
- gsc_normal_string ("Glk read log is ");
- gsc_normal_string (gsc_readlog_stream ? "on" : "off");
- gsc_normal_string (".\n");
- }
-
- else
- {
- gsc_normal_string ("Glk read log can be ");
- gsc_standout_string ("on");
- gsc_normal_string (", or ");
- gsc_standout_string ("off");
- gsc_normal_string (".\n");
- }
+gsc_command_readlog(const char *argument) {
+ assert(argument);
+
+ if (sc_strcasecmp(argument, "on") == 0) {
+ frefid_t fileref;
+
+ if (gsc_readlog_stream) {
+ gsc_normal_string("Glk read log is already on.\n");
+ return;
+ }
+
+ fileref = g_vm->glk_fileref_create_by_prompt(fileusage_InputRecord
+ | fileusage_BinaryMode,
+ filemode_Read, 0);
+ if (!fileref) {
+ gsc_standout_string("Glk read log failed.\n");
+ return;
+ }
+
+ if (!g_vm->glk_fileref_does_file_exist(fileref)) {
+ g_vm->glk_fileref_destroy(fileref);
+ gsc_standout_string("Glk read log failed.\n");
+ return;
+ }
+
+ gsc_readlog_stream = g_vm->glk_stream_open_file(fileref, filemode_Read, 0);
+ g_vm->glk_fileref_destroy(fileref);
+ if (!gsc_readlog_stream) {
+ gsc_standout_string("Glk read log failed.\n");
+ return;
+ }
+
+ gsc_normal_string("Glk read log is now on.\n");
+ }
+
+ else if (sc_strcasecmp(argument, "off") == 0) {
+ if (!gsc_readlog_stream) {
+ gsc_normal_string("Glk read log is already off.\n");
+ return;
+ }
+
+ g_vm->glk_stream_close(gsc_readlog_stream, nullptr);
+ gsc_readlog_stream = nullptr;
+
+ gsc_normal_string("Glk read log is now off.\n");
+ }
+
+ else if (strlen(argument) == 0) {
+ gsc_normal_string("Glk read log is ");
+ gsc_normal_string(gsc_readlog_stream ? "on" : "off");
+ gsc_normal_string(".\n");
+ }
+
+ else {
+ gsc_normal_string("Glk read log can be ");
+ gsc_standout_string("on");
+ gsc_normal_string(", or ");
+ gsc_standout_string("off");
+ gsc_normal_string(".\n");
+ }
}
@@ -2022,49 +1909,42 @@ gsc_command_readlog (const char *argument)
* Turn abbreviation expansions on and off.
*/
static void
-gsc_command_abbreviations (const char *argument)
-{
- assert (argument);
-
- if (sc_strcasecmp (argument, "on") == 0)
- {
- if (gsc_abbreviations_enabled)
- {
- gsc_normal_string ("Glk abbreviation expansions are already on.\n");
- return;
- }
-
- gsc_abbreviations_enabled = TRUE;
- gsc_normal_string ("Glk abbreviation expansions are now on.\n");
- }
-
- else if (sc_strcasecmp (argument, "off") == 0)
- {
- if (!gsc_abbreviations_enabled)
- {
- gsc_normal_string ("Glk abbreviation expansions are already off.\n");
- return;
- }
-
- gsc_abbreviations_enabled = FALSE;
- gsc_normal_string ("Glk abbreviation expansions are now off.\n");
- }
-
- else if (strlen (argument) == 0)
- {
- gsc_normal_string ("Glk abbreviation expansions are ");
- gsc_normal_string (gsc_abbreviations_enabled ? "on" : "off");
- gsc_normal_string (".\n");
- }
-
- else
- {
- gsc_normal_string ("Glk abbreviation expansions can be ");
- gsc_standout_string ("on");
- gsc_normal_string (", or ");
- gsc_standout_string ("off");
- gsc_normal_string (".\n");
- }
+gsc_command_abbreviations(const char *argument) {
+ assert(argument);
+
+ if (sc_strcasecmp(argument, "on") == 0) {
+ if (gsc_abbreviations_enabled) {
+ gsc_normal_string("Glk abbreviation expansions are already on.\n");
+ return;
+ }
+
+ gsc_abbreviations_enabled = TRUE;
+ gsc_normal_string("Glk abbreviation expansions are now on.\n");
+ }
+
+ else if (sc_strcasecmp(argument, "off") == 0) {
+ if (!gsc_abbreviations_enabled) {
+ gsc_normal_string("Glk abbreviation expansions are already off.\n");
+ return;
+ }
+
+ gsc_abbreviations_enabled = FALSE;
+ gsc_normal_string("Glk abbreviation expansions are now off.\n");
+ }
+
+ else if (strlen(argument) == 0) {
+ gsc_normal_string("Glk abbreviation expansions are ");
+ gsc_normal_string(gsc_abbreviations_enabled ? "on" : "off");
+ gsc_normal_string(".\n");
+ }
+
+ else {
+ gsc_normal_string("Glk abbreviation expansions can be ");
+ gsc_standout_string("on");
+ gsc_normal_string(", or ");
+ gsc_standout_string("off");
+ gsc_normal_string(".\n");
+ }
}
@@ -2075,31 +1955,29 @@ gsc_command_abbreviations (const char *argument)
* Print out the Glk library version number.
*/
static void
-gsc_command_print_version_number (glui32 version)
-{
- char buffer[64];
+gsc_command_print_version_number(glui32 version) {
+ char buffer[64];
- sprintf (buffer, "%lu.%lu.%lu",
- (unsigned long) version >> 16,
- (unsigned long) (version >> 8) & 0xff,
- (unsigned long) version & 0xff);
- gsc_normal_string (buffer);
+ sprintf(buffer, "%lu.%lu.%lu",
+ (unsigned long) version >> 16,
+ (unsigned long)(version >> 8) & 0xff,
+ (unsigned long) version & 0xff);
+ gsc_normal_string(buffer);
}
static void
-gsc_command_version (const char *argument)
-{
- glui32 version;
- assert (argument);
+gsc_command_version(const char *argument) {
+ glui32 version;
+ assert(argument);
- gsc_normal_string ("This is version ");
- gsc_command_print_version_number (GSC_PORT_VERSION);
- gsc_normal_string (" of the Glk SCARE port.\n");
+ gsc_normal_string("This is version ");
+ gsc_command_print_version_number(GSC_PORT_VERSION);
+ gsc_normal_string(" of the Glk SCARE port.\n");
- version = g_vm->glk_gestalt (gestalt_Version, 0);
- gsc_normal_string ("The Glk library version is ");
- gsc_command_print_version_number (version);
- gsc_normal_string (".\n");
+ version = g_vm->glk_gestalt(gestalt_Version, 0);
+ gsc_normal_string("The Glk library version is ");
+ gsc_command_print_version_number(version);
+ gsc_normal_string(".\n");
}
@@ -2110,36 +1988,31 @@ gsc_command_version (const char *argument)
* Commands must be on already to enter this function.
*/
static void
-gsc_command_commands (const char *argument)
-{
- assert (argument);
+gsc_command_commands(const char *argument) {
+ assert(argument);
- if (sc_strcasecmp (argument, "on") == 0)
- {
- gsc_normal_string ("Glk commands are already on.\n");
- }
+ if (sc_strcasecmp(argument, "on") == 0) {
+ gsc_normal_string("Glk commands are already on.\n");
+ }
- else if (sc_strcasecmp (argument, "off") == 0)
- {
- gsc_commands_enabled = FALSE;
- gsc_normal_string ("Glk commands are now off.\n");
- }
+ else if (sc_strcasecmp(argument, "off") == 0) {
+ gsc_commands_enabled = FALSE;
+ gsc_normal_string("Glk commands are now off.\n");
+ }
- else if (strlen (argument) == 0)
- {
- gsc_normal_string ("Glk commands are ");
- gsc_normal_string (gsc_commands_enabled ? "on" : "off");
- gsc_normal_string (".\n");
- }
+ else if (strlen(argument) == 0) {
+ gsc_normal_string("Glk commands are ");
+ gsc_normal_string(gsc_commands_enabled ? "on" : "off");
+ gsc_normal_string(".\n");
+ }
- else
- {
- gsc_normal_string ("Glk commands can be ");
- gsc_standout_string ("on");
- gsc_normal_string (", or ");
- gsc_standout_string ("off");
- gsc_normal_string (".\n");
- }
+ else {
+ gsc_normal_string("Glk commands can be ");
+ gsc_standout_string("on");
+ gsc_normal_string(", or ");
+ gsc_standout_string("off");
+ gsc_normal_string(".\n");
+ }
}
@@ -2149,59 +2022,57 @@ gsc_command_commands (const char *argument)
* Print licensing terms.
*/
static void
-gsc_command_license (const char *argument)
-{
- assert (argument);
+gsc_command_license(const char *argument) {
+ assert(argument);
- gsc_normal_string ("This program is free software; you can redistribute it"
- " and/or modify it under the terms of version 2 of the"
- " GNU General Public License as published by the Free"
- " Software Foundation.\n\n");
+ gsc_normal_string("This program is free software; you can redistribute it"
+ " and/or modify it under the terms of version 2 of the"
+ " GNU General Public License as published by the Free"
+ " Software Foundation.\n\n");
- gsc_normal_string ("This program is distributed in the hope that it will be"
- " useful, but ");
- gsc_standout_string ("WITHOUT ANY WARRANTY");
- gsc_normal_string ("; without even the implied warranty of ");
- gsc_standout_string ("MERCHANTABILITY");
- gsc_normal_string (" or ");
- gsc_standout_string ("FITNESS FOR A PARTICULAR PURPOSE");
- gsc_normal_string (". See the GNU General Public License for more"
- " details.\n\n");
+ gsc_normal_string("This program is distributed in the hope that it will be"
+ " useful, but ");
+ gsc_standout_string("WITHOUT ANY WARRANTY");
+ gsc_normal_string("; without even the implied warranty of ");
+ gsc_standout_string("MERCHANTABILITY");
+ gsc_normal_string(" or ");
+ gsc_standout_string("FITNESS FOR A PARTICULAR PURPOSE");
+ gsc_normal_string(". See the GNU General Public License for more"
+ " details.\n\n");
- gsc_normal_string ("You should have received a copy of the GNU General"
- " Public License along with this program; if not, write"
- " to the Free Software Foundation, Inc., 51 Franklin"
- " Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n");
+ gsc_normal_string("You should have received a copy of the GNU General"
+ " Public License along with this program; if not, write"
+ " to the Free Software Foundation, Inc., 51 Franklin"
+ " Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n");
- gsc_normal_string ("Please report any bugs, omissions, or misfeatures to ");
- gsc_standout_string ("simon_baldwin@yahoo.com");
- gsc_normal_string (".\n");
+ gsc_normal_string("Please report any bugs, omissions, or misfeatures to ");
+ gsc_standout_string("simon_baldwin@yahoo.com");
+ gsc_normal_string(".\n");
}
/* Glk subcommands and handler functions. */
-typedef const struct
-{
- const char * const command; /* Glk subcommand. */
- void (* const handler) (const char *argument); /* Subcommand handler. */
- const int takes_argument; /* Argument flag. */
+typedef const struct {
+ const char *const command; /* Glk subcommand. */
+ void (* const handler)(const char *argument); /* Subcommand handler. */
+ const int takes_argument; /* Argument flag. */
} gsc_command_t;
typedef gsc_command_t *gsc_commandref_t;
-static void gsc_command_summary (const char *argument);
-static void gsc_command_help (const char *argument);
+static void gsc_command_summary(const char *argument);
+static void gsc_command_help(const char *argument);
static gsc_command_t GSC_COMMAND_TABLE[] = {
- {"summary", gsc_command_summary, FALSE},
- {"script", gsc_command_script, TRUE},
- {"inputlog", gsc_command_inputlog, TRUE},
- {"readlog", gsc_command_readlog, TRUE},
- {"abbreviations", gsc_command_abbreviations, TRUE},
- {"version", gsc_command_version, FALSE},
- {"commands", gsc_command_commands, TRUE},
- {"license", gsc_command_license, FALSE},
- {"help", gsc_command_help, TRUE},
- {nullptr, nullptr, FALSE}
+ {"summary", gsc_command_summary, FALSE},
+ {"script", gsc_command_script, TRUE},
+ {"inputlog", gsc_command_inputlog, TRUE},
+ {"readlog", gsc_command_readlog, TRUE},
+ {"abbreviations", gsc_command_abbreviations, TRUE},
+ {"version", gsc_command_version, FALSE},
+ {"commands", gsc_command_commands, TRUE},
+ {"license", gsc_command_license, FALSE},
+ {"help", gsc_command_help, TRUE},
+ {nullptr, nullptr, FALSE}
};
@@ -2211,24 +2082,22 @@ static gsc_command_t GSC_COMMAND_TABLE[] = {
* Report all current Glk settings.
*/
static void
-gsc_command_summary (const char *argument)
-{
- gsc_commandref_t entry;
- assert (argument);
+gsc_command_summary(const char *argument) {
+ gsc_commandref_t entry;
+ assert(argument);
- /*
- * Call handlers that have status to report with an empty argument,
- * prompting each to print its current setting.
- */
- for (entry = GSC_COMMAND_TABLE; entry->command; entry++)
- {
- if (entry->handler == gsc_command_summary
- || entry->handler == gsc_command_license
- || entry->handler == gsc_command_help)
- continue;
+ /*
+ * Call handlers that have status to report with an empty argument,
+ * prompting each to print its current setting.
+ */
+ for (entry = GSC_COMMAND_TABLE; entry->command; entry++) {
+ if (entry->handler == gsc_command_summary
+ || entry->handler == gsc_command_license
+ || entry->handler == gsc_command_help)
+ continue;
- entry->handler ("");
- }
+ entry->handler("");
+ }
}
@@ -2238,139 +2107,124 @@ gsc_command_summary (const char *argument)
* Document the available Glk commands.
*/
static void
-gsc_command_help (const char *command)
-{
- gsc_commandref_t entry, matched;
- assert (command);
-
- if (strlen (command) == 0)
- {
- gsc_normal_string ("Glk commands are");
- for (entry = GSC_COMMAND_TABLE; entry->command; entry++)
- {
- gsc_commandref_t next;
-
- next = entry + 1;
- gsc_normal_string (next->command ? " " : " and ");
- gsc_standout_string (entry->command);
- gsc_normal_string (next->command ? "," : ".\n\n");
- }
-
- gsc_normal_string ("Glk commands may be abbreviated, as long as"
- " the abbreviation is unambiguous. Use ");
- gsc_standout_string ("glk help");
- gsc_normal_string (" followed by a Glk command name for help on that"
- " command.\n");
- return;
- }
-
- matched = nullptr;
- for (entry = GSC_COMMAND_TABLE; entry->command; entry++)
- {
- if (sc_strncasecmp (command, entry->command, strlen (command)) == 0)
- {
- if (matched)
- {
- gsc_normal_string ("The Glk command ");
- gsc_standout_string (command);
- gsc_normal_string (" is ambiguous. Try ");
- gsc_standout_string ("glk help");
- gsc_normal_string (" for more information.\n");
- return;
- }
- matched = entry;
- }
- }
- if (!matched)
- {
- gsc_normal_string ("The Glk command ");
- gsc_standout_string (command);
- gsc_normal_string (" is not valid. Try ");
- gsc_standout_string ("glk help");
- gsc_normal_string (" for more information.\n");
- return;
- }
-
- if (matched->handler == gsc_command_summary)
- {
- gsc_normal_string ("Prints a summary of all the current Glk SCARE"
- " settings.\n");
- }
-
- else if (matched->handler == gsc_command_script)
- {
- gsc_normal_string ("Logs the game's output to a file.\n\nUse ");
- gsc_standout_string ("glk script on");
- gsc_normal_string (" to begin logging game output, and ");
- gsc_standout_string ("glk script off");
- gsc_normal_string (" to end it. Glk SCARE will ask you for a file"
- " when you turn scripts on.\n");
- }
-
- else if (matched->handler == gsc_command_inputlog)
- {
- gsc_normal_string ("Records the commands you type into a game.\n\nUse ");
- gsc_standout_string ("glk inputlog on");
- gsc_normal_string (", to begin recording your commands, and ");
- gsc_standout_string ("glk inputlog off");
- gsc_normal_string (" to turn off input logs. You can play back"
- " recorded commands into a game with the ");
- gsc_standout_string ("glk readlog");
- gsc_normal_string (" command.\n");
- }
-
- else if (matched->handler == gsc_command_readlog)
- {
- gsc_normal_string ("Plays back commands recorded with ");
- gsc_standout_string ("glk inputlog on");
- gsc_normal_string (".\n\nUse ");
- gsc_standout_string ("glk readlog on");
- gsc_normal_string (". Command play back stops at the end of the"
- " file. You can also play back commands from a"
- " text file created using any standard editor.\n");
- }
-
- else if (matched->handler == gsc_command_abbreviations)
- {
- gsc_normal_string ("Controls abbreviation expansion.\n\nGlk SCARE"
- " automatically expands several standard single"
- " letter abbreviations for you; for example, \"x\""
- " becomes \"examine\". Use ");
- gsc_standout_string ("glk abbreviations on");
- gsc_normal_string (" to turn this feature on, and ");
- gsc_standout_string ("glk abbreviations off");
- gsc_normal_string (" to turn it off. While the feature is on, you"
- " can bypass abbreviation expansion for an"
- " individual game command by prefixing it with a"
- " single quote.\n");
- }
-
- else if (matched->handler == gsc_command_version)
- {
- gsc_normal_string ("Prints the version numbers of the Glk library"
- " and the Glk SCARE port.\n");
- }
-
- else if (matched->handler == gsc_command_commands)
- {
- gsc_normal_string ("Turn off Glk commands.\n\nUse ");
- gsc_standout_string ("glk commands off");
- gsc_normal_string (" to disable all Glk commands, including this one."
- " Once turned off, there is no way to turn Glk"
- " commands back on while inside the game.\n");
- }
-
- else if (matched->handler == gsc_command_license)
- {
- gsc_normal_string ("Prints Glk SCARE's software license.\n");
- }
-
- else if (matched->handler == gsc_command_help)
- gsc_command_help ("");
-
- else
- gsc_normal_string ("There is no help available on that Glk command."
- " Sorry.\n");
+gsc_command_help(const char *command) {
+ gsc_commandref_t entry, matched;
+ assert(command);
+
+ if (strlen(command) == 0) {
+ gsc_normal_string("Glk commands are");
+ for (entry = GSC_COMMAND_TABLE; entry->command; entry++) {
+ gsc_commandref_t next;
+
+ next = entry + 1;
+ gsc_normal_string(next->command ? " " : " and ");
+ gsc_standout_string(entry->command);
+ gsc_normal_string(next->command ? "," : ".\n\n");
+ }
+
+ gsc_normal_string("Glk commands may be abbreviated, as long as"
+ " the abbreviation is unambiguous. Use ");
+ gsc_standout_string("glk help");
+ gsc_normal_string(" followed by a Glk command name for help on that"
+ " command.\n");
+ return;
+ }
+
+ matched = nullptr;
+ for (entry = GSC_COMMAND_TABLE; entry->command; entry++) {
+ if (sc_strncasecmp(command, entry->command, strlen(command)) == 0) {
+ if (matched) {
+ gsc_normal_string("The Glk command ");
+ gsc_standout_string(command);
+ gsc_normal_string(" is ambiguous. Try ");
+ gsc_standout_string("glk help");
+ gsc_normal_string(" for more information.\n");
+ return;
+ }
+ matched = entry;
+ }
+ }
+ if (!matched) {
+ gsc_normal_string("The Glk command ");
+ gsc_standout_string(command);
+ gsc_normal_string(" is not valid. Try ");
+ gsc_standout_string("glk help");
+ gsc_normal_string(" for more information.\n");
+ return;
+ }
+
+ if (matched->handler == gsc_command_summary) {
+ gsc_normal_string("Prints a summary of all the current Glk SCARE"
+ " settings.\n");
+ }
+
+ else if (matched->handler == gsc_command_script) {
+ gsc_normal_string("Logs the game's output to a file.\n\nUse ");
+ gsc_standout_string("glk script on");
+ gsc_normal_string(" to begin logging game output, and ");
+ gsc_standout_string("glk script off");
+ gsc_normal_string(" to end it. Glk SCARE will ask you for a file"
+ " when you turn scripts on.\n");
+ }
+
+ else if (matched->handler == gsc_command_inputlog) {
+ gsc_normal_string("Records the commands you type into a game.\n\nUse ");
+ gsc_standout_string("glk inputlog on");
+ gsc_normal_string(", to begin recording your commands, and ");
+ gsc_standout_string("glk inputlog off");
+ gsc_normal_string(" to turn off input logs. You can play back"
+ " recorded commands into a game with the ");
+ gsc_standout_string("glk readlog");
+ gsc_normal_string(" command.\n");
+ }
+
+ else if (matched->handler == gsc_command_readlog) {
+ gsc_normal_string("Plays back commands recorded with ");
+ gsc_standout_string("glk inputlog on");
+ gsc_normal_string(".\n\nUse ");
+ gsc_standout_string("glk readlog on");
+ gsc_normal_string(". Command play back stops at the end of the"
+ " file. You can also play back commands from a"
+ " text file created using any standard editor.\n");
+ }
+
+ else if (matched->handler == gsc_command_abbreviations) {
+ gsc_normal_string("Controls abbreviation expansion.\n\nGlk SCARE"
+ " automatically expands several standard single"
+ " letter abbreviations for you; for example, \"x\""
+ " becomes \"examine\". Use ");
+ gsc_standout_string("glk abbreviations on");
+ gsc_normal_string(" to turn this feature on, and ");
+ gsc_standout_string("glk abbreviations off");
+ gsc_normal_string(" to turn it off. While the feature is on, you"
+ " can bypass abbreviation expansion for an"
+ " individual game command by prefixing it with a"
+ " single quote.\n");
+ }
+
+ else if (matched->handler == gsc_command_version) {
+ gsc_normal_string("Prints the version numbers of the Glk library"
+ " and the Glk SCARE port.\n");
+ }
+
+ else if (matched->handler == gsc_command_commands) {
+ gsc_normal_string("Turn off Glk commands.\n\nUse ");
+ gsc_standout_string("glk commands off");
+ gsc_normal_string(" to disable all Glk commands, including this one."
+ " Once turned off, there is no way to turn Glk"
+ " commands back on while inside the game.\n");
+ }
+
+ else if (matched->handler == gsc_command_license) {
+ gsc_normal_string("Prints Glk SCARE's software license.\n");
+ }
+
+ else if (matched->handler == gsc_command_help)
+ gsc_command_help("");
+
+ else
+ gsc_normal_string("There is no help available on that Glk command."
+ " Sorry.\n");
}
@@ -2381,103 +2235,94 @@ gsc_command_help (const char *command)
* Glk port command, handle it and return TRUE, otherwise return FALSE.
*/
static int
-gsc_command_escape (const char *string)
-{
- int posn;
- char *string_copy, *command, *argument;
- assert (string);
-
- /*
- * Return FALSE if the string doesn't begin with the Glk command escape
- * introducer.
- */
- posn = strspn (string, "\t ");
- if (sc_strncasecmp (string + posn, "glk", strlen ("glk")) != 0)
- return FALSE;
-
- /* Take a copy of the string, without any leading space or introducer. */
- string_copy = (char *)gsc_malloc (strlen (string + posn) + 1 - strlen ("glk"));
- strcpy (string_copy, string + posn + strlen ("glk"));
-
- /*
- * Find the subcommand; the first word in the string copy. Find its end,
- * and ensure it terminates with a NUL.
- */
- posn = strspn (string_copy, "\t ");
- command = string_copy + posn;
- posn += strcspn (string_copy + posn, "\t ");
- if (string_copy[posn] != '\0')
- string_copy[posn++] = '\0';
-
- /*
- * Now find any argument data for the command, ensuring it too terminates
- * with a NUL.
- */
- posn += strspn (string_copy + posn, "\t ");
- argument = string_copy + posn;
- posn += strcspn (string_copy + posn, "\t ");
- string_copy[posn] = '\0';
-
- /*
- * Try to handle the command and argument as a Glk subcommand. If it
- * doesn't run unambiguously, print command usage. Treat an empty command
- * as "help".
- */
- if (strlen (command) > 0)
- {
- gsc_commandref_t entry, matched;
- int matches;
-
- /*
- * Search for the first unambiguous table command string matching
- * the command passed in.
- */
- matches = 0;
- matched = nullptr;
- for (entry = GSC_COMMAND_TABLE; entry->command; entry++)
- {
- if (sc_strncasecmp (command, entry->command, strlen (command)) == 0)
- {
- matches++;
- matched = entry;
- }
- }
-
- /* If the match was unambiguous, call the command handler. */
- if (matches == 1)
- {
- gsc_normal_char ('\n');
- matched->handler (argument);
-
- if (!matched->takes_argument && strlen (argument) > 0)
- {
- gsc_normal_string ("[The ");
- gsc_standout_string (matched->command);
- gsc_normal_string (" command ignores arguments.]\n");
- }
- }
-
- /* No match, or the command was ambiguous. */
- else
- {
- gsc_normal_string ("\nThe Glk command ");
- gsc_standout_string (command);
- gsc_normal_string (" is ");
- gsc_normal_string (matches == 0 ? "not valid" : "ambiguous");
- gsc_normal_string (". Try ");
- gsc_standout_string ("glk help");
- gsc_normal_string (" for more information.\n");
- }
- }
- else
- {
- gsc_normal_char ('\n');
- gsc_command_help ("");
- }
-
- /* The string contained a Glk command; return TRUE. */
- free (string_copy);
- return TRUE;
+gsc_command_escape(const char *string) {
+ int posn;
+ char *string_copy, *command, *argument;
+ assert(string);
+
+ /*
+ * Return FALSE if the string doesn't begin with the Glk command escape
+ * introducer.
+ */
+ posn = strspn(string, "\t ");
+ if (sc_strncasecmp(string + posn, "glk", strlen("glk")) != 0)
+ return FALSE;
+
+ /* Take a copy of the string, without any leading space or introducer. */
+ string_copy = (char *)gsc_malloc(strlen(string + posn) + 1 - strlen("glk"));
+ strcpy(string_copy, string + posn + strlen("glk"));
+
+ /*
+ * Find the subcommand; the first word in the string copy. Find its end,
+ * and ensure it terminates with a NUL.
+ */
+ posn = strspn(string_copy, "\t ");
+ command = string_copy + posn;
+ posn += strcspn(string_copy + posn, "\t ");
+ if (string_copy[posn] != '\0')
+ string_copy[posn++] = '\0';
+
+ /*
+ * Now find any argument data for the command, ensuring it too terminates
+ * with a NUL.
+ */
+ posn += strspn(string_copy + posn, "\t ");
+ argument = string_copy + posn;
+ posn += strcspn(string_copy + posn, "\t ");
+ string_copy[posn] = '\0';
+
+ /*
+ * Try to handle the command and argument as a Glk subcommand. If it
+ * doesn't run unambiguously, print command usage. Treat an empty command
+ * as "help".
+ */
+ if (strlen(command) > 0) {
+ gsc_commandref_t entry, matched;
+ int matches;
+
+ /*
+ * Search for the first unambiguous table command string matching
+ * the command passed in.
+ */
+ matches = 0;
+ matched = nullptr;
+ for (entry = GSC_COMMAND_TABLE; entry->command; entry++) {
+ if (sc_strncasecmp(command, entry->command, strlen(command)) == 0) {
+ matches++;
+ matched = entry;
+ }
+ }
+
+ /* If the match was unambiguous, call the command handler. */
+ if (matches == 1) {
+ gsc_normal_char('\n');
+ matched->handler(argument);
+
+ if (!matched->takes_argument && strlen(argument) > 0) {
+ gsc_normal_string("[The ");
+ gsc_standout_string(matched->command);
+ gsc_normal_string(" command ignores arguments.]\n");
+ }
+ }
+
+ /* No match, or the command was ambiguous. */
+ else {
+ gsc_normal_string("\nThe Glk command ");
+ gsc_standout_string(command);
+ gsc_normal_string(" is ");
+ gsc_normal_string(matches == 0 ? "not valid" : "ambiguous");
+ gsc_normal_string(". Try ");
+ gsc_standout_string("glk help");
+ gsc_normal_string(" for more information.\n");
+ }
+ } else {
+ gsc_normal_char('\n');
+ gsc_command_help("");
+ }
+
+ /* The string contained a Glk command; return TRUE. */
+ free(string_copy);
+ return TRUE;
}
@@ -2490,19 +2335,18 @@ static const char GSC_QUOTED_INPUT = '\'';
/* Table of single-character command abbreviations. */
-typedef const struct
-{
- const char abbreviation; /* Abbreviation character. */
- const char *const expansion; /* Expansion string. */
+typedef const struct {
+ const char abbreviation; /* Abbreviation character. */
+ const char *const expansion; /* Expansion string. */
} gsc_abbreviation_t;
typedef gsc_abbreviation_t *gsc_abbreviationref_t;
static gsc_abbreviation_t GSC_ABBREVIATIONS[] = {
- {'c', "close"}, {'g', "again"}, {'i', "inventory"},
- {'k', "attack"}, {'l', "look"}, {'p', "open"},
- {'q', "quit"}, {'r', "drop"}, {'t', "take"},
- {'x', "examine"}, {'y', "yes"}, {'z', "wait"},
- {'\0', nullptr}
+ {'c', "close"}, {'g', "again"}, {'i', "inventory"},
+ {'k', "attack"}, {'l', "look"}, {'p', "open"},
+ {'q', "quit"}, {'r', "drop"}, {'t', "take"},
+ {'x', "examine"}, {'y', "yes"}, {'z', "wait"},
+ {'\0', nullptr}
};
@@ -2513,49 +2357,45 @@ static gsc_abbreviation_t GSC_ABBREVIATIONS[] = {
* game systems.
*/
static void
-gsc_expand_abbreviations (char *buffer, int size)
-{
- char *command, abbreviation;
- const char *expansion;
- gsc_abbreviationref_t entry;
- assert (buffer);
-
- /* Ignore anything that isn't a single letter command. */
- command = buffer + strspn (buffer, "\t ");
- if (!(strlen (command) == 1
- || (strlen (command) > 1 && Common::isSpace(command[1]))))
- return;
-
- /* Scan the abbreviations table for a match. */
- abbreviation = g_vm->glk_char_to_lower ((unsigned char) command[0]);
- expansion = nullptr;
- for (entry = GSC_ABBREVIATIONS; entry->expansion; entry++)
- {
- if (entry->abbreviation == abbreviation)
- {
- expansion = entry->expansion;
- break;
- }
- }
-
- /*
- * If a match found, check for a fit, then replace the character with the
- * expansion string.
- */
- if (expansion)
- {
- if (strlen (buffer) + strlen (expansion) - 1 >= (unsigned int) size)
- return;
-
- memmove (command + strlen (expansion) - 1, command, strlen (command) + 1);
- memcpy (command, expansion, strlen (expansion));
-
- gsc_standout_string ("[");
- gsc_standout_char (abbreviation);
- gsc_standout_string (" -> ");
- gsc_standout_string (expansion);
- gsc_standout_string ("]\n");
- }
+gsc_expand_abbreviations(char *buffer, int size) {
+ char *command, abbreviation;
+ const char *expansion;
+ gsc_abbreviationref_t entry;
+ assert(buffer);
+
+ /* Ignore anything that isn't a single letter command. */
+ command = buffer + strspn(buffer, "\t ");
+ if (!(strlen(command) == 1
+ || (strlen(command) > 1 && Common::isSpace(command[1]))))
+ return;
+
+ /* Scan the abbreviations table for a match. */
+ abbreviation = g_vm->glk_char_to_lower((unsigned char) command[0]);
+ expansion = nullptr;
+ for (entry = GSC_ABBREVIATIONS; entry->expansion; entry++) {
+ if (entry->abbreviation == abbreviation) {
+ expansion = entry->expansion;
+ break;
+ }
+ }
+
+ /*
+ * If a match found, check for a fit, then replace the character with the
+ * expansion string.
+ */
+ if (expansion) {
+ if (strlen(buffer) + strlen(expansion) - 1 >= (unsigned int) size)
+ return;
+
+ memmove(command + strlen(expansion) - 1, command, strlen(command) + 1);
+ memcpy(command, expansion, strlen(expansion));
+
+ gsc_standout_string("[");
+ gsc_standout_char(abbreviation);
+ gsc_standout_string(" -> ");
+ gsc_standout_string(expansion);
+ gsc_standout_string("]\n");
+ }
}
@@ -2565,123 +2405,111 @@ gsc_expand_abbreviations (char *buffer, int size)
* Read and return a line of player input.
*/
sc_bool
-os_read_line (sc_char *buffer, sc_int length)
-{
- sc_int characters;
- assert (buffer && length > 0);
-
- /* If a help request is pending, provide a user hint. */
- gsc_output_provide_help_hint ();
-
- /*
- * Ensure normal style, update the status line, and issue an input prompt.
- */
- gsc_reset_glk_style ();
- gsc_status_notify ();
- g_vm->glk_put_string (">");
-
- /*
- * If we have an input log to read from, use that until it is exhausted.
- * On end of file, close the stream and resume input from line requests.
- */
- if (gsc_readlog_stream)
- {
- glui32 chars;
-
- /* Get the next line from the log stream. */
- chars = g_vm->glk_get_line_stream (gsc_readlog_stream, buffer, length);
- if (chars > 0)
- {
- /* Echo the line just read in input style. */
- g_vm->glk_set_style (style_Input);
- gsc_put_buffer (buffer, chars);
- g_vm->glk_set_style (style_Normal);
-
- /* Return this line as player input. */
- return TRUE;
- }
-
- /*
- * We're at the end of the log stream. Close it, and then continue
- * on to request a line from Glk.
- */
- g_vm->glk_stream_close (gsc_readlog_stream, nullptr);
- gsc_readlog_stream = nullptr;
- }
-
- /*
- * No input log being read, or we just hit the end of file on one. Revert
- * to normal line input; start by getting a new line from Glk.
- */
- characters = gsc_read_line (buffer, length - 1);
- assert (characters <= length);
- buffer[characters] = '\0';
-
- /*
- * If neither abbreviations nor local commands are enabled, use the data
- * read above without further massaging.
- */
- if (gsc_abbreviations_enabled || gsc_commands_enabled)
- {
- char *command;
-
- /*
- * If the first non-space input character is a quote, bypass all
- * abbreviation expansion and local command recognition, and use the
- * unadulterated input, less introductory quote.
- */
- command = buffer + strspn (buffer, "\t ");
- if (command[0] == GSC_QUOTED_INPUT)
- {
- /* Delete the quote with memmove(). */
- memmove (command, command + 1, strlen (command));
- }
- else
- {
- /* Check for, and expand, and abbreviated commands. */
- if (gsc_abbreviations_enabled)
- gsc_expand_abbreviations (buffer, length);
-
- /*
- * Check for standalone "help", then for Glk port special commands;
- * suppress the interpreter's use of this input for Glk commands by
- * returning FALSE.
- */
- if (gsc_commands_enabled)
- {
- int posn;
-
- posn = strspn (buffer, "\t ");
- if (sc_strncasecmp (buffer + posn, "help", strlen ("help"))== 0)
- {
- if (strspn (buffer + posn + strlen ("help"), "\t ")
- == strlen (buffer + posn + strlen ("help")))
- {
- gsc_output_register_help_request ();
- }
- }
-
- if (gsc_command_escape (buffer))
- {
- gsc_output_silence_help_hints ();
- return FALSE;
- }
- }
- }
- }
-
- /*
- * If there is an input log active, log this input string to it. Note that
- * by logging here we get any abbreviation expansions but we won't log glk
- * special commands, nor any input read from a current open input log.
- */
- if (gsc_inputlog_stream)
- {
- g_vm->glk_put_string_stream (gsc_inputlog_stream, buffer);
- g_vm->glk_put_char_stream (gsc_inputlog_stream, '\n');
- }
-
- return TRUE;
+os_read_line(sc_char *buffer, sc_int length) {
+ sc_int characters;
+ assert(buffer && length > 0);
+
+ /* If a help request is pending, provide a user hint. */
+ gsc_output_provide_help_hint();
+
+ /*
+ * Ensure normal style, update the status line, and issue an input prompt.
+ */
+ gsc_reset_glk_style();
+ gsc_status_notify();
+ g_vm->glk_put_string(">");
+
+ /*
+ * If we have an input log to read from, use that until it is exhausted.
+ * On end of file, close the stream and resume input from line requests.
+ */
+ if (gsc_readlog_stream) {
+ glui32 chars;
+
+ /* Get the next line from the log stream. */
+ chars = g_vm->glk_get_line_stream(gsc_readlog_stream, buffer, length);
+ if (chars > 0) {
+ /* Echo the line just read in input style. */
+ g_vm->glk_set_style(style_Input);
+ gsc_put_buffer(buffer, chars);
+ g_vm->glk_set_style(style_Normal);
+
+ /* Return this line as player input. */
+ return TRUE;
+ }
+
+ /*
+ * We're at the end of the log stream. Close it, and then continue
+ * on to request a line from Glk.
+ */
+ g_vm->glk_stream_close(gsc_readlog_stream, nullptr);
+ gsc_readlog_stream = nullptr;
+ }
+
+ /*
+ * No input log being read, or we just hit the end of file on one. Revert
+ * to normal line input; start by getting a new line from Glk.
+ */
+ characters = gsc_read_line(buffer, length - 1);
+ assert(characters <= length);
+ buffer[characters] = '\0';
+
+ /*
+ * If neither abbreviations nor local commands are enabled, use the data
+ * read above without further massaging.
+ */
+ if (gsc_abbreviations_enabled || gsc_commands_enabled) {
+ char *command;
+
+ /*
+ * If the first non-space input character is a quote, bypass all
+ * abbreviation expansion and local command recognition, and use the
+ * unadulterated input, less introductory quote.
+ */
+ command = buffer + strspn(buffer, "\t ");
+ if (command[0] == GSC_QUOTED_INPUT) {
+ /* Delete the quote with memmove(). */
+ memmove(command, command + 1, strlen(command));
+ } else {
+ /* Check for, and expand, and abbreviated commands. */
+ if (gsc_abbreviations_enabled)
+ gsc_expand_abbreviations(buffer, length);
+
+ /*
+ * Check for standalone "help", then for Glk port special commands;
+ * suppress the interpreter's use of this input for Glk commands by
+ * returning FALSE.
+ */
+ if (gsc_commands_enabled) {
+ int posn;
+
+ posn = strspn(buffer, "\t ");
+ if (sc_strncasecmp(buffer + posn, "help", strlen("help")) == 0) {
+ if (strspn(buffer + posn + strlen("help"), "\t ")
+ == strlen(buffer + posn + strlen("help"))) {
+ gsc_output_register_help_request();
+ }
+ }
+
+ if (gsc_command_escape(buffer)) {
+ gsc_output_silence_help_hints();
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ /*
+ * If there is an input log active, log this input string to it. Note that
+ * by logging here we get any abbreviation expansions but we won't log glk
+ * special commands, nor any input read from a current open input log.
+ */
+ if (gsc_inputlog_stream) {
+ g_vm->glk_put_string_stream(gsc_inputlog_stream, buffer);
+ g_vm->glk_put_char_stream(gsc_inputlog_stream, '\n');
+ }
+
+ return TRUE;
}
@@ -2693,12 +2521,11 @@ os_read_line (sc_char *buffer, sc_int length)
* prompt.
*/
sc_bool
-os_read_line_debug (sc_char *buffer, sc_int length)
-{
- gsc_output_silence_help_hints ();
- gsc_reset_glk_style ();
- g_vm->glk_put_string ("[SCARE debug]");
- return os_read_line (buffer, length);
+os_read_line_debug(sc_char *buffer, sc_int length) {
+ gsc_output_silence_help_hints();
+ gsc_reset_glk_style();
+ g_vm->glk_put_string("[SCARE debug]");
+ return os_read_line(buffer, length);
}
@@ -2708,85 +2535,78 @@ os_read_line_debug (sc_char *buffer, sc_int length)
* Confirm a game action with a yes/no prompt.
*/
sc_bool
-os_confirm (sc_int type)
-{
- sc_char response;
-
- /*
- * Always allow game saves and hint display, and if we're reading from an
- * input log, allow everything no matter what, on the assumption that the
- * user knows what they are doing.
- */
- if (gsc_readlog_stream
- || type == SC_CONF_SAVE || type == SC_CONF_VIEW_HINTS)
- return TRUE;
-
- /* Ensure back to normal style, and update status. */
- gsc_reset_glk_style ();
- gsc_status_notify ();
-
- /* Prompt for the confirmation, based on the type. */
- if (type == GSC_CONF_SUBTLE_HINT)
- g_vm->glk_put_string ("View the subtle hint for this topic");
- else if (type == GSC_CONF_UNSUBTLE_HINT)
- g_vm->glk_put_string ("View the unsubtle hint for this topic");
- else if (type == GSC_CONF_CONTINUE_HINTS)
- g_vm->glk_put_string ("Continue with hints");
- else
- {
- g_vm->glk_put_string ("Do you really want to ");
- switch (type)
- {
- case SC_CONF_QUIT:
- g_vm->glk_put_string ("quit");
- break;
- case SC_CONF_RESTART:
- g_vm->glk_put_string ("restart");
- break;
- case SC_CONF_SAVE:
- g_vm->glk_put_string ("save");
- break;
- case SC_CONF_RESTORE:
- g_vm->glk_put_string ("restore");
- break;
- case SC_CONF_VIEW_HINTS:
- g_vm->glk_put_string ("view hints");
- break;
- default:
- g_vm->glk_put_string ("do that");
- break;
- }
- }
- g_vm->glk_put_string ("? ");
-
- /* Loop until 'yes' or 'no' returned. */
- do
- {
- event_t event;
-
- /* Wait for a standard key, ignoring Glk special keys. */
- do
- {
- g_vm->glk_request_char_event (gsc_main_window);
- gsc_event_wait (evtype_CharInput, &event);
- }
- while (event.val1 > UCHAR_MAX);
- response = g_vm->glk_char_to_upper (event.val1);
- }
- while (response != 'Y' && response != 'N');
-
- /* Echo the confirmation response, and a new line. */
- g_vm->glk_set_style (style_Input);
- g_vm->glk_put_string (response == 'Y' ? "Yes" : "No");
- g_vm->glk_set_style (style_Normal);
- g_vm->glk_put_char ('\n');
-
- /* Use a short delay on restarts, if confirmed. */
- if (type == SC_CONF_RESTART && response == 'Y')
- gsc_short_delay ();
-
- /* Return TRUE if 'Y' was entered. */
- return (response == 'Y');
+os_confirm(sc_int type) {
+ sc_char response;
+
+ /*
+ * Always allow game saves and hint display, and if we're reading from an
+ * input log, allow everything no matter what, on the assumption that the
+ * user knows what they are doing.
+ */
+ if (gsc_readlog_stream
+ || type == SC_CONF_SAVE || type == SC_CONF_VIEW_HINTS)
+ return TRUE;
+
+ /* Ensure back to normal style, and update status. */
+ gsc_reset_glk_style();
+ gsc_status_notify();
+
+ /* Prompt for the confirmation, based on the type. */
+ if (type == GSC_CONF_SUBTLE_HINT)
+ g_vm->glk_put_string("View the subtle hint for this topic");
+ else if (type == GSC_CONF_UNSUBTLE_HINT)
+ g_vm->glk_put_string("View the unsubtle hint for this topic");
+ else if (type == GSC_CONF_CONTINUE_HINTS)
+ g_vm->glk_put_string("Continue with hints");
+ else {
+ g_vm->glk_put_string("Do you really want to ");
+ switch (type) {
+ case SC_CONF_QUIT:
+ g_vm->glk_put_string("quit");
+ break;
+ case SC_CONF_RESTART:
+ g_vm->glk_put_string("restart");
+ break;
+ case SC_CONF_SAVE:
+ g_vm->glk_put_string("save");
+ break;
+ case SC_CONF_RESTORE:
+ g_vm->glk_put_string("restore");
+ break;
+ case SC_CONF_VIEW_HINTS:
+ g_vm->glk_put_string("view hints");
+ break;
+ default:
+ g_vm->glk_put_string("do that");
+ break;
+ }
+ }
+ g_vm->glk_put_string("? ");
+
+ /* Loop until 'yes' or 'no' returned. */
+ do {
+ event_t event;
+
+ /* Wait for a standard key, ignoring Glk special keys. */
+ do {
+ g_vm->glk_request_char_event(gsc_main_window);
+ gsc_event_wait(evtype_CharInput, &event);
+ } while (event.val1 > UCHAR_MAX);
+ response = g_vm->glk_char_to_upper(event.val1);
+ } while (response != 'Y' && response != 'N');
+
+ /* Echo the confirmation response, and a new line. */
+ g_vm->glk_set_style(style_Input);
+ g_vm->glk_put_string(response == 'Y' ? "Yes" : "No");
+ g_vm->glk_set_style(style_Normal);
+ g_vm->glk_put_char('\n');
+
+ /* Use a short delay on restarts, if confirmed. */
+ if (type == SC_CONF_RESTART && response == 'Y')
+ gsc_short_delay();
+
+ /* Return TRUE if 'Y' was entered. */
+ return (response == 'Y');
}
@@ -2806,23 +2626,20 @@ static const glui32 GSC_DELAY_TIMEOUTS_COUNT = 10;
* immediate, and abrupt, restart.
*/
static void
-gsc_short_delay()
-{
- /* Ignore the call if the Glk doesn't have timers. */
- if (g_vm->glk_gestalt (gestalt_Timer, 0))
- {
- glui32 timeout;
-
- /* Timeout in small chunks to minimize Glk jitter. */
- g_vm->glk_request_timer_events (GSC_DELAY_TIMEOUT);
- for (timeout = 0; timeout < GSC_DELAY_TIMEOUTS_COUNT; timeout++)
- {
- event_t event;
+gsc_short_delay() {
+ /* Ignore the call if the Glk doesn't have timers. */
+ if (g_vm->glk_gestalt(gestalt_Timer, 0)) {
+ glui32 timeout;
+
+ /* Timeout in small chunks to minimize Glk jitter. */
+ g_vm->glk_request_timer_events(GSC_DELAY_TIMEOUT);
+ for (timeout = 0; timeout < GSC_DELAY_TIMEOUTS_COUNT; timeout++) {
+ event_t event;
- gsc_event_wait (evtype_Timer, &event);
- }
- g_vm->glk_request_timer_events (0);
- }
+ gsc_event_wait(evtype_Timer, &event);
+ }
+ g_vm->glk_request_timer_events(0);
+ }
}
@@ -2834,36 +2651,31 @@ gsc_short_delay()
* Return the event of that type.
*/
static void
-gsc_event_wait_2 (glui32 wait_type_1, glui32 wait_type_2, event_t * event)
-{
- assert (event);
-
- do
- {
- g_vm->glk_select (event);
- if (g_vm->shouldQuit()) {
- g_vm->glk_cancel_line_event(gsc_main_window, event);
- return;
- }
-
- switch (event->type)
- {
- case evtype_Arrange:
- case evtype_Redraw:
- /* Refresh any sensitive windows on size events. */
- gsc_status_redraw ();
- break;
- }
- }
- while (!(event->type == (EvType)wait_type_1 || event->type == (EvType)wait_type_2));
+gsc_event_wait_2(glui32 wait_type_1, glui32 wait_type_2, event_t *event) {
+ assert(event);
+
+ do {
+ g_vm->glk_select(event);
+ if (g_vm->shouldQuit()) {
+ g_vm->glk_cancel_line_event(gsc_main_window, event);
+ return;
+ }
+
+ switch (event->type) {
+ case evtype_Arrange:
+ case evtype_Redraw:
+ /* Refresh any sensitive windows on size events. */
+ gsc_status_redraw();
+ break;
+ }
+ } while (!(event->type == (EvType)wait_type_1 || event->type == (EvType)wait_type_2));
}
static void
-gsc_event_wait (glui32 wait_type, event_t * event)
-{
- assert (event);
+gsc_event_wait(glui32 wait_type, event_t *event) {
+ assert(event);
- gsc_event_wait_2 (wait_type, evtype_None, event);
+ gsc_event_wait_2(wait_type, evtype_None, event);
}
@@ -2877,28 +2689,27 @@ gsc_event_wait (glui32 wait_type, event_t * event)
* Open a file for save or restore, and return a Glk stream for the opened
* file.
*/
-void *os_open_file (sc_bool is_save) {
- glui32 usage, fmode;
- frefid_t fileref;
- strid_t stream;
+void *os_open_file(sc_bool is_save) {
+ glui32 usage, fmode;
+ frefid_t fileref;
+ strid_t stream;
- usage = fileusage_SavedGame | fileusage_BinaryMode;
- fmode = is_save ? filemode_Write : filemode_Read;
+ usage = fileusage_SavedGame | fileusage_BinaryMode;
+ fmode = is_save ? filemode_Write : filemode_Read;
- fileref = g_vm->glk_fileref_create_by_prompt(usage, (FileMode)fmode, 0);
- if (!fileref)
- return nullptr;
+ fileref = g_vm->glk_fileref_create_by_prompt(usage, (FileMode)fmode, 0);
+ if (!fileref)
+ return nullptr;
- if (!is_save && !g_vm->glk_fileref_does_file_exist (fileref))
- {
- g_vm->glk_fileref_destroy (fileref);
- return nullptr;
- }
+ if (!is_save && !g_vm->glk_fileref_does_file_exist(fileref)) {
+ g_vm->glk_fileref_destroy(fileref);
+ return nullptr;
+ }
- stream = g_vm->glk_stream_open_file (fileref, (FileMode)fmode, 0);
- g_vm->glk_fileref_destroy (fileref);
+ stream = g_vm->glk_stream_open_file(fileref, (FileMode)fmode, 0);
+ g_vm->glk_fileref_destroy(fileref);
- return stream;
+ return stream;
}
@@ -2909,21 +2720,19 @@ void *os_open_file (sc_bool is_save) {
* Write/read the given buffered data to/from the open Glk stream.
*/
void
-os_write_file (void *opaque, const sc_byte *buffer, sc_int length)
-{
- strid_t stream = (strid_t) opaque;
- assert (opaque && buffer);
+os_write_file(void *opaque, const sc_byte *buffer, sc_int length) {
+ strid_t stream = (strid_t) opaque;
+ assert(opaque && buffer);
- g_vm->glk_put_buffer_stream (stream, (char *) buffer, length);
+ g_vm->glk_put_buffer_stream(stream, (char *) buffer, length);
}
sc_int
-os_read_file (void *opaque, sc_byte *buffer, sc_int length)
-{
- strid_t stream = (strid_t) opaque;
- assert (opaque && buffer);
+os_read_file(void *opaque, sc_byte *buffer, sc_int length) {
+ strid_t stream = (strid_t) opaque;
+ assert(opaque && buffer);
- return g_vm->glk_get_buffer_stream (stream, (char *) buffer, length);
+ return g_vm->glk_get_buffer_stream(stream, (char *) buffer, length);
}
@@ -2933,12 +2742,11 @@ os_read_file (void *opaque, sc_byte *buffer, sc_int length)
* Close the opened Glk stream.
*/
void
-os_close_file (void *opaque)
-{
- strid_t stream = (strid_t) opaque;
- assert (opaque);
+os_close_file(void *opaque) {
+ strid_t stream = (strid_t) opaque;
+ assert(opaque);
- g_vm->glk_stream_close (stream, nullptr);
+ g_vm->glk_stream_close(stream, nullptr);
}
@@ -2981,68 +2789,63 @@ static sc_int gsc_callback(void *opaque, sc_byte *buffer, sc_int length) {
* end option. Called on game completion.
*/
static enum gsc_end_option
-gsc_get_ending_option()
-{
- sc_char response;
-
- /* Ensure back to normal style, and update status. */
- gsc_reset_glk_style ();
- gsc_status_notify ();
-
- /* Prompt for restart, undo, or quit. */
- g_vm->glk_put_string ("\nWould you like to RESTART, UNDO a turn, or QUIT? ");
-
- /* Loop until 'restart', 'undo' or 'quit'. */
- do
- {
- event_t event;
-
- do
- {
- g_vm->glk_request_char_event (gsc_main_window);
- gsc_event_wait (evtype_CharInput, &event);
- }
- while (event.val1 > UCHAR_MAX);
- response = g_vm->glk_char_to_upper (event.val1);
- }
- while (response != 'R' && response != 'U' && response != 'Q');
-
- /* Echo the confirmation response, and a new line. */
- g_vm->glk_set_style (style_Input);
- switch (response)
- {
- case 'R':
- g_vm->glk_put_string ("Restart");
- break;
- case 'U':
- g_vm->glk_put_string ("Undo");
- break;
- case 'Q':
- g_vm->glk_put_string ("Quit");
- break;
- default:
- gsc_fatal ("GLK: Invalid response encountered");
- g_vm->glk_exit ();
- }
- g_vm->glk_set_style (style_Normal);
- g_vm->glk_put_char ('\n');
-
- /* Return the appropriate value for response. */
- switch (response)
- {
- case 'R':
- return GAME_RESTART;
- case 'U':
- return GAME_UNDO;
- case 'Q':
- return GAME_QUIT;
- default:
- gsc_fatal ("GLK: Invalid response encountered");
- g_vm->glk_exit ();
- }
-
- /* Unreachable; supplied to suppress compiler warning. */
- return GAME_QUIT;
+gsc_get_ending_option() {
+ sc_char response;
+
+ /* Ensure back to normal style, and update status. */
+ gsc_reset_glk_style();
+ gsc_status_notify();
+
+ /* Prompt for restart, undo, or quit. */
+ g_vm->glk_put_string("\nWould you like to RESTART, UNDO a turn, or QUIT? ");
+
+ /* Loop until 'restart', 'undo' or 'quit'. */
+ do
+ {
+ event_t event;
+
+ do
+ {
+ g_vm->glk_request_char_event(gsc_main_window);
+ gsc_event_wait(evtype_CharInput, &event);
+ } while (event.val1 > UCHAR_MAX);
+ response = g_vm->glk_char_to_upper(event.val1);
+ } while (response != 'R' && response != 'U' && response != 'Q');
+
+ /* Echo the confirmation response, and a new line. */
+ g_vm->glk_set_style(style_Input);
+ switch (response) {
+ case 'R':
+ g_vm->glk_put_string("Restart");
+ break;
+ case 'U':
+ g_vm->glk_put_string("Undo");
+ break;
+ case 'Q':
+ g_vm->glk_put_string("Quit");
+ break;
+ default:
+ gsc_fatal("GLK: Invalid response encountered");
+ g_vm->glk_exit();
+ }
+ g_vm->glk_set_style(style_Normal);
+ g_vm->glk_put_char('\n');
+
+ /* Return the appropriate value for response. */
+ switch (response) {
+ case 'R':
+ return GAME_RESTART;
+ case 'U':
+ return GAME_UNDO;
+ case 'Q':
+ return GAME_QUIT;
+ default:
+ gsc_fatal("GLK: Invalid response encountered");
+ g_vm->glk_exit();
+ }
+
+ /* Unreachable; supplied to suppress compiler warning. */
+ return GAME_QUIT;
}
@@ -3057,16 +2860,14 @@ gsc_get_ending_option()
*/
static int
gsc_startup_code(Common::SeekableReadStream *game_stream, strid_t restore_stream,
- sc_uint trace_flags, sc_bool enable_debugger,
- sc_bool stable_random, const sc_char *locale)
-{
+ sc_uint trace_flags, sc_bool enable_debugger,
+ sc_bool stable_random, const sc_char *locale) {
winid_t window;
assert(game_stream);
/* Open a temporary Glk main window. */
window = g_vm->glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
- if (window)
- {
+ if (window) {
/* Clear and initialize the temporary window. */
g_vm->glk_window_clear(window);
g_vm->glk_set_window(window);
@@ -3113,42 +2914,35 @@ gsc_startup_code(Common::SeekableReadStream *game_stream, strid_t restore_stream
*/
sc_set_trace_flags(trace_flags);
gsc_game = sc_game_from_callback(gsc_callback, game_stream);
- if (!gsc_game)
- {
+ if (!gsc_game) {
gsc_game = nullptr;
gsc_game_message = "Unable to load an Adrift game from the requested file.";
- }
- else
+ } else
gsc_game_message = nullptr;
/*
* If the game was created successfully and there is a restore stream, try
* to immediately restore the game from that stream.
*/
- if (gsc_game && restore_stream)
- {
- if (!sc_load_game_from_callback(gsc_game, gsc_callback, restore_stream))
- {
+ if (gsc_game && restore_stream) {
+ if (!sc_load_game_from_callback(gsc_game, gsc_callback, restore_stream)) {
sc_free_game(gsc_game);
gsc_game = nullptr;
gsc_game_message = "Unable to restore this Adrift game from the requested file.";
- }
- else
+ } else
gsc_game_message = nullptr;
}
if (restore_stream)
g_vm->glk_stream_close(restore_stream, nullptr);
/* If successful, set game debugging and synchronize to the core's locale. */
- if (gsc_game)
- {
+ if (gsc_game) {
sc_set_game_debugger_enabled(gsc_game, enable_debugger);
gsc_set_locale(sc_get_locale());
}
/* Set portable and predictable random number generation if requested. */
- if (stable_random)
- {
+ if (stable_random) {
sc_set_portable_random(TRUE);
sc_reseed_random_sequence(1);
}
@@ -3167,126 +2961,112 @@ gsc_startup_code(Common::SeekableReadStream *game_stream, strid_t restore_stream
}
static void
-gsc_main()
-{
- sc_bool is_running;
-
- /* Ensure SCARE internal types have the right sizes. */
- if (!(sizeof (sc_byte) == 1 && sizeof (sc_char) == 1
- && sizeof (sc_uint) >= 4 && sizeof (sc_int) >= 4
- && sizeof (sc_uint) <= 8 && sizeof (sc_int) <= 8))
- {
- gsc_fatal ("GLK: Types sized incorrectly, recompilation is needed");
- g_vm->glk_exit ();
- }
-
- /* Create the Glk window, and set its stream as the current one. */
- gsc_main_window = g_vm->glk_window_open (0, 0, 0, wintype_TextBuffer, 0);
- if (!gsc_main_window)
- {
- gsc_fatal ("GLK: Can't open main window");
- g_vm->glk_exit ();
- }
- g_vm->glk_window_clear (gsc_main_window);
- g_vm->glk_set_window (gsc_main_window);
- g_vm->glk_set_style (style_Normal);
-
- /* If there's a problem with the game file, complain now. */
- if (!gsc_game)
- {
- assert (gsc_game_message);
- gsc_header_string ("Glk SCARE Error\n\n");
- gsc_normal_string (gsc_game_message);
- gsc_normal_char ('\n');
- g_vm->glk_exit ();
- }
-
- /* Try to create a one-line status window. We can live without it. */
- g_vm->glk_stylehint_set (wintype_TextGrid, style_User1, stylehint_ReverseColor, 1);
- gsc_status_window = g_vm->glk_window_open (gsc_main_window,
- winmethod_Above | winmethod_Fixed,
- 1, wintype_TextGrid, 0);
-
- /* Repeat the game until no more restarts requested. */
- is_running = TRUE;
- while (is_running)
- {
- /* Run the game until it ends, or the user quits. */
- gsc_status_notify ();
- sc_interpret_game (gsc_game);
-
- /*
- * If the game did not complete, the user quit explicitly, so leave the
- * game repeat loop.
- */
- if (!sc_has_game_completed (gsc_game))
- {
- is_running = FALSE;
- break;
- }
-
- /*
- * If reading from an input log, close it now. We need to request a
- * user selection, probably modal, and after that we probably don't
- * want the follow-on readlog data being used as game input.
- */
- if (gsc_readlog_stream)
- {
- g_vm->glk_stream_close (gsc_readlog_stream, nullptr);
- gsc_readlog_stream = nullptr;
- }
-
- /*
- * Get user selection of restart, undo a turn, or quit completed game.
- * If undo is unavailable (this should not be possible), degrade to
- * restart.
- */
- switch (gsc_get_ending_option ())
- {
- case GAME_RESTART:
- gsc_short_delay ();
- sc_restart_game (gsc_game);
- break;
-
- case GAME_UNDO:
- if (sc_is_game_undo_available (gsc_game))
- {
- sc_undo_game_turn (gsc_game);
- gsc_normal_string ("The previous turn has been undone.\n");
- }
- else
- {
- gsc_normal_string ("Sorry, no undo is available.\n");
- gsc_short_delay ();
- sc_restart_game (gsc_game);
- }
- break;
-
- case GAME_QUIT:
- is_running = FALSE;
- break;
- }
- }
-
- /* All done -- release game resources. */
- sc_free_game (gsc_game);
-
- /* Close any open transcript, input log, and/or read log. */
- if (gsc_transcript_stream)
- {
- g_vm->glk_stream_close (gsc_transcript_stream, nullptr);
- gsc_transcript_stream = nullptr;
- }
- if (gsc_inputlog_stream)
- {
- g_vm->glk_stream_close (gsc_inputlog_stream, nullptr);
- gsc_inputlog_stream = nullptr;
- }
- if (gsc_readlog_stream)
- {
- g_vm->glk_stream_close (gsc_readlog_stream, nullptr);
- gsc_readlog_stream = nullptr;
- }
+gsc_main() {
+ sc_bool is_running;
+
+ /* Ensure SCARE internal types have the right sizes. */
+ if (!(sizeof(sc_byte) == 1 && sizeof(sc_char) == 1
+ && sizeof(sc_uint) >= 4 && sizeof(sc_int) >= 4
+ && sizeof(sc_uint) <= 8 && sizeof(sc_int) <= 8)) {
+ gsc_fatal("GLK: Types sized incorrectly, recompilation is needed");
+ g_vm->glk_exit();
+ }
+
+ /* Create the Glk window, and set its stream as the current one. */
+ gsc_main_window = g_vm->glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
+ if (!gsc_main_window) {
+ gsc_fatal("GLK: Can't open main window");
+ g_vm->glk_exit();
+ }
+ g_vm->glk_window_clear(gsc_main_window);
+ g_vm->glk_set_window(gsc_main_window);
+ g_vm->glk_set_style(style_Normal);
+
+ /* If there's a problem with the game file, complain now. */
+ if (!gsc_game) {
+ assert(gsc_game_message);
+ gsc_header_string("Glk SCARE Error\n\n");
+ gsc_normal_string(gsc_game_message);
+ gsc_normal_char('\n');
+ g_vm->glk_exit();
+ }
+
+ /* Try to create a one-line status window. We can live without it. */
+ g_vm->glk_stylehint_set(wintype_TextGrid, style_User1, stylehint_ReverseColor, 1);
+ gsc_status_window = g_vm->glk_window_open(gsc_main_window,
+ winmethod_Above | winmethod_Fixed,
+ 1, wintype_TextGrid, 0);
+
+ /* Repeat the game until no more restarts requested. */
+ is_running = TRUE;
+ while (is_running) {
+ /* Run the game until it ends, or the user quits. */
+ gsc_status_notify();
+ sc_interpret_game(gsc_game);
+
+ /*
+ * If the game did not complete, the user quit explicitly, so leave the
+ * game repeat loop.
+ */
+ if (!sc_has_game_completed(gsc_game)) {
+ is_running = FALSE;
+ break;
+ }
+
+ /*
+ * If reading from an input log, close it now. We need to request a
+ * user selection, probably modal, and after that we probably don't
+ * want the follow-on readlog data being used as game input.
+ */
+ if (gsc_readlog_stream) {
+ g_vm->glk_stream_close(gsc_readlog_stream, nullptr);
+ gsc_readlog_stream = nullptr;
+ }
+
+ /*
+ * Get user selection of restart, undo a turn, or quit completed game.
+ * If undo is unavailable (this should not be possible), degrade to
+ * restart.
+ */
+ switch (gsc_get_ending_option()) {
+ case GAME_RESTART:
+ gsc_short_delay();
+ sc_restart_game(gsc_game);
+ break;
+
+ case GAME_UNDO:
+ if (sc_is_game_undo_available(gsc_game)) {
+ sc_undo_game_turn(gsc_game);
+ gsc_normal_string("The previous turn has been undone.\n");
+ } else {
+ gsc_normal_string("Sorry, no undo is available.\n");
+ gsc_short_delay();
+ sc_restart_game(gsc_game);
+ }
+ break;
+
+ case GAME_QUIT:
+ is_running = FALSE;
+ break;
+ }
+ }
+
+ /* All done -- release game resources. */
+ sc_free_game(gsc_game);
+
+ /* Close any open transcript, input log, and/or read log. */
+ if (gsc_transcript_stream) {
+ g_vm->glk_stream_close(gsc_transcript_stream, nullptr);
+ gsc_transcript_stream = nullptr;
+ }
+ if (gsc_inputlog_stream) {
+ g_vm->glk_stream_close(gsc_inputlog_stream, nullptr);
+ gsc_inputlog_stream = nullptr;
+ }
+ if (gsc_readlog_stream) {
+ g_vm->glk_stream_close(gsc_readlog_stream, nullptr);
+ gsc_readlog_stream = nullptr;
+ }
}
@@ -3325,21 +3105,33 @@ void adrift_main() {
* Glk arguments for UNIX versions of the Glk interpreter.
*/
glkunix_argumentlist_t glkunix_arguments[] = {
- {(char *) "-nc", glkunix_arg_NoValue,
- (char *) "-nc No local handling for Glk special commands"},
- {(char *) "-na", glkunix_arg_NoValue,
- (char *) "-na Turn off abbreviation expansions"},
- {(char *) "-nu", glkunix_arg_NoValue,
- (char *) "-nu Turn off any use of Unicode output"},
+ {
+ (char *) "-nc", glkunix_arg_NoValue,
+ (char *) "-nc No local handling for Glk special commands"
+ },
+ {
+ (char *) "-na", glkunix_arg_NoValue,
+ (char *) "-na Turn off abbreviation expansions"
+ },
+ {
+ (char *) "-nu", glkunix_arg_NoValue,
+ (char *) "-nu Turn off any use of Unicode output"
+ },
#ifdef LINUX_GRAPHICS
- {(char *) "-ng", glkunix_arg_NoValue,
- (char *) "-ng Turn off attempts at game graphics"},
+ {
+ (char *) "-ng", glkunix_arg_NoValue,
+ (char *) "-ng Turn off attempts at game graphics"
+ },
#endif
- {(char *) "-r", glkunix_arg_ValueFollows,
- (char *) "-r FILE Restore from FILE on starting the game"},
- {(char *) "", glkunix_arg_ValueCanFollow,
- (char *) "filename game to run"},
- {nullptr, glkunix_arg_End, nullptr}
+ {
+ (char *) "-r", glkunix_arg_ValueFollows,
+ (char *) "-r FILE Restore from FILE on starting the game"
+ },
+ {
+ (char *) "", glkunix_arg_ValueCanFollow,
+ (char *) "filename game to run"
+ },
+ {nullptr, glkunix_arg_End, nullptr}
};
#endif
diff --git a/engines/glk/adrift/scare.h b/engines/glk/adrift/scare.h
index 43ce75af1d..d4e02314e6 100644
--- a/engines/glk/adrift/scare.h
+++ b/engines/glk/adrift/scare.h
@@ -50,67 +50,67 @@ typedef unsigned long sc_uint;
typedef int sc_bool;
/* Enumerated confirmation types, passed to os_confirm(). */
-enum
-{ SC_CONF_QUIT = 0,
- SC_CONF_RESTART, SC_CONF_SAVE, SC_CONF_RESTORE, SC_CONF_VIEW_HINTS
+enum {
+ SC_CONF_QUIT = 0,
+ SC_CONF_RESTART, SC_CONF_SAVE, SC_CONF_RESTORE, SC_CONF_VIEW_HINTS
};
/* HTML-like tag enumerated values, passed to os_print_tag(). */
-enum
-{ SC_TAG_UNKNOWN = 0, SC_TAG_ITALICS, SC_TAG_ENDITALICS, SC_TAG_BOLD,
- SC_TAG_ENDBOLD, SC_TAG_UNDERLINE, SC_TAG_ENDUNDERLINE, SC_TAG_COLOR,
- SC_TAG_ENDCOLOR, SC_TAG_FONT, SC_TAG_ENDFONT, SC_TAG_BGCOLOR, SC_TAG_CENTER,
- SC_TAG_ENDCENTER, SC_TAG_RIGHT, SC_TAG_ENDRIGHT, SC_TAG_WAIT, SC_TAG_WAITKEY,
- SC_TAG_CLS,
-
- /* British spelling equivalents. */
- SC_TAG_COLOUR = SC_TAG_COLOR,
- SC_TAG_ENDCOLOUR = SC_TAG_ENDCOLOR,
- SC_TAG_BGCOLOUR = SC_TAG_BGCOLOR,
- SC_TAG_CENTRE = SC_TAG_CENTER,
- SC_TAG_ENDCENTRE = SC_TAG_ENDCENTER
+enum {
+ SC_TAG_UNKNOWN = 0, SC_TAG_ITALICS, SC_TAG_ENDITALICS, SC_TAG_BOLD,
+ SC_TAG_ENDBOLD, SC_TAG_UNDERLINE, SC_TAG_ENDUNDERLINE, SC_TAG_COLOR,
+ SC_TAG_ENDCOLOR, SC_TAG_FONT, SC_TAG_ENDFONT, SC_TAG_BGCOLOR, SC_TAG_CENTER,
+ SC_TAG_ENDCENTER, SC_TAG_RIGHT, SC_TAG_ENDRIGHT, SC_TAG_WAIT, SC_TAG_WAITKEY,
+ SC_TAG_CLS,
+
+ /* British spelling equivalents. */
+ SC_TAG_COLOUR = SC_TAG_COLOR,
+ SC_TAG_ENDCOLOUR = SC_TAG_ENDCOLOR,
+ SC_TAG_BGCOLOUR = SC_TAG_BGCOLOR,
+ SC_TAG_CENTRE = SC_TAG_CENTER,
+ SC_TAG_ENDCENTRE = SC_TAG_ENDCENTER
};
/* OS interface function prototypes; interpreters must define these. */
typedef void *sc_game;
-extern void os_print_string (const sc_char *string);
+extern void os_print_string(const sc_char *string);
extern void os_print_tag(sc_int tag, const sc_char *argument);
-extern void os_play_sound (const sc_char *filepath,
- sc_int offset, sc_int length, sc_bool is_looping);
+extern void os_play_sound(const sc_char *filepath,
+ sc_int offset, sc_int length, sc_bool is_looping);
extern void os_stop_sound();
-extern void os_show_graphic (const sc_char *filepath,
- sc_int offset, sc_int length);
+extern void os_show_graphic(const sc_char *filepath,
+ sc_int offset, sc_int length);
extern sc_bool os_read_line(sc_char *buffer, sc_int length);
extern sc_bool os_confirm(sc_int type);
extern void *os_open_file(sc_bool is_save);
-extern void os_write_file (void *opaque, const sc_byte *buffer, sc_int length);
-extern sc_int os_read_file (void *opaque, sc_byte *buffer, sc_int length);
-extern void os_close_file (void *opaque);
+extern void os_write_file(void *opaque, const sc_byte *buffer, sc_int length);
+extern sc_int os_read_file(void *opaque, sc_byte *buffer, sc_int length);
+extern void os_close_file(void *opaque);
extern void os_display_hints(sc_game game);
-extern void os_print_string_debug (const sc_char *string);
+extern void os_print_string_debug(const sc_char *string);
extern sc_bool os_read_line_debug(sc_char *buffer, sc_int length);
/* Interpreter trace flag bits, passed to sc_set_trace_flags(). */
-enum
-{ SC_TRACE_PARSE = 1, SC_TRACE_PROPERTIES = 2, SC_TRACE_VARIABLES = 4,
- SC_TRACE_PARSER = 8, SC_TRACE_LIBRARY = 16, SC_TRACE_EVENTS = 32,
- SC_TRACE_NPCS = 64, SC_TRACE_OBJECTS = 128, SC_TRACE_TASKS = 256,
- SC_TRACE_PRINTFILTER = 512,
-
- SC_DUMP_TAF = 1024, SC_DUMP_PROPERTIES = 2048, SC_DUMP_VARIABLES = 4096,
- SC_DUMP_PARSER_TREES = 8192, SC_DUMP_LOCALE_TABLES = 16384
+enum {
+ SC_TRACE_PARSE = 1, SC_TRACE_PROPERTIES = 2, SC_TRACE_VARIABLES = 4,
+ SC_TRACE_PARSER = 8, SC_TRACE_LIBRARY = 16, SC_TRACE_EVENTS = 32,
+ SC_TRACE_NPCS = 64, SC_TRACE_OBJECTS = 128, SC_TRACE_TASKS = 256,
+ SC_TRACE_PRINTFILTER = 512,
+
+ SC_DUMP_TAF = 1024, SC_DUMP_PROPERTIES = 2048, SC_DUMP_VARIABLES = 4096,
+ SC_DUMP_PARSER_TREES = 8192, SC_DUMP_LOCALE_TABLES = 16384
};
/* Module-wide trace control function prototype. */
extern void sc_set_trace_flags(sc_uint trace_flags);
/* Interpreter interface function prototypes. */
-extern sc_game sc_game_from_filename (const sc_char *filename);
-extern sc_game sc_game_from_stream (Common::SeekableReadStream *stream);
-extern sc_game sc_game_from_callback(sc_int (*callback)
- (void *, sc_byte *, sc_int),
- void *opaque);
+extern sc_game sc_game_from_filename(const sc_char *filename);
+extern sc_game sc_game_from_stream(Common::SeekableReadStream *stream);
+extern sc_game sc_game_from_callback(sc_int(*callback)
+ (void *, sc_byte *, sc_int),
+ void *opaque);
extern void sc_interpret_game(sc_game game);
extern void sc_restart_game(sc_game game);
extern sc_bool sc_save_game(sc_game game);
@@ -120,16 +120,16 @@ extern void sc_quit_game(sc_game game);
extern sc_bool sc_save_game_to_filename(sc_game game, const sc_char *filename);
extern void sc_save_game_to_stream(sc_game game, Common::SeekableReadStream *stream);
extern void sc_save_game_to_callback(sc_game game,
- void (*callback)
- (void *, const sc_byte *, sc_int),
- void *opaque);
+ void (*callback)
+ (void *, const sc_byte *, sc_int),
+ void *opaque);
extern sc_bool sc_load_game_from_filename(sc_game game,
- const sc_char *filename);
+ const sc_char *filename);
extern sc_bool sc_load_game_from_stream(sc_game game, Common::SeekableReadStream *stream);
extern sc_bool sc_load_game_from_callback(sc_game game,
- sc_int (*callback)
- (void *, sc_byte *, sc_int),
- void *opaque);
+ sc_int(*callback)
+ (void *, sc_byte *, sc_int),
+ void *opaque);
extern void sc_free_game(sc_game game);
extern sc_bool sc_is_game_running(sc_game game);
extern const sc_char *sc_get_game_name(sc_game game);
@@ -157,26 +157,26 @@ typedef void *sc_game_hint;
extern sc_game_hint sc_get_first_game_hint(sc_game game);
extern sc_game_hint sc_get_next_game_hint(sc_game game, sc_game_hint hint);
extern const sc_char *sc_get_game_hint_question(sc_game game,
- sc_game_hint hint);
+ sc_game_hint hint);
extern const sc_char *sc_get_game_subtle_hint(sc_game game,
- sc_game_hint hint);
+ sc_game_hint hint);
extern const sc_char *sc_get_game_unsubtle_hint(sc_game game,
- sc_game_hint hint);
+ sc_game_hint hint);
extern void sc_set_game_debugger_enabled(sc_game game, sc_bool flag);
extern sc_bool sc_get_game_debugger_enabled(sc_game game);
extern sc_bool sc_run_game_debugger_command(sc_game game,
- const sc_char *debug_command);
+ const sc_char *debug_command);
extern void sc_set_portable_random(sc_bool flag);
extern void sc_reseed_random_sequence(sc_uint new_seed);
/* Locale control and query functions. */
-extern sc_bool sc_set_locale (const sc_char *name);
+extern sc_bool sc_set_locale(const sc_char *name);
extern const sc_char *sc_get_locale();
/* A few possibly useful utilities. */
-extern sc_int sc_strncasecmp (const sc_char *s1, const sc_char *s2, sc_int n);
-extern sc_int sc_strcasecmp (const sc_char *s1, const sc_char *s2);
+extern sc_int sc_strncasecmp(const sc_char *s1, const sc_char *s2, sc_int n);
+extern sc_int sc_strcasecmp(const sc_char *s1, const sc_char *s2);
extern const sc_char *sc_scare_version();
extern sc_int sc_scare_emulation();
diff --git a/engines/glk/adrift/scdebug.cpp b/engines/glk/adrift/scdebug.cpp
index 3852d164e1..35900c37f4 100644
--- a/engines/glk/adrift/scdebug.cpp
+++ b/engines/glk/adrift/scdebug.cpp
@@ -32,19 +32,19 @@ static const sc_uint DEBUG_MAGIC = 0xc4584d2e;
enum { DEBUG_BUFFER_SIZE = 256 };
/* Debugging command and command argument type. */
-typedef enum
-{ DEBUG_NONE = 0, DEBUG_CONTINUE, DEBUG_STEP, DEBUG_BUFFER, DEBUG_RESOURCES,
- DEBUG_HELP, DEBUG_GAME,
- DEBUG_PLAYER, DEBUG_ROOMS, DEBUG_OBJECTS, DEBUG_NPCS, DEBUG_EVENTS,
- DEBUG_TASKS, DEBUG_VARIABLES,
- DEBUG_OLDPLAYER, DEBUG_OLDROOMS, DEBUG_OLDOBJECTS, DEBUG_OLDNPCS,
- DEBUG_OLDEVENTS, DEBUG_OLDTASKS, DEBUG_OLDVARIABLES,
- DEBUG_WATCHPLAYER, DEBUG_WATCHOBJECTS, DEBUG_WATCHNPCS, DEBUG_WATCHEVENTS,
- DEBUG_WATCHTASKS, DEBUG_WATCHVARIABLES,
- DEBUG_CLEARPLAYER, DEBUG_CLEAROBJECTS, DEBUG_CLEARNPCS, DEBUG_CLEAREVENTS,
- DEBUG_CLEARTASKS, DEBUG_CLEARVARIABLES,
- DEBUG_WATCHALL, DEBUG_CLEARALL, DEBUG_RANDOM,
- DEBUG_QUIT
+typedef enum {
+ DEBUG_NONE = 0, DEBUG_CONTINUE, DEBUG_STEP, DEBUG_BUFFER, DEBUG_RESOURCES,
+ DEBUG_HELP, DEBUG_GAME,
+ DEBUG_PLAYER, DEBUG_ROOMS, DEBUG_OBJECTS, DEBUG_NPCS, DEBUG_EVENTS,
+ DEBUG_TASKS, DEBUG_VARIABLES,
+ DEBUG_OLDPLAYER, DEBUG_OLDROOMS, DEBUG_OLDOBJECTS, DEBUG_OLDNPCS,
+ DEBUG_OLDEVENTS, DEBUG_OLDTASKS, DEBUG_OLDVARIABLES,
+ DEBUG_WATCHPLAYER, DEBUG_WATCHOBJECTS, DEBUG_WATCHNPCS, DEBUG_WATCHEVENTS,
+ DEBUG_WATCHTASKS, DEBUG_WATCHVARIABLES,
+ DEBUG_CLEARPLAYER, DEBUG_CLEAROBJECTS, DEBUG_CLEARNPCS, DEBUG_CLEAREVENTS,
+ DEBUG_CLEARTASKS, DEBUG_CLEARVARIABLES,
+ DEBUG_WATCHALL, DEBUG_CLEARALL, DEBUG_RANDOM,
+ DEBUG_QUIT
}
sc_command_t;
@@ -53,30 +53,29 @@ typedef enum
sc_command_type_t;
/* Table connecting debugging command strings to commands. */
-typedef struct
-{
- const sc_char *const command_string;
- const sc_command_t command;
+typedef struct {
+ const sc_char *const command_string;
+ const sc_command_t command;
} sc_strings_t;
static const sc_strings_t DEBUG_COMMANDS[] = {
- {"continue", DEBUG_CONTINUE}, {"step", DEBUG_STEP}, {"buffer", DEBUG_BUFFER},
- {"resources", DEBUG_RESOURCES}, {"help", DEBUG_HELP}, {"game", DEBUG_GAME},
- {"player", DEBUG_PLAYER}, {"rooms", DEBUG_ROOMS}, {"objects", DEBUG_OBJECTS},
- {"npcs", DEBUG_NPCS}, {"events", DEBUG_EVENTS}, {"tasks", DEBUG_TASKS},
- {"variables", DEBUG_VARIABLES},
- {"oldplayer", DEBUG_OLDPLAYER}, {"oldrooms", DEBUG_OLDROOMS},
- {"oldobjects", DEBUG_OLDOBJECTS}, {"oldnpcs", DEBUG_OLDNPCS},
- {"oldevents", DEBUG_OLDEVENTS}, {"oldtasks", DEBUG_OLDTASKS},
- {"oldvariables", DEBUG_OLDVARIABLES},
- {"watchplayer", DEBUG_WATCHPLAYER}, {"clearplayer", DEBUG_CLEARPLAYER},
- {"watchobjects", DEBUG_WATCHOBJECTS}, {"watchnpcs", DEBUG_WATCHNPCS},
- {"watchevents", DEBUG_WATCHEVENTS}, {"watchtasks", DEBUG_WATCHTASKS},
- {"watchvariables", DEBUG_WATCHVARIABLES},
- {"clearobjects", DEBUG_CLEAROBJECTS}, {"clearnpcs", DEBUG_CLEARNPCS},
- {"clearevents", DEBUG_CLEAREVENTS}, {"cleartasks", DEBUG_CLEARTASKS},
- {"clearvariables", DEBUG_CLEARVARIABLES}, {"watchall", DEBUG_WATCHALL},
- {"clearall", DEBUG_CLEARALL}, {"random", DEBUG_RANDOM}, {"quit", DEBUG_QUIT},
- {NULL, DEBUG_NONE}
+ {"continue", DEBUG_CONTINUE}, {"step", DEBUG_STEP}, {"buffer", DEBUG_BUFFER},
+ {"resources", DEBUG_RESOURCES}, {"help", DEBUG_HELP}, {"game", DEBUG_GAME},
+ {"player", DEBUG_PLAYER}, {"rooms", DEBUG_ROOMS}, {"objects", DEBUG_OBJECTS},
+ {"npcs", DEBUG_NPCS}, {"events", DEBUG_EVENTS}, {"tasks", DEBUG_TASKS},
+ {"variables", DEBUG_VARIABLES},
+ {"oldplayer", DEBUG_OLDPLAYER}, {"oldrooms", DEBUG_OLDROOMS},
+ {"oldobjects", DEBUG_OLDOBJECTS}, {"oldnpcs", DEBUG_OLDNPCS},
+ {"oldevents", DEBUG_OLDEVENTS}, {"oldtasks", DEBUG_OLDTASKS},
+ {"oldvariables", DEBUG_OLDVARIABLES},
+ {"watchplayer", DEBUG_WATCHPLAYER}, {"clearplayer", DEBUG_CLEARPLAYER},
+ {"watchobjects", DEBUG_WATCHOBJECTS}, {"watchnpcs", DEBUG_WATCHNPCS},
+ {"watchevents", DEBUG_WATCHEVENTS}, {"watchtasks", DEBUG_WATCHTASKS},
+ {"watchvariables", DEBUG_WATCHVARIABLES},
+ {"clearobjects", DEBUG_CLEAROBJECTS}, {"clearnpcs", DEBUG_CLEARNPCS},
+ {"clearevents", DEBUG_CLEAREVENTS}, {"cleartasks", DEBUG_CLEARTASKS},
+ {"clearvariables", DEBUG_CLEARVARIABLES}, {"watchall", DEBUG_WATCHALL},
+ {"clearall", DEBUG_CLEARALL}, {"random", DEBUG_RANDOM}, {"quit", DEBUG_QUIT},
+ {NULL, DEBUG_NONE}
};
/*
@@ -84,18 +83,17 @@ static const sc_strings_t DEBUG_COMMANDS[] = {
* added to the game on enabling debug, and removed and destroyed on
* disabling debugging.
*/
-typedef struct sc_debugger_s
-{
- sc_uint magic;
- sc_bool *watch_objects;
- sc_bool *watch_npcs;
- sc_bool *watch_events;
- sc_bool *watch_tasks;
- sc_bool *watch_variables;
- sc_bool watch_player;
- sc_bool single_step;
- sc_bool quit_pending;
- sc_uint elapsed_seconds;
+typedef struct sc_debugger_s {
+ sc_uint magic;
+ sc_bool *watch_objects;
+ sc_bool *watch_npcs;
+ sc_bool *watch_events;
+ sc_bool *watch_tasks;
+ sc_bool *watch_variables;
+ sc_bool watch_player;
+ sc_bool single_step;
+ sc_bool quit_pending;
+ sc_uint elapsed_seconds;
} sc_debugger_t;
@@ -105,9 +103,8 @@ typedef struct sc_debugger_s
* Return TRUE if pointer is a valid debugger, FALSE otherwise.
*/
static sc_bool
-debug_is_valid (sc_debuggerref_t debug)
-{
- return debug && debug->magic == DEBUG_MAGIC;
+debug_is_valid(sc_debuggerref_t debug) {
+ return debug && debug->magic == DEBUG_MAGIC;
}
@@ -117,11 +114,10 @@ debug_is_valid (sc_debuggerref_t debug)
* Return the debugger reference from a game, or NULL if none.
*/
static sc_debuggerref_t
-debug_get_debugger (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
+debug_get_debugger(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
- return game->debugger;
+ return game->debugger;
}
@@ -131,17 +127,16 @@ debug_get_debugger (sc_gameref_t game)
* Common helper to return the count of variables defined in a game.
*/
static sc_int
-debug_variable_count (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key;
- sc_int variable_count;
+debug_variable_count(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key;
+ sc_int variable_count;
- /* Find and return the variables count. */
- vt_key.string = "Variables";
- variable_count = prop_get_child_count (bundle, "I<-s", &vt_key);
+ /* Find and return the variables count. */
+ vt_key.string = "Variables";
+ variable_count = prop_get_child_count(bundle, "I<-s", &vt_key);
- return variable_count;
+ return variable_count;
}
@@ -152,45 +147,44 @@ debug_variable_count (sc_gameref_t game)
* game passed in.
*/
static void
-debug_initialize (sc_gameref_t game)
-{
- sc_debuggerref_t debug;
-
- /* Create the easy bits of the new debugging set. */
- debug = (sc_debuggerref_t)sc_malloc (sizeof (*debug));
- debug->magic = DEBUG_MAGIC;
- debug->watch_player = FALSE;
- debug->single_step = FALSE;
- debug->quit_pending = FALSE;
- debug->elapsed_seconds = 0;
-
- /* Allocate watchpoints for everything we can watch. */
- debug->watch_objects = (sc_bool *)sc_malloc (gs_object_count (game)
- * sizeof (*debug->watch_objects));
- debug->watch_npcs = (sc_bool *)sc_malloc (gs_npc_count (game)
- * sizeof (*debug->watch_npcs));
- debug->watch_events = (sc_bool *)sc_malloc (gs_event_count (game)
- * sizeof (*debug->watch_events));
- debug->watch_tasks = (sc_bool *)sc_malloc (gs_task_count (game)
- * sizeof (*debug->watch_tasks));
- debug->watch_variables = (sc_bool *)sc_malloc (debug_variable_count (game)
- * sizeof (*debug->watch_variables));
-
- /* Clear all watchpoint arrays. */
- memset (debug->watch_objects, FALSE,
- gs_object_count (game) * sizeof (*debug->watch_objects));
- memset (debug->watch_npcs, FALSE,
- gs_npc_count (game) * sizeof (*debug->watch_npcs));
- memset (debug->watch_events, FALSE,
- gs_event_count (game) * sizeof (*debug->watch_events));
- memset (debug->watch_tasks, FALSE,
- gs_task_count (game) * sizeof (*debug->watch_tasks));
- memset (debug->watch_variables, FALSE,
- debug_variable_count (game) * sizeof (*debug->watch_variables));
-
- /* Append the new debugger set to the game. */
- assert (!game->debugger);
- game->debugger = debug;
+debug_initialize(sc_gameref_t game) {
+ sc_debuggerref_t debug;
+
+ /* Create the easy bits of the new debugging set. */
+ debug = (sc_debuggerref_t)sc_malloc(sizeof(*debug));
+ debug->magic = DEBUG_MAGIC;
+ debug->watch_player = FALSE;
+ debug->single_step = FALSE;
+ debug->quit_pending = FALSE;
+ debug->elapsed_seconds = 0;
+
+ /* Allocate watchpoints for everything we can watch. */
+ debug->watch_objects = (sc_bool *)sc_malloc(gs_object_count(game)
+ * sizeof(*debug->watch_objects));
+ debug->watch_npcs = (sc_bool *)sc_malloc(gs_npc_count(game)
+ * sizeof(*debug->watch_npcs));
+ debug->watch_events = (sc_bool *)sc_malloc(gs_event_count(game)
+ * sizeof(*debug->watch_events));
+ debug->watch_tasks = (sc_bool *)sc_malloc(gs_task_count(game)
+ * sizeof(*debug->watch_tasks));
+ debug->watch_variables = (sc_bool *)sc_malloc(debug_variable_count(game)
+ * sizeof(*debug->watch_variables));
+
+ /* Clear all watchpoint arrays. */
+ memset(debug->watch_objects, FALSE,
+ gs_object_count(game) * sizeof(*debug->watch_objects));
+ memset(debug->watch_npcs, FALSE,
+ gs_npc_count(game) * sizeof(*debug->watch_npcs));
+ memset(debug->watch_events, FALSE,
+ gs_event_count(game) * sizeof(*debug->watch_events));
+ memset(debug->watch_tasks, FALSE,
+ gs_task_count(game) * sizeof(*debug->watch_tasks));
+ memset(debug->watch_variables, FALSE,
+ debug_variable_count(game) * sizeof(*debug->watch_variables));
+
+ /* Append the new debugger set to the game. */
+ assert(!game->debugger);
+ game->debugger = debug;
}
@@ -201,24 +195,23 @@ debug_initialize (sc_gameref_t game)
* from the game.
*/
static void
-debug_finalize (sc_gameref_t game)
-{
- sc_debuggerref_t debug = debug_get_debugger (game);
- assert (debug_is_valid (debug));
-
- /* Free all allocated watchpoint arrays. */
- sc_free (debug->watch_objects);
- sc_free (debug->watch_npcs);
- sc_free (debug->watch_events);
- sc_free (debug->watch_tasks);
- sc_free (debug->watch_variables);
-
- /* Poison and free the debugger itself. */
- memset (debug, 0xaa, sizeof (*debug));
- sc_free (debug);
-
- /* Remove the debug reference from the game. */
- game->debugger = NULL;
+debug_finalize(sc_gameref_t game) {
+ sc_debuggerref_t debug = debug_get_debugger(game);
+ assert(debug_is_valid(debug));
+
+ /* Free all allocated watchpoint arrays. */
+ sc_free(debug->watch_objects);
+ sc_free(debug->watch_npcs);
+ sc_free(debug->watch_events);
+ sc_free(debug->watch_tasks);
+ sc_free(debug->watch_variables);
+
+ /* Poison and free the debugger itself. */
+ memset(debug, 0xaa, sizeof(*debug));
+ sc_free(debug);
+
+ /* Remove the debug reference from the game. */
+ game->debugger = NULL;
}
@@ -228,312 +221,309 @@ debug_finalize (sc_gameref_t game)
* Print debugging help.
*/
static void
-debug_help (sc_command_t topic)
-{
- /* Is help general, or specific? */
- if (topic == DEBUG_NONE)
- {
- if_print_debug (
- "The following debugging commands examine game state:\n\n");
- if_print_debug (
- " game -- Print general game information,"
- " and class counts\n"
- " player -- Show the player location and position\n"
- " rooms [Range] -- Print information on game rooms\n"
- " objects [Range] -- Print information on objects in the game\n"
- " npcs [Range] -- Print information on game NPCs\n"
- " events [Range] -- Print information on the game's events\n"
- " tasks [Range] -- Print information on the game's tasks\n"
- " variables [Range] -- Show variables defined by the game\n\n");
- if_print_debug (
- "Most commands take range inputs. This can be a single number, to"
- " apply the command to just that item, a range such as '0 to 10' (or"
- " '0 - 10', '0 .. 10', or simply '0 10') to apply to that range of"
- " items, or '*' to apply the command to all items of the class. If"
- " omitted, the command is applied only to the items of the class"
- " 'relevant' to the current game state; see the help for specific"
- " commands for more on what is 'relevant'.\n\n");
- if_print_debug (
- "The 'player', 'objects', 'npcs', 'events', 'tasks', and 'variables'"
- " commands may be prefixed with 'old', in which case the values"
- " printed will be those for the previous game turn, rather than the"
- " current values.\n\n");
- if_print_debug (
- "These debugging commands manage watchpoints:\n\n");
- if_print_debug (
- "The 'player', 'objects', 'npcs', 'events', 'tasks', and 'variables'"
- " commands may be prefixed with 'watch', to set watchpoints."
- " Watchpoints automatically enter the debugger when the item changes"
- " state during a game turn. For example 'watchobject 10' monitors"
- " object 10 for changes, and 'watchnpc *' monitors all NPCs. A"
- " 'watch' command with no range prints out all watchpoints set for"
- " that class.\n\n");
- if_print_debug (
- "Prefix commands with 'clear' to clear watchpoints, for example"
- " 'clearnpcs *'. Use 'watchall' to obtain a complete list of every"
- " watchpoint set, and 'clearall' to clear all watchpoints in one go."
- " A 'clear' command with no range behaves the same as a 'watch'"
- " command with no range.\n\n");
- if_print_debug (
- "These debugging commands print details of game output and control the"
- " debugger and interpreter:\n\n");
- if_print_debug (
- " buffer -- Show the current buffered game text\n"
- " resources -- Show current and requested game resources\n"
- " random [Seed] -- Control the random number generator\n"
- " step -- Run one game turn, then re-enter the debugger\n"
- " continue -- Leave the debugger and resume the game\n"
- " quit -- Exit the interpreter main loop\n"
- " help [Command] -- Print help specific to Command\n\n");
- if_print_debug (
- "Debugging commands may be abbreviated to their shortest unambiguous"
- " form.\n\n");
- if_print_debug (
- "Use the 'debug' or '#debug' command in a game, typed at the usual"
- " game prompt, to return to the debugger.\n");
- return;
- }
-
- /* Command-specific help. */
- switch (topic)
- {
- case DEBUG_HELP:
- if_print_debug (
- "Give the name of the command you want help on, for example 'help"
- " continue'.\n");
- break;
-
- case DEBUG_CONTINUE:
- if_print_debug (
- "Leave the debugger and resume the game. Use the 'debug' or '#debug'"
- " command in a game, typed at the usual game prompt, to return to the"
- " debugger.\n");
- break;
-
- case DEBUG_STEP:
- if_print_debug (
- "Run one game turn, then re-enter the debugger. Useful for games that"
- " intercept empty input lines, which otherwise catch the 'debug'"
- " command before SCARE can get to it.\n");
- break;
-
- case DEBUG_QUIT:
- if_print_debug (
- "Exit the interpreter main loop. Equivalent to a confirmed 'quit'"
- " from within the game itself, this ends the interpreter session.\n");
- break;
-
- case DEBUG_BUFFER:
- if_print_debug (
- "Print the current text that the game has buffered for output. The"
- " debugger catches games before they have printed their turn output"
- " -- this is the text that will be filtered and printed on exiting the"
- " debugger.\n");
- break;
-
- case DEBUG_RESOURCES:
- if_print_debug (
- "Print any resources currently active, and any requested by the game"
- " on the current turn. The requested resources will become the active"
- " ones on exiting the debugger.\n");
- break;
-
- case DEBUG_RANDOM:
- if_print_debug (
- "If no seed is given, report the current random number generator"
- " setting. Otherwise, seed the random number generator with the value"
- " given. This is useful for persuading games with random sections to"
- " behave predictably. A new seed value of zero is invalid.\n");
- break;
-
- case DEBUG_GAME:
- if_print_debug (
- "Print general game information, including the number of rooms,"
- " objects, events, tasks, and variables that the game defines\n");
- break;
-
- case DEBUG_PLAYER:
- if_print_debug (
- "Print out the current player room and position, and any parent object"
- " of the player character.\n");
- break;
-
- case DEBUG_OLDPLAYER:
- if_print_debug (
- "Print out the player room and position from the previous turn, and"
- " any parent object of the player character.\n");
- break;
-
- case DEBUG_ROOMS:
- if_print_debug (
- "Print out the name and contents of rooms in the range. If no range,"
- " print details of the room containing the player.\n");
- break;
-
- case DEBUG_OLDROOMS:
- if_print_debug (
- "Print out the name and contents of rooms in the range for the"
- " previous turn. If no range, print details of the room that"
- " contained the player on the previous turn.\n");
- break;
-
- case DEBUG_OBJECTS:
- if_print_debug (
- "Print out details of all objects in the range. If no range, print"
- " details of objects in the room containing the player, and visible to"
- " the player.\n");
- break;
-
- case DEBUG_OLDOBJECTS:
- if_print_debug (
- "Print out details of all objects in the range for the previous turn."
- " If no range, print details of objects in the room that contained"
- " the player, and were visible to the player.\n");
- break;
-
- case DEBUG_NPCS:
- if_print_debug (
- "Print out details of all NPCs in the range. If no range, print"
- " details of only NPCs in the room containing the player.\n");
- break;
-
- case DEBUG_OLDNPCS:
- if_print_debug (
- "Print out details of all NPCs in the range for the previous turn."
- " If no range, print details of only NPCs in the room that contained"
- " the player.\n");
- break;
-
- case DEBUG_EVENTS:
- if_print_debug (
- "Print out details of all events in the range. If no range, print"
- " details of only events currently running.\n");
- break;
-
- case DEBUG_OLDEVENTS:
- if_print_debug (
- "Print out details of all events in the range for the previous turn."
- " If no range, print details of only events running on the previous"
- " turn.\n");
- break;
-
- case DEBUG_TASKS:
- if_print_debug (
- "Print out details of all tasks in the range. If no range, print"
- " details of only tasks that are runnable, for the current state of"
- " the game.\n");
- break;
-
- case DEBUG_OLDTASKS:
- if_print_debug (
- "Print out details of all tasks in the range for the previous turn."
- " If no range, print details of only tasks that were runnable, for"
- " the previous state of the game.\n");
- break;
-
- case DEBUG_VARIABLES:
- if_print_debug (
- "Print out the names, types, and values of all game variables in the"
- " range. If no range, print details of all variables (equivalent to"
- " 'variables *').\n");
- break;
-
- case DEBUG_OLDVARIABLES:
- if_print_debug (
- "Print out the names, types, and values at the previous turn of all"
- " game variables in the range. If no range, print details of all"
- " variables (equivalent to 'variables *').\n");
- break;
-
- case DEBUG_WATCHPLAYER:
- if_print_debug (
- "If no range is given, list any watchpoint on player movement. If"
- " range '0' is given, set a watchpoint on player movement. Other"
- " usages of 'watchplayer' behave as if no range is given.\n");
- break;
-
- case DEBUG_WATCHOBJECTS:
- if_print_debug (
- "Set watchpoints on all objects in the range. If no range, list out"
- " object watchpoints currently set.\n");
- break;
-
- case DEBUG_WATCHNPCS:
- if_print_debug (
- "Set watchpoints on all NPCs in the range. If no range, list out NPC"
- " watchpoints currently set.\n");
- break;
-
- case DEBUG_WATCHEVENTS:
- if_print_debug (
- "Set watchpoints on all events in the range. If no range, list out"
- " event watchpoints currently set.\n");
- break;
-
- case DEBUG_WATCHTASKS:
- if_print_debug (
- "Set watchpoints on all tasks in the range. If no range, list out"
- " task watchpoints currently set.\n");
- break;
-
- case DEBUG_WATCHVARIABLES:
- if_print_debug (
- "Set watchpoints on all game variables in the range. If no range,"
- " list variable watchpoints currently set.\n");
- break;
-
- case DEBUG_CLEARPLAYER:
- if_print_debug (
- "Clear any watchpoint set on player movements.\n");
- break;
-
- case DEBUG_CLEAROBJECTS:
- if_print_debug (
- "Clear watchpoints on all objects in the range. If no range, list"
- " out object watchpoints currently set.\n");
- break;
-
- case DEBUG_CLEARNPCS:
- if_print_debug (
- "Clear watchpoints on all NPCs in the range. If no range, list out"
- " NPC watchpoints currently set.\n");
- break;
-
- case DEBUG_CLEAREVENTS:
- if_print_debug (
- "Clear watchpoints on all events in the range. If no range, list out"
- " event watchpoints currently set.\n");
- break;
-
- case DEBUG_CLEARTASKS:
- if_print_debug (
- "Clear watchpoints on all tasks in the range. If no range, list out"
- " task watchpoints currently set.\n");
- break;
-
- case DEBUG_CLEARVARIABLES:
- if_print_debug (
- "Clear watchpoints on all game variables in the range. If no range,"
- " list variable watchpoints currently set.\n");
- break;
-
- case DEBUG_WATCHALL:
- if_print_debug (
- "Print out a list of all all watchpoints set for all the classes of"
- " item on which watchpoints can be used.\n");
- break;
-
- case DEBUG_CLEARALL:
- if_print_debug (
- "Clear all watchpoints set, on all classes of item on which"
- " watchpoints can be used.\n");
- break;
-
- default:
- if_print_debug (
- "Sorry, there is no help available on that at the moment.\n");
- break;
- }
+debug_help(sc_command_t topic) {
+ /* Is help general, or specific? */
+ if (topic == DEBUG_NONE) {
+ if_print_debug(
+ "The following debugging commands examine game state:\n\n");
+ if_print_debug(
+ " game -- Print general game information,"
+ " and class counts\n"
+ " player -- Show the player location and position\n"
+ " rooms [Range] -- Print information on game rooms\n"
+ " objects [Range] -- Print information on objects in the game\n"
+ " npcs [Range] -- Print information on game NPCs\n"
+ " events [Range] -- Print information on the game's events\n"
+ " tasks [Range] -- Print information on the game's tasks\n"
+ " variables [Range] -- Show variables defined by the game\n\n");
+ if_print_debug(
+ "Most commands take range inputs. This can be a single number, to"
+ " apply the command to just that item, a range such as '0 to 10' (or"
+ " '0 - 10', '0 .. 10', or simply '0 10') to apply to that range of"
+ " items, or '*' to apply the command to all items of the class. If"
+ " omitted, the command is applied only to the items of the class"
+ " 'relevant' to the current game state; see the help for specific"
+ " commands for more on what is 'relevant'.\n\n");
+ if_print_debug(
+ "The 'player', 'objects', 'npcs', 'events', 'tasks', and 'variables'"
+ " commands may be prefixed with 'old', in which case the values"
+ " printed will be those for the previous game turn, rather than the"
+ " current values.\n\n");
+ if_print_debug(
+ "These debugging commands manage watchpoints:\n\n");
+ if_print_debug(
+ "The 'player', 'objects', 'npcs', 'events', 'tasks', and 'variables'"
+ " commands may be prefixed with 'watch', to set watchpoints."
+ " Watchpoints automatically enter the debugger when the item changes"
+ " state during a game turn. For example 'watchobject 10' monitors"
+ " object 10 for changes, and 'watchnpc *' monitors all NPCs. A"
+ " 'watch' command with no range prints out all watchpoints set for"
+ " that class.\n\n");
+ if_print_debug(
+ "Prefix commands with 'clear' to clear watchpoints, for example"
+ " 'clearnpcs *'. Use 'watchall' to obtain a complete list of every"
+ " watchpoint set, and 'clearall' to clear all watchpoints in one go."
+ " A 'clear' command with no range behaves the same as a 'watch'"
+ " command with no range.\n\n");
+ if_print_debug(
+ "These debugging commands print details of game output and control the"
+ " debugger and interpreter:\n\n");
+ if_print_debug(
+ " buffer -- Show the current buffered game text\n"
+ " resources -- Show current and requested game resources\n"
+ " random [Seed] -- Control the random number generator\n"
+ " step -- Run one game turn, then re-enter the debugger\n"
+ " continue -- Leave the debugger and resume the game\n"
+ " quit -- Exit the interpreter main loop\n"
+ " help [Command] -- Print help specific to Command\n\n");
+ if_print_debug(
+ "Debugging commands may be abbreviated to their shortest unambiguous"
+ " form.\n\n");
+ if_print_debug(
+ "Use the 'debug' or '#debug' command in a game, typed at the usual"
+ " game prompt, to return to the debugger.\n");
+ return;
+ }
+
+ /* Command-specific help. */
+ switch (topic) {
+ case DEBUG_HELP:
+ if_print_debug(
+ "Give the name of the command you want help on, for example 'help"
+ " continue'.\n");
+ break;
+
+ case DEBUG_CONTINUE:
+ if_print_debug(
+ "Leave the debugger and resume the game. Use the 'debug' or '#debug'"
+ " command in a game, typed at the usual game prompt, to return to the"
+ " debugger.\n");
+ break;
+
+ case DEBUG_STEP:
+ if_print_debug(
+ "Run one game turn, then re-enter the debugger. Useful for games that"
+ " intercept empty input lines, which otherwise catch the 'debug'"
+ " command before SCARE can get to it.\n");
+ break;
+
+ case DEBUG_QUIT:
+ if_print_debug(
+ "Exit the interpreter main loop. Equivalent to a confirmed 'quit'"
+ " from within the game itself, this ends the interpreter session.\n");
+ break;
+
+ case DEBUG_BUFFER:
+ if_print_debug(
+ "Print the current text that the game has buffered for output. The"
+ " debugger catches games before they have printed their turn output"
+ " -- this is the text that will be filtered and printed on exiting the"
+ " debugger.\n");
+ break;
+
+ case DEBUG_RESOURCES:
+ if_print_debug(
+ "Print any resources currently active, and any requested by the game"
+ " on the current turn. The requested resources will become the active"
+ " ones on exiting the debugger.\n");
+ break;
+
+ case DEBUG_RANDOM:
+ if_print_debug(
+ "If no seed is given, report the current random number generator"
+ " setting. Otherwise, seed the random number generator with the value"
+ " given. This is useful for persuading games with random sections to"
+ " behave predictably. A new seed value of zero is invalid.\n");
+ break;
+
+ case DEBUG_GAME:
+ if_print_debug(
+ "Print general game information, including the number of rooms,"
+ " objects, events, tasks, and variables that the game defines\n");
+ break;
+
+ case DEBUG_PLAYER:
+ if_print_debug(
+ "Print out the current player room and position, and any parent object"
+ " of the player character.\n");
+ break;
+
+ case DEBUG_OLDPLAYER:
+ if_print_debug(
+ "Print out the player room and position from the previous turn, and"
+ " any parent object of the player character.\n");
+ break;
+
+ case DEBUG_ROOMS:
+ if_print_debug(
+ "Print out the name and contents of rooms in the range. If no range,"
+ " print details of the room containing the player.\n");
+ break;
+
+ case DEBUG_OLDROOMS:
+ if_print_debug(
+ "Print out the name and contents of rooms in the range for the"
+ " previous turn. If no range, print details of the room that"
+ " contained the player on the previous turn.\n");
+ break;
+
+ case DEBUG_OBJECTS:
+ if_print_debug(
+ "Print out details of all objects in the range. If no range, print"
+ " details of objects in the room containing the player, and visible to"
+ " the player.\n");
+ break;
+
+ case DEBUG_OLDOBJECTS:
+ if_print_debug(
+ "Print out details of all objects in the range for the previous turn."
+ " If no range, print details of objects in the room that contained"
+ " the player, and were visible to the player.\n");
+ break;
+
+ case DEBUG_NPCS:
+ if_print_debug(
+ "Print out details of all NPCs in the range. If no range, print"
+ " details of only NPCs in the room containing the player.\n");
+ break;
+
+ case DEBUG_OLDNPCS:
+ if_print_debug(
+ "Print out details of all NPCs in the range for the previous turn."
+ " If no range, print details of only NPCs in the room that contained"
+ " the player.\n");
+ break;
+
+ case DEBUG_EVENTS:
+ if_print_debug(
+ "Print out details of all events in the range. If no range, print"
+ " details of only events currently running.\n");
+ break;
+
+ case DEBUG_OLDEVENTS:
+ if_print_debug(
+ "Print out details of all events in the range for the previous turn."
+ " If no range, print details of only events running on the previous"
+ " turn.\n");
+ break;
+
+ case DEBUG_TASKS:
+ if_print_debug(
+ "Print out details of all tasks in the range. If no range, print"
+ " details of only tasks that are runnable, for the current state of"
+ " the game.\n");
+ break;
+
+ case DEBUG_OLDTASKS:
+ if_print_debug(
+ "Print out details of all tasks in the range for the previous turn."
+ " If no range, print details of only tasks that were runnable, for"
+ " the previous state of the game.\n");
+ break;
+
+ case DEBUG_VARIABLES:
+ if_print_debug(
+ "Print out the names, types, and values of all game variables in the"
+ " range. If no range, print details of all variables (equivalent to"
+ " 'variables *').\n");
+ break;
+
+ case DEBUG_OLDVARIABLES:
+ if_print_debug(
+ "Print out the names, types, and values at the previous turn of all"
+ " game variables in the range. If no range, print details of all"
+ " variables (equivalent to 'variables *').\n");
+ break;
+
+ case DEBUG_WATCHPLAYER:
+ if_print_debug(
+ "If no range is given, list any watchpoint on player movement. If"
+ " range '0' is given, set a watchpoint on player movement. Other"
+ " usages of 'watchplayer' behave as if no range is given.\n");
+ break;
+
+ case DEBUG_WATCHOBJECTS:
+ if_print_debug(
+ "Set watchpoints on all objects in the range. If no range, list out"
+ " object watchpoints currently set.\n");
+ break;
+
+ case DEBUG_WATCHNPCS:
+ if_print_debug(
+ "Set watchpoints on all NPCs in the range. If no range, list out NPC"
+ " watchpoints currently set.\n");
+ break;
+
+ case DEBUG_WATCHEVENTS:
+ if_print_debug(
+ "Set watchpoints on all events in the range. If no range, list out"
+ " event watchpoints currently set.\n");
+ break;
+
+ case DEBUG_WATCHTASKS:
+ if_print_debug(
+ "Set watchpoints on all tasks in the range. If no range, list out"
+ " task watchpoints currently set.\n");
+ break;
+
+ case DEBUG_WATCHVARIABLES:
+ if_print_debug(
+ "Set watchpoints on all game variables in the range. If no range,"
+ " list variable watchpoints currently set.\n");
+ break;
+
+ case DEBUG_CLEARPLAYER:
+ if_print_debug(
+ "Clear any watchpoint set on player movements.\n");
+ break;
+
+ case DEBUG_CLEAROBJECTS:
+ if_print_debug(
+ "Clear watchpoints on all objects in the range. If no range, list"
+ " out object watchpoints currently set.\n");
+ break;
+
+ case DEBUG_CLEARNPCS:
+ if_print_debug(
+ "Clear watchpoints on all NPCs in the range. If no range, list out"
+ " NPC watchpoints currently set.\n");
+ break;
+
+ case DEBUG_CLEAREVENTS:
+ if_print_debug(
+ "Clear watchpoints on all events in the range. If no range, list out"
+ " event watchpoints currently set.\n");
+ break;
+
+ case DEBUG_CLEARTASKS:
+ if_print_debug(
+ "Clear watchpoints on all tasks in the range. If no range, list out"
+ " task watchpoints currently set.\n");
+ break;
+
+ case DEBUG_CLEARVARIABLES:
+ if_print_debug(
+ "Clear watchpoints on all game variables in the range. If no range,"
+ " list variable watchpoints currently set.\n");
+ break;
+
+ case DEBUG_WATCHALL:
+ if_print_debug(
+ "Print out a list of all all watchpoints set for all the classes of"
+ " item on which watchpoints can be used.\n");
+ break;
+
+ case DEBUG_CLEARALL:
+ if_print_debug(
+ "Clear all watchpoints set, on all classes of item on which"
+ " watchpoints can be used.\n");
+ break;
+
+ default:
+ if_print_debug(
+ "Sorry, there is no help available on that at the moment.\n");
+ break;
+ }
}
@@ -550,217 +540,200 @@ debug_help (sc_command_t topic)
* Low level output helpers.
*/
static void
-debug_print_quoted (const sc_char *string)
-{
- if_print_debug_character ('"');
- if_print_debug (string);
- if_print_debug_character ('"');
+debug_print_quoted(const sc_char *string) {
+ if_print_debug_character('"');
+ if_print_debug(string);
+ if_print_debug_character('"');
}
static void
-debug_print_player (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- const sc_char *playername;
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "PlayerName";
- playername = prop_get_string (bundle, "S<-ss", vt_key);
- if_print_debug ("Player ");
- debug_print_quoted (playername);
+debug_print_player(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ const sc_char *playername;
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "PlayerName";
+ playername = prop_get_string(bundle, "S<-ss", vt_key);
+ if_print_debug("Player ");
+ debug_print_quoted(playername);
}
static void
-debug_print_room (sc_gameref_t game, sc_int room)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_char buffer[32];
- const sc_char *name;
-
- if_print_debug ("Room ");
- if (room < 0 || room >= gs_room_count (game))
- {
- sprintf (buffer, "%ld ", room);
- if_print_debug (buffer);
- if_print_debug ("[Out of range]");
- return;
- }
-
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- sprintf (buffer, "%ld ", room);
- if_print_debug (buffer);
- debug_print_quoted (name);
+debug_print_room(sc_gameref_t game, sc_int room) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_char buffer[32];
+ const sc_char *name;
+
+ if_print_debug("Room ");
+ if (room < 0 || room >= gs_room_count(game)) {
+ sprintf(buffer, "%ld ", room);
+ if_print_debug(buffer);
+ if_print_debug("[Out of range]");
+ return;
+ }
+
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ sprintf(buffer, "%ld ", room);
+ if_print_debug(buffer);
+ debug_print_quoted(name);
}
static void
-debug_print_object (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_bool bstatic;
- sc_char buffer[32];
- const sc_char *prefix, *name;
-
- if (object < 0 || object >= gs_object_count (game))
- {
- if_print_debug ("Object ");
- sprintf (buffer, "%ld ", object);
- if_print_debug (buffer);
- if_print_debug ("[Out of range]");
- return;
- }
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Static";
- bstatic = prop_get_boolean (bundle, "B<-sis", vt_key);
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- if (bstatic)
- if_print_debug ("Static ");
- else
- if_print_debug ("Dynamic ");
- sprintf (buffer, "%ld ", object);
- if_print_debug (buffer);
- debug_print_quoted (prefix);
- if_print_debug_character (' ');
- debug_print_quoted (name);
+debug_print_object(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_bool bstatic;
+ sc_char buffer[32];
+ const sc_char *prefix, *name;
+
+ if (object < 0 || object >= gs_object_count(game)) {
+ if_print_debug("Object ");
+ sprintf(buffer, "%ld ", object);
+ if_print_debug(buffer);
+ if_print_debug("[Out of range]");
+ return;
+ }
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Static";
+ bstatic = prop_get_boolean(bundle, "B<-sis", vt_key);
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ if (bstatic)
+ if_print_debug("Static ");
+ else
+ if_print_debug("Dynamic ");
+ sprintf(buffer, "%ld ", object);
+ if_print_debug(buffer);
+ debug_print_quoted(prefix);
+ if_print_debug_character(' ');
+ debug_print_quoted(name);
}
static void
-debug_print_npc (sc_gameref_t game, sc_int npc)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_char buffer[32];
- const sc_char *prefix, *name;
-
- if_print_debug ("NPC ");
- if (npc < 0 || npc >= gs_npc_count (game))
- {
- sprintf (buffer, "%ld ", npc);
- if_print_debug (buffer);
- if_print_debug ("[Out of range]");
- return;
- }
-
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- sprintf (buffer, "%ld ", npc);
- if_print_debug (buffer);
- debug_print_quoted (prefix);
- if_print_debug_character (' ');
- debug_print_quoted (name);
+debug_print_npc(sc_gameref_t game, sc_int npc) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_char buffer[32];
+ const sc_char *prefix, *name;
+
+ if_print_debug("NPC ");
+ if (npc < 0 || npc >= gs_npc_count(game)) {
+ sprintf(buffer, "%ld ", npc);
+ if_print_debug(buffer);
+ if_print_debug("[Out of range]");
+ return;
+ }
+
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ sprintf(buffer, "%ld ", npc);
+ if_print_debug(buffer);
+ debug_print_quoted(prefix);
+ if_print_debug_character(' ');
+ debug_print_quoted(name);
}
static void
-debug_print_event (sc_gameref_t game, sc_int event)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_char buffer[32];
- const sc_char *name;
-
- if_print_debug ("Event ");
- if (event < 0 || event >= gs_event_count (game))
- {
- sprintf (buffer, "%ld ", event);
- if_print_debug (buffer);
- if_print_debug ("[Out of range]");
- return;
- }
-
- vt_key[0].string = "Events";
- vt_key[1].integer = event;
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- sprintf (buffer, "%ld ", event);
- if_print_debug (buffer);
- debug_print_quoted (name);
+debug_print_event(sc_gameref_t game, sc_int event) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_char buffer[32];
+ const sc_char *name;
+
+ if_print_debug("Event ");
+ if (event < 0 || event >= gs_event_count(game)) {
+ sprintf(buffer, "%ld ", event);
+ if_print_debug(buffer);
+ if_print_debug("[Out of range]");
+ return;
+ }
+
+ vt_key[0].string = "Events";
+ vt_key[1].integer = event;
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ sprintf(buffer, "%ld ", event);
+ if_print_debug(buffer);
+ debug_print_quoted(name);
}
static void
-debug_print_task (sc_gameref_t game, sc_int task)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[4];
- sc_char buffer[32];
- const sc_char *command;
-
- if_print_debug ("Task ");
- if (task < 0 || task >= gs_task_count (game))
- {
- sprintf (buffer, "%ld ", task);
- if_print_debug (buffer);
- if_print_debug ("[Out of range]");
- return;
- }
-
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "Command";
- vt_key[3].integer = 0;
- command = prop_get_string (bundle, "S<-sisi", vt_key);
- sprintf (buffer, "%ld ", task);
- if_print_debug (buffer);
- debug_print_quoted (command);
+debug_print_task(sc_gameref_t game, sc_int task) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[4];
+ sc_char buffer[32];
+ const sc_char *command;
+
+ if_print_debug("Task ");
+ if (task < 0 || task >= gs_task_count(game)) {
+ sprintf(buffer, "%ld ", task);
+ if_print_debug(buffer);
+ if_print_debug("[Out of range]");
+ return;
+ }
+
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "Command";
+ vt_key[3].integer = 0;
+ command = prop_get_string(bundle, "S<-sisi", vt_key);
+ sprintf(buffer, "%ld ", task);
+ if_print_debug(buffer);
+ debug_print_quoted(command);
}
static void
-debug_print_variable (sc_gameref_t game, sc_int variable)
-{
- 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], vt_rvalue;
- sc_char buffer[32];
- sc_int var_type;
- const sc_char *name;
-
- if (variable < 0 || variable >= debug_variable_count (game))
- {
- if_print_debug ("Variable ");
- sprintf (buffer, "%ld ", variable);
- if_print_debug (buffer);
- if_print_debug ("[Out of range]");
- return;
- }
-
- vt_key[0].string = "Variables";
- vt_key[1].integer = variable;
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- if (var_get (vars, name, &var_type, &vt_rvalue))
- {
- switch (var_type)
- {
- case VAR_INTEGER:
- if_print_debug ("Integer ");
- break;
- case VAR_STRING:
- if_print_debug ("String ");
- break;
- default:
- if_print_debug ("[Invalid type] ");
- break;
- }
- }
- else
- if_print_debug ("[Invalid variable] ");
- sprintf (buffer, "%ld ", variable);
- if_print_debug (buffer);
- debug_print_quoted (name);
+debug_print_variable(sc_gameref_t game, sc_int variable) {
+ 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], vt_rvalue;
+ sc_char buffer[32];
+ sc_int var_type;
+ const sc_char *name;
+
+ if (variable < 0 || variable >= debug_variable_count(game)) {
+ if_print_debug("Variable ");
+ sprintf(buffer, "%ld ", variable);
+ if_print_debug(buffer);
+ if_print_debug("[Out of range]");
+ return;
+ }
+
+ vt_key[0].string = "Variables";
+ vt_key[1].integer = variable;
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ if (var_get(vars, name, &var_type, &vt_rvalue)) {
+ switch (var_type) {
+ case VAR_INTEGER:
+ if_print_debug("Integer ");
+ break;
+ case VAR_STRING:
+ if_print_debug("String ");
+ break;
+ default:
+ if_print_debug("[Invalid type] ");
+ break;
+ }
+ } else
+ if_print_debug("[Invalid variable] ");
+ sprintf(buffer, "%ld ", variable);
+ if_print_debug(buffer);
+ debug_print_quoted(name);
}
@@ -770,148 +743,145 @@ debug_print_variable (sc_gameref_t game, sc_int variable)
* Display overall game details.
*/
static void
-debug_game (sc_gameref_t game, sc_command_type_t type)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- const sc_debuggerref_t debug = debug_get_debugger (game);
- sc_vartype_t vt_key[2];
- const sc_char *version, *gamename, *compiledate, *gameauthor;
- sc_int perspective, waitturns;
- sc_bool has_sound, has_graphics, has_battle;
- sc_char buffer[32];
- assert (debug_is_valid (debug));
-
- if (type != COMMAND_QUERY)
- {
- if_print_debug ("The Game command takes no arguments.\n");
- return;
- }
-
- if_print_debug ("Game ");
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- gamename = prop_get_string (bundle, "S<-ss", vt_key);
- debug_print_quoted (gamename);
- if_print_debug_character ('\n');
-
- if_print_debug (" Compiled ");
- vt_key[0].string = "CompileDate";
- compiledate = prop_get_string (bundle, "S<-s", vt_key);
- debug_print_quoted (compiledate);
-
- if_print_debug (", Author ");
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameAuthor";
- gameauthor = prop_get_string (bundle, "S<-ss", vt_key);
- debug_print_quoted (gameauthor);
- if_print_debug_character ('\n');
-
- vt_key[0].string = "VersionString";
- version = prop_get_string (bundle, "S<-s", vt_key);
- if_print_debug (" Version ");
- if_print_debug (version);
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "Perspective";
- perspective = prop_get_integer (bundle, "I<-ss", vt_key);
- switch (perspective)
- {
- case 0:
- if_print_debug (", First person");
- break;
- case 1:
- if_print_debug (", Second person");
- break;
- case 2:
- if_print_debug (", Third person");
- break;
- default:
- if_print_debug (", [Unknown perspective]");
- break;
- }
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "WaitTurns";
- waitturns = prop_get_integer (bundle, "I<-ss", vt_key);
- if_print_debug (", Waitturns ");
- sprintf (buffer, "%ld", waitturns);
- if_print_debug (buffer);
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "Sound";
- has_sound = prop_get_boolean (bundle, "B<-ss", vt_key);
- vt_key[1].string = "Graphics";
- has_graphics = prop_get_boolean (bundle, "B<-ss", vt_key);
- if (has_sound)
- if_print_debug (", Sound");
- if (has_graphics)
- if_print_debug (", Graphics");
- if_print_debug_character ('\n');
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "BattleSystem";
- has_battle = prop_get_boolean (bundle, "B<-ss", vt_key);
- if (has_battle)
- if_print_debug (" Battle system\n");
-
- if_print_debug (" Room count ");
- sprintf (buffer, "%ld", gs_room_count (game));
- if_print_debug (buffer);
-
- if_print_debug (", Object count ");
- sprintf (buffer, "%ld", gs_object_count (game));
- if_print_debug (buffer);
-
- if_print_debug (", NPC count ");
- sprintf (buffer, "%ld", gs_npc_count (game));
- if_print_debug (buffer);
- if_print_debug_character ('\n');
-
- if_print_debug (" Event count ");
- sprintf (buffer, "%ld", gs_event_count (game));
- if_print_debug (buffer);
-
- if_print_debug (", Task count ");
- sprintf (buffer, "%ld", gs_task_count (game));
- if_print_debug (buffer);
-
- if_print_debug (", Variable count ");
- sprintf (buffer, "%ld", debug_variable_count (game));
- if_print_debug (buffer);
- if_print_debug_character ('\n');
-
- if (game->is_running)
- if_print_debug (" Running");
- else
- if_print_debug (" Not running");
- if (game->has_completed)
- if_print_debug (", Completed");
- else
- if_print_debug (", Not completed");
- if (game->verbose)
- if_print_debug (", Verbose");
- else
- if_print_debug (", Not verbose");
- if (game->bold_room_names)
- if_print_debug (", Bold");
- else
- if_print_debug (", Not bold");
- if (game->undo_available)
- if_print_debug (", Undo");
- else
- if_print_debug (", No undo");
- if_print_debug_character ('\n');
-
- if_print_debug (" Score ");
- sprintf (buffer, "%ld", game->score);
- if_print_debug (buffer);
- if_print_debug (", Turns ");
- sprintf (buffer, "%ld", game->turns);
- if_print_debug (buffer);
- if_print_debug (", Seconds ");
- sprintf (buffer, "%lu", debug->elapsed_seconds);
- if_print_debug (buffer);
- if_print_debug_character ('\n');
+debug_game(sc_gameref_t game, sc_command_type_t type) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+ sc_vartype_t vt_key[2];
+ const sc_char *version, *gamename, *compiledate, *gameauthor;
+ sc_int perspective, waitturns;
+ sc_bool has_sound, has_graphics, has_battle;
+ sc_char buffer[32];
+ assert(debug_is_valid(debug));
+
+ if (type != COMMAND_QUERY) {
+ if_print_debug("The Game command takes no arguments.\n");
+ return;
+ }
+
+ if_print_debug("Game ");
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ gamename = prop_get_string(bundle, "S<-ss", vt_key);
+ debug_print_quoted(gamename);
+ if_print_debug_character('\n');
+
+ if_print_debug(" Compiled ");
+ vt_key[0].string = "CompileDate";
+ compiledate = prop_get_string(bundle, "S<-s", vt_key);
+ debug_print_quoted(compiledate);
+
+ if_print_debug(", Author ");
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameAuthor";
+ gameauthor = prop_get_string(bundle, "S<-ss", vt_key);
+ debug_print_quoted(gameauthor);
+ if_print_debug_character('\n');
+
+ vt_key[0].string = "VersionString";
+ version = prop_get_string(bundle, "S<-s", vt_key);
+ if_print_debug(" Version ");
+ if_print_debug(version);
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Perspective";
+ perspective = prop_get_integer(bundle, "I<-ss", vt_key);
+ switch (perspective) {
+ case 0:
+ if_print_debug(", First person");
+ break;
+ case 1:
+ if_print_debug(", Second person");
+ break;
+ case 2:
+ if_print_debug(", Third person");
+ break;
+ default:
+ if_print_debug(", [Unknown perspective]");
+ break;
+ }
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "WaitTurns";
+ waitturns = prop_get_integer(bundle, "I<-ss", vt_key);
+ if_print_debug(", Waitturns ");
+ sprintf(buffer, "%ld", waitturns);
+ if_print_debug(buffer);
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Sound";
+ has_sound = prop_get_boolean(bundle, "B<-ss", vt_key);
+ vt_key[1].string = "Graphics";
+ has_graphics = prop_get_boolean(bundle, "B<-ss", vt_key);
+ if (has_sound)
+ if_print_debug(", Sound");
+ if (has_graphics)
+ if_print_debug(", Graphics");
+ if_print_debug_character('\n');
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "BattleSystem";
+ has_battle = prop_get_boolean(bundle, "B<-ss", vt_key);
+ if (has_battle)
+ if_print_debug(" Battle system\n");
+
+ if_print_debug(" Room count ");
+ sprintf(buffer, "%ld", gs_room_count(game));
+ if_print_debug(buffer);
+
+ if_print_debug(", Object count ");
+ sprintf(buffer, "%ld", gs_object_count(game));
+ if_print_debug(buffer);
+
+ if_print_debug(", NPC count ");
+ sprintf(buffer, "%ld", gs_npc_count(game));
+ if_print_debug(buffer);
+ if_print_debug_character('\n');
+
+ if_print_debug(" Event count ");
+ sprintf(buffer, "%ld", gs_event_count(game));
+ if_print_debug(buffer);
+
+ if_print_debug(", Task count ");
+ sprintf(buffer, "%ld", gs_task_count(game));
+ if_print_debug(buffer);
+
+ if_print_debug(", Variable count ");
+ sprintf(buffer, "%ld", debug_variable_count(game));
+ if_print_debug(buffer);
+ if_print_debug_character('\n');
+
+ if (game->is_running)
+ if_print_debug(" Running");
+ else
+ if_print_debug(" Not running");
+ if (game->has_completed)
+ if_print_debug(", Completed");
+ else
+ if_print_debug(", Not completed");
+ if (game->verbose)
+ if_print_debug(", Verbose");
+ else
+ if_print_debug(", Not verbose");
+ if (game->bold_room_names)
+ if_print_debug(", Bold");
+ else
+ if_print_debug(", Not bold");
+ if (game->undo_available)
+ if_print_debug(", Undo");
+ else
+ if_print_debug(", No undo");
+ if_print_debug_character('\n');
+
+ if_print_debug(" Score ");
+ sprintf(buffer, "%ld", game->score);
+ if_print_debug(buffer);
+ if_print_debug(", Turns ");
+ sprintf(buffer, "%ld", game->turns);
+ if_print_debug(buffer);
+ if_print_debug(", Seconds ");
+ sprintf(buffer, "%lu", debug->elapsed_seconds);
+ if_print_debug(buffer);
+ if_print_debug_character('\n');
}
@@ -921,61 +891,54 @@ debug_game (sc_gameref_t game, sc_command_type_t type)
* Print a few brief details about the player status.
*/
static void
-debug_player (sc_gameref_t game,
- sc_command_t command, sc_command_type_t type)
-{
- if (type != COMMAND_QUERY)
- {
- if_print_debug ("The Player command takes no arguments.\n");
- return;
- }
-
- if (command == DEBUG_OLDPLAYER)
- {
- if (!game->undo_available)
- {
- if_print_debug ("There is no previous game state to examine.\n");
- return;
- }
-
- game = game->undo;
- assert (gs_is_game_valid (game));
- }
-
- debug_print_player (game);
- if_print_debug_character ('\n');
-
- if (gs_playerroom (game) == -1)
- if_print_debug (" Hidden!\n");
- else
- {
- if_print_debug (" In ");
- debug_print_room (game, gs_playerroom (game));
- if_print_debug_character ('\n');
- }
-
- switch (gs_playerposition (game))
- {
- case 0:
- if_print_debug (" Standing\n");
- break;
- case 1:
- if_print_debug (" Sitting\n");
- break;
- case 2:
- if_print_debug (" Lying\n");
- break;
- default:
- if_print_debug (" [Invalid position]\n");
- break;
- }
-
- if (gs_playerparent (game) != -1)
- {
- if_print_debug (" Parent is ");
- debug_print_object (game, gs_playerparent (game));
- if_print_debug_character ('\n');
- }
+debug_player(sc_gameref_t game,
+ sc_command_t command, sc_command_type_t type) {
+ if (type != COMMAND_QUERY) {
+ if_print_debug("The Player command takes no arguments.\n");
+ return;
+ }
+
+ if (command == DEBUG_OLDPLAYER) {
+ if (!game->undo_available) {
+ if_print_debug("There is no previous game state to examine.\n");
+ return;
+ }
+
+ game = game->undo;
+ assert(gs_is_game_valid(game));
+ }
+
+ debug_print_player(game);
+ if_print_debug_character('\n');
+
+ if (gs_playerroom(game) == -1)
+ if_print_debug(" Hidden!\n");
+ else {
+ if_print_debug(" In ");
+ debug_print_room(game, gs_playerroom(game));
+ if_print_debug_character('\n');
+ }
+
+ switch (gs_playerposition(game)) {
+ case 0:
+ if_print_debug(" Standing\n");
+ break;
+ case 1:
+ if_print_debug(" Sitting\n");
+ break;
+ case 2:
+ if_print_debug(" Lying\n");
+ break;
+ default:
+ if_print_debug(" [Invalid position]\n");
+ break;
+ }
+
+ if (gs_playerparent(game) != -1) {
+ if_print_debug(" Parent is ");
+ debug_print_object(game, gs_playerparent(game));
+ if_print_debug_character('\n');
+ }
}
@@ -986,41 +949,38 @@ debug_player (sc_gameref_t game,
* debug commands that take ranges.
*/
static sc_bool
-debug_normalize_arguments (sc_command_type_t type,
- sc_int *arg1, sc_int *arg2, sc_int limit)
-{
- sc_int low = 0, high = 0;
-
- /* Set range low and high depending on the command type. */
- switch (type)
- {
- case COMMAND_QUERY:
- case COMMAND_ALL:
- low = 0;
- high = limit - 1;
- break;
- case COMMAND_ONE:
- low = *arg1;
- high = *arg1;
- break;
- case COMMAND_RANGE:
- low = *arg1;
- high = *arg2;
- break;
- default:
- sc_fatal ("debug_normalize_arguments: bad command type\n");
- }
-
- /* If range is valid, copy out and return TRUE. */
- if (low >= 0 && low < limit && high >= 0 && high < limit && high >= low)
- {
- *arg1 = low;
- *arg2 = high;
- return TRUE;
- }
-
- /* Input range is invalid. */
- return FALSE;
+debug_normalize_arguments(sc_command_type_t type,
+ sc_int *arg1, sc_int *arg2, sc_int limit) {
+ sc_int low = 0, high = 0;
+
+ /* Set range low and high depending on the command type. */
+ switch (type) {
+ case COMMAND_QUERY:
+ case COMMAND_ALL:
+ low = 0;
+ high = limit - 1;
+ break;
+ case COMMAND_ONE:
+ low = *arg1;
+ high = *arg1;
+ break;
+ case COMMAND_RANGE:
+ low = *arg1;
+ high = *arg2;
+ break;
+ default:
+ sc_fatal("debug_normalize_arguments: bad command type\n");
+ }
+
+ /* If range is valid, copy out and return TRUE. */
+ if (low >= 0 && low < limit && high >= 0 && high < limit && high >= low) {
+ *arg1 = low;
+ *arg2 = high;
+ return TRUE;
+ }
+
+ /* Input range is invalid. */
+ return FALSE;
}
@@ -1031,50 +991,43 @@ debug_normalize_arguments (sc_command_type_t type,
* Print details of rooms and their direct contents.
*/
static sc_bool
-debug_filter_room (sc_gameref_t game, sc_int room)
-{
- return room == gs_playerroom (game);
+debug_filter_room(sc_gameref_t game, sc_int room) {
+ return room == gs_playerroom(game);
}
static void
-debug_dump_room (sc_gameref_t game, sc_int room)
-{
- sc_int object, npc;
-
- debug_print_room (game, room);
- if_print_debug_character ('\n');
-
- if (gs_room_seen (game, room))
- if_print_debug (" Visited\n");
- else
- if_print_debug (" Not visited\n");
-
- if (gs_playerroom (game) == room)
- {
- if_print_debug (" ");
- debug_print_player (game);
- if_print_debug_character ('\n');
- }
-
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (obj_indirectly_in_room (game, object, room))
- {
- if_print_debug (" ");
- debug_print_object (game, object);
- if_print_debug_character ('\n');
- }
- }
-
- for (npc = 0; npc < gs_npc_count (game); npc++)
- {
- if (npc_in_room (game, npc, room))
- {
- if_print_debug (" ");
- debug_print_npc (game, npc);
- if_print_debug_character ('\n');
- }
- }
+debug_dump_room(sc_gameref_t game, sc_int room) {
+ sc_int object, npc;
+
+ debug_print_room(game, room);
+ if_print_debug_character('\n');
+
+ if (gs_room_seen(game, room))
+ if_print_debug(" Visited\n");
+ else
+ if_print_debug(" Not visited\n");
+
+ if (gs_playerroom(game) == room) {
+ if_print_debug(" ");
+ debug_print_player(game);
+ if_print_debug_character('\n');
+ }
+
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (obj_indirectly_in_room(game, object, room)) {
+ if_print_debug(" ");
+ debug_print_object(game, object);
+ if_print_debug_character('\n');
+ }
+ }
+
+ for (npc = 0; npc < gs_npc_count(game); npc++) {
+ if (npc_in_room(game, npc, room)) {
+ if_print_debug(" ");
+ debug_print_npc(game, npc);
+ if_print_debug_character('\n');
+ }
+ }
}
@@ -1085,139 +1038,130 @@ debug_dump_room (sc_gameref_t game, sc_int room)
* Print the changeable details of game objects.
*/
static sc_bool
-debug_filter_object (sc_gameref_t game, sc_int object)
-{
- return obj_indirectly_in_room (game, object, gs_playerroom (game));
+debug_filter_object(sc_gameref_t game, sc_int object) {
+ return obj_indirectly_in_room(game, object, gs_playerroom(game));
}
static void
-debug_dump_object (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int openness;
- sc_vartype_t vt_key[3];
- sc_bool bstatic, is_statussed;
- sc_int position, parent;
-
- debug_print_object (game, object);
- if_print_debug_character ('\n');
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Static";
- bstatic = prop_get_boolean (bundle, "B<-sis", vt_key);
-
- if (gs_object_seen (game, object))
- if_print_debug (" Seen");
- else
- if_print_debug (" Not seen");
- if (bstatic)
- {
- if (gs_object_static_unmoved (game, object))
- if_print_debug (", Not relocated");
- else
- if_print_debug (", Relocated");
- }
- else
- {
- vt_key[2].string = "OnlyWhenNotMoved";
- if (prop_get_integer (bundle, "I<-sis", vt_key) == 1)
- {
- if (gs_object_unmoved (game, object))
- if_print_debug (", Not moved");
- else
- if_print_debug (", Moved");
- }
- }
- openness = gs_object_openness (game, object);
- switch (openness)
- {
- case OBJ_OPEN:
- if_print_debug (", Open");
- break;
- case OBJ_CLOSED:
- if_print_debug (", Closed");
- break;
- case OBJ_LOCKED:
- if_print_debug (", Locked");
- break;
- }
- if_print_debug_character ('\n');
-
- position = gs_object_position (game, object);
- parent = gs_object_parent (game, object);
- switch (position)
- {
- case OBJ_HIDDEN:
- if (bstatic)
- if_print_debug (" Static default\n");
- else
- if_print_debug (" Hidden\n");
- break;
- case OBJ_HELD_PLAYER:
- if_print_debug (" Held by ");
- debug_print_player (game);
- if_print_debug_character ('\n');
- break;
- case OBJ_HELD_NPC:
- if_print_debug (" Held by ");
- debug_print_npc (game, parent);
- if_print_debug_character ('\n');
- break;
- case OBJ_WORN_PLAYER:
- if_print_debug (" Worn by ");
- debug_print_player (game);
- if_print_debug_character ('\n');
- break;
- case OBJ_WORN_NPC:
- if_print_debug (" Worn by ");
- debug_print_npc (game, parent);
- if_print_debug_character ('\n');
- break;
- case OBJ_PART_NPC:
- if_print_debug (" Part of ");
- if (parent == -1)
- debug_print_player (game);
- else
- debug_print_npc (game, parent);
- if_print_debug_character ('\n');
- break;
- case OBJ_ON_OBJECT:
- if_print_debug (" On ");
- debug_print_object (game, parent);
- if_print_debug_character ('\n');
- break;
- case OBJ_IN_OBJECT:
- if_print_debug (" Inside ");
- debug_print_object (game, parent);
- if_print_debug_character ('\n');
- break;
- default:
- if_print_debug (" In ");
- debug_print_room (game, position - 1);
- if_print_debug_character ('\n');
- break;
- }
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "CurrentState";
- is_statussed = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- if (is_statussed)
- {
- sc_char buffer[32];
- const sc_char *states;
-
- if_print_debug (" State ");
- sprintf (buffer, "%ld", gs_object_state (game, object));
- if_print_debug (buffer);
-
- vt_key[2].string = "States";
- states = prop_get_string (bundle, "S<-sis", vt_key);
- if_print_debug (" of ");
- debug_print_quoted (states);
- if_print_debug_character ('\n');
- }
+debug_dump_object(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int openness;
+ sc_vartype_t vt_key[3];
+ sc_bool bstatic, is_statussed;
+ sc_int position, parent;
+
+ debug_print_object(game, object);
+ if_print_debug_character('\n');
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Static";
+ bstatic = prop_get_boolean(bundle, "B<-sis", vt_key);
+
+ if (gs_object_seen(game, object))
+ if_print_debug(" Seen");
+ else
+ if_print_debug(" Not seen");
+ if (bstatic) {
+ if (gs_object_static_unmoved(game, object))
+ if_print_debug(", Not relocated");
+ else
+ if_print_debug(", Relocated");
+ } else {
+ vt_key[2].string = "OnlyWhenNotMoved";
+ if (prop_get_integer(bundle, "I<-sis", vt_key) == 1) {
+ if (gs_object_unmoved(game, object))
+ if_print_debug(", Not moved");
+ else
+ if_print_debug(", Moved");
+ }
+ }
+ openness = gs_object_openness(game, object);
+ switch (openness) {
+ case OBJ_OPEN:
+ if_print_debug(", Open");
+ break;
+ case OBJ_CLOSED:
+ if_print_debug(", Closed");
+ break;
+ case OBJ_LOCKED:
+ if_print_debug(", Locked");
+ break;
+ }
+ if_print_debug_character('\n');
+
+ position = gs_object_position(game, object);
+ parent = gs_object_parent(game, object);
+ switch (position) {
+ case OBJ_HIDDEN:
+ if (bstatic)
+ if_print_debug(" Static default\n");
+ else
+ if_print_debug(" Hidden\n");
+ break;
+ case OBJ_HELD_PLAYER:
+ if_print_debug(" Held by ");
+ debug_print_player(game);
+ if_print_debug_character('\n');
+ break;
+ case OBJ_HELD_NPC:
+ if_print_debug(" Held by ");
+ debug_print_npc(game, parent);
+ if_print_debug_character('\n');
+ break;
+ case OBJ_WORN_PLAYER:
+ if_print_debug(" Worn by ");
+ debug_print_player(game);
+ if_print_debug_character('\n');
+ break;
+ case OBJ_WORN_NPC:
+ if_print_debug(" Worn by ");
+ debug_print_npc(game, parent);
+ if_print_debug_character('\n');
+ break;
+ case OBJ_PART_NPC:
+ if_print_debug(" Part of ");
+ if (parent == -1)
+ debug_print_player(game);
+ else
+ debug_print_npc(game, parent);
+ if_print_debug_character('\n');
+ break;
+ case OBJ_ON_OBJECT:
+ if_print_debug(" On ");
+ debug_print_object(game, parent);
+ if_print_debug_character('\n');
+ break;
+ case OBJ_IN_OBJECT:
+ if_print_debug(" Inside ");
+ debug_print_object(game, parent);
+ if_print_debug_character('\n');
+ break;
+ default:
+ if_print_debug(" In ");
+ debug_print_room(game, position - 1);
+ if_print_debug_character('\n');
+ break;
+ }
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "CurrentState";
+ is_statussed = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ if (is_statussed) {
+ sc_char buffer[32];
+ const sc_char *states;
+
+ if_print_debug(" State ");
+ sprintf(buffer, "%ld", gs_object_state(game, object));
+ if_print_debug(buffer);
+
+ vt_key[2].string = "States";
+ states = prop_get_string(bundle, "S<-sis", vt_key);
+ if_print_debug(" of ");
+ debug_print_quoted(states);
+ if_print_debug_character('\n');
+ }
}
@@ -1228,71 +1172,64 @@ debug_dump_object (sc_gameref_t game, sc_int object)
* Print stuff about NPCs.
*/
static sc_bool
-debug_filter_npc (sc_gameref_t game, sc_int npc)
-{
- return npc_in_room (game, npc, gs_playerroom (game));
+debug_filter_npc(sc_gameref_t game, sc_int npc) {
+ return npc_in_room(game, npc, gs_playerroom(game));
}
static void
-debug_dump_npc (sc_gameref_t game, sc_int npc)
-{
- debug_print_npc (game, npc);
- if_print_debug_character ('\n');
-
- if (gs_npc_seen (game, npc))
- if_print_debug (" Seen\n");
- else
- if_print_debug (" Not seen\n");
-
- if (gs_npc_location (game, npc) - 1 == -1)
- if_print_debug (" Hidden\n");
- else
- {
- if_print_debug (" In ");
- debug_print_room (game, gs_npc_location (game, npc) - 1);
- if_print_debug_character ('\n');
- }
-
- switch (gs_npc_position (game, npc))
- {
- case 0:
- if_print_debug (" Standing\n");
- break;
- case 1:
- if_print_debug (" Sitting\n");
- break;
- case 2:
- if_print_debug (" Lying\n");
- break;
- default:
- if_print_debug (" [Invalid position]\n");
- break;
- }
-
- if (gs_npc_parent (game, npc) != -1)
- {
- if_print_debug (" Parent is ");
- debug_print_object (game, gs_npc_parent (game, npc));
- if_print_debug_character ('\n');
- }
-
- if (gs_npc_walkstep_count (game, npc) > 0)
- {
- sc_char buffer[32];
- sc_int walk;
-
- if_print_debug (" Walkstep count ");
- sprintf (buffer, "%ld", gs_npc_walkstep_count (game, npc));
- if_print_debug (buffer);
- if_print_debug (", Walks { ");
- for (walk = 0; walk < gs_npc_walkstep_count (game, npc); walk++)
- {
- sprintf (buffer, "%ld", gs_npc_walkstep (game, npc, walk));
- if_print_debug (buffer);
- if_print_debug_character (' ');
- }
- if_print_debug ("}.\n");
- }
+debug_dump_npc(sc_gameref_t game, sc_int npc) {
+ debug_print_npc(game, npc);
+ if_print_debug_character('\n');
+
+ if (gs_npc_seen(game, npc))
+ if_print_debug(" Seen\n");
+ else
+ if_print_debug(" Not seen\n");
+
+ if (gs_npc_location(game, npc) - 1 == -1)
+ if_print_debug(" Hidden\n");
+ else {
+ if_print_debug(" In ");
+ debug_print_room(game, gs_npc_location(game, npc) - 1);
+ if_print_debug_character('\n');
+ }
+
+ switch (gs_npc_position(game, npc)) {
+ case 0:
+ if_print_debug(" Standing\n");
+ break;
+ case 1:
+ if_print_debug(" Sitting\n");
+ break;
+ case 2:
+ if_print_debug(" Lying\n");
+ break;
+ default:
+ if_print_debug(" [Invalid position]\n");
+ break;
+ }
+
+ if (gs_npc_parent(game, npc) != -1) {
+ if_print_debug(" Parent is ");
+ debug_print_object(game, gs_npc_parent(game, npc));
+ if_print_debug_character('\n');
+ }
+
+ if (gs_npc_walkstep_count(game, npc) > 0) {
+ sc_char buffer[32];
+ sc_int walk;
+
+ if_print_debug(" Walkstep count ");
+ sprintf(buffer, "%ld", gs_npc_walkstep_count(game, npc));
+ if_print_debug(buffer);
+ if_print_debug(", Walks { ");
+ for (walk = 0; walk < gs_npc_walkstep_count(game, npc); walk++) {
+ sprintf(buffer, "%ld", gs_npc_walkstep(game, npc, walk));
+ if_print_debug(buffer);
+ if_print_debug_character(' ');
+ }
+ if_print_debug("}.\n");
+ }
}
@@ -1303,44 +1240,41 @@ debug_dump_npc (sc_gameref_t game, sc_int npc)
* Print stuff about events.
*/
static sc_bool
-debug_filter_event (sc_gameref_t game, sc_int event)
-{
- return gs_event_state (game, event) == ES_RUNNING;
+debug_filter_event(sc_gameref_t game, sc_int event) {
+ return gs_event_state(game, event) == ES_RUNNING;
}
static void
-debug_dump_event (sc_gameref_t game, sc_int event)
-{
- sc_char buffer[32];
-
- debug_print_event (game, event);
- if_print_debug_character ('\n');
-
- switch (gs_event_state (game, event))
- {
- case ES_WAITING:
- if_print_debug (" Waiting\n");
- break;
- case ES_RUNNING:
- if_print_debug (" Running\n");
- break;
- case ES_AWAITING:
- if_print_debug (" Awaiting\n");
- break;
- case ES_FINISHED:
- if_print_debug (" Finished\n");
- break;
- case ES_PAUSED:
- if_print_debug (" Paused\n");
- break;
- default:
- if_print_debug (" [Invalid state]\n");
- break;
- }
-
- if_print_debug (" Time ");
- sprintf (buffer, "%ld\n", gs_event_time (game, event));
- if_print_debug (buffer);
+debug_dump_event(sc_gameref_t game, sc_int event) {
+ sc_char buffer[32];
+
+ debug_print_event(game, event);
+ if_print_debug_character('\n');
+
+ switch (gs_event_state(game, event)) {
+ case ES_WAITING:
+ if_print_debug(" Waiting\n");
+ break;
+ case ES_RUNNING:
+ if_print_debug(" Running\n");
+ break;
+ case ES_AWAITING:
+ if_print_debug(" Awaiting\n");
+ break;
+ case ES_FINISHED:
+ if_print_debug(" Finished\n");
+ break;
+ case ES_PAUSED:
+ if_print_debug(" Paused\n");
+ break;
+ default:
+ if_print_debug(" [Invalid state]\n");
+ break;
+ }
+
+ if_print_debug(" Time ");
+ sprintf(buffer, "%ld\n", gs_event_time(game, event));
+ if_print_debug(buffer);
}
@@ -1351,29 +1285,27 @@ debug_dump_event (sc_gameref_t game, sc_int event)
* Print stuff about tasks.
*/
static sc_bool
-debug_filter_task (sc_gameref_t game, sc_int task)
-{
- return task_can_run_task (game, task);
+debug_filter_task(sc_gameref_t game, sc_int task) {
+ return task_can_run_task(game, task);
}
static void
-debug_dump_task (sc_gameref_t game, sc_int task)
-{
- debug_print_task (game, task);
- if_print_debug_character ('\n');
-
- if (task_can_run_task (game, task))
- if_print_debug (" Runnable");
- else
- if_print_debug (" Not runnable");
- if (gs_task_done (game, task))
- if_print_debug (", Done");
- else
- if_print_debug (", Not done");
- if (gs_task_scored (game, task))
- if_print_debug (", Scored\n");
- else
- if_print_debug (", Not scored\n");
+debug_dump_task(sc_gameref_t game, sc_int task) {
+ debug_print_task(game, task);
+ if_print_debug_character('\n');
+
+ if (task_can_run_task(game, task))
+ if_print_debug(" Runnable");
+ else
+ if_print_debug(" Not runnable");
+ if (gs_task_done(game, task))
+ if_print_debug(", Done");
+ else
+ if_print_debug(", Not done");
+ if (gs_task_scored(game, task))
+ if_print_debug(", Scored\n");
+ else
+ if_print_debug(", Not scored\n");
}
@@ -1383,46 +1315,41 @@ debug_dump_task (sc_gameref_t game, sc_int task)
* Print stuff about variables.
*/
static void
-debug_dump_variable (sc_gameref_t game, sc_int variable)
-{
- 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], vt_rvalue;
- const sc_char *name;
- sc_int var_type;
-
- debug_print_variable (game, variable);
- if_print_debug_character ('\n');
-
- vt_key[0].string = "Variables";
- vt_key[1].integer = variable;
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- if_print_debug (" Value = ");
- if (var_get (vars, name, &var_type, &vt_rvalue))
- {
- switch (var_type)
- {
- case VAR_INTEGER:
- {
- sc_char buffer[32];
-
- sprintf (buffer, "%ld", vt_rvalue.integer);
- if_print_debug (buffer);
- break;
- }
- case VAR_STRING:
- debug_print_quoted (vt_rvalue.string);
- break;
- default:
- if_print_debug ("[Unknown]");
- break;
- }
- }
- else
- if_print_debug ("[Unknown]");
- if_print_debug_character ('\n');
+debug_dump_variable(sc_gameref_t game, sc_int variable) {
+ 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], vt_rvalue;
+ const sc_char *name;
+ sc_int var_type;
+
+ debug_print_variable(game, variable);
+ if_print_debug_character('\n');
+
+ vt_key[0].string = "Variables";
+ vt_key[1].integer = variable;
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ if_print_debug(" Value = ");
+ if (var_get(vars, name, &var_type, &vt_rvalue)) {
+ switch (var_type) {
+ case VAR_INTEGER: {
+ sc_char buffer[32];
+
+ sprintf(buffer, "%ld", vt_rvalue.integer);
+ if_print_debug(buffer);
+ break;
+ }
+ case VAR_STRING:
+ debug_print_quoted(vt_rvalue.string);
+ break;
+ default:
+ if_print_debug("[Unknown]");
+ break;
+ }
+ } else
+ if_print_debug("[Unknown]");
+ if_print_debug_character('\n');
}
@@ -1432,142 +1359,131 @@ debug_dump_variable (sc_gameref_t game, sc_int variable)
* Common handler for iterating dumps of classes.
*/
static void
-debug_dump_common (sc_gameref_t game, sc_command_t command,
- sc_command_type_t type, sc_int arg1, sc_int arg2)
-{
- sc_int low = arg1, high = arg2;
- sc_int limit, index_;
- const sc_char *class_;
- sc_bool (*filter_function) (sc_gameref_t, sc_int);
- void (*dumper_function) (sc_gameref_t, sc_int);
- sc_bool printed = FALSE;
-
- /* Initialize variables to avoid gcc warnings. */
- limit = 0;
- class_ = NULL;
- filter_function = NULL;
- dumper_function = NULL;
-
- /* Switch to undo game on relevant commands. */
- switch (command)
- {
- case DEBUG_OLDROOMS:
- case DEBUG_OLDOBJECTS:
- case DEBUG_OLDNPCS:
- case DEBUG_OLDEVENTS:
- case DEBUG_OLDTASKS:
- case DEBUG_OLDVARIABLES:
- if (!game->undo_available)
- {
- if_print_debug ("There is no previous game state to examine.\n");
- return;
- }
-
- game = game->undo;
- assert (gs_is_game_valid (game));
- break;
-
- default:
- break;
- }
-
- /* Demultiplex dump command. */
- switch (command)
- {
- case DEBUG_ROOMS:
- case DEBUG_OLDROOMS:
- class_ = "Room";
- filter_function = debug_filter_room;
- dumper_function = debug_dump_room;
- limit = gs_room_count (game);
- break;
- case DEBUG_OBJECTS:
- case DEBUG_OLDOBJECTS:
- class_ = "Object";
- filter_function = debug_filter_object;
- dumper_function = debug_dump_object;
- limit = gs_object_count (game);
- break;
- case DEBUG_NPCS:
- case DEBUG_OLDNPCS:
- class_ = "NPC";
- filter_function = debug_filter_npc;
- dumper_function = debug_dump_npc;
- limit = gs_npc_count (game);
- break;
- case DEBUG_EVENTS:
- case DEBUG_OLDEVENTS:
- class_ = "Event";
- filter_function = debug_filter_event;
- dumper_function = debug_dump_event;
- limit = gs_event_count (game);
- break;
- case DEBUG_TASKS:
- case DEBUG_OLDTASKS:
- class_ = "Task";
- filter_function = debug_filter_task;
- dumper_function = debug_dump_task;
- limit = gs_task_count (game);
- break;
- case DEBUG_VARIABLES:
- case DEBUG_OLDVARIABLES:
- class_ = "Variable";
- filter_function = NULL;
- dumper_function = debug_dump_variable;
- limit = debug_variable_count (game);
- break;
- default:
- sc_fatal ("debug_dump_common: invalid command\n");
- }
-
- /* Normalize to this limit. */
- if (!debug_normalize_arguments (type, &low, &high, limit))
- {
- if (limit == 0)
- {
- if_print_debug ("There is nothing of type ");
- debug_print_quoted (class_);
- if_print_debug (" to print.\n");
- }
- else
- {
- if_print_debug ("Invalid item or range for ");
- debug_print_quoted (class_);
- if (limit == 1)
- if_print_debug ("; only 0 is valid.\n");
- else
- {
- sc_char buffer[32];
-
- if_print_debug ("; valid values are 0 to ");
- sprintf (buffer, "%ld", limit - 1);
- if_print_debug (buffer);
- if_print_debug (".\n");
- }
- }
- return;
- }
-
- /* Print each item of the class, filtering on query commands. */
- for (index_ = low; index_ <= high; index_++)
- {
- if (type == COMMAND_QUERY
- && filter_function && !filter_function (game, index_))
- continue;
-
- if (printed)
- if_print_debug_character ('\n');
- dumper_function (game, index_);
- printed = TRUE;
- }
- if (!printed)
- {
- if_print_debug ("Nothing of type ");
- debug_print_quoted (class_);
- if_print_debug (" is relevant.\nTry \"");
- if_print_debug (class_);
- if_print_debug (" *\" to show all items of this type.\n");
- }
+debug_dump_common(sc_gameref_t game, sc_command_t command,
+ sc_command_type_t type, sc_int arg1, sc_int arg2) {
+ sc_int low = arg1, high = arg2;
+ sc_int limit, index_;
+ const sc_char *class_;
+ sc_bool(*filter_function)(sc_gameref_t, sc_int);
+ void (*dumper_function)(sc_gameref_t, sc_int);
+ sc_bool printed = FALSE;
+
+ /* Initialize variables to avoid gcc warnings. */
+ limit = 0;
+ class_ = NULL;
+ filter_function = NULL;
+ dumper_function = NULL;
+
+ /* Switch to undo game on relevant commands. */
+ switch (command) {
+ case DEBUG_OLDROOMS:
+ case DEBUG_OLDOBJECTS:
+ case DEBUG_OLDNPCS:
+ case DEBUG_OLDEVENTS:
+ case DEBUG_OLDTASKS:
+ case DEBUG_OLDVARIABLES:
+ if (!game->undo_available) {
+ if_print_debug("There is no previous game state to examine.\n");
+ return;
+ }
+
+ game = game->undo;
+ assert(gs_is_game_valid(game));
+ break;
+
+ default:
+ break;
+ }
+
+ /* Demultiplex dump command. */
+ switch (command) {
+ case DEBUG_ROOMS:
+ case DEBUG_OLDROOMS:
+ class_ = "Room";
+ filter_function = debug_filter_room;
+ dumper_function = debug_dump_room;
+ limit = gs_room_count(game);
+ break;
+ case DEBUG_OBJECTS:
+ case DEBUG_OLDOBJECTS:
+ class_ = "Object";
+ filter_function = debug_filter_object;
+ dumper_function = debug_dump_object;
+ limit = gs_object_count(game);
+ break;
+ case DEBUG_NPCS:
+ case DEBUG_OLDNPCS:
+ class_ = "NPC";
+ filter_function = debug_filter_npc;
+ dumper_function = debug_dump_npc;
+ limit = gs_npc_count(game);
+ break;
+ case DEBUG_EVENTS:
+ case DEBUG_OLDEVENTS:
+ class_ = "Event";
+ filter_function = debug_filter_event;
+ dumper_function = debug_dump_event;
+ limit = gs_event_count(game);
+ break;
+ case DEBUG_TASKS:
+ case DEBUG_OLDTASKS:
+ class_ = "Task";
+ filter_function = debug_filter_task;
+ dumper_function = debug_dump_task;
+ limit = gs_task_count(game);
+ break;
+ case DEBUG_VARIABLES:
+ case DEBUG_OLDVARIABLES:
+ class_ = "Variable";
+ filter_function = NULL;
+ dumper_function = debug_dump_variable;
+ limit = debug_variable_count(game);
+ break;
+ default:
+ sc_fatal("debug_dump_common: invalid command\n");
+ }
+
+ /* Normalize to this limit. */
+ if (!debug_normalize_arguments(type, &low, &high, limit)) {
+ if (limit == 0) {
+ if_print_debug("There is nothing of type ");
+ debug_print_quoted(class_);
+ if_print_debug(" to print.\n");
+ } else {
+ if_print_debug("Invalid item or range for ");
+ debug_print_quoted(class_);
+ if (limit == 1)
+ if_print_debug("; only 0 is valid.\n");
+ else {
+ sc_char buffer[32];
+
+ if_print_debug("; valid values are 0 to ");
+ sprintf(buffer, "%ld", limit - 1);
+ if_print_debug(buffer);
+ if_print_debug(".\n");
+ }
+ }
+ return;
+ }
+
+ /* Print each item of the class, filtering on query commands. */
+ for (index_ = low; index_ <= high; index_++) {
+ if (type == COMMAND_QUERY
+ && filter_function && !filter_function(game, index_))
+ continue;
+
+ if (printed)
+ if_print_debug_character('\n');
+ dumper_function(game, index_);
+ printed = TRUE;
+ }
+ if (!printed) {
+ if_print_debug("Nothing of type ");
+ debug_print_quoted(class_);
+ if_print_debug(" is relevant.\nTry \"");
+ if_print_debug(class_);
+ if_print_debug(" *\" to show all items of this type.\n");
+ }
}
@@ -1577,22 +1493,20 @@ debug_dump_common (sc_gameref_t game, sc_command_t command,
* Print the current raw printfilter contents.
*/
static void
-debug_buffer (sc_gameref_t game, sc_command_type_t type)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_char *buffer;
-
- if (type != COMMAND_QUERY)
- {
- if_print_debug ("The Buffer command takes no arguments.\n");
- return;
- }
-
- buffer = pf_get_buffer (filter);
- if (buffer)
- if_print_debug (buffer);
- else
- if_print_debug ("There is no game text buffered.\n");
+debug_buffer(sc_gameref_t game, sc_command_type_t type) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_char *buffer;
+
+ if (type != COMMAND_QUERY) {
+ if_print_debug("The Buffer command takes no arguments.\n");
+ return;
+ }
+
+ buffer = pf_get_buffer(filter);
+ if (buffer)
+ if_print_debug(buffer);
+ else
+ if_print_debug("There is no game text buffered.\n");
}
@@ -1602,17 +1516,16 @@ debug_buffer (sc_gameref_t game, sc_command_type_t type)
* Helper for debug_resources().
*/
static void
-debug_print_resource (const sc_resource_t *resource)
-{
- sc_char buffer[32];
-
- debug_print_quoted (resource->name);
- if_print_debug (", offset ");
- sprintf (buffer, "%ld", resource->offset);
- if_print_debug (buffer);
- if_print_debug (", length ");
- sprintf (buffer, "%ld", resource->length);
- if_print_debug (buffer);
+debug_print_resource(const sc_resource_t *resource) {
+ sc_char buffer[32];
+
+ debug_print_quoted(resource->name);
+ if_print_debug(", offset ");
+ sprintf(buffer, "%ld", resource->offset);
+ if_print_debug(buffer);
+ if_print_debug(", length ");
+ sprintf(buffer, "%ld", resource->length);
+ if_print_debug(buffer);
}
@@ -1622,61 +1535,54 @@ debug_print_resource (const sc_resource_t *resource)
* Print any active and requested resources.
*/
static void
-debug_resources (sc_gameref_t game, sc_command_type_t type)
-{
- sc_bool printed = FALSE;
-
- if (type != COMMAND_QUERY)
- {
- if_print_debug ("The Resources command takes no arguments.\n");
- return;
- }
-
- if (game->stop_sound)
- {
- if_print_debug ("Sound stop");
- if (strlen (game->requested_sound.name) > 0)
- if_print_debug (" before new sound");
- if_print_debug (" requested");
- if (game->sound_active)
- if_print_debug (", sound active");
- if_print_debug (".\n");
- printed = TRUE;
- }
- if (!res_compare_resource (&game->requested_sound,
- &game->playing_sound))
- {
- if_print_debug ("Requested Sound ");
- debug_print_resource (&game->requested_sound);
- if_print_debug (".\n");
- printed = TRUE;
- }
- if (!res_compare_resource (&game->requested_graphic,
- &game->displayed_graphic))
- {
- if_print_debug ("Requested Graphic ");
- debug_print_resource (&game->requested_graphic);
- if_print_debug (".\n");
- printed = TRUE;
- }
-
- if (strlen (game->playing_sound.name) > 0)
- {
- if_print_debug ("Playing Sound ");
- debug_print_resource (&game->playing_sound);
- if_print_debug (".\n");
- printed = TRUE;
- }
- if (strlen (game->displayed_graphic.name) > 0)
- {
- if_print_debug ("Displaying Graphic ");
- debug_print_resource (&game->displayed_graphic);
- if_print_debug (".\n");
- printed = TRUE;
- }
-
- if (!printed)
- if_print_debug ("There is no game resource activity.\n");
+debug_resources(sc_gameref_t game, sc_command_type_t type) {
+ sc_bool printed = FALSE;
+
+ if (type != COMMAND_QUERY) {
+ if_print_debug("The Resources command takes no arguments.\n");
+ return;
+ }
+
+ if (game->stop_sound) {
+ if_print_debug("Sound stop");
+ if (strlen(game->requested_sound.name) > 0)
+ if_print_debug(" before new sound");
+ if_print_debug(" requested");
+ if (game->sound_active)
+ if_print_debug(", sound active");
+ if_print_debug(".\n");
+ printed = TRUE;
+ }
+ if (!res_compare_resource(&game->requested_sound,
+ &game->playing_sound)) {
+ if_print_debug("Requested Sound ");
+ debug_print_resource(&game->requested_sound);
+ if_print_debug(".\n");
+ printed = TRUE;
+ }
+ if (!res_compare_resource(&game->requested_graphic,
+ &game->displayed_graphic)) {
+ if_print_debug("Requested Graphic ");
+ debug_print_resource(&game->requested_graphic);
+ if_print_debug(".\n");
+ printed = TRUE;
+ }
+
+ if (strlen(game->playing_sound.name) > 0) {
+ if_print_debug("Playing Sound ");
+ debug_print_resource(&game->playing_sound);
+ if_print_debug(".\n");
+ printed = TRUE;
+ }
+ if (strlen(game->displayed_graphic.name) > 0) {
+ if_print_debug("Displaying Graphic ");
+ debug_print_resource(&game->displayed_graphic);
+ if_print_debug(".\n");
+ printed = TRUE;
+ }
+
+ if (!printed)
+ if_print_debug("There is no game resource activity.\n");
}
@@ -1687,42 +1593,38 @@ debug_resources (sc_gameref_t game, sc_command_type_t type)
* given value.
*/
static void
-debug_random (sc_command_type_t type, sc_int new_seed)
-{
- const sc_char *random_type;
- sc_char buffer[32];
-
- if (type != COMMAND_ONE && type != COMMAND_QUERY)
- {
- if_print_debug ("The Random command takes either one argument or"
- " no arguments.\n");
- return;
- }
-
- random_type = sc_is_congruential_random () ? "congruential" : "platform";
-
- if (type == COMMAND_QUERY)
- {
- if_print_debug ("The ");
- if_print_debug (random_type);
- if_print_debug (" random number generator is selected.\n");
- return;
- }
-
- if (new_seed == 0)
- {
- if_print_debug ("The seed value may not be zero.\n");
- return;
- }
-
- sc_seed_random (new_seed);
-
- if_print_debug ("Set seed ");
- sprintf (buffer, "%ld", new_seed);
- if_print_debug (buffer);
- if_print_debug (" for the ");
- if_print_debug (random_type);
- if_print_debug (" random number generator.\n");
+debug_random(sc_command_type_t type, sc_int new_seed) {
+ const sc_char *random_type;
+ sc_char buffer[32];
+
+ if (type != COMMAND_ONE && type != COMMAND_QUERY) {
+ if_print_debug("The Random command takes either one argument or"
+ " no arguments.\n");
+ return;
+ }
+
+ random_type = sc_is_congruential_random() ? "congruential" : "platform";
+
+ if (type == COMMAND_QUERY) {
+ if_print_debug("The ");
+ if_print_debug(random_type);
+ if_print_debug(" random number generator is selected.\n");
+ return;
+ }
+
+ if (new_seed == 0) {
+ if_print_debug("The seed value may not be zero.\n");
+ return;
+ }
+
+ sc_seed_random(new_seed);
+
+ if_print_debug("Set seed ");
+ sprintf(buffer, "%ld", new_seed);
+ if_print_debug(buffer);
+ if_print_debug(" for the ");
+ if_print_debug(random_type);
+ if_print_debug(" random number generator.\n");
}
@@ -1732,184 +1634,165 @@ debug_random (sc_command_type_t type, sc_int new_seed)
* Common handler for setting and clearing watchpoints.
*/
static void
-debug_watchpoint_common (sc_gameref_t game, sc_command_t command,
- sc_command_type_t type, sc_int arg1, sc_int arg2)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
- sc_int low = arg1, high = arg2;
- sc_int limit, index_;
- const sc_char *class_;
- sc_bool *watchpoints, action;
- sc_char buffer[32];
- assert (debug_is_valid (debug));
-
- /* Initialize variables to avoid gcc warnings. */
- limit = 0;
- class_ = NULL;
- watchpoints = NULL;
- action = FALSE;
-
- /* Set action to TRUE or FALSE, for setting/clearing watchpoints. */
- switch (command)
- {
- case DEBUG_WATCHPLAYER:
- case DEBUG_WATCHOBJECTS:
- case DEBUG_WATCHNPCS:
- case DEBUG_WATCHEVENTS:
- case DEBUG_WATCHTASKS:
- case DEBUG_WATCHVARIABLES:
- action = TRUE;
- break;
- case DEBUG_CLEARPLAYER:
- case DEBUG_CLEAROBJECTS:
- case DEBUG_CLEARNPCS:
- case DEBUG_CLEAREVENTS:
- case DEBUG_CLEARTASKS:
- case DEBUG_CLEARVARIABLES:
- action = FALSE;
- break;
- default:
- sc_fatal ("debug_watchpoint_common: invalid command\n");
- }
-
- /* Handle player watchpoint setting. */
- if (command == DEBUG_WATCHPLAYER || command == DEBUG_CLEARPLAYER)
- {
- if (command == DEBUG_CLEARPLAYER)
- {
- debug->watch_player = action;
- if_print_debug ("Cleared Player watchpoint.\n");
- }
- else if (type == COMMAND_ONE && arg1 == 0)
- {
- debug->watch_player = action;
- if_print_debug ("Set Player watchpoint.\n");
- }
- else
- {
- if (debug->watch_player)
- if_print_debug ("Player watchpoint is set.\n");
- else
- if_print_debug ("No Player watchpoint is set; to set one, use"
- " \"Watchplayer 0\".\n");
- }
- return;
- }
-
- /* Demultiplex watchpoint command. */
- switch (command)
- {
- case DEBUG_WATCHOBJECTS:
- case DEBUG_CLEAROBJECTS:
- class_ = "Object";
- watchpoints = debug->watch_objects;
- limit = gs_object_count (game);
- break;
- case DEBUG_WATCHNPCS:
- case DEBUG_CLEARNPCS:
- class_ = "NPC";
- watchpoints = debug->watch_npcs;
- limit = gs_npc_count (game);
- break;
- case DEBUG_WATCHEVENTS:
- case DEBUG_CLEAREVENTS:
- class_ = "Event";
- watchpoints = debug->watch_events;
- limit = gs_event_count (game);
- break;
- case DEBUG_WATCHTASKS:
- case DEBUG_CLEARTASKS:
- class_ = "Task";
- watchpoints = debug->watch_tasks;
- limit = gs_task_count (game);
- break;
- case DEBUG_WATCHVARIABLES:
- case DEBUG_CLEARVARIABLES:
- class_ = "Variable";
- watchpoints = debug->watch_variables;
- limit = debug_variable_count (game);
- break;
- default:
- sc_fatal ("debug_watchpoint_common: invalid command\n");
- }
-
- /* Normalize to this limit. */
- if (!debug_normalize_arguments (type, &low, &high, limit))
- {
- if (limit == 0)
- {
- if_print_debug ("There is nothing of type ");
- debug_print_quoted (class_);
- if_print_debug (" to watch.\n");
- }
- else
- {
- if_print_debug ("Invalid item or range for ");
- debug_print_quoted (class_);
- if (limit == 1)
- if_print_debug ("; only 0 is valid.\n");
- else
- {
- if_print_debug ("; valid values are 0 to ");
- sprintf (buffer, "%ld", limit - 1);
- if_print_debug (buffer);
- if_print_debug (".\n");
- }
- }
- return;
- }
-
- /* On query, search the array for set flags, and print out. */
- if (type == COMMAND_QUERY)
- {
- sc_bool printed = FALSE;
-
- /* Scan for set watchpoints, and list each found. */
- for (index_ = low; index_ <= high; index_++)
- {
- if (watchpoints[index_])
- {
- if (!printed)
- {
- if_print_debug ("Watchpoints are set for ");
- if_print_debug (class_);
- if_print_debug (" { ");
- }
- sprintf (buffer, "%ld", index_);
- if_print_debug (buffer);
- if_print_debug_character (' ');
- printed = TRUE;
- }
- }
- if (printed)
- if_print_debug ("}.\n");
- else
- {
- if_print_debug ("No ");
- if_print_debug (class_);
- if_print_debug (" watchpoints are set.\n");
- }
- return;
- }
-
- /*
- * For non-queries, set watchpoint flags as defined in action for
- * the range determined, and print confirmation.
- */
- for (index_ = low; index_ <= high; index_++)
- watchpoints[index_] = action;
-
- if (action)
- if_print_debug ("Set ");
- else
- if_print_debug ("Cleared ");
- sprintf (buffer, "%ld ", high - low + 1);
- if_print_debug (buffer);
- if_print_debug (class_);
- if (high == low)
- if_print_debug (" watchpoint.\n");
- else
- if_print_debug (" watchpoints.\n");
+debug_watchpoint_common(sc_gameref_t game, sc_command_t command,
+ sc_command_type_t type, sc_int arg1, sc_int arg2) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+ sc_int low = arg1, high = arg2;
+ sc_int limit, index_;
+ const sc_char *class_;
+ sc_bool *watchpoints, action;
+ sc_char buffer[32];
+ assert(debug_is_valid(debug));
+
+ /* Initialize variables to avoid gcc warnings. */
+ limit = 0;
+ class_ = NULL;
+ watchpoints = NULL;
+ action = FALSE;
+
+ /* Set action to TRUE or FALSE, for setting/clearing watchpoints. */
+ switch (command) {
+ case DEBUG_WATCHPLAYER:
+ case DEBUG_WATCHOBJECTS:
+ case DEBUG_WATCHNPCS:
+ case DEBUG_WATCHEVENTS:
+ case DEBUG_WATCHTASKS:
+ case DEBUG_WATCHVARIABLES:
+ action = TRUE;
+ break;
+ case DEBUG_CLEARPLAYER:
+ case DEBUG_CLEAROBJECTS:
+ case DEBUG_CLEARNPCS:
+ case DEBUG_CLEAREVENTS:
+ case DEBUG_CLEARTASKS:
+ case DEBUG_CLEARVARIABLES:
+ action = FALSE;
+ break;
+ default:
+ sc_fatal("debug_watchpoint_common: invalid command\n");
+ }
+
+ /* Handle player watchpoint setting. */
+ if (command == DEBUG_WATCHPLAYER || command == DEBUG_CLEARPLAYER) {
+ if (command == DEBUG_CLEARPLAYER) {
+ debug->watch_player = action;
+ if_print_debug("Cleared Player watchpoint.\n");
+ } else if (type == COMMAND_ONE && arg1 == 0) {
+ debug->watch_player = action;
+ if_print_debug("Set Player watchpoint.\n");
+ } else {
+ if (debug->watch_player)
+ if_print_debug("Player watchpoint is set.\n");
+ else
+ if_print_debug("No Player watchpoint is set; to set one, use"
+ " \"Watchplayer 0\".\n");
+ }
+ return;
+ }
+
+ /* Demultiplex watchpoint command. */
+ switch (command) {
+ case DEBUG_WATCHOBJECTS:
+ case DEBUG_CLEAROBJECTS:
+ class_ = "Object";
+ watchpoints = debug->watch_objects;
+ limit = gs_object_count(game);
+ break;
+ case DEBUG_WATCHNPCS:
+ case DEBUG_CLEARNPCS:
+ class_ = "NPC";
+ watchpoints = debug->watch_npcs;
+ limit = gs_npc_count(game);
+ break;
+ case DEBUG_WATCHEVENTS:
+ case DEBUG_CLEAREVENTS:
+ class_ = "Event";
+ watchpoints = debug->watch_events;
+ limit = gs_event_count(game);
+ break;
+ case DEBUG_WATCHTASKS:
+ case DEBUG_CLEARTASKS:
+ class_ = "Task";
+ watchpoints = debug->watch_tasks;
+ limit = gs_task_count(game);
+ break;
+ case DEBUG_WATCHVARIABLES:
+ case DEBUG_CLEARVARIABLES:
+ class_ = "Variable";
+ watchpoints = debug->watch_variables;
+ limit = debug_variable_count(game);
+ break;
+ default:
+ sc_fatal("debug_watchpoint_common: invalid command\n");
+ }
+
+ /* Normalize to this limit. */
+ if (!debug_normalize_arguments(type, &low, &high, limit)) {
+ if (limit == 0) {
+ if_print_debug("There is nothing of type ");
+ debug_print_quoted(class_);
+ if_print_debug(" to watch.\n");
+ } else {
+ if_print_debug("Invalid item or range for ");
+ debug_print_quoted(class_);
+ if (limit == 1)
+ if_print_debug("; only 0 is valid.\n");
+ else {
+ if_print_debug("; valid values are 0 to ");
+ sprintf(buffer, "%ld", limit - 1);
+ if_print_debug(buffer);
+ if_print_debug(".\n");
+ }
+ }
+ return;
+ }
+
+ /* On query, search the array for set flags, and print out. */
+ if (type == COMMAND_QUERY) {
+ sc_bool printed = FALSE;
+
+ /* Scan for set watchpoints, and list each found. */
+ for (index_ = low; index_ <= high; index_++) {
+ if (watchpoints[index_]) {
+ if (!printed) {
+ if_print_debug("Watchpoints are set for ");
+ if_print_debug(class_);
+ if_print_debug(" { ");
+ }
+ sprintf(buffer, "%ld", index_);
+ if_print_debug(buffer);
+ if_print_debug_character(' ');
+ printed = TRUE;
+ }
+ }
+ if (printed)
+ if_print_debug("}.\n");
+ else {
+ if_print_debug("No ");
+ if_print_debug(class_);
+ if_print_debug(" watchpoints are set.\n");
+ }
+ return;
+ }
+
+ /*
+ * For non-queries, set watchpoint flags as defined in action for
+ * the range determined, and print confirmation.
+ */
+ for (index_ = low; index_ <= high; index_++)
+ watchpoints[index_] = action;
+
+ if (action)
+ if_print_debug("Set ");
+ else
+ if_print_debug("Cleared ");
+ sprintf(buffer, "%ld ", high - low + 1);
+ if_print_debug(buffer);
+ if_print_debug(class_);
+ if (high == low)
+ if_print_debug(" watchpoint.\n");
+ else
+ if_print_debug(" watchpoints.\n");
}
@@ -1919,53 +1802,50 @@ debug_watchpoint_common (sc_gameref_t game, sc_command_t command,
* Common handler to list out and clear all set watchpoints at a stroke.
*/
static void
-debug_watchall_common (sc_gameref_t game,
- sc_command_t command, sc_command_type_t type)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
- assert (debug_is_valid (debug));
-
- if (type != COMMAND_QUERY)
- {
- if (command == DEBUG_WATCHALL)
- if_print_debug ("The Watchall command takes no arguments.\n");
- else
- if_print_debug ("The Clearall command takes no arguments.\n");
- return;
- }
-
- /* Query all set watchpoints using common watchpoint handler... */
- if (command == DEBUG_WATCHALL)
- {
- debug_watchpoint_common (game,
- DEBUG_WATCHPLAYER, COMMAND_QUERY, 0, 0);
- debug_watchpoint_common (game,
- DEBUG_WATCHOBJECTS, COMMAND_QUERY, 0, 0);
- debug_watchpoint_common (game,
- DEBUG_WATCHNPCS, COMMAND_QUERY, 0, 0);
- debug_watchpoint_common (game,
- DEBUG_WATCHEVENTS, COMMAND_QUERY, 0, 0);
- debug_watchpoint_common (game,
- DEBUG_WATCHTASKS, COMMAND_QUERY, 0, 0);
- debug_watchpoint_common (game,
- DEBUG_WATCHVARIABLES, COMMAND_QUERY, 0, 0);
- return;
- }
-
- /* ...but reset all the fast way, with memset(). */
- assert (command == DEBUG_CLEARALL);
- debug->watch_player = FALSE;
- memset (debug->watch_objects, FALSE,
- gs_object_count (game) * sizeof (*debug->watch_objects));
- memset (debug->watch_npcs, FALSE,
- gs_npc_count (game) * sizeof (*debug->watch_npcs));
- memset (debug->watch_events, FALSE,
- gs_event_count (game) * sizeof (*debug->watch_events));
- memset (debug->watch_tasks, FALSE,
- gs_task_count (game) * sizeof (*debug->watch_tasks));
- memset (debug->watch_variables, FALSE,
- debug_variable_count (game) * sizeof (*debug->watch_variables));
- if_print_debug ("Cleared all watchpoints.\n");
+debug_watchall_common(sc_gameref_t game,
+ sc_command_t command, sc_command_type_t type) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+ assert(debug_is_valid(debug));
+
+ if (type != COMMAND_QUERY) {
+ if (command == DEBUG_WATCHALL)
+ if_print_debug("The Watchall command takes no arguments.\n");
+ else
+ if_print_debug("The Clearall command takes no arguments.\n");
+ return;
+ }
+
+ /* Query all set watchpoints using common watchpoint handler... */
+ if (command == DEBUG_WATCHALL) {
+ debug_watchpoint_common(game,
+ DEBUG_WATCHPLAYER, COMMAND_QUERY, 0, 0);
+ debug_watchpoint_common(game,
+ DEBUG_WATCHOBJECTS, COMMAND_QUERY, 0, 0);
+ debug_watchpoint_common(game,
+ DEBUG_WATCHNPCS, COMMAND_QUERY, 0, 0);
+ debug_watchpoint_common(game,
+ DEBUG_WATCHEVENTS, COMMAND_QUERY, 0, 0);
+ debug_watchpoint_common(game,
+ DEBUG_WATCHTASKS, COMMAND_QUERY, 0, 0);
+ debug_watchpoint_common(game,
+ DEBUG_WATCHVARIABLES, COMMAND_QUERY, 0, 0);
+ return;
+ }
+
+ /* ...but reset all the fast way, with memset(). */
+ assert(command == DEBUG_CLEARALL);
+ debug->watch_player = FALSE;
+ memset(debug->watch_objects, FALSE,
+ gs_object_count(game) * sizeof(*debug->watch_objects));
+ memset(debug->watch_npcs, FALSE,
+ gs_npc_count(game) * sizeof(*debug->watch_npcs));
+ memset(debug->watch_events, FALSE,
+ gs_event_count(game) * sizeof(*debug->watch_events));
+ memset(debug->watch_tasks, FALSE,
+ gs_task_count(game) * sizeof(*debug->watch_tasks));
+ memset(debug->watch_variables, FALSE,
+ debug_variable_count(game) * sizeof(*debug->watch_variables));
+ if_print_debug("Cleared all watchpoints.\n");
}
@@ -1975,18 +1855,17 @@ debug_watchall_common (sc_gameref_t game,
* Compare two objects, and return TRUE if the same.
*/
static sc_bool
-debug_compare_object (sc_gameref_t from, sc_gameref_t with, sc_int object)
-{
- const sc_objectstate_t *from_object = from->objects + object;
- const sc_objectstate_t *with_object = with->objects + object;
-
- return from_object->unmoved == with_object->unmoved
- && from_object->static_unmoved == with_object->static_unmoved
- && from_object->position == with_object->position
- && from_object->parent == with_object->parent
- && from_object->openness == with_object->openness
- && from_object->state == with_object->state
- && from_object->seen == with_object->seen;
+debug_compare_object(sc_gameref_t from, sc_gameref_t with, sc_int object) {
+ const sc_objectstate_t *from_object = from->objects + object;
+ const sc_objectstate_t *with_object = with->objects + object;
+
+ return from_object->unmoved == with_object->unmoved
+ && from_object->static_unmoved == with_object->static_unmoved
+ && from_object->position == with_object->position
+ && from_object->parent == with_object->parent
+ && from_object->openness == with_object->openness
+ && from_object->state == with_object->state
+ && from_object->seen == with_object->seen;
}
@@ -1996,21 +1875,20 @@ debug_compare_object (sc_gameref_t from, sc_gameref_t with, sc_int object)
* Compare two NPCs, and return TRUE if the same.
*/
static sc_bool
-debug_compare_npc (sc_gameref_t from, sc_gameref_t with, sc_int npc)
-{
- const sc_npcstate_t *from_npc = from->npcs + npc;
- const sc_npcstate_t *with_npc = with->npcs + npc;
-
- if (from_npc->walkstep_count != with_npc->walkstep_count)
- sc_fatal ("debug_compare_npc: walkstep count error\n");
-
- return from_npc->location == with_npc->location
- && from_npc->position == with_npc->position
- && from_npc->parent == with_npc->parent
- && from_npc->seen == with_npc->seen
- && memcmp (from_npc->walksteps, with_npc->walksteps,
- from_npc->walkstep_count
- * sizeof (*from_npc->walksteps)) == 0;
+debug_compare_npc(sc_gameref_t from, sc_gameref_t with, sc_int npc) {
+ const sc_npcstate_t *from_npc = from->npcs + npc;
+ const sc_npcstate_t *with_npc = with->npcs + npc;
+
+ if (from_npc->walkstep_count != with_npc->walkstep_count)
+ sc_fatal("debug_compare_npc: walkstep count error\n");
+
+ return from_npc->location == with_npc->location
+ && from_npc->position == with_npc->position
+ && from_npc->parent == with_npc->parent
+ && from_npc->seen == with_npc->seen
+ && memcmp(from_npc->walksteps, with_npc->walksteps,
+ from_npc->walkstep_count
+ * sizeof(*from_npc->walksteps)) == 0;
}
@@ -2020,13 +1898,12 @@ debug_compare_npc (sc_gameref_t from, sc_gameref_t with, sc_int npc)
* Compare two events, and return TRUE if the same.
*/
static sc_bool
-debug_compare_event (sc_gameref_t from, sc_gameref_t with, sc_int event)
-{
- const sc_eventstate_t *from_event = from->events + event;
- const sc_eventstate_t *with_event = with->events + event;
+debug_compare_event(sc_gameref_t from, sc_gameref_t with, sc_int event) {
+ const sc_eventstate_t *from_event = from->events + event;
+ const sc_eventstate_t *with_event = with->events + event;
- return from_event->state == with_event->state
- && from_event->time == with_event->time;
+ return from_event->state == with_event->state
+ && from_event->time == with_event->time;
}
@@ -2036,13 +1913,12 @@ debug_compare_event (sc_gameref_t from, sc_gameref_t with, sc_int event)
* Compare two tasks, and return TRUE if the same.
*/
static sc_bool
-debug_compare_task (sc_gameref_t from, sc_gameref_t with, sc_int task)
-{
- const sc_taskstate_t *from_task = from->tasks + task;
- const sc_taskstate_t *with_task = with->tasks + task;
+debug_compare_task(sc_gameref_t from, sc_gameref_t with, sc_int task) {
+ const sc_taskstate_t *from_task = from->tasks + task;
+ const sc_taskstate_t *with_task = with->tasks + task;
- return from_task->done == with_task->done
- && from_task->scored == with_task->scored;
+ return from_task->done == with_task->done
+ && from_task->scored == with_task->scored;
}
@@ -2052,44 +1928,42 @@ debug_compare_task (sc_gameref_t from, sc_gameref_t with, sc_int task)
* Compare two variables, and return TRUE if the same.
*/
static sc_bool
-debug_compare_variable (sc_gameref_t from, sc_gameref_t with, sc_int variable)
-{
- const sc_prop_setref_t bundle = from->bundle;
- const sc_var_setref_t from_var = from->vars;
- const sc_var_setref_t with_var = with->vars;
- sc_vartype_t vt_key[3], vt_rvalue, vt_rvalue2;
- const sc_char *name;
- sc_int var_type, var_type2;
- sc_bool equal = FALSE;
-
- if (from->bundle != with->bundle)
- sc_fatal ("debug_compare_variable: property sharing malfunction\n");
-
- vt_key[0].string = "Variables";
- vt_key[1].integer = variable;
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- if (!var_get (from_var, name, &var_type, &vt_rvalue)
- || !var_get (with_var, name, &var_type2, &vt_rvalue2))
- sc_fatal ("debug_compare_variable: can't find variable %s\n", name);
- else if (var_type != var_type2)
- sc_fatal ("debug_compare_variable: variable type mismatch %s\n", name);
-
- switch (var_type)
- {
- case VAR_INTEGER:
- equal = (vt_rvalue.integer == vt_rvalue2.integer);
- break;
- case VAR_STRING:
- equal = !strcmp (vt_rvalue.string, vt_rvalue2.string);
- break;
- default:
- sc_fatal ("debug_compare_variable:"
- " invalid variable type, %ld\n", var_type);
- }
-
- return equal;
+debug_compare_variable(sc_gameref_t from, sc_gameref_t with, sc_int variable) {
+ const sc_prop_setref_t bundle = from->bundle;
+ const sc_var_setref_t from_var = from->vars;
+ const sc_var_setref_t with_var = with->vars;
+ sc_vartype_t vt_key[3], vt_rvalue, vt_rvalue2;
+ const sc_char *name;
+ sc_int var_type, var_type2;
+ sc_bool equal = FALSE;
+
+ if (from->bundle != with->bundle)
+ sc_fatal("debug_compare_variable: property sharing malfunction\n");
+
+ vt_key[0].string = "Variables";
+ vt_key[1].integer = variable;
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ if (!var_get(from_var, name, &var_type, &vt_rvalue)
+ || !var_get(with_var, name, &var_type2, &vt_rvalue2))
+ sc_fatal("debug_compare_variable: can't find variable %s\n", name);
+ else if (var_type != var_type2)
+ sc_fatal("debug_compare_variable: variable type mismatch %s\n", name);
+
+ switch (var_type) {
+ case VAR_INTEGER:
+ equal = (vt_rvalue.integer == vt_rvalue2.integer);
+ break;
+ case VAR_STRING:
+ equal = !strcmp(vt_rvalue.string, vt_rvalue2.string);
+ break;
+ default:
+ sc_fatal("debug_compare_variable:"
+ " invalid variable type, %ld\n", var_type);
+ }
+
+ return equal;
}
@@ -2102,44 +1976,40 @@ debug_compare_variable (sc_gameref_t from, sc_gameref_t with, sc_int variable)
* if any differed.
*/
static sc_bool
-debug_check_class (sc_gameref_t from, sc_gameref_t with,
- const sc_char *class_, sc_int class_count,
- const sc_bool *watchpoints,
- sc_bool (*const compare_function)
- (sc_gameref_t, sc_gameref_t, sc_int))
-{
- sc_int index_;
- sc_bool triggered = FALSE;
-
- /*
- * Scan the watchpoints array for set watchpoints, comparing classes
- * where the watchpoint flag is set.
- */
- for (index_ = 0; index_ < class_count; index_++)
- {
- if (!watchpoints[index_])
- continue;
-
- if (!compare_function (from, with, index_))
- {
- sc_char buffer[32];
-
- if (!triggered)
- {
- if_print_debug ("--- ");
- if_print_debug (class_);
- if_print_debug (" watchpoint triggered { ");
- }
- sprintf (buffer, "%ld ", index_);
- if_print_debug (buffer);
- triggered = TRUE;
- }
- }
- if (triggered)
- if_print_debug ("}.\n");
-
- /* Return TRUE if anything differed. */
- return triggered;
+debug_check_class(sc_gameref_t from, sc_gameref_t with,
+ const sc_char *class_, sc_int class_count,
+ const sc_bool *watchpoints,
+ sc_bool(*const compare_function)
+ (sc_gameref_t, sc_gameref_t, sc_int)) {
+ sc_int index_;
+ sc_bool triggered = FALSE;
+
+ /*
+ * Scan the watchpoints array for set watchpoints, comparing classes
+ * where the watchpoint flag is set.
+ */
+ for (index_ = 0; index_ < class_count; index_++) {
+ if (!watchpoints[index_])
+ continue;
+
+ if (!compare_function(from, with, index_)) {
+ sc_char buffer[32];
+
+ if (!triggered) {
+ if_print_debug("--- ");
+ if_print_debug(class_);
+ if_print_debug(" watchpoint triggered { ");
+ }
+ sprintf(buffer, "%ld ", index_);
+ if_print_debug(buffer);
+ triggered = TRUE;
+ }
+ }
+ if (triggered)
+ if_print_debug("}.\n");
+
+ /* Return TRUE if anything differed. */
+ return triggered;
}
@@ -2151,49 +2021,46 @@ debug_check_class (sc_gameref_t from, sc_gameref_t with,
* in which case no check is possible).
*/
static sc_bool
-debug_check_watchpoints (sc_gameref_t game)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
- const sc_gameref_t undo = game->undo;
- sc_bool triggered;
- assert (debug_is_valid (debug) && gs_is_game_valid (undo));
-
- /* If no undo is present, no check is possible. */
- if (!game->undo_available)
- return FALSE;
-
- /* Check first for player watchpoint. */
- triggered = FALSE;
- if (debug->watch_player)
- {
- if (gs_playerroom (game) != gs_playerroom (undo)
- || gs_playerposition (game) != gs_playerposition (undo)
- || gs_playerparent (game) != gs_playerparent (undo))
- {
- if_print_debug ("--- Player watchpoint triggered.\n");
- triggered |= TRUE;
- }
- }
-
- /* Now check other classes of watchpoint. */
- triggered |= debug_check_class (game, undo,
- "Object", gs_object_count (game),
- debug->watch_objects, debug_compare_object);
- triggered |= debug_check_class (game, undo,
- "NPC", gs_npc_count (game),
- debug->watch_npcs, debug_compare_npc);
- triggered |= debug_check_class (game, undo,
- "Event", gs_event_count (game),
- debug->watch_events, debug_compare_event);
- triggered |= debug_check_class (game, undo,
- "Task", gs_task_count (game),
- debug->watch_tasks, debug_compare_task);
- triggered |= debug_check_class (game, undo,
- "Variable", debug_variable_count (game),
- debug->watch_variables,
- debug_compare_variable);
-
- return triggered;
+debug_check_watchpoints(sc_gameref_t game) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+ const sc_gameref_t undo = game->undo;
+ sc_bool triggered;
+ assert(debug_is_valid(debug) && gs_is_game_valid(undo));
+
+ /* If no undo is present, no check is possible. */
+ if (!game->undo_available)
+ return FALSE;
+
+ /* Check first for player watchpoint. */
+ triggered = FALSE;
+ if (debug->watch_player) {
+ if (gs_playerroom(game) != gs_playerroom(undo)
+ || gs_playerposition(game) != gs_playerposition(undo)
+ || gs_playerparent(game) != gs_playerparent(undo)) {
+ if_print_debug("--- Player watchpoint triggered.\n");
+ triggered |= TRUE;
+ }
+ }
+
+ /* Now check other classes of watchpoint. */
+ triggered |= debug_check_class(game, undo,
+ "Object", gs_object_count(game),
+ debug->watch_objects, debug_compare_object);
+ triggered |= debug_check_class(game, undo,
+ "NPC", gs_npc_count(game),
+ debug->watch_npcs, debug_compare_npc);
+ triggered |= debug_check_class(game, undo,
+ "Event", gs_event_count(game),
+ debug->watch_events, debug_compare_event);
+ triggered |= debug_check_class(game, undo,
+ "Task", gs_task_count(game),
+ debug->watch_tasks, debug_compare_task);
+ triggered |= debug_check_class(game, undo,
+ "Variable", debug_variable_count(game),
+ debug->watch_variables,
+ debug_compare_variable);
+
+ return triggered;
}
@@ -2205,123 +2072,112 @@ debug_check_watchpoints (sc_gameref_t game)
* fails.
*/
static sc_command_t
-debug_parse_command (const sc_char *command_string,
- sc_command_type_t *type,
- sc_int *arg1, sc_int *arg2, sc_command_t *help_topic)
-{
- sc_command_t return_command;
- sc_command_type_t return_type;
- sc_int val1, val2, converted, matches;
- sc_char *help, *string, junk, wildcard;
- sc_bool is_help, is_parsed, is_wildcard;
- const sc_strings_t *entry;
-
- /* Allocate temporary strings long enough to take a copy of the input. */
- string = (sc_char *)sc_malloc (strlen (command_string) + 1);
- help = (sc_char *)sc_malloc (strlen (command_string) + 1);
-
- /*
- * Parse the input line, in a very simplistic fashion. The argument count
- * is one less than sscanf converts.
- */
- is_parsed = is_wildcard = is_help = FALSE;
- val1 = val2 = 0;
- converted = sscanf (command_string, " %s %s %c", help, string, &junk);
- if (converted == 2 && sc_strcasecmp (help, "help") == 0)
- {
- is_help = TRUE;
- is_parsed = TRUE;
- }
- sc_free (help);
- if (!is_parsed)
- {
- converted = sscanf (command_string,
- " %s %ld to %ld %c", string, &val1, &val2, &junk);
- if (converted != 3)
- converted = sscanf (command_string,
- " %s %ld - %ld %c", string, &val1, &val2, &junk);
- if (converted != 3)
- converted = sscanf (command_string,
- " %s %ld .. %ld %c", string, &val1, &val2, &junk);
- if (converted != 3)
- converted = sscanf (command_string,
- " %s %ld %ld %c", string, &val1, &val2, &junk);
- is_parsed |= converted == 3;
- }
- if (!is_parsed)
- {
- converted = sscanf (command_string,
- " %s %ld %c", string, &val1, &junk);
- is_parsed |= converted == 2;
- }
- if (!is_parsed)
- {
- converted = sscanf (command_string,
- " %s %c %c", string, &wildcard, &junk);
- if (converted == 2 && wildcard == '*')
- {
- is_wildcard = TRUE;
- is_parsed = TRUE;
- }
- else
- is_parsed |= converted == 1;
- }
- if (!is_parsed)
- {
- if_print_debug ("Invalid debug command.");
- if_print_debug (" Type 'help' for a list of valid commands.\n");
- sc_free (string);
- return DEBUG_NONE;
- }
-
- /* Decide on a command type based on the parse. */
- if (is_wildcard)
- return_type = COMMAND_ALL;
- else if (converted == 3)
- return_type = COMMAND_RANGE;
- else if (converted == 2)
- return_type = COMMAND_ONE;
- else
- return_type = COMMAND_QUERY;
-
- /*
- * Find the first unambiguous command matching the string. If none,
- * return DEBUG_NONE.
- */
- matches = 0;
- return_command = DEBUG_NONE;
- for (entry = DEBUG_COMMANDS; entry->command_string; entry++)
- {
- if (sc_strncasecmp (string, entry->command_string, strlen (string)) == 0)
- {
- matches++;
- return_command = entry->command;
- }
- }
- if (matches != 1)
- {
- if (matches > 1)
- if_print_debug ("Ambiguous debug command.");
- else
- if_print_debug ("Unrecognized debug command.");
- if_print_debug (" Type 'help' for a list of valid commands.\n");
- sc_free (string);
- return DEBUG_NONE;
- }
-
- /* Done with temporary command parse area. */
- sc_free (string);
-
- /*
- * Return the command type, arguments, and the debugging command. For help
- * <topic>, the command is help, with the command on which help requested
- * in *help_topic. All clear, then?
- */
- *type = return_type;
- *arg1 = val1;
- *arg2 = val2;
- *help_topic = is_help ? return_command : DEBUG_NONE;
- return is_help ? DEBUG_HELP : return_command;
+debug_parse_command(const sc_char *command_string,
+ sc_command_type_t *type,
+ sc_int *arg1, sc_int *arg2, sc_command_t *help_topic) {
+ sc_command_t return_command;
+ sc_command_type_t return_type;
+ sc_int val1, val2, converted, matches;
+ sc_char *help, *string, junk, wildcard;
+ sc_bool is_help, is_parsed, is_wildcard;
+ const sc_strings_t *entry;
+
+ /* Allocate temporary strings long enough to take a copy of the input. */
+ string = (sc_char *)sc_malloc(strlen(command_string) + 1);
+ help = (sc_char *)sc_malloc(strlen(command_string) + 1);
+
+ /*
+ * Parse the input line, in a very simplistic fashion. The argument count
+ * is one less than sscanf converts.
+ */
+ is_parsed = is_wildcard = is_help = FALSE;
+ val1 = val2 = 0;
+ converted = sscanf(command_string, " %s %s %c", help, string, &junk);
+ if (converted == 2 && sc_strcasecmp(help, "help") == 0) {
+ is_help = TRUE;
+ is_parsed = TRUE;
+ }
+ sc_free(help);
+ if (!is_parsed) {
+ converted = sscanf(command_string,
+ " %s %ld to %ld %c", string, &val1, &val2, &junk);
+ if (converted != 3)
+ converted = sscanf(command_string,
+ " %s %ld - %ld %c", string, &val1, &val2, &junk);
+ if (converted != 3)
+ converted = sscanf(command_string,
+ " %s %ld .. %ld %c", string, &val1, &val2, &junk);
+ if (converted != 3)
+ converted = sscanf(command_string,
+ " %s %ld %ld %c", string, &val1, &val2, &junk);
+ is_parsed |= converted == 3;
+ }
+ if (!is_parsed) {
+ converted = sscanf(command_string,
+ " %s %ld %c", string, &val1, &junk);
+ is_parsed |= converted == 2;
+ }
+ if (!is_parsed) {
+ converted = sscanf(command_string,
+ " %s %c %c", string, &wildcard, &junk);
+ if (converted == 2 && wildcard == '*') {
+ is_wildcard = TRUE;
+ is_parsed = TRUE;
+ } else
+ is_parsed |= converted == 1;
+ }
+ if (!is_parsed) {
+ if_print_debug("Invalid debug command.");
+ if_print_debug(" Type 'help' for a list of valid commands.\n");
+ sc_free(string);
+ return DEBUG_NONE;
+ }
+
+ /* Decide on a command type based on the parse. */
+ if (is_wildcard)
+ return_type = COMMAND_ALL;
+ else if (converted == 3)
+ return_type = COMMAND_RANGE;
+ else if (converted == 2)
+ return_type = COMMAND_ONE;
+ else
+ return_type = COMMAND_QUERY;
+
+ /*
+ * Find the first unambiguous command matching the string. If none,
+ * return DEBUG_NONE.
+ */
+ matches = 0;
+ return_command = DEBUG_NONE;
+ for (entry = DEBUG_COMMANDS; entry->command_string; entry++) {
+ if (sc_strncasecmp(string, entry->command_string, strlen(string)) == 0) {
+ matches++;
+ return_command = entry->command;
+ }
+ }
+ if (matches != 1) {
+ if (matches > 1)
+ if_print_debug("Ambiguous debug command.");
+ else
+ if_print_debug("Unrecognized debug command.");
+ if_print_debug(" Type 'help' for a list of valid commands.\n");
+ sc_free(string);
+ return DEBUG_NONE;
+ }
+
+ /* Done with temporary command parse area. */
+ sc_free(string);
+
+ /*
+ * Return the command type, arguments, and the debugging command. For help
+ * <topic>, the command is help, with the command on which help requested
+ * in *help_topic. All clear, then?
+ */
+ *type = return_type;
+ *arg1 = val1;
+ *arg2 = val2;
+ *help_topic = is_help ? return_command : DEBUG_NONE;
+ return is_help ? DEBUG_HELP : return_command;
}
@@ -2331,69 +2187,67 @@ debug_parse_command (const sc_char *command_string,
* Dispatch a debugging command to the appropriate handler.
*/
static void
-debug_dispatch (sc_gameref_t game,
- sc_command_t command, sc_command_type_t type,
- sc_int arg1, sc_int arg2, sc_command_t help_topic)
-{
- /* Demultiplex debugging command, and call handlers. */
- switch (command)
- {
- case DEBUG_HELP:
- debug_help (help_topic);
- break;
- case DEBUG_BUFFER:
- debug_buffer (game, type);
- break;
- case DEBUG_RESOURCES:
- debug_resources (game, type);
- break;
- case DEBUG_RANDOM:
- debug_random (type, arg1);
- break;
- case DEBUG_GAME:
- debug_game (game, type);
- break;
- case DEBUG_PLAYER:
- case DEBUG_OLDPLAYER:
- debug_player (game, command, type);
- break;
- case DEBUG_ROOMS:
- case DEBUG_OBJECTS:
- case DEBUG_NPCS:
- case DEBUG_EVENTS:
- case DEBUG_TASKS:
- case DEBUG_VARIABLES:
- case DEBUG_OLDROOMS:
- case DEBUG_OLDOBJECTS:
- case DEBUG_OLDNPCS:
- case DEBUG_OLDEVENTS:
- case DEBUG_OLDTASKS:
- case DEBUG_OLDVARIABLES:
- debug_dump_common (game, command, type, arg1, arg2);
- break;
- case DEBUG_WATCHPLAYER:
- case DEBUG_WATCHOBJECTS:
- case DEBUG_WATCHNPCS:
- case DEBUG_WATCHEVENTS:
- case DEBUG_WATCHTASKS:
- case DEBUG_WATCHVARIABLES:
- case DEBUG_CLEARPLAYER:
- case DEBUG_CLEAROBJECTS:
- case DEBUG_CLEARNPCS:
- case DEBUG_CLEAREVENTS:
- case DEBUG_CLEARTASKS:
- case DEBUG_CLEARVARIABLES:
- debug_watchpoint_common (game, command, type, arg1, arg2);
- break;
- case DEBUG_WATCHALL:
- case DEBUG_CLEARALL:
- debug_watchall_common (game, command, type);
- break;
- case DEBUG_NONE:
- break;
- default:
- sc_fatal ("debug_dispatch: invalid debug command\n");
- }
+debug_dispatch(sc_gameref_t game,
+ sc_command_t command, sc_command_type_t type,
+ sc_int arg1, sc_int arg2, sc_command_t help_topic) {
+ /* Demultiplex debugging command, and call handlers. */
+ switch (command) {
+ case DEBUG_HELP:
+ debug_help(help_topic);
+ break;
+ case DEBUG_BUFFER:
+ debug_buffer(game, type);
+ break;
+ case DEBUG_RESOURCES:
+ debug_resources(game, type);
+ break;
+ case DEBUG_RANDOM:
+ debug_random(type, arg1);
+ break;
+ case DEBUG_GAME:
+ debug_game(game, type);
+ break;
+ case DEBUG_PLAYER:
+ case DEBUG_OLDPLAYER:
+ debug_player(game, command, type);
+ break;
+ case DEBUG_ROOMS:
+ case DEBUG_OBJECTS:
+ case DEBUG_NPCS:
+ case DEBUG_EVENTS:
+ case DEBUG_TASKS:
+ case DEBUG_VARIABLES:
+ case DEBUG_OLDROOMS:
+ case DEBUG_OLDOBJECTS:
+ case DEBUG_OLDNPCS:
+ case DEBUG_OLDEVENTS:
+ case DEBUG_OLDTASKS:
+ case DEBUG_OLDVARIABLES:
+ debug_dump_common(game, command, type, arg1, arg2);
+ break;
+ case DEBUG_WATCHPLAYER:
+ case DEBUG_WATCHOBJECTS:
+ case DEBUG_WATCHNPCS:
+ case DEBUG_WATCHEVENTS:
+ case DEBUG_WATCHTASKS:
+ case DEBUG_WATCHVARIABLES:
+ case DEBUG_CLEARPLAYER:
+ case DEBUG_CLEAROBJECTS:
+ case DEBUG_CLEARNPCS:
+ case DEBUG_CLEAREVENTS:
+ case DEBUG_CLEARTASKS:
+ case DEBUG_CLEARVARIABLES:
+ debug_watchpoint_common(game, command, type, arg1, arg2);
+ break;
+ case DEBUG_WATCHALL:
+ case DEBUG_CLEARALL:
+ debug_watchall_common(game, command, type);
+ break;
+ case DEBUG_NONE:
+ break;
+ default:
+ sc_fatal("debug_dispatch: invalid debug command\n");
+ }
}
@@ -2403,91 +2257,82 @@ debug_dispatch (sc_gameref_t game,
* Create a small debugging dialog with the user.
*/
static void
-debug_dialog (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_debuggerref_t debug = debug_get_debugger (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- assert (debug_is_valid (debug));
-
- /*
- * Note elapsed seconds, so time stands still while debugging, and clear
- * any pending game quit left over from prior dialogs (just in case).
- */
- debug->elapsed_seconds = var_get_elapsed_seconds (vars);
- debug->quit_pending = FALSE;
-
- /* Handle debug commands until debugger quit or game quit. */
- while (TRUE)
- {
- sc_char buffer[DEBUG_BUFFER_SIZE];
- sc_command_t command, help_topic;
- sc_command_type_t type;
- sc_int arg1, arg2;
-
- /* Get a debugging command string from the user. */
- do
- {
- if_read_debug (buffer, sizeof (buffer));
-
- if (g_vm->shouldQuit())
- return;
- }
- while (sc_strempty (buffer));
-
- /* Parse the command read, and handle dialog exit commands. */
- command = debug_parse_command (buffer,
- &type, &arg1, &arg2, &help_topic);
- if (command == DEBUG_CONTINUE || command == DEBUG_STEP)
- {
- if (!game->is_running)
- {
- if_print_debug ("The game is no longer running.\n");
- continue;
- }
-
- debug->single_step = (command == DEBUG_STEP);
- break;
- }
- else if (command == DEBUG_QUIT)
- {
- /*
- * If the game is not running, we can't halt it, and we don't need
- * to confirm the quit (either the player "quit" or the game
- * completed), so leave the dialog loop.
- */
- if (!game->is_running)
- break;
-
- /*
- * The game is still running, so confirm quit by requiring a repeat,
- * or if this is the confirmation, force the game to a halt.
- */
- if (!debug->quit_pending)
- {
- if_print_debug ("Use 'quit' again to confirm, or another"
- " debugger command to cancel.\n");
- debug->quit_pending = TRUE;
- continue;
- }
-
- /* Drop printfilter contents and quit the game. */
- pf_empty (filter);
- run_quit (game);
-
- /* Just in case... */
- if_print_debug ("Unable to quit from the game. Sorry.\n");
- continue;
- }
-
- /* Dispatch the remaining debugging commands, and clear quit flag. */
- debug_dispatch (game, command, type, arg1, arg2, help_topic);
- debug->quit_pending = FALSE;
- }
-
- /* Restart time, and clear any pending game quit. */
- var_set_elapsed_seconds (vars, debug->elapsed_seconds);
- debug->quit_pending = FALSE;
+debug_dialog(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ assert(debug_is_valid(debug));
+
+ /*
+ * Note elapsed seconds, so time stands still while debugging, and clear
+ * any pending game quit left over from prior dialogs (just in case).
+ */
+ debug->elapsed_seconds = var_get_elapsed_seconds(vars);
+ debug->quit_pending = FALSE;
+
+ /* Handle debug commands until debugger quit or game quit. */
+ while (TRUE) {
+ sc_char buffer[DEBUG_BUFFER_SIZE];
+ sc_command_t command, help_topic;
+ sc_command_type_t type;
+ sc_int arg1, arg2;
+
+ /* Get a debugging command string from the user. */
+ do {
+ if_read_debug(buffer, sizeof(buffer));
+
+ if (g_vm->shouldQuit())
+ return;
+ } while (sc_strempty(buffer));
+
+ /* Parse the command read, and handle dialog exit commands. */
+ command = debug_parse_command(buffer,
+ &type, &arg1, &arg2, &help_topic);
+ if (command == DEBUG_CONTINUE || command == DEBUG_STEP) {
+ if (!game->is_running) {
+ if_print_debug("The game is no longer running.\n");
+ continue;
+ }
+
+ debug->single_step = (command == DEBUG_STEP);
+ break;
+ } else if (command == DEBUG_QUIT) {
+ /*
+ * If the game is not running, we can't halt it, and we don't need
+ * to confirm the quit (either the player "quit" or the game
+ * completed), so leave the dialog loop.
+ */
+ if (!game->is_running)
+ break;
+
+ /*
+ * The game is still running, so confirm quit by requiring a repeat,
+ * or if this is the confirmation, force the game to a halt.
+ */
+ if (!debug->quit_pending) {
+ if_print_debug("Use 'quit' again to confirm, or another"
+ " debugger command to cancel.\n");
+ debug->quit_pending = TRUE;
+ continue;
+ }
+
+ /* Drop printfilter contents and quit the game. */
+ pf_empty(filter);
+ run_quit(game);
+
+ /* Just in case... */
+ if_print_debug("Unable to quit from the game. Sorry.\n");
+ continue;
+ }
+
+ /* Dispatch the remaining debugging commands, and clear quit flag. */
+ debug_dispatch(game, command, type, arg1, arg2, help_topic);
+ debug->quit_pending = FALSE;
+ }
+
+ /* Restart time, and clear any pending game quit. */
+ var_set_elapsed_seconds(vars, debug->elapsed_seconds);
+ debug->quit_pending = FALSE;
}
@@ -2498,34 +2343,32 @@ debug_dialog (sc_gameref_t game)
* TRUE if valid, FALSE if invalid (parse failed, not understood).
*/
sc_bool
-debug_run_command (sc_gameref_t game, const sc_char *debug_command)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
- sc_command_t command, help_topic;
- sc_command_type_t type;
- sc_int arg1, arg2;
-
- /* If debugging disallowed (not initialized), refuse the call. */
- if (debug)
- {
- /*
- * Parse the command string passed in, and return FALSE if the parse
- * fails, or if it returns DEBUG_CONTINUE, DEBUG_STEP, or DEBUG_QUIT,
- * none of which make any sense in this context.
- */
- command = debug_parse_command (debug_command,
- &type, &arg1, &arg2, &help_topic);
- if (command == DEBUG_NONE
- || command == DEBUG_CONTINUE || command == DEBUG_STEP
- || command == DEBUG_QUIT)
- return FALSE;
-
- /* Dispatch the remaining debugging commands, return successfully. */
- debug_dispatch (game, command, type, arg1, arg2, help_topic);
- return TRUE;
- }
-
- return FALSE;
+debug_run_command(sc_gameref_t game, const sc_char *debug_command) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+ sc_command_t command, help_topic;
+ sc_command_type_t type;
+ sc_int arg1, arg2;
+
+ /* If debugging disallowed (not initialized), refuse the call. */
+ if (debug) {
+ /*
+ * Parse the command string passed in, and return FALSE if the parse
+ * fails, or if it returns DEBUG_CONTINUE, DEBUG_STEP, or DEBUG_QUIT,
+ * none of which make any sense in this context.
+ */
+ command = debug_parse_command(debug_command,
+ &type, &arg1, &arg2, &help_topic);
+ if (command == DEBUG_NONE
+ || command == DEBUG_CONTINUE || command == DEBUG_STEP
+ || command == DEBUG_QUIT)
+ return FALSE;
+
+ /* Dispatch the remaining debugging commands, return successfully. */
+ debug_dispatch(game, command, type, arg1, arg2, help_topic);
+ return TRUE;
+ }
+
+ return FALSE;
}
@@ -2537,22 +2380,21 @@ debug_run_command (sc_gameref_t game, const sc_char *debug_command)
* dialog. Uses if_print_string() as this isn't debug output.
*/
sc_bool
-debug_cmd_debugger (sc_gameref_t game)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
-
- /* If debugging disallowed (not initialized), ignore the call. */
- if (debug)
- debug_dialog (game);
- else
- if_print_string ("SCARE's game debugger is not enabled. Sorry.\n");
-
- /*
- * Set as administrative command, so as not to consume a game turn, and
- * return successfully.
- */
- game->is_admin = TRUE;
- return TRUE;
+debug_cmd_debugger(sc_gameref_t game) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+
+ /* If debugging disallowed (not initialized), ignore the call. */
+ if (debug)
+ debug_dialog(game);
+ else
+ if_print_string("SCARE's game debugger is not enabled. Sorry.\n");
+
+ /*
+ * Set as administrative command, so as not to consume a game turn, and
+ * return successfully.
+ */
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -2569,79 +2411,67 @@ debug_cmd_debugger (sc_gameref_t game)
* watchpoints and offer the debug dialog one last time.
*/
void
-debug_game_started (sc_gameref_t game)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
-
- /* If debugging disallowed (not initialized), ignore the call. */
- if (debug)
- {
- /* Starting a new game, or a restore or undo of an old one? */
- if (!gs_room_seen (game, gs_playerroom (game)))
- {
- /*
- * It's a new game starting or restarting. Print a banner, and
- * run the debugger dialog.
- */
- if_print_debug ("\n--- SCARE " SCARE_VERSION SCARE_PATCH_LEVEL
- " Game Debugger\n"
- "--- Type 'help' for a list of commands.\n");
- debug_dialog (game);
- }
- else
- {
- /*
- * It's a restore or undo through memos, so run the dialog only if
- * single-stepping; no need to check watchpoints for this case as
- * none can be set -- no undo.
- */
- if (debug->single_step)
- debug_dialog (game);
- }
- }
+debug_game_started(sc_gameref_t game) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+
+ /* If debugging disallowed (not initialized), ignore the call. */
+ if (debug) {
+ /* Starting a new game, or a restore or undo of an old one? */
+ if (!gs_room_seen(game, gs_playerroom(game))) {
+ /*
+ * It's a new game starting or restarting. Print a banner, and
+ * run the debugger dialog.
+ */
+ if_print_debug("\n--- SCARE " SCARE_VERSION SCARE_PATCH_LEVEL
+ " Game Debugger\n"
+ "--- Type 'help' for a list of commands.\n");
+ debug_dialog(game);
+ } else {
+ /*
+ * It's a restore or undo through memos, so run the dialog only if
+ * single-stepping; no need to check watchpoints for this case as
+ * none can be set -- no undo.
+ */
+ if (debug->single_step)
+ debug_dialog(game);
+ }
+ }
}
void
-debug_game_ended (sc_gameref_t game)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
-
- /* If debugging disallowed (not initialized), ignore the call. */
- if (debug)
- {
- /*
- * Using our carnal knowledge of the run main loop, we know here that
- * if the loop exited with do_restart or do_restore, we'll get a call to
- * debug_game_start() when the loop restarts. So in this case, ignore
- * the call (even if single stepping).
- */
- if (game->do_restart || game->do_restore)
- return;
-
- /*
- * Check for any final watchpoints, and print a message describing why
- * we're here. Suppress the check for watchpoints if the user exited
- * the game, as it'll only be a repeat of any found last turn update.
- */
- if (!game->is_running)
- {
- if (game->has_completed)
- {
- debug_check_watchpoints (game);
- if_print_debug ("\n--- The game has completed.\n");
- }
- else
- if_print_debug ("\n--- The game has exited.\n");
- }
- else
- {
- debug_check_watchpoints (game);
- if_print_debug ("\n--- The game is still running!\n");
- }
-
- /* Run a final dialog. */
- debug_dialog (game);
- }
+debug_game_ended(sc_gameref_t game) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+
+ /* If debugging disallowed (not initialized), ignore the call. */
+ if (debug) {
+ /*
+ * Using our carnal knowledge of the run main loop, we know here that
+ * if the loop exited with do_restart or do_restore, we'll get a call to
+ * debug_game_start() when the loop restarts. So in this case, ignore
+ * the call (even if single stepping).
+ */
+ if (game->do_restart || game->do_restore)
+ return;
+
+ /*
+ * Check for any final watchpoints, and print a message describing why
+ * we're here. Suppress the check for watchpoints if the user exited
+ * the game, as it'll only be a repeat of any found last turn update.
+ */
+ if (!game->is_running) {
+ if (game->has_completed) {
+ debug_check_watchpoints(game);
+ if_print_debug("\n--- The game has completed.\n");
+ } else
+ if_print_debug("\n--- The game has exited.\n");
+ } else {
+ debug_check_watchpoints(game);
+ if_print_debug("\n--- The game is still running!\n");
+ }
+
+ /* Run a final dialog. */
+ debug_dialog(game);
+ }
}
@@ -2652,29 +2482,27 @@ debug_game_ended (sc_gameref_t game)
* watchpoints, and triggers a debug dialog when any fire.
*/
void
-debug_turn_update (sc_gameref_t game)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
-
- /* If debugging disallowed (not initialized), ignore the call. */
- if (debug)
- {
- /*
- * Again using carnal knowledge of the run main loop, if we're in
- * mid-wait, ignore the call. Also, ignore the call if the game is
- * no longer running, as we'll see a debug_game_ended() call come
- * along to handle that.
- */
- if (game->waitcounter > 0 || !game->is_running)
- return;
-
- /*
- * Run debugger dialog if any watchpoints triggered, or if single
- * stepping (even if none triggered).
- */
- if (debug_check_watchpoints (game) || debug->single_step)
- debug_dialog (game);
- }
+debug_turn_update(sc_gameref_t game) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+
+ /* If debugging disallowed (not initialized), ignore the call. */
+ if (debug) {
+ /*
+ * Again using carnal knowledge of the run main loop, if we're in
+ * mid-wait, ignore the call. Also, ignore the call if the game is
+ * no longer running, as we'll see a debug_game_ended() call come
+ * along to handle that.
+ */
+ if (game->waitcounter > 0 || !game->is_running)
+ return;
+
+ /*
+ * Run debugger dialog if any watchpoints triggered, or if single
+ * stepping (even if none triggered).
+ */
+ if (debug_check_watchpoints(game) || debug->single_step)
+ debug_dialog(game);
+ }
}
@@ -2690,30 +2518,27 @@ debug_turn_update (sc_gameref_t game)
* disabling.
*/
void
-debug_set_enabled (sc_gameref_t game, sc_bool enable)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
-
- /*
- * If enabling and not already enabled, or disabling and not already
- * disabled, either initialize or finalize..
- */
- if ((enable && !debug) || (!enable && debug))
- {
- /* Initialize or finalize debugging, as appropriate. */
- if (enable)
- debug_initialize (game);
- else
- debug_finalize (game);
- }
+debug_set_enabled(sc_gameref_t game, sc_bool enable) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
+
+ /*
+ * If enabling and not already enabled, or disabling and not already
+ * disabled, either initialize or finalize..
+ */
+ if ((enable && !debug) || (!enable && debug)) {
+ /* Initialize or finalize debugging, as appropriate. */
+ if (enable)
+ debug_initialize(game);
+ else
+ debug_finalize(game);
+ }
}
sc_bool
-debug_get_enabled (sc_gameref_t game)
-{
- const sc_debuggerref_t debug = debug_get_debugger (game);
+debug_get_enabled(sc_gameref_t game) {
+ const sc_debuggerref_t debug = debug_get_debugger(game);
- return debug != NULL;
+ return debug != NULL;
}
} // End of namespace Adrift
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
diff --git a/engines/glk/adrift/scexpr.cpp b/engines/glk/adrift/scexpr.cpp
index ed3386020f..a316b7cdec 100644
--- a/engines/glk/adrift/scexpr.cpp
+++ b/engines/glk/adrift/scexpr.cpp
@@ -51,50 +51,49 @@ static const sc_char DOUBLE_QUOTE = '"';
* serves to indicate string concatenation -- it's never returned by the
* tokenizer.
*/
-enum
-{ TOK_NONE = -1,
- TOK_ADD = '+', TOK_SUBTRACT = '-', TOK_MULTIPLY = '*', TOK_DIVIDE = '/',
- TOK_AND = '&', TOK_OR = '|',
- TOK_LPAREN = '(', TOK_RPAREN = ')', TOK_COMMA = ',', TOK_POWER = '^',
- TOK_EQUAL = '=', TOK_GREATER = '>', TOK_LESS = '<',
-
- TOK_IDENT = 256,
- TOK_INTEGER, TOK_STRING, TOK_VARIABLE, TOK_UMINUS, TOK_UPLUS,
- TOK_MOD, TOK_NOT_EQUAL, TOK_GREATER_EQ, TOK_LESS_EQ, TOK_IF,
- TOK_MIN, TOK_MAX, TOK_EITHER, TOK_RANDOM, TOK_INSTR, TOK_LEN, TOK_VAL,
- TOK_ABS, TOK_UPPER, TOK_LOWER, TOK_PROPER, TOK_RIGHT, TOK_LEFT, TOK_MID,
- TOK_STR, TOK_CONCATENATE,
- TOK_EOS
+enum {
+ TOK_NONE = -1,
+ TOK_ADD = '+', TOK_SUBTRACT = '-', TOK_MULTIPLY = '*', TOK_DIVIDE = '/',
+ TOK_AND = '&', TOK_OR = '|',
+ TOK_LPAREN = '(', TOK_RPAREN = ')', TOK_COMMA = ',', TOK_POWER = '^',
+ TOK_EQUAL = '=', TOK_GREATER = '>', TOK_LESS = '<',
+
+ TOK_IDENT = 256,
+ TOK_INTEGER, TOK_STRING, TOK_VARIABLE, TOK_UMINUS, TOK_UPLUS,
+ TOK_MOD, TOK_NOT_EQUAL, TOK_GREATER_EQ, TOK_LESS_EQ, TOK_IF,
+ TOK_MIN, TOK_MAX, TOK_EITHER, TOK_RANDOM, TOK_INSTR, TOK_LEN, TOK_VAL,
+ TOK_ABS, TOK_UPPER, TOK_LOWER, TOK_PROPER, TOK_RIGHT, TOK_LEFT, TOK_MID,
+ TOK_STR, TOK_CONCATENATE,
+ TOK_EOS
};
/*
* Small tables tying multicharacter tokens strings to tokens. At present,
* the string lengths for names are not used.
*/
-typedef struct
-{
- const sc_char *const name;
- const sc_int length;
- const sc_int token;
+typedef struct {
+ const sc_char *const name;
+ const sc_int length;
+ const sc_int token;
} sc_expr_multichar_t;
static const sc_expr_multichar_t FUNCTION_TOKENS[] = {
- {"either", 6, TOK_EITHER},
- {"proper", 6, TOK_PROPER}, {"pcase", 5, TOK_PROPER}, {"instr", 5, TOK_INSTR},
- {"upper", 5, TOK_UPPER}, {"ucase", 5, TOK_UPPER},
- {"lower", 5, TOK_LOWER}, {"lcase", 5, TOK_LOWER},
- {"right", 5, TOK_RIGHT}, {"left", 4, TOK_LEFT},
- {"rand", 4, TOK_RANDOM}, {"max", 3, TOK_MAX}, {"min", 3, TOK_MIN},
- {"mod", 3, TOK_MOD}, {"abs", 3, TOK_ABS}, {"len", 3, TOK_LEN},
- {"val", 3, TOK_VAL}, {"and", 3, TOK_AND}, {"mid", 3, TOK_MID},
- {"str", 3, TOK_STR}, {"or", 2, TOK_OR}, {"if", 2, TOK_IF},
- {NULL, 0, TOK_NONE}
+ {"either", 6, TOK_EITHER},
+ {"proper", 6, TOK_PROPER}, {"pcase", 5, TOK_PROPER}, {"instr", 5, TOK_INSTR},
+ {"upper", 5, TOK_UPPER}, {"ucase", 5, TOK_UPPER},
+ {"lower", 5, TOK_LOWER}, {"lcase", 5, TOK_LOWER},
+ {"right", 5, TOK_RIGHT}, {"left", 4, TOK_LEFT},
+ {"rand", 4, TOK_RANDOM}, {"max", 3, TOK_MAX}, {"min", 3, TOK_MIN},
+ {"mod", 3, TOK_MOD}, {"abs", 3, TOK_ABS}, {"len", 3, TOK_LEN},
+ {"val", 3, TOK_VAL}, {"and", 3, TOK_AND}, {"mid", 3, TOK_MID},
+ {"str", 3, TOK_STR}, {"or", 2, TOK_OR}, {"if", 2, TOK_IF},
+ {NULL, 0, TOK_NONE}
};
static const sc_expr_multichar_t OPERATOR_TOKENS[] = {
- {"&&", 2, TOK_AND}, {"||", 2, TOK_OR},
- {"==", 2, TOK_EQUAL}, {"!=", 2, TOK_NOT_EQUAL},
- {"<>", 2, TOK_NOT_EQUAL}, {">=", 2, TOK_GREATER_EQ}, {"<=", 2, TOK_LESS_EQ},
- {NULL, 0, TOK_NONE}
+ {"&&", 2, TOK_AND}, {"||", 2, TOK_OR},
+ {"==", 2, TOK_EQUAL}, {"!=", 2, TOK_NOT_EQUAL},
+ {"<>", 2, TOK_NOT_EQUAL}, {">=", 2, TOK_GREATER_EQ}, {"<=", 2, TOK_LESS_EQ},
+ {NULL, 0, TOK_NONE}
};
@@ -105,19 +104,17 @@ static const sc_expr_multichar_t OPERATOR_TOKENS[] = {
* TOK_NONE if no match.
*/
static sc_int
-expr_multichar_search (const sc_char *name, const sc_expr_multichar_t *table)
-{
- const sc_expr_multichar_t *entry;
-
- /* Scan the table for a case-independent full string match. */
- for (entry = table; entry->name; entry++)
- {
- if (sc_strcasecmp (name, entry->name) == 0)
- break;
- }
-
- /* Return the token matched, or TOK_NONE. */
- return entry->name ? entry->token : TOK_NONE;
+expr_multichar_search(const sc_char *name, const sc_expr_multichar_t *table) {
+ const sc_expr_multichar_t *entry;
+
+ /* Scan the table for a case-independent full string match. */
+ for (entry = table; entry->name; entry++) {
+ if (sc_strcasecmp(name, entry->name) == 0)
+ break;
+ }
+
+ /* Return the token matched, or TOK_NONE. */
+ return entry->name ? entry->token : TOK_NONE;
}
@@ -135,60 +132,53 @@ static sc_int expr_current_token = TOK_NONE;
* Start and wrap up expression string tokenization.
*/
static void
-expr_tokenize_start (const sc_char *expression)
-{
- static sc_bool initialized = FALSE;
-
- /* On first call only, verify the string lengths in the tables. */
- if (!initialized)
- {
- const sc_expr_multichar_t *entry;
-
- /* Compare table lengths with string lengths. */
- for (entry = FUNCTION_TOKENS; entry->name; entry++)
- {
- if (entry->length != (sc_int) strlen (entry->name))
- {
- sc_fatal ("expr_tokenize_start:"
- " token string length is wrong for \"%s\"\n",
- entry->name);
- }
- }
-
- for (entry = OPERATOR_TOKENS; entry->name; entry++)
- {
- if (entry->length != (sc_int) strlen (entry->name))
- {
- sc_fatal ("expr_tokenize_start:"
- " operator string length is wrong for \"%s\"\n",
- entry->name);
- }
- }
-
- initialized = TRUE;
- }
-
- /* Save expression, and restart index. */
- expr_expression = expression;
- expr_index = 0;
-
- /* Allocate a temporary token value/literals string. */
- assert (!expr_temporary);
- expr_temporary = (sc_char *)sc_malloc (strlen (expression) + 1);
-
- /* Reset last token to none. */
- expr_current_token = TOK_NONE;
+expr_tokenize_start(const sc_char *expression) {
+ static sc_bool initialized = FALSE;
+
+ /* On first call only, verify the string lengths in the tables. */
+ if (!initialized) {
+ const sc_expr_multichar_t *entry;
+
+ /* Compare table lengths with string lengths. */
+ for (entry = FUNCTION_TOKENS; entry->name; entry++) {
+ if (entry->length != (sc_int) strlen(entry->name)) {
+ sc_fatal("expr_tokenize_start:"
+ " token string length is wrong for \"%s\"\n",
+ entry->name);
+ }
+ }
+
+ for (entry = OPERATOR_TOKENS; entry->name; entry++) {
+ if (entry->length != (sc_int) strlen(entry->name)) {
+ sc_fatal("expr_tokenize_start:"
+ " operator string length is wrong for \"%s\"\n",
+ entry->name);
+ }
+ }
+
+ initialized = TRUE;
+ }
+
+ /* Save expression, and restart index. */
+ expr_expression = expression;
+ expr_index = 0;
+
+ /* Allocate a temporary token value/literals string. */
+ assert(!expr_temporary);
+ expr_temporary = (sc_char *)sc_malloc(strlen(expression) + 1);
+
+ /* Reset last token to none. */
+ expr_current_token = TOK_NONE;
}
static void
-expr_tokenize_end (void)
-{
- /* Deallocate temporary strings, clear expression. */
- sc_free (expr_temporary);
- expr_temporary = NULL;
- expr_expression = NULL;
- expr_index = 0;
- expr_current_token = TOK_NONE;
+expr_tokenize_end(void) {
+ /* Deallocate temporary strings, clear expression. */
+ sc_free(expr_temporary);
+ expr_temporary = NULL;
+ expr_expression = NULL;
+ expr_index = 0;
+ expr_current_token = TOK_NONE;
}
@@ -200,219 +190,198 @@ expr_tokenize_end (void)
* be adjusted into a unary +/- depending on the value of the previous token.
*/
static sc_int
-expr_next_token_unadjusted (sc_vartype_t *token_value)
-{
- sc_int c;
- assert (expr_expression);
-
- /* Skip any and all leading whitespace. */
- do
- {
- c = expr_expression[expr_index++];
- }
- while (sc_isspace (c) && c != NUL);
-
- /* Return EOS if at expression end. */
- if (c == NUL)
- {
- expr_index--;
- return TOK_EOS;
- }
-
- /*
- * Identify and return numerics. We deal only with unsigned numbers here;
- * the unary +/- tokens take care of any integer sign issues.
- */
- else if (sc_isdigit (c))
- {
- sc_int value;
-
- sscanf (expr_expression + expr_index - 1, "%ld", &value);
-
- while (sc_isdigit (c) && c != NUL)
- c = expr_expression[expr_index++];
- expr_index--;
-
- token_value->integer = value;
- return TOK_INTEGER;
- }
-
- /* Identify and return variable references. */
- else if (c == PERCENT)
- {
- sc_int index_;
-
- /* Copy variable name. */
- c = expr_expression[expr_index++];
- for (index_ = 0; c != PERCENT && c != NUL;)
- {
- expr_temporary[index_++] = c;
- c = expr_expression[expr_index++];
- }
- expr_temporary[index_++] = NUL;
-
- if (c == NUL)
- {
- sc_error ("expr_next_token_unadjusted:"
- " warning: unterminated variable name\n");
- expr_index--;
- }
-
- /* Return a variable name. */
- token_value->string = expr_temporary;
- return TOK_VARIABLE;
- }
-
- /* Identify and return string literals. */
- else if (c == DOUBLE_QUOTE || c == SINGLE_QUOTE)
- {
- sc_int index_;
- sc_char quote;
-
- /* Copy maximal string literal. */
- quote = c;
- c = expr_expression[expr_index++];
- for (index_ = 0; c != quote && c != NUL;)
- {
- expr_temporary[index_++] = c;
- c = expr_expression[expr_index++];
- }
- expr_temporary[index_++] = NUL;
-
- if (c == NUL)
- {
- sc_error ("expr_next_token_unadjusted:"
- " warning: unterminated string literal\n");
- expr_index--;
- }
-
- /* Return string literal. */
- token_value->string = expr_temporary;
- return TOK_STRING;
- }
-
- /* Identify ids and other multicharacter tokens. */
- else if (sc_isalpha (c))
- {
- sc_int index_, token;
-
- /*
- * Copy maximal alphabetical string. While an ident would normally
- * be alpha followed by zero or more alnum, for Adrift purposes we
- * use only alpha -- all idents should really be "functions", and
- * in particular we want to see "mod7" as "mod" and 7 separately.
- */
- for (index_ = 0; sc_isalpha (c) && c != NUL;)
- {
- expr_temporary[index_++] = c;
- c = expr_expression[expr_index++];
- }
- expr_index--;
- expr_temporary[index_++] = NUL;
-
- /*
- * Check for a function name, and if known, return that, otherwise
- * return a bare id.
- */
- token = expr_multichar_search (expr_temporary, FUNCTION_TOKENS);
- if (token == TOK_NONE)
- {
- token_value->string = expr_temporary;
- return TOK_IDENT;
- }
- else
- return token;
- }
-
- /*
- * Last chance check for two-character (multichar) operators, and if none
- * then return a single-character token.
- */
- else
- {
- sc_char operator_[3];
- sc_int token;
-
- /*
- * Build a two-character string. If we happen to be at the last
- * expression character, we'll pick up the expression NUL into
- * operator_[1], so no need to special case end of expression here.
- */
- operator_[0] = c;
- operator_[1] = expr_expression[expr_index];
- operator_[2] = NUL;
-
- /* Search for this two-character operator. */
- if (operator_[0] != NUL && operator_[1] != NUL)
- {
- token = expr_multichar_search (operator_, OPERATOR_TOKENS);
- if (token != TOK_NONE)
- {
- /* Matched, so advance expression index and return this token. */
- expr_index++;
- return token;
- }
- }
-
- /*
- * No match, or at last expression character; return a single character
- * token.
- */
- return c;
- }
+expr_next_token_unadjusted(sc_vartype_t *token_value) {
+ sc_int c;
+ assert(expr_expression);
+
+ /* Skip any and all leading whitespace. */
+ do {
+ c = expr_expression[expr_index++];
+ } while (sc_isspace(c) && c != NUL);
+
+ /* Return EOS if at expression end. */
+ if (c == NUL) {
+ expr_index--;
+ return TOK_EOS;
+ }
+
+ /*
+ * Identify and return numerics. We deal only with unsigned numbers here;
+ * the unary +/- tokens take care of any integer sign issues.
+ */
+ else if (sc_isdigit(c)) {
+ sc_int value;
+
+ sscanf(expr_expression + expr_index - 1, "%ld", &value);
+
+ while (sc_isdigit(c) && c != NUL)
+ c = expr_expression[expr_index++];
+ expr_index--;
+
+ token_value->integer = value;
+ return TOK_INTEGER;
+ }
+
+ /* Identify and return variable references. */
+ else if (c == PERCENT) {
+ sc_int index_;
+
+ /* Copy variable name. */
+ c = expr_expression[expr_index++];
+ for (index_ = 0; c != PERCENT && c != NUL;) {
+ expr_temporary[index_++] = c;
+ c = expr_expression[expr_index++];
+ }
+ expr_temporary[index_++] = NUL;
+
+ if (c == NUL) {
+ sc_error("expr_next_token_unadjusted:"
+ " warning: unterminated variable name\n");
+ expr_index--;
+ }
+
+ /* Return a variable name. */
+ token_value->string = expr_temporary;
+ return TOK_VARIABLE;
+ }
+
+ /* Identify and return string literals. */
+ else if (c == DOUBLE_QUOTE || c == SINGLE_QUOTE) {
+ sc_int index_;
+ sc_char quote;
+
+ /* Copy maximal string literal. */
+ quote = c;
+ c = expr_expression[expr_index++];
+ for (index_ = 0; c != quote && c != NUL;) {
+ expr_temporary[index_++] = c;
+ c = expr_expression[expr_index++];
+ }
+ expr_temporary[index_++] = NUL;
+
+ if (c == NUL) {
+ sc_error("expr_next_token_unadjusted:"
+ " warning: unterminated string literal\n");
+ expr_index--;
+ }
+
+ /* Return string literal. */
+ token_value->string = expr_temporary;
+ return TOK_STRING;
+ }
+
+ /* Identify ids and other multicharacter tokens. */
+ else if (sc_isalpha(c)) {
+ sc_int index_, token;
+
+ /*
+ * Copy maximal alphabetical string. While an ident would normally
+ * be alpha followed by zero or more alnum, for Adrift purposes we
+ * use only alpha -- all idents should really be "functions", and
+ * in particular we want to see "mod7" as "mod" and 7 separately.
+ */
+ for (index_ = 0; sc_isalpha(c) && c != NUL;) {
+ expr_temporary[index_++] = c;
+ c = expr_expression[expr_index++];
+ }
+ expr_index--;
+ expr_temporary[index_++] = NUL;
+
+ /*
+ * Check for a function name, and if known, return that, otherwise
+ * return a bare id.
+ */
+ token = expr_multichar_search(expr_temporary, FUNCTION_TOKENS);
+ if (token == TOK_NONE) {
+ token_value->string = expr_temporary;
+ return TOK_IDENT;
+ } else
+ return token;
+ }
+
+ /*
+ * Last chance check for two-character (multichar) operators, and if none
+ * then return a single-character token.
+ */
+ else {
+ sc_char operator_[3];
+ sc_int token;
+
+ /*
+ * Build a two-character string. If we happen to be at the last
+ * expression character, we'll pick up the expression NUL into
+ * operator_[1], so no need to special case end of expression here.
+ */
+ operator_[0] = c;
+ operator_[1] = expr_expression[expr_index];
+ operator_[2] = NUL;
+
+ /* Search for this two-character operator. */
+ if (operator_[0] != NUL && operator_[1] != NUL) {
+ token = expr_multichar_search(operator_, OPERATOR_TOKENS);
+ if (token != TOK_NONE) {
+ /* Matched, so advance expression index and return this token. */
+ expr_index++;
+ return token;
+ }
+ }
+
+ /*
+ * No match, or at last expression character; return a single character
+ * token.
+ */
+ return c;
+ }
}
static sc_int
-expr_next_token (void)
-{
- sc_int token;
- sc_vartype_t token_value;
-
- /*
- * Get the basic next token. We may adjust it later for unary minus/plus
- * depending on what it is, and the prior token.
- */
- token_value.voidp = NULL;
- token = expr_next_token_unadjusted (&token_value);
-
- /* Special handling for unary minus/plus signs. */
- if (token == TOK_SUBTRACT || token == TOK_ADD)
- {
- /*
- * Unary minus/plus if prior token was an operator or a comparison, left
- * parenthesis, or comma, or if there was no prior token.
- */
- switch (expr_current_token)
- {
- case TOK_MOD:
- case TOK_POWER:
- case TOK_ADD:
- case TOK_SUBTRACT:
- case TOK_MULTIPLY:
- case TOK_DIVIDE:
- case TOK_AND:
- case TOK_OR:
- case TOK_EQUAL:
- case TOK_GREATER:
- case TOK_LESS:
- case TOK_NOT_EQUAL:
- case TOK_GREATER_EQ:
- case TOK_LESS_EQ:
- case TOK_LPAREN:
- case TOK_COMMA:
- case TOK_NONE:
- token = (token == TOK_SUBTRACT) ? TOK_UMINUS : TOK_UPLUS;
- break;
-
- default:
- break;
- }
- }
-
- /* Set current token to the one just found, and return it. */
- expr_current_token = token;
- expr_token_value = token_value;
- return token;
+expr_next_token(void) {
+ sc_int token;
+ sc_vartype_t token_value;
+
+ /*
+ * Get the basic next token. We may adjust it later for unary minus/plus
+ * depending on what it is, and the prior token.
+ */
+ token_value.voidp = NULL;
+ token = expr_next_token_unadjusted(&token_value);
+
+ /* Special handling for unary minus/plus signs. */
+ if (token == TOK_SUBTRACT || token == TOK_ADD) {
+ /*
+ * Unary minus/plus if prior token was an operator or a comparison, left
+ * parenthesis, or comma, or if there was no prior token.
+ */
+ switch (expr_current_token) {
+ case TOK_MOD:
+ case TOK_POWER:
+ case TOK_ADD:
+ case TOK_SUBTRACT:
+ case TOK_MULTIPLY:
+ case TOK_DIVIDE:
+ case TOK_AND:
+ case TOK_OR:
+ case TOK_EQUAL:
+ case TOK_GREATER:
+ case TOK_LESS:
+ case TOK_NOT_EQUAL:
+ case TOK_GREATER_EQ:
+ case TOK_LESS_EQ:
+ case TOK_LPAREN:
+ case TOK_COMMA:
+ case TOK_NONE:
+ token = (token == TOK_SUBTRACT) ? TOK_UMINUS : TOK_UPLUS;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Set current token to the one just found, and return it. */
+ expr_current_token = token;
+ expr_token_value = token_value;
+ return token;
}
@@ -423,24 +392,22 @@ expr_next_token (void)
* token is not numeric, an id, or a variable.
*/
static void
-expr_current_token_value (sc_vartype_t *value)
-{
- /* Quick check that the value is a valid one. */
- switch (expr_current_token)
- {
- case TOK_INTEGER:
- case TOK_STRING:
- case TOK_VARIABLE:
- case TOK_IDENT:
- break;
-
- default:
- sc_fatal ("expr_current_token_value:"
- " taking undefined token value, %ld\n", expr_current_token);
- }
-
- /* Return value. */
- *value = expr_token_value;
+expr_current_token_value(sc_vartype_t *value) {
+ /* Quick check that the value is a valid one. */
+ switch (expr_current_token) {
+ case TOK_INTEGER:
+ case TOK_STRING:
+ case TOK_VARIABLE:
+ case TOK_IDENT:
+ break;
+
+ default:
+ sc_fatal("expr_current_token_value:"
+ " taking undefined token value, %ld\n", expr_current_token);
+ }
+
+ /* Return value. */
+ *value = expr_token_value;
}
@@ -449,10 +416,9 @@ expr_current_token_value (sc_vartype_t *value)
* integers and strings, and flags strings for possible garbage collection
* on parse errors.
*/
-typedef struct
-{
- sc_bool is_collectible;
- sc_vartype_t value;
+typedef struct {
+ sc_bool is_collectible;
+ sc_vartype_t value;
} sc_stack_t;
static sc_stack_t expr_eval_stack[MAX_NESTING_DEPTH];
static sc_int expr_eval_stack_index = 0;
@@ -467,10 +433,9 @@ static sc_var_setref_t expr_varset = NULL;
* set to use when referencing %...% variables.
*/
static void
-expr_eval_start (sc_var_setref_t vars)
-{
- expr_eval_stack_index = 0;
- expr_varset = vars;
+expr_eval_start(sc_var_setref_t vars) {
+ expr_eval_stack_index = 0;
+ expr_varset = vars;
}
@@ -481,22 +446,20 @@ expr_eval_start (sc_var_setref_t vars)
* strings left in the evaluation array.
*/
static void
-expr_eval_garbage_collect (void)
-{
- sc_int index_;
-
- /*
- * Find and free all collectible strings still in the stack. We have to
- * free through mutable string rather than const string.
- */
- for (index_ = 0; index_ < expr_eval_stack_index; index_++)
- {
- if (expr_eval_stack[index_].is_collectible)
- sc_free (expr_eval_stack[index_].value.mutable_string);
- }
-
- /* Reset the stack index, for clarity and neatness. */
- expr_eval_stack_index = 0;
+expr_eval_garbage_collect(void) {
+ sc_int index_;
+
+ /*
+ * Find and free all collectible strings still in the stack. We have to
+ * free through mutable string rather than const string.
+ */
+ for (index_ = 0; index_ < expr_eval_stack_index; index_++) {
+ if (expr_eval_stack[index_].is_collectible)
+ sc_free(expr_eval_stack[index_].value.mutable_string);
+ }
+
+ /* Reset the stack index, for clarity and neatness. */
+ expr_eval_stack_index = 0;
}
@@ -511,38 +474,35 @@ expr_eval_garbage_collect (void)
* the caller should not subsequently free the string.
*/
static void
-expr_eval_push_integer (sc_int value)
-{
- if (expr_eval_stack_index >= MAX_NESTING_DEPTH)
- sc_fatal ("expr_eval_push_integer: stack overflow\n");
+expr_eval_push_integer(sc_int value) {
+ if (expr_eval_stack_index >= MAX_NESTING_DEPTH)
+ sc_fatal("expr_eval_push_integer: stack overflow\n");
- expr_eval_stack[expr_eval_stack_index].is_collectible = FALSE;
- expr_eval_stack[expr_eval_stack_index++].value.integer = value;
+ expr_eval_stack[expr_eval_stack_index].is_collectible = FALSE;
+ expr_eval_stack[expr_eval_stack_index++].value.integer = value;
}
static void
-expr_eval_push_string (const sc_char *value)
-{
- sc_char *value_copy;
-
- if (expr_eval_stack_index >= MAX_NESTING_DEPTH)
- sc_fatal ("expr_eval_push_string: stack overflow\n");
-
- /* Push a copy of value. */
- value_copy = (sc_char *)sc_malloc (strlen (value) + 1);
- strcpy (value_copy, value);
- expr_eval_stack[expr_eval_stack_index].is_collectible = TRUE;
- expr_eval_stack[expr_eval_stack_index++].value.mutable_string = value_copy;
+expr_eval_push_string(const sc_char *value) {
+ sc_char *value_copy;
+
+ if (expr_eval_stack_index >= MAX_NESTING_DEPTH)
+ sc_fatal("expr_eval_push_string: stack overflow\n");
+
+ /* Push a copy of value. */
+ value_copy = (sc_char *)sc_malloc(strlen(value) + 1);
+ strcpy(value_copy, value);
+ expr_eval_stack[expr_eval_stack_index].is_collectible = TRUE;
+ expr_eval_stack[expr_eval_stack_index++].value.mutable_string = value_copy;
}
static void
-expr_eval_push_alloced_string (sc_char *value)
-{
- if (expr_eval_stack_index >= MAX_NESTING_DEPTH)
- sc_fatal ("expr_eval_push_alloced_string: stack overflow\n");
+expr_eval_push_alloced_string(sc_char *value) {
+ if (expr_eval_stack_index >= MAX_NESTING_DEPTH)
+ sc_fatal("expr_eval_push_alloced_string: stack overflow\n");
- expr_eval_stack[expr_eval_stack_index].is_collectible = TRUE;
- expr_eval_stack[expr_eval_stack_index++].value.mutable_string = value;
+ expr_eval_stack[expr_eval_stack_index].is_collectible = TRUE;
+ expr_eval_stack[expr_eval_stack_index++].value.mutable_string = value;
}
@@ -554,24 +514,22 @@ expr_eval_push_alloced_string (sc_char *value)
* and the caller is responsible for freeing them.
*/
static sc_int
-expr_eval_pop_integer (void)
-{
- if (expr_eval_stack_index == 0)
- sc_fatal ("expr_eval_pop_integer: stack underflow\n");
+expr_eval_pop_integer(void) {
+ if (expr_eval_stack_index == 0)
+ sc_fatal("expr_eval_pop_integer: stack underflow\n");
- assert (!expr_eval_stack[expr_eval_stack_index - 1].is_collectible);
- return expr_eval_stack[--expr_eval_stack_index].value.integer;
+ assert(!expr_eval_stack[expr_eval_stack_index - 1].is_collectible);
+ return expr_eval_stack[--expr_eval_stack_index].value.integer;
}
static sc_char *
-expr_eval_pop_string (void)
-{
- if (expr_eval_stack_index == 0)
- sc_fatal ("expr_eval_pop_string: stack underflow\n");
-
- /* Returns mutable string rather than const string. */
- assert (expr_eval_stack[expr_eval_stack_index - 1].is_collectible);
- return expr_eval_stack[--expr_eval_stack_index].value.mutable_string;
+expr_eval_pop_string(void) {
+ if (expr_eval_stack_index == 0)
+ sc_fatal("expr_eval_pop_string: stack underflow\n");
+
+ /* Returns mutable string rather than const string. */
+ assert(expr_eval_stack[expr_eval_stack_index - 1].is_collectible);
+ return expr_eval_stack[--expr_eval_stack_index].value.mutable_string;
}
@@ -581,14 +539,13 @@ expr_eval_pop_string (void)
* Return the top of the values stack as the expression result.
*/
static void
-expr_eval_result (sc_vartype_t *vt_rvalue)
-{
- if (expr_eval_stack_index != 1)
- sc_fatal ("expr_eval_result: values stack not completed\n");
-
- /* Clear down stack and return the top value. */
- expr_eval_stack_index = 0;
- *vt_rvalue = expr_eval_stack[0].value;
+expr_eval_result(sc_vartype_t *vt_rvalue) {
+ if (expr_eval_stack_index != 1)
+ sc_fatal("expr_eval_result: values stack not completed\n");
+
+ /* Clear down stack and return the top value. */
+ expr_eval_stack_index = 0;
+ *vt_rvalue = expr_eval_stack[0].value;
}
@@ -599,9 +556,8 @@ expr_eval_result (sc_vartype_t *vt_rvalue)
* avoids tying sc_int to long types too closely.
*/
static sc_int
-expr_eval_abs (sc_int value)
-{
- return value < 0 ? -value : value;
+expr_eval_abs(sc_int value) {
+ return value < 0 ? -value : value;
}
@@ -614,525 +570,489 @@ static jmp_buf expr_parse_error;
* Evaluate the effect of a token into the values stack.
*/
static void
-expr_eval_action (sc_int token)
-{
- sc_vartype_t token_value;
-
- switch (token)
- {
- /* Handle tokens representing stack pushes. */
- case TOK_INTEGER:
- expr_current_token_value (&token_value);
- expr_eval_push_integer (token_value.integer);
- break;
-
- case TOK_STRING:
- expr_current_token_value (&token_value);
- expr_eval_push_string (token_value.string);
- break;
-
- case TOK_VARIABLE:
- {
- sc_vartype_t vt_rvalue;
- sc_int type;
-
- expr_current_token_value (&token_value);
- if (!var_get (expr_varset, token_value.string, &type, &vt_rvalue))
- {
- sc_error ("expr_eval_action:"
- " undefined variable, %s\n", token_value.string);
- longjmp (expr_parse_error, 1);
- }
- switch (type)
- {
- case VAR_INTEGER:
- expr_eval_push_integer (vt_rvalue.integer);
- break;
-
- case VAR_STRING:
- expr_eval_push_string (vt_rvalue.string);
- break;
-
- default:
- sc_fatal ("expr_eval_action: bad variable type\n");
- }
- break;
- }
-
- /* Handle tokens representing functions returning numeric. */
- case TOK_IF:
- {
- sc_int test, val1, val2;
-
- /* Pop the test and alternatives, and push back result. */
- val2 = expr_eval_pop_integer ();
- val1 = expr_eval_pop_integer ();
- test = expr_eval_pop_integer ();
- expr_eval_push_integer (test ? val1 : val2);
- break;
- }
-
- case TOK_MAX:
- case TOK_MIN:
- {
- sc_int argument_count, index_, result;
-
- /* Get argument count off the top of the stack. */
- argument_count = expr_eval_pop_integer ();
- assert (argument_count > 0);
-
- /* Find the max or min of these stacked values. */
- result = expr_eval_pop_integer ();
- for (index_ = 1; index_ < argument_count; index_++)
- {
- sc_int next;
-
- next = expr_eval_pop_integer ();
- switch (token)
- {
- case TOK_MAX:
- result = (next > result) ? next : result;
- break;
-
- case TOK_MIN:
- result = (next < result) ? next : result;
- break;
-
- default:
- sc_fatal ("expr_eval_action: bad token, %ld\n", token);
- }
- }
-
- /* Push back the result. */
- expr_eval_push_integer (result);
- break;
- }
-
- case TOK_EITHER:
- {
- sc_int argument_count, pick, index_;
- sc_int result = 0;
-
- /* Get argument count off the top of the stack. */
- argument_count = expr_eval_pop_integer ();
- assert (argument_count > 0);
-
- /*
- * Pick one of the top N items at random, then unstack all N and
- * push back the value of the one picked.
- */
- pick = sc_rand () % argument_count;
- for (index_ = 0; index_ < argument_count; index_++)
- {
- sc_int val;
-
- val = expr_eval_pop_integer ();
- if (index_ == pick)
- result = val;
- }
-
- /* Push back the result. */
- expr_eval_push_integer (result);
- break;
- }
-
- case TOK_INSTR:
- {
- sc_char *val1, *val2, *search;
- sc_int result;
-
- /* Extract the two values to work on. */
- val2 = expr_eval_pop_string ();
- val1 = expr_eval_pop_string ();
-
- /*
- * Search for the second in the first. The result is the character
- * position, starting at 1, or 0 if not found. Then free the popped
- * strings, and push back the result.
- */
- search = (val1[0] != NUL) ? strstr (val1, val2) : NULL;
- result = (!search) ? 0 : search - val1 + 1;
- sc_free (val1);
- sc_free (val2);
- expr_eval_push_integer (result);
- break;
- }
-
- case TOK_LEN:
- {
- sc_char *val;
- sc_int result;
-
- /* Pop the top string, and push back its length. */
- val = expr_eval_pop_string ();
- result = strlen (val);
- sc_free (val);
- expr_eval_push_integer (result);
- break;
- }
-
- case TOK_VAL:
- {
- sc_char *val;
- sc_int result = 0;
-
- /*
- * Extract the string at stack top, and try to convert, returning
- * zero if conversion fails. Free the popped string, and push back
- * the result.
- */
- val = expr_eval_pop_string ();
- sscanf (val, "%ld", &result);
- sc_free (val);
- expr_eval_push_integer (result);
- break;
- }
-
- /* Handle tokens representing unary numeric operations. */
- case TOK_UMINUS:
- expr_eval_push_integer (-(expr_eval_pop_integer ()));
- break;
-
- case TOK_UPLUS:
- break;
-
- case TOK_ABS:
- expr_eval_push_integer (expr_eval_abs (expr_eval_pop_integer ()));
- break;
-
- /* Handle tokens representing most binary numeric operations. */
- case TOK_ADD:
- case TOK_SUBTRACT:
- case TOK_MULTIPLY:
- case TOK_AND:
- case TOK_OR:
- case TOK_EQUAL:
- case TOK_GREATER:
- case TOK_LESS:
- case TOK_NOT_EQUAL:
- case TOK_GREATER_EQ:
- case TOK_LESS_EQ:
- case TOK_RANDOM:
- {
- sc_int val1, val2, result = 0;
-
- /* Extract the two values to work on. */
- val2 = expr_eval_pop_integer ();
- val1 = expr_eval_pop_integer ();
-
- /* Generate the result value. */
- switch (token)
- {
- case TOK_ADD:
- result = val1 + val2;
- break;
- case TOK_SUBTRACT:
- result = val1 - val2;
- break;
- case TOK_MULTIPLY:
- result = val1 * val2;
- break;
- case TOK_AND:
- result = val1 && val2;
- break;
- case TOK_OR:
- result = val1 || val2;
- break;
- case TOK_EQUAL:
- result = val1 == val2;
- break;
- case TOK_GREATER:
- result = val1 > val2;
- break;
- case TOK_LESS:
- result = val1 < val2;
- break;
- case TOK_NOT_EQUAL:
- result = val1 != val2;
- break;
- case TOK_GREATER_EQ:
- result = val1 >= val2;
- break;
- case TOK_LESS_EQ:
- result = val1 <= val2;
- break;
- case TOK_RANDOM:
- result = sc_randomint (val1, val2);
- break;
- default:
- sc_fatal ("expr_eval_action: bad token, %ld\n", token);
- }
-
- /* Put result back at top of stack. */
- expr_eval_push_integer (result);
- break;
- }
-
- /* Handle division and modulus separately; they're "eccentric". */
- case TOK_DIVIDE:
- case TOK_MOD:
- {
- sc_int val1, val2, x, y, result = 0;
-
- /* Extract the two values to work on, complain about division by 0. */
- val2 = expr_eval_pop_integer ();
- val1 = expr_eval_pop_integer ();
- if (val2 == 0)
- {
- sc_error ("expr_eval_action: attempt to divide by zero\n");
- expr_eval_push_integer (result);
- break;
- }
-
- /*
- * ANSI/ISO C only defines integer division for positive values.
- * Negative values usually work consistently across platforms, but are
- * not guaranteed. For maximum portability, then, here we'll work
- * carefully with positive integers only.
- */
- x = expr_eval_abs (val1);
- y = expr_eval_abs (val2);
-
- /* Generate the result value. */
- switch (token)
- {
- case TOK_DIVIDE:
- /*
- * Adrift's division apparently works by dividing using floating
- * point, then applying (asymmetrical) rounding, so we have to do
- * the same here.
- */
- result = ((val1 < 0) == (val2 < 0))
- ? ((x / y) + (((x % y) * 2 >= y) ? 1 : 0))
- : -((x / y) + (((x % y) * 2 > y) ? 1 : 0));
- break;
-
- case TOK_MOD:
- /*
- * Adrift also breaks numerical consistency by defining mod in a
- * conventional (non-rounded), way, so that A=(AdivB)*B+AmodB
- * does not hold.
- */
- result = (val1 < 0) ? -(x % y) : (x % y);
- break;
-
- default:
- sc_fatal ("expr_eval_action: bad token, %ld\n", token);
- }
-
- /* Put result back at top of stack. */
- expr_eval_push_integer (result);
- break;
- }
-
- /* Handle power individually, to avoid needing a maths library. */
- case TOK_POWER:
- {
- sc_int val1, val2, result;
-
- /* Extract the two values to work on. */
- val2 = expr_eval_pop_integer ();
- val1 = expr_eval_pop_integer ();
-
- /* Handle negative and zero power values first, as special cases. */
- if (val2 == 0)
- result = 1;
- else if (val2 < 0)
- {
- if (val1 == 0)
- {
- sc_error ("expr_eval_action: attempt to divide by zero\n");
- result = 0;
- }
- else if (val1 == 1)
- result = val1;
- else if (val1 == -1)
- result = (-val2 & 1) ? val1 : -val1;
- else
- result = 0;
- }
- else
- {
- /* Raise to positive powers using the Russian Peasant algorithm. */
- while ((val2 & 1) == 0)
- {
- val1 = val1 * val1;
- val2 >>= 1;
- }
-
- result = val1;
- val2 >>= 1;
- while (val2 > 0)
- {
- val1 = val1 * val1;
- if (val2 & 1)
- result = result * val1;
- val2 >>= 1;
- }
- }
-
- /* Put result back at top of stack. */
- expr_eval_push_integer (result);
- break;
- }
-
- /* Handle tokens representing functions returning string. */
- case TOK_LEFT:
- case TOK_RIGHT:
- {
- sc_char *text;
- sc_int length;
-
- /*
- * Extract the text and length. If length is longer than text, or
- * negative, do nothing.
- */
- length = expr_eval_pop_integer ();
- text = expr_eval_pop_string ();
- if (length < 0 || length >= (sc_int) strlen (text))
- {
- expr_eval_push_alloced_string (text);
- break;
- }
-
- /*
- * Take the left or right segment -- for left, the operation is a
- * simple truncation; for right, it's a memmove.
- */
- switch (token)
- {
- case TOK_LEFT:
- text[length] = NUL;
- break;
-
- case TOK_RIGHT:
- memmove (text, text + strlen (text) - length, length + 1);
- break;
-
- default:
- sc_fatal ("expr_eval_action: bad token, %ld\n", token);
- }
-
- /* Put result back at top of stack. */
- expr_eval_push_alloced_string (text);
- break;
- }
-
- case TOK_MID:
- {
- sc_char *text;
- sc_int length, start, limit;
-
- /*
- * Extract the text, start, and length, re-basing start from 1 to 0,
- * and calculate the limit on characters available for the move.
- */
- length = expr_eval_pop_integer ();
- start = expr_eval_pop_integer () - 1;
- text = expr_eval_pop_string ();
- limit = strlen (text);
-
- /*
- * Clamp ranges that roam outside the available text -- start less
- * than 0 to 0, and greater than len(text) to len(text), and length
- * less than 0 to 0, and off string end to string end.
- */
- if (start < 0)
- start = 0;
- else if (start > limit)
- start = limit;
- if (length < 0)
- length = 0;
- else if (length > limit - start)
- length = limit - start;
-
- /* Move substring, terminate, and put back at top of stack. */
- memmove (text, text + start, length + 1);
- text[length] = NUL;
- expr_eval_push_alloced_string (text);
- break;
- }
-
- case TOK_STR:
- {
- sc_int val;
- sc_char buffer[32];
-
- /*
- * Extract the value, convert it, and push back the resulting string.
- * The leading space on positive values matches the Runner.
- */
- val = expr_eval_pop_integer ();
- sprintf (buffer, "% ld", val);
- expr_eval_push_string (buffer);
- break;
- }
-
-
- /* Handle tokens representing unary string operations. */
- case TOK_UPPER:
- case TOK_LOWER:
- case TOK_PROPER:
- {
- sc_char *text;
- sc_int index_;
-
- /* Extract the value to work on. */
- text = expr_eval_pop_string ();
-
- /* Convert the entire string in place -- it's malloc'ed. */
- for (index_ = 0; text[index_] != NUL; index_++)
- {
- switch (token)
- {
- case TOK_UPPER:
- text[index_] = sc_toupper (text[index_]);
- break;
-
- case TOK_LOWER:
- text[index_] = sc_tolower (text[index_]);
- break;
-
- case TOK_PROPER:
- if (index_ == 0 || sc_isspace (text[index_ - 1]))
- text[index_] = sc_toupper (text[index_]);
- else
- text[index_] = sc_tolower (text[index_]);
- break;
-
- default:
- sc_fatal ("expr_eval_action: bad token, %ld\n", token);
- }
- }
-
- /* Put result back at top of stack. */
- expr_eval_push_alloced_string (text);
- break;
- }
-
- /* Handle token representing binary string operation. */
- case TOK_CONCATENATE:
- {
- sc_char *text1, *text2;
-
- /* Extract the two texts to work on. */
- text2 = expr_eval_pop_string ();
- text1 = expr_eval_pop_string ();
-
- /*
- * Resize text1 to be long enough for both, and concatenate, then
- * free text2, and push back the concatenation.
- */
- text1 = (sc_char *)sc_realloc (text1, strlen (text1) + strlen (text2) + 1);
- strcat (text1, text2);
- sc_free (text2);
- expr_eval_push_alloced_string (text1);
- break;
- }
-
- default:
- sc_fatal ("expr_eval_action: bad token, %ld\n", token);
- }
+expr_eval_action(sc_int token) {
+ sc_vartype_t token_value;
+
+ switch (token) {
+ /* Handle tokens representing stack pushes. */
+ case TOK_INTEGER:
+ expr_current_token_value(&token_value);
+ expr_eval_push_integer(token_value.integer);
+ break;
+
+ case TOK_STRING:
+ expr_current_token_value(&token_value);
+ expr_eval_push_string(token_value.string);
+ break;
+
+ case TOK_VARIABLE: {
+ sc_vartype_t vt_rvalue;
+ sc_int type;
+
+ expr_current_token_value(&token_value);
+ if (!var_get(expr_varset, token_value.string, &type, &vt_rvalue)) {
+ sc_error("expr_eval_action:"
+ " undefined variable, %s\n", token_value.string);
+ longjmp(expr_parse_error, 1);
+ }
+ switch (type) {
+ case VAR_INTEGER:
+ expr_eval_push_integer(vt_rvalue.integer);
+ break;
+
+ case VAR_STRING:
+ expr_eval_push_string(vt_rvalue.string);
+ break;
+
+ default:
+ sc_fatal("expr_eval_action: bad variable type\n");
+ }
+ break;
+ }
+
+ /* Handle tokens representing functions returning numeric. */
+ case TOK_IF: {
+ sc_int test, val1, val2;
+
+ /* Pop the test and alternatives, and push back result. */
+ val2 = expr_eval_pop_integer();
+ val1 = expr_eval_pop_integer();
+ test = expr_eval_pop_integer();
+ expr_eval_push_integer(test ? val1 : val2);
+ break;
+ }
+
+ case TOK_MAX:
+ case TOK_MIN: {
+ sc_int argument_count, index_, result;
+
+ /* Get argument count off the top of the stack. */
+ argument_count = expr_eval_pop_integer();
+ assert(argument_count > 0);
+
+ /* Find the max or min of these stacked values. */
+ result = expr_eval_pop_integer();
+ for (index_ = 1; index_ < argument_count; index_++) {
+ sc_int next;
+
+ next = expr_eval_pop_integer();
+ switch (token) {
+ case TOK_MAX:
+ result = (next > result) ? next : result;
+ break;
+
+ case TOK_MIN:
+ result = (next < result) ? next : result;
+ break;
+
+ default:
+ sc_fatal("expr_eval_action: bad token, %ld\n", token);
+ }
+ }
+
+ /* Push back the result. */
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ case TOK_EITHER: {
+ sc_int argument_count, pick, index_;
+ sc_int result = 0;
+
+ /* Get argument count off the top of the stack. */
+ argument_count = expr_eval_pop_integer();
+ assert(argument_count > 0);
+
+ /*
+ * Pick one of the top N items at random, then unstack all N and
+ * push back the value of the one picked.
+ */
+ pick = sc_rand() % argument_count;
+ for (index_ = 0; index_ < argument_count; index_++) {
+ sc_int val;
+
+ val = expr_eval_pop_integer();
+ if (index_ == pick)
+ result = val;
+ }
+
+ /* Push back the result. */
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ case TOK_INSTR: {
+ sc_char *val1, *val2, *search;
+ sc_int result;
+
+ /* Extract the two values to work on. */
+ val2 = expr_eval_pop_string();
+ val1 = expr_eval_pop_string();
+
+ /*
+ * Search for the second in the first. The result is the character
+ * position, starting at 1, or 0 if not found. Then free the popped
+ * strings, and push back the result.
+ */
+ search = (val1[0] != NUL) ? strstr(val1, val2) : NULL;
+ result = (!search) ? 0 : search - val1 + 1;
+ sc_free(val1);
+ sc_free(val2);
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ case TOK_LEN: {
+ sc_char *val;
+ sc_int result;
+
+ /* Pop the top string, and push back its length. */
+ val = expr_eval_pop_string();
+ result = strlen(val);
+ sc_free(val);
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ case TOK_VAL: {
+ sc_char *val;
+ sc_int result = 0;
+
+ /*
+ * Extract the string at stack top, and try to convert, returning
+ * zero if conversion fails. Free the popped string, and push back
+ * the result.
+ */
+ val = expr_eval_pop_string();
+ sscanf(val, "%ld", &result);
+ sc_free(val);
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ /* Handle tokens representing unary numeric operations. */
+ case TOK_UMINUS:
+ expr_eval_push_integer(-(expr_eval_pop_integer()));
+ break;
+
+ case TOK_UPLUS:
+ break;
+
+ case TOK_ABS:
+ expr_eval_push_integer(expr_eval_abs(expr_eval_pop_integer()));
+ break;
+
+ /* Handle tokens representing most binary numeric operations. */
+ case TOK_ADD:
+ case TOK_SUBTRACT:
+ case TOK_MULTIPLY:
+ case TOK_AND:
+ case TOK_OR:
+ case TOK_EQUAL:
+ case TOK_GREATER:
+ case TOK_LESS:
+ case TOK_NOT_EQUAL:
+ case TOK_GREATER_EQ:
+ case TOK_LESS_EQ:
+ case TOK_RANDOM: {
+ sc_int val1, val2, result = 0;
+
+ /* Extract the two values to work on. */
+ val2 = expr_eval_pop_integer();
+ val1 = expr_eval_pop_integer();
+
+ /* Generate the result value. */
+ switch (token) {
+ case TOK_ADD:
+ result = val1 + val2;
+ break;
+ case TOK_SUBTRACT:
+ result = val1 - val2;
+ break;
+ case TOK_MULTIPLY:
+ result = val1 * val2;
+ break;
+ case TOK_AND:
+ result = val1 && val2;
+ break;
+ case TOK_OR:
+ result = val1 || val2;
+ break;
+ case TOK_EQUAL:
+ result = val1 == val2;
+ break;
+ case TOK_GREATER:
+ result = val1 > val2;
+ break;
+ case TOK_LESS:
+ result = val1 < val2;
+ break;
+ case TOK_NOT_EQUAL:
+ result = val1 != val2;
+ break;
+ case TOK_GREATER_EQ:
+ result = val1 >= val2;
+ break;
+ case TOK_LESS_EQ:
+ result = val1 <= val2;
+ break;
+ case TOK_RANDOM:
+ result = sc_randomint(val1, val2);
+ break;
+ default:
+ sc_fatal("expr_eval_action: bad token, %ld\n", token);
+ }
+
+ /* Put result back at top of stack. */
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ /* Handle division and modulus separately; they're "eccentric". */
+ case TOK_DIVIDE:
+ case TOK_MOD: {
+ sc_int val1, val2, x, y, result = 0;
+
+ /* Extract the two values to work on, complain about division by 0. */
+ val2 = expr_eval_pop_integer();
+ val1 = expr_eval_pop_integer();
+ if (val2 == 0) {
+ sc_error("expr_eval_action: attempt to divide by zero\n");
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ /*
+ * ANSI/ISO C only defines integer division for positive values.
+ * Negative values usually work consistently across platforms, but are
+ * not guaranteed. For maximum portability, then, here we'll work
+ * carefully with positive integers only.
+ */
+ x = expr_eval_abs(val1);
+ y = expr_eval_abs(val2);
+
+ /* Generate the result value. */
+ switch (token) {
+ case TOK_DIVIDE:
+ /*
+ * Adrift's division apparently works by dividing using floating
+ * point, then applying (asymmetrical) rounding, so we have to do
+ * the same here.
+ */
+ result = ((val1 < 0) == (val2 < 0))
+ ? ((x / y) + (((x % y) * 2 >= y) ? 1 : 0))
+ : -((x / y) + (((x % y) * 2 > y) ? 1 : 0));
+ break;
+
+ case TOK_MOD:
+ /*
+ * Adrift also breaks numerical consistency by defining mod in a
+ * conventional (non-rounded), way, so that A=(AdivB)*B+AmodB
+ * does not hold.
+ */
+ result = (val1 < 0) ? -(x % y) : (x % y);
+ break;
+
+ default:
+ sc_fatal("expr_eval_action: bad token, %ld\n", token);
+ }
+
+ /* Put result back at top of stack. */
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ /* Handle power individually, to avoid needing a maths library. */
+ case TOK_POWER: {
+ sc_int val1, val2, result;
+
+ /* Extract the two values to work on. */
+ val2 = expr_eval_pop_integer();
+ val1 = expr_eval_pop_integer();
+
+ /* Handle negative and zero power values first, as special cases. */
+ if (val2 == 0)
+ result = 1;
+ else if (val2 < 0) {
+ if (val1 == 0) {
+ sc_error("expr_eval_action: attempt to divide by zero\n");
+ result = 0;
+ } else if (val1 == 1)
+ result = val1;
+ else if (val1 == -1)
+ result = (-val2 & 1) ? val1 : -val1;
+ else
+ result = 0;
+ } else {
+ /* Raise to positive powers using the Russian Peasant algorithm. */
+ while ((val2 & 1) == 0) {
+ val1 = val1 * val1;
+ val2 >>= 1;
+ }
+
+ result = val1;
+ val2 >>= 1;
+ while (val2 > 0) {
+ val1 = val1 * val1;
+ if (val2 & 1)
+ result = result * val1;
+ val2 >>= 1;
+ }
+ }
+
+ /* Put result back at top of stack. */
+ expr_eval_push_integer(result);
+ break;
+ }
+
+ /* Handle tokens representing functions returning string. */
+ case TOK_LEFT:
+ case TOK_RIGHT: {
+ sc_char *text;
+ sc_int length;
+
+ /*
+ * Extract the text and length. If length is longer than text, or
+ * negative, do nothing.
+ */
+ length = expr_eval_pop_integer();
+ text = expr_eval_pop_string();
+ if (length < 0 || length >= (sc_int) strlen(text)) {
+ expr_eval_push_alloced_string(text);
+ break;
+ }
+
+ /*
+ * Take the left or right segment -- for left, the operation is a
+ * simple truncation; for right, it's a memmove.
+ */
+ switch (token) {
+ case TOK_LEFT:
+ text[length] = NUL;
+ break;
+
+ case TOK_RIGHT:
+ memmove(text, text + strlen(text) - length, length + 1);
+ break;
+
+ default:
+ sc_fatal("expr_eval_action: bad token, %ld\n", token);
+ }
+
+ /* Put result back at top of stack. */
+ expr_eval_push_alloced_string(text);
+ break;
+ }
+
+ case TOK_MID: {
+ sc_char *text;
+ sc_int length, start, limit;
+
+ /*
+ * Extract the text, start, and length, re-basing start from 1 to 0,
+ * and calculate the limit on characters available for the move.
+ */
+ length = expr_eval_pop_integer();
+ start = expr_eval_pop_integer() - 1;
+ text = expr_eval_pop_string();
+ limit = strlen(text);
+
+ /*
+ * Clamp ranges that roam outside the available text -- start less
+ * than 0 to 0, and greater than len(text) to len(text), and length
+ * less than 0 to 0, and off string end to string end.
+ */
+ if (start < 0)
+ start = 0;
+ else if (start > limit)
+ start = limit;
+ if (length < 0)
+ length = 0;
+ else if (length > limit - start)
+ length = limit - start;
+
+ /* Move substring, terminate, and put back at top of stack. */
+ memmove(text, text + start, length + 1);
+ text[length] = NUL;
+ expr_eval_push_alloced_string(text);
+ break;
+ }
+
+ case TOK_STR: {
+ sc_int val;
+ sc_char buffer[32];
+
+ /*
+ * Extract the value, convert it, and push back the resulting string.
+ * The leading space on positive values matches the Runner.
+ */
+ val = expr_eval_pop_integer();
+ sprintf(buffer, "% ld", val);
+ expr_eval_push_string(buffer);
+ break;
+ }
+
+
+ /* Handle tokens representing unary string operations. */
+ case TOK_UPPER:
+ case TOK_LOWER:
+ case TOK_PROPER: {
+ sc_char *text;
+ sc_int index_;
+
+ /* Extract the value to work on. */
+ text = expr_eval_pop_string();
+
+ /* Convert the entire string in place -- it's malloc'ed. */
+ for (index_ = 0; text[index_] != NUL; index_++) {
+ switch (token) {
+ case TOK_UPPER:
+ text[index_] = sc_toupper(text[index_]);
+ break;
+
+ case TOK_LOWER:
+ text[index_] = sc_tolower(text[index_]);
+ break;
+
+ case TOK_PROPER:
+ if (index_ == 0 || sc_isspace(text[index_ - 1]))
+ text[index_] = sc_toupper(text[index_]);
+ else
+ text[index_] = sc_tolower(text[index_]);
+ break;
+
+ default:
+ sc_fatal("expr_eval_action: bad token, %ld\n", token);
+ }
+ }
+
+ /* Put result back at top of stack. */
+ expr_eval_push_alloced_string(text);
+ break;
+ }
+
+ /* Handle token representing binary string operation. */
+ case TOK_CONCATENATE: {
+ sc_char *text1, *text2;
+
+ /* Extract the two texts to work on. */
+ text2 = expr_eval_pop_string();
+ text1 = expr_eval_pop_string();
+
+ /*
+ * Resize text1 to be long enough for both, and concatenate, then
+ * free text2, and push back the concatenation.
+ */
+ text1 = (sc_char *)sc_realloc(text1, strlen(text1) + strlen(text2) + 1);
+ strcat(text1, text2);
+ sc_free(text2);
+ expr_eval_push_alloced_string(text1);
+ break;
+ }
+
+ default:
+ sc_fatal("expr_eval_action: bad token, %ld\n", token);
+ }
}
@@ -1140,9 +1060,9 @@ expr_eval_action (sc_int token)
static sc_int expr_parse_lookahead = TOK_NONE;
/* Forward declaration of factor parsers and string expression parser. */
-static void expr_parse_numeric_factor (void);
-static void expr_parse_string_factor (void);
-static void expr_parse_string_expr (void);
+static void expr_parse_numeric_factor(void);
+static void expr_parse_string_factor(void);
+static void expr_parse_string_expr(void);
/*
* expr_parse_match()
@@ -1150,17 +1070,15 @@ static void expr_parse_string_expr (void);
* Match a token to the lookahead, then advance lookahead.
*/
static void
-expr_parse_match (sc_int token)
-{
- if (expr_parse_lookahead == token)
- expr_parse_lookahead = expr_next_token ();
- else
- {
- /* Syntax error. */
- sc_error ("expr_parse_match: syntax error,"
- " expected %ld, got %ld\n", expr_parse_lookahead, token);
- longjmp (expr_parse_error, 1);
- }
+expr_parse_match(sc_int token) {
+ if (expr_parse_lookahead == token)
+ expr_parse_lookahead = expr_next_token();
+ else {
+ /* Syntax error. */
+ sc_error("expr_parse_match: syntax error,"
+ " expected %ld, got %ld\n", expr_parse_lookahead, token);
+ longjmp(expr_parse_error, 1);
+ }
}
@@ -1171,10 +1089,9 @@ expr_parse_match (sc_int token)
* a list with no operators (although in practice we need to put a TOK_NONE
* in here since some C compilers won't accept { } as an empty initializer).
*/
-typedef struct
-{
- const sc_int token_count;
- const sc_int tokens[6];
+typedef struct {
+ const sc_int token_count;
+ const sc_int tokens[6];
} sc_precedence_entry_t;
#if 0
/*
@@ -1183,14 +1100,14 @@ typedef struct
* comparisons, and boolean combiners.
*/
static const sc_precedence_entry_t PRECEDENCE_TABLE[] = {
- {1, {TOK_OR}},
- {1, {TOK_AND}},
- {2, {TOK_EQUAL, TOK_NOT_EQUAL}},
- {4, {TOK_GREATER, TOK_LESS, TOK_GREATER_EQ, TOK_LESS_EQ}},
- {2, {TOK_ADD, TOK_SUBTRACT}},
- {3, {TOK_MULTIPLY, TOK_DIVIDE, TOK_MOD}},
- {1, {TOK_POWER}},
- {0, {TOK_NONE}}
+ {1, {TOK_OR}},
+ {1, {TOK_AND}},
+ {2, {TOK_EQUAL, TOK_NOT_EQUAL}},
+ {4, {TOK_GREATER, TOK_LESS, TOK_GREATER_EQ, TOK_LESS_EQ}},
+ {2, {TOK_ADD, TOK_SUBTRACT}},
+ {3, {TOK_MULTIPLY, TOK_DIVIDE, TOK_MOD}},
+ {1, {TOK_POWER}},
+ {0, {TOK_NONE}}
};
#else
/*
@@ -1199,12 +1116,16 @@ static const sc_precedence_entry_t PRECEDENCE_TABLE[] = {
* subtraction, and boolean 'and' and 'or' have equal precedence.
*/
static const sc_precedence_entry_t PRECEDENCE_TABLE[] = {
- {2, {TOK_OR, TOK_AND}},
- {6, {TOK_EQUAL, TOK_NOT_EQUAL,
- TOK_GREATER, TOK_LESS, TOK_GREATER_EQ, TOK_LESS_EQ}},
- {4, {TOK_ADD, TOK_SUBTRACT, TOK_POWER, TOK_MOD}},
- {2, {TOK_MULTIPLY, TOK_DIVIDE}},
- {0, {TOK_NONE}}
+ {2, {TOK_OR, TOK_AND}},
+ {
+ 6, {
+ TOK_EQUAL, TOK_NOT_EQUAL,
+ TOK_GREATER, TOK_LESS, TOK_GREATER_EQ, TOK_LESS_EQ
+ }
+ },
+ {4, {TOK_ADD, TOK_SUBTRACT, TOK_POWER, TOK_MOD}},
+ {2, {TOK_MULTIPLY, TOK_DIVIDE}},
+ {0, {TOK_NONE}}
};
#endif
@@ -1216,23 +1137,20 @@ static const sc_precedence_entry_t PRECEDENCE_TABLE[] = {
* entry passed in, and return TRUE if it contains the given token.
*/
static int
-expr_parse_contains_token (const sc_precedence_entry_t *entry, sc_int token)
-{
- sc_bool is_matched;
- sc_int index_;
-
- /* Search the entry's token list for the token passed in. */
- is_matched = FALSE;
- for (index_ = 0; index_ < entry->token_count; index_++)
- {
- if (entry->tokens[index_] == token)
- {
- is_matched = TRUE;
- break;
- }
- }
-
- return is_matched;
+expr_parse_contains_token(const sc_precedence_entry_t *entry, sc_int token) {
+ sc_bool is_matched;
+ sc_int index_;
+
+ /* Search the entry's token list for the token passed in. */
+ is_matched = FALSE;
+ for (index_ = 0; index_ < entry->token_count; index_++) {
+ if (entry->tokens[index_] == token) {
+ is_matched = TRUE;
+ break;
+ }
+ }
+
+ return is_matched;
}
@@ -1244,34 +1162,31 @@ expr_parse_contains_token (const sc_precedence_entry_t *entry, sc_int token)
* whether to parse a highest-precedence factor.
*/
static void
-expr_parse_numeric_element (sc_int precedence)
-{
- const sc_precedence_entry_t *entry;
-
- /* See if the level passed in has listed tokens. */
- entry = PRECEDENCE_TABLE + precedence;
- if (entry->token_count == 0)
- {
- /* Precedence levels that hit the table end are factors. */
- expr_parse_numeric_factor ();
- return;
- }
-
- /*
- * Parse initial higher-precedence factor, then others that associate
- * with the given level.
- */
- expr_parse_numeric_element (precedence + 1);
- while (expr_parse_contains_token (entry, expr_parse_lookahead))
- {
- sc_int token;
-
- /* Note token and match, parse next level, then action this token. */
- token = expr_parse_lookahead;
- expr_parse_match (token);
- expr_parse_numeric_element (precedence + 1);
- expr_eval_action (token);
- }
+expr_parse_numeric_element(sc_int precedence) {
+ const sc_precedence_entry_t *entry;
+
+ /* See if the level passed in has listed tokens. */
+ entry = PRECEDENCE_TABLE + precedence;
+ if (entry->token_count == 0) {
+ /* Precedence levels that hit the table end are factors. */
+ expr_parse_numeric_factor();
+ return;
+ }
+
+ /*
+ * Parse initial higher-precedence factor, then others that associate
+ * with the given level.
+ */
+ expr_parse_numeric_element(precedence + 1);
+ while (expr_parse_contains_token(entry, expr_parse_lookahead)) {
+ sc_int token;
+
+ /* Note token and match, parse next level, then action this token. */
+ token = expr_parse_lookahead;
+ expr_parse_match(token);
+ expr_parse_numeric_element(precedence + 1);
+ expr_eval_action(token);
+ }
}
@@ -1281,10 +1196,9 @@ expr_parse_numeric_element (sc_int precedence)
* Parse a complete numeric (sub-)expression.
*/
static void
-expr_parse_numeric_expr (void)
-{
- /* Call the parser of the lowest precedence operators. */
- expr_parse_numeric_element (0);
+expr_parse_numeric_expr(void) {
+ /* Call the parser of the lowest precedence operators. */
+ expr_parse_numeric_element(0);
}
@@ -1294,161 +1208,155 @@ expr_parse_numeric_expr (void)
* Parse a numeric expression factor.
*/
static void
-expr_parse_numeric_factor (void)
-{
- /* Handle factors based on lookahead token. */
- switch (expr_parse_lookahead)
- {
- /* Handle straightforward factors first. */
- case TOK_LPAREN:
- expr_parse_match (TOK_LPAREN);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_RPAREN);
- break;
-
- case TOK_UMINUS:
- expr_parse_match (TOK_UMINUS);
- expr_parse_numeric_factor ();
- expr_eval_action (TOK_UMINUS);
- break;
-
- case TOK_UPLUS:
- expr_parse_match (TOK_UPLUS);
- expr_parse_numeric_factor ();
- break;
-
- case TOK_INTEGER:
- expr_eval_action (TOK_INTEGER);
- expr_parse_match (TOK_INTEGER);
- break;
-
- case TOK_VARIABLE:
- {
- sc_vartype_t token_value, vt_rvalue;
- sc_int type;
-
- expr_current_token_value (&token_value);
- if (!var_get (expr_varset, token_value.string, &type, &vt_rvalue))
- {
- sc_error ("expr_parse_numeric_factor:"
- " undefined variable, %s\n", token_value.string);
- longjmp (expr_parse_error, 1);
- }
- if (type != VAR_INTEGER)
- {
- sc_error ("expr_parse_numeric_factor:"
- " string variable in numeric context, %s\n",
- token_value.string);
- longjmp (expr_parse_error, 1);
- }
- expr_eval_action (TOK_VARIABLE);
- expr_parse_match (TOK_VARIABLE);
- break;
- }
-
- /* Handle functions as factors. */
- case TOK_ABS:
- /* Parse as "abs (val)". */
- expr_parse_match (TOK_ABS);
- expr_parse_match (TOK_LPAREN);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (TOK_ABS);
- break;
-
- case TOK_IF:
- /* Parse as "if (boolean, val1, val2)". */
- expr_parse_match (TOK_IF);
- expr_parse_match (TOK_LPAREN);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_COMMA);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_COMMA);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (TOK_IF);
- break;
-
- case TOK_RANDOM:
- /* Parse as "random (low, high)". */
- expr_parse_match (TOK_RANDOM);
- expr_parse_match (TOK_LPAREN);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_COMMA);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (TOK_RANDOM);
- break;
-
- case TOK_MAX:
- case TOK_MIN:
- case TOK_EITHER:
- /* Parse as "<func> (val1[,val2[,val3...]]])". */
- {
- sc_int token, argument_count;
-
- /* Match up the function name and opening parenthesis. */
- token = expr_parse_lookahead;
- expr_parse_match (token);
- expr_parse_match (TOK_LPAREN);
-
- /* Count variable number of arguments as they are stacked. */
- expr_parse_numeric_expr ();
- argument_count = 1;
- while (expr_parse_lookahead == TOK_COMMA)
- {
- expr_parse_match (TOK_COMMA);
- expr_parse_numeric_expr ();
- argument_count++;
- }
- expr_parse_match (TOK_RPAREN);
-
- /* Push additional value -- the count of arguments. */
- expr_eval_push_integer (argument_count);
- expr_eval_action (token);
- break;
- }
-
- case TOK_INSTR:
- /* Parse as "instr (val1, val2)". */
- expr_parse_match (TOK_INSTR);
- expr_parse_match (TOK_LPAREN);
- expr_parse_string_expr ();
- expr_parse_match (TOK_COMMA);
- expr_parse_string_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (TOK_INSTR);
- break;
-
- case TOK_LEN:
- /* Parse as "len (val)". */
- expr_parse_match (TOK_LEN);
- expr_parse_match (TOK_LPAREN);
- expr_parse_string_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (TOK_LEN);
- break;
-
- case TOK_VAL:
- /* Parse as "val (val)". */
- expr_parse_match (TOK_VAL);
- expr_parse_match (TOK_LPAREN);
- expr_parse_string_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (TOK_VAL);
- break;
-
- case TOK_IDENT:
- /* Unrecognized function-type token. */
- sc_error ("expr_parse_numeric_factor: syntax error, unknown ident\n");
- longjmp (expr_parse_error, 1);
-
- default:
- /* Syntax error. */
- sc_error ("expr_parse_numeric_factor:"
- " syntax error, unexpected token, %ld\n", expr_parse_lookahead);
- longjmp (expr_parse_error, 1);
- }
+expr_parse_numeric_factor(void) {
+ /* Handle factors based on lookahead token. */
+ switch (expr_parse_lookahead) {
+ /* Handle straightforward factors first. */
+ case TOK_LPAREN:
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_RPAREN);
+ break;
+
+ case TOK_UMINUS:
+ expr_parse_match(TOK_UMINUS);
+ expr_parse_numeric_factor();
+ expr_eval_action(TOK_UMINUS);
+ break;
+
+ case TOK_UPLUS:
+ expr_parse_match(TOK_UPLUS);
+ expr_parse_numeric_factor();
+ break;
+
+ case TOK_INTEGER:
+ expr_eval_action(TOK_INTEGER);
+ expr_parse_match(TOK_INTEGER);
+ break;
+
+ case TOK_VARIABLE: {
+ sc_vartype_t token_value, vt_rvalue;
+ sc_int type;
+
+ expr_current_token_value(&token_value);
+ if (!var_get(expr_varset, token_value.string, &type, &vt_rvalue)) {
+ sc_error("expr_parse_numeric_factor:"
+ " undefined variable, %s\n", token_value.string);
+ longjmp(expr_parse_error, 1);
+ }
+ if (type != VAR_INTEGER) {
+ sc_error("expr_parse_numeric_factor:"
+ " string variable in numeric context, %s\n",
+ token_value.string);
+ longjmp(expr_parse_error, 1);
+ }
+ expr_eval_action(TOK_VARIABLE);
+ expr_parse_match(TOK_VARIABLE);
+ break;
+ }
+
+ /* Handle functions as factors. */
+ case TOK_ABS:
+ /* Parse as "abs (val)". */
+ expr_parse_match(TOK_ABS);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(TOK_ABS);
+ break;
+
+ case TOK_IF:
+ /* Parse as "if (boolean, val1, val2)". */
+ expr_parse_match(TOK_IF);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_COMMA);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_COMMA);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(TOK_IF);
+ break;
+
+ case TOK_RANDOM:
+ /* Parse as "random (low, high)". */
+ expr_parse_match(TOK_RANDOM);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_COMMA);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(TOK_RANDOM);
+ break;
+
+ case TOK_MAX:
+ case TOK_MIN:
+ case TOK_EITHER:
+ /* Parse as "<func> (val1[,val2[,val3...]]])". */
+ {
+ sc_int token, argument_count;
+
+ /* Match up the function name and opening parenthesis. */
+ token = expr_parse_lookahead;
+ expr_parse_match(token);
+ expr_parse_match(TOK_LPAREN);
+
+ /* Count variable number of arguments as they are stacked. */
+ expr_parse_numeric_expr();
+ argument_count = 1;
+ while (expr_parse_lookahead == TOK_COMMA) {
+ expr_parse_match(TOK_COMMA);
+ expr_parse_numeric_expr();
+ argument_count++;
+ }
+ expr_parse_match(TOK_RPAREN);
+
+ /* Push additional value -- the count of arguments. */
+ expr_eval_push_integer(argument_count);
+ expr_eval_action(token);
+ break;
+ }
+
+ case TOK_INSTR:
+ /* Parse as "instr (val1, val2)". */
+ expr_parse_match(TOK_INSTR);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_string_expr();
+ expr_parse_match(TOK_COMMA);
+ expr_parse_string_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(TOK_INSTR);
+ break;
+
+ case TOK_LEN:
+ /* Parse as "len (val)". */
+ expr_parse_match(TOK_LEN);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_string_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(TOK_LEN);
+ break;
+
+ case TOK_VAL:
+ /* Parse as "val (val)". */
+ expr_parse_match(TOK_VAL);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_string_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(TOK_VAL);
+ break;
+
+ case TOK_IDENT:
+ /* Unrecognized function-type token. */
+ sc_error("expr_parse_numeric_factor: syntax error, unknown ident\n");
+ longjmp(expr_parse_error, 1);
+
+ default:
+ /* Syntax error. */
+ sc_error("expr_parse_numeric_factor:"
+ " syntax error, unexpected token, %ld\n", expr_parse_lookahead);
+ longjmp(expr_parse_error, 1);
+ }
}
@@ -1458,20 +1366,18 @@ expr_parse_numeric_factor (void)
* Parse a complete string (sub-)expression.
*/
static void
-expr_parse_string_expr (void)
-{
- /*
- * Parse a string factor, then all repeated concatenations. Because the '+'
- * and '&' are context sensitive, we have to invent/translate them into the
- * otherwise unused TOK_CONCATENATE for evaluation.
- */
- expr_parse_string_factor ();
- while (expr_parse_lookahead == TOK_AND || expr_parse_lookahead == TOK_ADD)
- {
- expr_parse_match (expr_parse_lookahead);
- expr_parse_string_factor ();
- expr_eval_action (TOK_CONCATENATE);
- }
+expr_parse_string_expr(void) {
+ /*
+ * Parse a string factor, then all repeated concatenations. Because the '+'
+ * and '&' are context sensitive, we have to invent/translate them into the
+ * otherwise unused TOK_CONCATENATE for evaluation.
+ */
+ expr_parse_string_factor();
+ while (expr_parse_lookahead == TOK_AND || expr_parse_lookahead == TOK_ADD) {
+ expr_parse_match(expr_parse_lookahead);
+ expr_parse_string_factor();
+ expr_eval_action(TOK_CONCATENATE);
+ }
}
@@ -1481,114 +1387,109 @@ expr_parse_string_expr (void)
* Parse a string expression factor.
*/
static void
-expr_parse_string_factor (void)
-{
- /* Handle factors based on lookahead token. */
- switch (expr_parse_lookahead)
- {
- /* Handle straightforward factors first. */
- case TOK_LPAREN:
- expr_parse_match (TOK_LPAREN);
- expr_parse_string_expr ();
- expr_parse_match (TOK_RPAREN);
- break;
-
- case TOK_STRING:
- expr_eval_action (TOK_STRING);
- expr_parse_match (TOK_STRING);
- break;
-
- case TOK_VARIABLE:
- {
- sc_vartype_t token_value, vt_rvalue;
- sc_int type;
-
- expr_current_token_value (&token_value);
- if (!var_get (expr_varset, token_value.string, &type, &vt_rvalue))
- {
- sc_error ("expr_parse_string_factor:"
- " undefined variable, %s\n", token_value.string);
- longjmp (expr_parse_error, 1);
- }
- if (type != VAR_STRING)
- {
- sc_error ("expr_parse_string_factor:"
- " numeric variable in string context, %s\n",
- token_value.string);
- longjmp (expr_parse_error, 1);
- }
- expr_eval_action (TOK_VARIABLE);
- expr_parse_match (TOK_VARIABLE);
- break;
- }
-
- /* Handle functions as factors. */
- case TOK_UPPER:
- case TOK_LOWER:
- case TOK_PROPER:
- /* Parse as "<func> (text)". */
- {
- sc_int token;
-
- token = expr_parse_lookahead;
- expr_parse_match (token);
- expr_parse_match (TOK_LPAREN);
- expr_parse_string_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (token);
- break;
- }
-
- case TOK_LEFT:
- case TOK_RIGHT:
- /* Parse as "<func> (text,length)". */
- {
- sc_int token;
-
- token = expr_parse_lookahead;
- expr_parse_match (token);
- expr_parse_match (TOK_LPAREN);
- expr_parse_string_expr ();
- expr_parse_match (TOK_COMMA);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (token);
- break;
- }
-
- case TOK_MID:
- /* Parse as "mid (text,start,length)". */
- expr_parse_match (TOK_MID);
- expr_parse_match (TOK_LPAREN);
- expr_parse_string_expr ();
- expr_parse_match (TOK_COMMA);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_COMMA);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (TOK_MID);
- break;
-
- case TOK_STR:
- /* Parse as "str (val)". */
- expr_parse_match (TOK_STR);
- expr_parse_match (TOK_LPAREN);
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_RPAREN);
- expr_eval_action (TOK_STR);
- break;
-
- case TOK_IDENT:
- /* Unrecognized function-type token. */
- sc_error ("expr_parse_string_factor: syntax error, unknown ident\n");
- longjmp (expr_parse_error, 1);
-
- default:
- /* Syntax error. */
- sc_error ("expr_parse_string_factor:"
- " syntax error, unexpected token, %ld\n", expr_parse_lookahead);
- longjmp (expr_parse_error, 1);
- }
+expr_parse_string_factor(void) {
+ /* Handle factors based on lookahead token. */
+ switch (expr_parse_lookahead) {
+ /* Handle straightforward factors first. */
+ case TOK_LPAREN:
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_string_expr();
+ expr_parse_match(TOK_RPAREN);
+ break;
+
+ case TOK_STRING:
+ expr_eval_action(TOK_STRING);
+ expr_parse_match(TOK_STRING);
+ break;
+
+ case TOK_VARIABLE: {
+ sc_vartype_t token_value, vt_rvalue;
+ sc_int type;
+
+ expr_current_token_value(&token_value);
+ if (!var_get(expr_varset, token_value.string, &type, &vt_rvalue)) {
+ sc_error("expr_parse_string_factor:"
+ " undefined variable, %s\n", token_value.string);
+ longjmp(expr_parse_error, 1);
+ }
+ if (type != VAR_STRING) {
+ sc_error("expr_parse_string_factor:"
+ " numeric variable in string context, %s\n",
+ token_value.string);
+ longjmp(expr_parse_error, 1);
+ }
+ expr_eval_action(TOK_VARIABLE);
+ expr_parse_match(TOK_VARIABLE);
+ break;
+ }
+
+ /* Handle functions as factors. */
+ case TOK_UPPER:
+ case TOK_LOWER:
+ case TOK_PROPER:
+ /* Parse as "<func> (text)". */
+ {
+ sc_int token;
+
+ token = expr_parse_lookahead;
+ expr_parse_match(token);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_string_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(token);
+ break;
+ }
+
+ case TOK_LEFT:
+ case TOK_RIGHT:
+ /* Parse as "<func> (text,length)". */
+ {
+ sc_int token;
+
+ token = expr_parse_lookahead;
+ expr_parse_match(token);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_string_expr();
+ expr_parse_match(TOK_COMMA);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(token);
+ break;
+ }
+
+ case TOK_MID:
+ /* Parse as "mid (text,start,length)". */
+ expr_parse_match(TOK_MID);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_string_expr();
+ expr_parse_match(TOK_COMMA);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_COMMA);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(TOK_MID);
+ break;
+
+ case TOK_STR:
+ /* Parse as "str (val)". */
+ expr_parse_match(TOK_STR);
+ expr_parse_match(TOK_LPAREN);
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_RPAREN);
+ expr_eval_action(TOK_STR);
+ break;
+
+ case TOK_IDENT:
+ /* Unrecognized function-type token. */
+ sc_error("expr_parse_string_factor: syntax error, unknown ident\n");
+ longjmp(expr_parse_error, 1);
+
+ default:
+ /* Syntax error. */
+ sc_error("expr_parse_string_factor:"
+ " syntax error, unexpected token, %ld\n", expr_parse_lookahead);
+ longjmp(expr_parse_error, 1);
+ }
}
@@ -1599,38 +1500,34 @@ expr_parse_string_factor (void)
* value of the expression.
*/
static sc_bool
-expr_evaluate_expression (const sc_char *expression, sc_var_setref_t vars,
- sc_int assign_type, sc_vartype_t *vt_rvalue)
-{
- assert (assign_type == VAR_INTEGER || assign_type == VAR_STRING);
-
- /* Reset values stack and start tokenizer. */
- expr_eval_start (vars);
- expr_tokenize_start (expression);
-
- /* Try parsing an expression, and catch errors. */
- if (setjmp (expr_parse_error) == 0)
- {
- /* Parse an expression, and ensure it ends at string end. */
- expr_parse_lookahead = expr_next_token ();
- if (assign_type == VAR_STRING)
- expr_parse_string_expr ();
- else
- expr_parse_numeric_expr ();
- expr_parse_match (TOK_EOS);
- }
- else
- {
- /* Parse error -- clean up tokenizer, collect garbage, and fail. */
- expr_tokenize_end ();
- expr_eval_garbage_collect ();
- return FALSE;
- }
-
- /* Clean up tokenizer and return successfully with result. */
- expr_tokenize_end ();
- expr_eval_result (vt_rvalue);
- return TRUE;
+expr_evaluate_expression(const sc_char *expression, sc_var_setref_t vars,
+ sc_int assign_type, sc_vartype_t *vt_rvalue) {
+ assert(assign_type == VAR_INTEGER || assign_type == VAR_STRING);
+
+ /* Reset values stack and start tokenizer. */
+ expr_eval_start(vars);
+ expr_tokenize_start(expression);
+
+ /* Try parsing an expression, and catch errors. */
+ if (setjmp(expr_parse_error) == 0) {
+ /* Parse an expression, and ensure it ends at string end. */
+ expr_parse_lookahead = expr_next_token();
+ if (assign_type == VAR_STRING)
+ expr_parse_string_expr();
+ else
+ expr_parse_numeric_expr();
+ expr_parse_match(TOK_EOS);
+ } else {
+ /* Parse error -- clean up tokenizer, collect garbage, and fail. */
+ expr_tokenize_end();
+ expr_eval_garbage_collect();
+ return FALSE;
+ }
+
+ /* Clean up tokenizer and return successfully with result. */
+ expr_tokenize_end();
+ expr_eval_result(vt_rvalue);
+ return TRUE;
}
@@ -1644,33 +1541,31 @@ expr_evaluate_expression (const sc_char *expression, sc_var_setref_t vars,
* it.
*/
sc_bool
-expr_eval_numeric_expression (const sc_char *expression,
- sc_var_setref_t vars, sc_int *rvalue)
-{
- sc_vartype_t vt_rvalue;
- sc_bool status;
- assert (expression && vars && rvalue);
-
- /* Evaluate numeric expression, and return value if valid. */
- status = expr_evaluate_expression (expression, vars, VAR_INTEGER, &vt_rvalue);
- if (status)
- *rvalue = vt_rvalue.integer;
- return status;
+expr_eval_numeric_expression(const sc_char *expression,
+ sc_var_setref_t vars, sc_int *rvalue) {
+ sc_vartype_t vt_rvalue;
+ sc_bool status;
+ assert(expression && vars && rvalue);
+
+ /* Evaluate numeric expression, and return value if valid. */
+ status = expr_evaluate_expression(expression, vars, VAR_INTEGER, &vt_rvalue);
+ if (status)
+ *rvalue = vt_rvalue.integer;
+ return status;
}
sc_bool
-expr_eval_string_expression (const sc_char *expression,
- sc_var_setref_t vars, sc_char **rvalue)
-{
- sc_vartype_t vt_rvalue;
- sc_bool status;
- assert (expression && vars && rvalue);
-
- /* Evaluate string expression, and return value if valid. */
- status = expr_evaluate_expression (expression, vars, VAR_STRING, &vt_rvalue);
- if (status)
- *rvalue = vt_rvalue.mutable_string;
- return status;
+expr_eval_string_expression(const sc_char *expression,
+ sc_var_setref_t vars, sc_char **rvalue) {
+ sc_vartype_t vt_rvalue;
+ sc_bool status;
+ assert(expression && vars && rvalue);
+
+ /* Evaluate string expression, and return value if valid. */
+ status = expr_evaluate_expression(expression, vars, VAR_STRING, &vt_rvalue);
+ if (status)
+ *rvalue = vt_rvalue.mutable_string;
+ return status;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scgamest.cpp b/engines/glk/adrift/scgamest.cpp
index 2d9d78fbb3..f2af6b85d6 100644
--- a/engines/glk/adrift/scgamest.cpp
+++ b/engines/glk/adrift/scgamest.cpp
@@ -37,30 +37,26 @@ static const sc_uint GAME_MAGIC = 0x35aed26e;
* Move the player to a given room, and check presence in a given room.
*/
void
-gs_move_player_to_room (sc_gameref_t game, sc_int room)
-{
- assert(gs_is_game_valid (game));
+gs_move_player_to_room(sc_gameref_t game, sc_int room) {
+ assert(gs_is_game_valid(game));
- if (room < 0)
- {
- sc_fatal ("gs_move_player_to_room: invalid room, %ld\n", room);
- return;
- }
- else if (room < game->room_count)
- game->playerroom = room;
- else
- game->playerroom = lib_random_roomgroup_member (game,
- room - game->room_count);
+ if (room < 0) {
+ sc_fatal("gs_move_player_to_room: invalid room, %ld\n", room);
+ return;
+ } else if (room < game->room_count)
+ game->playerroom = room;
+ else
+ game->playerroom = lib_random_roomgroup_member(game,
+ room - game->room_count);
- game->playerparent = -1;
- game->playerposition = 0;
+ game->playerparent = -1;
+ game->playerposition = 0;
}
sc_bool
-gs_player_in_room (sc_gameref_t game, sc_int room)
-{
- assert(gs_is_game_valid (game));
- return game->playerroom == room;
+gs_player_in_room(sc_gameref_t game, sc_int room) {
+ assert(gs_is_game_valid(game));
+ return game->playerroom == room;
}
@@ -70,9 +66,8 @@ gs_player_in_room (sc_gameref_t game, sc_int room)
* Helper for event, room, object, and npc range assertions.
*/
static sc_bool
-gs_in_range (sc_int value, sc_int limit)
-{
- return value >= 0 && value < limit;
+gs_in_range(sc_int value, sc_int limit) {
+ return value >= 0 && value < limit;
}
@@ -82,31 +77,27 @@ gs_in_range (sc_int value, sc_int limit)
* Game accessors and mutators.
*/
sc_var_setref_t
-gs_get_vars (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->vars;
+gs_get_vars(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->vars;
}
sc_prop_setref_t
-gs_get_bundle (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->bundle;
+gs_get_bundle(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->bundle;
}
sc_filterref_t
-gs_get_filter (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->filter;
+gs_get_filter(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->filter;
}
sc_memo_setref_t
-gs_get_memento (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->memento;
+gs_get_memento(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->memento;
}
@@ -114,45 +105,39 @@ gs_get_memento (sc_gameref_t gs)
* Game accessors and mutators for the player.
*/
void
-gs_set_playerroom (sc_gameref_t gs, sc_int room)
-{
- assert(gs_is_game_valid (gs));
- gs->playerroom = room;
+gs_set_playerroom(sc_gameref_t gs, sc_int room) {
+ assert(gs_is_game_valid(gs));
+ gs->playerroom = room;
}
void
-gs_set_playerposition (sc_gameref_t gs, sc_int position)
-{
- assert(gs_is_game_valid (gs));
- gs->playerposition = position;
+gs_set_playerposition(sc_gameref_t gs, sc_int position) {
+ assert(gs_is_game_valid(gs));
+ gs->playerposition = position;
}
void
-gs_set_playerparent (sc_gameref_t gs, sc_int parent)
-{
- assert(gs_is_game_valid (gs));
- gs->playerparent = parent;
+gs_set_playerparent(sc_gameref_t gs, sc_int parent) {
+ assert(gs_is_game_valid(gs));
+ gs->playerparent = parent;
}
sc_int
-gs_playerroom (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->playerroom;
+gs_playerroom(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->playerroom;
}
sc_int
-gs_playerposition (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->playerposition;
+gs_playerposition(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->playerposition;
}
sc_int
-gs_playerparent (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->playerparent;
+gs_playerparent(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->playerparent;
}
@@ -160,45 +145,39 @@ gs_playerparent (sc_gameref_t gs)
* Game accessors and mutators for events.
*/
sc_int
-gs_event_count (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->event_count;
+gs_event_count(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->event_count;
}
void
-gs_set_event_state (sc_gameref_t gs, sc_int event, sc_int state)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (event, gs->event_count));
- gs->events[event].state = state;
+gs_set_event_state(sc_gameref_t gs, sc_int event, sc_int state) {
+ assert(gs_is_game_valid(gs) && gs_in_range(event, gs->event_count));
+ gs->events[event].state = state;
}
void
-gs_set_event_time (sc_gameref_t gs, sc_int event, sc_int etime)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (event, gs->event_count));
- gs->events[event].time = etime;
+gs_set_event_time(sc_gameref_t gs, sc_int event, sc_int etime) {
+ assert(gs_is_game_valid(gs) && gs_in_range(event, gs->event_count));
+ gs->events[event].time = etime;
}
sc_int
-gs_event_state (sc_gameref_t gs, sc_int event)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (event, gs->event_count));
- return gs->events[event].state;
+gs_event_state(sc_gameref_t gs, sc_int event) {
+ assert(gs_is_game_valid(gs) && gs_in_range(event, gs->event_count));
+ return gs->events[event].state;
}
sc_int
-gs_event_time (sc_gameref_t gs, sc_int event)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (event, gs->event_count));
- return gs->events[event].time;
+gs_event_time(sc_gameref_t gs, sc_int event) {
+ assert(gs_is_game_valid(gs) && gs_in_range(event, gs->event_count));
+ return gs->events[event].time;
}
void
-gs_decrement_event_time (sc_gameref_t gs, sc_int event)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (event, gs->event_count));
- gs->events[event].time--;
+gs_decrement_event_time(sc_gameref_t gs, sc_int event) {
+ assert(gs_is_game_valid(gs) && gs_in_range(event, gs->event_count));
+ gs->events[event].time--;
}
@@ -206,24 +185,21 @@ gs_decrement_event_time (sc_gameref_t gs, sc_int event)
* Game accessors and mutators for rooms.
*/
sc_int
-gs_room_count (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->room_count;
+gs_room_count(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->room_count;
}
void
-gs_set_room_seen (sc_gameref_t gs, sc_int room, sc_bool seen)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (room, gs->room_count));
- gs->rooms[room].visited = seen;
+gs_set_room_seen(sc_gameref_t gs, sc_int room, sc_bool seen) {
+ assert(gs_is_game_valid(gs) && gs_in_range(room, gs->room_count));
+ gs->rooms[room].visited = seen;
}
sc_bool
-gs_room_seen (sc_gameref_t gs, sc_int room)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (room, gs->room_count));
- return gs->rooms[room].visited;
+gs_room_seen(sc_gameref_t gs, sc_int room) {
+ assert(gs_is_game_valid(gs) && gs_in_range(room, gs->room_count));
+ return gs->rooms[room].visited;
}
@@ -231,38 +207,33 @@ gs_room_seen (sc_gameref_t gs, sc_int room)
* Game accessors and mutators for tasks.
*/
sc_int
-gs_task_count (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->task_count;
+gs_task_count(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->task_count;
}
void
-gs_set_task_done (sc_gameref_t gs, sc_int task, sc_bool done)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (task, gs->task_count));
- gs->tasks[task].done = done;
+gs_set_task_done(sc_gameref_t gs, sc_int task, sc_bool done) {
+ assert(gs_is_game_valid(gs) && gs_in_range(task, gs->task_count));
+ gs->tasks[task].done = done;
}
void
-gs_set_task_scored (sc_gameref_t gs, sc_int task, sc_bool scored)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (task, gs->task_count));
- gs->tasks[task].scored = scored;
+gs_set_task_scored(sc_gameref_t gs, sc_int task, sc_bool scored) {
+ assert(gs_is_game_valid(gs) && gs_in_range(task, gs->task_count));
+ gs->tasks[task].scored = scored;
}
sc_bool
-gs_task_done (sc_gameref_t gs, sc_int task)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (task, gs->task_count));
- return gs->tasks[task].done;
+gs_task_done(sc_gameref_t gs, sc_int task) {
+ assert(gs_is_game_valid(gs) && gs_in_range(task, gs->task_count));
+ return gs->tasks[task].done;
}
sc_bool
-gs_task_scored (sc_gameref_t gs, sc_int task)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (task, gs->task_count));
- return gs->tasks[task].scored;
+gs_task_scored(sc_gameref_t gs, sc_int task) {
+ assert(gs_is_game_valid(gs) && gs_in_range(task, gs->task_count));
+ return gs->tasks[task].scored;
}
@@ -270,250 +241,213 @@ gs_task_scored (sc_gameref_t gs, sc_int task)
* Game accessors and mutators for objects.
*/
sc_int
-gs_object_count (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->object_count;
+gs_object_count(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->object_count;
}
void
-gs_set_object_openness (sc_gameref_t gs, sc_int object, sc_int openness)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].openness = openness;
+gs_set_object_openness(sc_gameref_t gs, sc_int object, sc_int openness) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].openness = openness;
}
void
-gs_set_object_state (sc_gameref_t gs, sc_int object, sc_int state)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].state = state;
+gs_set_object_state(sc_gameref_t gs, sc_int object, sc_int state) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].state = state;
}
void
-gs_set_object_seen (sc_gameref_t gs, sc_int object, sc_bool seen)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].seen = seen;
+gs_set_object_seen(sc_gameref_t gs, sc_int object, sc_bool seen) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].seen = seen;
}
void
-gs_set_object_unmoved (sc_gameref_t gs, sc_int object, sc_bool unmoved)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].unmoved = unmoved;
+gs_set_object_unmoved(sc_gameref_t gs, sc_int object, sc_bool unmoved) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].unmoved = unmoved;
}
void
-gs_set_object_static_unmoved (sc_gameref_t gs, sc_int object, sc_bool unmoved)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].static_unmoved = unmoved;
+gs_set_object_static_unmoved(sc_gameref_t gs, sc_int object, sc_bool unmoved) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].static_unmoved = unmoved;
}
sc_int
-gs_object_openness (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- return gs->objects[object].openness;
+gs_object_openness(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ return gs->objects[object].openness;
}
sc_int
-gs_object_state (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- return gs->objects[object].state;
+gs_object_state(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ return gs->objects[object].state;
}
sc_bool
-gs_object_seen (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- return gs->objects[object].seen;
+gs_object_seen(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ return gs->objects[object].seen;
}
sc_bool
-gs_object_unmoved (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- return gs->objects[object].unmoved;
+gs_object_unmoved(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ return gs->objects[object].unmoved;
}
sc_bool
-gs_object_static_unmoved (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- return gs->objects[object].static_unmoved;
+gs_object_static_unmoved(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ return gs->objects[object].static_unmoved;
}
sc_int
-gs_object_position (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- return gs->objects[object].position;
+gs_object_position(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ return gs->objects[object].position;
}
sc_int
-gs_object_parent (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- return gs->objects[object].parent;
+gs_object_parent(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ return gs->objects[object].parent;
}
static void
-gs_object_move_onto_unchecked (sc_gameref_t gs, sc_int object, sc_int onto)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].position = OBJ_ON_OBJECT;
- gs->objects[object].parent = onto;
+gs_object_move_onto_unchecked(sc_gameref_t gs, sc_int object, sc_int onto) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].position = OBJ_ON_OBJECT;
+ gs->objects[object].parent = onto;
}
static void
-gs_object_move_into_unchecked (sc_gameref_t gs, sc_int object, sc_int into)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].position = OBJ_IN_OBJECT;
- gs->objects[object].parent = into;
+gs_object_move_into_unchecked(sc_gameref_t gs, sc_int object, sc_int into) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].position = OBJ_IN_OBJECT;
+ gs->objects[object].parent = into;
}
static void
-gs_object_make_hidden_unchecked (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].position = OBJ_HIDDEN;
- gs->objects[object].parent = -1;
+gs_object_make_hidden_unchecked(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].position = OBJ_HIDDEN;
+ gs->objects[object].parent = -1;
}
static void
-gs_object_player_get_unchecked (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].position = OBJ_HELD_PLAYER;
- gs->objects[object].parent = -1;
+gs_object_player_get_unchecked(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].position = OBJ_HELD_PLAYER;
+ gs->objects[object].parent = -1;
}
static void
-gs_object_npc_get_unchecked (sc_gameref_t gs, sc_int object, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].position = OBJ_HELD_NPC;
- gs->objects[object].parent = npc;
+gs_object_npc_get_unchecked(sc_gameref_t gs, sc_int object, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].position = OBJ_HELD_NPC;
+ gs->objects[object].parent = npc;
}
static void
-gs_object_player_wear_unchecked (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].position = OBJ_WORN_PLAYER;
- gs->objects[object].parent = 0;
+gs_object_player_wear_unchecked(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].position = OBJ_WORN_PLAYER;
+ gs->objects[object].parent = 0;
}
static void
-gs_object_npc_wear_unchecked (sc_gameref_t gs, sc_int object, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].position = OBJ_WORN_NPC;
- gs->objects[object].parent = npc;
+gs_object_npc_wear_unchecked(sc_gameref_t gs, sc_int object, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].position = OBJ_WORN_NPC;
+ gs->objects[object].parent = npc;
}
static void
-gs_object_to_room_unchecked (sc_gameref_t gs, sc_int object, sc_int room)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- gs->objects[object].position = room + 1;
- gs->objects[object].parent = -1;
+gs_object_to_room_unchecked(sc_gameref_t gs, sc_int object, sc_int room) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ gs->objects[object].position = room + 1;
+ gs->objects[object].parent = -1;
}
void
-gs_object_move_onto (sc_gameref_t gs, sc_int object, sc_int onto)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- if (gs->objects[object].position != OBJ_ON_OBJECT
- || gs->objects[object].parent != onto)
- {
- gs_object_move_onto_unchecked (gs, object, onto);
- gs->objects[object].unmoved = FALSE;
- }
+gs_object_move_onto(sc_gameref_t gs, sc_int object, sc_int onto) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ if (gs->objects[object].position != OBJ_ON_OBJECT
+ || gs->objects[object].parent != onto) {
+ gs_object_move_onto_unchecked(gs, object, onto);
+ gs->objects[object].unmoved = FALSE;
+ }
}
void
-gs_object_move_into (sc_gameref_t gs, sc_int object, sc_int into)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- if (gs->objects[object].position != OBJ_IN_OBJECT
- || gs->objects[object].parent != into)
- {
- gs_object_move_into_unchecked (gs, object, into);
- gs->objects[object].unmoved = FALSE;
- }
+gs_object_move_into(sc_gameref_t gs, sc_int object, sc_int into) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ if (gs->objects[object].position != OBJ_IN_OBJECT
+ || gs->objects[object].parent != into) {
+ gs_object_move_into_unchecked(gs, object, into);
+ gs->objects[object].unmoved = FALSE;
+ }
}
void
-gs_object_make_hidden (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- if (gs->objects[object].position != OBJ_HIDDEN)
- {
- gs_object_make_hidden_unchecked (gs, object);
- gs->objects[object].unmoved = FALSE;
- }
+gs_object_make_hidden(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ if (gs->objects[object].position != OBJ_HIDDEN) {
+ gs_object_make_hidden_unchecked(gs, object);
+ gs->objects[object].unmoved = FALSE;
+ }
}
void
-gs_object_player_get (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- if (gs->objects[object].position != OBJ_HELD_PLAYER)
- {
- gs_object_player_get_unchecked (gs, object);
- gs->objects[object].unmoved = FALSE;
- }
+gs_object_player_get(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ if (gs->objects[object].position != OBJ_HELD_PLAYER) {
+ gs_object_player_get_unchecked(gs, object);
+ gs->objects[object].unmoved = FALSE;
+ }
}
void
-gs_object_npc_get (sc_gameref_t gs, sc_int object, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- if (gs->objects[object].position != OBJ_HELD_NPC
- || gs->objects[object].parent != npc)
- {
- gs_object_npc_get_unchecked (gs, object, npc);
- gs->objects[object].unmoved = FALSE;
- }
+gs_object_npc_get(sc_gameref_t gs, sc_int object, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ if (gs->objects[object].position != OBJ_HELD_NPC
+ || gs->objects[object].parent != npc) {
+ gs_object_npc_get_unchecked(gs, object, npc);
+ gs->objects[object].unmoved = FALSE;
+ }
}
void
-gs_object_player_wear (sc_gameref_t gs, sc_int object)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- if (gs->objects[object].position != OBJ_WORN_PLAYER)
- {
- gs_object_player_wear_unchecked (gs, object);
- gs->objects[object].unmoved = FALSE;
- }
+gs_object_player_wear(sc_gameref_t gs, sc_int object) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ if (gs->objects[object].position != OBJ_WORN_PLAYER) {
+ gs_object_player_wear_unchecked(gs, object);
+ gs->objects[object].unmoved = FALSE;
+ }
}
void
-gs_object_npc_wear (sc_gameref_t gs, sc_int object, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- if (gs->objects[object].position != OBJ_WORN_NPC
- || gs->objects[object].parent != npc)
- {
- gs_object_npc_wear_unchecked (gs, object, npc);
- gs->objects[object].unmoved = FALSE;
- }
+gs_object_npc_wear(sc_gameref_t gs, sc_int object, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ if (gs->objects[object].position != OBJ_WORN_NPC
+ || gs->objects[object].parent != npc) {
+ gs_object_npc_wear_unchecked(gs, object, npc);
+ gs->objects[object].unmoved = FALSE;
+ }
}
void
-gs_object_to_room (sc_gameref_t gs, sc_int object, sc_int room)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (object, gs->object_count));
- if (gs->objects[object].position != room + 1)
- {
- gs_object_to_room_unchecked (gs, object, room);
- gs->objects[object].unmoved = FALSE;
- }
+gs_object_to_room(sc_gameref_t gs, sc_int object, sc_int room) {
+ assert(gs_is_game_valid(gs) && gs_in_range(object, gs->object_count));
+ if (gs->objects[object].position != room + 1) {
+ gs_object_to_room_unchecked(gs, object, room);
+ gs->objects[object].unmoved = FALSE;
+ }
}
@@ -521,98 +455,85 @@ gs_object_to_room (sc_gameref_t gs, sc_int object, sc_int room)
* Game accessors and mutators for NPCs.
*/
sc_int
-gs_npc_count (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- return gs->npc_count;
+gs_npc_count(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ return gs->npc_count;
}
void
-gs_set_npc_location (sc_gameref_t gs, sc_int npc, sc_int location)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- gs->npcs[npc].location = location;
+gs_set_npc_location(sc_gameref_t gs, sc_int npc, sc_int location) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ gs->npcs[npc].location = location;
}
sc_int
-gs_npc_location (sc_gameref_t gs, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- return gs->npcs[npc].location;
+gs_npc_location(sc_gameref_t gs, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ return gs->npcs[npc].location;
}
void
-gs_set_npc_position (sc_gameref_t gs, sc_int npc, sc_int position)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- gs->npcs[npc].position = position;
+gs_set_npc_position(sc_gameref_t gs, sc_int npc, sc_int position) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ gs->npcs[npc].position = position;
}
sc_int
-gs_npc_position (sc_gameref_t gs, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- return gs->npcs[npc].position;
+gs_npc_position(sc_gameref_t gs, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ return gs->npcs[npc].position;
}
void
-gs_set_npc_parent (sc_gameref_t gs, sc_int npc, sc_int parent)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- gs->npcs[npc].parent = parent;
+gs_set_npc_parent(sc_gameref_t gs, sc_int npc, sc_int parent) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ gs->npcs[npc].parent = parent;
}
sc_int
-gs_npc_parent (sc_gameref_t gs, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- return gs->npcs[npc].parent;
+gs_npc_parent(sc_gameref_t gs, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ return gs->npcs[npc].parent;
}
void
-gs_set_npc_seen (sc_gameref_t gs, sc_int npc, sc_bool seen)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- gs->npcs[npc].seen = seen;
+gs_set_npc_seen(sc_gameref_t gs, sc_int npc, sc_bool seen) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ gs->npcs[npc].seen = seen;
}
sc_bool
-gs_npc_seen (sc_gameref_t gs, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- return gs->npcs[npc].seen;
+gs_npc_seen(sc_gameref_t gs, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ return gs->npcs[npc].seen;
}
sc_int
-gs_npc_walkstep_count (sc_gameref_t gs, sc_int npc)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count));
- return gs->npcs[npc].walkstep_count;
+gs_npc_walkstep_count(sc_gameref_t gs, sc_int npc) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count));
+ return gs->npcs[npc].walkstep_count;
}
void
-gs_set_npc_walkstep (sc_gameref_t gs,
- sc_int npc, sc_int walk, sc_int walkstep)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count)
- && gs_in_range (walk, gs->npcs[npc].walkstep_count));
- gs->npcs[npc].walksteps[walk] = walkstep;
+gs_set_npc_walkstep(sc_gameref_t gs,
+ sc_int npc, sc_int walk, sc_int walkstep) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count)
+ && gs_in_range(walk, gs->npcs[npc].walkstep_count));
+ gs->npcs[npc].walksteps[walk] = walkstep;
}
sc_int
-gs_npc_walkstep (sc_gameref_t gs, sc_int npc, sc_int walk)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count)
- && gs_in_range (walk, gs->npcs[npc].walkstep_count));
- return gs->npcs[npc].walksteps[walk];
+gs_npc_walkstep(sc_gameref_t gs, sc_int npc, sc_int walk) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count)
+ && gs_in_range(walk, gs->npcs[npc].walkstep_count));
+ return gs->npcs[npc].walksteps[walk];
}
void
-gs_decrement_npc_walkstep (sc_gameref_t gs, sc_int npc, sc_int walk)
-{
- assert(gs_is_game_valid (gs) && gs_in_range (npc, gs->npc_count)
- && gs_in_range (walk, gs->npcs[npc].walkstep_count));
- gs->npcs[npc].walksteps[walk]--;
+gs_decrement_npc_walkstep(sc_gameref_t gs, sc_int npc, sc_int walk) {
+ assert(gs_is_game_valid(gs) && gs_in_range(npc, gs->npc_count)
+ && gs_in_range(walk, gs->npcs[npc].walkstep_count));
+ gs->npcs[npc].walksteps[walk]--;
}
@@ -620,35 +541,31 @@ gs_decrement_npc_walkstep (sc_gameref_t gs, sc_int npc, sc_int walk)
* Convenience functions for bulk clearance of references.
*/
void
-gs_clear_npc_references (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- memset (gs->npc_references,
- FALSE, gs->npc_count * sizeof (*gs->npc_references));
+gs_clear_npc_references(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ memset(gs->npc_references,
+ FALSE, gs->npc_count * sizeof(*gs->npc_references));
}
void
-gs_clear_object_references (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- memset (gs->object_references,
- FALSE, gs->object_count * sizeof (*gs->object_references));
+gs_clear_object_references(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ memset(gs->object_references,
+ FALSE, gs->object_count * sizeof(*gs->object_references));
}
void
-gs_set_multiple_references (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- memset (gs->multiple_references,
- TRUE, gs->object_count * sizeof (*gs->multiple_references));
+gs_set_multiple_references(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ memset(gs->multiple_references,
+ TRUE, gs->object_count * sizeof(*gs->multiple_references));
}
void
-gs_clear_multiple_references (sc_gameref_t gs)
-{
- assert(gs_is_game_valid (gs));
- memset (gs->multiple_references,
- FALSE, gs->object_count * sizeof (*gs->multiple_references));
+gs_clear_multiple_references(sc_gameref_t gs) {
+ assert(gs_is_game_valid(gs));
+ memset(gs->multiple_references,
+ FALSE, gs->object_count * sizeof(*gs->multiple_references));
}
@@ -658,314 +575,294 @@ gs_clear_multiple_references (sc_gameref_t gs)
* Create and initialize a game state.
*/
sc_gameref_t
-gs_create (sc_var_setref_t vars,
- sc_prop_setref_t bundle, sc_filterref_t filter)
-{
- sc_gameref_t game;
- sc_vartype_t vt_key[4];
- sc_int index_, bytes;
- assert(vars && bundle && filter);
-
- /* Create the initial state structure. */
- game = (sc_gameref_t)sc_malloc (sizeof (*game));
- game->magic = GAME_MAGIC;
-
- /* Store the variables, properties bundle, and filter references. */
- game->vars = vars;
- game->bundle = bundle;
- game->filter = filter;
-
- /* Set memento to NULL for now; it's added later. */
- game->memento = NULL;
-
- /* Initialize for no debugger. */
- game->debugger = NULL;
-
- /* Initialize the undo buffers to NULL for now. */
- game->temporary = NULL;
- game->undo = NULL;
- game->undo_available = FALSE;
-
- /* Create rooms state array. */
- vt_key[0].string = "Rooms";
- game->room_count = prop_get_child_count (bundle, "I<-s", vt_key);
- game->rooms = (sc_roomstate_t *)sc_malloc (game->room_count * sizeof (*game->rooms));
-
- /* Set up initial rooms states. */
- for (index_ = 0; index_ < game->room_count; index_++)
- gs_set_room_seen (game, index_, FALSE);
-
- /* Create objects state array. */
- vt_key[0].string = "Objects";
- game->object_count = prop_get_child_count (bundle, "I<-s", vt_key);
- game->objects = (sc_objectstate_t *)sc_malloc (game->object_count * sizeof (*game->objects));
-
- /* Set up initial object states. */
- for (index_ = 0; index_ < game->object_count; index_++)
- {
- const sc_char *inroomdesc;
- sc_bool is_static, unmoved;
-
- vt_key[1].integer = index_;
-
- vt_key[2].string = "Static";
- is_static = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (is_static)
- {
- sc_int type;
-
- vt_key[2].string = "Where";
- vt_key[3].string = "Type";
- type = prop_get_integer (bundle, "I<-siss", vt_key);
- if (type == ROOMLIST_NPC_PART)
- {
- sc_int parent;
-
- game->objects[index_].position = OBJ_PART_NPC;
-
- vt_key[2].string = "Parent";
- parent = prop_get_integer (bundle, "I<-sis", vt_key) - 1;
- game->objects[index_].parent = parent;
- }
- else
- gs_object_make_hidden_unchecked (game, index_);
- }
- else
- {
- sc_int initialparent, initialposition;
-
- vt_key[2].string = "Parent";
- initialparent = prop_get_integer (bundle, "I<-sis", vt_key);
- vt_key[2].string = "InitialPosition";
- initialposition = prop_get_integer (bundle, "I<-sis", vt_key);
- switch (initialposition)
- {
- case 0: /* Hidden. */
- gs_object_make_hidden_unchecked (game, index_);
- break;
-
- case 1: /* Held. */
- if (initialparent == 0) /* By player. */
- gs_object_player_get_unchecked (game, index_);
- else /* By NPC. */
- gs_object_npc_get_unchecked (game, index_, initialparent - 1);
- break;
-
- case 2: /* In container. */
- gs_object_move_into_unchecked (game, index_,
- obj_container_object (game, initialparent));
- break;
-
- case 3: /* On surface. */
- gs_object_move_onto_unchecked (game, index_,
- obj_surface_object (game, initialparent));
- break;
-
- default: /* In room, or worn by player/NPC. */
- if (initialposition >= 4
- && initialposition < 4 + game->room_count)
- {
- gs_object_to_room_unchecked (game,
- index_, initialposition - 4);
- }
- else if (initialposition == 4 + game->room_count)
- {
- if (initialparent == 0)
- gs_object_player_wear_unchecked (game, index_);
- else
- gs_object_npc_wear_unchecked (game,
- index_, initialparent - 1);
- }
- else
- {
- sc_error ("gs_create: object in out of bounds room, %ld\n",
- initialposition - 4 - game->room_count);
- gs_object_to_room_unchecked (game, index_, -2);
- }
- }
- }
-
- vt_key[2].string = "CurrentState";
- gs_set_object_state (game, index_,
- prop_get_integer (bundle, "I<-sis", vt_key));
-
- vt_key[2].string = "Openable";
- gs_set_object_openness (game, index_,
- prop_get_integer (bundle, "I<-sis", vt_key));
-
- gs_set_object_seen (game, index_, FALSE);
-
- vt_key[2].string = "InRoomDesc";
- inroomdesc = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (inroomdesc))
- {
- vt_key[2].string = "OnlyWhenNotMoved";
- if (prop_get_integer (bundle, "I<-sis", vt_key) == 1)
- unmoved = TRUE;
- else
- unmoved = FALSE;
- }
- else
- unmoved = FALSE;
- gs_set_object_unmoved (game, index_, unmoved);
- gs_set_object_static_unmoved (game, index_, TRUE);
- }
-
- /* Create tasks state array. */
- vt_key[0].string = "Tasks";
- game->task_count = prop_get_child_count (bundle, "I<-s", vt_key);
- game->tasks = (sc_taskstate_t *)sc_malloc (game->task_count * sizeof (*game->tasks));
-
- /* Set up initial tasks states. */
- for (index_ = 0; index_ < game->task_count; index_++)
- {
- gs_set_task_done (game, index_, FALSE);
- gs_set_task_scored (game, index_, FALSE);
- }
-
- /* Create events state array. */
- vt_key[0].string = "Events";
- game->event_count = prop_get_child_count (bundle, "I<-s", vt_key);
- game->events = (sc_eventstate_t *)sc_malloc (game->event_count * sizeof (*game->events));
-
- /* Set up initial events states. */
- for (index_ = 0; index_ < game->event_count; index_++)
- {
- sc_int startertype;
-
- vt_key[1].integer = index_;
- vt_key[2].string = "StarterType";
- startertype = prop_get_integer (bundle, "I<-sis", vt_key);
-
- switch (startertype)
- {
- case 1:
- gs_set_event_state (game, index_, ES_WAITING);
- gs_set_event_time (game, index_, 0);
- break;
-
- case 2:
- {
- sc_int start, end;
-
- gs_set_event_state (game, index_, 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, index_, sc_randomint (start, end));
- break;
- }
-
- case 3:
- gs_set_event_state (game, index_, ES_AWAITING);
- gs_set_event_time (game, index_, 0);
- break;
- }
- }
-
- /* Create NPCs state array. */
- vt_key[0].string = "NPCs";
- game->npc_count = prop_get_child_count (bundle, "I<-s", vt_key);
- game->npcs = (sc_npcstate_t *)sc_malloc (game->npc_count * sizeof (*game->npcs));
-
- /* Set up initial NPCs states. */
- for (index_ = 0; index_ < game->npc_count; index_++)
- {
- sc_int walk, walkstep_count;
-
- gs_set_npc_position (game, index_, 0);
- gs_set_npc_parent (game, index_, -1);
- gs_set_npc_seen (game, index_, FALSE);
-
- vt_key[1].integer = index_;
-
- vt_key[2].string = "StartRoom";
- gs_set_npc_location (game, index_,
- prop_get_integer (bundle, "I<-sis", vt_key));
-
- vt_key[2].string = "Walks";
- walkstep_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- game->npcs[index_].walkstep_count = walkstep_count;
- game->npcs[index_].walksteps = (sc_int *)sc_malloc (walkstep_count
- * sizeof (*game->npcs[0].walksteps));
-
- for (walk = 0; walk < walkstep_count; walk++)
- gs_set_npc_walkstep (game, index_, walk, 0);
- }
-
- /* Set up the player portions of the game state. */
- vt_key[0].string = "Header";
- vt_key[1].string = "StartRoom";
- game->playerroom = prop_get_integer (bundle, "I<-ss", vt_key);
- vt_key[0].string = "Globals";
- vt_key[1].string = "ParentObject";
- game->playerparent = prop_get_integer (bundle, "I<-ss", vt_key) - 1;
- vt_key[1].string = "Position";
- game->playerposition = prop_get_integer (bundle, "I<-ss", vt_key);
-
- /* Initialize score notifications from game properties. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "NoScoreNotify";
- game->notify_score_change = !prop_get_boolean (bundle, "B<-ss", vt_key);
-
- /* Miscellaneous state defaults. */
- game->turns = 0;
- game->score = 0;
- game->bold_room_names = TRUE;
- game->verbose = FALSE;
- game->current_room_name = NULL;
- game->status_line = NULL;
- game->title = NULL;
- game->author = NULL;
- game->hint_text = NULL;
-
- /* Resource controls. */
- res_clear_resource (&game->requested_sound);
- res_clear_resource (&game->requested_graphic);
- res_clear_resource (&game->playing_sound);
- res_clear_resource (&game->displayed_graphic);
- game->stop_sound = FALSE;
- game->sound_active = FALSE;
-
- /* Initialize wait turns from game properties. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "WaitTurns";
- game->waitturns = prop_get_integer (bundle, "I<-ss", vt_key);
-
- /* Non-game conveniences. */
- game->is_running = FALSE;
- game->has_notified = FALSE;
- game->is_admin = FALSE;
- game->has_completed = FALSE;
- game->waitcounter = 0;
- game->do_again = FALSE;
- game->redo_sequence = 0;
- game->do_restart = FALSE;
- game->do_restore = FALSE;
-
- bytes = game->object_count * sizeof (*game->object_references);
- game->object_references = (sc_bool *)sc_malloc (bytes);
- memset (game->object_references, FALSE, bytes);
- bytes = game->object_count * sizeof (*game->multiple_references);
- game->multiple_references = (sc_bool *)sc_malloc (bytes);
- memset (game->multiple_references, FALSE, bytes);
-
- bytes = game->npc_count * sizeof (*game->npc_references);
- game->npc_references = (sc_bool *)sc_malloc (bytes);
- memset (game->npc_references, FALSE, bytes);
-
- game->it_object = -1;
- game->him_npc = -1;
- game->her_npc = -1;
- game->it_npc = -1;
-
- /* Clear the quit jump buffer for tidiness. */
- memset (&game->quitter, 0, sizeof (game->quitter));
-
- /* Return the constructed game state. */
- return game;
+gs_create(sc_var_setref_t vars,
+ sc_prop_setref_t bundle, sc_filterref_t filter) {
+ sc_gameref_t game;
+ sc_vartype_t vt_key[4];
+ sc_int index_, bytes;
+ assert(vars && bundle && filter);
+
+ /* Create the initial state structure. */
+ game = (sc_gameref_t)sc_malloc(sizeof(*game));
+ game->magic = GAME_MAGIC;
+
+ /* Store the variables, properties bundle, and filter references. */
+ game->vars = vars;
+ game->bundle = bundle;
+ game->filter = filter;
+
+ /* Set memento to NULL for now; it's added later. */
+ game->memento = NULL;
+
+ /* Initialize for no debugger. */
+ game->debugger = NULL;
+
+ /* Initialize the undo buffers to NULL for now. */
+ game->temporary = NULL;
+ game->undo = NULL;
+ game->undo_available = FALSE;
+
+ /* Create rooms state array. */
+ vt_key[0].string = "Rooms";
+ game->room_count = prop_get_child_count(bundle, "I<-s", vt_key);
+ game->rooms = (sc_roomstate_t *)sc_malloc(game->room_count * sizeof(*game->rooms));
+
+ /* Set up initial rooms states. */
+ for (index_ = 0; index_ < game->room_count; index_++)
+ gs_set_room_seen(game, index_, FALSE);
+
+ /* Create objects state array. */
+ vt_key[0].string = "Objects";
+ game->object_count = prop_get_child_count(bundle, "I<-s", vt_key);
+ game->objects = (sc_objectstate_t *)sc_malloc(game->object_count * sizeof(*game->objects));
+
+ /* Set up initial object states. */
+ for (index_ = 0; index_ < game->object_count; index_++) {
+ const sc_char *inroomdesc;
+ sc_bool is_static, unmoved;
+
+ vt_key[1].integer = index_;
+
+ vt_key[2].string = "Static";
+ is_static = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (is_static) {
+ sc_int type;
+
+ vt_key[2].string = "Where";
+ vt_key[3].string = "Type";
+ type = prop_get_integer(bundle, "I<-siss", vt_key);
+ if (type == ROOMLIST_NPC_PART) {
+ sc_int parent;
+
+ game->objects[index_].position = OBJ_PART_NPC;
+
+ vt_key[2].string = "Parent";
+ parent = prop_get_integer(bundle, "I<-sis", vt_key) - 1;
+ game->objects[index_].parent = parent;
+ } else
+ gs_object_make_hidden_unchecked(game, index_);
+ } else {
+ sc_int initialparent, initialposition;
+
+ vt_key[2].string = "Parent";
+ initialparent = prop_get_integer(bundle, "I<-sis", vt_key);
+ vt_key[2].string = "InitialPosition";
+ initialposition = prop_get_integer(bundle, "I<-sis", vt_key);
+ switch (initialposition) {
+ case 0: /* Hidden. */
+ gs_object_make_hidden_unchecked(game, index_);
+ break;
+
+ case 1: /* Held. */
+ if (initialparent == 0) /* By player. */
+ gs_object_player_get_unchecked(game, index_);
+ else /* By NPC. */
+ gs_object_npc_get_unchecked(game, index_, initialparent - 1);
+ break;
+
+ case 2: /* In container. */
+ gs_object_move_into_unchecked(game, index_,
+ obj_container_object(game, initialparent));
+ break;
+
+ case 3: /* On surface. */
+ gs_object_move_onto_unchecked(game, index_,
+ obj_surface_object(game, initialparent));
+ break;
+
+ default: /* In room, or worn by player/NPC. */
+ if (initialposition >= 4
+ && initialposition < 4 + game->room_count) {
+ gs_object_to_room_unchecked(game,
+ index_, initialposition - 4);
+ } else if (initialposition == 4 + game->room_count) {
+ if (initialparent == 0)
+ gs_object_player_wear_unchecked(game, index_);
+ else
+ gs_object_npc_wear_unchecked(game,
+ index_, initialparent - 1);
+ } else {
+ sc_error("gs_create: object in out of bounds room, %ld\n",
+ initialposition - 4 - game->room_count);
+ gs_object_to_room_unchecked(game, index_, -2);
+ }
+ }
+ }
+
+ vt_key[2].string = "CurrentState";
+ gs_set_object_state(game, index_,
+ prop_get_integer(bundle, "I<-sis", vt_key));
+
+ vt_key[2].string = "Openable";
+ gs_set_object_openness(game, index_,
+ prop_get_integer(bundle, "I<-sis", vt_key));
+
+ gs_set_object_seen(game, index_, FALSE);
+
+ vt_key[2].string = "InRoomDesc";
+ inroomdesc = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(inroomdesc)) {
+ vt_key[2].string = "OnlyWhenNotMoved";
+ if (prop_get_integer(bundle, "I<-sis", vt_key) == 1)
+ unmoved = TRUE;
+ else
+ unmoved = FALSE;
+ } else
+ unmoved = FALSE;
+ gs_set_object_unmoved(game, index_, unmoved);
+ gs_set_object_static_unmoved(game, index_, TRUE);
+ }
+
+ /* Create tasks state array. */
+ vt_key[0].string = "Tasks";
+ game->task_count = prop_get_child_count(bundle, "I<-s", vt_key);
+ game->tasks = (sc_taskstate_t *)sc_malloc(game->task_count * sizeof(*game->tasks));
+
+ /* Set up initial tasks states. */
+ for (index_ = 0; index_ < game->task_count; index_++) {
+ gs_set_task_done(game, index_, FALSE);
+ gs_set_task_scored(game, index_, FALSE);
+ }
+
+ /* Create events state array. */
+ vt_key[0].string = "Events";
+ game->event_count = prop_get_child_count(bundle, "I<-s", vt_key);
+ game->events = (sc_eventstate_t *)sc_malloc(game->event_count * sizeof(*game->events));
+
+ /* Set up initial events states. */
+ for (index_ = 0; index_ < game->event_count; index_++) {
+ sc_int startertype;
+
+ vt_key[1].integer = index_;
+ vt_key[2].string = "StarterType";
+ startertype = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ switch (startertype) {
+ case 1:
+ gs_set_event_state(game, index_, ES_WAITING);
+ gs_set_event_time(game, index_, 0);
+ break;
+
+ case 2: {
+ sc_int start, end;
+
+ gs_set_event_state(game, index_, 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, index_, sc_randomint(start, end));
+ break;
+ }
+
+ case 3:
+ gs_set_event_state(game, index_, ES_AWAITING);
+ gs_set_event_time(game, index_, 0);
+ break;
+ }
+ }
+
+ /* Create NPCs state array. */
+ vt_key[0].string = "NPCs";
+ game->npc_count = prop_get_child_count(bundle, "I<-s", vt_key);
+ game->npcs = (sc_npcstate_t *)sc_malloc(game->npc_count * sizeof(*game->npcs));
+
+ /* Set up initial NPCs states. */
+ for (index_ = 0; index_ < game->npc_count; index_++) {
+ sc_int walk, walkstep_count;
+
+ gs_set_npc_position(game, index_, 0);
+ gs_set_npc_parent(game, index_, -1);
+ gs_set_npc_seen(game, index_, FALSE);
+
+ vt_key[1].integer = index_;
+
+ vt_key[2].string = "StartRoom";
+ gs_set_npc_location(game, index_,
+ prop_get_integer(bundle, "I<-sis", vt_key));
+
+ vt_key[2].string = "Walks";
+ walkstep_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ game->npcs[index_].walkstep_count = walkstep_count;
+ game->npcs[index_].walksteps = (sc_int *)sc_malloc(walkstep_count
+ * sizeof(*game->npcs[0].walksteps));
+
+ for (walk = 0; walk < walkstep_count; walk++)
+ gs_set_npc_walkstep(game, index_, walk, 0);
+ }
+
+ /* Set up the player portions of the game state. */
+ vt_key[0].string = "Header";
+ vt_key[1].string = "StartRoom";
+ game->playerroom = prop_get_integer(bundle, "I<-ss", vt_key);
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "ParentObject";
+ game->playerparent = prop_get_integer(bundle, "I<-ss", vt_key) - 1;
+ vt_key[1].string = "Position";
+ game->playerposition = prop_get_integer(bundle, "I<-ss", vt_key);
+
+ /* Initialize score notifications from game properties. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "NoScoreNotify";
+ game->notify_score_change = !prop_get_boolean(bundle, "B<-ss", vt_key);
+
+ /* Miscellaneous state defaults. */
+ game->turns = 0;
+ game->score = 0;
+ game->bold_room_names = TRUE;
+ game->verbose = FALSE;
+ game->current_room_name = NULL;
+ game->status_line = NULL;
+ game->title = NULL;
+ game->author = NULL;
+ game->hint_text = NULL;
+
+ /* Resource controls. */
+ res_clear_resource(&game->requested_sound);
+ res_clear_resource(&game->requested_graphic);
+ res_clear_resource(&game->playing_sound);
+ res_clear_resource(&game->displayed_graphic);
+ game->stop_sound = FALSE;
+ game->sound_active = FALSE;
+
+ /* Initialize wait turns from game properties. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "WaitTurns";
+ game->waitturns = prop_get_integer(bundle, "I<-ss", vt_key);
+
+ /* Non-game conveniences. */
+ game->is_running = FALSE;
+ game->has_notified = FALSE;
+ game->is_admin = FALSE;
+ game->has_completed = FALSE;
+ game->waitcounter = 0;
+ game->do_again = FALSE;
+ game->redo_sequence = 0;
+ game->do_restart = FALSE;
+ game->do_restore = FALSE;
+
+ bytes = game->object_count * sizeof(*game->object_references);
+ game->object_references = (sc_bool *)sc_malloc(bytes);
+ memset(game->object_references, FALSE, bytes);
+ bytes = game->object_count * sizeof(*game->multiple_references);
+ game->multiple_references = (sc_bool *)sc_malloc(bytes);
+ memset(game->multiple_references, FALSE, bytes);
+
+ bytes = game->npc_count * sizeof(*game->npc_references);
+ game->npc_references = (sc_bool *)sc_malloc(bytes);
+ memset(game->npc_references, FALSE, bytes);
+
+ game->it_object = -1;
+ game->him_npc = -1;
+ game->her_npc = -1;
+ game->it_npc = -1;
+
+ /* Clear the quit jump buffer for tidiness. */
+ memset(&game->quitter, 0, sizeof(game->quitter));
+
+ /* Return the constructed game state. */
+ return game;
}
@@ -975,9 +872,8 @@ gs_create (sc_var_setref_t vars,
* Return TRUE if pointer is a valid game, FALSE otherwise.
*/
sc_bool
-gs_is_game_valid (sc_gameref_t game)
-{
- return game && game->magic == GAME_MAGIC;
+gs_is_game_valid(sc_gameref_t game) {
+ return game && game->magic == GAME_MAGIC;
}
@@ -988,19 +884,16 @@ gs_is_game_valid (sc_gameref_t game)
* if from is NULL, taking care not to leak memory.
*/
static void
-gs_string_copy (sc_char **to_string, const sc_char *from_string)
-{
- /* Free any current contents of to_string. */
- sc_free (*to_string);
+gs_string_copy(sc_char **to_string, const sc_char *from_string) {
+ /* Free any current contents of to_string. */
+ sc_free(*to_string);
- /* Copy from_string if set, otherwise set to_string to NULL. */
- if (from_string)
- {
- *to_string = (sc_char *)sc_malloc (strlen (from_string) + 1);
- strcpy (*to_string, from_string);
- }
- else
- *to_string = NULL;
+ /* Copy from_string if set, otherwise set to_string to NULL. */
+ if (from_string) {
+ *to_string = (sc_char *)sc_malloc(strlen(from_string) + 1);
+ strcpy(*to_string, from_string);
+ } else
+ *to_string = NULL;
}
@@ -1011,146 +904,142 @@ gs_string_copy (sc_char **to_string, const sc_char *from_string)
* game structure.
*/
void
-gs_copy (sc_gameref_t to, sc_gameref_t from)
-{
- const sc_prop_setref_t bundle = from->bundle;
- sc_vartype_t vt_key[3];
- sc_int var_count, var, npc;
- assert(gs_is_game_valid (to) && gs_is_game_valid (from));
-
- /*
- * Copy over references to the properties bundle and filter. The debugger
- * is specifically excluded, as it's considered to be tied to the game.
- */
- to->bundle = from->bundle;
- to->filter = from->filter;
-
- /* Copy over references to the undo buffers. */
- to->temporary = from->temporary;
- to->undo = from->undo;
- to->undo_available = from->undo_available;
-
- /* Copy over all variables values. */
- vt_key[0].string = "Variables";
- var_count = prop_get_child_count (bundle, "I<-s", vt_key);
-
- for (var = 0; var < var_count; var++)
- {
- const sc_char *name;
- sc_int var_type;
-
- vt_key[1].integer = var;
-
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Type";
- var_type = prop_get_integer (bundle, "I<-sis", vt_key);
-
- switch (var_type)
- {
- case TAFVAR_NUMERIC:
- var_put_integer (to->vars, name, var_get_integer (from->vars, name));
- break;
-
- case TAFVAR_STRING:
- var_put_string (to->vars, name, var_get_string (from->vars, name));
- break;
-
- default:
- sc_fatal ("gs_copy: unknown variable type, %ld\n", var_type);
- }
- }
-
- /* Copy over the variable timestamp. */
- var_set_elapsed_seconds (to->vars, var_get_elapsed_seconds (from->vars));
-
- /* Copy over room states. */
- assert(to->room_count == from->room_count);
- memcpy (to->rooms, from->rooms, from->room_count * sizeof (*from->rooms));
-
- /* Copy over object states. */
- assert(to->object_count == from->object_count);
- memcpy (to->objects, from->objects,
- from->object_count * sizeof (*from->objects));
-
- /* Copy over task states. */
- assert(to->task_count == from->task_count);
- memcpy (to->tasks, from->tasks, from->task_count * sizeof (*from->tasks));
-
- /* Copy over event states. */
- assert(to->event_count == from->event_count);
- memcpy (to->events, from->events, from->event_count * sizeof (*from->events));
-
- /* Copy over NPC states individually, to avoid walks problems. */
- for (npc = 0; npc < from->npc_count; npc++)
- {
- to->npcs[npc].location = from->npcs[npc].location;
- to->npcs[npc].position = from->npcs[npc].position;
- to->npcs[npc].parent = from->npcs[npc].parent;
- to->npcs[npc].seen = from->npcs[npc].seen;
- to->npcs[npc].walkstep_count = from->npcs[npc].walkstep_count;
-
- /* Copy over NPC walks information. */
- assert(to->npcs[npc].walkstep_count == from->npcs[npc].walkstep_count);
- memcpy (to->npcs[npc].walksteps, from->npcs[npc].walksteps,
- from->npcs[npc].walkstep_count
- * sizeof (*from->npcs[npc].walksteps));
- }
-
- /* Copy over player information. */
- to->playerroom = from->playerroom;
- to->playerposition = from->playerposition;
- to->playerparent = from->playerparent;
-
- /*
- * Copy over miscellaneous other details. Specifically exclude bold rooms,
- * verbose, and score notification, so that they are invariant across copies,
- * particularly undo/restore.
- */
- to->turns = from->turns;
- to->score = from->score;
-
- gs_string_copy (&to->current_room_name, from->current_room_name);
- gs_string_copy (&to->status_line, from->status_line);
- gs_string_copy (&to->title, from->title);
- gs_string_copy (&to->author, from->author);
- gs_string_copy (&to->hint_text, from->hint_text);
-
- /*
- * Specifically exclude playing sound and displayed graphic from the copy
- * so that they remain invariant across game copies.
- */
- to->requested_sound = from->requested_sound;
- to->requested_graphic = from->requested_graphic;
- to->stop_sound = from->stop_sound;
-
- to->is_running = from->is_running;
- to->has_notified = from->has_notified;
- to->is_admin = from->is_admin;
- to->has_completed = from->has_completed;
-
- to->waitturns = from->waitturns;
-
- to->waitcounter = from->waitcounter;
- to->do_again = from->do_again;
- to->redo_sequence = from->redo_sequence;
- to->do_restart = from->do_restart;
- to->do_restore = from->do_restore;
-
- memcpy (to->object_references, from->object_references,
- from->object_count * sizeof (*from->object_references));
- memcpy (to->multiple_references, from->multiple_references,
- from->object_count * sizeof (*from->multiple_references));
- memcpy (to->npc_references, from->npc_references,
- from->npc_count * sizeof (*from->npc_references));
-
- to->it_object = from->it_object;
- to->him_npc = from->him_npc;
- to->her_npc = from->her_npc;
- to->it_npc = from->it_npc;
-
- /* Copy over the quit jump buffer. */
- memcpy (&to->quitter, &from->quitter, sizeof (from->quitter));
+gs_copy(sc_gameref_t to, sc_gameref_t from) {
+ const sc_prop_setref_t bundle = from->bundle;
+ sc_vartype_t vt_key[3];
+ sc_int var_count, var, npc;
+ assert(gs_is_game_valid(to) && gs_is_game_valid(from));
+
+ /*
+ * Copy over references to the properties bundle and filter. The debugger
+ * is specifically excluded, as it's considered to be tied to the game.
+ */
+ to->bundle = from->bundle;
+ to->filter = from->filter;
+
+ /* Copy over references to the undo buffers. */
+ to->temporary = from->temporary;
+ to->undo = from->undo;
+ to->undo_available = from->undo_available;
+
+ /* Copy over all variables values. */
+ vt_key[0].string = "Variables";
+ var_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ for (var = 0; var < var_count; var++) {
+ const sc_char *name;
+ sc_int var_type;
+
+ vt_key[1].integer = var;
+
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Type";
+ var_type = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ switch (var_type) {
+ case TAFVAR_NUMERIC:
+ var_put_integer(to->vars, name, var_get_integer(from->vars, name));
+ break;
+
+ case TAFVAR_STRING:
+ var_put_string(to->vars, name, var_get_string(from->vars, name));
+ break;
+
+ default:
+ sc_fatal("gs_copy: unknown variable type, %ld\n", var_type);
+ }
+ }
+
+ /* Copy over the variable timestamp. */
+ var_set_elapsed_seconds(to->vars, var_get_elapsed_seconds(from->vars));
+
+ /* Copy over room states. */
+ assert(to->room_count == from->room_count);
+ memcpy(to->rooms, from->rooms, from->room_count * sizeof(*from->rooms));
+
+ /* Copy over object states. */
+ assert(to->object_count == from->object_count);
+ memcpy(to->objects, from->objects,
+ from->object_count * sizeof(*from->objects));
+
+ /* Copy over task states. */
+ assert(to->task_count == from->task_count);
+ memcpy(to->tasks, from->tasks, from->task_count * sizeof(*from->tasks));
+
+ /* Copy over event states. */
+ assert(to->event_count == from->event_count);
+ memcpy(to->events, from->events, from->event_count * sizeof(*from->events));
+
+ /* Copy over NPC states individually, to avoid walks problems. */
+ for (npc = 0; npc < from->npc_count; npc++) {
+ to->npcs[npc].location = from->npcs[npc].location;
+ to->npcs[npc].position = from->npcs[npc].position;
+ to->npcs[npc].parent = from->npcs[npc].parent;
+ to->npcs[npc].seen = from->npcs[npc].seen;
+ to->npcs[npc].walkstep_count = from->npcs[npc].walkstep_count;
+
+ /* Copy over NPC walks information. */
+ assert(to->npcs[npc].walkstep_count == from->npcs[npc].walkstep_count);
+ memcpy(to->npcs[npc].walksteps, from->npcs[npc].walksteps,
+ from->npcs[npc].walkstep_count
+ * sizeof(*from->npcs[npc].walksteps));
+ }
+
+ /* Copy over player information. */
+ to->playerroom = from->playerroom;
+ to->playerposition = from->playerposition;
+ to->playerparent = from->playerparent;
+
+ /*
+ * Copy over miscellaneous other details. Specifically exclude bold rooms,
+ * verbose, and score notification, so that they are invariant across copies,
+ * particularly undo/restore.
+ */
+ to->turns = from->turns;
+ to->score = from->score;
+
+ gs_string_copy(&to->current_room_name, from->current_room_name);
+ gs_string_copy(&to->status_line, from->status_line);
+ gs_string_copy(&to->title, from->title);
+ gs_string_copy(&to->author, from->author);
+ gs_string_copy(&to->hint_text, from->hint_text);
+
+ /*
+ * Specifically exclude playing sound and displayed graphic from the copy
+ * so that they remain invariant across game copies.
+ */
+ to->requested_sound = from->requested_sound;
+ to->requested_graphic = from->requested_graphic;
+ to->stop_sound = from->stop_sound;
+
+ to->is_running = from->is_running;
+ to->has_notified = from->has_notified;
+ to->is_admin = from->is_admin;
+ to->has_completed = from->has_completed;
+
+ to->waitturns = from->waitturns;
+
+ to->waitcounter = from->waitcounter;
+ to->do_again = from->do_again;
+ to->redo_sequence = from->redo_sequence;
+ to->do_restart = from->do_restart;
+ to->do_restore = from->do_restore;
+
+ memcpy(to->object_references, from->object_references,
+ from->object_count * sizeof(*from->object_references));
+ memcpy(to->multiple_references, from->multiple_references,
+ from->object_count * sizeof(*from->multiple_references));
+ memcpy(to->npc_references, from->npc_references,
+ from->npc_count * sizeof(*from->npc_references));
+
+ to->it_object = from->it_object;
+ to->him_npc = from->him_npc;
+ to->her_npc = from->her_npc;
+ to->it_npc = from->it_npc;
+
+ /* Copy over the quit jump buffer. */
+ memcpy(&to->quitter, &from->quitter, sizeof(from->quitter));
}
@@ -1160,35 +1049,34 @@ gs_copy (sc_gameref_t to, sc_gameref_t from)
* Free all the memory associated with a game state.
*/
void
-gs_destroy (sc_gameref_t game)
-{
- sc_int npc;
- assert(gs_is_game_valid (game));
-
- /* Free the malloc'ed state arrays. */
- sc_free (game->rooms);
- sc_free (game->objects);
- sc_free (game->tasks);
- sc_free (game->events);
- for (npc = 0; npc < game->npc_count; npc++)
- sc_free (game->npcs[npc].walksteps);
- sc_free (game->npcs);
-
- /* Free the malloc'ed object and NPC references. */
- sc_free (game->object_references);
- sc_free (game->multiple_references);
- sc_free (game->npc_references);
-
- /* Free malloc'ed game strings. */
- sc_free (game->current_room_name);
- sc_free (game->status_line);
- sc_free (game->title);
- sc_free (game->author);
- sc_free (game->hint_text);
-
- /* Poison and free the game state itself. */
- memset (game, 0xaa, sizeof (*game));
- sc_free (game);
+gs_destroy(sc_gameref_t game) {
+ sc_int npc;
+ assert(gs_is_game_valid(game));
+
+ /* Free the malloc'ed state arrays. */
+ sc_free(game->rooms);
+ sc_free(game->objects);
+ sc_free(game->tasks);
+ sc_free(game->events);
+ for (npc = 0; npc < game->npc_count; npc++)
+ sc_free(game->npcs[npc].walksteps);
+ sc_free(game->npcs);
+
+ /* Free the malloc'ed object and NPC references. */
+ sc_free(game->object_references);
+ sc_free(game->multiple_references);
+ sc_free(game->npc_references);
+
+ /* Free malloc'ed game strings. */
+ sc_free(game->current_room_name);
+ sc_free(game->status_line);
+ sc_free(game->title);
+ sc_free(game->author);
+ sc_free(game->hint_text);
+
+ /* Poison and free the game state itself. */
+ memset(game, 0xaa, sizeof(*game));
+ sc_free(game);
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scgamest.h b/engines/glk/adrift/scgamest.h
index 4287551bfd..a246d05164 100644
--- a/engines/glk/adrift/scgamest.h
+++ b/engines/glk/adrift/scgamest.h
@@ -67,9 +67,9 @@ struct sc_taskstate_s {
typedef sc_taskstate_s sc_taskstate_t;
/* Event state structure, holds event state, and timing information. */
-enum
-{ ES_WAITING = 1,
- ES_RUNNING = 2, ES_AWAITING = 3, ES_FINISHED = 4, ES_PAUSED = 5
+enum {
+ ES_WAITING = 1,
+ ES_RUNNING = 2, ES_AWAITING = 3, ES_FINISHED = 4, ES_PAUSED = 5
};
struct sc_eventstate_s {
sc_int state;
diff --git a/engines/glk/adrift/scinterf.cpp b/engines/glk/adrift/scinterf.cpp
index cc8e1235d7..c5e53e959d 100644
--- a/engines/glk/adrift/scinterf.cpp
+++ b/engines/glk/adrift/scinterf.cpp
@@ -46,37 +46,28 @@ static sc_uint if_trace_flags = 0;
* tries to ensure correct compile options.
*/
static void
-if_initialize (void)
-{
- static sc_bool initialized = FALSE;
-
- /* Only do checks on the first call. */
- if (!initialized)
- {
- /* Make a few quick checks on types and type sizes. */
- if (sizeof (sc_byte) != 1 || sizeof (sc_char) != 1)
- {
- sc_error ("if_initialize: sizeof sc_byte or sc_char"
- " is not 1, check compile options\n");
- }
- else if (sizeof (sc_uint) < 4 || sizeof (sc_int) < 4)
- {
- sc_error ("if_initialize: sizeof sc_uint or sc_int"
- " is not at least 4, check compile options\n");
- }
- else if (sizeof (sc_uint) > 8 || sizeof (sc_int) > 8)
- {
- sc_error ("if_initialize: sizeof sc_uint or sc_int"
- " is more than 8, check compile options\n");
- }
- else if (!((sc_uint) -1 > 0))
- {
- sc_error ("if_initialize: sc_uint appears not to be unsigned,"
- " check compile options\n");
- }
-
- initialized = TRUE;
- }
+if_initialize(void) {
+ static sc_bool initialized = FALSE;
+
+ /* Only do checks on the first call. */
+ if (!initialized) {
+ /* Make a few quick checks on types and type sizes. */
+ if (sizeof(sc_byte) != 1 || sizeof(sc_char) != 1) {
+ sc_error("if_initialize: sizeof sc_byte or sc_char"
+ " is not 1, check compile options\n");
+ } else if (sizeof(sc_uint) < 4 || sizeof(sc_int) < 4) {
+ sc_error("if_initialize: sizeof sc_uint or sc_int"
+ " is not at least 4, check compile options\n");
+ } else if (sizeof(sc_uint) > 8 || sizeof(sc_int) > 8) {
+ sc_error("if_initialize: sizeof sc_uint or sc_int"
+ " is more than 8, check compile options\n");
+ } else if (!((sc_uint) - 1 > 0)) {
+ sc_error("if_initialize: sc_uint appears not to be unsigned,"
+ " check compile options\n");
+ }
+
+ initialized = TRUE;
+ }
}
@@ -89,37 +80,34 @@ if_initialize (void)
* tracing setting to all modules that support it.
*/
static sc_bool
-if_bool (sc_uint flag)
-{
- return flag ? TRUE : FALSE;
+if_bool(sc_uint flag) {
+ return flag ? TRUE : FALSE;
}
void
-sc_set_trace_flags (sc_uint trace_flags)
-{
- if_initialize ();
-
- /* Save the value for queries. */
- if_trace_flags = trace_flags;
-
- /* Propagate tracing to modules that support it. */
- parse_debug_trace (if_bool (trace_flags & SC_TRACE_PARSE));
- prop_debug_trace (if_bool (trace_flags & SC_TRACE_PROPERTIES));
- var_debug_trace (if_bool (trace_flags & SC_TRACE_VARIABLES));
- uip_debug_trace (if_bool (trace_flags & SC_TRACE_PARSER));
- lib_debug_trace (if_bool (trace_flags & SC_TRACE_LIBRARY));
- evt_debug_trace (if_bool (trace_flags & SC_TRACE_EVENTS));
- npc_debug_trace (if_bool (trace_flags & SC_TRACE_NPCS));
- obj_debug_trace (if_bool (trace_flags & SC_TRACE_OBJECTS));
- task_debug_trace (if_bool (trace_flags & SC_TRACE_TASKS));
- restr_debug_trace (if_bool (trace_flags & SC_TRACE_TASKS));
- pf_debug_trace (if_bool (trace_flags & SC_TRACE_PRINTFILTER));
+sc_set_trace_flags(sc_uint trace_flags) {
+ if_initialize();
+
+ /* Save the value for queries. */
+ if_trace_flags = trace_flags;
+
+ /* Propagate tracing to modules that support it. */
+ parse_debug_trace(if_bool(trace_flags & SC_TRACE_PARSE));
+ prop_debug_trace(if_bool(trace_flags & SC_TRACE_PROPERTIES));
+ var_debug_trace(if_bool(trace_flags & SC_TRACE_VARIABLES));
+ uip_debug_trace(if_bool(trace_flags & SC_TRACE_PARSER));
+ lib_debug_trace(if_bool(trace_flags & SC_TRACE_LIBRARY));
+ evt_debug_trace(if_bool(trace_flags & SC_TRACE_EVENTS));
+ npc_debug_trace(if_bool(trace_flags & SC_TRACE_NPCS));
+ obj_debug_trace(if_bool(trace_flags & SC_TRACE_OBJECTS));
+ task_debug_trace(if_bool(trace_flags & SC_TRACE_TASKS));
+ restr_debug_trace(if_bool(trace_flags & SC_TRACE_TASKS));
+ pf_debug_trace(if_bool(trace_flags & SC_TRACE_PRINTFILTER));
}
sc_bool
-if_get_trace_flag (sc_uint bitmask)
-{
- return if_bool (if_trace_flags & bitmask);
+if_get_trace_flag(sc_uint bitmask) {
+ return if_bool(if_trace_flags & bitmask);
}
@@ -135,59 +123,51 @@ if_get_trace_flag (sc_uint bitmask)
* Call OS-specific print function for the given arguments.
*/
static void
-if_print_string_common (const sc_char *string,
- void (*print_string_function) (const sc_char *))
-{
- assert (string);
+if_print_string_common(const sc_char *string,
+ void (*print_string_function)(const sc_char *)) {
+ assert(string);
- if (string[0] != NUL)
- print_string_function (string);
+ if (string[0] != NUL)
+ print_string_function(string);
}
void
-if_print_string (const sc_char *string)
-{
- if_print_string_common (string, os_print_string);
+if_print_string(const sc_char *string) {
+ if_print_string_common(string, os_print_string);
}
void
-if_print_debug (const sc_char *string)
-{
- if_print_string_common (string, os_print_string_debug);
+if_print_debug(const sc_char *string) {
+ if_print_string_common(string, os_print_string_debug);
}
static void
-if_print_character_common (sc_char character,
- void (*print_string_function) (const sc_char *))
-{
- if (character != NUL)
- {
- sc_char buffer[2];
+if_print_character_common(sc_char character,
+ void (*print_string_function)(const sc_char *)) {
+ if (character != NUL) {
+ sc_char buffer[2];
- buffer[0] = character;
- buffer[1] = NUL;
- print_string_function (buffer);
- }
+ buffer[0] = character;
+ buffer[1] = NUL;
+ print_string_function(buffer);
+ }
}
void
-if_print_character (sc_char character)
-{
- if_print_character_common (character, os_print_string);
+if_print_character(sc_char character) {
+ if_print_character_common(character, os_print_string);
}
void
-if_print_debug_character (sc_char character)
-{
- if_print_character_common (character, os_print_string_debug);
+if_print_debug_character(sc_char character) {
+ if_print_character_common(character, os_print_string_debug);
}
void
-if_print_tag (sc_int tag, const sc_char *arg)
-{
- assert (arg);
+if_print_tag(sc_int tag, const sc_char *arg) {
+ assert(arg);
- os_print_tag (tag, arg);
+ os_print_tag(tag, arg);
}
@@ -200,43 +180,38 @@ if_print_tag (sc_int tag, const sc_char *arg)
* before returning it to the caller.
*/
static void
-if_read_line_common (sc_char *buffer, sc_int length,
- sc_bool (*read_line_function) (sc_char *, sc_int))
-{
- sc_bool is_line_available;
- sc_int last;
- assert (buffer && length > 0);
-
- /* Loop until valid player input is available. */
- do
- {
- /* Space first with a blank line, and clear the buffer. */
- if_print_character ('\n');
- memset (buffer, NUL, length);
-
- is_line_available = read_line_function (buffer, length);
- if (g_vm->shouldQuit())
- return;
- }
- while (!is_line_available);
-
- /* Drop any trailing newline/return. */
- last = strlen (buffer) - 1;
- while (last >= 0
- && (buffer[last] == CARRIAGE_RETURN || buffer[last] == NEWLINE))
- buffer[last--] = NUL;
+if_read_line_common(sc_char *buffer, sc_int length,
+ sc_bool(*read_line_function)(sc_char *, sc_int)) {
+ sc_bool is_line_available;
+ sc_int last;
+ assert(buffer && length > 0);
+
+ /* Loop until valid player input is available. */
+ do {
+ /* Space first with a blank line, and clear the buffer. */
+ if_print_character('\n');
+ memset(buffer, NUL, length);
+
+ is_line_available = read_line_function(buffer, length);
+ if (g_vm->shouldQuit())
+ return;
+ } while (!is_line_available);
+
+ /* Drop any trailing newline/return. */
+ last = strlen(buffer) - 1;
+ while (last >= 0
+ && (buffer[last] == CARRIAGE_RETURN || buffer[last] == NEWLINE))
+ buffer[last--] = NUL;
}
void
-if_read_line (sc_char *buffer, sc_int length)
-{
- if_read_line_common (buffer, length, os_read_line);
+if_read_line(sc_char *buffer, sc_int length) {
+ if_read_line_common(buffer, length, os_read_line);
}
void
-if_read_debug (sc_char *buffer, sc_int length)
-{
- if_read_line_common (buffer, length, os_read_line_debug);
+if_read_debug(sc_char *buffer, sc_int length) {
+ if_read_line_common(buffer, length, os_read_line_debug);
}
@@ -246,9 +221,8 @@ if_read_debug (sc_char *buffer, sc_int length)
* Call OS-specific confirm function.
*/
sc_bool
-if_confirm (sc_int type)
-{
- return os_confirm (type);
+if_confirm(sc_int type) {
+ return os_confirm(type);
}
@@ -261,31 +235,27 @@ if_confirm (sc_int type)
* Call OS-specific functions for saving and restoring games.
*/
void *
-if_open_saved_game (sc_bool is_save)
-{
- return os_open_file (is_save);
+if_open_saved_game(sc_bool is_save) {
+ return os_open_file(is_save);
}
void
-if_write_saved_game (void *opaque, const sc_byte *buffer, sc_int length)
-{
- assert (buffer);
+if_write_saved_game(void *opaque, const sc_byte *buffer, sc_int length) {
+ assert(buffer);
- os_write_file (opaque, buffer, length);
+ os_write_file(opaque, buffer, length);
}
sc_int
-if_read_saved_game (void *opaque, sc_byte *buffer, sc_int length)
-{
- assert (buffer);
+if_read_saved_game(void *opaque, sc_byte *buffer, sc_int length) {
+ assert(buffer);
- return os_read_file (opaque, buffer, length);
+ return os_read_file(opaque, buffer, length);
}
void
-if_close_saved_game (void *opaque)
-{
- os_close_file (opaque);
+if_close_saved_game(void *opaque) {
+ os_close_file(opaque);
}
@@ -295,11 +265,10 @@ if_close_saved_game (void *opaque)
* Call OS-specific hint display function.
*/
void
-if_display_hints (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
+if_display_hints(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
- os_display_hints ((sc_game) game);
+ os_display_hints((sc_game) game);
}
@@ -310,21 +279,19 @@ if_display_hints (sc_gameref_t game)
* Call OS-specific sound and graphic handler functions.
*/
void
-if_update_sound (const sc_char *filename,
- sc_int sound_offset, sc_int sound_length,
- sc_bool is_looping)
-{
- if (strlen (filename) > 0)
- os_play_sound (filename, sound_offset, sound_length, is_looping);
- else
- os_stop_sound ();
+if_update_sound(const sc_char *filename,
+ sc_int sound_offset, sc_int sound_length,
+ sc_bool is_looping) {
+ if (strlen(filename) > 0)
+ os_play_sound(filename, sound_offset, sound_length, is_looping);
+ else
+ os_stop_sound();
}
void
-if_update_graphic (const sc_char *filename,
- sc_int graphic_offset, sc_int graphic_length)
-{
- os_show_graphic (filename, graphic_offset, graphic_length);
+if_update_graphic(const sc_char *filename,
+ sc_int graphic_offset, sc_int graphic_length) {
+ os_show_graphic(filename, graphic_offset, graphic_length);
}
@@ -335,17 +302,15 @@ if_update_graphic (const sc_char *filename,
* Return a version string and Adrift emulation level.
*/
const sc_char *
-sc_scare_version (void)
-{
- if_initialize ();
- return "SCARE " SCARE_VERSION SCARE_PATCH_LEVEL;
+sc_scare_version(void) {
+ if_initialize();
+ return "SCARE " SCARE_VERSION SCARE_PATCH_LEVEL;
}
sc_int
-sc_scare_emulation (void)
-{
- if_initialize ();
- return SCARE_EMULATION;
+sc_scare_emulation(void) {
+ if_initialize();
+ return SCARE_EMULATION;
}
@@ -357,24 +322,23 @@ sc_scare_emulation (void)
* calls from filename and stream variants.
*/
static sc_int
-if_file_read_callback (void *opaque, sc_byte *buffer, sc_int length) {
- Common::SeekableReadStream *stream = (Common::SeekableReadStream *)opaque;
- sc_int bytes;
+if_file_read_callback(void *opaque, sc_byte *buffer, sc_int length) {
+ Common::SeekableReadStream *stream = (Common::SeekableReadStream *)opaque;
+ sc_int bytes;
- bytes = stream->read(buffer, length);
- if (stream->err())
- sc_error ("if_file_read_callback: warning: read error\n");
+ bytes = stream->read(buffer, length);
+ if (stream->err())
+ sc_error("if_file_read_callback: warning: read error\n");
- return bytes;
+ return bytes;
}
-static void if_file_write_callback (void *opaque, const sc_byte *buffer, sc_int length)
-{
- Common::WriteStream *stream = (Common::WriteStream *) opaque;
+static void if_file_write_callback(void *opaque, const sc_byte *buffer, sc_int length) {
+ Common::WriteStream *stream = (Common::WriteStream *) opaque;
- stream->write(buffer, length);
- if (stream->err())
- sc_error ("if_file_write_callback: warning: write error\n");
+ stream->write(buffer, length);
+ if (stream->err())
+ sc_error("if_file_write_callback: warning: write error\n");
}
@@ -387,53 +351,49 @@ static void if_file_write_callback (void *opaque, const sc_byte *buffer, sc_int
* and _stream() variants are adapters for run_create().
*/
sc_game
-sc_game_from_filename (const sc_char *filename) {
- Common::File *stream;
- sc_game game;
+sc_game_from_filename(const sc_char *filename) {
+ Common::File *stream;
+ sc_game game;
- if_initialize ();
- if (!filename)
- {
- sc_error ("sc_game_from_filename: nullptr filename\n");
- return nullptr;
- }
+ if_initialize();
+ if (!filename) {
+ sc_error("sc_game_from_filename: nullptr filename\n");
+ return nullptr;
+ }
- stream = new Common::File();
- if (!stream->open(filename)) {
- delete stream;
- sc_error ("sc_game_from_filename: fopen error\n");
- return nullptr;
- }
+ stream = new Common::File();
+ if (!stream->open(filename)) {
+ delete stream;
+ sc_error("sc_game_from_filename: fopen error\n");
+ return nullptr;
+ }
- game = run_create (if_file_read_callback, stream);
- delete stream;
+ game = run_create(if_file_read_callback, stream);
+ delete stream;
- return game;
+ return game;
}
-sc_game sc_game_from_stream (Common::SeekableReadStream *stream) {
- if_initialize ();
- if (!stream)
- {
- sc_error ("sc_game_from_stream: nullptr stream\n");
- return nullptr;
- }
+sc_game sc_game_from_stream(Common::SeekableReadStream *stream) {
+ if_initialize();
+ if (!stream) {
+ sc_error("sc_game_from_stream: nullptr stream\n");
+ return nullptr;
+ }
- return run_create (if_file_read_callback, stream);
+ return run_create(if_file_read_callback, stream);
}
sc_game
-sc_game_from_callback (sc_int (*callback) (void *, sc_byte *, sc_int),
- void *opaque)
-{
- if_initialize ();
- if (!callback)
- {
- sc_error ("sc_game_from_callback: nullptr callback\n");
- return nullptr;
- }
+sc_game_from_callback(sc_int(*callback)(void *, sc_byte *, sc_int),
+ void *opaque) {
+ if_initialize();
+ if (!callback) {
+ sc_error("sc_game_from_callback: nullptr callback\n");
+ return nullptr;
+ }
- return run_create (callback, opaque);
+ return run_create(callback, opaque);
}
@@ -444,20 +404,18 @@ sc_game_from_callback (sc_int (*callback) (void *, sc_byte *, sc_int),
* is a valid game. Returns TRUE on game error, FALSE if okay.
*/
static sc_bool
-if_game_error (sc_gameref_t game, const sc_char *function_name)
-{
- /* Check for invalid game -- null pointer or bad magic. */
- if (!gs_is_game_valid (game))
- {
- if (game)
- sc_error ("%s: invalid game\n", function_name);
- else
- sc_error ("%s: nullptr game\n", function_name);
- return TRUE;
- }
+if_game_error(sc_gameref_t game, const sc_char *function_name) {
+ /* Check for invalid game -- null pointer or bad magic. */
+ if (!gs_is_game_valid(game)) {
+ if (game)
+ sc_error("%s: invalid game\n", function_name);
+ else
+ sc_error("%s: nullptr game\n", function_name);
+ return TRUE;
+ }
- /* No game error. */
- return FALSE;
+ /* No game error. */
+ return FALSE;
}
@@ -478,69 +436,63 @@ if_game_error (sc_gameref_t game, const sc_char *function_name)
* be restored. sc_undo_game_turn() behaves like sc_load_game().
*/
void
-sc_interpret_game (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_interpret_game(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_interpret_game"))
- return;
+ if (if_game_error(game_, "sc_interpret_game"))
+ return;
- run_interpret (game_);
+ run_interpret(game_);
}
void
-sc_restart_game (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_restart_game(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_restart_game"))
- return;
+ if (if_game_error(game_, "sc_restart_game"))
+ return;
- run_restart (game_);
+ run_restart(game_);
}
sc_bool
-sc_save_game (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_save_game(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_save_game"))
- return FALSE;
+ if (if_game_error(game_, "sc_save_game"))
+ return FALSE;
- return run_save_prompted (game_);
+ return run_save_prompted(game_);
}
sc_bool
-sc_load_game (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_load_game(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_load_game"))
- return FALSE;
+ if (if_game_error(game_, "sc_load_game"))
+ return FALSE;
- return run_restore_prompted (game_);
+ return run_restore_prompted(game_);
}
sc_bool
-sc_undo_game_turn (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_undo_game_turn(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_undo_game_turn"))
- return FALSE;
+ if (if_game_error(game_, "sc_undo_game_turn"))
+ return FALSE;
- return run_undo (game_);
+ return run_undo(game_);
}
void
-sc_quit_game (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_quit_game(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_quit_game"))
- return;
+ if (if_game_error(game_, "sc_quit_game"))
+ return;
- run_quit (game_);
+ run_quit(game_);
}
@@ -559,132 +511,119 @@ sc_quit_game (sc_game game)
* streams.
*/
sc_bool
-sc_save_game_to_filename (sc_game game, const sc_char *filename)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- Common::OutSaveFile *sf;
+sc_save_game_to_filename(sc_game game, const sc_char *filename) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ Common::OutSaveFile *sf;
- if (if_game_error (game_, "sc_save_game_to_filename"))
- return FALSE;
+ if (if_game_error(game_, "sc_save_game_to_filename"))
+ return FALSE;
- if (!filename)
- {
- sc_error ("sc_save_game_to_filename: nullptr filename\n");
- return FALSE;
- }
+ if (!filename) {
+ sc_error("sc_save_game_to_filename: nullptr filename\n");
+ return FALSE;
+ }
- sf = g_system->getSavefileManager()->openForSaving(filename);
- if (!sf) {
- sc_error ("sc_save_game_to_filename: fopen error\n");
- return FALSE;
- }
+ sf = g_system->getSavefileManager()->openForSaving(filename);
+ if (!sf) {
+ sc_error("sc_save_game_to_filename: fopen error\n");
+ return FALSE;
+ }
- run_save(game_, if_file_write_callback, sf);
- sf->finalize();
- delete sf;
+ run_save(game_, if_file_write_callback, sf);
+ sf->finalize();
+ delete sf;
- return TRUE;
+ return TRUE;
}
void
-sc_save_game_to_stream (sc_game game, Common::SeekableReadStream *stream)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_save_game_to_stream(sc_game game, Common::SeekableReadStream *stream) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_save_game_to_stream"))
- return;
+ if (if_game_error(game_, "sc_save_game_to_stream"))
+ return;
- if (!stream)
- {
- sc_error ("sc_save_game_to_stream: nullptr stream\n");
- return;
- }
+ if (!stream) {
+ sc_error("sc_save_game_to_stream: nullptr stream\n");
+ return;
+ }
- run_save (game_, if_file_write_callback, stream);
+ run_save(game_, if_file_write_callback, stream);
}
void
-sc_save_game_to_callback (sc_game game,
- void (*callback) (void *, const sc_byte *, sc_int),
- void *opaque)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_save_game_to_callback(sc_game game,
+ void (*callback)(void *, const sc_byte *, sc_int),
+ void *opaque) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_save_game_to_callback"))
- return;
+ if (if_game_error(game_, "sc_save_game_to_callback"))
+ return;
- if (!callback)
- {
- sc_error ("sc_save_game_to_callback: nullptr callback\n");
- return;
- }
+ if (!callback) {
+ sc_error("sc_save_game_to_callback: nullptr callback\n");
+ return;
+ }
- run_save (game_, callback, opaque);
+ run_save(game_, callback, opaque);
}
sc_bool
-sc_load_game_from_filename (sc_game game, const sc_char *filename)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- Common::InSaveFile *sf;
- sc_bool status;
+sc_load_game_from_filename(sc_game game, const sc_char *filename) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ Common::InSaveFile *sf;
+ sc_bool status;
- if (if_game_error (game_, "sc_load_game_from_filename"))
- return FALSE;
+ if (if_game_error(game_, "sc_load_game_from_filename"))
+ return FALSE;
- if (!filename)
- {
- sc_error ("sc_load_game_from_filename: nullptr filename\n");
- return FALSE;
- }
+ if (!filename) {
+ sc_error("sc_load_game_from_filename: nullptr filename\n");
+ return FALSE;
+ }
- sf = g_system->getSavefileManager()->openForLoading(filename);
- if (!sf)
- {
- sc_error ("sc_load_game_from_filename: fopen error\n");
- return FALSE;
- }
+ sf = g_system->getSavefileManager()->openForLoading(filename);
+ if (!sf) {
+ sc_error("sc_load_game_from_filename: fopen error\n");
+ return FALSE;
+ }
- status = run_restore (game_, if_file_read_callback, sf);
- delete sf;
+ status = run_restore(game_, if_file_read_callback, sf);
+ delete sf;
- return status;
+ return status;
}
sc_bool
-sc_load_game_from_stream (sc_game game, Common::SeekableReadStream *stream)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_load_game_from_stream(sc_game game, Common::SeekableReadStream *stream) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_load_game_from_stream"))
- return FALSE;
+ if (if_game_error(game_, "sc_load_game_from_stream"))
+ return FALSE;
- if (!stream)
- {
- sc_error ("sc_load_game_from_stream: nullptr stream\n");
- return FALSE;
- }
+ if (!stream) {
+ sc_error("sc_load_game_from_stream: nullptr stream\n");
+ return FALSE;
+ }
- return run_restore (game_, if_file_read_callback, stream);
+ return run_restore(game_, if_file_read_callback, stream);
}
sc_bool
-sc_load_game_from_callback (sc_game game,
- sc_int (*callback) (void *, sc_byte *, sc_int),
- void *opaque)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_load_game_from_callback(sc_game game,
+ sc_int(*callback)(void *, sc_byte *, sc_int),
+ void *opaque) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_load_game_from_callback"))
- return FALSE;
+ if (if_game_error(game_, "sc_load_game_from_callback"))
+ return FALSE;
- if (!callback)
- {
- sc_error ("sc_load_game_from_callback: nullptr callback\n");
- return FALSE;
- }
+ if (!callback) {
+ sc_error("sc_load_game_from_callback: nullptr callback\n");
+ return FALSE;
+ }
- return run_restore (game_, callback, opaque);
+ return run_restore(game_, callback, opaque);
}
@@ -694,14 +633,13 @@ sc_load_game_from_callback (sc_game game,
* Called by the OS-specific layer to free run context memory.
*/
void
-sc_free_game (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_free_game(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_free_game"))
- return;
+ if (if_game_error(game_, "sc_free_game"))
+ return;
- run_destroy (game_);
+ run_destroy(game_);
}
@@ -725,206 +663,191 @@ sc_free_game (sc_game game)
* Return a few attributes of a game.
*/
sc_bool
-sc_is_game_running (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_is_game_running(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_is_game_running"))
- return FALSE;
+ if (if_game_error(game_, "sc_is_game_running"))
+ return FALSE;
- return run_is_running (game_);
+ return run_is_running(game_);
}
const sc_char *
-sc_get_game_name (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_char *retval;
+sc_get_game_name(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_char *retval;
- if (if_game_error (game_, "sc_get_game_name"))
- return "[invalid game]";
+ if (if_game_error(game_, "sc_get_game_name"))
+ return "[invalid game]";
- run_get_attributes (game_, &retval,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, &retval,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr);
+ return retval;
}
const sc_char *
-sc_get_game_author (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_char *retval;
+sc_get_game_author(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_char *retval;
- if (if_game_error (game_, "sc_get_game_author"))
- return "[invalid game]";
+ if (if_game_error(game_, "sc_get_game_author"))
+ return "[invalid game]";
- run_get_attributes (game_, nullptr, &retval,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, &retval,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr);
+ return retval;
}
const sc_char *
-sc_get_game_compile_date (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_char *retval;
+sc_get_game_compile_date(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_char *retval;
- if (if_game_error (game_, "sc_get_game_compile_date"))
- return "[invalid game]";
+ if (if_game_error(game_, "sc_get_game_compile_date"))
+ return "[invalid game]";
- run_get_attributes (game_, nullptr, nullptr, &retval,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, &retval,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ return retval;
}
sc_int
-sc_get_game_turns (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_int retval;
+sc_get_game_turns(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_int retval;
- if (if_game_error (game_, "sc_get_game_turns"))
- return 0;
+ if (if_game_error(game_, "sc_get_game_turns"))
+ return 0;
- run_get_attributes (game_, nullptr, nullptr, nullptr, &retval,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, &retval,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ return retval;
}
sc_int
-sc_get_game_score (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_int retval;
+sc_get_game_score(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_int retval;
- if (if_game_error (game_, "sc_get_game_score"))
- return 0;
+ if (if_game_error(game_, "sc_get_game_score"))
+ return 0;
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, &retval,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, &retval,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ return retval;
}
sc_int
-sc_get_game_max_score (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_int retval;
+sc_get_game_max_score(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_int retval;
- if (if_game_error (game_, "sc_get_game_max_score"))
- return 0;
+ if (if_game_error(game_, "sc_get_game_max_score"))
+ return 0;
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, &retval,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, &retval,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ return retval;
}
const sc_char *
-sc_get_game_room (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_char *retval;
+sc_get_game_room(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_char *retval;
- if (if_game_error (game_, "sc_get_game_room"))
- return "[invalid game]";
+ if (if_game_error(game_, "sc_get_game_room"))
+ return "[invalid game]";
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &retval,
- nullptr, nullptr, nullptr, nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &retval,
+ nullptr, nullptr, nullptr, nullptr, nullptr);
+ return retval;
}
const sc_char *
-sc_get_game_status_line (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_char *retval;
+sc_get_game_status_line(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_char *retval;
- if (if_game_error (game_, "sc_get_game_status_line"))
- return "[invalid game]";
+ if (if_game_error(game_, "sc_get_game_status_line"))
+ return "[invalid game]";
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- &retval, nullptr, nullptr, nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ &retval, nullptr, nullptr, nullptr, nullptr);
+ return retval;
}
const sc_char *
-sc_get_game_preferred_font (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_char *retval;
+sc_get_game_preferred_font(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_char *retval;
- if (if_game_error (game_, "sc_get_game_preferred_font"))
- return "[invalid game]";
+ if (if_game_error(game_, "sc_get_game_preferred_font"))
+ return "[invalid game]";
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, &retval, nullptr, nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, &retval, nullptr, nullptr, nullptr);
+ return retval;
}
sc_bool
-sc_get_game_bold_room_names (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_bool retval;
+sc_get_game_bold_room_names(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_bool retval;
- if (if_game_error (game_, "sc_get_game_bold_room_names"))
- return FALSE;
+ if (if_game_error(game_, "sc_get_game_bold_room_names"))
+ return FALSE;
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, &retval, nullptr, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, &retval, nullptr, nullptr);
+ return retval;
}
sc_bool
-sc_get_game_verbose (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_bool retval;
+sc_get_game_verbose(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_bool retval;
- if (if_game_error (game_, "sc_get_game_verbose"))
- return FALSE;
+ if (if_game_error(game_, "sc_get_game_verbose"))
+ return FALSE;
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, &retval, nullptr);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, &retval, nullptr);
+ return retval;
}
sc_bool
-sc_get_game_notify_score_change (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_bool retval;
+sc_get_game_notify_score_change(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_bool retval;
- if (if_game_error (game_, "sc_get_game_notify_score_change"))
- return FALSE;
+ if (if_game_error(game_, "sc_get_game_notify_score_change"))
+ return FALSE;
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, &retval);
- return retval;
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, &retval);
+ return retval;
}
sc_bool
-sc_has_game_completed (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_has_game_completed(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_has_game_completed"))
- return FALSE;
+ if (if_game_error(game_, "sc_has_game_completed"))
+ return FALSE;
- return run_has_completed (game_);
+ return run_has_completed(game_);
}
sc_bool
-sc_is_game_undo_available (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_is_game_undo_available(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_is_game_undo_available"))
- return FALSE;
+ if (if_game_error(game_, "sc_is_game_undo_available"))
+ return FALSE;
- return run_is_undo_available (game_);
+ return run_is_undo_available(game_);
}
@@ -936,45 +859,42 @@ sc_is_game_undo_available (sc_game game)
* Set a few attributes of a game.
*/
void
-sc_set_game_bold_room_names (sc_game game, sc_bool flag)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_bool bold, verbose, notify;
+sc_set_game_bold_room_names(sc_game game, sc_bool flag) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_bool bold, verbose, notify;
- if (if_game_error (game_, "sc_set_game_bold_room_names"))
- return;
+ if (if_game_error(game_, "sc_set_game_bold_room_names"))
+ return;
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, &bold, &verbose, &notify);
- run_set_attributes (game_, flag, verbose, notify);
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, &bold, &verbose, &notify);
+ run_set_attributes(game_, flag, verbose, notify);
}
void
-sc_set_game_verbose (sc_game game, sc_bool flag)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_bool bold, verbose, notify;
+sc_set_game_verbose(sc_game game, sc_bool flag) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_bool bold, verbose, notify;
- if (if_game_error (game_, "sc_set_game_verbose"))
- return;
+ if (if_game_error(game_, "sc_set_game_verbose"))
+ return;
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, &bold, &verbose, &notify);
- run_set_attributes (game_, bold, flag, notify);
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, &bold, &verbose, &notify);
+ run_set_attributes(game_, bold, flag, notify);
}
void
-sc_set_game_notify_score_change (sc_game game, sc_bool flag)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- sc_bool bold, verbose, notify;
+sc_set_game_notify_score_change(sc_game game, sc_bool flag) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ sc_bool bold, verbose, notify;
- if (if_game_error (game_, "sc_set_game_notify_score_change"))
- return;
+ if (if_game_error(game_, "sc_set_game_notify_score_change"))
+ return;
- run_get_attributes (game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, &bold, &verbose, &notify);
- run_set_attributes (game_, bold, verbose, flag);
+ run_get_attributes(game_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, &bold, &verbose, &notify);
+ run_set_attributes(game_, bold, verbose, flag);
}
@@ -985,25 +905,23 @@ sc_set_game_notify_score_change (sc_game game, sc_bool flag)
* Indicate the game's use of resources.
*/
sc_bool
-sc_does_game_use_sounds (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_does_game_use_sounds(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_does_game_use_sounds"))
- return FALSE;
+ if (if_game_error(game_, "sc_does_game_use_sounds"))
+ return FALSE;
- return res_has_sound (game_);
+ return res_has_sound(game_);
}
sc_bool
-sc_does_game_use_graphics (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_does_game_use_graphics(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_does_game_use_graphics"))
- return FALSE;
+ if (if_game_error(game_, "sc_does_game_use_graphics"))
+ return FALSE;
- return res_has_graphics (game_);
+ return res_has_graphics(game_);
}
@@ -1017,82 +935,73 @@ sc_does_game_use_graphics (sc_game game)
* Iterate currently available hints, and return strings for a hint.
*/
sc_game_hint
-sc_get_first_game_hint (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_get_first_game_hint(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_get_first_game_hint"))
- return nullptr;
+ if (if_game_error(game_, "sc_get_first_game_hint"))
+ return nullptr;
- return run_hint_iterate (game_, nullptr);
+ return run_hint_iterate(game_, nullptr);
}
sc_game_hint
-sc_get_next_game_hint (sc_game game, sc_game_hint hint)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_hintref_t hint_ = (const sc_hintref_t)hint;
+sc_get_next_game_hint(sc_game game, sc_game_hint hint) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_hintref_t hint_ = (const sc_hintref_t)hint;
- if (if_game_error (game_, "sc_get_next_game_hint"))
- return nullptr;
- if (!hint_)
- {
- sc_error ("sc_get_next_game_hint: nullptr hint\n");
- return nullptr;
- }
+ if (if_game_error(game_, "sc_get_next_game_hint"))
+ return nullptr;
+ if (!hint_) {
+ sc_error("sc_get_next_game_hint: nullptr hint\n");
+ return nullptr;
+ }
- return run_hint_iterate (game_, hint_);
+ return run_hint_iterate(game_, hint_);
}
const sc_char *
-sc_get_game_hint_question (sc_game game, sc_game_hint hint)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_hintref_t hint_ = (const sc_hintref_t)hint;
+sc_get_game_hint_question(sc_game game, sc_game_hint hint) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_hintref_t hint_ = (const sc_hintref_t)hint;
- if (if_game_error (game_, "sc_get_game_hint_question"))
- return nullptr;
- if (!hint_)
- {
- sc_error ("sc_get_game_hint_question: nullptr hint\n");
- return nullptr;
- }
+ if (if_game_error(game_, "sc_get_game_hint_question"))
+ return nullptr;
+ if (!hint_) {
+ sc_error("sc_get_game_hint_question: nullptr hint\n");
+ return nullptr;
+ }
- return run_get_hint_question (game_, hint_);
+ return run_get_hint_question(game_, hint_);
}
const sc_char *
-sc_get_game_subtle_hint (sc_game game, sc_game_hint hint)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_hintref_t hint_ = (const sc_hintref_t)hint;
+sc_get_game_subtle_hint(sc_game game, sc_game_hint hint) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_hintref_t hint_ = (const sc_hintref_t)hint;
- if (if_game_error (game_, "sc_get_game_subtle_hint"))
- return nullptr;
- if (!hint_)
- {
- sc_error ("sc_get_game_subtle_hint: nullptr hint\n");
- return nullptr;
- }
+ if (if_game_error(game_, "sc_get_game_subtle_hint"))
+ return nullptr;
+ if (!hint_) {
+ sc_error("sc_get_game_subtle_hint: nullptr hint\n");
+ return nullptr;
+ }
- return run_get_subtle_hint (game_, hint_);
+ return run_get_subtle_hint(game_, hint_);
}
const sc_char *
-sc_get_game_unsubtle_hint (sc_game game, sc_game_hint hint)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
- const sc_hintref_t hint_ = (const sc_hintref_t)hint;
+sc_get_game_unsubtle_hint(sc_game game, sc_game_hint hint) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
+ const sc_hintref_t hint_ = (const sc_hintref_t)hint;
- if (if_game_error (game_, "sc_get_game_unsubtle_hint"))
- return nullptr;
- if (!hint_)
- {
- sc_error ("sc_get_game_unsubtle_hint: nullptr hint\n");
- return nullptr;
- }
+ if (if_game_error(game_, "sc_get_game_unsubtle_hint"))
+ return nullptr;
+ if (!hint_) {
+ sc_error("sc_get_game_unsubtle_hint: nullptr hint\n");
+ return nullptr;
+ }
- return run_get_unsubtle_hint (game_, hint_);
+ return run_get_unsubtle_hint(game_, hint_);
}
@@ -1104,36 +1013,33 @@ sc_get_game_unsubtle_hint (sc_game game, sc_game_hint hint)
* Enable, disable, and query game debugging, and run a single debug command.
*/
void
-sc_set_game_debugger_enabled (sc_game game, sc_bool flag)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_set_game_debugger_enabled(sc_game game, sc_bool flag) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_set_game_debugger_enabled"))
- return;
+ if (if_game_error(game_, "sc_set_game_debugger_enabled"))
+ return;
- debug_set_enabled (game_, flag);
+ debug_set_enabled(game_, flag);
}
sc_bool
-sc_get_game_debugger_enabled (sc_game game)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_get_game_debugger_enabled(sc_game game) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_get_game_debugger_enabled"))
- return FALSE;
+ if (if_game_error(game_, "sc_get_game_debugger_enabled"))
+ return FALSE;
- return debug_get_enabled (game_);
+ return debug_get_enabled(game_);
}
sc_bool
-sc_run_game_debugger_command (sc_game game, const sc_char *debug_command)
-{
- const sc_gameref_t game_ = (const sc_gameref_t)game;
+sc_run_game_debugger_command(sc_game game, const sc_char *debug_command) {
+ const sc_gameref_t game_ = (const sc_gameref_t)game;
- if (if_game_error (game_, "sc_run_game_debugger_command"))
- return FALSE;
+ if (if_game_error(game_, "sc_run_game_debugger_command"))
+ return FALSE;
- return debug_run_command (game_, debug_command);
+ return debug_run_command(game_, debug_command);
}
@@ -1144,21 +1050,18 @@ sc_run_game_debugger_command (sc_game game, const sc_char *debug_command)
* Set the interpreter locale, and get the currently set locale.
*/
sc_bool
-sc_set_locale (const sc_char *name)
-{
- if (!name)
- {
- sc_error ("sc_set_locale: nullptr name\n");
- return FALSE;
- }
+sc_set_locale(const sc_char *name) {
+ if (!name) {
+ sc_error("sc_set_locale: nullptr name\n");
+ return FALSE;
+ }
- return loc_set_locale (name);
+ return loc_set_locale(name);
}
const sc_char *
-sc_get_locale (void)
-{
- return loc_get_locale ();
+sc_get_locale(void) {
+ return loc_get_locale();
}
@@ -1170,24 +1073,21 @@ sc_get_locale (void)
* for random number generators.
*/
void
-sc_set_portable_random (sc_bool flag)
-{
- if (flag)
- sc_set_congruential_random ();
- else
- sc_set_platform_random ();
+sc_set_portable_random(sc_bool flag) {
+ if (flag)
+ sc_set_congruential_random();
+ else
+ sc_set_platform_random();
}
void
-sc_reseed_random_sequence (sc_uint new_seed)
-{
- if (new_seed == 0)
- {
- sc_error ("sc_reseed_random_sequence: new_seed may not be 0\n");
- return;
- }
-
- sc_seed_random (new_seed);
+sc_reseed_random_sequence(sc_uint new_seed) {
+ if (new_seed == 0) {
+ sc_error("sc_reseed_random_sequence: new_seed may not be 0\n");
+ return;
+ }
+
+ sc_seed_random(new_seed);
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sclibrar.cpp b/engines/glk/adrift/sclibrar.cpp
index 8f97a7c05a..bfa1711aea 100644
--- a/engines/glk/adrift/sclibrar.cpp
+++ b/engines/glk/adrift/sclibrar.cpp
@@ -40,10 +40,10 @@ namespace Adrift {
/* Assorted definitions and constants. */
static const sc_char NUL = '\0';
static const sc_char COMMA = ',';
-enum
-{ SECS_PER_MINUTE = 60,
- MINS_PER_HOUR = 60,
- SECS_PER_HOUR = 3600
+enum {
+ SECS_PER_MINUTE = 60,
+ MINS_PER_HOUR = 60,
+ SECS_PER_HOUR = 3600
};
enum { LIB_ALLOCATION_AVOIDANCE_SIZE = 128 };
@@ -59,25 +59,24 @@ static sc_bool lib_trace = FALSE;
* with ALRs.
*/
void
-lib_warn_battle_system (void)
-{
- if_print_tag (SC_TAG_FONT, "size=16");
- if_print_string ("SCARE WARNING");
- if_print_tag (SC_TAG_ENDFONT, "");
+lib_warn_battle_system(void) {
+ if_print_tag(SC_TAG_FONT, "size=16");
+ if_print_string("SCARE WARNING");
+ if_print_tag(SC_TAG_ENDFONT, "");
- if_print_string (
- "\n\nThe game uses Adrift's Battle System, something not fully supported"
- " by this release of SCARE.\n\n");
+ if_print_string(
+ "\n\nThe game uses Adrift's Battle System, something not fully supported"
+ " by this release of SCARE.\n\n");
- if_print_string (
- "SCARE will still run the game, but it will not create character"
- " battles where they would normally occur. For some games, this may"
- " be perfectly okay, as the Battle System is sometimes turned on"
- " by accident in a game, but never actually used. For others, though,"
- " the omission of this feature may be more serious.\n\n");
+ if_print_string(
+ "SCARE will still run the game, but it will not create character"
+ " battles where they would normally occur. For some games, this may"
+ " be perfectly okay, as the Battle System is sometimes turned on"
+ " by accident in a game, but never actually used. For others, though,"
+ " the omission of this feature may be more serious.\n\n");
- if_print_string ("Please press a key to continue...\n\n");
- if_print_tag (SC_TAG_WAITKEY, "");
+ if_print_string("Please press a key to continue...\n\n");
+ if_print_tag(SC_TAG_WAITKEY, "");
}
@@ -87,34 +86,31 @@ lib_warn_battle_system (void)
* Return a random member of a roomgroup.
*/
sc_int
-lib_random_roomgroup_member (sc_gameref_t game, sc_int roomgroup)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[4];
- sc_int count, room;
+lib_random_roomgroup_member(sc_gameref_t game, sc_int roomgroup) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[4];
+ sc_int count, room;
- /* Get the count of rooms in the group. */
- vt_key[0].string = "RoomGroups";
- vt_key[1].integer = roomgroup;
- vt_key[2].string = "List2";
- count = prop_get_child_count (bundle, "I<-sis", vt_key);
- if (count == 0)
- {
- sc_fatal ("lib_random_roomgroup_member:"
- " no rooms in group %ld\n", roomgroup);
- }
+ /* Get the count of rooms in the group. */
+ vt_key[0].string = "RoomGroups";
+ vt_key[1].integer = roomgroup;
+ vt_key[2].string = "List2";
+ count = prop_get_child_count(bundle, "I<-sis", vt_key);
+ if (count == 0) {
+ sc_fatal("lib_random_roomgroup_member:"
+ " no rooms in group %ld\n", roomgroup);
+ }
- /* Pick a room at random and return it. */
- vt_key[3].integer = sc_randomint (0, count - 1);
- room = prop_get_integer (bundle, "I<-sisi", vt_key);
+ /* Pick a room at random and return it. */
+ vt_key[3].integer = sc_randomint(0, count - 1);
+ room = prop_get_integer(bundle, "I<-sisi", vt_key);
- if (lib_trace)
- {
- sc_trace ("Library: random room for group %ld is %ld\n",
- roomgroup, room);
- }
+ if (lib_trace) {
+ sc_trace("Library: random room for group %ld is %ld\n",
+ roomgroup, room);
+ }
- return room;
+ return room;
}
@@ -124,129 +120,123 @@ lib_random_roomgroup_member (sc_gameref_t game, sc_int roomgroup)
* Return TRUE if a particular alternate room description should be used.
*/
static sc_bool
-lib_use_room_alt (sc_gameref_t game, sc_int room, sc_int alt)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int type;
- sc_bool retval;
-
- /* Get alternate type. */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Alts";
- vt_key[3].integer = alt;
- vt_key[4].string = "Type";
- type = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- /* Select based on type. */
- retval = FALSE;
- switch (type)
- {
- case 0: /* Task. */
- {
- sc_int var2, var3;
-
- vt_key[4].string = "Var2";
- var2 = prop_get_integer (bundle, "I<-sisis", vt_key);
- if (var2 == 0) /* No task. */
- retval = TRUE;
- else
- {
- vt_key[4].string = "Var3";
- var3 = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- retval = gs_task_done (game, var2 - 1) == !(var3 != 0);
- }
- break;
- }
-
- case 1: /* Stateful object. */
- {
- sc_int var2, var3, object;
-
- vt_key[4].string = "Var2";
- var2 = prop_get_integer (bundle, "I<-sisis", vt_key);
- if (var2 == 0) /* No object. */
- retval = TRUE;
- else
- {
- vt_key[4].string = "Var3";
- var3 = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- object = obj_stateful_index (game, var2 - 1);
- retval = restr_pass_task_object_state (game, object + 1, var3 - 1);
- }
- break;
- }
-
- case 2: /* Player condition. */
- {
- sc_int var2, var3, object;
-
- 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);
-
- if (var3 == 0)
- {
- switch (var2)
- {
- case 0: case 2: case 5:
- retval = TRUE;
- break;
- case 1: case 3: case 4:
- retval = FALSE;
- break;
- default:
- sc_fatal ("lib_use_room_alt:"
- " invalid player condition, %ld\n", var2);
- }
- break;
- }
-
- if (var2 == 2 || var2 == 3)
- object = obj_wearable_object (game, var3 - 1);
- else
- object = obj_dynamic_object (game, var3 - 1);
-
- switch (var2)
- {
- case 0: /* Isn't holding (or wearing). */
- retval = gs_object_position (game, object) != OBJ_HELD_PLAYER
- && gs_object_position (game, object) != OBJ_WORN_PLAYER;
- break;
- case 1: /* Is holding (or wearing). */
- retval = gs_object_position (game, object) == OBJ_HELD_PLAYER
- || gs_object_position (game, object) == OBJ_WORN_PLAYER;
- break;
- case 2: /* Isn't wearing. */
- retval = gs_object_position (game, object) != OBJ_WORN_PLAYER;
- break;
- case 3: /* Is wearing. */
- retval = gs_object_position (game, object) == OBJ_WORN_PLAYER;
- break;
- case 4: /* Isn't in the same room as. */
- retval = !obj_indirectly_in_room (game,
- object, gs_playerroom (game));
- break;
- case 5: /* Is in the same room as. */
- retval = obj_indirectly_in_room (game,
- object, gs_playerroom (game));
- break;
- default:
- sc_fatal ("lib_use_room_alt:"
- " invalid player condition, %ld\n", var2);
- }
- break;
- }
-
- default:
- sc_fatal ("lib_use_room_alt: invalid type, %ld\n", type);
- }
-
- return retval;
+lib_use_room_alt(sc_gameref_t game, sc_int room, sc_int alt) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int type;
+ sc_bool retval;
+
+ /* Get alternate type. */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Alts";
+ vt_key[3].integer = alt;
+ vt_key[4].string = "Type";
+ type = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ /* Select based on type. */
+ retval = FALSE;
+ switch (type) {
+ case 0: { /* Task. */
+ sc_int var2, var3;
+
+ vt_key[4].string = "Var2";
+ var2 = prop_get_integer(bundle, "I<-sisis", vt_key);
+ if (var2 == 0) /* No task. */
+ retval = TRUE;
+ else {
+ vt_key[4].string = "Var3";
+ var3 = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ retval = gs_task_done(game, var2 - 1) == !(var3 != 0);
+ }
+ break;
+ }
+
+ case 1: { /* Stateful object. */
+ sc_int var2, var3, object;
+
+ vt_key[4].string = "Var2";
+ var2 = prop_get_integer(bundle, "I<-sisis", vt_key);
+ if (var2 == 0) /* No object. */
+ retval = TRUE;
+ else {
+ vt_key[4].string = "Var3";
+ var3 = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ object = obj_stateful_index(game, var2 - 1);
+ retval = restr_pass_task_object_state(game, object + 1, var3 - 1);
+ }
+ break;
+ }
+
+ case 2: { /* Player condition. */
+ sc_int var2, var3, object;
+
+ 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);
+
+ if (var3 == 0) {
+ switch (var2) {
+ case 0:
+ case 2:
+ case 5:
+ retval = TRUE;
+ break;
+ case 1:
+ case 3:
+ case 4:
+ retval = FALSE;
+ break;
+ default:
+ sc_fatal("lib_use_room_alt:"
+ " invalid player condition, %ld\n", var2);
+ }
+ break;
+ }
+
+ if (var2 == 2 || var2 == 3)
+ object = obj_wearable_object(game, var3 - 1);
+ else
+ object = obj_dynamic_object(game, var3 - 1);
+
+ switch (var2) {
+ case 0: /* Isn't holding (or wearing). */
+ retval = gs_object_position(game, object) != OBJ_HELD_PLAYER
+ && gs_object_position(game, object) != OBJ_WORN_PLAYER;
+ break;
+ case 1: /* Is holding (or wearing). */
+ retval = gs_object_position(game, object) == OBJ_HELD_PLAYER
+ || gs_object_position(game, object) == OBJ_WORN_PLAYER;
+ break;
+ case 2: /* Isn't wearing. */
+ retval = gs_object_position(game, object) != OBJ_WORN_PLAYER;
+ break;
+ case 3: /* Is wearing. */
+ retval = gs_object_position(game, object) == OBJ_WORN_PLAYER;
+ break;
+ case 4: /* Isn't in the same room as. */
+ retval = !obj_indirectly_in_room(game,
+ object, gs_playerroom(game));
+ break;
+ case 5: /* Is in the same room as. */
+ retval = obj_indirectly_in_room(game,
+ object, gs_playerroom(game));
+ break;
+ default:
+ sc_fatal("lib_use_room_alt:"
+ " invalid player condition, %ld\n", var2);
+ }
+ break;
+ }
+
+ default:
+ sc_fatal("lib_use_room_alt: invalid type, %ld\n", type);
+ }
+
+ return retval;
}
@@ -258,61 +248,54 @@ lib_use_room_alt (sc_gameref_t game, sc_int room, sc_int alt)
* no alt overrides the default room long description.
*/
static sc_int
-lib_find_starting_alt (sc_gameref_t game, sc_int room)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int alt_count, alt, retval;
-
- /* Get count of room alternates. */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Alts";
- alt_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- /* Search backwards for a method-0 or method-1 overriding description. */
- retval = -1;
- for (alt = alt_count - 1; alt >= 0; alt--)
- {
- sc_int method;
-
- vt_key[3].integer = alt;
- vt_key[4].string = "DisplayRoom";
- method = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- if (!(method == 0 || method == 1))
- continue;
-
- if (lib_use_room_alt (game, room, alt))
- {
- const sc_char *m1;
-
- vt_key[3].integer = alt;
- vt_key[4].string = "M1";
- m1 = prop_get_string (bundle, "S<-sisis", vt_key);
- if (!sc_strempty (m1))
- {
- retval = alt;
- break;
- }
- }
- else
- {
- const sc_char *m2;
-
- vt_key[3].integer = alt;
- vt_key[4].string = "M2";
- m2 = prop_get_string (bundle, "S<-sisis", vt_key);
- if (!sc_strempty (m2))
- {
- retval = alt;
- break;
- }
- }
- }
-
- /* Return the index of the base alt, or -1 if none found. */
- return retval;
+lib_find_starting_alt(sc_gameref_t game, sc_int room) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int alt_count, alt, retval;
+
+ /* Get count of room alternates. */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Alts";
+ alt_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ /* Search backwards for a method-0 or method-1 overriding description. */
+ retval = -1;
+ for (alt = alt_count - 1; alt >= 0; alt--) {
+ sc_int method;
+
+ vt_key[3].integer = alt;
+ vt_key[4].string = "DisplayRoom";
+ method = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ if (!(method == 0 || method == 1))
+ continue;
+
+ if (lib_use_room_alt(game, room, alt)) {
+ const sc_char *m1;
+
+ vt_key[3].integer = alt;
+ vt_key[4].string = "M1";
+ m1 = prop_get_string(bundle, "S<-sisis", vt_key);
+ if (!sc_strempty(m1)) {
+ retval = alt;
+ break;
+ }
+ } else {
+ const sc_char *m2;
+
+ vt_key[3].integer = alt;
+ vt_key[4].string = "M2";
+ m2 = prop_get_string(bundle, "S<-sisis", vt_key);
+ if (!sc_strempty(m2)) {
+ retval = alt;
+ break;
+ }
+ }
+ }
+
+ /* Return the index of the base alt, or -1 if none found. */
+ return retval;
}
@@ -323,78 +306,71 @@ lib_find_starting_alt (sc_gameref_t game, sc_int room)
* Get/print out the name for a given room.
*/
const sc_char *
-lib_get_room_name (sc_gameref_t game, sc_int room)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int alt_count, alt, start;
- const sc_char *name;
-
- /* Get the basic room name, and the count of room alternates. */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- vt_key[2].string = "Alts";
- alt_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- /* Get our starting point in the alts list. */
- start = lib_find_starting_alt (game, room);
-
- /*
- * Run forwards through all alts lower than our starting point, or all alts
- * if no starting point found.
- */
- for (alt = (start != -1) ? start : 0; alt < alt_count; alt++)
- {
- /* Ignore all non-method-2 alts except for the starter. */
- if (alt != start)
- {
- sc_int method;
-
- vt_key[3].integer = alt;
- vt_key[4].string = "DisplayRoom";
- method = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- if (method != 2)
- continue;
- }
-
- /* If this alt offers a name change, note it and continue. */
- if (lib_use_room_alt (game, room, alt))
- {
- const sc_char *changed;
-
- vt_key[3].integer = alt;
- vt_key[4].string = "Changed";
- changed = prop_get_string (bundle, "S<-sisis", vt_key);
- if (!sc_strempty (changed))
- name = changed;
- }
- }
-
- /* Return the final selected name. */
- return name;
+lib_get_room_name(sc_gameref_t game, sc_int room) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int alt_count, alt, start;
+ const sc_char *name;
+
+ /* Get the basic room name, and the count of room alternates. */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ vt_key[2].string = "Alts";
+ alt_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ /* Get our starting point in the alts list. */
+ start = lib_find_starting_alt(game, room);
+
+ /*
+ * Run forwards through all alts lower than our starting point, or all alts
+ * if no starting point found.
+ */
+ for (alt = (start != -1) ? start : 0; alt < alt_count; alt++) {
+ /* Ignore all non-method-2 alts except for the starter. */
+ if (alt != start) {
+ sc_int method;
+
+ vt_key[3].integer = alt;
+ vt_key[4].string = "DisplayRoom";
+ method = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ if (method != 2)
+ continue;
+ }
+
+ /* If this alt offers a name change, note it and continue. */
+ if (lib_use_room_alt(game, room, alt)) {
+ const sc_char *changed;
+
+ vt_key[3].integer = alt;
+ vt_key[4].string = "Changed";
+ changed = prop_get_string(bundle, "S<-sisis", vt_key);
+ if (!sc_strempty(changed))
+ name = changed;
+ }
+ }
+
+ /* Return the final selected name. */
+ return name;
}
void
-lib_print_room_name (sc_gameref_t game, sc_int room)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_char *name;
+lib_print_room_name(sc_gameref_t game, sc_int room) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_char *name;
- /* Print the room name, possibly in bold. */
- name = lib_get_room_name (game, room);
- if (game->bold_room_names)
- {
- pf_buffer_tag (filter, SC_TAG_BOLD);
- pf_buffer_string (filter, name);
- pf_buffer_tag (filter, SC_TAG_ENDBOLD);
- }
- else
- pf_buffer_string (filter, name);
- pf_buffer_character (filter, '\n');
+ /* Print the room name, possibly in bold. */
+ name = lib_get_room_name(game, room);
+ if (game->bold_room_names) {
+ pf_buffer_tag(filter, SC_TAG_BOLD);
+ pf_buffer_string(filter, name);
+ pf_buffer_tag(filter, SC_TAG_ENDBOLD);
+ } else
+ pf_buffer_string(filter, name);
+ pf_buffer_character(filter, '\n');
}
@@ -407,110 +383,96 @@ lib_print_room_name (sc_gameref_t game, sc_int room)
* prefix.
*/
static void
-lib_print_object_np (sc_gameref_t game, sc_int object)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *prefix, *normalized, *name;
-
- /* Get the object's prefix. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
-
- /*
- * Normalize by skipping any leading "a"/"an"/"some", replacing it instead
- * with "the", and skipping any odd "the" already present. If no prefix at
- * all, add a "the " anyway.
- *
- * TODO This is empirical, based on observed Adrift Runner behavior, and
- * what it's _really_ supposed to do is a mystery. This routine has been a
- * real PITA.
- */
- normalized = prefix;
- if (sc_compare_word (prefix, "a", 1))
- {
- normalized = prefix + 1;
- pf_buffer_string (filter, "the");
- }
- else if (sc_compare_word (prefix, "an", 2))
- {
- normalized = prefix + 2;
- pf_buffer_string (filter, "the");
- }
- else if (sc_compare_word (prefix, "the", 3))
- {
- normalized = prefix + 3;
- pf_buffer_string (filter, "the");
- }
- else if (sc_compare_word (prefix, "some", 4))
- {
- normalized = prefix + 4;
- pf_buffer_string (filter, "the");
- }
- else if (sc_strempty (prefix))
- pf_buffer_string (filter, "the ");
-
- /*
- * If the remaining normalized prefix isn't empty, print it, and a space.
- * If it is, then consider adding a space to any "the" printed above, except
- * for the one done for empty prefixes, that is.
- */
- if (!sc_strempty (normalized))
- {
- pf_buffer_string (filter, normalized);
- pf_buffer_character (filter, ' ');
- }
- else if (normalized > prefix)
- pf_buffer_character (filter, ' ');
-
- /*
- * Print the object's name; here we also look for a leading article and
- * strip if found -- some games may avoid prefix and do this instead.
- */
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- if (sc_compare_word (name, "a", 1))
- name += 1;
- else if (sc_compare_word (name, "an", 2))
- name += 2;
- else if (sc_compare_word (name, "the", 3))
- name += 3;
- else if (sc_compare_word (name, "some", 4))
- name += 4;
- pf_buffer_string (filter, name);
+lib_print_object_np(sc_gameref_t game, sc_int object) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *prefix, *normalized, *name;
+
+ /* Get the object's prefix. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+
+ /*
+ * Normalize by skipping any leading "a"/"an"/"some", replacing it instead
+ * with "the", and skipping any odd "the" already present. If no prefix at
+ * all, add a "the " anyway.
+ *
+ * TODO This is empirical, based on observed Adrift Runner behavior, and
+ * what it's _really_ supposed to do is a mystery. This routine has been a
+ * real PITA.
+ */
+ normalized = prefix;
+ if (sc_compare_word(prefix, "a", 1)) {
+ normalized = prefix + 1;
+ pf_buffer_string(filter, "the");
+ } else if (sc_compare_word(prefix, "an", 2)) {
+ normalized = prefix + 2;
+ pf_buffer_string(filter, "the");
+ } else if (sc_compare_word(prefix, "the", 3)) {
+ normalized = prefix + 3;
+ pf_buffer_string(filter, "the");
+ } else if (sc_compare_word(prefix, "some", 4)) {
+ normalized = prefix + 4;
+ pf_buffer_string(filter, "the");
+ } else if (sc_strempty(prefix))
+ pf_buffer_string(filter, "the ");
+
+ /*
+ * If the remaining normalized prefix isn't empty, print it, and a space.
+ * If it is, then consider adding a space to any "the" printed above, except
+ * for the one done for empty prefixes, that is.
+ */
+ if (!sc_strempty(normalized)) {
+ pf_buffer_string(filter, normalized);
+ pf_buffer_character(filter, ' ');
+ } else if (normalized > prefix)
+ pf_buffer_character(filter, ' ');
+
+ /*
+ * Print the object's name; here we also look for a leading article and
+ * strip if found -- some games may avoid prefix and do this instead.
+ */
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ if (sc_compare_word(name, "a", 1))
+ name += 1;
+ else if (sc_compare_word(name, "an", 2))
+ name += 2;
+ else if (sc_compare_word(name, "the", 3))
+ name += 3;
+ else if (sc_compare_word(name, "some", 4))
+ name += 4;
+ pf_buffer_string(filter, name);
}
static void
-lib_print_object (sc_gameref_t game, sc_int object)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *prefix, *name;
-
- /*
- * Get the object's prefix, and print if not empty, otherwise default to an
- * "a " prefix, as that's what Adrift seems to do.
- */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (prefix))
- {
- pf_buffer_string (filter, prefix);
- pf_buffer_character (filter, ' ');
- }
- else
- pf_buffer_string (filter, "a ");
-
- /* Print object name. */
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- pf_buffer_string (filter, name);
+lib_print_object(sc_gameref_t game, sc_int object) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *prefix, *name;
+
+ /*
+ * Get the object's prefix, and print if not empty, otherwise default to an
+ * "a " prefix, as that's what Adrift seems to do.
+ */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(prefix)) {
+ pf_buffer_string(filter, prefix);
+ pf_buffer_character(filter, ' ');
+ } else
+ pf_buffer_string(filter, "a ");
+
+ /* Print object name. */
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ pf_buffer_string(filter, name);
}
@@ -522,44 +484,41 @@ lib_print_object (sc_gameref_t game, sc_int object)
* any prefix.
*/
static void
-lib_print_npc_np (sc_gameref_t game, sc_int npc)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *name;
+lib_print_npc_np(sc_gameref_t game, sc_int npc) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *name;
- /* Get the NPC's short description, and print it. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
+ /* Get the NPC's short description, and print it. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
- pf_buffer_string (filter, name);
+ pf_buffer_string(filter, name);
}
#if 0
static void
-lib_print_npc (sc_gameref_t game, sc_int npc)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *prefix;
-
- /* Get the NPC's prefix. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
-
- /* If the prefix isn't empty, print it, then print NPC name. */
- if (!sc_strempty (prefix))
- {
- pf_buffer_string (filter, prefix);
- pf_buffer_character (filter, ' ');
- }
- lib_print_npc_np (game, npc);
+lib_print_npc(sc_gameref_t game, sc_int npc) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *prefix;
+
+ /* Get the NPC's prefix. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+
+ /* If the prefix isn't empty, print it, then print NPC name. */
+ if (!sc_strempty(prefix)) {
+ pf_buffer_string(filter, prefix);
+ pf_buffer_character(filter, ' ');
+ }
+ lib_print_npc_np(game, npc);
}
#endif
@@ -572,46 +531,43 @@ lib_print_npc (sc_gameref_t game, sc_int npc)
* response string for a game, based on perspective or object plurality.
*/
static const sc_char *
-lib_select_response (sc_gameref_t game,
- const sc_char *second_person,
- const sc_char *first_person,
- const sc_char *third_person)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_int perspective;
- const sc_char *response;
-
- /* Return the response appropriate for Perspective. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "Perspective";
- perspective = prop_get_integer (bundle, "I<-ss", vt_key);
- switch (perspective)
- {
- case LIB_FIRST_PERSON:
- response = first_person;
- break;
- case LIB_SECOND_PERSON:
- response = second_person;
- break;
- case LIB_THIRD_PERSON:
- response = third_person;
- break;
- default:
- sc_error ("lib_select_response:"
- " unknown perspective, %ld\n", perspective);
- response = second_person;
- break;
- }
-
- return response;
+lib_select_response(sc_gameref_t game,
+ const sc_char *second_person,
+ const sc_char *first_person,
+ const sc_char *third_person) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_int perspective;
+ const sc_char *response;
+
+ /* Return the response appropriate for Perspective. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Perspective";
+ perspective = prop_get_integer(bundle, "I<-ss", vt_key);
+ switch (perspective) {
+ case LIB_FIRST_PERSON:
+ response = first_person;
+ break;
+ case LIB_SECOND_PERSON:
+ response = second_person;
+ break;
+ case LIB_THIRD_PERSON:
+ response = third_person;
+ break;
+ default:
+ sc_error("lib_select_response:"
+ " unknown perspective, %ld\n", perspective);
+ response = second_person;
+ break;
+ }
+
+ return response;
}
static const sc_char *
-lib_select_plurality (sc_gameref_t game, sc_int object,
- const sc_char *singular, const sc_char *plural)
-{
- return obj_appears_plural (game, object) ? plural : singular;
+lib_select_plurality(sc_gameref_t game, sc_int object,
+ const sc_char *singular, const sc_char *plural) {
+ return obj_appears_plural(game, object) ? plural : singular;
}
@@ -623,39 +579,36 @@ lib_select_plurality (sc_gameref_t game, sc_int object,
* return the standard inroom text.
*/
static const sc_char *
-lib_get_npc_inroom_text (sc_gameref_t game, sc_int npc)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int walk_count, walk;
- const sc_char *inroomtext;
-
- /* Get the count of NPC walks. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Walks";
- walk_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- /* Check for any active walk with a description, return if found. */
- for (walk = walk_count - 1; walk >= 0; walk--)
- {
- if (gs_npc_walkstep (game, npc, walk) > 0)
- {
- const sc_char *changeddesc;
-
- /* Get and check any walk active description. */
- vt_key[3].integer = walk;
- vt_key[4].string = "ChangedDesc";
- changeddesc = prop_get_string (bundle, "S<-sisis", vt_key);
- if (!sc_strempty (changeddesc))
- return changeddesc;
- }
- }
-
- /* Return the standard inroom text. */
- vt_key[2].string = "InRoomText";
- inroomtext = prop_get_string (bundle, "S<-sis", vt_key);
- return inroomtext;
+lib_get_npc_inroom_text(sc_gameref_t game, sc_int npc) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int walk_count, walk;
+ const sc_char *inroomtext;
+
+ /* Get the count of NPC walks. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Walks";
+ walk_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ /* Check for any active walk with a description, return if found. */
+ for (walk = walk_count - 1; walk >= 0; walk--) {
+ if (gs_npc_walkstep(game, npc, walk) > 0) {
+ const sc_char *changeddesc;
+
+ /* Get and check any walk active description. */
+ vt_key[3].integer = walk;
+ vt_key[4].string = "ChangedDesc";
+ changeddesc = prop_get_string(bundle, "S<-sisis", vt_key);
+ if (!sc_strempty(changeddesc))
+ return changeddesc;
+ }
+ }
+
+ /* Return the standard inroom text. */
+ vt_key[2].string = "InRoomText";
+ inroomtext = prop_get_string(bundle, "S<-sis", vt_key);
+ return inroomtext;
}
@@ -665,177 +618,155 @@ lib_get_npc_inroom_text (sc_gameref_t game, sc_int npc)
* Print a list of the contents of a room.
*/
static void
-lib_print_room_contents (sc_gameref_t game, sc_int 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[4];
- sc_int object, npc, count, trail;
-
- /* List all objects that show their initial description. */
- count = 0;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (obj_directly_in_room (game, object, room)
- && obj_shows_initial_description (game, object))
- {
- const sc_char *inroomdesc;
-
- /* Find and print in room description. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "InRoomDesc";
- inroomdesc = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (inroomdesc))
- {
- if (count == 0)
- pf_buffer_character (filter, '\n');
- else
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter, inroomdesc);
- count++;
- }
- }
- }
- if (count > 0)
- pf_buffer_character (filter, '\n');
-
- /*
- * List dynamic objects directly located in the room, and not already listed
- * above since they lack, or suppress, an in room description.
- *
- * If an object sets ListFlag, then if dynamic it's suppressed from the list
- * where it would normally be included, but if static it's included where it
- * would normally be excluded.
- */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (obj_directly_in_room (game, object, room))
- {
- const sc_char *inroomdesc;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "InRoomDesc";
- inroomdesc = prop_get_string (bundle, "S<-sis", vt_key);
-
- if (!obj_shows_initial_description (game, object)
- || sc_strempty (inroomdesc))
- {
- sc_bool listflag;
-
- vt_key[2].string = "ListFlag";
- listflag = prop_get_boolean (bundle, "B<-sis", vt_key);
-
- if (listflag == obj_is_static (game, object))
- {
- if (count > 0)
- {
- if (count == 1)
- pf_buffer_string (filter,
- lib_select_plurality (game, trail,
- "\nAlso here is ",
- "\nAlso here are "));
- else
- pf_buffer_string (filter, ", ");
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- }
- }
- if (count >= 1)
- {
- if (count == 1)
- pf_buffer_string (filter,
- lib_select_plurality (game, trail,
- "\nAlso here is ",
- "\nAlso here are "));
- else
- pf_buffer_string (filter, " and ");
- lib_print_object (game, trail);
- pf_buffer_string (filter, ".\n");
- }
-
- /* List NPCs directly in the room that have an in room description. */
- count = 0;
- for (npc = 0; npc < gs_npc_count (game); npc++)
- {
- if (npc_in_room (game, npc, room))
- {
- const sc_char *description;
-
- /* Print any non='#' in-room description. */
- description = lib_get_npc_inroom_text (game, npc);
- if (!sc_strempty (description) && sc_strcasecmp (description, "#"))
- {
- if (count == 0)
- pf_buffer_character (filter, '\n');
- else
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter, description);
- count++;
- }
- }
- }
- if (count > 0)
- pf_buffer_character (filter, '\n');
-
- /*
- * List NPCs in the room that don't have an in room description and that
- * request a default "...is here" with "#".
- *
- * TODO Is this right?
- */
- count = 0;
- trail = -1;
- for (npc = 0; npc < gs_npc_count (game); npc++)
- {
- if (npc_in_room (game, npc, room))
- {
- const sc_char *description;
-
- /* Print name for descriptions marked '#'. */
- description = lib_get_npc_inroom_text (game, npc);
- if (!sc_strempty (description) && !sc_strcasecmp (description, "#"))
- {
- if (count > 0)
- {
- if (count > 1)
- pf_buffer_string (filter, ", ");
- else
- {
- pf_buffer_character (filter, '\n');
- pf_new_sentence (filter);
- }
- lib_print_npc_np (game, trail);
- }
- trail = npc;
- count++;
- }
- }
- }
- if (count >= 1)
- {
- if (count == 1)
- {
- pf_buffer_character (filter, '\n');
- pf_new_sentence (filter);
- lib_print_npc_np (game, trail);
- pf_buffer_string (filter, " is here");
- }
- else
- {
- pf_buffer_string (filter, " and ");
- lib_print_npc_np (game, trail);
- pf_buffer_string (filter, " are here");
- }
- pf_buffer_string (filter, ".\n");
- }
+lib_print_room_contents(sc_gameref_t game, sc_int 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[4];
+ sc_int object, npc, count, trail;
+
+ /* List all objects that show their initial description. */
+ count = 0;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (obj_directly_in_room(game, object, room)
+ && obj_shows_initial_description(game, object)) {
+ const sc_char *inroomdesc;
+
+ /* Find and print in room description. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "InRoomDesc";
+ inroomdesc = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(inroomdesc)) {
+ if (count == 0)
+ pf_buffer_character(filter, '\n');
+ else
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter, inroomdesc);
+ count++;
+ }
+ }
+ }
+ if (count > 0)
+ pf_buffer_character(filter, '\n');
+
+ /*
+ * List dynamic objects directly located in the room, and not already listed
+ * above since they lack, or suppress, an in room description.
+ *
+ * If an object sets ListFlag, then if dynamic it's suppressed from the list
+ * where it would normally be included, but if static it's included where it
+ * would normally be excluded.
+ */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (obj_directly_in_room(game, object, room)) {
+ const sc_char *inroomdesc;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "InRoomDesc";
+ inroomdesc = prop_get_string(bundle, "S<-sis", vt_key);
+
+ if (!obj_shows_initial_description(game, object)
+ || sc_strempty(inroomdesc)) {
+ sc_bool listflag;
+
+ vt_key[2].string = "ListFlag";
+ listflag = prop_get_boolean(bundle, "B<-sis", vt_key);
+
+ if (listflag == obj_is_static(game, object)) {
+ if (count > 0) {
+ if (count == 1)
+ pf_buffer_string(filter,
+ lib_select_plurality(game, trail,
+ "\nAlso here is ",
+ "\nAlso here are "));
+ else
+ pf_buffer_string(filter, ", ");
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ }
+ }
+ if (count >= 1) {
+ if (count == 1)
+ pf_buffer_string(filter,
+ lib_select_plurality(game, trail,
+ "\nAlso here is ",
+ "\nAlso here are "));
+ else
+ pf_buffer_string(filter, " and ");
+ lib_print_object(game, trail);
+ pf_buffer_string(filter, ".\n");
+ }
+
+ /* List NPCs directly in the room that have an in room description. */
+ count = 0;
+ for (npc = 0; npc < gs_npc_count(game); npc++) {
+ if (npc_in_room(game, npc, room)) {
+ const sc_char *description;
+
+ /* Print any non='#' in-room description. */
+ description = lib_get_npc_inroom_text(game, npc);
+ if (!sc_strempty(description) && sc_strcasecmp(description, "#")) {
+ if (count == 0)
+ pf_buffer_character(filter, '\n');
+ else
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter, description);
+ count++;
+ }
+ }
+ }
+ if (count > 0)
+ pf_buffer_character(filter, '\n');
+
+ /*
+ * List NPCs in the room that don't have an in room description and that
+ * request a default "...is here" with "#".
+ *
+ * TODO Is this right?
+ */
+ count = 0;
+ trail = -1;
+ for (npc = 0; npc < gs_npc_count(game); npc++) {
+ if (npc_in_room(game, npc, room)) {
+ const sc_char *description;
+
+ /* Print name for descriptions marked '#'. */
+ description = lib_get_npc_inroom_text(game, npc);
+ if (!sc_strempty(description) && !sc_strcasecmp(description, "#")) {
+ if (count > 0) {
+ if (count > 1)
+ pf_buffer_string(filter, ", ");
+ else {
+ pf_buffer_character(filter, '\n');
+ pf_new_sentence(filter);
+ }
+ lib_print_npc_np(game, trail);
+ }
+ trail = npc;
+ count++;
+ }
+ }
+ }
+ if (count >= 1) {
+ if (count == 1) {
+ pf_buffer_character(filter, '\n');
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, trail);
+ pf_buffer_string(filter, " is here");
+ } else {
+ pf_buffer_string(filter, " and ");
+ lib_print_npc_np(game, trail);
+ pf_buffer_string(filter, " are here");
+ }
+ pf_buffer_string(filter, ".\n");
+ }
}
@@ -845,152 +776,139 @@ lib_print_room_contents (sc_gameref_t game, sc_int room)
* Print out the long description for a given room.
*/
void
-lib_print_room_description (sc_gameref_t game, sc_int 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];
- sc_bool showobjects, is_described, is_suppressed;
- sc_int alt_count, alt, start, event;
-
- /* Get count of room alternates. */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Alts";
- alt_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- /* Start with no description, and get our starting point in the alts list. */
- is_described = FALSE;
- start = lib_find_starting_alt (game, room);
-
- /* Print the standard description unless a start alt indicates not. */
- if (start == -1)
- is_suppressed = FALSE;
- else
- {
- sc_int method;
-
- vt_key[3].integer = start;
- vt_key[4].string = "DisplayRoom";
- method = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- is_suppressed = (method == 0);
- }
- if (!is_suppressed)
- {
- const sc_char *description;
-
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Long";
- description = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (description))
- {
- pf_buffer_string (filter, description);
- is_described = TRUE;
- }
-
- vt_key[2].string = "Res";
- res_handle_resource (game, "sis", vt_key);
- }
-
- /* Ensure that we're back to handling room alts. */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Alts";
-
- /*
- * Run forwards through all alts lower than our starting point, or all alts
- * if no starting point overrider found.
- */
- showobjects = TRUE;
- for (alt = (start != -1) ? start : 0; alt < alt_count; alt++)
- {
- /* Ignore all non-method-2 alts except for the starter. */
- if (alt != start)
- {
- sc_int method;
-
- vt_key[3].integer = alt;
- vt_key[4].string = "DisplayRoom";
- method = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- if (method != 2)
- continue;
- }
-
- if (lib_use_room_alt (game, room, alt))
- {
- const sc_char *m1;
- sc_int hideobjects;
-
- vt_key[3].integer = alt;
- vt_key[4].string = "M1";
- m1 = prop_get_string (bundle, "S<-sisis", vt_key);
- if (!sc_strempty (m1))
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter, m1);
- is_described = TRUE;
- }
-
- vt_key[4].string = "Res1";
- res_handle_resource (game, "sisis", vt_key);
-
- vt_key[4].string = "HideObjects";
- hideobjects = prop_get_integer (bundle, "I<-sisis", vt_key);
- if (hideobjects == 1)
- showobjects = FALSE;
- }
- else
- {
- const sc_char *m2;
-
- vt_key[3].integer = alt;
- vt_key[4].string = "M2";
- m2 = prop_get_string (bundle, "S<-sisis", vt_key);
- if (!sc_strempty (m2))
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter, m2);
- is_described = TRUE;
- }
-
- vt_key[4].string = "Res2";
- res_handle_resource (game, "sisis", vt_key);
- }
- }
-
- /* Print out any relevant event look text. */
- for (event = 0; event < gs_event_count (game); event++)
- {
- if (gs_event_state (game, event) == ES_RUNNING
- && evt_can_see_event (game, event))
- {
- const sc_char *looktext;
-
- vt_key[0].string = "Events";
- vt_key[1].integer = event;
- vt_key[2].string = "LookText";
- looktext = prop_get_string (bundle, "S<-sis", vt_key);
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter, looktext);
- is_described = TRUE;
-
- vt_key[2].string = "Res";
- vt_key[3].integer = 1;
- res_handle_resource (game, "sisi", vt_key);
- }
- }
- if (is_described)
- pf_buffer_character (filter, '\n');
-
- /* Finally, print room contents. */
- if (showobjects)
- lib_print_room_contents (game, room);
+lib_print_room_description(sc_gameref_t game, sc_int 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];
+ sc_bool showobjects, is_described, is_suppressed;
+ sc_int alt_count, alt, start, event;
+
+ /* Get count of room alternates. */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Alts";
+ alt_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ /* Start with no description, and get our starting point in the alts list. */
+ is_described = FALSE;
+ start = lib_find_starting_alt(game, room);
+
+ /* Print the standard description unless a start alt indicates not. */
+ if (start == -1)
+ is_suppressed = FALSE;
+ else {
+ sc_int method;
+
+ vt_key[3].integer = start;
+ vt_key[4].string = "DisplayRoom";
+ method = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ is_suppressed = (method == 0);
+ }
+ if (!is_suppressed) {
+ const sc_char *description;
+
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Long";
+ description = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(description)) {
+ pf_buffer_string(filter, description);
+ is_described = TRUE;
+ }
+
+ vt_key[2].string = "Res";
+ res_handle_resource(game, "sis", vt_key);
+ }
+
+ /* Ensure that we're back to handling room alts. */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Alts";
+
+ /*
+ * Run forwards through all alts lower than our starting point, or all alts
+ * if no starting point overrider found.
+ */
+ showobjects = TRUE;
+ for (alt = (start != -1) ? start : 0; alt < alt_count; alt++) {
+ /* Ignore all non-method-2 alts except for the starter. */
+ if (alt != start) {
+ sc_int method;
+
+ vt_key[3].integer = alt;
+ vt_key[4].string = "DisplayRoom";
+ method = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ if (method != 2)
+ continue;
+ }
+
+ if (lib_use_room_alt(game, room, alt)) {
+ const sc_char *m1;
+ sc_int hideobjects;
+
+ vt_key[3].integer = alt;
+ vt_key[4].string = "M1";
+ m1 = prop_get_string(bundle, "S<-sisis", vt_key);
+ if (!sc_strempty(m1)) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter, m1);
+ is_described = TRUE;
+ }
+
+ vt_key[4].string = "Res1";
+ res_handle_resource(game, "sisis", vt_key);
+
+ vt_key[4].string = "HideObjects";
+ hideobjects = prop_get_integer(bundle, "I<-sisis", vt_key);
+ if (hideobjects == 1)
+ showobjects = FALSE;
+ } else {
+ const sc_char *m2;
+
+ vt_key[3].integer = alt;
+ vt_key[4].string = "M2";
+ m2 = prop_get_string(bundle, "S<-sisis", vt_key);
+ if (!sc_strempty(m2)) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter, m2);
+ is_described = TRUE;
+ }
+
+ vt_key[4].string = "Res2";
+ res_handle_resource(game, "sisis", vt_key);
+ }
+ }
+
+ /* Print out any relevant event look text. */
+ for (event = 0; event < gs_event_count(game); event++) {
+ if (gs_event_state(game, event) == ES_RUNNING
+ && evt_can_see_event(game, event)) {
+ const sc_char *looktext;
+
+ vt_key[0].string = "Events";
+ vt_key[1].integer = event;
+ vt_key[2].string = "LookText";
+ looktext = prop_get_string(bundle, "S<-sis", vt_key);
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter, looktext);
+ is_described = TRUE;
+
+ vt_key[2].string = "Res";
+ vt_key[3].integer = 1;
+ res_handle_resource(game, "sisi", vt_key);
+ }
+ }
+ if (is_described)
+ pf_buffer_character(filter, '\n');
+
+ /* Finally, print room contents. */
+ if (showobjects)
+ lib_print_room_contents(game, room);
}
@@ -1000,134 +918,116 @@ lib_print_room_description (sc_gameref_t game, sc_int room)
* Return TRUE if the player can move in the given direction.
*/
static sc_bool
-lib_can_go (sc_gameref_t game, sc_int room, sc_int direction)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int restriction;
- sc_bool is_restricted = FALSE;
-
- /* Set up invariant parts of key. */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = room;
- vt_key[2].string = "Exits";
- vt_key[3].integer = direction;
-
- /* Check for any movement restrictions. */
- vt_key[4].string = "Var1";
- restriction = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if (restriction >= 0)
- {
- sc_int type;
-
- if (lib_trace)
- sc_trace ("Library: hit move restriction\n");
-
- /* Get restriction type. */
- vt_key[4].string = "Var3";
- type = prop_get_integer (bundle, "I<-sisis", vt_key);
- switch (type)
- {
- case 0: /* Task type restriction */
- {
- sc_int check;
-
- /* Get the expected completion state. */
- vt_key[4].string = "Var2";
- check = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- if (lib_trace)
- {
- sc_trace ("Library: task %ld, check %ld\n",
- restriction, check);
- }
-
- /* Restrict if task isn't done/not done as expected. */
- if ((check != 0) == gs_task_done (game, restriction))
- is_restricted = TRUE;
- break;
- }
-
- case 1: /* Object state restriction */
- {
- sc_int object, check, openable;
-
- /* Get the target object. */
- object = obj_stateful_object (game, restriction);
-
- /* Get the expected object state. */
- vt_key[4].string = "Var2";
- check = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- if (lib_trace)
- sc_trace ("Library: object %ld, check %ld\n", object, check);
-
- /* Check openable and lockable 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)
- {
- sc_int lockable;
-
- /* See if lockable. */
- vt_key[2].string = "Key";
- lockable = prop_get_integer (bundle, "I<-sis", vt_key);
- if (lockable >= 0)
- {
- /* Lockable. */
- if (check <= 2)
- {
- if (gs_object_openness (game, object) != check + 5)
- is_restricted = TRUE;
- }
- else
- {
- if (gs_object_state (game, object) != check - 2)
- is_restricted = TRUE;
- }
- }
- else
- {
- /* Not lockable, though openable. */
- if (check <= 1)
- {
- if (gs_object_openness (game, object) != check + 5)
- is_restricted = TRUE;
- }
- else
- {
- if (gs_object_state (game, object) != check - 1)
- is_restricted = TRUE;
- }
- }
- }
- else
- {
- /* Not openable. */
- if (gs_object_state (game, object) != check + 1)
- is_restricted = TRUE;
- }
- break;
- }
- }
- }
-
- /* Return TRUE if not restricted. */
- return !is_restricted;
+lib_can_go(sc_gameref_t game, sc_int room, sc_int direction) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int restriction;
+ sc_bool is_restricted = FALSE;
+
+ /* Set up invariant parts of key. */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = room;
+ vt_key[2].string = "Exits";
+ vt_key[3].integer = direction;
+
+ /* Check for any movement restrictions. */
+ vt_key[4].string = "Var1";
+ restriction = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if (restriction >= 0) {
+ sc_int type;
+
+ if (lib_trace)
+ sc_trace("Library: hit move restriction\n");
+
+ /* Get restriction type. */
+ vt_key[4].string = "Var3";
+ type = prop_get_integer(bundle, "I<-sisis", vt_key);
+ switch (type) {
+ case 0: { /* Task type restriction */
+ sc_int check;
+
+ /* Get the expected completion state. */
+ vt_key[4].string = "Var2";
+ check = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ if (lib_trace) {
+ sc_trace("Library: task %ld, check %ld\n",
+ restriction, check);
+ }
+
+ /* Restrict if task isn't done/not done as expected. */
+ if ((check != 0) == gs_task_done(game, restriction))
+ is_restricted = TRUE;
+ break;
+ }
+
+ case 1: { /* Object state restriction */
+ sc_int object, check, openable;
+
+ /* Get the target object. */
+ object = obj_stateful_object(game, restriction);
+
+ /* Get the expected object state. */
+ vt_key[4].string = "Var2";
+ check = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ if (lib_trace)
+ sc_trace("Library: object %ld, check %ld\n", object, check);
+
+ /* Check openable and lockable 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) {
+ sc_int lockable;
+
+ /* See if lockable. */
+ vt_key[2].string = "Key";
+ lockable = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (lockable >= 0) {
+ /* Lockable. */
+ if (check <= 2) {
+ if (gs_object_openness(game, object) != check + 5)
+ is_restricted = TRUE;
+ } else {
+ if (gs_object_state(game, object) != check - 2)
+ is_restricted = TRUE;
+ }
+ } else {
+ /* Not lockable, though openable. */
+ if (check <= 1) {
+ if (gs_object_openness(game, object) != check + 5)
+ is_restricted = TRUE;
+ } else {
+ if (gs_object_state(game, object) != check - 1)
+ is_restricted = TRUE;
+ }
+ }
+ } else {
+ /* Not openable. */
+ if (gs_object_state(game, object) != check + 1)
+ is_restricted = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Return TRUE if not restricted. */
+ return !is_restricted;
}
/* List of direction names, for printing and counting exits. */
static const sc_char *const DIRNAMES_4[] = {
- "north", "east", "south", "west", "up", "down", "in", "out",
- NULL
+ "north", "east", "south", "west", "up", "down", "in", "out",
+ NULL
};
static const sc_char *const DIRNAMES_8[] = {
- "north", "east", "south", "west", "up", "down", "in", "out",
- "northeast", "southeast", "southwest", "northwest",
- NULL
+ "north", "east", "south", "west", "up", "down", "in", "out",
+ "northeast", "southeast", "southwest", "northwest",
+ NULL
};
@@ -1137,86 +1037,75 @@ static const sc_char *const DIRNAMES_8[] = {
* Print a list of exits from the player room.
*/
sc_bool
-lib_cmd_print_room_exits (sc_gameref_t game)
-{
- 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_bool eightpointcompass;
- const sc_char *const *dirnames;
- sc_int count, index_, trail;
-
- /* 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;
-
- /* Poll for an exit for each valid direction name. */
- count = 0;
- trail = -1;
- for (index_ = 0; dirnames[index_]; index_++)
- {
- sc_vartype_t vt_rvalue;
-
- vt_key[0].string = "Rooms";
- vt_key[1].integer = gs_playerroom (game);
- vt_key[2].string = "Exits";
- vt_key[3].integer = index_;
- if (prop_get (bundle, "I<-sisi", &vt_rvalue, vt_key)
- && lib_can_go (game, gs_playerroom (game), index_))
- {
- if (count > 0)
- {
- if (count == 1)
- {
- /* Vary text slightly for DispFirstRoom. */
- if (game->turns == 0)
- pf_buffer_string (filter, "There are exits ");
- else
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can move ",
- "I can move ",
- "%player% can move "));
- }
- else
- pf_buffer_string (filter, ", ");
- pf_buffer_string (filter, dirnames[trail]);
- }
- trail = index_;
- count++;
- }
- }
- if (count >= 1)
- {
- if (count == 1)
- {
- /* Vary text slightly for DispFirstRoom. */
- if (game->turns == 0)
- pf_buffer_string (filter, "There is an exit ");
- else
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can only move ",
- "I can only move ",
- "%player% can only move "));
- }
- else
- pf_buffer_string (filter, " and ");
- pf_buffer_string (filter, dirnames[trail]);
- pf_buffer_string (filter, ".\n");
- }
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't go in any direction!\n",
- "I can't go in any direction!\n",
- "%player% can't go in any direction!\n"));
- }
-
- return TRUE;
+lib_cmd_print_room_exits(sc_gameref_t game) {
+ 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_bool eightpointcompass;
+ const sc_char *const *dirnames;
+ sc_int count, index_, trail;
+
+ /* 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;
+
+ /* Poll for an exit for each valid direction name. */
+ count = 0;
+ trail = -1;
+ for (index_ = 0; dirnames[index_]; index_++) {
+ sc_vartype_t vt_rvalue;
+
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = gs_playerroom(game);
+ vt_key[2].string = "Exits";
+ vt_key[3].integer = index_;
+ if (prop_get(bundle, "I<-sisi", &vt_rvalue, vt_key)
+ && lib_can_go(game, gs_playerroom(game), index_)) {
+ if (count > 0) {
+ if (count == 1) {
+ /* Vary text slightly for DispFirstRoom. */
+ if (game->turns == 0)
+ pf_buffer_string(filter, "There are exits ");
+ else
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can move ",
+ "I can move ",
+ "%player% can move "));
+ } else
+ pf_buffer_string(filter, ", ");
+ pf_buffer_string(filter, dirnames[trail]);
+ }
+ trail = index_;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ if (count == 1) {
+ /* Vary text slightly for DispFirstRoom. */
+ if (game->turns == 0)
+ pf_buffer_string(filter, "There is an exit ");
+ else
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can only move ",
+ "I can only move ",
+ "%player% can only move "));
+ } else
+ pf_buffer_string(filter, " and ");
+ pf_buffer_string(filter, dirnames[trail]);
+ pf_buffer_string(filter, ".\n");
+ } else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't go in any direction!\n",
+ "I can't go in any direction!\n",
+ "%player% can't go in any direction!\n"));
+ }
+
+ return TRUE;
}
@@ -1227,34 +1116,31 @@ lib_cmd_print_room_exits (sc_gameref_t game)
* room has already been visited.
*/
static void
-lib_describe_player_room (sc_gameref_t game, sc_bool force_verbose)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
+lib_describe_player_room(sc_gameref_t game, sc_bool force_verbose) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
- /* Print the room name. */
- lib_print_room_name (game, gs_playerroom (game));
+ /* Print the room name. */
+ lib_print_room_name(game, gs_playerroom(game));
- /* Print other room details if applicable. */
- if (force_verbose
- || game->verbose || !gs_room_seen (game, gs_playerroom (game)))
- {
- sc_bool showexits;
+ /* Print other room details if applicable. */
+ if (force_verbose
+ || game->verbose || !gs_room_seen(game, gs_playerroom(game))) {
+ sc_bool showexits;
- /* Print room description, and objects and NPCs. */
- lib_print_room_description (game, gs_playerroom (game));
+ /* Print room description, and objects and NPCs. */
+ lib_print_room_description(game, gs_playerroom(game));
- /* Print exits if the ShowExits global requests it. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "ShowExits";
- showexits = prop_get_boolean (bundle, "B<-ss", vt_key);
- if (showexits)
- {
- pf_buffer_character (filter, '\n');
- lib_cmd_print_room_exits (game);
- }
- }
+ /* Print exits if the ShowExits global requests it. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "ShowExits";
+ showexits = prop_get_boolean(bundle, "B<-ss", vt_key);
+ if (showexits) {
+ pf_buffer_character(filter, '\n');
+ lib_cmd_print_room_exits(game);
+ }
+ }
}
@@ -1264,13 +1150,12 @@ lib_describe_player_room (sc_gameref_t game, sc_bool force_verbose)
* Command handler for "look" command.
*/
sc_bool
-lib_cmd_look (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_look(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_character (filter, '\n');
- lib_describe_player_room (game, TRUE);
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ lib_describe_player_room(game, TRUE);
+ return TRUE;
}
@@ -1280,13 +1165,12 @@ lib_cmd_look (sc_gameref_t game)
* Called on "quit". Exits from the game main loop.
*/
sc_bool
-lib_cmd_quit (sc_gameref_t game)
-{
- if (if_confirm (SC_CONF_QUIT))
- game->is_running = FALSE;
+lib_cmd_quit(sc_gameref_t game) {
+ if (if_confirm(SC_CONF_QUIT))
+ game->is_running = FALSE;
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1297,16 +1181,14 @@ lib_cmd_quit (sc_gameref_t game)
* request set.
*/
sc_bool
-lib_cmd_restart (sc_gameref_t game)
-{
- if (if_confirm (SC_CONF_RESTART))
- {
- game->is_running = FALSE;
- game->do_restart = TRUE;
- }
+lib_cmd_restart(sc_gameref_t game) {
+ if (if_confirm(SC_CONF_RESTART)) {
+ game->is_running = FALSE;
+ game->do_restart = TRUE;
+ }
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1316,46 +1198,43 @@ lib_cmd_restart (sc_gameref_t game)
* Called on "undo". Restores any undo game or memo to the main game.
*/
sc_bool
-lib_cmd_undo (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_memo_setref_t memento = gs_get_memento (game);
+lib_cmd_undo(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_memo_setref_t memento = gs_get_memento(game);
- /* If an undo buffer is available, restore it. */
- if (game->undo_available)
- {
- gs_copy (game, game->undo);
- game->undo_available = FALSE;
+ /* If an undo buffer is available, restore it. */
+ if (game->undo_available) {
+ gs_copy(game, game->undo);
+ game->undo_available = FALSE;
- lib_print_room_name (game, gs_playerroom (game));
- pf_buffer_string (filter, "[The previous turn has been undone.]\n");
+ lib_print_room_name(game, gs_playerroom(game));
+ pf_buffer_string(filter, "[The previous turn has been undone.]\n");
- /* Undo can't properly unravel layered sounds... */
- game->stop_sound = TRUE;
- }
+ /* Undo can't properly unravel layered sounds... */
+ game->stop_sound = TRUE;
+ }
- /*
- * If there is no undo buffer, try to restore one saved previously in a
- * memo. If that works, treat as for restore from file, since that's
- * effectively what it is.
- */
- else if (memo_load_game (memento, game))
- {
- lib_print_room_name (game, gs_playerroom (game));
- pf_buffer_string (filter, "[The previous turn has been undone.]\n");
+ /*
+ * If there is no undo buffer, try to restore one saved previously in a
+ * memo. If that works, treat as for restore from file, since that's
+ * effectively what it is.
+ */
+ else if (memo_load_game(memento, game)) {
+ lib_print_room_name(game, gs_playerroom(game));
+ pf_buffer_string(filter, "[The previous turn has been undone.]\n");
- game->is_running = FALSE;
- game->do_restore = TRUE;
- }
+ game->is_running = FALSE;
+ game->do_restore = TRUE;
+ }
- /* If no undo buffer and memo restore failed, there's no undo available. */
- else if (game->turns == 0)
- pf_buffer_string (filter, "You can't undo what hasn't been done.\n");
- else
- pf_buffer_string (filter, "Sorry, no more undo is available.\n");
+ /* If no undo buffer and memo restore failed, there's no undo available. */
+ else if (game->turns == 0)
+ pf_buffer_string(filter, "You can't undo what hasn't been done.\n");
+ else
+ pf_buffer_string(filter, "Sorry, no more undo is available.\n");
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1368,106 +1247,98 @@ lib_cmd_undo (sc_gameref_t game)
* than using the printfilter to avoid possible clashes with ALRs.
*/
static sc_bool
-lib_cmd_history_common (sc_gameref_t game, sc_int limit)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_memo_setref_t memento = gs_get_memento (game);
- sc_int first, count, timestamp;
-
- /*
- * The runner main loop will add an entry for the "history" command that
- * got us here, but it hasn't done so yet. To keep the history list
- * accurate for recalling commands, we add a surrogate "history" command
- * to the history here, and remove it when we've done listing. This matches
- * the c-shell, which always shows 'history' listed last.
- */
- timestamp = var_get_elapsed_seconds (vars);
- memo_save_command (memento, "[history]", timestamp, game->turns);
-
- /* Decide on the first history to display; all if limit is 0 or less. */
- if (limit > 0)
- {
- /*
- * Get a count of the history length recorded. Because of the surrogate
- * "history" above, this is always at least one. From this, choose a
- * start point for the display; all if not enough history.
- */
- count = memo_get_command_count (memento);
- first = (count > limit) ? count - limit : 0;
- }
- else
- first = 0;
-
- if_print_string ("These are your most recent game commands:\n\n");
-
- /* Display history starting at the first entry determined above. */
- memo_first_command (memento);
- for (count = 0; memo_more_commands (memento); count++)
- {
- const sc_char *command;
- sc_int sequence, turns;
-
- /* Obtain the history entry, and write if included. */
- memo_next_command (memento, &command, &sequence, &timestamp, &turns);
- if (count >= first)
- {
- sc_int hr, min, sec;
- sc_char buffer[64];
-
- /* Write the history entry sequence. */
- sprintf (buffer, "%4ld -- Time ", sequence);
- if_print_string (buffer);
-
- /* Separate the timestamp out into components. */
- hr = timestamp / SECS_PER_HOUR;
- min = (timestamp % SECS_PER_HOUR) / MINS_PER_HOUR;
- sec = timestamp % SECS_PER_MINUTE;
-
- /* Print playing time as "[HHh ][M]Mm SSs". */
- if (hr > 0)
- sprintf (buffer, "%ldh %02ldm %02lds", hr, min, sec);
- else
- sprintf (buffer, "%ldm %02lds", min, sec);
- if_print_string (buffer);
-
- /* Follow up with the turns count, and the command string itself. */
- sprintf (buffer, ", turn %ld : ", turns);
- if_print_string (buffer);
- if_print_string (command);
- if_print_character ('\n');
- }
- }
-
- /* Remove the surrogate "history"; the main loop will add the real one. */
- memo_unsave_command (memento);
-
- game->is_admin = TRUE;
- return TRUE;
-}
-
-sc_bool
-lib_cmd_history_number (sc_gameref_t game)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int limit;
-
- /* Get requested length of history list, and complain if not valid. */
- limit = var_get_ref_number (vars);
- if (limit < 1)
- {
- if_print_string ("That's not a valid history length.\n");
-
- game->is_admin = TRUE;
- return TRUE;
- }
-
- return lib_cmd_history_common (game, limit);
-}
-
-sc_bool
-lib_cmd_history (sc_gameref_t game)
-{
- return lib_cmd_history_common (game, 0);
+lib_cmd_history_common(sc_gameref_t game, sc_int limit) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_memo_setref_t memento = gs_get_memento(game);
+ sc_int first, count, timestamp;
+
+ /*
+ * The runner main loop will add an entry for the "history" command that
+ * got us here, but it hasn't done so yet. To keep the history list
+ * accurate for recalling commands, we add a surrogate "history" command
+ * to the history here, and remove it when we've done listing. This matches
+ * the c-shell, which always shows 'history' listed last.
+ */
+ timestamp = var_get_elapsed_seconds(vars);
+ memo_save_command(memento, "[history]", timestamp, game->turns);
+
+ /* Decide on the first history to display; all if limit is 0 or less. */
+ if (limit > 0) {
+ /*
+ * Get a count of the history length recorded. Because of the surrogate
+ * "history" above, this is always at least one. From this, choose a
+ * start point for the display; all if not enough history.
+ */
+ count = memo_get_command_count(memento);
+ first = (count > limit) ? count - limit : 0;
+ } else
+ first = 0;
+
+ if_print_string("These are your most recent game commands:\n\n");
+
+ /* Display history starting at the first entry determined above. */
+ memo_first_command(memento);
+ for (count = 0; memo_more_commands(memento); count++) {
+ const sc_char *command;
+ sc_int sequence, turns;
+
+ /* Obtain the history entry, and write if included. */
+ memo_next_command(memento, &command, &sequence, &timestamp, &turns);
+ if (count >= first) {
+ sc_int hr, min, sec;
+ sc_char buffer[64];
+
+ /* Write the history entry sequence. */
+ sprintf(buffer, "%4ld -- Time ", sequence);
+ if_print_string(buffer);
+
+ /* Separate the timestamp out into components. */
+ hr = timestamp / SECS_PER_HOUR;
+ min = (timestamp % SECS_PER_HOUR) / MINS_PER_HOUR;
+ sec = timestamp % SECS_PER_MINUTE;
+
+ /* Print playing time as "[HHh ][M]Mm SSs". */
+ if (hr > 0)
+ sprintf(buffer, "%ldh %02ldm %02lds", hr, min, sec);
+ else
+ sprintf(buffer, "%ldm %02lds", min, sec);
+ if_print_string(buffer);
+
+ /* Follow up with the turns count, and the command string itself. */
+ sprintf(buffer, ", turn %ld : ", turns);
+ if_print_string(buffer);
+ if_print_string(command);
+ if_print_character('\n');
+ }
+ }
+
+ /* Remove the surrogate "history"; the main loop will add the real one. */
+ memo_unsave_command(memento);
+
+ game->is_admin = TRUE;
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_history_number(sc_gameref_t game) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int limit;
+
+ /* Get requested length of history list, and complain if not valid. */
+ limit = var_get_ref_number(vars);
+ if (limit < 1) {
+ if_print_string("That's not a valid history length.\n");
+
+ game->is_admin = TRUE;
+ return TRUE;
+ }
+
+ return lib_cmd_history_common(game, limit);
+}
+
+sc_bool
+lib_cmd_history(sc_gameref_t game) {
+ return lib_cmd_history_common(game, 0);
}
@@ -1483,167 +1354,150 @@ lib_cmd_history (sc_gameref_t game)
* to re-run.
*/
sc_bool
-lib_cmd_again (sc_gameref_t game)
-{
- game->do_again = TRUE;
- game->redo_sequence = 0;
-
- game->is_admin = TRUE;
- return TRUE;
-}
-
-sc_bool
-lib_cmd_redo_number (sc_gameref_t game)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_memo_setref_t memento = gs_get_memento (game);
- sc_int sequence;
-
- /*
- * Get the history sequence entry requested and validate it. The sequence
- * may be positive (absolute) or negative (relative to history end), but
- * not zero.
- */
- sequence = var_get_ref_number (vars);
- if (sequence != 0 && memo_find_command (memento, sequence))
- {
- game->do_again = TRUE;
- game->redo_sequence = sequence;
- }
- else
- {
- if_print_string ("No matching entry found in the command history.\n");
-
- /*
- * This is a failed redo, but returning FALSE will cause the game's
- * unknown command message to come up. However, returning TRUE will
- * cause the runner main loop to add this to its history, and at some
- * point a "redo 7" could cause problems (say, when it's at sequence 7,
- * where it'll cause an infinite loop). To work round this, here we'll
- * return a redo_sequence _without_ do_again, and have the runner catch
- * that as an indication not to save the command in its history. Sorry
- * for the ugliness.
- */
- game->do_again = FALSE;
- game->redo_sequence = INT_MAX;
- }
-
- game->is_admin = TRUE;
- return TRUE;
+lib_cmd_again(sc_gameref_t game) {
+ game->do_again = TRUE;
+ game->redo_sequence = 0;
+
+ game->is_admin = TRUE;
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_redo_number(sc_gameref_t game) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_memo_setref_t memento = gs_get_memento(game);
+ sc_int sequence;
+
+ /*
+ * Get the history sequence entry requested and validate it. The sequence
+ * may be positive (absolute) or negative (relative to history end), but
+ * not zero.
+ */
+ sequence = var_get_ref_number(vars);
+ if (sequence != 0 && memo_find_command(memento, sequence)) {
+ game->do_again = TRUE;
+ game->redo_sequence = sequence;
+ } else {
+ if_print_string("No matching entry found in the command history.\n");
+
+ /*
+ * This is a failed redo, but returning FALSE will cause the game's
+ * unknown command message to come up. However, returning TRUE will
+ * cause the runner main loop to add this to its history, and at some
+ * point a "redo 7" could cause problems (say, when it's at sequence 7,
+ * where it'll cause an infinite loop). To work round this, here we'll
+ * return a redo_sequence _without_ do_again, and have the runner catch
+ * that as an indication not to save the command in its history. Sorry
+ * for the ugliness.
+ */
+ game->do_again = FALSE;
+ game->redo_sequence = INT_MAX;
+ }
+
+ game->is_admin = TRUE;
+ return TRUE;
}
static sc_bool
-lib_cmd_redo_text_last_common (sc_gameref_t game, const sc_char *target)
-{
- const sc_memo_setref_t memento = gs_get_memento (game);
- sc_bool is_do_last, is_contains;
- sc_int length, matched_sequence;
-
- /* Make a special case of "!!", rerun the final command in the history. */
- is_do_last = (strcmp (target, "!") == 0);
-
- /*
- * Differentiate starts-with and contains searches, setting is_contains and
- * advancing by one if the target begins '?' (word search). Note target
- * string length.
- */
- is_contains = (target[0] == '?');
- target += is_contains ? 1 : 0;
- length = strlen (target);
-
- /* If there's no text left to search for, reject this call now. */
- if (length == 0)
- {
- if_print_string ("No matching entry found in the command history.\n");
-
- /* As with failed numeric redo above, special-case this return. */
- game->do_again = FALSE;
- game->redo_sequence = INT_MAX;
-
- game->is_admin = TRUE;
- return TRUE;
- }
-
- /*
- * Search saved commands for one that matches the target string in the
- * required way. We want to return the most recently saved match, so ideally
- * we'd search backwards, but the iterator is only forwards, so we do it the
- * hard way.
- */
- matched_sequence = 0;
- memo_first_command (memento);
- while (memo_more_commands (memento))
- {
- const sc_char *command;
- sc_int sequence, timestamp, turns;
- sc_bool is_matched;
-
- /* Get the command; only command and sequence are relevant. */
- memo_next_command (memento, &command, &sequence, &timestamp, &turns);
-
- /*
- * If this is the "!!" special case, match everything. Otherwise,
- * either search the command for the target, or match if the command
- * begins with the target.
- */
- if (is_do_last)
- is_matched = TRUE;
- else if (is_contains)
- {
- sc_int index_;
-
- /* Search this command for an occurrence of target anywhere. */
- is_matched = FALSE;
- for (index_ = strlen (command) - length; index_ >= 0; index_--)
- {
- if (sc_strncasecmp (command + index_, target, length) == 0)
- {
- is_matched = TRUE;
- break;
- }
- }
- }
- else
- is_matched = (sc_strncasecmp (command, target, length) == 0);
-
- /* If the command matched the target criteria, note it and continue. */
- if (is_matched)
- matched_sequence = sequence;
- }
-
- /* If we found a match, set the redo values accordingly. */
- if (matched_sequence > 0)
- {
- game->do_again = TRUE;
- game->redo_sequence = matched_sequence;
- }
- else
- {
- if_print_string ("No matching entry found in the command history.\n");
-
- /* As with failed numeric redo above, special-case this return. */
- game->do_again = FALSE;
- game->redo_sequence = INT_MAX;
- }
-
- game->is_admin = TRUE;
- return TRUE;
-}
-
-sc_bool
-lib_cmd_redo_text (sc_gameref_t game)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
-
- /* Call the common redo with the referenced text from %text%. */
- return lib_cmd_redo_text_last_common (game, var_get_ref_text (vars));
-}
-
-sc_bool
-lib_cmd_redo_last (sc_gameref_t game)
-{
- /* Call the common redo with, literally, "!", forming "!!" . */
- return lib_cmd_redo_text_last_common (game, "!");
+lib_cmd_redo_text_last_common(sc_gameref_t game, const sc_char *target) {
+ const sc_memo_setref_t memento = gs_get_memento(game);
+ sc_bool is_do_last, is_contains;
+ sc_int length, matched_sequence;
+
+ /* Make a special case of "!!", rerun the final command in the history. */
+ is_do_last = (strcmp(target, "!") == 0);
+
+ /*
+ * Differentiate starts-with and contains searches, setting is_contains and
+ * advancing by one if the target begins '?' (word search). Note target
+ * string length.
+ */
+ is_contains = (target[0] == '?');
+ target += is_contains ? 1 : 0;
+ length = strlen(target);
+
+ /* If there's no text left to search for, reject this call now. */
+ if (length == 0) {
+ if_print_string("No matching entry found in the command history.\n");
+
+ /* As with failed numeric redo above, special-case this return. */
+ game->do_again = FALSE;
+ game->redo_sequence = INT_MAX;
+
+ game->is_admin = TRUE;
+ return TRUE;
+ }
+
+ /*
+ * Search saved commands for one that matches the target string in the
+ * required way. We want to return the most recently saved match, so ideally
+ * we'd search backwards, but the iterator is only forwards, so we do it the
+ * hard way.
+ */
+ matched_sequence = 0;
+ memo_first_command(memento);
+ while (memo_more_commands(memento)) {
+ const sc_char *command;
+ sc_int sequence, timestamp, turns;
+ sc_bool is_matched;
+
+ /* Get the command; only command and sequence are relevant. */
+ memo_next_command(memento, &command, &sequence, &timestamp, &turns);
+
+ /*
+ * If this is the "!!" special case, match everything. Otherwise,
+ * either search the command for the target, or match if the command
+ * begins with the target.
+ */
+ if (is_do_last)
+ is_matched = TRUE;
+ else if (is_contains) {
+ sc_int index_;
+
+ /* Search this command for an occurrence of target anywhere. */
+ is_matched = FALSE;
+ for (index_ = strlen(command) - length; index_ >= 0; index_--) {
+ if (sc_strncasecmp(command + index_, target, length) == 0) {
+ is_matched = TRUE;
+ break;
+ }
+ }
+ } else
+ is_matched = (sc_strncasecmp(command, target, length) == 0);
+
+ /* If the command matched the target criteria, note it and continue. */
+ if (is_matched)
+ matched_sequence = sequence;
+ }
+
+ /* If we found a match, set the redo values accordingly. */
+ if (matched_sequence > 0) {
+ game->do_again = TRUE;
+ game->redo_sequence = matched_sequence;
+ } else {
+ if_print_string("No matching entry found in the command history.\n");
+
+ /* As with failed numeric redo above, special-case this return. */
+ game->do_again = FALSE;
+ game->redo_sequence = INT_MAX;
+ }
+
+ game->is_admin = TRUE;
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_redo_text(sc_gameref_t game) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+
+ /* Call the common redo with the referenced text from %text%. */
+ return lib_cmd_redo_text_last_common(game, var_get_ref_text(vars));
+}
+
+sc_bool
+lib_cmd_redo_last(sc_gameref_t game) {
+ /* Call the common redo with, literally, "!", forming "!!" . */
+ return lib_cmd_redo_text_last_common(game, "!");
}
@@ -1653,48 +1507,40 @@ lib_cmd_redo_last (sc_gameref_t game)
* Called on "hints". Requests the interface to display any available hints.
*/
sc_bool
-lib_cmd_hints (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int task;
- sc_bool game_has_hints;
-
- /*
- * Check for the presence of any game hints at all, no matter whether the
- * task is runnable or not.
- */
- game_has_hints = FALSE;
- for (task = 0; task < gs_task_count (game); task++)
- {
- if (task_has_hints (game, task))
- {
- game_has_hints = TRUE;
- break;
- }
- }
-
- /* If the game has hints, display any relevant ones. */
- if (game_has_hints)
- {
- if (run_hint_iterate (game, NULL))
- {
- if (if_confirm (SC_CONF_VIEW_HINTS))
- if_display_hints (game);
- }
- else
- pf_buffer_string (filter, "There are currently no hints available.\n");
- }
- else
- {
- pf_buffer_string (filter,
- "There are no hints available for this adventure.\n");
- pf_buffer_string (filter,
- "You're just going to have to work it out for"
- " yourself...\n");
- }
-
- game->is_admin = TRUE;
- return TRUE;
+lib_cmd_hints(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int task;
+ sc_bool game_has_hints;
+
+ /*
+ * Check for the presence of any game hints at all, no matter whether the
+ * task is runnable or not.
+ */
+ game_has_hints = FALSE;
+ for (task = 0; task < gs_task_count(game); task++) {
+ if (task_has_hints(game, task)) {
+ game_has_hints = TRUE;
+ break;
+ }
+ }
+
+ /* If the game has hints, display any relevant ones. */
+ if (game_has_hints) {
+ if (run_hint_iterate(game, NULL)) {
+ if (if_confirm(SC_CONF_VIEW_HINTS))
+ if_display_hints(game);
+ } else
+ pf_buffer_string(filter, "There are currently no hints available.\n");
+ } else {
+ pf_buffer_string(filter,
+ "There are no hints available for this adventure.\n");
+ pf_buffer_string(filter,
+ "You're just going to have to work it out for"
+ " yourself...\n");
+ }
+
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1705,19 +1551,17 @@ lib_cmd_hints (sc_gameref_t game)
* Convenience helpers for printing licensing and game information.
*/
static void
-lib_print_string_bold (const sc_char *string)
-{
- if_print_tag (SC_TAG_BOLD, "");
- if_print_string (string);
- if_print_tag (SC_TAG_ENDBOLD, "");
+lib_print_string_bold(const sc_char *string) {
+ if_print_tag(SC_TAG_BOLD, "");
+ if_print_string(string);
+ if_print_tag(SC_TAG_ENDBOLD, "");
}
static void
-lib_print_string_italics (const sc_char *string)
-{
- if_print_tag (SC_TAG_ITALICS, "");
- if_print_string (string);
- if_print_tag (SC_TAG_ENDITALICS, "");
+lib_print_string_italics(const sc_char *string) {
+ if_print_tag(SC_TAG_ITALICS, "");
+ if_print_string(string);
+ if_print_tag(SC_TAG_ENDITALICS, "");
}
@@ -1730,95 +1574,93 @@ lib_print_string_italics (const sc_char *string)
* to avoid possible clashes with ALRs.
*/
sc_bool
-lib_cmd_help (sc_gameref_t game)
-{
- if_print_string (
- "These are some of the typical commands used in this adventure:\n\n");
-
- if_print_string (
- " [N]orth, [E]ast, [S]outh, [W]est, [U]p, [D]own, [In], [O]ut,"
- " [L]ook, [Exits]\n E[x]amine <object>, [Get <object>],"
- " [Drop <object>], [...it], [...all]\n [Where is <object>]\n"
- " [Give <object> to <character>], [Open...], [Close...],"
- " [Ask <character> about <subject>]\n"
- " [Wear <object>], [Remove <object>], [I]nventory\n"
- " [Put <object> into <object>], [Put <object> onto <object>]\n");
-
- if_print_string ("\nUse the ");
- lib_print_string_italics ("Save");
- if_print_string (", ");
- lib_print_string_italics ("Restore");
- if_print_string (", ");
- lib_print_string_italics ("Undo");
- if_print_string (", and ");
- lib_print_string_italics ("Quit");
- if_print_string (
- " commands to save and restore games, undo a move, and leave the "
- " game. Use ");
- lib_print_string_italics ("History");
- if_print_string (" and ");
- lib_print_string_italics ("Redo");
- if_print_string (
- " to view and repeat recent game commands.\n");
-
- if_print_string ("\nThe ");
- lib_print_string_italics ("Hint");
- if_print_string (" command displays any game hints, ");
- lib_print_string_italics ("Notify");
- if_print_string (" provides score change notification, and ");
- lib_print_string_italics ("Verbose");
- if_print_string (" and ");
- lib_print_string_italics ("Brief");
- if_print_string (" control room descriptions.\n");
-
- if_print_string ("\nUse ");
- lib_print_string_italics ("License");
- if_print_string (
- " to view SCARE's licensing terms and conditions, and ");
- lib_print_string_italics ("Version");
- if_print_string (
- " to print both SCARE's and the game's version number.\n");
-
- game->is_admin = TRUE;
- return TRUE;
-}
-
-sc_bool
-lib_cmd_license (sc_gameref_t game)
-{
- lib_print_string_bold ("SCARE");
- if_print_string (" is ");
- lib_print_string_italics (
- "Copyright (C) 2003-2008 Simon Baldwin and Mark J. Tilford");
- if_print_string (".\n\n");
-
- if_print_string (
- "This program is free software; you can redistribute it and/or modify"
- " it under the terms of version 2 of the GNU General Public License"
- " as published by the Free Software Foundation.\n\n");
-
- if_print_string (
- "This program is distributed in the hope that it will be useful, but ");
- lib_print_string_bold ("WITHOUT ANY WARRANTY");
- if_print_string ("; without even the implied warranty of ");
- lib_print_string_bold ("MERCHANTABILITY");
- if_print_string (" or ");
- lib_print_string_bold ("FITNESS FOR A PARTICULAR PURPOSE");
- if_print_string (
- ". See the GNU General Public License for more details.\n\n");
-
- if_print_string (
- "You should have received a copy of the GNU General Public License"
- " along with this program; if not, write to the Free Software"
- " Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301"
- " USA\n\n");
-
- if_print_string ("Please report any bugs, omissions, or misfeatures to ");
- lib_print_string_italics ("simon_baldwin@yahoo.com");
- if_print_string (".\n");
-
- game->is_admin = TRUE;
- return TRUE;
+lib_cmd_help(sc_gameref_t game) {
+ if_print_string(
+ "These are some of the typical commands used in this adventure:\n\n");
+
+ if_print_string(
+ " [N]orth, [E]ast, [S]outh, [W]est, [U]p, [D]own, [In], [O]ut,"
+ " [L]ook, [Exits]\n E[x]amine <object>, [Get <object>],"
+ " [Drop <object>], [...it], [...all]\n [Where is <object>]\n"
+ " [Give <object> to <character>], [Open...], [Close...],"
+ " [Ask <character> about <subject>]\n"
+ " [Wear <object>], [Remove <object>], [I]nventory\n"
+ " [Put <object> into <object>], [Put <object> onto <object>]\n");
+
+ if_print_string("\nUse the ");
+ lib_print_string_italics("Save");
+ if_print_string(", ");
+ lib_print_string_italics("Restore");
+ if_print_string(", ");
+ lib_print_string_italics("Undo");
+ if_print_string(", and ");
+ lib_print_string_italics("Quit");
+ if_print_string(
+ " commands to save and restore games, undo a move, and leave the "
+ " game. Use ");
+ lib_print_string_italics("History");
+ if_print_string(" and ");
+ lib_print_string_italics("Redo");
+ if_print_string(
+ " to view and repeat recent game commands.\n");
+
+ if_print_string("\nThe ");
+ lib_print_string_italics("Hint");
+ if_print_string(" command displays any game hints, ");
+ lib_print_string_italics("Notify");
+ if_print_string(" provides score change notification, and ");
+ lib_print_string_italics("Verbose");
+ if_print_string(" and ");
+ lib_print_string_italics("Brief");
+ if_print_string(" control room descriptions.\n");
+
+ if_print_string("\nUse ");
+ lib_print_string_italics("License");
+ if_print_string(
+ " to view SCARE's licensing terms and conditions, and ");
+ lib_print_string_italics("Version");
+ if_print_string(
+ " to print both SCARE's and the game's version number.\n");
+
+ game->is_admin = TRUE;
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_license(sc_gameref_t game) {
+ lib_print_string_bold("SCARE");
+ if_print_string(" is ");
+ lib_print_string_italics(
+ "Copyright (C) 2003-2008 Simon Baldwin and Mark J. Tilford");
+ if_print_string(".\n\n");
+
+ if_print_string(
+ "This program is free software; you can redistribute it and/or modify"
+ " it under the terms of version 2 of the GNU General Public License"
+ " as published by the Free Software Foundation.\n\n");
+
+ if_print_string(
+ "This program is distributed in the hope that it will be useful, but ");
+ lib_print_string_bold("WITHOUT ANY WARRANTY");
+ if_print_string("; without even the implied warranty of ");
+ lib_print_string_bold("MERCHANTABILITY");
+ if_print_string(" or ");
+ lib_print_string_bold("FITNESS FOR A PARTICULAR PURPOSE");
+ if_print_string(
+ ". See the GNU General Public License for more details.\n\n");
+
+ if_print_string(
+ "You should have received a copy of the GNU General Public License"
+ " along with this program; if not, write to the Free Software"
+ " Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301"
+ " USA\n\n");
+
+ if_print_string("Please report any bugs, omissions, or misfeatures to ");
+ lib_print_string_italics("simon_baldwin@yahoo.com");
+ if_print_string(".\n");
+
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1830,46 +1672,44 @@ lib_cmd_license (sc_gameref_t game)
* avoid possible clashes with ALRs.
*/
sc_bool
-lib_cmd_information (sc_gameref_t game)
-{
- 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[2];
- const sc_char *gamename, *compile_date, *gameauthor;
- sc_char *filtered;
+lib_cmd_information(sc_gameref_t game) {
+ 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[2];
+ const sc_char *gamename, *compile_date, *gameauthor;
+ sc_char *filtered;
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- gamename = prop_get_string (bundle, "S<-ss", vt_key);
- filtered = pf_filter_for_info (gamename, vars);
- pf_strip_tags (filtered);
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ gamename = prop_get_string(bundle, "S<-ss", vt_key);
+ filtered = pf_filter_for_info(gamename, vars);
+ pf_strip_tags(filtered);
- if_print_string ("\"");
- if_print_string (!sc_strempty (filtered) ? filtered : "Untitled");
- if_print_string ("\"");
- sc_free (filtered);
+ if_print_string("\"");
+ if_print_string(!sc_strempty(filtered) ? filtered : "Untitled");
+ if_print_string("\"");
+ sc_free(filtered);
- vt_key[0].string = "CompileDate";
- compile_date = prop_get_string (bundle, "S<-s", vt_key);
- if (!sc_strempty (compile_date))
- {
- if_print_string (", ");
- if_print_string (compile_date);
- }
+ vt_key[0].string = "CompileDate";
+ compile_date = prop_get_string(bundle, "S<-s", vt_key);
+ if (!sc_strempty(compile_date)) {
+ if_print_string(", ");
+ if_print_string(compile_date);
+ }
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameAuthor";
- gameauthor = prop_get_string (bundle, "S<-ss", vt_key);
- filtered = pf_filter_for_info (gameauthor, vars);
- pf_strip_tags (filtered);
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameAuthor";
+ gameauthor = prop_get_string(bundle, "S<-ss", vt_key);
+ filtered = pf_filter_for_info(gameauthor, vars);
+ pf_strip_tags(filtered);
- if_print_string (", ");
- if_print_string (!sc_strempty (filtered) ? filtered : "Anonymous");
- if_print_string (".\n");
- sc_free (filtered);
+ if_print_string(", ");
+ if_print_string(!sc_strempty(filtered) ? filtered : "Anonymous");
+ if_print_string(".\n");
+ sc_free(filtered);
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1879,14 +1719,13 @@ lib_cmd_information (sc_gameref_t game)
* Clear the main game window (almost).
*/
sc_bool
-lib_cmd_clear (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_clear(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_tag (filter, SC_TAG_CLS);
- pf_buffer_string (filter, "Screen cleared.\n");
- game->is_admin = TRUE;
- return TRUE;
+ pf_buffer_tag(filter, SC_TAG_CLS);
+ pf_buffer_string(filter, "Screen cleared.\n");
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1898,47 +1737,42 @@ lib_cmd_clear (sc_gameref_t game)
* rather than using the printfilter to avoid possible clashes with ALRs.
*/
sc_bool
-lib_cmd_statusline (sc_gameref_t game)
-{
- const sc_char *name, *author, *room, *status;
- sc_int score;
+lib_cmd_statusline(sc_gameref_t game) {
+ const sc_char *name, *author, *room, *status;
+ sc_int score;
- /*
- * Retrieve the game's name and author, the description of the current
- * game room, and any formatted game status line.
- */
- run_get_attributes (game, &name, &author, NULL, NULL,
- &score, NULL, &room, &status, NULL, NULL, NULL, NULL);
+ /*
+ * Retrieve the game's name and author, the description of the current
+ * game room, and any formatted game status line.
+ */
+ run_get_attributes(game, &name, &author, NULL, NULL,
+ &score, NULL, &room, &status, NULL, NULL, NULL, NULL);
- /* If nothing is yet determined, print the game name and author. */
- if (!room || sc_strempty (room))
- {
- if_print_string (name);
- if_print_string (" | ");
- if_print_string (author);
- }
- else
- {
- /* Print the player location, and a separator. */
- if_print_string (room);
- if_print_string (" | ");
+ /* If nothing is yet determined, print the game name and author. */
+ if (!room || sc_strempty(room)) {
+ if_print_string(name);
+ if_print_string(" | ");
+ if_print_string(author);
+ } else {
+ /* Print the player location, and a separator. */
+ if_print_string(room);
+ if_print_string(" | ");
- /* If the game offers a status line, print it, otherwise the score. */
- if (status && !sc_strempty (status))
- if_print_string (status);
- else
- {
- sc_char buffer[32];
+ /* If the game offers a status line, print it, otherwise the score. */
+ if (status && !sc_strempty(status))
+ if_print_string(status);
+ else {
+ sc_char buffer[32];
- if_print_string ("Score: ");
- sprintf (buffer, "%ld", score);
- if_print_string (buffer);
- }
- }
- if_print_character ('\n');
+ if_print_string("Score: ");
+ sprintf(buffer, "%ld", score);
+ if_print_string(buffer);
+ }
+ }
+ if_print_character('\n');
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1949,32 +1783,31 @@ lib_cmd_statusline (sc_gameref_t game)
* printfilter to avoid possible clashes with ALRs.
*/
sc_bool
-lib_cmd_version (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key;
- sc_char buffer[64];
- sc_int major, minor, point;
- const sc_char *version;
+lib_cmd_version(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key;
+ sc_char buffer[64];
+ sc_int major, minor, point;
+ const sc_char *version;
- if_print_string ("SCARE version ");
- if_print_string (SCARE_VERSION SCARE_PATCH_LEVEL);
- if_print_string (" [Adrift ");
- major = SCARE_EMULATION / 1000;
- minor = (SCARE_EMULATION % 1000) / 100;
- point = SCARE_EMULATION % 100;
- sprintf (buffer, "%ld.%02ld.%02ld", major, minor, point);
- if_print_string (buffer);
- if_print_string (" compatible], ");
+ if_print_string("SCARE version ");
+ if_print_string(SCARE_VERSION SCARE_PATCH_LEVEL);
+ if_print_string(" [Adrift ");
+ major = SCARE_EMULATION / 1000;
+ minor = (SCARE_EMULATION % 1000) / 100;
+ point = SCARE_EMULATION % 100;
+ sprintf(buffer, "%ld.%02ld.%02ld", major, minor, point);
+ if_print_string(buffer);
+ if_print_string(" compatible], ");
- vt_key.string = "VersionString";
- version = prop_get_string (bundle, "S<-s", &vt_key);
- if_print_string ("Generator version ");
- if_print_string (version);
- if_print_string (".\n");
+ vt_key.string = "VersionString";
+ version = prop_get_string(bundle, "S<-s", &vt_key);
+ if_print_string("Generator version ");
+ if_print_string(version);
+ if_print_string(".\n");
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -1990,62 +1823,58 @@ lib_cmd_version (sc_gameref_t game)
* printfilter to avoid possible clashes with ALRs.
*/
sc_bool
-lib_cmd_wait (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_int waitturns;
+lib_cmd_wait(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_int waitturns;
- /* Note if wait turns is different from the game's setting. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "WaitTurns";
- waitturns = prop_get_integer (bundle, "I<-ss", vt_key);
- if (waitturns != game->waitturns)
- {
- sc_char buffer[32];
+ /* Note if wait turns is different from the game's setting. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "WaitTurns";
+ waitturns = prop_get_integer(bundle, "I<-ss", vt_key);
+ if (waitturns != game->waitturns) {
+ sc_char buffer[32];
- pf_buffer_string (filter, "(");
- sprintf (buffer, "%ld", game->waitturns);
- pf_buffer_string (filter, buffer);
- pf_buffer_string (filter,
- game->waitturns == 1 ? " turn)\n" : " turns)\n");
- }
+ pf_buffer_string(filter, "(");
+ sprintf(buffer, "%ld", game->waitturns);
+ pf_buffer_string(filter, buffer);
+ pf_buffer_string(filter,
+ game->waitturns == 1 ? " turn)\n" : " turns)\n");
+ }
- /* Reset the wait counter to the current waitturns setting. */
- game->waitcounter = game->waitturns;
+ /* Reset the wait counter to the current waitturns setting. */
+ game->waitcounter = game->waitturns;
- pf_buffer_string (filter, "Time passes...\n");
- return TRUE;
+ pf_buffer_string(filter, "Time passes...\n");
+ return TRUE;
}
sc_bool
-lib_cmd_wait_number (sc_gameref_t game)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int waitturns;
- sc_char buffer[32];
+lib_cmd_wait_number(sc_gameref_t game) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int waitturns;
+ sc_char buffer[32];
- /* Get and validate the waitturns setting. */
- waitturns = var_get_ref_number (vars);
- if (waitturns < 1 || waitturns > 20)
- {
- if_print_string ("You can only wait between 1 and 20 turns.\n");
- game->is_admin = TRUE;
- return TRUE;
- }
+ /* Get and validate the waitturns setting. */
+ waitturns = var_get_ref_number(vars);
+ if (waitturns < 1 || waitturns > 20) {
+ if_print_string("You can only wait between 1 and 20 turns.\n");
+ game->is_admin = TRUE;
+ return TRUE;
+ }
- /* Update the game setting, and confirm for the player. */
- game->waitturns = waitturns;
+ /* Update the game setting, and confirm for the player. */
+ game->waitturns = waitturns;
- if_print_string ("The game will now wait ");
- sprintf (buffer, "%ld", waitturns);
- if_print_string (buffer);
- if_print_string (waitturns == 1 ? " turn" : " turns");
- if_print_string (" for each 'wait' command you enter.\n");
+ if_print_string("The game will now wait ");
+ sprintf(buffer, "%ld", waitturns);
+ if_print_string(buffer);
+ if_print_string(waitturns == 1 ? " turn" : " turns");
+ if_print_string(" for each 'wait' command you enter.\n");
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -2057,35 +1886,33 @@ lib_cmd_wait_number (sc_gameref_t game)
* printfilter to avoid possible clashes with ALRs.
*/
sc_bool
-lib_cmd_verbose (sc_gameref_t game)
-{
- /* Set game verbose flag and return. */
- game->verbose = TRUE;
- if_print_string ("The game is now in its ");
- if_print_tag (SC_TAG_ITALICS, "");
- if_print_string ("verbose");
- if_print_tag (SC_TAG_ENDITALICS, "");
- if_print_string (" mode, which always gives long descriptions of locations"
- " (even if you've been there before).\n");
+lib_cmd_verbose(sc_gameref_t game) {
+ /* Set game verbose flag and return. */
+ game->verbose = TRUE;
+ if_print_string("The game is now in its ");
+ if_print_tag(SC_TAG_ITALICS, "");
+ if_print_string("verbose");
+ if_print_tag(SC_TAG_ENDITALICS, "");
+ if_print_string(" mode, which always gives long descriptions of locations"
+ " (even if you've been there before).\n");
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
sc_bool
-lib_cmd_brief (sc_gameref_t game)
-{
- /* Clear game verbose flag and return. */
- game->verbose = FALSE;
- if_print_string ("The game is now in its ");
- if_print_tag (SC_TAG_ITALICS, "");
- if_print_string ("brief");
- if_print_tag (SC_TAG_ENDITALICS, "");
- if_print_string (" mode, which gives long descriptions of places never"
- " before visited and short descriptions otherwise.\n");
+lib_cmd_brief(sc_gameref_t game) {
+ /* Clear game verbose flag and return. */
+ game->verbose = FALSE;
+ if_print_string("The game is now in its ");
+ if_print_tag(SC_TAG_ITALICS, "");
+ if_print_string("brief");
+ if_print_tag(SC_TAG_ENDITALICS, "");
+ if_print_string(" mode, which gives long descriptions of places never"
+ " before visited and short descriptions otherwise.\n");
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -2097,67 +1924,57 @@ lib_cmd_brief (sc_gameref_t game)
* rather than using the printfilter to avoid possible clashes with ALRs.
*/
sc_bool
-lib_cmd_notify_on_off (sc_gameref_t game)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_char *control;
-
- /* Get the text following the notify command, and check for "on"/"off". */
- control = var_get_ref_text (vars);
- if (sc_strcasecmp (control, "on") == 0)
- {
- /* Set score change notification. */
- game->notify_score_change = TRUE;
- if_print_string ("Game score change notification is now ");
- if_print_tag (SC_TAG_ITALICS, "");
- if_print_string ("on");
- if_print_tag (SC_TAG_ENDITALICS, "");
- if_print_string (", and the game will tell you of any changes in the"
- " score.\n");
- }
- else if (sc_strcasecmp (control, "off") == 0)
- {
- /* Clear score change notification. */
- game->notify_score_change = FALSE;
- if_print_string ("Game score change notification is now ");
- if_print_tag (SC_TAG_ITALICS, "");
- if_print_string ("off");
- if_print_tag (SC_TAG_ENDITALICS, "");
- if_print_string (", and the game will be silent on changes in the"
- " score.\n");
- }
- else
- {
- if_print_string ("Use 'notify on' or 'notify off' to control game"
- " score notification.\n");
- }
-
- game->is_admin = TRUE;
- return TRUE;
-}
-
-sc_bool
-lib_cmd_notify (sc_gameref_t game)
-{
- /* Report the current state of notification. */
- if_print_string ("Game score change notification is ");
- if_print_tag (SC_TAG_ITALICS, "");
- if_print_string (game->notify_score_change ? "on" : "off");
- if_print_tag (SC_TAG_ENDITALICS, "");
-
- if (game->notify_score_change)
- {
- if_print_string (", and the game will tell you of any changes in the"
- " score.\n");
- }
- else
- {
- if_print_string (", and the game will be silent on changes in the"
- " score.\n");
- }
-
- game->is_admin = TRUE;
- return TRUE;
+lib_cmd_notify_on_off(sc_gameref_t game) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_char *control;
+
+ /* Get the text following the notify command, and check for "on"/"off". */
+ control = var_get_ref_text(vars);
+ if (sc_strcasecmp(control, "on") == 0) {
+ /* Set score change notification. */
+ game->notify_score_change = TRUE;
+ if_print_string("Game score change notification is now ");
+ if_print_tag(SC_TAG_ITALICS, "");
+ if_print_string("on");
+ if_print_tag(SC_TAG_ENDITALICS, "");
+ if_print_string(", and the game will tell you of any changes in the"
+ " score.\n");
+ } else if (sc_strcasecmp(control, "off") == 0) {
+ /* Clear score change notification. */
+ game->notify_score_change = FALSE;
+ if_print_string("Game score change notification is now ");
+ if_print_tag(SC_TAG_ITALICS, "");
+ if_print_string("off");
+ if_print_tag(SC_TAG_ENDITALICS, "");
+ if_print_string(", and the game will be silent on changes in the"
+ " score.\n");
+ } else {
+ if_print_string("Use 'notify on' or 'notify off' to control game"
+ " score notification.\n");
+ }
+
+ game->is_admin = TRUE;
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_notify(sc_gameref_t game) {
+ /* Report the current state of notification. */
+ if_print_string("Game score change notification is ");
+ if_print_tag(SC_TAG_ITALICS, "");
+ if_print_string(game->notify_score_change ? "on" : "off");
+ if_print_tag(SC_TAG_ENDITALICS, "");
+
+ if (game->notify_score_change) {
+ if_print_string(", and the game will tell you of any changes in the"
+ " score.\n");
+ } else {
+ if_print_string(", and the game will be silent on changes in the"
+ " score.\n");
+ }
+
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -2170,39 +1987,37 @@ lib_cmd_notify (sc_gameref_t game)
* different.
*/
sc_bool
-lib_cmd_time (sc_gameref_t game)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_uint timestamp;
- sc_int hr, min, sec;
- sc_char buffer[64];
+lib_cmd_time(sc_gameref_t game) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_uint timestamp;
+ sc_int hr, min, sec;
+ sc_char buffer[64];
- /* Get elapsed game time and convert to hour, minutes, and seconds. */
- timestamp = var_get_elapsed_seconds (vars);
- hr = timestamp / SECS_PER_HOUR;
- min = (timestamp % SECS_PER_HOUR) / MINS_PER_HOUR;
- sec = timestamp % SECS_PER_MINUTE;
- if (hr > 0)
- sprintf (buffer, "%ldh %02ldm %02lds", hr, min, sec);
- else
- sprintf (buffer, "%ldm %02lds", min, sec);
+ /* Get elapsed game time and convert to hour, minutes, and seconds. */
+ timestamp = var_get_elapsed_seconds(vars);
+ hr = timestamp / SECS_PER_HOUR;
+ min = (timestamp % SECS_PER_HOUR) / MINS_PER_HOUR;
+ sec = timestamp % SECS_PER_MINUTE;
+ if (hr > 0)
+ sprintf(buffer, "%ldh %02ldm %02lds", hr, min, sec);
+ else
+ sprintf(buffer, "%ldm %02lds", min, sec);
- /* Print the game's elapsed time. */
- if_print_string ("You have been running the game for ");
- if_print_string (buffer);
- if_print_string (".\n");
+ /* Print the game's elapsed time. */
+ if_print_string("You have been running the game for ");
+ if_print_string(buffer);
+ if_print_string(".\n");
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
sc_bool
-lib_cmd_date (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_date(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "Maybe we should just be good friends.\n");
- return TRUE;
+ pf_buffer_string(filter, "Maybe we should just be good friends.\n");
+ return TRUE;
}
@@ -2211,10 +2026,10 @@ lib_cmd_date (sc_gameref_t game)
* into a single function. The values are explicit to ensure they match
* enumerations in the game data.
*/
-enum
-{ DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3,
- DIR_UP = 4, DIR_DOWN = 5, DIR_IN = 6, DIR_OUT = 7,
- DIR_NORTHEAST = 8, DIR_SOUTHEAST = 9, DIR_SOUTHWEST = 10, DIR_NORTHWEST = 11
+enum {
+ DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3,
+ DIR_UP = 4, DIR_DOWN = 5, DIR_IN = 6, DIR_OUT = 7,
+ DIR_NORTHEAST = 8, DIR_SOUTHEAST = 9, DIR_SOUTHWEST = 10, DIR_NORTHWEST = 11
};
@@ -2224,137 +2039,123 @@ enum
* Central movement command, called by all movement handlers.
*/
static sc_bool
-lib_go (sc_gameref_t game, sc_int direction)
-{
- 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;
- sc_bool eightpointcompass, is_trapped, is_exitable[12];
- sc_int destination, index_;
- const sc_char *const *dirnames;
-
- /* 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;
-
- /* Start by seeing if there are any exits at all available. */
- is_trapped = TRUE;
- for (index_ = 0; dirnames[index_]; index_++)
- {
- vt_key[0].string = "Rooms";
- vt_key[1].integer = gs_playerroom (game);
- vt_key[2].string = "Exits";
- vt_key[3].integer = index_;
- if (prop_get (bundle, "I<-sisi", &vt_rvalue, vt_key)
- && lib_can_go (game, gs_playerroom (game), index_))
- {
- is_exitable[index_] = TRUE;
- is_trapped = FALSE;
- }
- else
- is_exitable[index_] = FALSE;
- }
- if (is_trapped)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't go in any direction!\n",
- "I can't go in any direction!\n",
- "%player% can't go in any direction!\n"));
- return TRUE;
- }
-
- /*
- * Check for the exit, and if it doesn't exist, refuse, and list the possible
- * options.
- */
- vt_key[0].string = "Rooms";
- vt_key[1].integer = gs_playerroom (game);
- vt_key[2].string = "Exits";
- vt_key[3].integer = direction;
- vt_key[4].string = "Dest";
- if (prop_get (bundle, "I<-sisis", &vt_rvalue, vt_key))
- destination = vt_rvalue.integer - 1;
- else
- {
- sc_int count, trail;
-
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't go in that direction, but you can move ",
- "I can't go in that direction, but I can move ",
- "%player% can't go in that direction, but can move "));
-
- /* List available exits, found in exit test loop earlier. */
- count = 0;
- trail = -1;
- for (index_ = 0; dirnames[index_]; index_++)
- {
- if (is_exitable[index_])
- {
- if (count > 0)
- {
- if (count > 1)
- pf_buffer_string (filter, ", ");
- pf_buffer_string (filter, dirnames[trail]);
- }
- trail = index_;
- count++;
- }
- }
- if (count >= 1)
- {
- if (count > 1)
- pf_buffer_string (filter, " and ");
- pf_buffer_string (filter, dirnames[trail]);
- }
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- /* Check for any movement restrictions. */
- if (!lib_can_go (game, gs_playerroom (game), direction))
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't go in that direction (at present).\n",
- "I can't go in that direction (at present).\n",
- "%player% can't go in that direction (at present).\n"));
- return TRUE;
- }
-
- if (lib_trace)
- {
- sc_trace ("Library: moving player from %ld to %ld\n",
- gs_playerroom (game), destination);
- }
-
- /* Indicate if getting off something or standing up first. */
- if (gs_playerparent (game) != -1)
- {
- pf_buffer_string (filter, "(Getting off ");
- lib_print_object_np (game, gs_playerparent (game));
- pf_buffer_string (filter, " first)\n");
- }
- else if (gs_playerposition (game) != 0)
- pf_buffer_string (filter, "(Standing up first)\n");
-
- /* Confirm and then make move. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You move ",
- "I move ",
- "%player% moves "));
- pf_buffer_string (filter, dirnames[direction]);
- pf_buffer_string (filter, ".\n");
-
- gs_move_player_to_room (game, destination);
-
- /* Describe the new room and return. */
- lib_describe_player_room (game, FALSE);
- return TRUE;
+lib_go(sc_gameref_t game, sc_int direction) {
+ 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;
+ sc_bool eightpointcompass, is_trapped, is_exitable[12];
+ sc_int destination, index_;
+ const sc_char *const *dirnames;
+
+ /* 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;
+
+ /* Start by seeing if there are any exits at all available. */
+ is_trapped = TRUE;
+ for (index_ = 0; dirnames[index_]; index_++) {
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = gs_playerroom(game);
+ vt_key[2].string = "Exits";
+ vt_key[3].integer = index_;
+ if (prop_get(bundle, "I<-sisi", &vt_rvalue, vt_key)
+ && lib_can_go(game, gs_playerroom(game), index_)) {
+ is_exitable[index_] = TRUE;
+ is_trapped = FALSE;
+ } else
+ is_exitable[index_] = FALSE;
+ }
+ if (is_trapped) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't go in any direction!\n",
+ "I can't go in any direction!\n",
+ "%player% can't go in any direction!\n"));
+ return TRUE;
+ }
+
+ /*
+ * Check for the exit, and if it doesn't exist, refuse, and list the possible
+ * options.
+ */
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = gs_playerroom(game);
+ vt_key[2].string = "Exits";
+ vt_key[3].integer = direction;
+ vt_key[4].string = "Dest";
+ if (prop_get(bundle, "I<-sisis", &vt_rvalue, vt_key))
+ destination = vt_rvalue.integer - 1;
+ else {
+ sc_int count, trail;
+
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't go in that direction, but you can move ",
+ "I can't go in that direction, but I can move ",
+ "%player% can't go in that direction, but can move "));
+
+ /* List available exits, found in exit test loop earlier. */
+ count = 0;
+ trail = -1;
+ for (index_ = 0; dirnames[index_]; index_++) {
+ if (is_exitable[index_]) {
+ if (count > 0) {
+ if (count > 1)
+ pf_buffer_string(filter, ", ");
+ pf_buffer_string(filter, dirnames[trail]);
+ }
+ trail = index_;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ if (count > 1)
+ pf_buffer_string(filter, " and ");
+ pf_buffer_string(filter, dirnames[trail]);
+ }
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ /* Check for any movement restrictions. */
+ if (!lib_can_go(game, gs_playerroom(game), direction)) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't go in that direction (at present).\n",
+ "I can't go in that direction (at present).\n",
+ "%player% can't go in that direction (at present).\n"));
+ return TRUE;
+ }
+
+ if (lib_trace) {
+ sc_trace("Library: moving player from %ld to %ld\n",
+ gs_playerroom(game), destination);
+ }
+
+ /* Indicate if getting off something or standing up first. */
+ if (gs_playerparent(game) != -1) {
+ pf_buffer_string(filter, "(Getting off ");
+ lib_print_object_np(game, gs_playerparent(game));
+ pf_buffer_string(filter, " first)\n");
+ } else if (gs_playerposition(game) != 0)
+ pf_buffer_string(filter, "(Standing up first)\n");
+
+ /* Confirm and then make move. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You move ",
+ "I move ",
+ "%player% moves "));
+ pf_buffer_string(filter, dirnames[direction]);
+ pf_buffer_string(filter, ".\n");
+
+ gs_move_player_to_room(game, destination);
+
+ /* Describe the new room and return. */
+ lib_describe_player_room(game, FALSE);
+ return TRUE;
}
@@ -2364,75 +2165,63 @@ lib_go (sc_gameref_t game, sc_int direction)
* Direction-specific movement commands.
*/
sc_bool
-lib_cmd_go_north (sc_gameref_t game)
-{
- return lib_go (game, DIR_NORTH);
+lib_cmd_go_north(sc_gameref_t game) {
+ return lib_go(game, DIR_NORTH);
}
sc_bool
-lib_cmd_go_east (sc_gameref_t game)
-{
- return lib_go (game, DIR_EAST);
+lib_cmd_go_east(sc_gameref_t game) {
+ return lib_go(game, DIR_EAST);
}
sc_bool
-lib_cmd_go_south (sc_gameref_t game)
-{
- return lib_go (game, DIR_SOUTH);
+lib_cmd_go_south(sc_gameref_t game) {
+ return lib_go(game, DIR_SOUTH);
}
sc_bool
-lib_cmd_go_west (sc_gameref_t game)
-{
- return lib_go (game, DIR_WEST);
+lib_cmd_go_west(sc_gameref_t game) {
+ return lib_go(game, DIR_WEST);
}
sc_bool
-lib_cmd_go_up (sc_gameref_t game)
-{
- return lib_go (game, DIR_UP);
+lib_cmd_go_up(sc_gameref_t game) {
+ return lib_go(game, DIR_UP);
}
sc_bool
-lib_cmd_go_down (sc_gameref_t game)
-{
- return lib_go (game, DIR_DOWN);
+lib_cmd_go_down(sc_gameref_t game) {
+ return lib_go(game, DIR_DOWN);
}
sc_bool
-lib_cmd_go_in (sc_gameref_t game)
-{
- return lib_go (game, DIR_IN);
+lib_cmd_go_in(sc_gameref_t game) {
+ return lib_go(game, DIR_IN);
}
sc_bool
-lib_cmd_go_out (sc_gameref_t game)
-{
- return lib_go (game, DIR_OUT);
+lib_cmd_go_out(sc_gameref_t game) {
+ return lib_go(game, DIR_OUT);
}
sc_bool
-lib_cmd_go_northeast (sc_gameref_t game)
-{
- return lib_go (game, DIR_NORTHEAST);
+lib_cmd_go_northeast(sc_gameref_t game) {
+ return lib_go(game, DIR_NORTHEAST);
}
sc_bool
-lib_cmd_go_southeast (sc_gameref_t game)
-{
- return lib_go (game, DIR_SOUTHEAST);
+lib_cmd_go_southeast(sc_gameref_t game) {
+ return lib_go(game, DIR_SOUTHEAST);
}
sc_bool
-lib_cmd_go_northwest (sc_gameref_t game)
-{
- return lib_go (game, DIR_NORTHWEST);
+lib_cmd_go_northwest(sc_gameref_t game) {
+ return lib_go(game, DIR_NORTHWEST);
}
sc_bool
-lib_cmd_go_southwest (sc_gameref_t game)
-{
- return lib_go (game, DIR_SOUTHWEST);
+lib_cmd_go_southwest(sc_gameref_t game) {
+ return lib_go(game, DIR_SOUTHWEST);
}
@@ -2444,34 +2233,33 @@ lib_cmd_go_southwest (sc_gameref_t game)
* requires that string is filtered, stripped, trimmed and normalized.
*/
static sc_bool
-lib_compare_rooms (sc_gameref_t game, sc_int room, const sc_char *string)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_char *name, *compare_name;
- sc_bool status;
+lib_compare_rooms(sc_gameref_t game, sc_int room, const sc_char *string) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_char *name, *compare_name;
+ sc_bool status;
- /* Get the name of the room, and filter it down to a plain string. */
- name = pf_filter (lib_get_room_name (game, room), vars, bundle);
- pf_strip_tags (name);
- sc_normalize_string (sc_trim_string (name));
+ /* Get the name of the room, and filter it down to a plain string. */
+ name = pf_filter(lib_get_room_name(game, room), vars, bundle);
+ pf_strip_tags(name);
+ sc_normalize_string(sc_trim_string(name));
- /* Bypass any prefix on the room name. */
- if (sc_compare_word (name, "a", 1))
- compare_name = name + 1;
- else if (sc_compare_word (name, "an", 2))
- compare_name = name + 2;
- else if (sc_compare_word (name, "the", 3))
- compare_name = name + 3;
- else
- compare_name = name;
- sc_trim_string (compare_name);
+ /* Bypass any prefix on the room name. */
+ if (sc_compare_word(name, "a", 1))
+ compare_name = name + 1;
+ else if (sc_compare_word(name, "an", 2))
+ compare_name = name + 2;
+ else if (sc_compare_word(name, "the", 3))
+ compare_name = name + 3;
+ else
+ compare_name = name;
+ sc_trim_string(compare_name);
- /* Compare strings, then free the allocated name. */
- status = sc_strcasecmp (compare_name, string) == 0;
- sc_free (name);
+ /* Compare strings, then free the allocated name. */
+ status = sc_strcasecmp(compare_name, string) == 0;
+ sc_free(name);
- return status;
+ return status;
}
@@ -2488,118 +2276,108 @@ lib_compare_rooms (sc_gameref_t game, sc_int room, const sc_char *string)
* differentiated within the game with trailing "<some_tag>" components.
*/
sc_bool
-lib_cmd_go_room (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5], vt_rvalue;
- sc_bool eightpointcompass, is_trapped, is_ambiguous;
- sc_int direction, destination, index_;
- const sc_char *const *dirnames;
- sc_char *name, *compare_name;
-
- /* Determine the requested room, and filter it down to a plain string. */
- name = pf_filter (var_get_ref_text (vars), vars, bundle);
- pf_strip_tags (name);
- sc_normalize_string (sc_trim_string (name));
-
- /* Bypass any prefix on the request room name. */
- if (sc_compare_word (name, "a", 1))
- compare_name = name + 1;
- else if (sc_compare_word (name, "an", 2))
- compare_name = name + 2;
- else if (sc_compare_word (name, "the", 3))
- compare_name = name + 3;
- else
- compare_name = name;
- sc_trim_string (compare_name);
-
- /* See if the named room is the current player room. */
- if (lib_compare_rooms (game, gs_playerroom (game), compare_name))
- {
- pf_buffer_string (filter, "You are already there!\n");
- sc_free (name);
- return TRUE;
- }
-
- /* 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;
-
- /* Search adjacent and available rooms for a name match. */
- is_trapped = TRUE;
- is_ambiguous = FALSE;
- direction = -1;
- destination = -1;
- for (index_ = 0; dirnames[index_]; index_++)
- {
- vt_key[0].string = "Rooms";
- vt_key[1].integer = gs_playerroom (game);
- vt_key[2].string = "Exits";
- vt_key[3].integer = index_;
- if (prop_get (bundle, "I<-sisi", &vt_rvalue, vt_key)
- && lib_can_go (game, gs_playerroom (game), index_))
- {
- is_trapped = FALSE;
-
- /*
- * Room is available. Compare its name with that requested provided
- * that it's a location we've not already accepted (that is, some
- * rooms are reachable by multiple directions, such as both "south"
- * and "out").
- */
- vt_key[4].string = "Dest";
- if (prop_get (bundle, "I<-sisis", &vt_rvalue, vt_key))
- {
- sc_int location;
-
- location = vt_rvalue.integer - 1;
- if (location != destination
- && lib_compare_rooms (game, location, compare_name))
- {
- if (direction != -1)
- is_ambiguous = TRUE;
- direction = index_;
- destination = location;
- }
- }
- }
- }
- sc_free (name);
-
- /* If trapped or it's unclear where to go, handle these cases. */
- if (is_trapped)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't go in any direction!\n",
- "I can't go in any direction!\n",
- "%player% can't go in any direction!\n"));
- return TRUE;
- }
- else if (is_ambiguous)
- {
- pf_buffer_string (filter,
- "I'm not clear about where you want to go."
- " Please try using just a direction.\n");
- pf_buffer_character (filter, '\n');
- lib_cmd_print_room_exits (game);
- return TRUE;
- }
-
- /* If no match, note it, otherwise handle as standard directional move. */
- if (direction == -1)
- {
- pf_buffer_string (filter, "I don't know how to get there from here.\n");
- pf_buffer_character (filter, '\n');
- lib_cmd_print_room_exits (game);
- return TRUE;
- }
-
- return lib_go (game, direction);
+lib_cmd_go_room(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5], vt_rvalue;
+ sc_bool eightpointcompass, is_trapped, is_ambiguous;
+ sc_int direction, destination, index_;
+ const sc_char *const *dirnames;
+ sc_char *name, *compare_name;
+
+ /* Determine the requested room, and filter it down to a plain string. */
+ name = pf_filter(var_get_ref_text(vars), vars, bundle);
+ pf_strip_tags(name);
+ sc_normalize_string(sc_trim_string(name));
+
+ /* Bypass any prefix on the request room name. */
+ if (sc_compare_word(name, "a", 1))
+ compare_name = name + 1;
+ else if (sc_compare_word(name, "an", 2))
+ compare_name = name + 2;
+ else if (sc_compare_word(name, "the", 3))
+ compare_name = name + 3;
+ else
+ compare_name = name;
+ sc_trim_string(compare_name);
+
+ /* See if the named room is the current player room. */
+ if (lib_compare_rooms(game, gs_playerroom(game), compare_name)) {
+ pf_buffer_string(filter, "You are already there!\n");
+ sc_free(name);
+ return TRUE;
+ }
+
+ /* 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;
+
+ /* Search adjacent and available rooms for a name match. */
+ is_trapped = TRUE;
+ is_ambiguous = FALSE;
+ direction = -1;
+ destination = -1;
+ for (index_ = 0; dirnames[index_]; index_++) {
+ vt_key[0].string = "Rooms";
+ vt_key[1].integer = gs_playerroom(game);
+ vt_key[2].string = "Exits";
+ vt_key[3].integer = index_;
+ if (prop_get(bundle, "I<-sisi", &vt_rvalue, vt_key)
+ && lib_can_go(game, gs_playerroom(game), index_)) {
+ is_trapped = FALSE;
+
+ /*
+ * Room is available. Compare its name with that requested provided
+ * that it's a location we've not already accepted (that is, some
+ * rooms are reachable by multiple directions, such as both "south"
+ * and "out").
+ */
+ vt_key[4].string = "Dest";
+ if (prop_get(bundle, "I<-sisis", &vt_rvalue, vt_key)) {
+ sc_int location;
+
+ location = vt_rvalue.integer - 1;
+ if (location != destination
+ && lib_compare_rooms(game, location, compare_name)) {
+ if (direction != -1)
+ is_ambiguous = TRUE;
+ direction = index_;
+ destination = location;
+ }
+ }
+ }
+ }
+ sc_free(name);
+
+ /* If trapped or it's unclear where to go, handle these cases. */
+ if (is_trapped) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't go in any direction!\n",
+ "I can't go in any direction!\n",
+ "%player% can't go in any direction!\n"));
+ return TRUE;
+ } else if (is_ambiguous) {
+ pf_buffer_string(filter,
+ "I'm not clear about where you want to go."
+ " Please try using just a direction.\n");
+ pf_buffer_character(filter, '\n');
+ lib_cmd_print_room_exits(game);
+ return TRUE;
+ }
+
+ /* If no match, note it, otherwise handle as standard directional move. */
+ if (direction == -1) {
+ pf_buffer_string(filter, "I don't know how to get there from here.\n");
+ pf_buffer_character(filter, '\n');
+ lib_cmd_print_room_exits(game);
+ return TRUE;
+ }
+
+ return lib_go(game, direction);
}
@@ -2609,121 +2387,108 @@ lib_cmd_go_room (sc_gameref_t game)
* Show the long description of a player.
*/
sc_bool
-lib_cmd_examine_self (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_int task, object, count, trail;
- const sc_char *description, *position = NULL;
-
- /* Get selection task. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "Task";
- task = prop_get_integer (bundle, "I<-ss", vt_key) - 1;
-
- /* Select either the main or the alternate description. */
- if (task >= 0 && gs_task_done (game, task))
- vt_key[1].string = "AltDesc";
- else
- vt_key[1].string = "PlayerDesc";
-
- /* Print the description, or default response. */
- description = prop_get_string (bundle, "S<-ss", vt_key);
- if (!sc_strempty (description))
- pf_buffer_string (filter, description);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are as well as can be expected,"
- " considering the circumstances.",
- "I am as well as can be expected,"
- " considering the circumstances.",
- "%player% is as well as can be expected,"
- " considering the circumstances."));
- }
-
- /* If not just standing on the floor, say more. */
- switch (gs_playerposition (game))
- {
- case 0:
- position = lib_select_response (game,
- "You are standing",
- "I am standing",
- "%player% is standing");
- break;
- case 1:
- position = lib_select_response (game,
- "You are sitting down",
- "I am sitting down",
- "%player% is sitting down");
- break;
- case 2:
- position = lib_select_response (game,
- "You are lying down",
- "I am lying down",
- "%player% is lying down");
- break;
- }
-
- if (position
- && !(gs_playerposition (game) == 0 && gs_playerparent (game) == -1))
- {
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter, position);
- if (gs_playerparent (game) != -1)
- {
- pf_buffer_string (filter, " on ");
- lib_print_object_np (game, gs_playerparent (game));
- }
- pf_buffer_character (filter, '.');
- }
-
- /* Find and list each object worn by the player. */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_WORN_PLAYER)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- " You are wearing ",
- " I am wearing ",
- " %player% is wearing "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- " You are wearing ",
- " I am wearing ",
- " %player% is wearing "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object (game, trail);
- pf_buffer_character (filter, '.');
- }
-
- pf_buffer_character (filter, '\n');
- return TRUE;
+lib_cmd_examine_self(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_int task, object, count, trail;
+ const sc_char *description, *position = NULL;
+
+ /* Get selection task. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Task";
+ task = prop_get_integer(bundle, "I<-ss", vt_key) - 1;
+
+ /* Select either the main or the alternate description. */
+ if (task >= 0 && gs_task_done(game, task))
+ vt_key[1].string = "AltDesc";
+ else
+ vt_key[1].string = "PlayerDesc";
+
+ /* Print the description, or default response. */
+ description = prop_get_string(bundle, "S<-ss", vt_key);
+ if (!sc_strempty(description))
+ pf_buffer_string(filter, description);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are as well as can be expected,"
+ " considering the circumstances.",
+ "I am as well as can be expected,"
+ " considering the circumstances.",
+ "%player% is as well as can be expected,"
+ " considering the circumstances."));
+ }
+
+ /* If not just standing on the floor, say more. */
+ switch (gs_playerposition(game)) {
+ case 0:
+ position = lib_select_response(game,
+ "You are standing",
+ "I am standing",
+ "%player% is standing");
+ break;
+ case 1:
+ position = lib_select_response(game,
+ "You are sitting down",
+ "I am sitting down",
+ "%player% is sitting down");
+ break;
+ case 2:
+ position = lib_select_response(game,
+ "You are lying down",
+ "I am lying down",
+ "%player% is lying down");
+ break;
+ }
+
+ if (position
+ && !(gs_playerposition(game) == 0 && gs_playerparent(game) == -1)) {
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter, position);
+ if (gs_playerparent(game) != -1) {
+ pf_buffer_string(filter, " on ");
+ lib_print_object_np(game, gs_playerparent(game));
+ }
+ pf_buffer_character(filter, '.');
+ }
+
+ /* Find and list each object worn by the player. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_WORN_PLAYER) {
+ if (count > 0) {
+ if (count == 1) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " You are wearing ",
+ " I am wearing ",
+ " %player% is wearing "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " You are wearing ",
+ " I am wearing ",
+ " %player% is wearing "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object(game, trail);
+ pf_buffer_character(filter, '.');
+ }
+
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -2737,83 +2502,74 @@ lib_cmd_examine_self (sc_gameref_t game)
* return -1.
*/
static sc_int
-lib_disambiguate_npc (sc_gameref_t game,
- const sc_char *verb, sc_bool *is_ambiguous)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int count, index_, npc, listed;
-
- /*
- * Filter out all referenced NPCs not actually visible or seen. Count the
- * number of NPCs remaining as referenced by the last command, and note the
- * last referenced NPC, for where count is 1.
- */
- count = 0;
- npc = -1;
- for (index_ = 0; index_ < gs_npc_count (game); index_++)
- {
- if (game->npc_references[index_]
- && gs_npc_seen (game, index_)
- && npc_in_room (game, index_, gs_playerroom (game)))
- {
- count++;
- npc = index_;
- }
- else
- game->npc_references[index_] = FALSE;
- }
-
- /* If the reference is unambiguous, set in variables and return it. */
- if (count == 1)
- {
- /* Set this NPC as the referenced character. */
- var_set_ref_character (vars, npc);
-
- /* Return, setting no ambiguity. */
- if (is_ambiguous)
- *is_ambiguous = FALSE;
- return npc;
- }
-
- /* If nothing referenced, return no NPC. */
- if (count == 0)
- {
- if (is_ambiguous)
- *is_ambiguous = FALSE;
- else
- {
- pf_buffer_string (filter,
- "Please be more clear, who do you want to ");
- pf_buffer_string (filter, verb);
- pf_buffer_string (filter, "?\n");
- }
- return -1;
- }
-
- /* The NPC reference is ambiguous, so list the choices. */
- pf_buffer_string (filter, "Please be more clear, who do you want to ");
- pf_buffer_string (filter, verb);
- pf_buffer_string (filter, "? ");
-
- pf_new_sentence (filter);
- listed = 0;
- for (index_ = 0; index_ < gs_npc_count (game); index_++)
- {
- if (game->npc_references[index_])
- {
- lib_print_npc_np (game, index_);
- listed++;
- if (listed < count)
- pf_buffer_string (filter, (listed < count - 1) ? ", " : " or ");
- }
- }
- pf_buffer_string (filter, "?\n");
-
- /* Return no NPC for an ambiguous reference. */
- if (is_ambiguous)
- *is_ambiguous = TRUE;
- return -1;
+lib_disambiguate_npc(sc_gameref_t game,
+ const sc_char *verb, sc_bool *is_ambiguous) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int count, index_, npc, listed;
+
+ /*
+ * Filter out all referenced NPCs not actually visible or seen. Count the
+ * number of NPCs remaining as referenced by the last command, and note the
+ * last referenced NPC, for where count is 1.
+ */
+ count = 0;
+ npc = -1;
+ for (index_ = 0; index_ < gs_npc_count(game); index_++) {
+ if (game->npc_references[index_]
+ && gs_npc_seen(game, index_)
+ && npc_in_room(game, index_, gs_playerroom(game))) {
+ count++;
+ npc = index_;
+ } else
+ game->npc_references[index_] = FALSE;
+ }
+
+ /* If the reference is unambiguous, set in variables and return it. */
+ if (count == 1) {
+ /* Set this NPC as the referenced character. */
+ var_set_ref_character(vars, npc);
+
+ /* Return, setting no ambiguity. */
+ if (is_ambiguous)
+ *is_ambiguous = FALSE;
+ return npc;
+ }
+
+ /* If nothing referenced, return no NPC. */
+ if (count == 0) {
+ if (is_ambiguous)
+ *is_ambiguous = FALSE;
+ else {
+ pf_buffer_string(filter,
+ "Please be more clear, who do you want to ");
+ pf_buffer_string(filter, verb);
+ pf_buffer_string(filter, "?\n");
+ }
+ return -1;
+ }
+
+ /* The NPC reference is ambiguous, so list the choices. */
+ pf_buffer_string(filter, "Please be more clear, who do you want to ");
+ pf_buffer_string(filter, verb);
+ pf_buffer_string(filter, "? ");
+
+ pf_new_sentence(filter);
+ listed = 0;
+ for (index_ = 0; index_ < gs_npc_count(game); index_++) {
+ if (game->npc_references[index_]) {
+ lib_print_npc_np(game, index_);
+ listed++;
+ if (listed < count)
+ pf_buffer_string(filter, (listed < count - 1) ? ", " : " or ");
+ }
+ }
+ pf_buffer_string(filter, "?\n");
+
+ /* Return no NPC for an ambiguous reference. */
+ if (is_ambiguous)
+ *is_ambiguous = TRUE;
+ return -1;
}
@@ -2835,158 +2591,141 @@ lib_disambiguate_npc (sc_gameref_t game,
* function used to filter objects for multiple references.
*/
static sc_int
-lib_disambiguate_object_common (sc_gameref_t game, const sc_char *verb,
- sc_bool (*resolver)
- (sc_gameref_t, sc_int, sc_int),
+lib_disambiguate_object_common(sc_gameref_t game, const sc_char *verb,
+ sc_bool(*resolver)
+ (sc_gameref_t, sc_int, sc_int),
sc_int resolver_arg,
- sc_bool *is_ambiguous)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int count, index_, object, listed;
-
- /*
- * Filter out all referenced objects not actually visible or seen. Count
- * the number of objects remaining as referenced by the last command, and
- * note the last referenced object, for where count is 1.
- */
- count = 0;
- object = -1;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (game->object_references[index_]
- && gs_object_seen (game, index_)
- && obj_indirectly_in_room (game, index_, gs_playerroom (game)))
- {
- count++;
- object = index_;
- }
- else
- game->object_references[index_] = FALSE;
- }
-
- /*
- * If this reference is ambiguous and a resolver was supplied, try to
- * resolve it unambiguously by calling the resolver filter on the remaining
- * set references.
- */
- if (resolver && count > 1)
- {
- sc_int retry_count;
-
- /*
- * Search for objects accepted by the resolver filter, but don't filter
- * references just yet. Again, note the last referenced.
- */
- retry_count = 0;
- object = -1;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (game->object_references[index_]
- && resolver (game, index_, resolver_arg))
- {
- retry_count++;
- object = index_;
- }
- }
-
- /* See if we narrowed the field without eliminating every object. */
- if (retry_count > 0 && retry_count < count)
- {
- /*
- * If we got down to a single object, the ambiguity is resolved.
- * In this case, set count to 1 so that 'object' is returned.
- */
- if (retry_count == 1)
- count = retry_count;
- else
- {
- /*
- * We got down to fewer objects; reduce references so that the
- * disambiguation message is clearer. Note that here we still
- * leave with count greater than 1.
- */
- count = 0;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (game->object_references[index_]
- && resolver (game, index_, resolver_arg))
- count++;
- else
- game->object_references[index_] = FALSE;
- }
- }
- }
- }
-
- /* If the reference is unambiguous, set in variables and return it. */
- if (count == 1)
- {
- /* Set this object as referenced. */
- var_set_ref_object (vars, object);
-
- /* Return, setting no ambiguity. */
- if (is_ambiguous)
- *is_ambiguous = FALSE;
- return object;
- }
-
- /* If nothing referenced, return no object. */
- if (count == 0)
- {
- if (is_ambiguous)
- *is_ambiguous = FALSE;
- else
- {
- pf_buffer_string (filter,
- "Please be more clear, what do you want to ");
- pf_buffer_string (filter, verb);
- pf_buffer_string (filter, "?\n");
- }
- return -1;
- }
-
- /* The object reference is ambiguous, so list the choices. */
- pf_buffer_string (filter, "Please be more clear, what do you want to ");
- pf_buffer_string (filter, verb);
- pf_buffer_string (filter, "? ");
-
- pf_new_sentence (filter);
- listed = 0;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (game->object_references[index_])
- {
- lib_print_object_np (game, index_);
- listed++;
- if (listed < count)
- pf_buffer_string (filter, (listed < count - 1) ? ", " : " or ");
- }
- }
- pf_buffer_string (filter, "?\n");
-
- /* Return no object for an ambiguous reference. */
- if (is_ambiguous)
- *is_ambiguous = TRUE;
- return -1;
+ sc_bool *is_ambiguous) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int count, index_, object, listed;
+
+ /*
+ * Filter out all referenced objects not actually visible or seen. Count
+ * the number of objects remaining as referenced by the last command, and
+ * note the last referenced object, for where count is 1.
+ */
+ count = 0;
+ object = -1;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (game->object_references[index_]
+ && gs_object_seen(game, index_)
+ && obj_indirectly_in_room(game, index_, gs_playerroom(game))) {
+ count++;
+ object = index_;
+ } else
+ game->object_references[index_] = FALSE;
+ }
+
+ /*
+ * If this reference is ambiguous and a resolver was supplied, try to
+ * resolve it unambiguously by calling the resolver filter on the remaining
+ * set references.
+ */
+ if (resolver && count > 1) {
+ sc_int retry_count;
+
+ /*
+ * Search for objects accepted by the resolver filter, but don't filter
+ * references just yet. Again, note the last referenced.
+ */
+ retry_count = 0;
+ object = -1;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (game->object_references[index_]
+ && resolver(game, index_, resolver_arg)) {
+ retry_count++;
+ object = index_;
+ }
+ }
+
+ /* See if we narrowed the field without eliminating every object. */
+ if (retry_count > 0 && retry_count < count) {
+ /*
+ * If we got down to a single object, the ambiguity is resolved.
+ * In this case, set count to 1 so that 'object' is returned.
+ */
+ if (retry_count == 1)
+ count = retry_count;
+ else {
+ /*
+ * We got down to fewer objects; reduce references so that the
+ * disambiguation message is clearer. Note that here we still
+ * leave with count greater than 1.
+ */
+ count = 0;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (game->object_references[index_]
+ && resolver(game, index_, resolver_arg))
+ count++;
+ else
+ game->object_references[index_] = FALSE;
+ }
+ }
+ }
+ }
+
+ /* If the reference is unambiguous, set in variables and return it. */
+ if (count == 1) {
+ /* Set this object as referenced. */
+ var_set_ref_object(vars, object);
+
+ /* Return, setting no ambiguity. */
+ if (is_ambiguous)
+ *is_ambiguous = FALSE;
+ return object;
+ }
+
+ /* If nothing referenced, return no object. */
+ if (count == 0) {
+ if (is_ambiguous)
+ *is_ambiguous = FALSE;
+ else {
+ pf_buffer_string(filter,
+ "Please be more clear, what do you want to ");
+ pf_buffer_string(filter, verb);
+ pf_buffer_string(filter, "?\n");
+ }
+ return -1;
+ }
+
+ /* The object reference is ambiguous, so list the choices. */
+ pf_buffer_string(filter, "Please be more clear, what do you want to ");
+ pf_buffer_string(filter, verb);
+ pf_buffer_string(filter, "? ");
+
+ pf_new_sentence(filter);
+ listed = 0;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (game->object_references[index_]) {
+ lib_print_object_np(game, index_);
+ listed++;
+ if (listed < count)
+ pf_buffer_string(filter, (listed < count - 1) ? ", " : " or ");
+ }
+ }
+ pf_buffer_string(filter, "?\n");
+
+ /* Return no object for an ambiguous reference. */
+ if (is_ambiguous)
+ *is_ambiguous = TRUE;
+ return -1;
}
static sc_int
-lib_disambiguate_object (sc_gameref_t game,
- const sc_char *verb, sc_bool *is_ambiguous)
-{
- return lib_disambiguate_object_common (game, verb, NULL, -1, is_ambiguous);
+lib_disambiguate_object(sc_gameref_t game,
+ const sc_char *verb, sc_bool *is_ambiguous) {
+ return lib_disambiguate_object_common(game, verb, NULL, -1, is_ambiguous);
}
static sc_int
-lib_disambiguate_object_extended (sc_gameref_t game, const sc_char *verb,
- sc_bool (*resolver)
- (sc_gameref_t, sc_int, sc_int),
- sc_int resolver_arg,
- sc_bool *is_ambiguous)
-{
- return lib_disambiguate_object_common (game, verb,
- resolver, resolver_arg, is_ambiguous);
+lib_disambiguate_object_extended(sc_gameref_t game, const sc_char *verb,
+ sc_bool(*resolver)
+ (sc_gameref_t, sc_int, sc_int),
+ sc_int resolver_arg,
+ sc_bool *is_ambiguous) {
+ return lib_disambiguate_object_common(game, verb,
+ resolver, resolver_arg, is_ambiguous);
}
@@ -2996,116 +2735,93 @@ lib_disambiguate_object_extended (sc_gameref_t game, const sc_char *verb,
* List objects carried and worn by an NPC.
*/
static sc_bool
-lib_list_npc_inventory (sc_gameref_t game, sc_int npc, sc_bool is_described)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object, count, trail;
- sc_bool wearing;
-
- /* Find and list each object worn by the NPC. */
- count = 0;
- trail = -1;
- wearing = FALSE;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_WORN_NPC
- && gs_object_parent (game, object) == npc)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " is wearing ");
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " is wearing ");
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object (game, trail);
- wearing = TRUE;
- }
-
- /* Find and list each object owned by the NPC. */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_HELD_NPC
- && gs_object_parent (game, object) == npc)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- if (!wearing)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_npc_np (game, npc);
- }
- else
- pf_buffer_string (filter, ", and");
- pf_buffer_string (filter, " is carrying ");
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- if (!wearing)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_npc_np (game, npc);
- }
- else
- pf_buffer_string (filter, ", and");
- pf_buffer_string (filter, " is carrying ");
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object (game, trail);
- pf_buffer_character (filter, '.');
- }
- else
- {
- if (wearing)
- pf_buffer_character (filter, '.');
- }
-
- /* Return TRUE if anything worn or carried. */
- return wearing || count > 0;
+lib_list_npc_inventory(sc_gameref_t game, sc_int npc, sc_bool is_described) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object, count, trail;
+ sc_bool wearing;
+
+ /* Find and list each object worn by the NPC. */
+ count = 0;
+ trail = -1;
+ wearing = FALSE;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_WORN_NPC
+ && gs_object_parent(game, object) == npc) {
+ if (count > 0) {
+ if (count == 1) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " is wearing ");
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " is wearing ");
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object(game, trail);
+ wearing = TRUE;
+ }
+
+ /* Find and list each object owned by the NPC. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_HELD_NPC
+ && gs_object_parent(game, object) == npc) {
+ if (count > 0) {
+ if (count == 1) {
+ if (!wearing) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, npc);
+ } else
+ pf_buffer_string(filter, ", and");
+ pf_buffer_string(filter, " is carrying ");
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ if (!wearing) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, npc);
+ } else
+ pf_buffer_string(filter, ", and");
+ pf_buffer_string(filter, " is carrying ");
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object(game, trail);
+ pf_buffer_character(filter, '.');
+ } else {
+ if (wearing)
+ pf_buffer_character(filter, '.');
+ }
+
+ /* Return TRUE if anything worn or carried. */
+ return wearing || count > 0;
}
@@ -3116,59 +2832,54 @@ lib_list_npc_inventory (sc_gameref_t game, sc_int npc, sc_bool is_described)
* list of what they're wearing and carrying.
*/
sc_bool
-lib_cmd_examine_npc (sc_gameref_t game)
-{
- 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 npc, task, resource;
- sc_bool is_ambiguous;
- const sc_char *description;
-
- /* Get the referenced npc, and if none, consider complete. */
- npc = lib_disambiguate_npc (game, "examine", &is_ambiguous);
- if (npc == -1)
- return is_ambiguous;
-
- /* Get selection task. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Task";
- task = prop_get_integer (bundle, "I<-sis", vt_key) - 1;
-
- /* Select either the main or the alternate description. */
- if (task >= 0 && gs_task_done (game, task))
- {
- vt_key[2].string = "AltText";
- resource = 1;
- }
- else
- {
- vt_key[2].string = "Descr";
- resource = 0;
- }
-
- /* Print the description, or a default message if none. */
- description = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (description))
- pf_buffer_string (filter, description);
- else
- {
- pf_buffer_string (filter, "There's nothing special about ");
- lib_print_npc_np (game, npc);
- pf_buffer_character (filter, '.');
- }
-
- /* Handle any associated resource. */
- vt_key[2].string = "Res";
- vt_key[3].integer = resource;
- res_handle_resource (game, "sisi", vt_key);
-
- /* Print what the NPC is wearing and carrying. */
- lib_list_npc_inventory (game, npc, TRUE);
-
- pf_buffer_character (filter, '\n');
- return TRUE;
+lib_cmd_examine_npc(sc_gameref_t game) {
+ 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 npc, task, resource;
+ sc_bool is_ambiguous;
+ const sc_char *description;
+
+ /* Get the referenced npc, and if none, consider complete. */
+ npc = lib_disambiguate_npc(game, "examine", &is_ambiguous);
+ if (npc == -1)
+ return is_ambiguous;
+
+ /* Get selection task. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Task";
+ task = prop_get_integer(bundle, "I<-sis", vt_key) - 1;
+
+ /* Select either the main or the alternate description. */
+ if (task >= 0 && gs_task_done(game, task)) {
+ vt_key[2].string = "AltText";
+ resource = 1;
+ } else {
+ vt_key[2].string = "Descr";
+ resource = 0;
+ }
+
+ /* Print the description, or a default message if none. */
+ description = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(description))
+ pf_buffer_string(filter, description);
+ else {
+ pf_buffer_string(filter, "There's nothing special about ");
+ lib_print_npc_np(game, npc);
+ pf_buffer_character(filter, '.');
+ }
+
+ /* Handle any associated resource. */
+ vt_key[2].string = "Res";
+ vt_key[3].integer = resource;
+ res_handle_resource(game, "sisi", vt_key);
+
+ /* Print what the NPC is wearing and carrying. */
+ lib_list_npc_inventory(game, npc, TRUE);
+
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -3178,66 +2889,57 @@ lib_cmd_examine_npc (sc_gameref_t game)
* List the objects in a given container object, normal format listing.
*/
static sc_bool
-lib_list_in_object_normal (sc_gameref_t game,
- sc_int container, sc_bool is_described)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object, count, trail;
-
- /* List out the containers contained in this container. */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- /* Contained? */
- if (gs_object_position (game, object) == OBJ_IN_OBJECT
- && gs_object_parent (game, object) == container)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter, "Inside ");
- lib_print_object_np (game, container);
- pf_buffer_string (filter,
- lib_select_plurality (game, trail,
- " is ", " are "));
- }
- else
- pf_buffer_string (filter, ", ");
-
- /* Print out the current list object. */
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter, "Inside ");
- lib_print_object_np (game, container);
- pf_buffer_string (filter,
- lib_select_plurality (game, trail,
- " is ", " are "));
- }
- else
- pf_buffer_string (filter, " and ");
-
- /* Print out the final object. */
- lib_print_object (game, trail);
- pf_buffer_character (filter, '.');
- }
-
- /* Return TRUE if anything listed. */
- return count > 0;
+lib_list_in_object_normal(sc_gameref_t game,
+ sc_int container, sc_bool is_described) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object, count, trail;
+
+ /* List out the containers contained in this container. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ /* Contained? */
+ if (gs_object_position(game, object) == OBJ_IN_OBJECT
+ && gs_object_parent(game, object) == container) {
+ if (count > 0) {
+ if (count == 1) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter, "Inside ");
+ lib_print_object_np(game, container);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, trail,
+ " is ", " are "));
+ } else
+ pf_buffer_string(filter, ", ");
+
+ /* Print out the current list object. */
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter, "Inside ");
+ lib_print_object_np(game, container);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, trail,
+ " is ", " are "));
+ } else
+ pf_buffer_string(filter, " and ");
+
+ /* Print out the final object. */
+ lib_print_object(game, trail);
+ pf_buffer_character(filter, '.');
+ }
+
+ /* Return TRUE if anything listed. */
+ return count > 0;
}
@@ -3247,67 +2949,57 @@ lib_list_in_object_normal (sc_gameref_t game,
* List the objects in a given container object, alternate format listing.
*/
static sc_bool
-lib_list_in_object_alternate (sc_gameref_t game,
- sc_int container, sc_bool is_described)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object, count, trail;
-
- /* List out the objects contained in this object. */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- /* Contained? */
- if (gs_object_position (game, object) == OBJ_IN_OBJECT
- && gs_object_parent (game, object) == container)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- }
- else
- pf_buffer_string (filter, ", ");
-
- /* Print out the current list object. */
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object (game, trail);
- pf_buffer_string (filter,
- lib_select_plurality (game, trail,
- " is inside ",
- " are inside "));
- }
- else
- {
- pf_buffer_string (filter, " and ");
- lib_print_object (game, trail);
- pf_buffer_string (filter, " are inside ");
- }
-
- /* Print out the container. */
- lib_print_object_np (game, container);
- pf_buffer_character (filter, '.');
- }
-
- /* Return TRUE if anything listed. */
- return count > 0;
+lib_list_in_object_alternate(sc_gameref_t game,
+ sc_int container, sc_bool is_described) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object, count, trail;
+
+ /* List out the objects contained in this object. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ /* Contained? */
+ if (gs_object_position(game, object) == OBJ_IN_OBJECT
+ && gs_object_parent(game, object) == container) {
+ if (count > 0) {
+ if (count == 1) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ } else
+ pf_buffer_string(filter, ", ");
+
+ /* Print out the current list object. */
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object(game, trail);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, trail,
+ " is inside ",
+ " are inside "));
+ } else {
+ pf_buffer_string(filter, " and ");
+ lib_print_object(game, trail);
+ pf_buffer_string(filter, " are inside ");
+ }
+
+ /* Print out the container. */
+ lib_print_object_np(game, container);
+ pf_buffer_character(filter, '.');
+ }
+
+ /* Return TRUE if anything listed. */
+ return count > 0;
}
@@ -3323,45 +3015,40 @@ lib_list_in_object_alternate (sc_gameref_t game,
* but it's almost certainly wrong. Or, at minimum, incomplete.
*/
static sc_bool
-lib_list_in_object (sc_gameref_t game, sc_int container, sc_bool is_described)
-{
- sc_bool use_alternate_format = FALSE;
+lib_list_in_object(sc_gameref_t game, sc_int container, sc_bool is_described) {
+ sc_bool use_alternate_format = FALSE;
- /*
- * Switch if the object is static and part of an NPC or the player, or if
- * the count of contained objects in a dynamic container is exactly one.
- */
- if (obj_is_static (game, container))
- {
- sc_int object_position;
+ /*
+ * Switch if the object is static and part of an NPC or the player, or if
+ * the count of contained objects in a dynamic container is exactly one.
+ */
+ if (obj_is_static(game, container)) {
+ sc_int object_position;
- object_position = gs_object_position (game, container);
+ object_position = gs_object_position(game, container);
- if (object_position == OBJ_PART_NPC || object_position == OBJ_PART_PLAYER)
- use_alternate_format = TRUE;
- }
- else
- {
- sc_int object, count;
+ if (object_position == OBJ_PART_NPC || object_position == OBJ_PART_PLAYER)
+ use_alternate_format = TRUE;
+ } else {
+ sc_int object, count;
- count = 0;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_IN_OBJECT
- && gs_object_parent (game, object) == container)
- count++;
- if (count > 1)
- break;
- }
+ count = 0;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_IN_OBJECT
+ && gs_object_parent(game, object) == container)
+ count++;
+ if (count > 1)
+ break;
+ }
- if (count == 1)
- use_alternate_format = TRUE;
- }
+ if (count == 1)
+ use_alternate_format = TRUE;
+ }
- /* List contained objects using the selected handler. */
- return use_alternate_format
- ? lib_list_in_object_alternate (game, container, is_described)
- : lib_list_in_object_normal (game, container, is_described);
+ /* List contained objects using the selected handler. */
+ return use_alternate_format
+ ? lib_list_in_object_alternate(game, container, is_described)
+ : lib_list_in_object_normal(game, container, is_described);
}
@@ -3371,66 +3058,56 @@ lib_list_in_object (sc_gameref_t game, sc_int container, sc_bool is_described)
* List the objects on a given surface object.
*/
static sc_bool
-lib_list_on_object (sc_gameref_t game, sc_int supporter, sc_bool is_described)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object, count, trail;
-
- /* List out the objects standing on this object. */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- /* Standing on? */
- if (gs_object_position (game, object) == OBJ_ON_OBJECT
- && gs_object_parent (game, object) == supporter)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- }
- else
- pf_buffer_string (filter, ", ");
-
- /* Print out the current list object. */
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object (game, trail);
- pf_buffer_string (filter,
- lib_select_plurality (game, trail,
- " is on ",
- " are on "));
- }
- else
- {
- pf_buffer_string (filter, " and ");
- lib_print_object (game, trail);
- pf_buffer_string (filter, " are on ");
- }
-
- /* Print out the surface. */
- lib_print_object_np (game, supporter);
- pf_buffer_character (filter, '.');
- }
-
- /* Return TRUE if anything listed. */
- return count > 0;
+lib_list_on_object(sc_gameref_t game, sc_int supporter, sc_bool is_described) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object, count, trail;
+
+ /* List out the objects standing on this object. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ /* Standing on? */
+ if (gs_object_position(game, object) == OBJ_ON_OBJECT
+ && gs_object_parent(game, object) == supporter) {
+ if (count > 0) {
+ if (count == 1) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ } else
+ pf_buffer_string(filter, ", ");
+
+ /* Print out the current list object. */
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object(game, trail);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, trail,
+ " is on ",
+ " are on "));
+ } else {
+ pf_buffer_string(filter, " and ");
+ lib_print_object(game, trail);
+ pf_buffer_string(filter, " are on ");
+ }
+
+ /* Print out the surface. */
+ lib_print_object_np(game, supporter);
+ pf_buffer_character(filter, '.');
+ }
+
+ /* Return TRUE if anything listed. */
+ return count > 0;
}
@@ -3440,47 +3117,42 @@ lib_list_on_object (sc_gameref_t game, sc_int supporter, sc_bool is_described)
* Describe the state of a stateful object.
*/
static sc_bool
-lib_list_object_state (sc_gameref_t game, sc_int object, sc_bool is_described)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_bool is_statussed;
- sc_char *state;
-
- /* Get object statefulness. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "CurrentState";
- is_statussed = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
-
- /* Ensure this is a stateful object. */
- if (is_statussed)
- {
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object, " is ", " are "));
-
- /* Add object state string. */
- state = obj_state_name (game, object);
- if (state)
- {
- pf_buffer_string (filter, state);
- sc_free (state);
- pf_buffer_string (filter, ".");
- }
- else
- {
- sc_error ("lib_list_object_state: invalid object state\n");
- pf_buffer_string (filter, "[invalid state].");
- }
- }
-
- /* Return TRUE if a state was printed. */
- return is_statussed;
+lib_list_object_state(sc_gameref_t game, sc_int object, sc_bool is_described) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_bool is_statussed;
+ sc_char *state;
+
+ /* Get object statefulness. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "CurrentState";
+ is_statussed = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+
+ /* Ensure this is a stateful object. */
+ if (is_statussed) {
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object, " is ", " are "));
+
+ /* Add object state string. */
+ state = obj_state_name(game, object);
+ if (state) {
+ pf_buffer_string(filter, state);
+ sc_free(state);
+ pf_buffer_string(filter, ".");
+ } else {
+ sc_error("lib_list_object_state: invalid object state\n");
+ pf_buffer_string(filter, "[invalid state].");
+ }
+ }
+
+ /* Return TRUE if a state was printed. */
+ return is_statussed;
}
@@ -3490,133 +3162,125 @@ lib_list_object_state (sc_gameref_t game, sc_int object, sc_bool is_described)
* Show the long description of the most recently referenced object.
*/
sc_bool
-lib_cmd_examine_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int object, task, openness;
- sc_bool is_described, is_statussed, is_mentioned, is_ambiguous, should_be;
- const sc_char *description, *resource;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "examine", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Begin assuming no description printed. */
- is_described = FALSE;
-
- /*
- * Get selection task and expected state; for the expected task state, FALSE
- * indicates task completed, TRUE not completed.
- */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Task";
- task = prop_get_integer (bundle, "I<-sis", vt_key) - 1;
- vt_key[2].string = "TaskNotDone";
- should_be = !prop_get_boolean (bundle, "B<-sis", vt_key);
-
- /* Select either the main or the alternate description. */
- if (task >= 0 && gs_task_done (game, task) == should_be)
- {
- vt_key[2].string = "AltDesc";
- resource = "Res2";
- }
- else
- {
- vt_key[2].string = "Description";
- resource = "Res1";
- }
-
- /* Print the description, or a default response. */
- description = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (description))
- {
- pf_buffer_string (filter, description);
- is_described |= TRUE;
- }
-
- /* Handle any associated resource. */
- vt_key[2].string = resource;
- res_handle_resource (game, "sis", vt_key);
-
- /* If the object is openable, print its openness state. */
- openness = gs_object_openness (game, object);
- switch (openness)
- {
- case OBJ_OPEN:
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is open.", " are open."));
- is_described |= TRUE;
- break;
-
- case OBJ_CLOSED:
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is closed.", " are closed."));
- is_described |= TRUE;
- break;
-
- case OBJ_LOCKED:
- if (is_described)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is locked.", " are locked."));
- is_described |= TRUE;
- break;
-
- default:
- break;
- }
-
- /* Add any extra details for stateful objects. */
- vt_key[1].integer = object;
- vt_key[2].string = "CurrentState";
- is_statussed = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- if (is_statussed)
- {
- vt_key[2].string = "StateListed";
- is_mentioned = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (is_mentioned)
- is_described |= lib_list_object_state (game, object, is_described);
- }
-
- /* For open container objects, list out what's in them. */
- if (obj_is_container (game, object) && openness <= OBJ_OPEN)
- is_described |= lib_list_in_object (game, object, is_described);
-
- /* For surface objects, list out what's on them. */
- if (obj_is_surface (game, object))
- is_described |= lib_list_on_object (game, object, is_described);
-
- /* If nothing yet said, print a default response. */
- if (!is_described)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You see nothing special about ",
- "I see nothing special about ",
- "%player% sees nothing special about "));
- lib_print_object_np (game, object);
- pf_buffer_character (filter, '.');
- }
-
- pf_buffer_character (filter, '\n');
- return TRUE;
+lib_cmd_examine_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int object, task, openness;
+ sc_bool is_described, is_statussed, is_mentioned, is_ambiguous, should_be;
+ const sc_char *description, *resource;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "examine", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Begin assuming no description printed. */
+ is_described = FALSE;
+
+ /*
+ * Get selection task and expected state; for the expected task state, FALSE
+ * indicates task completed, TRUE not completed.
+ */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Task";
+ task = prop_get_integer(bundle, "I<-sis", vt_key) - 1;
+ vt_key[2].string = "TaskNotDone";
+ should_be = !prop_get_boolean(bundle, "B<-sis", vt_key);
+
+ /* Select either the main or the alternate description. */
+ if (task >= 0 && gs_task_done(game, task) == should_be) {
+ vt_key[2].string = "AltDesc";
+ resource = "Res2";
+ } else {
+ vt_key[2].string = "Description";
+ resource = "Res1";
+ }
+
+ /* Print the description, or a default response. */
+ description = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(description)) {
+ pf_buffer_string(filter, description);
+ is_described |= TRUE;
+ }
+
+ /* Handle any associated resource. */
+ vt_key[2].string = resource;
+ res_handle_resource(game, "sis", vt_key);
+
+ /* If the object is openable, print its openness state. */
+ openness = gs_object_openness(game, object);
+ switch (openness) {
+ case OBJ_OPEN:
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is open.", " are open."));
+ is_described |= TRUE;
+ break;
+
+ case OBJ_CLOSED:
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is closed.", " are closed."));
+ is_described |= TRUE;
+ break;
+
+ case OBJ_LOCKED:
+ if (is_described)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is locked.", " are locked."));
+ is_described |= TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Add any extra details for stateful objects. */
+ vt_key[1].integer = object;
+ vt_key[2].string = "CurrentState";
+ is_statussed = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ if (is_statussed) {
+ vt_key[2].string = "StateListed";
+ is_mentioned = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (is_mentioned)
+ is_described |= lib_list_object_state(game, object, is_described);
+ }
+
+ /* For open container objects, list out what's in them. */
+ if (obj_is_container(game, object) && openness <= OBJ_OPEN)
+ is_described |= lib_list_in_object(game, object, is_described);
+
+ /* For surface objects, list out what's on them. */
+ if (obj_is_surface(game, object))
+ is_described |= lib_list_on_object(game, object, is_described);
+
+ /* If nothing yet said, print a default response. */
+ if (!is_described) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You see nothing special about ",
+ "I see nothing special about ",
+ "%player% sees nothing special about "));
+ lib_print_object_np(game, object);
+ pf_buffer_character(filter, '.');
+ }
+
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -3631,32 +3295,30 @@ lib_cmd_examine_object (sc_gameref_t game)
* its own buffer; testing the return value shows which happened.
*/
static sc_bool *
-lib_save_object_references (sc_gameref_t game, sc_bool buffer[], sc_int length)
-{
- sc_int required, available;
- sc_bool *references;
+lib_save_object_references(sc_gameref_t game, sc_bool buffer[], sc_int length) {
+ sc_int required, available;
+ sc_bool *references;
- /*
- * Calculate the required bytes for references, and then either allocate or
- * use the buffer supplied.
- */
- required = gs_object_count (game) * sizeof (*references);
- available = length * sizeof (buffer[0]);
- references = required > available ? (sc_bool *)sc_malloc (required) : buffer;
+ /*
+ * Calculate the required bytes for references, and then either allocate or
+ * use the buffer supplied.
+ */
+ required = gs_object_count(game) * sizeof(*references);
+ available = length * sizeof(buffer[0]);
+ references = required > available ? (sc_bool *)sc_malloc(required) : buffer;
- /* Copy over references from the game, and return the saved copy. */
- memcpy (references, game->object_references, required);
- return references;
+ /* Copy over references from the game, and return the saved copy. */
+ memcpy(references, game->object_references, required);
+ return references;
}
static void
-lib_restore_object_references (sc_gameref_t game, const sc_bool references[])
-{
- sc_int bytes;
+lib_restore_object_references(sc_gameref_t game, const sc_bool references[]) {
+ sc_int bytes;
- /* Calculate the bytes in the references array, and copy back to the game. */
- bytes = gs_object_count (game) * sizeof (references[0]);
- memcpy (game->object_references, references, bytes);
+ /* Calculate the bytes in the references array, and copy back to the game. */
+ bytes = gs_object_count(game) * sizeof(references[0]);
+ memcpy(game->object_references, references, bytes);
}
@@ -3671,148 +3333,134 @@ lib_restore_object_references (sc_gameref_t game, const sc_bool references[])
* makes "take/pick up/put down" work with a game's overridden get/drop.
*/
static sc_bool
-lib_try_game_command_common (sc_gameref_t game,
- const sc_char *verb, sc_int object,
- const sc_char *preposition,
- sc_int associate,
- sc_bool is_associate_object,
- sc_bool is_associate_npc)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_char buffer[LIB_ALLOCATION_AVOIDANCE_SIZE];
- sc_bool references_buffer[LIB_ALLOCATION_AVOIDANCE_SIZE];
- const sc_char *prefix, *name;
- sc_char *command;
- sc_bool *references, status;
- assert (!is_associate_object || !is_associate_npc);
-
- /* Save the game's references, for restore later on. */
- references = lib_save_object_references (game, references_buffer,
- LIB_ALLOCATION_AVOIDANCE_SIZE);
-
- /* Get the addressed object's prefix and main name. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- /* Construct and try for game commands with a standard verb. */
- if (is_associate_object || is_associate_npc)
- {
- const sc_char *associate_prefix, *associate_name;
- sc_int required;
-
- /* Get the associate's prefix and main name. */
- if (is_associate_object)
- {
- vt_key[0].string = "Objects";
- vt_key[1].integer = associate;
- vt_key[2].string = "Prefix";
- associate_prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Short";
- associate_name = prop_get_string (bundle, "S<-sis", vt_key);
- }
- else
- {
- assert (is_associate_npc);
- vt_key[0].string = "NPCs";
- vt_key[1].integer = associate;
- vt_key[2].string = "Prefix";
- associate_prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Name";
- associate_name = prop_get_string (bundle, "S<-sis", vt_key);
- }
-
- assert (preposition);
- required = strlen (verb) + strlen (prefix) + strlen (name)
- + strlen (preposition) + strlen (associate_prefix)
- + strlen (associate_name) + 6;
- command = required > (sc_int) sizeof (buffer)
- ? (sc_char *)sc_malloc (required) : buffer;
-
- /*
- * Try the command with and without prefixes on both the target object
- * and the associate.
- */
- sprintf (command, "%s %s %s %s %s %s", verb,
- prefix, name, preposition, associate_prefix, associate_name);
- status = run_game_task_commands (game, command);
- if (!status)
- {
- sprintf (command, "%s %s %s %s %s",
- verb, prefix, name, preposition, associate_name);
- status = run_game_task_commands (game, command);
- }
- if (!status)
- {
- sprintf (command, "%s %s %s %s %s",
- verb, name, preposition, associate_prefix, associate_name);
- status = run_game_task_commands (game, command);
- }
- if (!status)
- {
- sprintf (command, "%s %s %s %s",
- verb, name, preposition, associate_name);
- status = run_game_task_commands (game, command);
- }
- }
- else
- {
- sc_int required;
-
- required = strlen (verb) + strlen (prefix) + strlen (name) + 3;
- command = required > (sc_int) sizeof (buffer)
- ? (sc_char *)sc_malloc (required) : buffer;
-
- /* Try the command with and without prefixes on the addressed object. */
- sprintf (command, "%s %s %s", verb, prefix, name);
- status = run_game_task_commands (game, command);
- if (!status)
- {
- sprintf (command, "%s %s", verb, name);
- status = run_game_task_commands (game, command);
- }
- }
-
- /* Restore the game object references back to their state on entry. */
- lib_restore_object_references (game, references);
-
- /* Free any allocations, and return the game command status. */
- if (command != buffer)
- sc_free (command);
- if (references != references_buffer)
- sc_free (references);
- return status;
+lib_try_game_command_common(sc_gameref_t game,
+ const sc_char *verb, sc_int object,
+ const sc_char *preposition,
+ sc_int associate,
+ sc_bool is_associate_object,
+ sc_bool is_associate_npc) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_char buffer[LIB_ALLOCATION_AVOIDANCE_SIZE];
+ sc_bool references_buffer[LIB_ALLOCATION_AVOIDANCE_SIZE];
+ const sc_char *prefix, *name;
+ sc_char *command;
+ sc_bool *references, status;
+ assert(!is_associate_object || !is_associate_npc);
+
+ /* Save the game's references, for restore later on. */
+ references = lib_save_object_references(game, references_buffer,
+ LIB_ALLOCATION_AVOIDANCE_SIZE);
+
+ /* Get the addressed object's prefix and main name. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ /* Construct and try for game commands with a standard verb. */
+ if (is_associate_object || is_associate_npc) {
+ const sc_char *associate_prefix, *associate_name;
+ sc_int required;
+
+ /* Get the associate's prefix and main name. */
+ if (is_associate_object) {
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = associate;
+ vt_key[2].string = "Prefix";
+ associate_prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Short";
+ associate_name = prop_get_string(bundle, "S<-sis", vt_key);
+ } else {
+ assert(is_associate_npc);
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = associate;
+ vt_key[2].string = "Prefix";
+ associate_prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Name";
+ associate_name = prop_get_string(bundle, "S<-sis", vt_key);
+ }
+
+ assert(preposition);
+ required = strlen(verb) + strlen(prefix) + strlen(name)
+ + strlen(preposition) + strlen(associate_prefix)
+ + strlen(associate_name) + 6;
+ command = required > (sc_int) sizeof(buffer)
+ ? (sc_char *)sc_malloc(required) : buffer;
+
+ /*
+ * Try the command with and without prefixes on both the target object
+ * and the associate.
+ */
+ sprintf(command, "%s %s %s %s %s %s", verb,
+ prefix, name, preposition, associate_prefix, associate_name);
+ status = run_game_task_commands(game, command);
+ if (!status) {
+ sprintf(command, "%s %s %s %s %s",
+ verb, prefix, name, preposition, associate_name);
+ status = run_game_task_commands(game, command);
+ }
+ if (!status) {
+ sprintf(command, "%s %s %s %s %s",
+ verb, name, preposition, associate_prefix, associate_name);
+ status = run_game_task_commands(game, command);
+ }
+ if (!status) {
+ sprintf(command, "%s %s %s %s",
+ verb, name, preposition, associate_name);
+ status = run_game_task_commands(game, command);
+ }
+ } else {
+ sc_int required;
+
+ required = strlen(verb) + strlen(prefix) + strlen(name) + 3;
+ command = required > (sc_int) sizeof(buffer)
+ ? (sc_char *)sc_malloc(required) : buffer;
+
+ /* Try the command with and without prefixes on the addressed object. */
+ sprintf(command, "%s %s %s", verb, prefix, name);
+ status = run_game_task_commands(game, command);
+ if (!status) {
+ sprintf(command, "%s %s", verb, name);
+ status = run_game_task_commands(game, command);
+ }
+ }
+
+ /* Restore the game object references back to their state on entry. */
+ lib_restore_object_references(game, references);
+
+ /* Free any allocations, and return the game command status. */
+ if (command != buffer)
+ sc_free(command);
+ if (references != references_buffer)
+ sc_free(references);
+ return status;
}
static sc_bool
-lib_try_game_command_short (sc_gameref_t game,
- const sc_char *verb, sc_int object)
-{
- return lib_try_game_command_common (game, verb, object,
- NULL, -1, FALSE, FALSE);
+lib_try_game_command_short(sc_gameref_t game,
+ const sc_char *verb, sc_int object) {
+ return lib_try_game_command_common(game, verb, object,
+ NULL, -1, FALSE, FALSE);
}
static sc_bool
-lib_try_game_command_with_object (sc_gameref_t game,
- const sc_char *verb, sc_int object,
- const sc_char *preposition,
- sc_int other_object)
-{
- return lib_try_game_command_common (game, verb, object,
- preposition, other_object, TRUE, FALSE);
+lib_try_game_command_with_object(sc_gameref_t game,
+ const sc_char *verb, sc_int object,
+ const sc_char *preposition,
+ sc_int other_object) {
+ return lib_try_game_command_common(game, verb, object,
+ preposition, other_object, TRUE, FALSE);
}
static sc_bool
-lib_try_game_command_with_npc (sc_gameref_t game,
- const sc_char *verb, sc_int object,
- const sc_char *preposition, sc_int npc)
-{
- return lib_try_game_command_common (game, verb, object,
- preposition, npc, FALSE, TRUE);
+lib_try_game_command_with_npc(sc_gameref_t game,
+ const sc_char *verb, sc_int object,
+ const sc_char *preposition, sc_int npc) {
+ return lib_try_game_command_common(game, verb, object,
+ preposition, npc, FALSE, TRUE);
}
@@ -3825,41 +3473,36 @@ lib_try_game_command_with_npc (sc_gameref_t game,
* but there appear to be more following it.
*/
static sc_bool
-lib_parse_next_object (sc_gameref_t game, const sc_char *verb,
- sc_bool (*resolver) (sc_gameref_t, sc_int, sc_int),
- sc_int resolver_arg,
- sc_int *object,
- sc_bool *are_more_objects, sc_bool *is_ambiguous)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_char *list;
- sc_bool is_matched;
-
- /* Look for "object" or "object and ...", and set match and more flags. */
- list = var_get_ref_text (vars);
- if (uip_match ("%object%", list, game))
- {
- *are_more_objects = FALSE;
- is_matched = TRUE;
- }
- else if (uip_match ("%object% and %text%", list, game))
- {
- *are_more_objects = TRUE;
- is_matched = TRUE;
- }
- else
- is_matched = FALSE;
-
- /* If we extracted an object from referenced text, disambiguate. */
- if (is_matched)
- *object = lib_disambiguate_object_extended (game, verb,
- resolver, resolver_arg,
- is_ambiguous);
- else
- *is_ambiguous = FALSE;
-
- /* Return TRUE if we matched anything. */
- return is_matched;
+lib_parse_next_object(sc_gameref_t game, const sc_char *verb,
+ sc_bool(*resolver)(sc_gameref_t, sc_int, sc_int),
+ sc_int resolver_arg,
+ sc_int *object,
+ sc_bool *are_more_objects, sc_bool *is_ambiguous) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_char *list;
+ sc_bool is_matched;
+
+ /* Look for "object" or "object and ...", and set match and more flags. */
+ list = var_get_ref_text(vars);
+ if (uip_match("%object%", list, game)) {
+ *are_more_objects = FALSE;
+ is_matched = TRUE;
+ } else if (uip_match("%object% and %text%", list, game)) {
+ *are_more_objects = TRUE;
+ is_matched = TRUE;
+ } else
+ is_matched = FALSE;
+
+ /* If we extracted an object from referenced text, disambiguate. */
+ if (is_matched)
+ *object = lib_disambiguate_object_extended(game, verb,
+ resolver, resolver_arg,
+ is_ambiguous);
+ else
+ *is_ambiguous = FALSE;
+
+ /* Return TRUE if we matched anything. */
+ return is_matched;
}
@@ -3871,101 +3514,93 @@ lib_parse_next_object (sc_gameref_t game, const sc_char *verb,
* the multiple objects in the game's multiple_references.
*/
static sc_bool
-lib_parse_multiple_objects (sc_gameref_t game, const sc_char *verb,
- sc_bool (*resolver) (sc_gameref_t, sc_int, sc_int),
- sc_int resolver_arg,
- sc_int *count)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int count_, object;
- sc_bool are_more_objects, is_ambiguous;
-
- /* Initialize variables to avoid gcc warnings. */
- object = -1;
- are_more_objects = FALSE;
-
- /* Clear all current multiple object references, and the count. */
- gs_clear_multiple_references (game);
- count_ = 0;
-
- /*
- * Parse the first object from the list. If we get nothing here, return
- * FALSE if it didn't look like a multiple object list, TRUE if ambiguous.
- * Beyond here, we always return TRUE, since after this point _something_
- * looked believable...
- */
- if (!lib_parse_next_object (game, verb,
- resolver, resolver_arg,
- &object, &are_more_objects, &is_ambiguous))
- return FALSE;
- else if (object == -1)
- {
- if (is_ambiguous)
- {
- /*
- * Return TRUE, with zero count, to cause caller to return. We get
- * here if the first parsed object was ambiguous. In this case,
- * the disambiguation has printed a message, so we want our caller
- * to simply return TRUE to indicate that the command was handled,
- * albeit not fully successfully.
- */
- *count = count_;
- return TRUE;
- }
- else
- {
- /*
- * No object matched after disambiguation, so return FALSE to have
- * our caller ignore the command.
- */
- return FALSE;
- }
- }
-
- /* Mark this first object as referenced in the return array. */
- game->multiple_references[object] = TRUE;
- count_++;
-
- /* Now parse each additional object from the list. */
- while (are_more_objects)
- {
- sc_int last_object;
-
- /*
- * If no next object, leave the loop. If no disambiguation message
- * then it was probably garble, so print a message for that case. We
- * also catch repeated objects here.
- */
- last_object = object;
- if (!lib_parse_next_object (game, verb,
- resolver, resolver_arg,
- &object, &are_more_objects, &is_ambiguous)
- || object == -1
- || game->multiple_references[object])
- {
- if (!is_ambiguous)
- {
- pf_buffer_string (filter,
- "I only understood you as far as wanting to ");
- pf_buffer_string (filter, verb);
- pf_buffer_character (filter, ' ');
- lib_print_object_np (game, last_object);
- pf_buffer_string (filter, ".\n");
- }
-
- /* Zero count to indicate an error somewhere in the list. */
- count_ = 0;
- break;
- }
-
- /* Mark the object as referenced in the return array. */
- game->multiple_references[object] = TRUE;
- count_++;
- }
-
- /* We found at least enough of an object list to say we matched. */
- *count = count_;
- return TRUE;
+lib_parse_multiple_objects(sc_gameref_t game, const sc_char *verb,
+ sc_bool(*resolver)(sc_gameref_t, sc_int, sc_int),
+ sc_int resolver_arg,
+ sc_int *count) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int count_, object;
+ sc_bool are_more_objects, is_ambiguous;
+
+ /* Initialize variables to avoid gcc warnings. */
+ object = -1;
+ are_more_objects = FALSE;
+
+ /* Clear all current multiple object references, and the count. */
+ gs_clear_multiple_references(game);
+ count_ = 0;
+
+ /*
+ * Parse the first object from the list. If we get nothing here, return
+ * FALSE if it didn't look like a multiple object list, TRUE if ambiguous.
+ * Beyond here, we always return TRUE, since after this point _something_
+ * looked believable...
+ */
+ if (!lib_parse_next_object(game, verb,
+ resolver, resolver_arg,
+ &object, &are_more_objects, &is_ambiguous))
+ return FALSE;
+ else if (object == -1) {
+ if (is_ambiguous) {
+ /*
+ * Return TRUE, with zero count, to cause caller to return. We get
+ * here if the first parsed object was ambiguous. In this case,
+ * the disambiguation has printed a message, so we want our caller
+ * to simply return TRUE to indicate that the command was handled,
+ * albeit not fully successfully.
+ */
+ *count = count_;
+ return TRUE;
+ } else {
+ /*
+ * No object matched after disambiguation, so return FALSE to have
+ * our caller ignore the command.
+ */
+ return FALSE;
+ }
+ }
+
+ /* Mark this first object as referenced in the return array. */
+ game->multiple_references[object] = TRUE;
+ count_++;
+
+ /* Now parse each additional object from the list. */
+ while (are_more_objects) {
+ sc_int last_object;
+
+ /*
+ * If no next object, leave the loop. If no disambiguation message
+ * then it was probably garble, so print a message for that case. We
+ * also catch repeated objects here.
+ */
+ last_object = object;
+ if (!lib_parse_next_object(game, verb,
+ resolver, resolver_arg,
+ &object, &are_more_objects, &is_ambiguous)
+ || object == -1
+ || game->multiple_references[object]) {
+ if (!is_ambiguous) {
+ pf_buffer_string(filter,
+ "I only understood you as far as wanting to ");
+ pf_buffer_string(filter, verb);
+ pf_buffer_character(filter, ' ');
+ lib_print_object_np(game, last_object);
+ pf_buffer_string(filter, ".\n");
+ }
+
+ /* Zero count to indicate an error somewhere in the list. */
+ count_ = 0;
+ break;
+ }
+
+ /* Mark the object as referenced in the return array. */
+ game->multiple_references[object] = TRUE;
+ count_++;
+ }
+
+ /* We found at least enough of an object list to say we matched. */
+ *count = count_;
+ return TRUE;
}
@@ -3978,80 +3613,70 @@ lib_parse_multiple_objects (sc_gameref_t game, const sc_char *verb,
* The first is inclusive, the second exclusive.
*/
static sc_int
-lib_apply_multiple_filter (sc_gameref_t game,
- sc_bool (*filter) (sc_gameref_t, sc_int, sc_int),
- sc_int filter_arg, sc_int *references)
-{
- sc_int count, object, references_;
-
- /* Clear all object references initially. */
- gs_clear_object_references (game);
-
- /*
- * Find objects included by the filter, and transfer the reference of each
- * from the multiple references into standard references.
- */
- count = 0;
- references_ = references ? *references : 0;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (filter (game, object, filter_arg))
- {
- /* Transfer the reference. */
- if (game->multiple_references[object])
- {
- game->object_references[object] = TRUE;
- count++;
- game->multiple_references[object] = FALSE;
- references_--;
- }
- }
- }
-
- /* Copy back the updated reference count, return count. */
- if (references)
- *references = references_;
- return count;
+lib_apply_multiple_filter(sc_gameref_t game,
+ sc_bool(*filter)(sc_gameref_t, sc_int, sc_int),
+ sc_int filter_arg, sc_int *references) {
+ sc_int count, object, references_;
+
+ /* Clear all object references initially. */
+ gs_clear_object_references(game);
+
+ /*
+ * Find objects included by the filter, and transfer the reference of each
+ * from the multiple references into standard references.
+ */
+ count = 0;
+ references_ = references ? *references : 0;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (filter(game, object, filter_arg)) {
+ /* Transfer the reference. */
+ if (game->multiple_references[object]) {
+ game->object_references[object] = TRUE;
+ count++;
+ game->multiple_references[object] = FALSE;
+ references_--;
+ }
+ }
+ }
+
+ /* Copy back the updated reference count, return count. */
+ if (references)
+ *references = references_;
+ return count;
}
static sc_int
-lib_apply_except_filter (sc_gameref_t game,
- sc_bool (*filter) (sc_gameref_t, sc_int, sc_int),
- sc_int filter_arg, sc_int *references)
-{
- sc_int count, object, references_;
-
- /* Clear all object references initially. */
- gs_clear_object_references (game);
-
- /*
- * Find objects included by the filter, and transfer the reference of each
- * from the multiple references into standard references.
- */
- count = 0;
- references_ = references ? *references : 0;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (filter (game, object, filter_arg))
- {
- /* If excepted, remove from exceptions, else add to references. */
- if (game->multiple_references[object])
- {
- game->multiple_references[object] = FALSE;
- references_--;
- }
- else
- {
- game->object_references[object] = TRUE;
- count++;
- }
- }
- }
-
- /* Copy back the updated reference count, return count. */
- if (references)
- *references = references_;
- return count;
+lib_apply_except_filter(sc_gameref_t game,
+ sc_bool(*filter)(sc_gameref_t, sc_int, sc_int),
+ sc_int filter_arg, sc_int *references) {
+ sc_int count, object, references_;
+
+ /* Clear all object references initially. */
+ gs_clear_object_references(game);
+
+ /*
+ * Find objects included by the filter, and transfer the reference of each
+ * from the multiple references into standard references.
+ */
+ count = 0;
+ references_ = references ? *references : 0;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (filter(game, object, filter_arg)) {
+ /* If excepted, remove from exceptions, else add to references. */
+ if (game->multiple_references[object]) {
+ game->multiple_references[object] = FALSE;
+ references_--;
+ } else {
+ game->object_references[object] = TRUE;
+ count++;
+ }
+ }
+ }
+
+ /* Copy back the updated reference count, return count. */
+ if (references)
+ *references = references_;
+ return count;
}
@@ -4061,49 +3686,46 @@ lib_apply_except_filter (sc_gameref_t game,
* Display player weight and size limits and amounts currently carried.
*/
sc_bool
-lib_cmd_count (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int index_, size, weight;
- sc_char buffer[32];
-
- /* Sum sizes for objects currently held or worn by player. */
- size = 0;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (gs_object_position (game, index_) == OBJ_HELD_PLAYER
- || gs_object_position (game, index_) == OBJ_WORN_PLAYER)
- size += obj_get_size (game, index_);
- }
-
- /* Sum weights for objects currently held or worn by player. */
- weight = 0;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (gs_object_position (game, index_) == OBJ_HELD_PLAYER
- || gs_object_position (game, index_) == OBJ_WORN_PLAYER)
- weight += obj_get_weight (game, index_);
- }
-
- /* Print the player limits and amounts used. */
- pf_buffer_string (filter, "Size: You have ");
- sprintf (buffer, "%ld", size);
- pf_buffer_string (filter, buffer);
- pf_buffer_string (filter, ". The most you can hold is ");
- sprintf (buffer, "%ld", obj_get_player_size_limit (game));
- pf_buffer_string (filter, buffer);
- pf_buffer_string (filter, ".\n");
-
- pf_buffer_string (filter, "Weight: You have ");
- sprintf (buffer, "%ld", weight);
- pf_buffer_string (filter, buffer);
- pf_buffer_string (filter, ". The most you can hold is ");
- sprintf (buffer, "%ld", obj_get_player_weight_limit (game));
- pf_buffer_string (filter, buffer);
- pf_buffer_string (filter, ".\n");
-
- game->is_admin = TRUE;
- return TRUE;
+lib_cmd_count(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int index_, size, weight;
+ sc_char buffer[32];
+
+ /* Sum sizes for objects currently held or worn by player. */
+ size = 0;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (gs_object_position(game, index_) == OBJ_HELD_PLAYER
+ || gs_object_position(game, index_) == OBJ_WORN_PLAYER)
+ size += obj_get_size(game, index_);
+ }
+
+ /* Sum weights for objects currently held or worn by player. */
+ weight = 0;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (gs_object_position(game, index_) == OBJ_HELD_PLAYER
+ || gs_object_position(game, index_) == OBJ_WORN_PLAYER)
+ weight += obj_get_weight(game, index_);
+ }
+
+ /* Print the player limits and amounts used. */
+ pf_buffer_string(filter, "Size: You have ");
+ sprintf(buffer, "%ld", size);
+ pf_buffer_string(filter, buffer);
+ pf_buffer_string(filter, ". The most you can hold is ");
+ sprintf(buffer, "%ld", obj_get_player_size_limit(game));
+ pf_buffer_string(filter, buffer);
+ pf_buffer_string(filter, ".\n");
+
+ pf_buffer_string(filter, "Weight: You have ");
+ sprintf(buffer, "%ld", weight);
+ pf_buffer_string(filter, buffer);
+ pf_buffer_string(filter, ". The most you can hold is ");
+ sprintf(buffer, "%ld", obj_get_player_weight_limit(game));
+ pf_buffer_string(filter, buffer);
+ pf_buffer_string(filter, ".\n");
+
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -4113,29 +3735,27 @@ lib_cmd_count (sc_gameref_t game)
* Return TRUE if the given object is too heavy for the player to carry.
*/
static sc_bool
-lib_object_too_heavy (sc_gameref_t game, sc_int object, sc_bool *is_portable)
-{
- sc_int player_limit, index_, weight, object_weight;
+lib_object_too_heavy(sc_gameref_t game, sc_int object, sc_bool *is_portable) {
+ sc_int player_limit, index_, weight, object_weight;
- /* Get the player limit and the given object weight. */
- player_limit = obj_get_player_weight_limit (game);
- object_weight = obj_get_weight (game, object);
+ /* Get the player limit and the given object weight. */
+ player_limit = obj_get_player_weight_limit(game);
+ object_weight = obj_get_weight(game, object);
- /* Sum weights for objects currently held or worn by player. */
- weight = 0;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (gs_object_position (game, index_) == OBJ_HELD_PLAYER
- || gs_object_position (game, index_) == OBJ_WORN_PLAYER)
- weight += obj_get_weight (game, index_);
- }
+ /* Sum weights for objects currently held or worn by player. */
+ weight = 0;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (gs_object_position(game, index_) == OBJ_HELD_PLAYER
+ || gs_object_position(game, index_) == OBJ_WORN_PLAYER)
+ weight += obj_get_weight(game, index_);
+ }
- /* If requested, return object portability. */
- if (is_portable)
- *is_portable = !(object_weight > player_limit);
+ /* If requested, return object portability. */
+ if (is_portable)
+ *is_portable = !(object_weight > player_limit);
- /* Return TRUE if the new object exceeds limit. */
- return weight + object_weight > player_limit;
+ /* Return TRUE if the new object exceeds limit. */
+ return weight + object_weight > player_limit;
}
@@ -4145,29 +3765,27 @@ lib_object_too_heavy (sc_gameref_t game, sc_int object, sc_bool *is_portable)
* Return TRUE if the given object is too large for the player to carry.
*/
static sc_bool
-lib_object_too_large (sc_gameref_t game, sc_int object, sc_bool *is_portable)
-{
- sc_int player_limit, index_, size, object_size;
+lib_object_too_large(sc_gameref_t game, sc_int object, sc_bool *is_portable) {
+ sc_int player_limit, index_, size, object_size;
- /* Get the player limit and the given object size. */
- player_limit = obj_get_player_size_limit (game);
- object_size = obj_get_size (game, object);
+ /* Get the player limit and the given object size. */
+ player_limit = obj_get_player_size_limit(game);
+ object_size = obj_get_size(game, object);
- /* Sum sizes for objects currently held or worn by player. */
- size = 0;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (gs_object_position (game, index_) == OBJ_HELD_PLAYER
- || gs_object_position (game, index_) == OBJ_WORN_PLAYER)
- size += obj_get_size (game, index_);
- }
+ /* Sum sizes for objects currently held or worn by player. */
+ size = 0;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (gs_object_position(game, index_) == OBJ_HELD_PLAYER
+ || gs_object_position(game, index_) == OBJ_WORN_PLAYER)
+ size += obj_get_size(game, index_);
+ }
- /* If requested, return object portability. */
- if (is_portable)
- *is_portable = !(object_size > player_limit);
+ /* If requested, return object portability. */
+ if (is_portable)
+ *is_portable = !(object_size > player_limit);
- /* Return TRUE if the new object exceeds limit. */
- return size + object_size > player_limit;
+ /* Return TRUE if the new object exceeds limit. */
+ return size + object_size > player_limit;
}
@@ -4177,22 +3795,21 @@ lib_object_too_large (sc_gameref_t game, sc_int object, sc_bool *is_portable)
* Reject attempts to take an npc.
*/
sc_bool
-lib_cmd_take_npc (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int npc;
- sc_bool is_ambiguous;
+lib_cmd_take_npc(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int npc;
+ sc_bool is_ambiguous;
- /* Get the referenced npc, and if none, consider complete. */
- npc = lib_disambiguate_npc (game, "take", &is_ambiguous);
- if (npc == -1)
- return is_ambiguous;
+ /* Get the referenced npc, and if none, consider complete. */
+ npc = lib_disambiguate_npc(game, "take", &is_ambiguous);
+ if (npc == -1)
+ return is_ambiguous;
- /* Reject this attempt. */
- pf_buffer_string (filter, "I don't think ");
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " would appreciate being handled.\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter, "I don't think ");
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " would appreciate being handled.\n");
+ return TRUE;
}
@@ -4207,624 +3824,545 @@ lib_cmd_take_npc (sc_gameref_t game)
* deemed not actionable are flagged in multiple_references.
*/
static void
-lib_take_backend_common (sc_gameref_t game, sc_int associate,
- sc_bool is_associate_object, sc_bool is_associate_npc)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object_count, object, count, trail, total, npc;
- sc_int too_heavy, too_large;
- sc_bool too_heavy_portable, too_large_portable, has_printed;
- assert (!is_associate_object || !is_associate_npc);
-
- /* Initialize our notions of anything exceeding player capacity. */
- too_heavy_portable = too_large_portable = FALSE;
- too_large = too_heavy = -1;
-
- /*
- * Try game commands for all referenced objects first. If any succeed,
- * remove that reference from the list. At the same time, filter out and
- * flag any object that takes us over the player's capacity. We report
- * only the first.
- */
- has_printed = FALSE;
- object_count = gs_object_count (game);
- for (object = 0; object < object_count; object++)
- {
- sc_bool status;
-
- if (!game->object_references[object])
- continue;
-
- /*
- * If the object is inside or on something already held by the player,
- * capacity checks are meaningless.
- */
- if (!((gs_object_position (game, object) == OBJ_IN_OBJECT
- || gs_object_position (game, object) == OBJ_ON_OBJECT)
- && obj_indirectly_held_by_player (game,
- gs_object_parent (game, object))))
- {
- sc_bool is_portable;
-
- /*
- * See if the object takes us beyond capacity. If it does and it's
- * the first of its kind, note it and continue.
- */
- if (lib_object_too_heavy (game, object, &is_portable))
- {
- if (too_heavy == -1)
- {
- too_heavy = object;
- too_heavy_portable = is_portable;
- }
- game->object_references[object] = FALSE;
- continue;
- }
- if (lib_object_too_large (game, object, &is_portable))
- {
- if (too_large == -1)
- {
- too_large = object;
- too_large_portable = is_portable;
- }
- game->object_references[object] = FALSE;
- continue;
- }
- }
-
- /* Now try for a game command, using the associate if supplied. */
- if (is_associate_object)
- status = lib_try_game_command_with_object (game, "get",
- object, "from", associate);
- else if (is_associate_npc)
- status = lib_try_game_command_with_npc (game, "get",
- object, "from", associate);
- else
- status = lib_try_game_command_short (game, "get", object);
- if (status)
- {
- game->object_references[object] = FALSE;
- has_printed = TRUE;
- }
- }
-
- /*
- * We attempt acquisition of get-able objects here only for cases where
- * there is either no associate, or where the associate is an object. If
- * the associate is an NPC, we're going to refuse all acquisitions later
- * on, by forcing object references.
- */
- total = 0;
- if (!is_associate_npc)
- {
- sc_int parent, start, limit;
-
- /*
- * Attempt to acquire each remaining get-able object in turn, looping
- * on each possible parent object in turn, with an initial parent of
- * -1 for objects not contained or supported.
- *
- * If we're dealing with only objects from a known container or
- * supporter, eliminate all but one iteration of the parent search.
- */
- start = is_associate_object ? associate : -1;
- limit = is_associate_object ? associate : object_count - 1;
-
- for (parent = start; parent <= limit; parent++)
- {
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- sc_bool is_portable;
-
- if (!game->object_references[object])
- continue;
-
- /*
- * If parent is -1, ignore contained objects, otherwise ignore
- * objects not contained, or if contained, not contained by the
- * current parent.
- */
- if (parent == -1)
- {
- if (gs_object_position (game, object) == OBJ_IN_OBJECT
- || gs_object_position (game, object) == OBJ_ON_OBJECT)
- continue;
- }
- else
- {
- if (!(gs_object_position (game, object) == OBJ_IN_OBJECT
- || gs_object_position (game, object) == OBJ_ON_OBJECT))
- continue;
- if (gs_object_parent (game, object) != parent)
- continue;
- }
-
- /*
- * Here we have to repeat capacity checks. As objects are
- * acquired more and more of the player's capacity gets used up.
- * This means a check directly before each acquisition.
- */
- if (parent == -1
- || !obj_indirectly_held_by_player (game, parent))
- {
- if (lib_object_too_heavy (game, object, &is_portable))
- {
- if (too_heavy == -1)
- {
- too_heavy = object;
- too_heavy_portable = is_portable;
- }
- continue;
- }
- if (lib_object_too_large (game, object, &is_portable))
- {
- if (too_large == -1)
- {
- too_large = object;
- too_large_portable = is_portable;
- }
- continue;
- }
- }
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, total == 0 ? "\n" : " ");
- if (parent == -1)
- pf_buffer_string (filter,
- lib_select_response (game,
- "You pick up ",
- "I pick up ",
- "%player% picks up "));
- else
- pf_buffer_string (filter,
- lib_select_response (game,
- "You take ",
- "I take ",
- "%player% takes "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- gs_object_player_get (game, object);
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, total == 0 ? "\n" : " ");
- if (parent == -1)
- pf_buffer_string (filter,
- lib_select_response (game,
- "You pick up ",
- "I pick up ",
- "%player% picks up "));
- else
- pf_buffer_string (filter,
- lib_select_response (game,
- "You take ",
- "I take ",
- "%player% takes "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- if (parent != -1)
- {
- pf_buffer_string (filter, " from ");
- lib_print_object_np (game, parent);
- }
- pf_buffer_character (filter, '.');
- }
- total += count;
- has_printed |= count > 0;
- }
- }
-
- /*
- * If we ran out of capacity, either in weight or in size, print the
- * details. Note that we currently only report the first object of any
- * type to go over capacity.
- */
- if (too_heavy != -1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, too_heavy);
- pf_buffer_string (filter,
- lib_select_plurality (game, too_heavy, " is", " are"));
- pf_buffer_string (filter,
- lib_select_response (game,
- " too heavy for you to carry",
- " too heavy for me to carry",
- " too heavy for %player% to carry"));
- if (too_heavy_portable)
- pf_buffer_string (filter, " at the moment");
- pf_buffer_character (filter, '.');
- has_printed |= TRUE;
- }
- else if (too_large != -1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "Your hands are full",
- "My hands are full",
- "%player%'s hands are full"));
- if (too_large_portable)
- pf_buffer_string (filter, " at the moment");
- pf_buffer_character (filter, '.');
- has_printed |= TRUE;
- }
-
- /*
- * Note any remaining multiple references left out of the take operation.
- * This is some workload...
- *
- * First, deal with the case where we have an associated object.
- */
- if (is_associate_object)
- {
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER
- || gs_object_position (game, object) == OBJ_WORN_PLAYER)
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, trail);
- }
- else
- pf_buffer_string (filter, ", ");
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, trail);
- pf_buffer_string (filter,
- lib_select_plurality (game, trail,
- " is not ",
- " are not "));
- }
- else
- {
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_string (filter, " are not ");
- }
- if (obj_is_container (game, associate))
- {
- pf_buffer_string (filter, "in ");
- if (obj_is_surface (game, associate))
- pf_buffer_string (filter, "or on ");
- }
- else
- pf_buffer_string (filter, "on ");
- lib_print_object_np (game, associate);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
- }
-
- /*
- * Now, deal with the case where we have an associated NPC. Once this
- * case is handled, we can force the object references so that the code
- * that follows on from here will report errors taking all objects.
- *
- * Note that this means that we can never successfully take an object
- * from an NPC; that'll have to happen via a game's own commands.
- */
- if (is_associate_npc)
- {
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (gs_object_position (game, object) == OBJ_PART_NPC)
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_npc_np (game, associate);
- pf_buffer_string (filter, " is not carrying ");
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_npc_np (game, associate);
- pf_buffer_string (filter, " is not carrying ");
- lib_print_object_np (game, trail);
- }
- else
- {
- pf_buffer_string (filter, " or ");
- lib_print_object_np (game, trail);
- }
- pf_buffer_character (filter, '!');
- }
- has_printed |= count > 0;
-
- /*
- * Merge any remaining object references into multiple references,
- * so that succeeding code complains about the inability to acquire
- * these objects.
- */
- for (object = 0; object < object_count; object++)
- {
- game->multiple_references[object] |= game->object_references[object];
- game->object_references[object] = FALSE;
- }
- }
-
- /*
- * The remainder of this routine is common error reporting for both object
- * and NPC associates (and also for no associates).
- */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (gs_object_position (game, object) != OBJ_HELD_PLAYER)
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You've already got ",
- "I've already got ",
- "%player% already has "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You've already got ",
- "I've already got ",
- "%player% already has "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '!');
- }
- has_printed |= count > 0;
-
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (gs_object_position (game, object) != OBJ_WORN_PLAYER)
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You're already wearing ",
- "I'm already wearing ",
- "%player% is already wearing "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You're already wearing ",
- "I'm already wearing ",
- "%player% is already wearing "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '!');
- }
- has_printed |= count > 0;
-
- for (npc = 0; npc < gs_npc_count (game); npc++)
- {
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (gs_object_position (game, object) != OBJ_HELD_NPC
- && gs_object_position (game, object) != OBJ_WORN_NPC)
- continue;
- if (gs_object_parent (game, object) != npc)
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_npc_np (game, gs_object_parent (game, trail));
- pf_buffer_string (filter,
- lib_select_response (game,
- " refuses to give you ",
- " refuses to give me ",
- " refuses to give %player% "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_npc_np (game, gs_object_parent (game, trail));
- pf_buffer_string (filter,
- lib_select_response (game,
- " refuses to give you ",
- " refuses to give me ",
- " refuses to give %player% "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '!');
- }
- has_printed |= count > 0;
- }
-
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't take ",
- "I can't take ",
- "%player% can't take "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't take ",
- "I can't take ",
- "%player% can't take "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '!');
- }
+lib_take_backend_common(sc_gameref_t game, sc_int associate,
+ sc_bool is_associate_object, sc_bool is_associate_npc) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object_count, object, count, trail, total, npc;
+ sc_int too_heavy, too_large;
+ sc_bool too_heavy_portable, too_large_portable, has_printed;
+ assert(!is_associate_object || !is_associate_npc);
+
+ /* Initialize our notions of anything exceeding player capacity. */
+ too_heavy_portable = too_large_portable = FALSE;
+ too_large = too_heavy = -1;
+
+ /*
+ * Try game commands for all referenced objects first. If any succeed,
+ * remove that reference from the list. At the same time, filter out and
+ * flag any object that takes us over the player's capacity. We report
+ * only the first.
+ */
+ has_printed = FALSE;
+ object_count = gs_object_count(game);
+ for (object = 0; object < object_count; object++) {
+ sc_bool status;
+
+ if (!game->object_references[object])
+ continue;
+
+ /*
+ * If the object is inside or on something already held by the player,
+ * capacity checks are meaningless.
+ */
+ if (!((gs_object_position(game, object) == OBJ_IN_OBJECT
+ || gs_object_position(game, object) == OBJ_ON_OBJECT)
+ && obj_indirectly_held_by_player(game,
+ gs_object_parent(game, object)))) {
+ sc_bool is_portable;
+
+ /*
+ * See if the object takes us beyond capacity. If it does and it's
+ * the first of its kind, note it and continue.
+ */
+ if (lib_object_too_heavy(game, object, &is_portable)) {
+ if (too_heavy == -1) {
+ too_heavy = object;
+ too_heavy_portable = is_portable;
+ }
+ game->object_references[object] = FALSE;
+ continue;
+ }
+ if (lib_object_too_large(game, object, &is_portable)) {
+ if (too_large == -1) {
+ too_large = object;
+ too_large_portable = is_portable;
+ }
+ game->object_references[object] = FALSE;
+ continue;
+ }
+ }
+
+ /* Now try for a game command, using the associate if supplied. */
+ if (is_associate_object)
+ status = lib_try_game_command_with_object(game, "get",
+ object, "from", associate);
+ else if (is_associate_npc)
+ status = lib_try_game_command_with_npc(game, "get",
+ object, "from", associate);
+ else
+ status = lib_try_game_command_short(game, "get", object);
+ if (status) {
+ game->object_references[object] = FALSE;
+ has_printed = TRUE;
+ }
+ }
+
+ /*
+ * We attempt acquisition of get-able objects here only for cases where
+ * there is either no associate, or where the associate is an object. If
+ * the associate is an NPC, we're going to refuse all acquisitions later
+ * on, by forcing object references.
+ */
+ total = 0;
+ if (!is_associate_npc) {
+ sc_int parent, start, limit;
+
+ /*
+ * Attempt to acquire each remaining get-able object in turn, looping
+ * on each possible parent object in turn, with an initial parent of
+ * -1 for objects not contained or supported.
+ *
+ * If we're dealing with only objects from a known container or
+ * supporter, eliminate all but one iteration of the parent search.
+ */
+ start = is_associate_object ? associate : -1;
+ limit = is_associate_object ? associate : object_count - 1;
+
+ for (parent = start; parent <= limit; parent++) {
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ sc_bool is_portable;
+
+ if (!game->object_references[object])
+ continue;
+
+ /*
+ * If parent is -1, ignore contained objects, otherwise ignore
+ * objects not contained, or if contained, not contained by the
+ * current parent.
+ */
+ if (parent == -1) {
+ if (gs_object_position(game, object) == OBJ_IN_OBJECT
+ || gs_object_position(game, object) == OBJ_ON_OBJECT)
+ continue;
+ } else {
+ if (!(gs_object_position(game, object) == OBJ_IN_OBJECT
+ || gs_object_position(game, object) == OBJ_ON_OBJECT))
+ continue;
+ if (gs_object_parent(game, object) != parent)
+ continue;
+ }
+
+ /*
+ * Here we have to repeat capacity checks. As objects are
+ * acquired more and more of the player's capacity gets used up.
+ * This means a check directly before each acquisition.
+ */
+ if (parent == -1
+ || !obj_indirectly_held_by_player(game, parent)) {
+ if (lib_object_too_heavy(game, object, &is_portable)) {
+ if (too_heavy == -1) {
+ too_heavy = object;
+ too_heavy_portable = is_portable;
+ }
+ continue;
+ }
+ if (lib_object_too_large(game, object, &is_portable)) {
+ if (too_large == -1) {
+ too_large = object;
+ too_large_portable = is_portable;
+ }
+ continue;
+ }
+ }
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, total == 0 ? "\n" : " ");
+ if (parent == -1)
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You pick up ",
+ "I pick up ",
+ "%player% picks up "));
+ else
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You take ",
+ "I take ",
+ "%player% takes "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ gs_object_player_get(game, object);
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, total == 0 ? "\n" : " ");
+ if (parent == -1)
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You pick up ",
+ "I pick up ",
+ "%player% picks up "));
+ else
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You take ",
+ "I take ",
+ "%player% takes "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ if (parent != -1) {
+ pf_buffer_string(filter, " from ");
+ lib_print_object_np(game, parent);
+ }
+ pf_buffer_character(filter, '.');
+ }
+ total += count;
+ has_printed |= count > 0;
+ }
+ }
+
+ /*
+ * If we ran out of capacity, either in weight or in size, print the
+ * details. Note that we currently only report the first object of any
+ * type to go over capacity.
+ */
+ if (too_heavy != -1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, too_heavy);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, too_heavy, " is", " are"));
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " too heavy for you to carry",
+ " too heavy for me to carry",
+ " too heavy for %player% to carry"));
+ if (too_heavy_portable)
+ pf_buffer_string(filter, " at the moment");
+ pf_buffer_character(filter, '.');
+ has_printed |= TRUE;
+ } else if (too_large != -1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "Your hands are full",
+ "My hands are full",
+ "%player%'s hands are full"));
+ if (too_large_portable)
+ pf_buffer_string(filter, " at the moment");
+ pf_buffer_character(filter, '.');
+ has_printed |= TRUE;
+ }
+
+ /*
+ * Note any remaining multiple references left out of the take operation.
+ * This is some workload...
+ *
+ * First, deal with the case where we have an associated object.
+ */
+ if (is_associate_object) {
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER
+ || gs_object_position(game, object) == OBJ_WORN_PLAYER)
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, trail);
+ } else
+ pf_buffer_string(filter, ", ");
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, trail);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, trail,
+ " is not ",
+ " are not "));
+ } else {
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_string(filter, " are not ");
+ }
+ if (obj_is_container(game, associate)) {
+ pf_buffer_string(filter, "in ");
+ if (obj_is_surface(game, associate))
+ pf_buffer_string(filter, "or on ");
+ } else
+ pf_buffer_string(filter, "on ");
+ lib_print_object_np(game, associate);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+ }
+
+ /*
+ * Now, deal with the case where we have an associated NPC. Once this
+ * case is handled, we can force the object references so that the code
+ * that follows on from here will report errors taking all objects.
+ *
+ * Note that this means that we can never successfully take an object
+ * from an NPC; that'll have to happen via a game's own commands.
+ */
+ if (is_associate_npc) {
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (gs_object_position(game, object) == OBJ_PART_NPC)
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, associate);
+ pf_buffer_string(filter, " is not carrying ");
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, associate);
+ pf_buffer_string(filter, " is not carrying ");
+ lib_print_object_np(game, trail);
+ } else {
+ pf_buffer_string(filter, " or ");
+ lib_print_object_np(game, trail);
+ }
+ pf_buffer_character(filter, '!');
+ }
+ has_printed |= count > 0;
+
+ /*
+ * Merge any remaining object references into multiple references,
+ * so that succeeding code complains about the inability to acquire
+ * these objects.
+ */
+ for (object = 0; object < object_count; object++) {
+ game->multiple_references[object] |= game->object_references[object];
+ game->object_references[object] = FALSE;
+ }
+ }
+
+ /*
+ * The remainder of this routine is common error reporting for both object
+ * and NPC associates (and also for no associates).
+ */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (gs_object_position(game, object) != OBJ_HELD_PLAYER)
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You've already got ",
+ "I've already got ",
+ "%player% already has "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You've already got ",
+ "I've already got ",
+ "%player% already has "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '!');
+ }
+ has_printed |= count > 0;
+
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (gs_object_position(game, object) != OBJ_WORN_PLAYER)
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You're already wearing ",
+ "I'm already wearing ",
+ "%player% is already wearing "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You're already wearing ",
+ "I'm already wearing ",
+ "%player% is already wearing "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '!');
+ }
+ has_printed |= count > 0;
+
+ for (npc = 0; npc < gs_npc_count(game); npc++) {
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (gs_object_position(game, object) != OBJ_HELD_NPC
+ && gs_object_position(game, object) != OBJ_WORN_NPC)
+ continue;
+ if (gs_object_parent(game, object) != npc)
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, gs_object_parent(game, trail));
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " refuses to give you ",
+ " refuses to give me ",
+ " refuses to give %player% "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, gs_object_parent(game, trail));
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " refuses to give you ",
+ " refuses to give me ",
+ " refuses to give %player% "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '!');
+ }
+ has_printed |= count > 0;
+ }
+
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't take ",
+ "I can't take ",
+ "%player% can't take "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't take ",
+ "I can't take ",
+ "%player% can't take "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '!');
+ }
}
@@ -4837,21 +4375,18 @@ lib_take_backend_common (sc_gameref_t game, sc_int associate,
* the plain "take" handlers, or the "take from <something>" handlers.
*/
static void
-lib_take_backend (sc_gameref_t game)
-{
- lib_take_backend_common (game, -1, FALSE, FALSE);
+lib_take_backend(sc_gameref_t game) {
+ lib_take_backend_common(game, -1, FALSE, FALSE);
}
static void
-lib_take_from_object_backend (sc_gameref_t game, sc_int associate)
-{
- lib_take_backend_common (game, associate, TRUE, FALSE);
+lib_take_from_object_backend(sc_gameref_t game, sc_int associate) {
+ lib_take_backend_common(game, associate, TRUE, FALSE);
}
static void
-lib_take_from_npc_backend (sc_gameref_t game, sc_int associate)
-{
- lib_take_backend_common (game, associate, FALSE, TRUE);
+lib_take_from_npc_backend(sc_gameref_t game, sc_int associate) {
+ lib_take_backend_common(game, associate, FALSE, TRUE);
}
@@ -4863,32 +4398,30 @@ lib_take_from_npc_backend (sc_gameref_t game, sc_int associate)
* Returns TRUE if an object may be acquired, FALSE otherwise.
*/
static sc_bool
-lib_take_filter (sc_gameref_t game, sc_int object, sc_int unused)
-{
- assert (unused == -1);
-
- /*
- * To be take-able, an object must be visible in the room, not static,
- * and not already held or worn by the player or an NPC.
- */
- return obj_indirectly_in_room (game, object, gs_playerroom (game))
- && !obj_is_static (game, object)
- && !(gs_object_position (game, object) == OBJ_HELD_PLAYER
- || gs_object_position (game, object) == OBJ_WORN_PLAYER)
- && !(gs_object_position (game, object) == OBJ_HELD_NPC
- || gs_object_position (game, object) == OBJ_WORN_NPC);
+lib_take_filter(sc_gameref_t game, sc_int object, sc_int unused) {
+ assert(unused == -1);
+
+ /*
+ * To be take-able, an object must be visible in the room, not static,
+ * and not already held or worn by the player or an NPC.
+ */
+ return obj_indirectly_in_room(game, object, gs_playerroom(game))
+ && !obj_is_static(game, object)
+ && !(gs_object_position(game, object) == OBJ_HELD_PLAYER
+ || gs_object_position(game, object) == OBJ_WORN_PLAYER)
+ && !(gs_object_position(game, object) == OBJ_HELD_NPC
+ || gs_object_position(game, object) == OBJ_WORN_NPC);
}
static sc_bool
-lib_take_not_associated_filter (sc_gameref_t game,
- sc_int object, sc_int unused)
-{
- assert (unused == -1);
+lib_take_not_associated_filter(sc_gameref_t game,
+ sc_int object, sc_int unused) {
+ assert(unused == -1);
- /* In addition to other checks, the object may not be in or on an object. */
- return lib_take_filter (game, object, -1)
- && !(gs_object_position (game, object) == OBJ_ON_OBJECT
- || gs_object_position (game, object) == OBJ_IN_OBJECT);
+ /* In addition to other checks, the object may not be in or on an object. */
+ return lib_take_filter(game, object, -1)
+ && !(gs_object_position(game, object) == OBJ_ON_OBJECT
+ || gs_object_position(game, object) == OBJ_IN_OBJECT);
}
@@ -4898,24 +4431,23 @@ lib_take_not_associated_filter (sc_gameref_t game,
* Attempt to take all objects currently visible to the player.
*/
sc_bool
-lib_cmd_take_all (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects;
+lib_cmd_take_all(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects;
- /* Filter objects into references, then handle with the backend. */
- gs_set_multiple_references (game);
- objects = lib_apply_multiple_filter (game,
- lib_take_not_associated_filter, -1,
- NULL);
- gs_clear_multiple_references (game);
- if (objects > 0)
- lib_take_backend (game);
- else
- pf_buffer_string (filter, "There is nothing to pick up here.");
+ /* Filter objects into references, then handle with the backend. */
+ gs_set_multiple_references(game);
+ objects = lib_apply_multiple_filter(game,
+ lib_take_not_associated_filter, -1,
+ NULL);
+ gs_clear_multiple_references(game);
+ if (objects > 0)
+ lib_take_backend(game);
+ else
+ pf_buffer_string(filter, "There is nothing to pick up here.");
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -4926,35 +4458,33 @@ lib_cmd_take_all (sc_gameref_t game)
* in %text%.
*/
sc_bool
-lib_cmd_take_except_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects, references;
+lib_cmd_take_except_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects, references;
- /* Parse the multiple objects list to find leave target objects. */
- if (!lib_parse_multiple_objects (game, "leave",
- lib_take_not_associated_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find leave target objects. */
+ if (!lib_parse_multiple_objects(game, "leave",
+ lib_take_not_associated_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_except_filter (game,
- lib_take_not_associated_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_take_backend (game);
- else
- {
- if (objects == 0)
- pf_buffer_string (filter, "There is nothing else to pick up here.");
- else
- pf_buffer_string (filter, "There is nothing to pick up here.");
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_except_filter(game,
+ lib_take_not_associated_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_take_backend(game);
+ else {
+ if (objects == 0)
+ pf_buffer_string(filter, "There is nothing else to pick up here.");
+ else
+ pf_buffer_string(filter, "There is nothing to pick up here.");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -4964,30 +4494,29 @@ lib_cmd_take_except_multiple (sc_gameref_t game)
* Take all objects currently available to the player and listed in %text%.
*/
sc_bool
-lib_cmd_take_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects, references;
+lib_cmd_take_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects, references;
- /* Parse the multiple objects list to find take target objects. */
- if (!lib_parse_multiple_objects (game, "take",
- lib_take_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find take target objects. */
+ if (!lib_parse_multiple_objects(game, "take",
+ lib_take_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_multiple_filter (game,
- lib_take_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_take_backend (game);
- else
- pf_buffer_string (filter, "There is nothing to pick up here.");
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_multiple_filter(game,
+ lib_take_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_take_backend(game);
+ else
+ pf_buffer_string(filter, "There is nothing to pick up here.");
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -4998,16 +4527,15 @@ lib_cmd_take_multiple (sc_gameref_t game)
* Returns TRUE if an object may be acquired, FALSE otherwise.
*/
static sc_bool
-lib_take_from_filter (sc_gameref_t game, sc_int object, sc_int associate)
-{
- /*
- * To be take-able, an object must be either inside or on the specified
- * object.
- */
- return (gs_object_position (game, object) == OBJ_IN_OBJECT
- || gs_object_position (game, object) == OBJ_ON_OBJECT)
- && !obj_is_static (game, object)
- && gs_object_parent (game, object) == associate;
+lib_take_from_filter(sc_gameref_t game, sc_int object, sc_int associate) {
+ /*
+ * To be take-able, an object must be either inside or on the specified
+ * object.
+ */
+ return (gs_object_position(game, object) == OBJ_IN_OBJECT
+ || gs_object_position(game, object) == OBJ_ON_OBJECT)
+ && !obj_is_static(game, object)
+ && gs_object_parent(game, object) == associate;
}
@@ -5018,70 +4546,57 @@ lib_take_from_filter (sc_gameref_t game, sc_int object, sc_int associate)
* supporter object.
*/
static void
-lib_take_from_empty (sc_gameref_t game, sc_int associate, sc_bool is_except)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- if (obj_is_container (game, associate) && obj_is_surface (game, associate))
- {
- if (gs_object_openness (game, associate) <= OBJ_OPEN)
- {
- if (is_except)
- pf_buffer_string (filter, "There is nothing else in or on ");
- else
- pf_buffer_string (filter, "There is nothing in or on ");
- lib_print_object_np (game, associate);
- pf_buffer_character (filter, '.');
- }
- else
- {
- if (is_except)
- pf_buffer_string (filter, "There is nothing else on ");
- else
- pf_buffer_string (filter, "There is nothing on ");
- lib_print_object_np (game, associate);
- if (gs_object_openness (game, associate) == OBJ_LOCKED)
- pf_buffer_string (filter, " and it is locked.");
- else
- pf_buffer_string (filter, " and it is closed.");
- }
- }
- else
- {
- if (obj_is_container (game, associate))
- {
- if (gs_object_openness (game, associate) <= OBJ_OPEN)
- {
- if (is_except)
- pf_buffer_string (filter, "There is nothing else inside ");
- else
- pf_buffer_string (filter, "There is nothing inside ");
- lib_print_object_np (game, associate);
- pf_buffer_character (filter, '.');
- }
- else
- {
- pf_new_sentence (filter);
- lib_print_object_np (game, associate);
- pf_buffer_string (filter,
- lib_select_plurality (game, associate,
- " is ", " are "));
- if (gs_object_openness (game, associate) == OBJ_LOCKED)
- pf_buffer_string (filter, "locked.");
- else
- pf_buffer_string (filter, "closed.");
- }
- }
- else
- {
- if (is_except)
- pf_buffer_string (filter, "There is nothing else on ");
- else
- pf_buffer_string (filter, "There is nothing on ");
- lib_print_object_np (game, associate);
- pf_buffer_character (filter, '.');
- }
- }
+lib_take_from_empty(sc_gameref_t game, sc_int associate, sc_bool is_except) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ if (obj_is_container(game, associate) && obj_is_surface(game, associate)) {
+ if (gs_object_openness(game, associate) <= OBJ_OPEN) {
+ if (is_except)
+ pf_buffer_string(filter, "There is nothing else in or on ");
+ else
+ pf_buffer_string(filter, "There is nothing in or on ");
+ lib_print_object_np(game, associate);
+ pf_buffer_character(filter, '.');
+ } else {
+ if (is_except)
+ pf_buffer_string(filter, "There is nothing else on ");
+ else
+ pf_buffer_string(filter, "There is nothing on ");
+ lib_print_object_np(game, associate);
+ if (gs_object_openness(game, associate) == OBJ_LOCKED)
+ pf_buffer_string(filter, " and it is locked.");
+ else
+ pf_buffer_string(filter, " and it is closed.");
+ }
+ } else {
+ if (obj_is_container(game, associate)) {
+ if (gs_object_openness(game, associate) <= OBJ_OPEN) {
+ if (is_except)
+ pf_buffer_string(filter, "There is nothing else inside ");
+ else
+ pf_buffer_string(filter, "There is nothing inside ");
+ lib_print_object_np(game, associate);
+ pf_buffer_character(filter, '.');
+ } else {
+ pf_new_sentence(filter);
+ lib_print_object_np(game, associate);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, associate,
+ " is ", " are "));
+ if (gs_object_openness(game, associate) == OBJ_LOCKED)
+ pf_buffer_string(filter, "locked.");
+ else
+ pf_buffer_string(filter, "closed.");
+ }
+ } else {
+ if (is_except)
+ pf_buffer_string(filter, "There is nothing else on ");
+ else
+ pf_buffer_string(filter, "There is nothing on ");
+ lib_print_object_np(game, associate);
+ pf_buffer_character(filter, '.');
+ }
+ }
}
@@ -5091,39 +4606,36 @@ lib_take_from_empty (sc_gameref_t game, sc_int associate, sc_bool is_except)
* Validate the supporter requested in "take from" commands.
*/
static sc_bool
-lib_take_from_is_valid (sc_gameref_t game, sc_int associate)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- /* Disallow emptying non-container/non-surface objects. */
- if (!(obj_is_container (game, associate)
- || obj_is_surface (game, associate)))
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't take anything from ",
- "I can't take anything from ",
- "%player% can't take anything from "));
- lib_print_object_np (game, associate);
- pf_buffer_string (filter, ".\n");
- return FALSE;
- }
-
- /* If object is a container, and is closed, reject now. */
- if (obj_is_container (game, associate)
- && gs_object_openness (game, associate) > OBJ_OPEN)
- {
- pf_new_sentence (filter);
- lib_print_object_np (game, associate);
- pf_buffer_string (filter,
- lib_select_plurality (game, associate,
- " is closed.\n",
- " are closed.\n"));
- return FALSE;
- }
-
- /* Associate is a valid target for "take from". */
- return TRUE;
+lib_take_from_is_valid(sc_gameref_t game, sc_int associate) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ /* Disallow emptying non-container/non-surface objects. */
+ if (!(obj_is_container(game, associate)
+ || obj_is_surface(game, associate))) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't take anything from ",
+ "I can't take anything from ",
+ "%player% can't take anything from "));
+ lib_print_object_np(game, associate);
+ pf_buffer_string(filter, ".\n");
+ return FALSE;
+ }
+
+ /* If object is a container, and is closed, reject now. */
+ if (obj_is_container(game, associate)
+ && gs_object_openness(game, associate) > OBJ_OPEN) {
+ pf_new_sentence(filter);
+ lib_print_object_np(game, associate);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, associate,
+ " is closed.\n",
+ " are closed.\n"));
+ return FALSE;
+ }
+
+ /* Associate is a valid target for "take from". */
+ return TRUE;
}
@@ -5133,34 +4645,33 @@ lib_take_from_is_valid (sc_gameref_t game, sc_int associate)
* Attempt to take all objects contained in or supported by a given object.
*/
sc_bool
-lib_cmd_take_all_from (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int associate, objects;
- sc_bool is_ambiguous;
+lib_cmd_take_all_from(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int associate, objects;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- associate = lib_disambiguate_object (game, "take from", &is_ambiguous);
- if (associate == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ associate = lib_disambiguate_object(game, "take from", &is_ambiguous);
+ if (associate == -1)
+ return is_ambiguous;
- /* Validate the associate object to take from. */
- if (!lib_take_from_is_valid (game, associate))
- return TRUE;
+ /* Validate the associate object to take from. */
+ if (!lib_take_from_is_valid(game, associate))
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- gs_set_multiple_references (game);
- objects = lib_apply_multiple_filter (game,
- lib_take_from_filter, associate,
- NULL);
- gs_clear_multiple_references (game);
- if (objects > 0)
- lib_take_from_object_backend (game, associate);
- else
- lib_take_from_empty (game, associate, FALSE);
+ /* Filter objects into references, then handle with the backend. */
+ gs_set_multiple_references(game);
+ objects = lib_apply_multiple_filter(game,
+ lib_take_from_filter, associate,
+ NULL);
+ gs_clear_multiple_references(game);
+ if (objects > 0)
+ lib_take_from_object_backend(game, associate);
+ else
+ lib_take_from_empty(game, associate, FALSE);
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5171,50 +4682,48 @@ lib_cmd_take_all_from (sc_gameref_t game)
* those listed in %text%.
*/
sc_bool
-lib_cmd_take_from_except_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int associate, objects, references;
- sc_bool is_ambiguous;
+lib_cmd_take_from_except_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int associate, objects, references;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- associate = lib_disambiguate_object (game, "take from", &is_ambiguous);
- if (associate == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ associate = lib_disambiguate_object(game, "take from", &is_ambiguous);
+ if (associate == -1)
+ return is_ambiguous;
- /* Parse the multiple objects list to find leave target objects. */
- if (!lib_parse_multiple_objects (game, "leave",
- lib_take_from_filter, associate,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find leave target objects. */
+ if (!lib_parse_multiple_objects(game, "leave",
+ lib_take_from_filter, associate,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Validate the associate object to take from. */
- if (!lib_take_from_is_valid (game, associate))
- return TRUE;
+ /* Validate the associate object to take from. */
+ if (!lib_take_from_is_valid(game, associate))
+ return TRUE;
- /* As a special case, complain about requests to retain the associate. */
- if (game->multiple_references[associate])
- {
- pf_buffer_string (filter,
- "I only understood you as far as wanting to leave ");
- lib_print_object_np (game, associate);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
+ /* As a special case, complain about requests to retain the associate. */
+ if (game->multiple_references[associate]) {
+ pf_buffer_string(filter,
+ "I only understood you as far as wanting to leave ");
+ lib_print_object_np(game, associate);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_except_filter (game,
- lib_take_from_filter, associate,
- &references);
- if (objects > 0 || references > 0)
- lib_take_from_object_backend (game, associate);
- else
- lib_take_from_empty (game, associate, TRUE);
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_except_filter(game,
+ lib_take_from_filter, associate,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_take_from_object_backend(game, associate);
+ else
+ lib_take_from_empty(game, associate, TRUE);
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5226,40 +4735,39 @@ lib_cmd_take_from_except_multiple (sc_gameref_t game)
* ers and surfaces, but it's a standard in Adrift so here it is.
*/
sc_bool
-lib_cmd_take_from_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int associate, objects, references;
- sc_bool is_ambiguous;
+lib_cmd_take_from_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int associate, objects, references;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- associate = lib_disambiguate_object (game, "take from", &is_ambiguous);
- if (associate == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ associate = lib_disambiguate_object(game, "take from", &is_ambiguous);
+ if (associate == -1)
+ return is_ambiguous;
- /* Parse the multiple objects list to find take target objects. */
- if (!lib_parse_multiple_objects (game, "take",
- lib_take_from_filter, associate,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find take target objects. */
+ if (!lib_parse_multiple_objects(game, "take",
+ lib_take_from_filter, associate,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Validate the associate object to take from. */
- if (!lib_take_from_is_valid (game, associate))
- return TRUE;
+ /* Validate the associate object to take from. */
+ if (!lib_take_from_is_valid(game, associate))
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_multiple_filter (game,
- lib_take_from_filter, associate,
- &references);
- if (objects > 0 || references > 0)
- lib_take_from_object_backend (game, associate);
- else
- lib_take_from_empty (game, associate, FALSE);
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_multiple_filter(game,
+ lib_take_from_filter, associate,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_take_from_object_backend(game, associate);
+ else
+ lib_take_from_empty(game, associate, FALSE);
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5270,16 +4778,15 @@ lib_cmd_take_from_multiple (sc_gameref_t game)
* Returns TRUE if an object may be acquired, FALSE otherwise.
*/
static sc_bool
-lib_take_from_npc_filter (sc_gameref_t game, sc_int object, sc_int associate)
-{
- /*
- * To be take-able, an object must be either held or worn by the specified
- * NPC.
- */
- return (gs_object_position (game, object) == OBJ_HELD_NPC
- || gs_object_position (game, object) == OBJ_WORN_NPC)
- && !obj_is_static (game, object)
- && gs_object_parent (game, object) == associate;
+lib_take_from_npc_filter(sc_gameref_t game, sc_int object, sc_int associate) {
+ /*
+ * To be take-able, an object must be either held or worn by the specified
+ * NPC.
+ */
+ return (gs_object_position(game, object) == OBJ_HELD_NPC
+ || gs_object_position(game, object) == OBJ_WORN_NPC)
+ && !obj_is_static(game, object)
+ && gs_object_parent(game, object) == associate;
}
@@ -5289,34 +4796,32 @@ lib_take_from_npc_filter (sc_gameref_t game, sc_int object, sc_int associate)
* Attempt to take all objects held or worn by a given NPC.
*/
sc_bool
-lib_cmd_take_all_from_npc (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int associate, objects;
- sc_bool is_ambiguous;
+lib_cmd_take_all_from_npc(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int associate, objects;
+ sc_bool is_ambiguous;
- /* Get the referenced NPC, and if none, consider complete. */
- associate = lib_disambiguate_npc (game, "take from", &is_ambiguous);
- if (associate == -1)
- return is_ambiguous;
+ /* Get the referenced NPC, and if none, consider complete. */
+ associate = lib_disambiguate_npc(game, "take from", &is_ambiguous);
+ if (associate == -1)
+ return is_ambiguous;
- /* Filter objects into references, then handle with the backend. */
- gs_set_multiple_references (game);
- objects = lib_apply_multiple_filter (game,
- lib_take_from_npc_filter, associate,
- NULL);
- gs_clear_multiple_references (game);
- if (objects > 0)
- lib_take_from_npc_backend (game, associate);
- else
- {
- pf_new_sentence (filter);
- lib_print_npc_np (game, associate);
- pf_buffer_string (filter, " is not carrying anything!");
- }
+ /* Filter objects into references, then handle with the backend. */
+ gs_set_multiple_references(game);
+ objects = lib_apply_multiple_filter(game,
+ lib_take_from_npc_filter, associate,
+ NULL);
+ gs_clear_multiple_references(game);
+ if (objects > 0)
+ lib_take_from_npc_backend(game, associate);
+ else {
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, associate);
+ pf_buffer_string(filter, " is not carrying anything!");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5327,40 +4832,38 @@ lib_cmd_take_all_from_npc (sc_gameref_t game)
* listed in %text%.
*/
sc_bool
-lib_cmd_take_from_npc_except_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int associate, objects, references;
- sc_bool is_ambiguous;
+lib_cmd_take_from_npc_except_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int associate, objects, references;
+ sc_bool is_ambiguous;
- /* Get the referenced NPC, and if none, consider complete. */
- associate = lib_disambiguate_npc (game, "take from", &is_ambiguous);
- if (associate == -1)
- return is_ambiguous;
+ /* Get the referenced NPC, and if none, consider complete. */
+ associate = lib_disambiguate_npc(game, "take from", &is_ambiguous);
+ if (associate == -1)
+ return is_ambiguous;
- /* Parse the multiple objects list to find leave target objects. */
- if (!lib_parse_multiple_objects (game, "leave",
- lib_take_from_npc_filter, associate,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find leave target objects. */
+ if (!lib_parse_multiple_objects(game, "leave",
+ lib_take_from_npc_filter, associate,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_except_filter (game,
- lib_take_from_npc_filter, associate,
- &references);
- if (objects > 0 || references > 0)
- lib_take_from_npc_backend (game, associate);
- else
- {
- pf_new_sentence (filter);
- lib_print_npc_np (game, associate);
- pf_buffer_string (filter, " is not carrying anything else!");
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_except_filter(game,
+ lib_take_from_npc_filter, associate,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_take_from_npc_backend(game, associate);
+ else {
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, associate);
+ pf_buffer_string(filter, " is not carrying anything else!");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5371,40 +4874,38 @@ lib_cmd_take_from_npc_except_multiple (sc_gameref_t game)
* in %text%.
*/
sc_bool
-lib_cmd_take_from_npc_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int associate, objects, references;
- sc_bool is_ambiguous;
+lib_cmd_take_from_npc_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int associate, objects, references;
+ sc_bool is_ambiguous;
- /* Get the referenced NPC, and if none, consider complete. */
- associate = lib_disambiguate_npc (game, "take from", &is_ambiguous);
- if (associate == -1)
- return is_ambiguous;
+ /* Get the referenced NPC, and if none, consider complete. */
+ associate = lib_disambiguate_npc(game, "take from", &is_ambiguous);
+ if (associate == -1)
+ return is_ambiguous;
- /* Parse the multiple objects list to find take target objects. */
- if (!lib_parse_multiple_objects (game, "take",
- lib_take_from_npc_filter, associate,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find take target objects. */
+ if (!lib_parse_multiple_objects(game, "take",
+ lib_take_from_npc_filter, associate,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_multiple_filter (game,
- lib_take_from_npc_filter, associate,
- &references);
- if (objects > 0 || references > 0)
- lib_take_from_npc_backend (game, associate);
- else
- {
- pf_new_sentence (filter);
- lib_print_npc_np (game, associate);
- pf_buffer_string (filter, " is not carrying anything!");
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_multiple_filter(game,
+ lib_take_from_npc_filter, associate,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_take_from_npc_backend(game, associate);
+ else {
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, associate);
+ pf_buffer_string(filter, " is not carrying anything!");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5419,126 +4920,109 @@ lib_cmd_take_from_npc_multiple (sc_gameref_t game)
* deemed not actionable are flagged in multiple_references.
*/
static void
-lib_drop_backend (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object_count, object, count, trail;
- sc_bool has_printed;
-
- /*
- * Try game commands for all referenced objects first. If any succeed,
- * remove that reference from the list.
- */
- has_printed = FALSE;
- object_count = gs_object_count (game);
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (lib_try_game_command_short (game, "drop", object))
- {
- game->object_references[object] = FALSE;
- has_printed = TRUE;
- }
- }
-
- /* Drop every object that remains referenced. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You drop ",
- "I drop ",
- "%player% drops "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- gs_object_to_room (game, object, gs_playerroom (game));
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You drop ",
- "I drop ",
- "%player% drops "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
-
- /* Note any remaining multiple references left out of the drop operation. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- }
- else
- pf_buffer_string (filter, " or ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
+lib_drop_backend(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object_count, object, count, trail;
+ sc_bool has_printed;
+
+ /*
+ * Try game commands for all referenced objects first. If any succeed,
+ * remove that reference from the list.
+ */
+ has_printed = FALSE;
+ object_count = gs_object_count(game);
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (lib_try_game_command_short(game, "drop", object)) {
+ game->object_references[object] = FALSE;
+ has_printed = TRUE;
+ }
+ }
+
+ /* Drop every object that remains referenced. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You drop ",
+ "I drop ",
+ "%player% drops "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ gs_object_to_room(game, object, gs_playerroom(game));
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You drop ",
+ "I drop ",
+ "%player% drops "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+
+ /* Note any remaining multiple references left out of the drop operation. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ } else
+ pf_buffer_string(filter, " or ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
}
@@ -5549,12 +5033,11 @@ lib_drop_backend (sc_gameref_t game)
* Returns TRUE if an object may be dropped, FALSE otherwise.
*/
static sc_bool
-lib_drop_filter (sc_gameref_t game, sc_int object, sc_int unused)
-{
- assert (unused == -1);
+lib_drop_filter(sc_gameref_t game, sc_int object, sc_int unused) {
+ assert(unused == -1);
- return !obj_is_static (game, object)
- && gs_object_position (game, object) == OBJ_HELD_PLAYER;
+ return !obj_is_static(game, object)
+ && gs_object_position(game, object) == OBJ_HELD_PLAYER;
}
@@ -5564,30 +5047,28 @@ lib_drop_filter (sc_gameref_t game, sc_int object, sc_int unused)
* Drop all objects currently held by the player.
*/
sc_bool
-lib_cmd_drop_all (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects;
+lib_cmd_drop_all(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects;
- /* Filter objects into references, then handle with the backend. */
- gs_set_multiple_references (game);
- objects = lib_apply_multiple_filter (game,
- lib_drop_filter, -1,
- NULL);
- gs_clear_multiple_references (game);
- if (objects > 0)
- lib_drop_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You're not carrying anything.",
- "I'm not carrying anything.",
- "%player%'s not carrying anything."));
- }
+ /* Filter objects into references, then handle with the backend. */
+ gs_set_multiple_references(game);
+ objects = lib_apply_multiple_filter(game,
+ lib_drop_filter, -1,
+ NULL);
+ gs_clear_multiple_references(game);
+ if (objects > 0)
+ lib_drop_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You're not carrying anything.",
+ "I'm not carrying anything.",
+ "%player%'s not carrying anything."));
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5598,39 +5079,37 @@ lib_cmd_drop_all (sc_gameref_t game)
* %text%.
*/
sc_bool
-lib_cmd_drop_except_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects, references;
+lib_cmd_drop_except_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects, references;
- /* Parse the multiple objects list to find retain target objects. */
- if (!lib_parse_multiple_objects (game, "retain",
- lib_drop_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find retain target objects. */
+ if (!lib_parse_multiple_objects(game, "retain",
+ lib_drop_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_except_filter (game,
- lib_drop_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_drop_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything",
- "I am not holding anything",
- "%player% is not holding anything"));
- if (objects == 0)
- pf_buffer_string (filter, " else");
- pf_buffer_character (filter, '.');
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_except_filter(game,
+ lib_drop_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_drop_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything",
+ "I am not holding anything",
+ "%player% is not holding anything"));
+ if (objects == 0)
+ pf_buffer_string(filter, " else");
+ pf_buffer_character(filter, '.');
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5640,36 +5119,34 @@ lib_cmd_drop_except_multiple (sc_gameref_t game)
* Drop all objects currently held by the player and listed in %text%.
*/
sc_bool
-lib_cmd_drop_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects, references;
+lib_cmd_drop_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects, references;
- /* Parse the multiple objects list to find drop target objects. */
- if (!lib_parse_multiple_objects (game, "drop",
- lib_drop_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find drop target objects. */
+ if (!lib_parse_multiple_objects(game, "drop",
+ lib_drop_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_multiple_filter (game,
- lib_drop_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_drop_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything.",
- "I am not holding anything.",
- "%player% is not holding anything."));
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_multiple_filter(game,
+ lib_drop_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_drop_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything.",
+ "I am not holding anything.",
+ "%player% is not holding anything."));
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -5680,74 +5157,70 @@ lib_cmd_drop_multiple (sc_gameref_t game)
* Attempt to give an object to an NPC.
*/
sc_bool
-lib_cmd_give_object_npc (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object, npc;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "give", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Get the referenced npc, and if none, consider complete. */
- npc = lib_disambiguate_npc (game, "give to", NULL);
- if (npc == -1)
- return TRUE;
-
- /* Reject if not holding the object offered. */
- if (gs_object_position (game, object) != OBJ_HELD_PLAYER)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You don't have ",
- "I don't have ",
- "%player% doesn't have "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, "!\n");
- return TRUE;
- }
-
- /* After all that, the npc is disinterested. */
- pf_new_sentence (filter);
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " doesn't seem interested in ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
-}
-
-sc_bool
-lib_cmd_give_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "give", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Reject if not holding the object offered. */
- if (gs_object_position (game, object) != OBJ_HELD_PLAYER)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You don't have ",
- "I don't have ",
- "%player% doesn't have "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, "!\n");
- return TRUE;
- }
-
- /* After all that, we have to ask (and shouldn't this be "to whom?"). */
- pf_buffer_string (filter, "Give ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " to who?\n");
- return TRUE;
+lib_cmd_give_object_npc(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object, npc;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "give", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Get the referenced npc, and if none, consider complete. */
+ npc = lib_disambiguate_npc(game, "give to", NULL);
+ if (npc == -1)
+ return TRUE;
+
+ /* Reject if not holding the object offered. */
+ if (gs_object_position(game, object) != OBJ_HELD_PLAYER) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You don't have ",
+ "I don't have ",
+ "%player% doesn't have "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, "!\n");
+ return TRUE;
+ }
+
+ /* After all that, the npc is disinterested. */
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " doesn't seem interested in ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_give_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "give", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Reject if not holding the object offered. */
+ if (gs_object_position(game, object) != OBJ_HELD_PLAYER) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You don't have ",
+ "I don't have ",
+ "%player% doesn't have "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, "!\n");
+ return TRUE;
+ }
+
+ /* After all that, we have to ask (and shouldn't this be "to whom?"). */
+ pf_buffer_string(filter, "Give ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " to who?\n");
+ return TRUE;
}
@@ -5761,228 +5234,197 @@ lib_cmd_give_object (sc_gameref_t game)
* deemed not actionable are flagged in multiple_references.
*/
static void
-lib_wear_backend (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object_count, object, count, trail;
- sc_bool has_printed;
-
- /*
- * Try game commands for all referenced objects first. If any succeed,
- * remove that reference from the list.
- */
- has_printed = FALSE;
- object_count = gs_object_count (game);
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (lib_try_game_command_short (game, "wear", object))
- {
- game->object_references[object] = FALSE;
- has_printed = TRUE;
- }
- }
-
- /* Wear every object referenced. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You put on ",
- "I put on ",
- "%player% puts on "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- gs_object_player_wear (game, object);
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You put on ",
- "I put on ",
- "%player% puts on "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
-
- /* Note any remaining multiple references left out of the wear operation. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (gs_object_position (game, object) != OBJ_WORN_PLAYER)
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are already wearing ",
- "I am already wearing ",
- "%player% is already wearing "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are already wearing ",
- "I am already wearing ",
- "%player% is already wearing "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
-
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER)
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- }
- else
- pf_buffer_string (filter, " or ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
-
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't wear ",
- "I can't wear ",
- "%player% can't wear "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't wear ",
- "I can't wear ",
- "%player% can't wear "));
- }
- else
- pf_buffer_string (filter, " or ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
+lib_wear_backend(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object_count, object, count, trail;
+ sc_bool has_printed;
+
+ /*
+ * Try game commands for all referenced objects first. If any succeed,
+ * remove that reference from the list.
+ */
+ has_printed = FALSE;
+ object_count = gs_object_count(game);
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (lib_try_game_command_short(game, "wear", object)) {
+ game->object_references[object] = FALSE;
+ has_printed = TRUE;
+ }
+ }
+
+ /* Wear every object referenced. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You put on ",
+ "I put on ",
+ "%player% puts on "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ gs_object_player_wear(game, object);
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You put on ",
+ "I put on ",
+ "%player% puts on "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+
+ /* Note any remaining multiple references left out of the wear operation. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (gs_object_position(game, object) != OBJ_WORN_PLAYER)
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are already wearing ",
+ "I am already wearing ",
+ "%player% is already wearing "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are already wearing ",
+ "I am already wearing ",
+ "%player% is already wearing "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER)
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ } else
+ pf_buffer_string(filter, " or ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't wear ",
+ "I can't wear ",
+ "%player% can't wear "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't wear ",
+ "I can't wear ",
+ "%player% can't wear "));
+ } else
+ pf_buffer_string(filter, " or ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
}
@@ -5993,29 +5435,27 @@ lib_wear_backend (sc_gameref_t game)
* Returns TRUE if an object may be worn, FALSE otherwise.
*/
static sc_bool
-lib_wear_filter (sc_gameref_t game, sc_int object, sc_int unused)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- assert (unused == -1);
+lib_wear_filter(sc_gameref_t game, sc_int object, sc_int unused) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ assert(unused == -1);
- /*
- * The object is wearable if the player is holding it, and it's not static
- * (static moved to player inventory by event), and if it's marked wearable
- * in properties.
- */
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER
- && !obj_is_static (game, object))
- {
- sc_vartype_t vt_key[3];
+ /*
+ * The object is wearable if the player is holding it, and it's not static
+ * (static moved to player inventory by event), and if it's marked wearable
+ * in properties.
+ */
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER
+ && !obj_is_static(game, object)) {
+ sc_vartype_t vt_key[3];
- /* Return wearability from the object properties. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Wearable";
- return prop_get_boolean (bundle, "B<-sis", vt_key);
- }
+ /* Return wearability from the object properties. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Wearable";
+ return prop_get_boolean(bundle, "B<-sis", vt_key);
+ }
- return FALSE;
+ return FALSE;
}
@@ -6025,31 +5465,29 @@ lib_wear_filter (sc_gameref_t game, sc_int object, sc_int unused)
* Wear all wearable objects currently held by the player.
*/
sc_bool
-lib_cmd_wear_all (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects;
+lib_cmd_wear_all(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects;
- /* Filter objects into references, then handle with the backend. */
- gs_set_multiple_references (game);
- objects = lib_apply_multiple_filter (game,
- lib_wear_filter, -1,
- NULL);
- gs_clear_multiple_references (game);
- if (objects > 0)
- lib_wear_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You're not carrying anything",
- "I'm not carrying anything",
- "%player%'s not carrying anything"));
- pf_buffer_string (filter, " that can be worn.");
- }
+ /* Filter objects into references, then handle with the backend. */
+ gs_set_multiple_references(game);
+ objects = lib_apply_multiple_filter(game,
+ lib_wear_filter, -1,
+ NULL);
+ gs_clear_multiple_references(game);
+ if (objects > 0)
+ lib_wear_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You're not carrying anything",
+ "I'm not carrying anything",
+ "%player%'s not carrying anything"));
+ pf_buffer_string(filter, " that can be worn.");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -6060,39 +5498,37 @@ lib_cmd_wear_all (sc_gameref_t game)
* listed in %text%.
*/
sc_bool
-lib_cmd_wear_except_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects, references;
+lib_cmd_wear_except_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects, references;
- /* Parse the multiple objects list to find retain target objects. */
- if (!lib_parse_multiple_objects (game, "retain",
- lib_wear_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find retain target objects. */
+ if (!lib_parse_multiple_objects(game, "retain",
+ lib_wear_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_except_filter (game,
- lib_wear_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_wear_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything",
- "I am not holding anything",
- "%player% is not holding anything"));
- if (objects == 0)
- pf_buffer_string (filter, " else");
- pf_buffer_string (filter, " that can be worn.");
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_except_filter(game,
+ lib_wear_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_wear_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything",
+ "I am not holding anything",
+ "%player% is not holding anything"));
+ if (objects == 0)
+ pf_buffer_string(filter, " else");
+ pf_buffer_string(filter, " that can be worn.");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -6103,37 +5539,35 @@ lib_cmd_wear_except_multiple (sc_gameref_t game)
* in %text%.
*/
sc_bool
-lib_cmd_wear_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects, references;
+lib_cmd_wear_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects, references;
- /* Parse the multiple objects list to find wear target objects. */
- if (!lib_parse_multiple_objects (game, "wear",
- lib_wear_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find wear target objects. */
+ if (!lib_parse_multiple_objects(game, "wear",
+ lib_wear_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_multiple_filter (game,
- lib_wear_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_wear_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything",
- "I am not holding anything",
- "%player% is not holding anything"));
- pf_buffer_string (filter, " that can be worn.");
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_multiple_filter(game,
+ lib_wear_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_wear_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything",
+ "I am not holding anything",
+ "%player% is not holding anything"));
+ pf_buffer_string(filter, " that can be worn.");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -6147,126 +5581,109 @@ lib_cmd_wear_multiple (sc_gameref_t game)
* deemed not actionable are flagged in multiple_references.
*/
static void
-lib_remove_backend (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object_count, object, count, trail;
- sc_bool has_printed;
-
- /*
- * Try game commands for all referenced objects first. If any succeed,
- * remove that reference from the list.
- */
- has_printed = FALSE;
- object_count = gs_object_count (game);
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (lib_try_game_command_short (game, "remove", object))
- {
- game->object_references[object] = FALSE;
- has_printed = TRUE;
- }
- }
-
- /* Remove every object referenced. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You remove ",
- "I remove ",
- "%player% removes "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- gs_object_player_get (game, object);
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You remove ",
- "I remove ",
- "%player% removes "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
-
- /* Note any remaining multiple references left out of the remove operation. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not wearing ",
- "I am not wearing ",
- "%player% is not wearing "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not wearing ",
- "I am not wearing ",
- "%player% is not wearing "));
- }
- else
- pf_buffer_string (filter, " or ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '!');
- }
+lib_remove_backend(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object_count, object, count, trail;
+ sc_bool has_printed;
+
+ /*
+ * Try game commands for all referenced objects first. If any succeed,
+ * remove that reference from the list.
+ */
+ has_printed = FALSE;
+ object_count = gs_object_count(game);
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (lib_try_game_command_short(game, "remove", object)) {
+ game->object_references[object] = FALSE;
+ has_printed = TRUE;
+ }
+ }
+
+ /* Remove every object referenced. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You remove ",
+ "I remove ",
+ "%player% removes "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ gs_object_player_get(game, object);
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You remove ",
+ "I remove ",
+ "%player% removes "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+
+ /* Note any remaining multiple references left out of the remove operation. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not wearing ",
+ "I am not wearing ",
+ "%player% is not wearing "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not wearing ",
+ "I am not wearing ",
+ "%player% is not wearing "));
+ } else
+ pf_buffer_string(filter, " or ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '!');
+ }
}
@@ -6277,12 +5694,11 @@ lib_remove_backend (sc_gameref_t game)
* Returns TRUE if an object is currently being worn, FALSE otherwise.
*/
static sc_bool
-lib_remove_filter (sc_gameref_t game, sc_int object, sc_int unused)
-{
- assert (unused == -1);
+lib_remove_filter(sc_gameref_t game, sc_int object, sc_int unused) {
+ assert(unused == -1);
- return !obj_is_static (game, object)
- && gs_object_position (game, object) == OBJ_WORN_PLAYER;
+ return !obj_is_static(game, object)
+ && gs_object_position(game, object) == OBJ_WORN_PLAYER;
}
@@ -6292,31 +5708,29 @@ lib_remove_filter (sc_gameref_t game, sc_int object, sc_int unused)
* Remove all objects currently held by the player.
*/
sc_bool
-lib_cmd_remove_all (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects;
+lib_cmd_remove_all(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects;
- /* Filter objects into references, then handle with the backend. */
- gs_set_multiple_references (game);
- objects = lib_apply_multiple_filter (game,
- lib_remove_filter, -1,
- NULL);
- gs_clear_multiple_references (game);
- if (objects > 0)
- lib_remove_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You're not wearing anything",
- "I'm not wearing anything",
- "%player%'s not wearing anything"));
- pf_buffer_string (filter, " that can be removed.");
- }
+ /* Filter objects into references, then handle with the backend. */
+ gs_set_multiple_references(game);
+ objects = lib_apply_multiple_filter(game,
+ lib_remove_filter, -1,
+ NULL);
+ gs_clear_multiple_references(game);
+ if (objects > 0)
+ lib_remove_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You're not wearing anything",
+ "I'm not wearing anything",
+ "%player%'s not wearing anything"));
+ pf_buffer_string(filter, " that can be removed.");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -6327,39 +5741,37 @@ lib_cmd_remove_all (sc_gameref_t game)
* in %text%.
*/
sc_bool
-lib_cmd_remove_except_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects, references;
+lib_cmd_remove_except_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects, references;
- /* Parse the multiple objects list to find retain target objects. */
- if (!lib_parse_multiple_objects (game, "retain",
- lib_remove_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find retain target objects. */
+ if (!lib_parse_multiple_objects(game, "retain",
+ lib_remove_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_except_filter (game,
- lib_remove_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_remove_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not wearing anything",
- "I am not wearing anything",
- "%player% is not wearing anything"));
- if (objects == 0)
- pf_buffer_string (filter, " else");
- pf_buffer_string (filter, " that can be removed.");
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_except_filter(game,
+ lib_remove_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_remove_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not wearing anything",
+ "I am not wearing anything",
+ "%player% is not wearing anything"));
+ if (objects == 0)
+ pf_buffer_string(filter, " else");
+ pf_buffer_string(filter, " that can be removed.");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -6369,37 +5781,35 @@ lib_cmd_remove_except_multiple (sc_gameref_t game)
* Remove all objects currently worn by the player, and listed in %text%.
*/
sc_bool
-lib_cmd_remove_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int objects, references;
+lib_cmd_remove_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int objects, references;
- /* Parse the multiple objects list to find remove target objects. */
- if (!lib_parse_multiple_objects (game, "remove",
- lib_remove_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find remove target objects. */
+ if (!lib_parse_multiple_objects(game, "remove",
+ lib_remove_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_multiple_filter (game,
- lib_remove_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_remove_backend (game);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything",
- "I am not holding anything",
- "%player% is not holding anything"));
- pf_buffer_string (filter, " that can be removed.");
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_multiple_filter(game,
+ lib_remove_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_remove_backend(game);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything",
+ "I am not holding anything",
+ "%player% is not holding anything"));
+ pf_buffer_string(filter, " that can be removed.");
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -6409,155 +5819,125 @@ lib_cmd_remove_multiple (sc_gameref_t game)
* List objects carried and worn by the player.
*/
sc_bool
-lib_cmd_inventory (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object, count, trail;
- sc_bool wearing;
-
- /* Find and list each object worn by the player. */
- count = 0;
- trail = -1;
- wearing = FALSE;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_WORN_PLAYER)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are wearing ",
- "I am wearing ",
- "%player% is wearing "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are wearing ",
- "I am wearing ",
- "%player% is wearing "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object (game, trail);
- wearing = TRUE;
- }
-
- /* Find and list each object owned by the player. */
- count = 0;
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- if (wearing)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- ", and you are carrying ",
- ", and I am carrying ",
- ", and %player% is carrying "));
- }
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are carrying ",
- "I am carrying ",
- "%player% is carrying "));
- }
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- if (wearing)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- ", and you are carrying ",
- ", and I am carrying ",
- ", and %player% is carrying "));
- }
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are carrying ",
- "I am carrying ",
- "%player% is carrying "));
- }
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object (game, trail);
- pf_buffer_character (filter, '.');
-
- /* Print contents of every container and surface carried. */
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER)
- {
- if (obj_is_container (game, object)
- && gs_object_openness (game, object) <= OBJ_OPEN)
- lib_list_in_object (game, object, TRUE);
-
- if (obj_is_surface (game, object))
- lib_list_on_object (game, object, TRUE);
- }
- }
- pf_buffer_character (filter, '\n');
- }
- else
- {
- if (wearing)
- {
- pf_buffer_string (filter, ", and ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "you are carrying nothing.\n",
- "I am carrying nothing.\n",
- "%player% is carrying nothing.\n"));
- }
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are carrying nothing.\n",
- "I am carrying nothing.\n",
- "%player% is carrying nothing.\n"));
- }
- }
-
- /* Successful command. */
- return TRUE;
+lib_cmd_inventory(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object, count, trail;
+ sc_bool wearing;
+
+ /* Find and list each object worn by the player. */
+ count = 0;
+ trail = -1;
+ wearing = FALSE;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_WORN_PLAYER) {
+ if (count > 0) {
+ if (count == 1) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are wearing ",
+ "I am wearing ",
+ "%player% is wearing "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are wearing ",
+ "I am wearing ",
+ "%player% is wearing "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object(game, trail);
+ wearing = TRUE;
+ }
+
+ /* Find and list each object owned by the player. */
+ count = 0;
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER) {
+ if (count > 0) {
+ if (count == 1) {
+ if (wearing) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ ", and you are carrying ",
+ ", and I am carrying ",
+ ", and %player% is carrying "));
+ } else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are carrying ",
+ "I am carrying ",
+ "%player% is carrying "));
+ }
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ if (wearing) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ ", and you are carrying ",
+ ", and I am carrying ",
+ ", and %player% is carrying "));
+ } else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are carrying ",
+ "I am carrying ",
+ "%player% is carrying "));
+ }
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object(game, trail);
+ pf_buffer_character(filter, '.');
+
+ /* Print contents of every container and surface carried. */
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER) {
+ if (obj_is_container(game, object)
+ && gs_object_openness(game, object) <= OBJ_OPEN)
+ lib_list_in_object(game, object, TRUE);
+
+ if (obj_is_surface(game, object))
+ lib_list_on_object(game, object, TRUE);
+ }
+ }
+ pf_buffer_character(filter, '\n');
+ } else {
+ if (wearing) {
+ pf_buffer_string(filter, ", and ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "you are carrying nothing.\n",
+ "I am carrying nothing.\n",
+ "%player% is carrying nothing.\n"));
+ } else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are carrying nothing.\n",
+ "I am carrying nothing.\n",
+ "%player% is carrying nothing.\n"));
+ }
+ }
+
+ /* Successful command. */
+ return TRUE;
}
@@ -6567,70 +5947,68 @@ lib_cmd_inventory (sc_gameref_t game)
* Attempt to open the referenced object.
*/
sc_bool
-lib_cmd_open_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object, openness;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "open", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Get the current object openness. */
- openness = gs_object_openness (game, object);
-
- /* React to the request based on openness state. */
- switch (openness)
- {
- case OBJ_OPEN:
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is already open!\n",
- " are already open!\n"));
- return TRUE;
-
- case OBJ_CLOSED:
- pf_buffer_string (filter,
- lib_select_response (game,
- "You open ",
- "I open ",
- "%player% opens "));
- lib_print_object_np (game, object);
- pf_buffer_character (filter, '.');
-
- /* Set open state, and list contents. */
- gs_set_object_openness (game, object, OBJ_OPEN);
- lib_list_in_object (game, object, TRUE);
- pf_buffer_character (filter, '\n');
- return TRUE;
-
- case OBJ_LOCKED:
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't open ",
- "I can't open ",
- "%player% can't open "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " as it is locked!\n");
- return TRUE;
-
- default:
- break;
- }
-
- /* The object isn't openable. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't open ",
- "I can't open ",
- "%player% can't open "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, "!\n");
- return TRUE;
+lib_cmd_open_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object, openness;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "open", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Get the current object openness. */
+ openness = gs_object_openness(game, object);
+
+ /* React to the request based on openness state. */
+ switch (openness) {
+ case OBJ_OPEN:
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is already open!\n",
+ " are already open!\n"));
+ return TRUE;
+
+ case OBJ_CLOSED:
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You open ",
+ "I open ",
+ "%player% opens "));
+ lib_print_object_np(game, object);
+ pf_buffer_character(filter, '.');
+
+ /* Set open state, and list contents. */
+ gs_set_object_openness(game, object, OBJ_OPEN);
+ lib_list_in_object(game, object, TRUE);
+ pf_buffer_character(filter, '\n');
+ return TRUE;
+
+ case OBJ_LOCKED:
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't open ",
+ "I can't open ",
+ "%player% can't open "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " as it is locked!\n");
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ /* The object isn't openable. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't open ",
+ "I can't open ",
+ "%player% can't open "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, "!\n");
+ return TRUE;
}
@@ -6640,59 +6018,57 @@ lib_cmd_open_object (sc_gameref_t game)
* Attempt to close the referenced object.
*/
sc_bool
-lib_cmd_close_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object, openness;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "close", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Get the current object openness. */
- openness = gs_object_openness (game, object);
-
- /* React to the request based on openness state. */
- switch (openness)
- {
- case OBJ_OPEN:
- pf_buffer_string (filter,
- lib_select_response (game,
- "You close ",
- "I close ",
- "%player% closes "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
-
- /* Set closed state. */
- gs_set_object_openness (game, object, OBJ_CLOSED);
- return TRUE;
-
- case OBJ_CLOSED:
- case OBJ_LOCKED:
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is already closed!\n",
- " are already closed!\n"));
- return TRUE;
-
- default:
- break;
- }
-
- /* The object isn't closeable. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't close ",
- "I can't close ",
- "%player% can't close "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, "!\n");
- return TRUE;
+lib_cmd_close_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object, openness;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "close", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Get the current object openness. */
+ openness = gs_object_openness(game, object);
+
+ /* React to the request based on openness state. */
+ switch (openness) {
+ case OBJ_OPEN:
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You close ",
+ "I close ",
+ "%player% closes "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+
+ /* Set closed state. */
+ gs_set_object_openness(game, object, OBJ_CLOSED);
+ return TRUE;
+
+ case OBJ_CLOSED:
+ case OBJ_LOCKED:
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is already closed!\n",
+ " are already closed!\n"));
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ /* The object isn't closeable. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't close ",
+ "I can't close ",
+ "%player% can't close "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, "!\n");
+ return TRUE;
}
@@ -6702,64 +6078,59 @@ lib_cmd_close_object (sc_gameref_t game)
* Automatically get an object being used as a key, if possible.
*/
static void
-lib_attempt_key_acquisition (sc_gameref_t game, sc_int object)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- /* Disallow getting static objects. */
- if (obj_is_static (game, object))
- return;
-
- /* If the object is not seen or available, reject the attempt. */
- if (!(gs_object_seen (game, object)
- && obj_indirectly_in_room (game, object, gs_playerroom (game))))
- return;
-
- /*
- * Check if we already have it, or are wearing it, or if a NPC has or is
- * wearing it.
- */
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER
- || gs_object_position (game, object) == OBJ_WORN_PLAYER
- || gs_object_position (game, object) == OBJ_HELD_NPC
- || gs_object_position (game, object) == OBJ_WORN_NPC)
- return;
-
- /*
- * If the object is contained in or on something we're already holding,
- * capacity checks are meaningless.
- */
- if (!obj_indirectly_held_by_player (game, object))
- {
- if (lib_object_too_heavy (game, object, NULL)
- || lib_object_too_large (game, object, NULL))
- return;
- }
-
- /* Retry game commands for the object with a standard "get". */
- if (lib_try_game_command_short (game, "get", object))
- return;
-
- /* Note what we're doing. */
- if (gs_object_position (game, object) == OBJ_IN_OBJECT
- || gs_object_position (game, object) == OBJ_ON_OBJECT)
- {
- pf_buffer_string (filter, "(Taking ");
- lib_print_object_np (game, object);
-
- pf_buffer_string (filter, " from ");
- lib_print_object_np (game, gs_object_parent (game, object));
- pf_buffer_string (filter, " first)\n");
- }
- else
- {
- pf_buffer_string (filter, "(Picking up ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " first)\n");
- }
-
- /* Take possession of the object. */
- gs_object_player_get (game, object);
+lib_attempt_key_acquisition(sc_gameref_t game, sc_int object) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ /* Disallow getting static objects. */
+ if (obj_is_static(game, object))
+ return;
+
+ /* If the object is not seen or available, reject the attempt. */
+ if (!(gs_object_seen(game, object)
+ && obj_indirectly_in_room(game, object, gs_playerroom(game))))
+ return;
+
+ /*
+ * Check if we already have it, or are wearing it, or if a NPC has or is
+ * wearing it.
+ */
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER
+ || gs_object_position(game, object) == OBJ_WORN_PLAYER
+ || gs_object_position(game, object) == OBJ_HELD_NPC
+ || gs_object_position(game, object) == OBJ_WORN_NPC)
+ return;
+
+ /*
+ * If the object is contained in or on something we're already holding,
+ * capacity checks are meaningless.
+ */
+ if (!obj_indirectly_held_by_player(game, object)) {
+ if (lib_object_too_heavy(game, object, NULL)
+ || lib_object_too_large(game, object, NULL))
+ return;
+ }
+
+ /* Retry game commands for the object with a standard "get". */
+ if (lib_try_game_command_short(game, "get", object))
+ return;
+
+ /* Note what we're doing. */
+ if (gs_object_position(game, object) == OBJ_IN_OBJECT
+ || gs_object_position(game, object) == OBJ_ON_OBJECT) {
+ pf_buffer_string(filter, "(Taking ");
+ lib_print_object_np(game, object);
+
+ pf_buffer_string(filter, " from ");
+ lib_print_object_np(game, gs_object_parent(game, object));
+ pf_buffer_string(filter, " first)\n");
+ } else {
+ pf_buffer_string(filter, "(Picking up ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " first)\n");
+ }
+
+ /* Take possession of the object. */
+ gs_object_player_get(game, object);
}
@@ -6769,110 +6140,104 @@ lib_attempt_key_acquisition (sc_gameref_t game, sc_int object)
* Attempt to unlock the referenced object.
*/
sc_bool
-lib_cmd_unlock_object_with (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, key, openness;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "unlock", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /*
- * Now try to get the key from referenced text, and disambiguate as usual.
- */
- if (!uip_match ("%object%", var_get_ref_text (vars), game))
- {
- pf_buffer_string (filter, "What do you want to unlock that with?\n");
- return TRUE;
- }
- key = lib_disambiguate_object (game, "unlock that with", NULL);
- if (key == -1)
- return TRUE;
-
- /* React to the request based on openness state. */
- openness = gs_object_openness (game, object);
- switch (openness)
- {
- case OBJ_OPEN:
- case OBJ_CLOSED:
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is not locked!\n",
- " are not locked!\n"));
- return TRUE;
-
- case OBJ_LOCKED:
- {
- sc_vartype_t vt_key[3];
- sc_int key_index, the_key;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Key";
- key_index = prop_get_integer (bundle, "I<-sis", vt_key);
- if (key_index == -1)
- break;
-
- the_key = obj_dynamic_object (game, key_index);
- if (the_key != key)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't unlock ",
- "I can't unlock ",
- "%player% can't unlock "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " with ");
- lib_print_object_np (game, key);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- if (gs_object_position (game, key) != OBJ_HELD_PLAYER)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- lib_print_object_np (game, key);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- gs_set_object_openness (game, object, OBJ_CLOSED);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You unlock ",
- "I unlock ",
- "%player% unlocks "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " with ");
- lib_print_object_np (game, key);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- default:
- break;
- }
-
- /* The object isn't lockable. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't unlock ",
- "I can't unlock ",
- "%player% can't unlock "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+lib_cmd_unlock_object_with(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, key, openness;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "unlock", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /*
+ * Now try to get the key from referenced text, and disambiguate as usual.
+ */
+ if (!uip_match("%object%", var_get_ref_text(vars), game)) {
+ pf_buffer_string(filter, "What do you want to unlock that with?\n");
+ return TRUE;
+ }
+ key = lib_disambiguate_object(game, "unlock that with", NULL);
+ if (key == -1)
+ return TRUE;
+
+ /* React to the request based on openness state. */
+ openness = gs_object_openness(game, object);
+ switch (openness) {
+ case OBJ_OPEN:
+ case OBJ_CLOSED:
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is not locked!\n",
+ " are not locked!\n"));
+ return TRUE;
+
+ case OBJ_LOCKED: {
+ sc_vartype_t vt_key[3];
+ sc_int key_index, the_key;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Key";
+ key_index = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (key_index == -1)
+ break;
+
+ the_key = obj_dynamic_object(game, key_index);
+ if (the_key != key) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't unlock ",
+ "I can't unlock ",
+ "%player% can't unlock "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " with ");
+ lib_print_object_np(game, key);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ if (gs_object_position(game, key) != OBJ_HELD_PLAYER) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ lib_print_object_np(game, key);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ gs_set_object_openness(game, object, OBJ_CLOSED);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You unlock ",
+ "I unlock ",
+ "%player% unlocks "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " with ");
+ lib_print_object_np(game, key);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ default:
+ break;
+ }
+
+ /* The object isn't lockable. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't unlock ",
+ "I can't unlock ",
+ "%player% can't unlock "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
@@ -6882,85 +6247,81 @@ lib_cmd_unlock_object_with (sc_gameref_t game)
* Attempt to unlock the referenced object, automatically selecting key.
*/
sc_bool
-lib_cmd_unlock_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, openness;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "unlock", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* React to the request based on openness state. */
- openness = gs_object_openness (game, object);
- switch (openness)
- {
- case OBJ_OPEN:
- case OBJ_CLOSED:
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is not locked!\n",
- " are not locked!\n"));
- return TRUE;
-
- case OBJ_LOCKED:
- {
- sc_vartype_t vt_key[3];
- sc_int key_index, key;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Key";
- key_index = prop_get_integer (bundle, "I<-sis", vt_key);
- if (key_index == -1)
- break;
-
- key = obj_dynamic_object (game, key_index);
- lib_attempt_key_acquisition (game, key);
- if (gs_object_position (game, key) != OBJ_HELD_PLAYER)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You don't have",
- "I don't have",
- "%player% doesn't have"));
- pf_buffer_string (filter, " anything to unlock ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " with!\n");
- return TRUE;
- }
-
- gs_set_object_openness (game, object, OBJ_CLOSED);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You unlock ",
- "I unlock ",
- "%player% unlocks "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " with ");
- lib_print_object_np (game, key);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- default:
- break;
- }
-
- /* The object isn't lockable. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't unlock ",
- "I can't unlock ",
- "%player% can't unlock "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+lib_cmd_unlock_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, openness;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "unlock", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* React to the request based on openness state. */
+ openness = gs_object_openness(game, object);
+ switch (openness) {
+ case OBJ_OPEN:
+ case OBJ_CLOSED:
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is not locked!\n",
+ " are not locked!\n"));
+ return TRUE;
+
+ case OBJ_LOCKED: {
+ sc_vartype_t vt_key[3];
+ sc_int key_index, key;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Key";
+ key_index = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (key_index == -1)
+ break;
+
+ key = obj_dynamic_object(game, key_index);
+ lib_attempt_key_acquisition(game, key);
+ if (gs_object_position(game, key) != OBJ_HELD_PLAYER) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You don't have",
+ "I don't have",
+ "%player% doesn't have"));
+ pf_buffer_string(filter, " anything to unlock ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " with!\n");
+ return TRUE;
+ }
+
+ gs_set_object_openness(game, object, OBJ_CLOSED);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You unlock ",
+ "I unlock ",
+ "%player% unlocks "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " with ");
+ lib_print_object_np(game, key);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ default:
+ break;
+ }
+
+ /* The object isn't lockable. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't unlock ",
+ "I can't unlock ",
+ "%player% can't unlock "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
@@ -6970,118 +6331,112 @@ lib_cmd_unlock_object (sc_gameref_t game)
* Attempt to lock the referenced object.
*/
sc_bool
-lib_cmd_lock_object_with (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, key, openness;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "lock", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /*
- * Now try to get the key from referenced text, and disambiguate as usual.
- */
- if (!uip_match ("%object%", var_get_ref_text (vars), game))
- {
- pf_buffer_string (filter, "What do you want to lock that with?\n");
- return TRUE;
- }
- key = lib_disambiguate_object (game, "lock that with", NULL);
- if (key == -1)
- return TRUE;
-
- /* React to the request based on openness state. */
- openness = gs_object_openness (game, object);
- switch (openness)
- {
- case OBJ_OPEN:
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't lock ",
- "I can't lock ",
- "%player% can't lock "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " as it is open.\n");
- return TRUE;
-
- case OBJ_CLOSED:
- {
- sc_vartype_t vt_key[3];
- sc_int key_index, the_key;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Key";
- key_index = prop_get_integer (bundle, "I<-sis", vt_key);
- if (key_index == -1)
- break;
-
- the_key = obj_dynamic_object (game, key_index);
- if (the_key != key)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't lock ",
- "I can't lock ",
- "%player% can't lock "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " with ");
- lib_print_object_np (game, key);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- if (gs_object_position (game, key) != OBJ_HELD_PLAYER)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- lib_print_object_np (game, key);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- gs_set_object_openness (game, object, OBJ_LOCKED);
- pf_buffer_string (filter, lib_select_response (game,
- "You lock ",
- "I lock ",
- "%player% locks "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " with ");
- lib_print_object_np (game, key);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- case OBJ_LOCKED:
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is already locked!\n",
- " are already locked!\n"));
- return TRUE;
-
- default:
- break;
- }
-
- /* The object isn't lockable. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't lock ",
- "I can't lock ",
- "%player% can't lock "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+lib_cmd_lock_object_with(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, key, openness;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "lock", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /*
+ * Now try to get the key from referenced text, and disambiguate as usual.
+ */
+ if (!uip_match("%object%", var_get_ref_text(vars), game)) {
+ pf_buffer_string(filter, "What do you want to lock that with?\n");
+ return TRUE;
+ }
+ key = lib_disambiguate_object(game, "lock that with", NULL);
+ if (key == -1)
+ return TRUE;
+
+ /* React to the request based on openness state. */
+ openness = gs_object_openness(game, object);
+ switch (openness) {
+ case OBJ_OPEN:
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't lock ",
+ "I can't lock ",
+ "%player% can't lock "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " as it is open.\n");
+ return TRUE;
+
+ case OBJ_CLOSED: {
+ sc_vartype_t vt_key[3];
+ sc_int key_index, the_key;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Key";
+ key_index = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (key_index == -1)
+ break;
+
+ the_key = obj_dynamic_object(game, key_index);
+ if (the_key != key) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't lock ",
+ "I can't lock ",
+ "%player% can't lock "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " with ");
+ lib_print_object_np(game, key);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ if (gs_object_position(game, key) != OBJ_HELD_PLAYER) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ lib_print_object_np(game, key);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ gs_set_object_openness(game, object, OBJ_LOCKED);
+ pf_buffer_string(filter, lib_select_response(game,
+ "You lock ",
+ "I lock ",
+ "%player% locks "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " with ");
+ lib_print_object_np(game, key);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ case OBJ_LOCKED:
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is already locked!\n",
+ " are already locked!\n"));
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ /* The object isn't lockable. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't lock ",
+ "I can't lock ",
+ "%player% can't lock "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
@@ -7091,94 +6446,90 @@ lib_cmd_lock_object_with (sc_gameref_t game)
* Attempt to lock the referenced object, automatically selecting key.
*/
sc_bool
-lib_cmd_lock_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, openness;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "lock", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* React to the request based on openness state. */
- openness = gs_object_openness (game, object);
- switch (openness)
- {
- case OBJ_OPEN:
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't lock ",
- "I can't lock ",
- "%player% can't lock "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " as it is open.\n");
- return TRUE;
-
- case OBJ_CLOSED:
- {
- sc_vartype_t vt_key[3];
- sc_int key_index, key;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Key";
- key_index = prop_get_integer (bundle, "I<-sis", vt_key);
- if (key_index == -1)
- break;
-
- key = obj_dynamic_object (game, key_index);
- lib_attempt_key_acquisition (game, key);
- if (gs_object_position (game, key) != OBJ_HELD_PLAYER)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You don't have",
- "I don't have",
- "%player% doesn't have"));
- pf_buffer_string (filter, " anything to lock ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " with!\n");
- return TRUE;
- }
-
- gs_set_object_openness (game, object, OBJ_LOCKED);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You lock ",
- "I lock ",
- "%player% locks "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " with ");
- lib_print_object_np (game, key);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- case OBJ_LOCKED:
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is already locked!\n",
- " are already locked!\n"));
- return TRUE;
-
- default:
- break;
- }
-
- /* The object isn't lockable. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't lock ",
- "I can't lock ",
- "%player% can't lock "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+lib_cmd_lock_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, openness;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "lock", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* React to the request based on openness state. */
+ openness = gs_object_openness(game, object);
+ switch (openness) {
+ case OBJ_OPEN:
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't lock ",
+ "I can't lock ",
+ "%player% can't lock "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " as it is open.\n");
+ return TRUE;
+
+ case OBJ_CLOSED: {
+ sc_vartype_t vt_key[3];
+ sc_int key_index, key;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Key";
+ key_index = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (key_index == -1)
+ break;
+
+ key = obj_dynamic_object(game, key_index);
+ lib_attempt_key_acquisition(game, key);
+ if (gs_object_position(game, key) != OBJ_HELD_PLAYER) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You don't have",
+ "I don't have",
+ "%player% doesn't have"));
+ pf_buffer_string(filter, " anything to lock ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " with!\n");
+ return TRUE;
+ }
+
+ gs_set_object_openness(game, object, OBJ_LOCKED);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You lock ",
+ "I lock ",
+ "%player% locks "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " with ");
+ lib_print_object_np(game, key);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ case OBJ_LOCKED:
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is already locked!\n",
+ " are already locked!\n"));
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ /* The object isn't lockable. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't lock ",
+ "I can't lock ",
+ "%player% can't lock "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
@@ -7188,58 +6539,55 @@ lib_cmd_lock_object (sc_gameref_t game)
* Compare a subject, comma or NUL terminated. Helper for ask.
*/
static sc_bool
-lib_compare_subject (const sc_char *subject, sc_int posn,
- const sc_char *string)
-{
- sc_int word_posn, string_posn;
-
- /* Skip any leading subject spaces. */
- for (word_posn = posn;
- subject[word_posn] != NUL && sc_isspace (subject[word_posn]);)
- word_posn++;
- for (string_posn = 0;
- string[string_posn] != NUL && sc_isspace (string[string_posn]);)
- string_posn++;
-
- /* Match characters from words with the string at position. */
- while (TRUE)
- {
- /* Any character mismatch means no match. */
- if (sc_tolower (subject[word_posn]) != sc_tolower (string[string_posn]))
- return FALSE;
-
- /* Move to next character in each. */
- word_posn++;
- string_posn++;
-
- /*
- * If at space, advance over whitespace in subjects list. Stop when we
- * hit the end of the element or list.
- */
- while (sc_isspace (subject[word_posn])
- && subject[word_posn] != COMMA && subject[word_posn] != NUL)
- subject++;
-
- /* Advance over whitespace in the current string too. */
- while (sc_isspace (string[string_posn]) && string[string_posn] != NUL)
- string_posn++;
-
- /*
- * If we found the end of the subject, and the end of the current string,
- * we've matched. If not at the end of the current string, though, only
- * a partial match.
- */
- if (subject[word_posn] == NUL || subject[word_posn] == COMMA)
- {
- if (string[string_posn] == NUL)
- break;
- else
- return FALSE;
- }
- }
-
- /* Matched in the loop; return TRUE. */
- return TRUE;
+lib_compare_subject(const sc_char *subject, sc_int posn,
+ const sc_char *string) {
+ sc_int word_posn, string_posn;
+
+ /* Skip any leading subject spaces. */
+ for (word_posn = posn;
+ subject[word_posn] != NUL && sc_isspace(subject[word_posn]);)
+ word_posn++;
+ for (string_posn = 0;
+ string[string_posn] != NUL && sc_isspace(string[string_posn]);)
+ string_posn++;
+
+ /* Match characters from words with the string at position. */
+ while (TRUE) {
+ /* Any character mismatch means no match. */
+ if (sc_tolower(subject[word_posn]) != sc_tolower(string[string_posn]))
+ return FALSE;
+
+ /* Move to next character in each. */
+ word_posn++;
+ string_posn++;
+
+ /*
+ * If at space, advance over whitespace in subjects list. Stop when we
+ * hit the end of the element or list.
+ */
+ while (sc_isspace(subject[word_posn])
+ && subject[word_posn] != COMMA && subject[word_posn] != NUL)
+ subject++;
+
+ /* Advance over whitespace in the current string too. */
+ while (sc_isspace(string[string_posn]) && string[string_posn] != NUL)
+ string_posn++;
+
+ /*
+ * If we found the end of the subject, and the end of the current string,
+ * we've matched. If not at the end of the current string, though, only
+ * a partial match.
+ */
+ if (subject[word_posn] == NUL || subject[word_posn] == COMMA) {
+ if (string[string_posn] == NUL)
+ break;
+ else
+ return FALSE;
+ }
+ }
+
+ /* Matched in the loop; return TRUE. */
+ return TRUE;
}
@@ -7249,37 +6597,35 @@ lib_compare_subject (const sc_char *subject, sc_int posn,
* Reply for an NPC on a given topic. Helper for ask.
*/
static sc_bool
-lib_npc_reply_to (sc_gameref_t game, sc_int npc, sc_int topic)
-{
- 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];
- sc_int task;
- const sc_char *response;
-
- /* Find any associated task to control response. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Topics";
- vt_key[3].integer = topic;
- vt_key[4].string = "Task";
- task = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- /* Get the response, and print if anything there. */
- if (task > 0 && gs_task_done (game, task - 1))
- vt_key[4].string = "AltReply";
- else
- vt_key[4].string = "Reply";
- response = prop_get_string (bundle, "S<-sisis", vt_key);
- if (!sc_strempty (response))
- {
- pf_buffer_string (filter, response);
- pf_buffer_character (filter, '\n');
- return TRUE;
- }
-
- /* No response to this combination. */
- return FALSE;
+lib_npc_reply_to(sc_gameref_t game, sc_int npc, sc_int topic) {
+ 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];
+ sc_int task;
+ const sc_char *response;
+
+ /* Find any associated task to control response. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Topics";
+ vt_key[3].integer = topic;
+ vt_key[4].string = "Task";
+ task = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ /* Get the response, and print if anything there. */
+ if (task > 0 && gs_task_done(game, task - 1))
+ vt_key[4].string = "AltReply";
+ else
+ vt_key[4].string = "Reply";
+ response = prop_get_string(bundle, "S<-sisis", vt_key);
+ if (!sc_strempty(response)) {
+ pf_buffer_string(filter, response);
+ pf_buffer_character(filter, '\n');
+ return TRUE;
+ }
+
+ /* No response to this combination. */
+ return FALSE;
}
@@ -7289,91 +6635,86 @@ lib_npc_reply_to (sc_gameref_t game, sc_int npc, sc_int topic)
* Converse with NPC.
*/
sc_bool
-lib_cmd_ask_npc_about (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int npc, topic_count, topic, topic_match, default_topic;
- sc_bool found, default_found, is_ambiguous;
-
- /* Get the referenced npc, and if none, consider complete. */
- npc = lib_disambiguate_npc (game, "ask", &is_ambiguous);
- if (npc == -1)
- return is_ambiguous;
-
- if (lib_trace)
- sc_trace ("Library: asking NPC %ld\n", npc);
-
- /* Get the topics the NPC converses about. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Topics";
- topic_count = prop_get_child_count (bundle, "I<-sis", vt_key);
- topic_match = default_topic = -1;
- found = default_found = FALSE;
- for (topic = 0; topic < topic_count; topic++)
- {
- const sc_char *subjects;
- sc_int posn;
-
- /* Get subject list for this topic. */
- vt_key[3].integer = topic;
- vt_key[4].string = "Subject";
- subjects = prop_get_string (bundle, "S<-sisis", vt_key);
-
- /* If this is the special "*" topic, note and continue. */
- if (!sc_strcasecmp (subjects, "*"))
- {
- if (lib_trace)
- sc_trace ("Library: \"*\" is %ld\n", topic);
-
- default_topic = topic;
- default_found = TRUE;
- continue;
- }
-
- /* Split into subjects by comma delimiter. */
- for (posn = 0; subjects[posn] != NUL;)
- {
- if (lib_trace)
- sc_trace ("Library: subject %s[%ld]\n", subjects, posn);
-
- /* See if this subject matches. */
- if (lib_compare_subject (subjects, posn, var_get_ref_text (vars)))
- {
- if (lib_trace)
- sc_trace ("Library: matched\n");
-
- topic_match = topic;
- found = TRUE;
- break;
- }
-
- /* Move to next subject, or end of list. */
- while (subjects[posn] != COMMA && subjects[posn] != NUL)
- posn++;
- if (subjects[posn] == COMMA)
- posn++;
- }
- }
-
- /* Handle any matched subject first, and "*" second. */
- if (found && lib_npc_reply_to (game, npc, topic_match))
- return TRUE;
- else if (default_found && lib_npc_reply_to (game, npc, default_topic))
- return TRUE;
-
- /* NPC has no response. */
- pf_new_sentence (filter);
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter,
- lib_select_response (game,
- " does not respond to your question.\n",
- " does not respond to my question.\n",
- " does not respond to %player%'s question.\n"));
- return TRUE;
+lib_cmd_ask_npc_about(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int npc, topic_count, topic, topic_match, default_topic;
+ sc_bool found, default_found, is_ambiguous;
+
+ /* Get the referenced npc, and if none, consider complete. */
+ npc = lib_disambiguate_npc(game, "ask", &is_ambiguous);
+ if (npc == -1)
+ return is_ambiguous;
+
+ if (lib_trace)
+ sc_trace("Library: asking NPC %ld\n", npc);
+
+ /* Get the topics the NPC converses about. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Topics";
+ topic_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+ topic_match = default_topic = -1;
+ found = default_found = FALSE;
+ for (topic = 0; topic < topic_count; topic++) {
+ const sc_char *subjects;
+ sc_int posn;
+
+ /* Get subject list for this topic. */
+ vt_key[3].integer = topic;
+ vt_key[4].string = "Subject";
+ subjects = prop_get_string(bundle, "S<-sisis", vt_key);
+
+ /* If this is the special "*" topic, note and continue. */
+ if (!sc_strcasecmp(subjects, "*")) {
+ if (lib_trace)
+ sc_trace("Library: \"*\" is %ld\n", topic);
+
+ default_topic = topic;
+ default_found = TRUE;
+ continue;
+ }
+
+ /* Split into subjects by comma delimiter. */
+ for (posn = 0; subjects[posn] != NUL;) {
+ if (lib_trace)
+ sc_trace("Library: subject %s[%ld]\n", subjects, posn);
+
+ /* See if this subject matches. */
+ if (lib_compare_subject(subjects, posn, var_get_ref_text(vars))) {
+ if (lib_trace)
+ sc_trace("Library: matched\n");
+
+ topic_match = topic;
+ found = TRUE;
+ break;
+ }
+
+ /* Move to next subject, or end of list. */
+ while (subjects[posn] != COMMA && subjects[posn] != NUL)
+ posn++;
+ if (subjects[posn] == COMMA)
+ posn++;
+ }
+ }
+
+ /* Handle any matched subject first, and "*" second. */
+ if (found && lib_npc_reply_to(game, npc, topic_match))
+ return TRUE;
+ else if (default_found && lib_npc_reply_to(game, npc, default_topic))
+ return TRUE;
+
+ /* NPC has no response. */
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " does not respond to your question.\n",
+ " does not respond to my question.\n",
+ " does not respond to %player%'s question.\n"));
+ return TRUE;
}
@@ -7384,49 +6725,43 @@ lib_cmd_ask_npc_about (sc_gameref_t game)
* TRUE if no recursion detected.
*/
static sc_bool
-lib_check_put_in_recursion (sc_gameref_t game,
- sc_int object, sc_int container, sc_bool report)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int check;
-
- /* Avoid the obvious possibility of infinite recursion. */
- if (container == object)
- {
- if (report)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't put an object inside itself!",
- "I can't put an object inside itself!",
- "%player% can't put an object inside itself!"));
- }
- return FALSE;
- }
-
- /* Avoid the subtle possibility of infinite recursion. */
- check = container;
- while (gs_object_position (game, check) == OBJ_ON_OBJECT
- || gs_object_position (game, check) == OBJ_IN_OBJECT)
- {
- check = gs_object_parent (game, check);
- if (check == object)
- {
- if (report)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't put an object inside one",
- "I can't put an object inside one",
- "%player% can't put an object inside one"));
- pf_buffer_string (filter, " it's on or in!");
- }
- return FALSE;
- }
- }
-
- /* No infinite recursion detected. */
- return TRUE;
+lib_check_put_in_recursion(sc_gameref_t game,
+ sc_int object, sc_int container, sc_bool report) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int check;
+
+ /* Avoid the obvious possibility of infinite recursion. */
+ if (container == object) {
+ if (report) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't put an object inside itself!",
+ "I can't put an object inside itself!",
+ "%player% can't put an object inside itself!"));
+ }
+ return FALSE;
+ }
+
+ /* Avoid the subtle possibility of infinite recursion. */
+ check = container;
+ while (gs_object_position(game, check) == OBJ_ON_OBJECT
+ || gs_object_position(game, check) == OBJ_IN_OBJECT) {
+ check = gs_object_parent(game, check);
+ if (check == object) {
+ if (report) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't put an object inside one",
+ "I can't put an object inside one",
+ "%player% can't put an object inside one"));
+ pf_buffer_string(filter, " it's on or in!");
+ }
+ return FALSE;
+ }
+ }
+
+ /* No infinite recursion detected. */
+ return TRUE;
}
@@ -7441,269 +6776,233 @@ lib_check_put_in_recursion (sc_gameref_t game,
* deemed not actionable are flagged in multiple_references.
*/
static void
-lib_put_in_backend (sc_gameref_t game, sc_int container)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object_count, object, count, trail, capacity, maxsize;
- sc_bool has_printed;
-
- /*
- * Try game commands for all referenced objects first. If any succeed,
- * remove that reference from the list. At the same time, check for and
- * weed out any moves that result in infinite recursion.
- */
- has_printed = FALSE;
- object_count = gs_object_count (game);
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- /* Reject and remove attempts to place objects in themselves. */
- if (!lib_check_put_in_recursion (game, object, container, !has_printed))
- {
- game->object_references[object] = FALSE;
- has_printed = TRUE;
- continue;
- }
-
- if (lib_try_game_command_with_object (game,
- "put", object, "in", container))
- {
- game->object_references[object] = FALSE;
- has_printed = TRUE;
- }
- }
-
- /* Retrieve the container's limits. */
- maxsize = obj_get_container_maxsize (game, container);
- capacity = obj_get_container_capacity (game, container);
-
- /* Put in every object that remains referenced. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- /* If too big, or exceeds container limits, ignore for now. */
- if (obj_get_size (game, object) > maxsize)
- continue;
- else
- {
- sc_int other, contains;
-
- contains = 0;
- for (other = 0; other < gs_object_count (game); other++)
- {
- if (gs_object_position (game, other) == OBJ_IN_OBJECT
- && gs_object_parent (game, other) == container)
- contains++;
- }
- if (contains >= capacity)
- continue;
- }
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You put ",
- "I put ",
- "%player% puts "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- gs_object_move_into (game, object, container);
- game->object_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You put ",
- "I put ",
- "%player% puts "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_string (filter, " inside ");
- lib_print_object_np (game, container);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
-
- /*
- * Report objects not put in because of their size. These objects remain in
- * standard references, as do objects rejected because of capacity limits.
- * By removing too large objects in this loop, we're left later on with just
- * the objects rejected by capacity limits.
- */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (!(obj_get_size (game, object) > maxsize))
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, trail);
- }
- else
- pf_buffer_string (filter, ", ");
- }
- trail = object;
- count++;
-
- game->object_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, trail);
- pf_buffer_string (filter,
- lib_select_plurality (game, trail,
- " is too big",
- " are too big"));
- }
- else
- {
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_string (filter, " are too big");
- }
- pf_buffer_string (filter, " to fit inside ");
- lib_print_object_np (game, container);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
-
- /*
- * Report objects not put in because the container is too full. This should
- * be all remaining objects in standard references.
- */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->object_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_new_sentence (filter);
- lib_print_object_np (game, trail);
- }
- else
- {
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- }
- pf_buffer_string (filter, " can't fit inside ");
- lib_print_object_np (game, container);
- pf_buffer_string (filter, " at the moment.");
- }
- has_printed |= count > 0;
-
- /* Note any remaining multiple references left out of the operation. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- }
- else
- pf_buffer_string (filter, " or ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
+lib_put_in_backend(sc_gameref_t game, sc_int container) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object_count, object, count, trail, capacity, maxsize;
+ sc_bool has_printed;
+
+ /*
+ * Try game commands for all referenced objects first. If any succeed,
+ * remove that reference from the list. At the same time, check for and
+ * weed out any moves that result in infinite recursion.
+ */
+ has_printed = FALSE;
+ object_count = gs_object_count(game);
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ /* Reject and remove attempts to place objects in themselves. */
+ if (!lib_check_put_in_recursion(game, object, container, !has_printed)) {
+ game->object_references[object] = FALSE;
+ has_printed = TRUE;
+ continue;
+ }
+
+ if (lib_try_game_command_with_object(game,
+ "put", object, "in", container)) {
+ game->object_references[object] = FALSE;
+ has_printed = TRUE;
+ }
+ }
+
+ /* Retrieve the container's limits. */
+ maxsize = obj_get_container_maxsize(game, container);
+ capacity = obj_get_container_capacity(game, container);
+
+ /* Put in every object that remains referenced. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ /* If too big, or exceeds container limits, ignore for now. */
+ if (obj_get_size(game, object) > maxsize)
+ continue;
+ else {
+ sc_int other, contains;
+
+ contains = 0;
+ for (other = 0; other < gs_object_count(game); other++) {
+ if (gs_object_position(game, other) == OBJ_IN_OBJECT
+ && gs_object_parent(game, other) == container)
+ contains++;
+ }
+ if (contains >= capacity)
+ continue;
+ }
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You put ",
+ "I put ",
+ "%player% puts "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ gs_object_move_into(game, object, container);
+ game->object_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You put ",
+ "I put ",
+ "%player% puts "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_string(filter, " inside ");
+ lib_print_object_np(game, container);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+
+ /*
+ * Report objects not put in because of their size. These objects remain in
+ * standard references, as do objects rejected because of capacity limits.
+ * By removing too large objects in this loop, we're left later on with just
+ * the objects rejected by capacity limits.
+ */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (!(obj_get_size(game, object) > maxsize))
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, trail);
+ } else
+ pf_buffer_string(filter, ", ");
+ }
+ trail = object;
+ count++;
+
+ game->object_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, trail);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, trail,
+ " is too big",
+ " are too big"));
+ } else {
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_string(filter, " are too big");
+ }
+ pf_buffer_string(filter, " to fit inside ");
+ lib_print_object_np(game, container);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+
+ /*
+ * Report objects not put in because the container is too full. This should
+ * be all remaining objects in standard references.
+ */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->object_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_new_sentence(filter);
+ lib_print_object_np(game, trail);
+ } else {
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ }
+ pf_buffer_string(filter, " can't fit inside ");
+ lib_print_object_np(game, container);
+ pf_buffer_string(filter, " at the moment.");
+ }
+ has_printed |= count > 0;
+
+ /* Note any remaining multiple references left out of the operation. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ } else
+ pf_buffer_string(filter, " or ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
}
@@ -7715,19 +7014,17 @@ lib_put_in_backend (sc_gameref_t game, sc_int container)
* context. Returns TRUE if an object may be manipulated, FALSE otherwise.
*/
static sc_bool
-lib_put_in_filter (sc_gameref_t game, sc_int object, sc_int unused)
-{
- assert (unused == -1);
+lib_put_in_filter(sc_gameref_t game, sc_int object, sc_int unused) {
+ assert(unused == -1);
- return !obj_is_static (game, object)
- && gs_object_position (game, object) == OBJ_HELD_PLAYER;
+ return !obj_is_static(game, object)
+ && gs_object_position(game, object) == OBJ_HELD_PLAYER;
}
static sc_bool
-lib_put_in_not_container_filter (sc_gameref_t game,
- sc_int object, sc_int container)
-{
- return lib_put_in_filter (game, object, -1) && object != container;
+lib_put_in_not_container_filter(sc_gameref_t game,
+ sc_int object, sc_int container) {
+ return lib_put_in_filter(game, object, -1) && object != container;
}
@@ -7737,39 +7034,36 @@ lib_put_in_not_container_filter (sc_gameref_t game,
* Validate the container requested in "put in" commands.
*/
static sc_bool
-lib_put_in_is_valid (sc_gameref_t game, sc_int container)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- /* Verify that the container object is a container. */
- if (!obj_is_container (game, container))
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't put anything inside ",
- "I can't put anything inside ",
- "%player% can't put anything inside "));
- lib_print_object_np (game, container);
- pf_buffer_string (filter, "!\n");
- return FALSE;
- }
-
- /* If the container is closed, reject now. */
- if (gs_object_openness (game, container) > OBJ_OPEN)
- {
- pf_new_sentence (filter);
- lib_print_object_np (game, container);
- pf_buffer_string (filter,
- lib_select_plurality (game, container, " is", " are"));
- if (gs_object_openness (game, container) == OBJ_LOCKED)
- pf_buffer_string (filter, " locked!\n");
- else
- pf_buffer_string (filter, " closed!\n");
- return FALSE;
- }
-
- /* Container is a valid target for "put in". */
- return TRUE;
+lib_put_in_is_valid(sc_gameref_t game, sc_int container) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ /* Verify that the container object is a container. */
+ if (!obj_is_container(game, container)) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't put anything inside ",
+ "I can't put anything inside ",
+ "%player% can't put anything inside "));
+ lib_print_object_np(game, container);
+ pf_buffer_string(filter, "!\n");
+ return FALSE;
+ }
+
+ /* If the container is closed, reject now. */
+ if (gs_object_openness(game, container) > OBJ_OPEN) {
+ pf_new_sentence(filter);
+ lib_print_object_np(game, container);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, container, " is", " are"));
+ if (gs_object_openness(game, container) == OBJ_LOCKED)
+ pf_buffer_string(filter, " locked!\n");
+ else
+ pf_buffer_string(filter, " closed!\n");
+ return FALSE;
+ }
+
+ /* Container is a valid target for "put in". */
+ return TRUE;
}
@@ -7779,43 +7073,41 @@ lib_put_in_is_valid (sc_gameref_t game, sc_int container)
* Put all objects currently held by the player into a container.
*/
sc_bool
-lib_cmd_put_all_in (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int container, objects;
- sc_bool is_ambiguous;
+lib_cmd_put_all_in(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int container, objects;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- container = lib_disambiguate_object (game, "put that into", &is_ambiguous);
- if (container == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ container = lib_disambiguate_object(game, "put that into", &is_ambiguous);
+ if (container == -1)
+ return is_ambiguous;
- /* Validate the container object to take from. */
- if (!lib_put_in_is_valid (game, container))
- return TRUE;
+ /* Validate the container object to take from. */
+ if (!lib_put_in_is_valid(game, container))
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- gs_set_multiple_references (game);
- objects = lib_apply_multiple_filter (game,
- lib_put_in_not_container_filter,
- container, NULL);
- gs_clear_multiple_references (game);
- if (objects > 0)
- lib_put_in_backend (game, container);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You're not carrying anything",
- "I'm not carrying anything",
- "%player%'s not carrying anything"));
- if (obj_indirectly_held_by_player (game, container))
- pf_buffer_string (filter, " else");
- pf_buffer_character (filter, '.');
- }
+ /* Filter objects into references, then handle with the backend. */
+ gs_set_multiple_references(game);
+ objects = lib_apply_multiple_filter(game,
+ lib_put_in_not_container_filter,
+ container, NULL);
+ gs_clear_multiple_references(game);
+ if (objects > 0)
+ lib_put_in_backend(game, container);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You're not carrying anything",
+ "I'm not carrying anything",
+ "%player%'s not carrying anything"));
+ if (obj_indirectly_held_by_player(game, container))
+ pf_buffer_string(filter, " else");
+ pf_buffer_character(filter, '.');
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -7826,59 +7118,56 @@ lib_cmd_put_all_in (sc_gameref_t game)
* those listed in %text%.
*/
sc_bool
-lib_cmd_put_in_except_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int container, objects, references;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- container = lib_disambiguate_object (game, "put that into", &is_ambiguous);
- if (container == -1)
- return is_ambiguous;
-
- /* Parse the multiple objects list to find retain target objects. */
- if (!lib_parse_multiple_objects (game, "retain",
- lib_put_in_not_container_filter,
- container, &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
-
- /* Validate the container object to put into. */
- if (!lib_put_in_is_valid (game, container))
- return TRUE;
-
- /* As a special case, complain about requests to retain the container. */
- if (game->multiple_references[container])
- {
- pf_buffer_string (filter,
- "I only understood you as far as wanting to retain ");
- lib_print_object_np (game, container);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_except_filter (game,
- lib_put_in_not_container_filter,
- container, &references);
- if (objects > 0 || references > 0)
- lib_put_in_backend (game, container);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything",
- "I am not holding anything",
- "%player% is not holding anything"));
- if (objects == 0)
- pf_buffer_string (filter, " else");
- pf_buffer_character (filter, '.');
- }
-
- pf_buffer_character (filter, '\n');
- return TRUE;
+lib_cmd_put_in_except_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int container, objects, references;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ container = lib_disambiguate_object(game, "put that into", &is_ambiguous);
+ if (container == -1)
+ return is_ambiguous;
+
+ /* Parse the multiple objects list to find retain target objects. */
+ if (!lib_parse_multiple_objects(game, "retain",
+ lib_put_in_not_container_filter,
+ container, &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
+
+ /* Validate the container object to put into. */
+ if (!lib_put_in_is_valid(game, container))
+ return TRUE;
+
+ /* As a special case, complain about requests to retain the container. */
+ if (game->multiple_references[container]) {
+ pf_buffer_string(filter,
+ "I only understood you as far as wanting to retain ");
+ lib_print_object_np(game, container);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_except_filter(game,
+ lib_put_in_not_container_filter,
+ container, &references);
+ if (objects > 0 || references > 0)
+ lib_put_in_backend(game, container);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything",
+ "I am not holding anything",
+ "%player% is not holding anything"));
+ if (objects == 0)
+ pf_buffer_string(filter, " else");
+ pf_buffer_character(filter, '.');
+ }
+
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -7889,46 +7178,44 @@ lib_cmd_put_in_except_multiple (sc_gameref_t game)
* object.
*/
sc_bool
-lib_cmd_put_in_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int container, objects, references;
- sc_bool is_ambiguous;
+lib_cmd_put_in_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int container, objects, references;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- container = lib_disambiguate_object (game, "put that into", &is_ambiguous);
- if (container == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ container = lib_disambiguate_object(game, "put that into", &is_ambiguous);
+ if (container == -1)
+ return is_ambiguous;
- /* Parse the multiple objects list to find retain target objects. */
- if (!lib_parse_multiple_objects (game, "move",
- lib_put_in_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find retain target objects. */
+ if (!lib_parse_multiple_objects(game, "move",
+ lib_put_in_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Validate the container object to put into. */
- if (!lib_put_in_is_valid (game, container))
- return TRUE;
+ /* Validate the container object to put into. */
+ if (!lib_put_in_is_valid(game, container))
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_multiple_filter (game,
- lib_put_in_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_put_in_backend (game, container);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything.",
- "I am not holding anything.",
- "%player% is not holding anything."));
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_multiple_filter(game,
+ lib_put_in_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_put_in_backend(game, container);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything.",
+ "I am not holding anything.",
+ "%player% is not holding anything."));
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -7939,49 +7226,43 @@ lib_cmd_put_in_multiple (sc_gameref_t game)
* TRUE if no recursion detected.
*/
static sc_bool
-lib_check_put_on_recursion (sc_gameref_t game,
- sc_int object, sc_int supporter, sc_bool report)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int check;
-
- /* Avoid the obvious possibility of infinite recursion. */
- if (supporter == object)
- {
- if (report)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't put an object onto itself!",
- "I can't put an object onto itself!",
- "%player% can't put an object onto itself!"));
- }
- return FALSE;
- }
-
- /* Avoid the subtle possibility of infinite recursion. */
- check = supporter;
- while (gs_object_position (game, check) == OBJ_ON_OBJECT
- || gs_object_position (game, check) == OBJ_IN_OBJECT)
- {
- check = gs_object_parent (game, check);
- if (check == object)
- {
- if (report)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't put an object onto one",
- "I can't put an object onto one",
- "%player% can't put an object onto one"));
- pf_buffer_string (filter, " it's on or in!");
- }
- return FALSE;
- }
- }
-
- /* No infinite recursion detected. */
- return TRUE;
+lib_check_put_on_recursion(sc_gameref_t game,
+ sc_int object, sc_int supporter, sc_bool report) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int check;
+
+ /* Avoid the obvious possibility of infinite recursion. */
+ if (supporter == object) {
+ if (report) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't put an object onto itself!",
+ "I can't put an object onto itself!",
+ "%player% can't put an object onto itself!"));
+ }
+ return FALSE;
+ }
+
+ /* Avoid the subtle possibility of infinite recursion. */
+ check = supporter;
+ while (gs_object_position(game, check) == OBJ_ON_OBJECT
+ || gs_object_position(game, check) == OBJ_IN_OBJECT) {
+ check = gs_object_parent(game, check);
+ if (check == object) {
+ if (report) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't put an object onto one",
+ "I can't put an object onto one",
+ "%player% can't put an object onto one"));
+ pf_buffer_string(filter, " it's on or in!");
+ }
+ return FALSE;
+ }
+ }
+
+ /* No infinite recursion detected. */
+ return TRUE;
}
@@ -7996,138 +7277,120 @@ lib_check_put_on_recursion (sc_gameref_t game,
* deemed not actionable are flagged in multiple_references.
*/
static void
-lib_put_on_backend (sc_gameref_t game, sc_int supporter)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object_count, object, count, trail;
- sc_bool has_printed;
-
- /*
- * Try game commands for all referenced objects first. If any succeed,
- * remove that reference from the list. At the same time, check for and
- * weed out any moves that result in infinite recursion.
- */
- has_printed = FALSE;
- object_count = gs_object_count (game);
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- /* Reject and remove attempts to place objects on themselves. */
- if (!lib_check_put_on_recursion (game, object, supporter, !has_printed))
- {
- game->object_references[object] = FALSE;
- has_printed = TRUE;
- continue;
- }
-
- if (lib_try_game_command_with_object (game,
- "put", object, "on", supporter))
- {
- game->object_references[object] = FALSE;
- has_printed = TRUE;
- }
- }
-
- /* Put on every object that remains referenced. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->object_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You put ",
- "I put ",
- "%player% puts "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- gs_object_move_onto (game, object, supporter);
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You put ",
- "I put ",
- "%player% puts "));
- }
- else
- pf_buffer_string (filter, " and ");
- lib_print_object_np (game, trail);
- pf_buffer_string (filter, " onto ");
- lib_print_object_np (game, supporter);
- pf_buffer_character (filter, '.');
- }
- has_printed |= count > 0;
-
- /* Note any remaining multiple references left out of the operation. */
- count = 0;
- trail = -1;
- for (object = 0; object < object_count; object++)
- {
- if (!game->multiple_references[object])
- continue;
-
- if (count > 0)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- }
- else
- pf_buffer_string (filter, ", ");
- lib_print_object_np (game, trail);
- }
- trail = object;
- count++;
-
- game->multiple_references[object] = FALSE;
- }
-
- if (count >= 1)
- {
- if (count == 1)
- {
- if (has_printed)
- pf_buffer_string (filter, " ");
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- }
- else
- pf_buffer_string (filter, " or ");
- lib_print_object_np (game, trail);
- pf_buffer_character (filter, '.');
- }
+lib_put_on_backend(sc_gameref_t game, sc_int supporter) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object_count, object, count, trail;
+ sc_bool has_printed;
+
+ /*
+ * Try game commands for all referenced objects first. If any succeed,
+ * remove that reference from the list. At the same time, check for and
+ * weed out any moves that result in infinite recursion.
+ */
+ has_printed = FALSE;
+ object_count = gs_object_count(game);
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ /* Reject and remove attempts to place objects on themselves. */
+ if (!lib_check_put_on_recursion(game, object, supporter, !has_printed)) {
+ game->object_references[object] = FALSE;
+ has_printed = TRUE;
+ continue;
+ }
+
+ if (lib_try_game_command_with_object(game,
+ "put", object, "on", supporter)) {
+ game->object_references[object] = FALSE;
+ has_printed = TRUE;
+ }
+ }
+
+ /* Put on every object that remains referenced. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->object_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You put ",
+ "I put ",
+ "%player% puts "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ gs_object_move_onto(game, object, supporter);
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You put ",
+ "I put ",
+ "%player% puts "));
+ } else
+ pf_buffer_string(filter, " and ");
+ lib_print_object_np(game, trail);
+ pf_buffer_string(filter, " onto ");
+ lib_print_object_np(game, supporter);
+ pf_buffer_character(filter, '.');
+ }
+ has_printed |= count > 0;
+
+ /* Note any remaining multiple references left out of the operation. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < object_count; object++) {
+ if (!game->multiple_references[object])
+ continue;
+
+ if (count > 0) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ } else
+ pf_buffer_string(filter, ", ");
+ lib_print_object_np(game, trail);
+ }
+ trail = object;
+ count++;
+
+ game->multiple_references[object] = FALSE;
+ }
+
+ if (count >= 1) {
+ if (count == 1) {
+ if (has_printed)
+ pf_buffer_string(filter, " ");
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ } else
+ pf_buffer_string(filter, " or ");
+ lib_print_object_np(game, trail);
+ pf_buffer_character(filter, '.');
+ }
}
@@ -8139,19 +7402,17 @@ lib_put_on_backend (sc_gameref_t game, sc_int supporter)
* context. Returns TRUE if an object may be manipulated, FALSE otherwise.
*/
static sc_bool
-lib_put_on_filter (sc_gameref_t game, sc_int object, sc_int unused)
-{
- assert (unused == -1);
+lib_put_on_filter(sc_gameref_t game, sc_int object, sc_int unused) {
+ assert(unused == -1);
- return !obj_is_static (game, object)
- && gs_object_position (game, object) == OBJ_HELD_PLAYER;
+ return !obj_is_static(game, object)
+ && gs_object_position(game, object) == OBJ_HELD_PLAYER;
}
static sc_bool
-lib_put_on_not_supporter_filter (sc_gameref_t game,
- sc_int object, sc_int supporter)
-{
- return lib_put_on_filter (game, object, -1) && object != supporter;
+lib_put_on_not_supporter_filter(sc_gameref_t game,
+ sc_int object, sc_int supporter) {
+ return lib_put_on_filter(game, object, -1) && object != supporter;
}
@@ -8161,25 +7422,23 @@ lib_put_on_not_supporter_filter (sc_gameref_t game,
* Validate the supporter requested in "put on" commands.
*/
static sc_bool
-lib_put_on_is_valid (sc_gameref_t game, sc_int supporter)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_put_on_is_valid(sc_gameref_t game, sc_int supporter) {
+ const sc_filterref_t filter = gs_get_filter(game);
- /* Verify that the supporter object is a supporter. */
- if (!obj_is_surface (game, supporter))
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't put anything on ",
- "I can't put anything on ",
- "%player% can't put anything on "));
- lib_print_object_np (game, supporter);
- pf_buffer_string (filter, "!\n");
- return FALSE;
- }
+ /* Verify that the supporter object is a supporter. */
+ if (!obj_is_surface(game, supporter)) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't put anything on ",
+ "I can't put anything on ",
+ "%player% can't put anything on "));
+ lib_print_object_np(game, supporter);
+ pf_buffer_string(filter, "!\n");
+ return FALSE;
+ }
- /* Surface is a valid target for "put on". */
- return TRUE;
+ /* Surface is a valid target for "put on". */
+ return TRUE;
}
@@ -8189,43 +7448,41 @@ lib_put_on_is_valid (sc_gameref_t game, sc_int supporter)
* Put all objects currently held by the player onto a supporter.
*/
sc_bool
-lib_cmd_put_all_on (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int supporter, objects;
- sc_bool is_ambiguous;
+lib_cmd_put_all_on(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int supporter, objects;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- supporter = lib_disambiguate_object (game, "put that onto", &is_ambiguous);
- if (supporter == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ supporter = lib_disambiguate_object(game, "put that onto", &is_ambiguous);
+ if (supporter == -1)
+ return is_ambiguous;
- /* Validate the supporter object to take from. */
- if (!lib_put_on_is_valid (game, supporter))
- return TRUE;
+ /* Validate the supporter object to take from. */
+ if (!lib_put_on_is_valid(game, supporter))
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- gs_set_multiple_references (game);
- objects = lib_apply_multiple_filter (game,
- lib_put_on_not_supporter_filter,
- supporter, NULL);
- gs_clear_multiple_references (game);
- if (objects > 0)
- lib_put_on_backend (game, supporter);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You're not carrying anything",
- "I'm not carrying anything",
- "%player%'s not carrying anything"));
- if (obj_indirectly_held_by_player (game, supporter))
- pf_buffer_string (filter, " else");
- pf_buffer_character (filter, '.');
- }
+ /* Filter objects into references, then handle with the backend. */
+ gs_set_multiple_references(game);
+ objects = lib_apply_multiple_filter(game,
+ lib_put_on_not_supporter_filter,
+ supporter, NULL);
+ gs_clear_multiple_references(game);
+ if (objects > 0)
+ lib_put_on_backend(game, supporter);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You're not carrying anything",
+ "I'm not carrying anything",
+ "%player%'s not carrying anything"));
+ if (obj_indirectly_held_by_player(game, supporter))
+ pf_buffer_string(filter, " else");
+ pf_buffer_character(filter, '.');
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -8236,59 +7493,56 @@ lib_cmd_put_all_on (sc_gameref_t game)
* those listed in %text%.
*/
sc_bool
-lib_cmd_put_on_except_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int supporter, objects, references;
- sc_bool is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- supporter = lib_disambiguate_object (game, "put that onto", &is_ambiguous);
- if (supporter == -1)
- return is_ambiguous;
-
- /* Parse the multiple objects list to find retain target objects. */
- if (!lib_parse_multiple_objects (game, "retain",
- lib_put_on_not_supporter_filter,
- supporter, &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
-
- /* Validate the supporter object to put into. */
- if (!lib_put_on_is_valid (game, supporter))
- return TRUE;
-
- /* As a special case, complain about requests to retain the supporter. */
- if (game->multiple_references[supporter])
- {
- pf_buffer_string (filter,
- "I only understood you as far as wanting to retain ");
- lib_print_object_np (game, supporter);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_except_filter (game,
- lib_put_on_not_supporter_filter,
- supporter, &references);
- if (objects > 0 || references > 0)
- lib_put_on_backend (game, supporter);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything",
- "I am not holding anything",
- "%player% is not holding anything"));
- if (objects == 0)
- pf_buffer_string (filter, " else");
- pf_buffer_character (filter, '.');
- }
-
- pf_buffer_character (filter, '\n');
- return TRUE;
+lib_cmd_put_on_except_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int supporter, objects, references;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ supporter = lib_disambiguate_object(game, "put that onto", &is_ambiguous);
+ if (supporter == -1)
+ return is_ambiguous;
+
+ /* Parse the multiple objects list to find retain target objects. */
+ if (!lib_parse_multiple_objects(game, "retain",
+ lib_put_on_not_supporter_filter,
+ supporter, &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
+
+ /* Validate the supporter object to put into. */
+ if (!lib_put_on_is_valid(game, supporter))
+ return TRUE;
+
+ /* As a special case, complain about requests to retain the supporter. */
+ if (game->multiple_references[supporter]) {
+ pf_buffer_string(filter,
+ "I only understood you as far as wanting to retain ");
+ lib_print_object_np(game, supporter);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_except_filter(game,
+ lib_put_on_not_supporter_filter,
+ supporter, &references);
+ if (objects > 0 || references > 0)
+ lib_put_on_backend(game, supporter);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything",
+ "I am not holding anything",
+ "%player% is not holding anything"));
+ if (objects == 0)
+ pf_buffer_string(filter, " else");
+ pf_buffer_character(filter, '.');
+ }
+
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -8299,46 +7553,44 @@ lib_cmd_put_on_except_multiple (sc_gameref_t game)
* object.
*/
sc_bool
-lib_cmd_put_on_multiple (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int supporter, objects, references;
- sc_bool is_ambiguous;
+lib_cmd_put_on_multiple(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int supporter, objects, references;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- supporter = lib_disambiguate_object (game, "put that onto", &is_ambiguous);
- if (supporter == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ supporter = lib_disambiguate_object(game, "put that onto", &is_ambiguous);
+ if (supporter == -1)
+ return is_ambiguous;
- /* Parse the multiple objects list to find retain target objects. */
- if (!lib_parse_multiple_objects (game, "move",
- lib_put_on_filter, -1,
- &references))
- return FALSE;
- else if (references == 0)
- return TRUE;
+ /* Parse the multiple objects list to find retain target objects. */
+ if (!lib_parse_multiple_objects(game, "move",
+ lib_put_on_filter, -1,
+ &references))
+ return FALSE;
+ else if (references == 0)
+ return TRUE;
- /* Validate the supporter object to put into. */
- if (!lib_put_on_is_valid (game, supporter))
- return TRUE;
+ /* Validate the supporter object to put into. */
+ if (!lib_put_on_is_valid(game, supporter))
+ return TRUE;
- /* Filter objects into references, then handle with the backend. */
- objects = lib_apply_multiple_filter (game,
- lib_put_on_filter, -1,
- &references);
- if (objects > 0 || references > 0)
- lib_put_on_backend (game, supporter);
- else
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding anything.",
- "I am not holding anything.",
- "%player% is not holding anything."));
- }
+ /* Filter objects into references, then handle with the backend. */
+ objects = lib_apply_multiple_filter(game,
+ lib_put_on_filter, -1,
+ &references);
+ if (objects > 0 || references > 0)
+ lib_put_on_backend(game, supporter);
+ else {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding anything.",
+ "I am not holding anything.",
+ "%player% is not holding anything."));
+ }
- pf_buffer_character (filter, '\n');
- return TRUE;
+ pf_buffer_character(filter, '\n');
+ return TRUE;
}
@@ -8349,84 +7601,79 @@ lib_cmd_put_on_multiple (sc_gameref_t game)
* Attempt to read the referenced object, or something else.
*/
sc_bool
-lib_cmd_read_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int object, task;
- sc_bool is_readable, is_ambiguous;
- const sc_char *readtext, *description;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "read", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Verify that the object is readable. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Readable";
- is_readable = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (!is_readable)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't read ",
- "I can't read ",
- "%player% can't read "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, "!\n");
- return TRUE;
- }
-
- /* Get and print the object's read text, if any. */
- vt_key[2].string = "ReadText";
- readtext = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (readtext))
- {
- pf_buffer_string (filter, readtext);
- pf_buffer_character (filter, '\n');
- return TRUE;
- }
-
- /* Degrade to a shortened object examine. */
- vt_key[2].string = "Task";
- task = prop_get_integer (bundle, "I<-sis", vt_key) - 1;
-
- /* Select either the main or the alternate description. */
- if (task >= 0 && gs_task_done (game, task))
- vt_key[2].string = "AltDesc";
- else
- vt_key[2].string = "Description";
-
- /* Print the description, or a "nothing special" default. */
- description = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (description))
- pf_buffer_string (filter, description);
- else
- {
- pf_buffer_string (filter, "There is nothing special about ");
- lib_print_object_np (game, object);
- pf_buffer_character (filter, '.');
- }
-
- pf_buffer_character (filter, '\n');
- return TRUE;
-}
-
-sc_bool
-lib_cmd_read_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- /* Reject the attempt. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You see no such thing.\n",
- "I see no such thing.\n",
- "%player% sees no such thing.\n"));
- return TRUE;
+lib_cmd_read_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int object, task;
+ sc_bool is_readable, is_ambiguous;
+ const sc_char *readtext, *description;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "read", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Verify that the object is readable. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Readable";
+ is_readable = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (!is_readable) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't read ",
+ "I can't read ",
+ "%player% can't read "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, "!\n");
+ return TRUE;
+ }
+
+ /* Get and print the object's read text, if any. */
+ vt_key[2].string = "ReadText";
+ readtext = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(readtext)) {
+ pf_buffer_string(filter, readtext);
+ pf_buffer_character(filter, '\n');
+ return TRUE;
+ }
+
+ /* Degrade to a shortened object examine. */
+ vt_key[2].string = "Task";
+ task = prop_get_integer(bundle, "I<-sis", vt_key) - 1;
+
+ /* Select either the main or the alternate description. */
+ if (task >= 0 && gs_task_done(game, task))
+ vt_key[2].string = "AltDesc";
+ else
+ vt_key[2].string = "Description";
+
+ /* Print the description, or a "nothing special" default. */
+ description = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(description))
+ pf_buffer_string(filter, description);
+ else {
+ pf_buffer_string(filter, "There is nothing special about ");
+ lib_print_object_np(game, object);
+ pf_buffer_character(filter, '.');
+ }
+
+ pf_buffer_character(filter, '\n');
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_read_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ /* Reject the attempt. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You see no such thing.\n",
+ "I see no such thing.\n",
+ "%player% sees no such thing.\n"));
+ return TRUE;
}
@@ -8437,103 +7684,96 @@ lib_cmd_read_other (sc_gameref_t game)
* Attempt to attack an NPC, with and without weaponry.
*/
sc_bool
-lib_cmd_attack_npc (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int npc;
- sc_bool is_ambiguous;
-
- /* Get the referenced npc, and if none, consider complete. */
- npc = lib_disambiguate_npc (game, "attack", &is_ambiguous);
- if (npc == -1)
- return is_ambiguous;
-
- /* Print a standard response. */
- pf_new_sentence (filter);
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter,
- lib_select_response (game,
- " avoids your feeble attempts.\n",
- " avoids my feeble attempts.\n",
- " avoids %player%'s feeble attempts.\n"));
- return TRUE;
-}
-
-sc_bool
-lib_cmd_attack_npc_with (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, npc;
- sc_vartype_t vt_key[3];
- sc_bool weapon, is_ambiguous;
-
- /* Get the referenced npc, and if none, consider complete. */
- npc = lib_disambiguate_npc (game, "attack", &is_ambiguous);
- if (npc == -1)
- return is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "attack with", NULL);
- if (object == -1)
- return TRUE;
-
- /* Ensure the referenced object is held. */
- if (gs_object_position (game, object) != OBJ_HELD_PLAYER)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- /* Check for static object moved to player by event. */
- if (obj_is_static (game, object))
- {
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object, " is", " are"));
- pf_buffer_string (filter, " not a weapon.\n");
- return TRUE;
- }
-
- /* Print standard response depending on if the object is a weapon. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Weapon";
- weapon = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (weapon)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You swing at ",
- "I swing at ",
- "%player% swings at "));
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " with ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_response (game,
- " but you miss.\n",
- " but I miss.\n",
- " but misses.\n"));
- }
- else
- {
- /*
- * TODO Adrift uses "affective" [sic] here. Should SCARE be right, or
- * bug-compatible?
- */
- pf_buffer_string (filter, "I don't think ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " would be a very effective weapon.\n");
- }
- return TRUE;
+lib_cmd_attack_npc(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int npc;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced npc, and if none, consider complete. */
+ npc = lib_disambiguate_npc(game, "attack", &is_ambiguous);
+ if (npc == -1)
+ return is_ambiguous;
+
+ /* Print a standard response. */
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " avoids your feeble attempts.\n",
+ " avoids my feeble attempts.\n",
+ " avoids %player%'s feeble attempts.\n"));
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_attack_npc_with(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, npc;
+ sc_vartype_t vt_key[3];
+ sc_bool weapon, is_ambiguous;
+
+ /* Get the referenced npc, and if none, consider complete. */
+ npc = lib_disambiguate_npc(game, "attack", &is_ambiguous);
+ if (npc == -1)
+ return is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "attack with", NULL);
+ if (object == -1)
+ return TRUE;
+
+ /* Ensure the referenced object is held. */
+ if (gs_object_position(game, object) != OBJ_HELD_PLAYER) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ /* Check for static object moved to player by event. */
+ if (obj_is_static(game, object)) {
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object, " is", " are"));
+ pf_buffer_string(filter, " not a weapon.\n");
+ return TRUE;
+ }
+
+ /* Print standard response depending on if the object is a weapon. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Weapon";
+ weapon = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (weapon) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You swing at ",
+ "I swing at ",
+ "%player% swings at "));
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " with ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " but you miss.\n",
+ " but I miss.\n",
+ " but misses.\n"));
+ } else {
+ /*
+ * TODO Adrift uses "affective" [sic] here. Should SCARE be right, or
+ * bug-compatible?
+ */
+ pf_buffer_string(filter, "I don't think ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " would be a very effective weapon.\n");
+ }
+ return TRUE;
}
@@ -8545,72 +7785,68 @@ lib_cmd_attack_npc_with (sc_gameref_t game)
* Reject romantic advances in all cases.
*/
sc_bool
-lib_cmd_kiss_npc (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int npc, gender;
- sc_bool is_ambiguous;
+lib_cmd_kiss_npc(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int npc, gender;
+ sc_bool is_ambiguous;
- /* Get the referenced npc, and if none, consider complete. */
- npc = lib_disambiguate_npc (game, "kiss", &is_ambiguous);
- if (npc == -1)
- return is_ambiguous;
+ /* Get the referenced npc, and if none, consider complete. */
+ npc = lib_disambiguate_npc(game, "kiss", &is_ambiguous);
+ if (npc == -1)
+ return is_ambiguous;
- /* Reject this attempt. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Gender";
- gender = prop_get_integer (bundle, "I<-sis", vt_key);
+ /* Reject this attempt. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Gender";
+ gender = prop_get_integer(bundle, "I<-sis", vt_key);
- switch (gender)
- {
- case NPC_MALE:
- pf_buffer_string (filter, "I'm not sure he would appreciate that!\n");
- break;
+ switch (gender) {
+ case NPC_MALE:
+ pf_buffer_string(filter, "I'm not sure he would appreciate that!\n");
+ break;
- case NPC_FEMALE:
- pf_buffer_string (filter, "I'm not sure she would appreciate that!\n");
- break;
+ case NPC_FEMALE:
+ pf_buffer_string(filter, "I'm not sure she would appreciate that!\n");
+ break;
- case NPC_NEUTER:
- pf_buffer_string (filter, "I'm not sure it would appreciate that!\n");
- break;
+ case NPC_NEUTER:
+ pf_buffer_string(filter, "I'm not sure it would appreciate that!\n");
+ break;
- default:
- sc_error ("lib_cmd_kiss_npc: unknown gender, %ld\n", gender);
- }
- return TRUE;
+ default:
+ sc_error("lib_cmd_kiss_npc: unknown gender, %ld\n", gender);
+ }
+ return TRUE;
}
sc_bool
-lib_cmd_kiss_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
+lib_cmd_kiss_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "kiss", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "kiss", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
- /* Reject this attempt. */
- pf_buffer_string (filter, "I'm not sure ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " would appreciate that.\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter, "I'm not sure ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " would appreciate that.\n");
+ return TRUE;
}
sc_bool
-lib_cmd_kiss_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_kiss_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- /* Reject this attempt. */
- pf_buffer_string (filter, "I'm not sure it would appreciate that.\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter, "I'm not sure it would appreciate that.\n");
+ return TRUE;
}
@@ -8621,34 +7857,32 @@ lib_cmd_kiss_other (sc_gameref_t game)
* Standard responses to attempts to buy something.
*/
sc_bool
-lib_cmd_buy_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
+lib_cmd_buy_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "buy", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "buy", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
- /* Reject this attempt. */
- pf_buffer_string (filter, "I don't think ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object, " is", " are"));
- pf_buffer_string (filter, " for sale.\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter, "I don't think ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object, " is", " are"));
+ pf_buffer_string(filter, " for sale.\n");
+ return TRUE;
}
sc_bool
-lib_cmd_buy_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_buy_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- /* Reject this attempt. */
- pf_buffer_string (filter, "I don't think that is for sale.\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter, "I don't think that is for sale.\n");
+ return TRUE;
}
@@ -8659,40 +7893,38 @@ lib_cmd_buy_other (sc_gameref_t game)
* Standard responses to attempts to break something.
*/
sc_bool
-lib_cmd_break_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
+lib_cmd_break_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "break", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "break", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
- /* Reject this attempt. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You might need ",
- "I might need ",
- "%player% might need "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You might need ",
+ "I might need ",
+ "%player% might need "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
sc_bool
-lib_cmd_break_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_break_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- /* Reject this attempt. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You might need that.\n",
- "I might need that.\n",
- "%player% might need that.\n"));
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You might need that.\n",
+ "I might need that.\n",
+ "%player% might need that.\n"));
+ return TRUE;
}
@@ -8703,32 +7935,30 @@ lib_cmd_break_other (sc_gameref_t game)
* Standard responses to attempts to smell something.
*/
sc_bool
-lib_cmd_smell_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
+lib_cmd_smell_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "smell", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "smell", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
- /* Reject this attempt. */
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " smells normal.\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " smells normal.\n");
+ return TRUE;
}
sc_bool
-lib_cmd_smell_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_smell_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- /* Reject this attempt. */
- pf_buffer_string (filter, "That smells normal.\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter, "That smells normal.\n");
+ return TRUE;
}
@@ -8739,31 +7969,29 @@ lib_cmd_smell_other (sc_gameref_t game)
* Standard responses to attempts to sell something.
*/
sc_bool
-lib_cmd_sell_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
+lib_cmd_sell_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "sell", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "sell", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
- /* Reject this attempt. */
- pf_buffer_string (filter, "No-one is interested in buying ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+ /* Reject this attempt. */
+ pf_buffer_string(filter, "No-one is interested in buying ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
sc_bool
-lib_cmd_sell_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_sell_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "No-one is interested in buying that.\n");
- return TRUE;
+ pf_buffer_string(filter, "No-one is interested in buying that.\n");
+ return TRUE;
}
@@ -8773,83 +8001,79 @@ lib_cmd_sell_other (sc_gameref_t game)
* Consume edible objects.
*/
sc_bool
-lib_cmd_eat_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int object;
- sc_bool edible, is_ambiguous;
-
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "eat", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Check that we have the object to eat. */
- if (gs_object_position (game, object) != OBJ_HELD_PLAYER)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not holding ",
- "I am not holding ",
- "%player% is not holding "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- /* Check for static object moved to player by event. */
- if (obj_is_static (game, object))
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't eat ",
- "I can't eat ",
- "%player% can't eat "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- /* Is this object inedible? */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Edible";
- edible = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (!edible)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't eat ",
- "I can't eat ",
- "%player% can't eat "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
-
- /* Confirm, and hide the object. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You eat ",
- "I eat ", "%player% eats "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- ". Not bad, but it could do with a pinch of salt!\n");
- gs_object_make_hidden (game, object);
- return TRUE;
+lib_cmd_eat_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int object;
+ sc_bool edible, is_ambiguous;
+
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "eat", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Check that we have the object to eat. */
+ if (gs_object_position(game, object) != OBJ_HELD_PLAYER) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not holding ",
+ "I am not holding ",
+ "%player% is not holding "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ /* Check for static object moved to player by event. */
+ if (obj_is_static(game, object)) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't eat ",
+ "I can't eat ",
+ "%player% can't eat "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ /* Is this object inedible? */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Edible";
+ edible = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (!edible) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't eat ",
+ "I can't eat ",
+ "%player% can't eat "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+
+ /* Confirm, and hide the object. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You eat ",
+ "I eat ", "%player% eats "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ ". Not bad, but it could do with a pinch of salt!\n");
+ gs_object_make_hidden(game, object);
+ return TRUE;
}
/* Enumerated sit/stand/lie types. */
-enum
-{ OBJ_STANDABLE_MASK = 1 << 0,
- OBJ_LIEABLE_MASK = 1 << 1
+enum {
+ OBJ_STANDABLE_MASK = 1 << 0,
+ OBJ_LIEABLE_MASK = 1 << 1
};
-enum
-{ MOVE_SIT, MOVE_SIT_FLOOR,
- MOVE_STAND, MOVE_STAND_FLOOR, MOVE_LIE, MOVE_LIE_FLOOR
+enum {
+ MOVE_SIT, MOVE_SIT_FLOOR,
+ MOVE_STAND, MOVE_STAND_FLOOR, MOVE_LIE, MOVE_LIE_FLOOR
};
/*
@@ -8858,221 +8082,209 @@ enum
* Central handler for stand, sit, and lie commands.
*/
static sc_bool
-lib_stand_sit_lie (sc_gameref_t game, sc_int movement)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, position;
- const sc_char *already_doing_that, *success_message;
-
- /* Initialize variables to avoid gcc warnings. */
- object = -1;
- already_doing_that = FALSE;
- success_message = FALSE;
- position = 0;
-
- /* Get a target object for movement, -1 if floor. */
- switch (movement)
- {
- case MOVE_STAND:
- case MOVE_SIT:
- case MOVE_LIE:
- {
- const sc_char *disambiguate, *cant_do_that;
- sc_int sit_lie_flags, movement_mask;
- sc_vartype_t vt_key[3];
- sc_bool is_ambiguous;
-
- /* Initialize variables to avoid gcc warnings. */
- disambiguate = NULL;
- cant_do_that = NULL;
- movement_mask = 0;
-
- /* Set disambiguation and not amenable messages. */
- switch (movement)
- {
- case MOVE_STAND:
- disambiguate = "stand on";
- cant_do_that = lib_select_response (game,
- "You can't stand on ",
- "I can't stand on ",
- "%player% can't stand on ");
- movement_mask = OBJ_STANDABLE_MASK;
- break;
- case MOVE_SIT:
- disambiguate = "sit on";
- cant_do_that = lib_select_response (game,
- "You can't sit on ",
- "I can't sit on ",
- "%player% can't sit on ");
- movement_mask = OBJ_STANDABLE_MASK;
- break;
- case MOVE_LIE:
- disambiguate = "lie on";
- cant_do_that = lib_select_response (game,
- "You can't lie on ",
- "I can't lie on ",
- "%player% can't lie on ");
- movement_mask = OBJ_LIEABLE_MASK;
- break;
- default:
- sc_fatal ("lib_sit_stand_lie: movement error, %ld\n", movement);
- }
-
- /* Get the referenced object; if none, consider complete. */
- object = lib_disambiguate_object (game, disambiguate, &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Verify the referenced object is amenable. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "SitLie";
- sit_lie_flags = prop_get_integer (bundle, "I<-sis", vt_key);
- if (!(sit_lie_flags & movement_mask))
- {
- pf_buffer_string (filter, cant_do_that);
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
- }
- break;
- }
-
- case MOVE_STAND_FLOOR:
- case MOVE_SIT_FLOOR:
- case MOVE_LIE_FLOOR:
- object = -1;
- break;
-
- default:
- sc_fatal ("lib_sit_stand_lie: movement error, %ld\n", movement);
- }
-
- /* Set up confirmation messages and position. */
- switch (movement)
- {
- case MOVE_STAND:
- already_doing_that = lib_select_response (game,
- "You are already standing on ",
- "I am already standing on ",
- "%player% is already standing on ");
- success_message = lib_select_response (game,
- "You stand on ",
- "I stand on ",
- "%player% stands on ");
- position = 0;
- break;
-
- case MOVE_STAND_FLOOR:
- already_doing_that = lib_select_response (game,
- "You are already standing!\n",
- "I am already standing!\n",
- "%player% is already standing!\n");
- success_message = lib_select_response (game,
- "You stand up",
- "I stand up",
- "%player% stands up");
- position = 0;
- break;
-
- case MOVE_SIT:
- already_doing_that = lib_select_response (game,
- "You are already sitting on ",
- "I am already sitting on ",
- "%player% is already sitting on ");
- if (gs_playerposition (game) == 2)
- success_message = lib_select_response (game,
- "You sit up on ",
- "I sit up on ",
- "%player% sits up on ");
- else
- success_message = lib_select_response (game,
- "You sit down on ",
- "I sit down on ",
- "%player% sits down on ");
- position = 1;
- break;
-
- case MOVE_SIT_FLOOR:
- already_doing_that = lib_select_response (game,
- "You are already sitting down.\n",
- "I am already sitting down.\n",
- "%player% is already sitting down.\n");
- if (gs_playerposition (game) == 2)
- success_message = lib_select_response (game,
- "You sit up on the ground.\n",
- "I sit up on the ground.\n",
- "%player% sits up on the ground.\n");
- else
- success_message = lib_select_response (game,
- "You sit down on the ground.\n",
- "I sit down on the ground.\n",
- "%player% sits down on the ground.\n");
- position = 1;
- break;
-
- case MOVE_LIE:
- already_doing_that = lib_select_response (game,
- "You are already lying on ",
- "I am already lying on ",
- "%player% is already lying on ");
- success_message = lib_select_response (game,
- "You lie down on ",
- "I lie down on ",
- "%player% lies down on ");
- position = 2;
- break;
-
- case MOVE_LIE_FLOOR:
- already_doing_that = lib_select_response (game,
- "You are already lying down.\n",
- "I am already lying down.\n",
- "%player% is already lying down.\n");
- success_message = lib_select_response (game,
- "You lie down on the ground.\n",
- "I lie down on the ground.\n",
- "%player% lies down on the ground.\n");
- position = 2;
- break;
-
- default:
- sc_fatal ("lib_sit_stand_lie: movement error, %ld\n", movement);
- }
-
- /* See if already doing this. */
- if (gs_playerposition (game) == position && gs_playerparent (game) == object)
- {
- pf_buffer_string (filter, already_doing_that);
- if (object != -1)
- {
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- }
- return TRUE;
- }
-
- /* Confirm movement, with special case for getting off an object. */
- pf_buffer_string (filter, success_message);
- if (movement == MOVE_STAND_FLOOR)
- {
- if (gs_playerparent (game) != -1)
- {
- pf_buffer_string (filter, " from ");
- lib_print_object_np (game, gs_playerparent (game));
- }
- pf_buffer_string (filter, ".\n");
- }
- else if (object != -1)
- {
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- }
-
- /* Adjust player position and parent. */
- gs_set_playerposition (game, position);
- gs_set_playerparent (game, object);
- return TRUE;
+lib_stand_sit_lie(sc_gameref_t game, sc_int movement) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, position;
+ const sc_char *already_doing_that, *success_message;
+
+ /* Initialize variables to avoid gcc warnings. */
+ object = -1;
+ already_doing_that = FALSE;
+ success_message = FALSE;
+ position = 0;
+
+ /* Get a target object for movement, -1 if floor. */
+ switch (movement) {
+ case MOVE_STAND:
+ case MOVE_SIT:
+ case MOVE_LIE: {
+ const sc_char *disambiguate, *cant_do_that;
+ sc_int sit_lie_flags, movement_mask;
+ sc_vartype_t vt_key[3];
+ sc_bool is_ambiguous;
+
+ /* Initialize variables to avoid gcc warnings. */
+ disambiguate = NULL;
+ cant_do_that = NULL;
+ movement_mask = 0;
+
+ /* Set disambiguation and not amenable messages. */
+ switch (movement) {
+ case MOVE_STAND:
+ disambiguate = "stand on";
+ cant_do_that = lib_select_response(game,
+ "You can't stand on ",
+ "I can't stand on ",
+ "%player% can't stand on ");
+ movement_mask = OBJ_STANDABLE_MASK;
+ break;
+ case MOVE_SIT:
+ disambiguate = "sit on";
+ cant_do_that = lib_select_response(game,
+ "You can't sit on ",
+ "I can't sit on ",
+ "%player% can't sit on ");
+ movement_mask = OBJ_STANDABLE_MASK;
+ break;
+ case MOVE_LIE:
+ disambiguate = "lie on";
+ cant_do_that = lib_select_response(game,
+ "You can't lie on ",
+ "I can't lie on ",
+ "%player% can't lie on ");
+ movement_mask = OBJ_LIEABLE_MASK;
+ break;
+ default:
+ sc_fatal("lib_sit_stand_lie: movement error, %ld\n", movement);
+ }
+
+ /* Get the referenced object; if none, consider complete. */
+ object = lib_disambiguate_object(game, disambiguate, &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Verify the referenced object is amenable. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "SitLie";
+ sit_lie_flags = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (!(sit_lie_flags & movement_mask)) {
+ pf_buffer_string(filter, cant_do_that);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+ }
+ break;
+ }
+
+ case MOVE_STAND_FLOOR:
+ case MOVE_SIT_FLOOR:
+ case MOVE_LIE_FLOOR:
+ object = -1;
+ break;
+
+ default:
+ sc_fatal("lib_sit_stand_lie: movement error, %ld\n", movement);
+ }
+
+ /* Set up confirmation messages and position. */
+ switch (movement) {
+ case MOVE_STAND:
+ already_doing_that = lib_select_response(game,
+ "You are already standing on ",
+ "I am already standing on ",
+ "%player% is already standing on ");
+ success_message = lib_select_response(game,
+ "You stand on ",
+ "I stand on ",
+ "%player% stands on ");
+ position = 0;
+ break;
+
+ case MOVE_STAND_FLOOR:
+ already_doing_that = lib_select_response(game,
+ "You are already standing!\n",
+ "I am already standing!\n",
+ "%player% is already standing!\n");
+ success_message = lib_select_response(game,
+ "You stand up",
+ "I stand up",
+ "%player% stands up");
+ position = 0;
+ break;
+
+ case MOVE_SIT:
+ already_doing_that = lib_select_response(game,
+ "You are already sitting on ",
+ "I am already sitting on ",
+ "%player% is already sitting on ");
+ if (gs_playerposition(game) == 2)
+ success_message = lib_select_response(game,
+ "You sit up on ",
+ "I sit up on ",
+ "%player% sits up on ");
+ else
+ success_message = lib_select_response(game,
+ "You sit down on ",
+ "I sit down on ",
+ "%player% sits down on ");
+ position = 1;
+ break;
+
+ case MOVE_SIT_FLOOR:
+ already_doing_that = lib_select_response(game,
+ "You are already sitting down.\n",
+ "I am already sitting down.\n",
+ "%player% is already sitting down.\n");
+ if (gs_playerposition(game) == 2)
+ success_message = lib_select_response(game,
+ "You sit up on the ground.\n",
+ "I sit up on the ground.\n",
+ "%player% sits up on the ground.\n");
+ else
+ success_message = lib_select_response(game,
+ "You sit down on the ground.\n",
+ "I sit down on the ground.\n",
+ "%player% sits down on the ground.\n");
+ position = 1;
+ break;
+
+ case MOVE_LIE:
+ already_doing_that = lib_select_response(game,
+ "You are already lying on ",
+ "I am already lying on ",
+ "%player% is already lying on ");
+ success_message = lib_select_response(game,
+ "You lie down on ",
+ "I lie down on ",
+ "%player% lies down on ");
+ position = 2;
+ break;
+
+ case MOVE_LIE_FLOOR:
+ already_doing_that = lib_select_response(game,
+ "You are already lying down.\n",
+ "I am already lying down.\n",
+ "%player% is already lying down.\n");
+ success_message = lib_select_response(game,
+ "You lie down on the ground.\n",
+ "I lie down on the ground.\n",
+ "%player% lies down on the ground.\n");
+ position = 2;
+ break;
+
+ default:
+ sc_fatal("lib_sit_stand_lie: movement error, %ld\n", movement);
+ }
+
+ /* See if already doing this. */
+ if (gs_playerposition(game) == position && gs_playerparent(game) == object) {
+ pf_buffer_string(filter, already_doing_that);
+ if (object != -1) {
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ }
+ return TRUE;
+ }
+
+ /* Confirm movement, with special case for getting off an object. */
+ pf_buffer_string(filter, success_message);
+ if (movement == MOVE_STAND_FLOOR) {
+ if (gs_playerparent(game) != -1) {
+ pf_buffer_string(filter, " from ");
+ lib_print_object_np(game, gs_playerparent(game));
+ }
+ pf_buffer_string(filter, ".\n");
+ } else if (object != -1) {
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ }
+
+ /* Adjust player position and parent. */
+ gs_set_playerposition(game, position);
+ gs_set_playerparent(game, object);
+ return TRUE;
}
@@ -9084,39 +8296,33 @@ lib_stand_sit_lie (sc_gameref_t game, sc_int movement)
* Stand, sit, or lie on an object, or on the floor.
*/
sc_bool
-lib_cmd_stand_on_object (sc_gameref_t game)
-{
- return lib_stand_sit_lie (game, MOVE_STAND);
+lib_cmd_stand_on_object(sc_gameref_t game) {
+ return lib_stand_sit_lie(game, MOVE_STAND);
}
sc_bool
-lib_cmd_stand_on_floor (sc_gameref_t game)
-{
- return lib_stand_sit_lie (game, MOVE_STAND_FLOOR);
+lib_cmd_stand_on_floor(sc_gameref_t game) {
+ return lib_stand_sit_lie(game, MOVE_STAND_FLOOR);
}
sc_bool
-lib_cmd_sit_on_object (sc_gameref_t game)
-{
- return lib_stand_sit_lie (game, MOVE_SIT);
+lib_cmd_sit_on_object(sc_gameref_t game) {
+ return lib_stand_sit_lie(game, MOVE_SIT);
}
sc_bool
-lib_cmd_sit_on_floor (sc_gameref_t game)
-{
- return lib_stand_sit_lie (game, MOVE_SIT_FLOOR);
+lib_cmd_sit_on_floor(sc_gameref_t game) {
+ return lib_stand_sit_lie(game, MOVE_SIT_FLOOR);
}
sc_bool
-lib_cmd_lie_on_object (sc_gameref_t game)
-{
- return lib_stand_sit_lie (game, MOVE_LIE);
+lib_cmd_lie_on_object(sc_gameref_t game) {
+ return lib_stand_sit_lie(game, MOVE_LIE);
}
sc_bool
-lib_cmd_lie_on_floor (sc_gameref_t game)
-{
- return lib_stand_sit_lie (game, MOVE_LIE_FLOOR);
+lib_cmd_lie_on_floor(sc_gameref_t game) {
+ return lib_stand_sit_lie(game, MOVE_LIE_FLOOR);
}
@@ -9127,72 +8333,68 @@ lib_cmd_lie_on_floor (sc_gameref_t game)
* Get off whatever supporter the player rests on.
*/
sc_bool
-lib_cmd_get_off_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
-
- /* Get the referenced object; if none, consider complete. */
- object = lib_disambiguate_object (game, "get off", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Reject the attempt if the player is not on the given object. */
- if (gs_playerparent (game) != object)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not on ",
- "I am not on ",
- "%player% is not on "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, "!\n");
- return TRUE;
- }
-
- /* Confirm movement. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You get off ", "I get off ",
- "%player% gets off "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
-
- /* Adjust player position and parent. */
- gs_set_playerposition (game, 0);
- gs_set_playerparent (game, -1);
- return TRUE;
-}
-
-sc_bool
-lib_cmd_get_off (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- /* Reject the attempt if the player is not on anything. */
- if (gs_playerparent (game) == -1)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are not on anything!\n",
- "I am not on anything!\n",
- "%player% is not on anything!\n"));
- return TRUE;
- }
-
- /* Confirm movement. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You get off ", "I get off ",
- "%player% gets off "));
- lib_print_object_np (game, gs_playerparent (game));
- pf_buffer_string (filter, ".\n");
-
- /* Adjust player position and parent. */
- gs_set_playerposition (game, 0);
- gs_set_playerparent (game, -1);
- return TRUE;
+lib_cmd_get_off_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
+
+ /* Get the referenced object; if none, consider complete. */
+ object = lib_disambiguate_object(game, "get off", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Reject the attempt if the player is not on the given object. */
+ if (gs_playerparent(game) != object) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not on ",
+ "I am not on ",
+ "%player% is not on "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, "!\n");
+ return TRUE;
+ }
+
+ /* Confirm movement. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You get off ", "I get off ",
+ "%player% gets off "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+
+ /* Adjust player position and parent. */
+ gs_set_playerposition(game, 0);
+ gs_set_playerparent(game, -1);
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_get_off(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ /* Reject the attempt if the player is not on anything. */
+ if (gs_playerparent(game) == -1) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are not on anything!\n",
+ "I am not on anything!\n",
+ "%player% is not on anything!\n"));
+ return TRUE;
+ }
+
+ /* Confirm movement. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You get off ", "I get off ",
+ "%player% gets off "));
+ lib_print_object_np(game, gs_playerparent(game));
+ pf_buffer_string(filter, ".\n");
+
+ /* Adjust player position and parent. */
+ gs_set_playerposition(game, 0);
+ gs_set_playerparent(game, -1);
+ return TRUE;
}
@@ -9203,37 +8405,31 @@ lib_cmd_get_off (sc_gameref_t game)
* Save/restore a game.
*/
sc_bool
-lib_cmd_save (sc_gameref_t game)
-{
- if (if_confirm (SC_CONF_SAVE))
- {
- if (ser_save_game_prompted (game))
- if_print_string ("Ok.\n");
- else
- if_print_string ("Save failed.\n");
- }
+lib_cmd_save(sc_gameref_t game) {
+ if (if_confirm(SC_CONF_SAVE)) {
+ if (ser_save_game_prompted(game))
+ if_print_string("Ok.\n");
+ else
+ if_print_string("Save failed.\n");
+ }
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
sc_bool
-lib_cmd_restore (sc_gameref_t game)
-{
- if (if_confirm (SC_CONF_RESTORE))
- {
- if (ser_load_game_prompted (game))
- {
- if_print_string ("Ok.\n");
- game->is_running = FALSE;
- game->do_restore = TRUE;
- }
- else
- if_print_string ("Restore failed.\n");
- }
+lib_cmd_restore(sc_gameref_t game) {
+ if (if_confirm(SC_CONF_RESTORE)) {
+ if (ser_load_game_prompted(game)) {
+ if_print_string("Ok.\n");
+ game->is_running = FALSE;
+ game->do_restore = TRUE;
+ } else
+ if_print_string("Restore failed.\n");
+ }
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -9244,300 +8440,268 @@ lib_cmd_restore (sc_gameref_t game)
* Display the location of a selected object, and selected NPC.
*/
sc_bool
-lib_cmd_locate_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int index_, count, object, room, position, parent;
-
- game->is_admin = TRUE;
-
- /*
- * Filter to remove unseen object references. Note that this is different
- * from NPCs, who we acknowledge even when unseen.
- */
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (!gs_object_seen (game, index_))
- game->object_references[index_] = FALSE;
- }
-
- /* Count the number of objects referenced by the last command. */
- count = 0;
- object = -1;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (game->object_references[index_])
- {
- count++;
- object = index_;
- }
- }
-
- /*
- * If no objects identified, be coy about revealing anything; if more than
- * one, be vague.
- */
- if (count == 0)
- {
- pf_buffer_string (filter, "I don't know where that is.\n");
- return TRUE;
- }
- else if (count > 1)
- {
- pf_buffer_string (filter,
- "Please be more clear about what you want to"
- " locate.\n");
- return TRUE;
- }
-
- /*
- * The reference is unambiguous, so we're responsible for noting it in
- * variables. Disambiguation would normally do this for us, but we just
- * bypassed it.
- */
- var_set_ref_object (vars, object);
-
- /* See if we can print a message based on position and parent. */
- position = gs_object_position (game, object);
- parent = gs_object_parent (game, object);
- switch (position)
- {
- case OBJ_HIDDEN:
- if (!obj_is_static (game, object))
- {
- pf_buffer_string (filter, "I don't know where that is.\n");
- return TRUE;
- }
- break;
-
- case OBJ_HELD_PLAYER:
- pf_new_sentence (filter);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are carrying ",
- "I am carrying ",
- "%player% is carrying "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, "!\n");
- return TRUE;
-
- case OBJ_WORN_PLAYER:
- pf_new_sentence (filter);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You are wearing ",
- "I am wearing ",
- "%player% is wearing "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, "!\n");
- return TRUE;
-
- case OBJ_HELD_NPC:
- case OBJ_WORN_NPC:
- if (gs_npc_seen (game, parent))
- {
- pf_new_sentence (filter);
- lib_print_npc_np (game, parent);
- pf_buffer_string (filter,
- (position == OBJ_HELD_NPC)
- ? " is holding " : " is wearing ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- }
- else
- pf_buffer_string (filter, "I don't know where that is.\n");
- return TRUE;
-
- case OBJ_PART_NPC:
- if (parent == -1)
- {
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object, " is", " are"));
- pf_buffer_string (filter,
- lib_select_response (game,
- " a part of you!\n",
- " a part of me!\n",
- " a part of %player%!\n"));
- }
- else
- {
- if (gs_npc_seen (game, parent))
- {
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object,
- " is", " are"));
- pf_buffer_string (filter, " a part of ");
- lib_print_npc_np (game, parent);
- pf_buffer_string (filter, ".\n");
- }
- else
- pf_buffer_string (filter, "I don't know where that is.\n");
- }
- return TRUE;
-
- case OBJ_ON_OBJECT:
- case OBJ_IN_OBJECT:
- if (gs_object_seen (game, parent))
- {
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object, " is", " are"));
- pf_buffer_string (filter,
- (position == OBJ_ON_OBJECT) ? " on " : " inside ");
- lib_print_object_np (game, parent);
- pf_buffer_string (filter, ".\n");
- }
- else
- pf_buffer_string (filter, "I don't know where that is.\n");
- return TRUE;
- }
-
- /*
- * Object is either static unmoved, or dynamic and on the floor of a room.
- * Check each room for the object, stopping on first found.
- */
- for (room = 0; room < gs_room_count (game); room++)
- {
- if (obj_indirectly_in_room (game, object, room))
- break;
- }
- if (room == gs_room_count (game))
- {
- pf_buffer_string (filter, "I don't know where that is.\n");
- return TRUE;
- }
-
- /* Check that this room's been visited by the player. */
- if (!gs_room_seen (game, room))
- {
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter,
- lib_select_plurality (game, object, " is", " are"));
- pf_buffer_string (filter,
- lib_select_response (game,
- " somewhere that you haven't been yet.\n",
- " somewhere that I haven't been yet.\n",
- " somewhere that %player% hasn't been yet.\n"));
- return TRUE;
- }
-
- /* Print the details of the object's room. */
- pf_new_sentence (filter);
- lib_print_object_np (game, object);
- pf_buffer_string (filter, " -- ");
- pf_buffer_string (filter, lib_get_room_name (game, room));
- pf_buffer_string (filter, ".\n");
- return TRUE;
-}
-
-sc_bool
-lib_cmd_locate_npc (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int index_, count, npc, room;
-
- game->is_admin = TRUE;
-
- /* Count the number of NPCs referenced by the last command. */
- count = 0;
- npc = -1;
- for (index_ = 0; index_ < gs_npc_count (game); index_++)
- {
- if (game->npc_references[index_])
- {
- count++;
- npc = index_;
- }
- }
-
- /*
- * If no NPCs identified, be coy about revealing anything; if more than one,
- * be vague. The "... where that is..." is the correct message even for
- * NPCs -- it's the same response as for lib_locate_other().
- */
- if (count == 0)
- {
- pf_buffer_string (filter, "I don't know where that is.\n");
- return TRUE;
- }
- else if (count > 1)
- {
- pf_buffer_string (filter,
- "Please be more clear about who you want to locate.\n");
- return TRUE;
- }
-
- /*
- * The reference is unambiguous, so we're responsible for noting it in
- * variables. Disambiguation would normally do this for us, but we just
- * bypassed it.
- */
- var_set_ref_character (vars, npc);
-
- /* See if this NPC has been seen yet. */
- if (!gs_npc_seen (game, npc))
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You haven't seen ",
- "I haven't seen ",
- "%player% hasn't seen "));
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " yet!\n");
- return TRUE;
- }
-
- /* Check each room for the NPC, stopping on first found. */
- for (room = 0; room < gs_room_count (game); room++)
- {
- if (npc_in_room (game, npc, room))
- break;
- }
- if (room == gs_room_count (game))
- {
- pf_buffer_string (filter, "I don't know where ");
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " is.\n");
- return TRUE;
- }
-
- /* Check that this room's been visited by the player. */
- if (!gs_room_seen (game, room))
- {
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter,
- lib_select_response (game,
- " is somewhere that you haven't been yet.\n",
- " is somewhere that I haven't been yet.\n",
- " is somewhere that %player% hasn't been yet.\n"));
- return TRUE;
- }
-
- /* Print the location, and smart-alec response. */
- pf_new_sentence (filter);
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " -- ");
- pf_buffer_string (filter, lib_get_room_name (game, room));
+lib_cmd_locate_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int index_, count, object, room, position, parent;
+
+ game->is_admin = TRUE;
+
+ /*
+ * Filter to remove unseen object references. Note that this is different
+ * from NPCs, who we acknowledge even when unseen.
+ */
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (!gs_object_seen(game, index_))
+ game->object_references[index_] = FALSE;
+ }
+
+ /* Count the number of objects referenced by the last command. */
+ count = 0;
+ object = -1;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (game->object_references[index_]) {
+ count++;
+ object = index_;
+ }
+ }
+
+ /*
+ * If no objects identified, be coy about revealing anything; if more than
+ * one, be vague.
+ */
+ if (count == 0) {
+ pf_buffer_string(filter, "I don't know where that is.\n");
+ return TRUE;
+ } else if (count > 1) {
+ pf_buffer_string(filter,
+ "Please be more clear about what you want to"
+ " locate.\n");
+ return TRUE;
+ }
+
+ /*
+ * The reference is unambiguous, so we're responsible for noting it in
+ * variables. Disambiguation would normally do this for us, but we just
+ * bypassed it.
+ */
+ var_set_ref_object(vars, object);
+
+ /* See if we can print a message based on position and parent. */
+ position = gs_object_position(game, object);
+ parent = gs_object_parent(game, object);
+ switch (position) {
+ case OBJ_HIDDEN:
+ if (!obj_is_static(game, object)) {
+ pf_buffer_string(filter, "I don't know where that is.\n");
+ return TRUE;
+ }
+ break;
+
+ case OBJ_HELD_PLAYER:
+ pf_new_sentence(filter);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are carrying ",
+ "I am carrying ",
+ "%player% is carrying "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, "!\n");
+ return TRUE;
+
+ case OBJ_WORN_PLAYER:
+ pf_new_sentence(filter);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You are wearing ",
+ "I am wearing ",
+ "%player% is wearing "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, "!\n");
+ return TRUE;
+
+ case OBJ_HELD_NPC:
+ case OBJ_WORN_NPC:
+ if (gs_npc_seen(game, parent)) {
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, parent);
+ pf_buffer_string(filter,
+ (position == OBJ_HELD_NPC)
+ ? " is holding " : " is wearing ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ } else
+ pf_buffer_string(filter, "I don't know where that is.\n");
+ return TRUE;
+
+ case OBJ_PART_NPC:
+ if (parent == -1) {
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object, " is", " are"));
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " a part of you!\n",
+ " a part of me!\n",
+ " a part of %player%!\n"));
+ } else {
+ if (gs_npc_seen(game, parent)) {
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object,
+ " is", " are"));
+ pf_buffer_string(filter, " a part of ");
+ lib_print_npc_np(game, parent);
+ pf_buffer_string(filter, ".\n");
+ } else
+ pf_buffer_string(filter, "I don't know where that is.\n");
+ }
+ return TRUE;
+
+ case OBJ_ON_OBJECT:
+ case OBJ_IN_OBJECT:
+ if (gs_object_seen(game, parent)) {
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object, " is", " are"));
+ pf_buffer_string(filter,
+ (position == OBJ_ON_OBJECT) ? " on " : " inside ");
+ lib_print_object_np(game, parent);
+ pf_buffer_string(filter, ".\n");
+ } else
+ pf_buffer_string(filter, "I don't know where that is.\n");
+ return TRUE;
+ }
+
+ /*
+ * Object is either static unmoved, or dynamic and on the floor of a room.
+ * Check each room for the object, stopping on first found.
+ */
+ for (room = 0; room < gs_room_count(game); room++) {
+ if (obj_indirectly_in_room(game, object, room))
+ break;
+ }
+ if (room == gs_room_count(game)) {
+ pf_buffer_string(filter, "I don't know where that is.\n");
+ return TRUE;
+ }
+
+ /* Check that this room's been visited by the player. */
+ if (!gs_room_seen(game, room)) {
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter,
+ lib_select_plurality(game, object, " is", " are"));
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " somewhere that you haven't been yet.\n",
+ " somewhere that I haven't been yet.\n",
+ " somewhere that %player% hasn't been yet.\n"));
+ return TRUE;
+ }
+
+ /* Print the details of the object's room. */
+ pf_new_sentence(filter);
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, " -- ");
+ pf_buffer_string(filter, lib_get_room_name(game, room));
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_locate_npc(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int index_, count, npc, room;
+
+ game->is_admin = TRUE;
+
+ /* Count the number of NPCs referenced by the last command. */
+ count = 0;
+ npc = -1;
+ for (index_ = 0; index_ < gs_npc_count(game); index_++) {
+ if (game->npc_references[index_]) {
+ count++;
+ npc = index_;
+ }
+ }
+
+ /*
+ * If no NPCs identified, be coy about revealing anything; if more than one,
+ * be vague. The "... where that is..." is the correct message even for
+ * NPCs -- it's the same response as for lib_locate_other().
+ */
+ if (count == 0) {
+ pf_buffer_string(filter, "I don't know where that is.\n");
+ return TRUE;
+ } else if (count > 1) {
+ pf_buffer_string(filter,
+ "Please be more clear about who you want to locate.\n");
+ return TRUE;
+ }
+
+ /*
+ * The reference is unambiguous, so we're responsible for noting it in
+ * variables. Disambiguation would normally do this for us, but we just
+ * bypassed it.
+ */
+ var_set_ref_character(vars, npc);
+
+ /* See if this NPC has been seen yet. */
+ if (!gs_npc_seen(game, npc)) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You haven't seen ",
+ "I haven't seen ",
+ "%player% hasn't seen "));
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " yet!\n");
+ return TRUE;
+ }
+
+ /* Check each room for the NPC, stopping on first found. */
+ for (room = 0; room < gs_room_count(game); room++) {
+ if (npc_in_room(game, npc, room))
+ break;
+ }
+ if (room == gs_room_count(game)) {
+ pf_buffer_string(filter, "I don't know where ");
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " is.\n");
+ return TRUE;
+ }
+
+ /* Check that this room's been visited by the player. */
+ if (!gs_room_seen(game, room)) {
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " is somewhere that you haven't been yet.\n",
+ " is somewhere that I haven't been yet.\n",
+ " is somewhere that %player% hasn't been yet.\n"));
+ return TRUE;
+ }
+
+ /* Print the location, and smart-alec response. */
+ pf_new_sentence(filter);
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " -- ");
+ pf_buffer_string(filter, lib_get_room_name(game, room));
#if 0
- if (room == gs_playerroom (game))
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- " (Right next to you, silly!)",
- " (Right next to me, silly!)",
- " (Right next to %player%, silly!)"));
- }
+ if (room == gs_playerroom(game)) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ " (Right next to you, silly!)",
+ " (Right next to me, silly!)",
+ " (Right next to %player%, silly!)"));
+ }
#endif
- pf_buffer_string (filter, ".\n");
- return TRUE;
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
@@ -9548,59 +8712,57 @@ lib_cmd_locate_npc (sc_gameref_t game)
* Display turns taken and score so far.
*/
sc_bool
-lib_cmd_turns (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_char buffer[32];
+lib_cmd_turns(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_char buffer[32];
- pf_buffer_string (filter, "You have taken ");
- sprintf (buffer, "%ld", game->turns);
- pf_buffer_string (filter, buffer);
- if (game->turns == 1)
- pf_buffer_string (filter, " turn so far.\n");
- else
- pf_buffer_string (filter, " turns so far.\n");
+ pf_buffer_string(filter, "You have taken ");
+ sprintf(buffer, "%ld", game->turns);
+ pf_buffer_string(filter, buffer);
+ if (game->turns == 1)
+ pf_buffer_string(filter, " turn so far.\n");
+ else
+ pf_buffer_string(filter, " turns so far.\n");
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
sc_bool
-lib_cmd_score (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_int max_score, percent;
- sc_char buffer[32];
+lib_cmd_score(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_int max_score, percent;
+ sc_char buffer[32];
- /* Get max score, and calculate score as a percentage. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "MaxScore";
- max_score = prop_get_integer (bundle, "I<-ss", vt_key);
- if (game->score > 0 && max_score > 0)
- percent = (game->score * 100) / max_score;
- else
- percent = 0;
+ /* Get max score, and calculate score as a percentage. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "MaxScore";
+ max_score = prop_get_integer(bundle, "I<-ss", vt_key);
+ if (game->score > 0 && max_score > 0)
+ percent = (game->score * 100) / max_score;
+ else
+ percent = 0;
- /* Output carefully formatted response. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "Your score is ",
- "My score is ",
- "%player%'s score is "));
- sprintf (buffer, "%ld", game->score);
- pf_buffer_string (filter, buffer);
- pf_buffer_string (filter, " out of a maximum of ");
- sprintf (buffer, "%ld", max_score);
- pf_buffer_string (filter, buffer);
- pf_buffer_string (filter, ". (");
- sprintf (buffer, "%ld", percent);
- pf_buffer_string (filter, buffer);
- pf_buffer_string (filter, "%)\n");
+ /* Output carefully formatted response. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "Your score is ",
+ "My score is ",
+ "%player%'s score is "));
+ sprintf(buffer, "%ld", game->score);
+ pf_buffer_string(filter, buffer);
+ pf_buffer_string(filter, " out of a maximum of ");
+ sprintf(buffer, "%ld", max_score);
+ pf_buffer_string(filter, buffer);
+ pf_buffer_string(filter, ". (");
+ sprintf(buffer, "%ld", percent);
+ pf_buffer_string(filter, buffer);
+ pf_buffer_string(filter, "%)\n");
- game->is_admin = TRUE;
- return TRUE;
+ game->is_admin = TRUE;
+ return TRUE;
}
@@ -9611,423 +8773,390 @@ lib_cmd_score (sc_gameref_t game)
* but it's good to make then right as game ALRs may look for them.
*/
sc_bool
-lib_cmd_profanity (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_profanity(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- "I really don't think there's any need for language like"
- " that!\n");
- return TRUE;
+ pf_buffer_string(filter,
+ "I really don't think there's any need for language like"
+ " that!\n");
+ return TRUE;
}
sc_bool
-lib_cmd_examine_all (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_examine_all(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "Please examine one object at a time.\n");
- return TRUE;
+ pf_buffer_string(filter, "Please examine one object at a time.\n");
+ return TRUE;
}
sc_bool
-lib_cmd_examine_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_examine_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You see no such thing.\n",
- "I see no such thing.\n",
- "%player% sees no such thing.\n"));
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You see no such thing.\n",
+ "I see no such thing.\n",
+ "%player% sees no such thing.\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_locate_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_locate_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "I don't know where that is!\n");
- game->is_admin = TRUE;
- return TRUE;
+ pf_buffer_string(filter, "I don't know where that is!\n");
+ game->is_admin = TRUE;
+ return TRUE;
}
sc_bool
-lib_cmd_unix_like (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_unix_like(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "This isn't Unix you know!\n");
- return TRUE;
+ pf_buffer_string(filter, "This isn't Unix you know!\n");
+ return TRUE;
}
sc_bool
-lib_cmd_dos_like (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_dos_like(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "This isn't Dos you know!\n");
- return TRUE;
+ pf_buffer_string(filter, "This isn't Dos you know!\n");
+ return TRUE;
}
sc_bool
-lib_cmd_cry (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_cry(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "There's no need for that!\n");
- return TRUE;
+ pf_buffer_string(filter, "There's no need for that!\n");
+ return TRUE;
}
sc_bool
-lib_cmd_dance (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_dance(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You do a little dance.\n",
- "I do a little dance.\n",
- "%player% does a little dance.\n"));
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You do a little dance.\n",
+ "I do a little dance.\n",
+ "%player% does a little dance.\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_eat_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_eat_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "I don't understand what you are trying to eat.\n");
- return TRUE;
+ pf_buffer_string(filter, "I don't understand what you are trying to eat.\n");
+ return TRUE;
}
sc_bool
-lib_cmd_fight (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_fight(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "There is nothing worth fighting here.\n");
- return TRUE;
+ pf_buffer_string(filter, "There is nothing worth fighting here.\n");
+ return TRUE;
}
sc_bool
-lib_cmd_feed (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_feed(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "There is nothing worth feeding here.\n");
- return TRUE;
+ pf_buffer_string(filter, "There is nothing worth feeding here.\n");
+ return TRUE;
}
sc_bool
-lib_cmd_feel (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_feel(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You feel nothing out of the ordinary.\n",
- "I feel nothing out of the ordinary.\n",
- "%player% feels nothing out of the ordinary.\n"));
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You feel nothing out of the ordinary.\n",
+ "I feel nothing out of the ordinary.\n",
+ "%player% feels nothing out of the ordinary.\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_fly (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_fly(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't fly.\n",
- "I can't fly.\n",
- "%player% can't fly.\n"));
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't fly.\n",
+ "I can't fly.\n",
+ "%player% can't fly.\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_hint (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_hint(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- "You're just going to have to work it out for"
- " yourself...\n");
- return TRUE;
+ pf_buffer_string(filter,
+ "You're just going to have to work it out for"
+ " yourself...\n");
+ return TRUE;
}
sc_bool
-lib_cmd_hum (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_hum(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You hum a little tune.\n",
- "I hum a little tune.\n",
- "%player% hums a little tune.\n"));
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You hum a little tune.\n",
+ "I hum a little tune.\n",
+ "%player% hums a little tune.\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_jump (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_jump(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "Wheee-boinng.\n");
- return TRUE;
+ pf_buffer_string(filter, "Wheee-boinng.\n");
+ return TRUE;
}
sc_bool
-lib_cmd_listen (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_listen(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- lib_select_response (game,
- "You hear nothing out of the ordinary.\n",
- "I hear nothing out of the ordinary.\n",
- "%player% hears nothing out of the ordinary.\n"));
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You hear nothing out of the ordinary.\n",
+ "I hear nothing out of the ordinary.\n",
+ "%player% hears nothing out of the ordinary.\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_please (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_please(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- lib_select_response (game,
- "Your kindness gets you nowhere.\n",
- "My kindness gets me nowhere.\n",
- "%player%'s kindness gets nowhere.\n"));
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "Your kindness gets you nowhere.\n",
+ "My kindness gets me nowhere.\n",
+ "%player%'s kindness gets nowhere.\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_punch (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_punch(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "Who do you think you are, Mike Tyson?\n");
- return TRUE;
+ pf_buffer_string(filter, "Who do you think you are, Mike Tyson?\n");
+ return TRUE;
}
sc_bool
-lib_cmd_run (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_run(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- lib_select_response (game,
- "Why would you want to run?\n",
- "Why would I want to run?\n",
- "Why would %player% want to run?\n"));
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "Why would you want to run?\n",
+ "Why would I want to run?\n",
+ "Why would %player% want to run?\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_shout (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_shout(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "Aaarrrrgggghhhhhh!\n");
- return TRUE;
+ pf_buffer_string(filter, "Aaarrrrgggghhhhhh!\n");
+ return TRUE;
}
sc_bool
-lib_cmd_say (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_char *string = NULL;
+lib_cmd_say(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_char *string = NULL;
+
+ switch (sc_randomint(1, 5)) {
+ case 1:
+ string = "Gosh, that was very impressive.\n";
+ break;
+ case 2:
+ string = lib_select_response(game,
+ "Not surprisingly, no-one takes any notice"
+ " of you.\n",
+ "Not surprisingly, no-one takes any notice"
+ " of me.\n",
+ "Not surprisingly, no-one takes any notice"
+ " of %player%.\n");
+ break;
+ case 3:
+ string = "Wow! That achieved a lot.\n";
+ break;
+ case 4:
+ string = "Uh huh, yes, very interesting.\n";
+ break;
+ default:
+ string = "That's the most interesting thing I've ever heard!\n";
+ break;
+ }
+
+ pf_buffer_string(filter, string);
+ return TRUE;
+}
- switch (sc_randomint (1, 5))
- {
- case 1:
- string = "Gosh, that was very impressive.\n";
- break;
- case 2:
- string = lib_select_response (game,
- "Not surprisingly, no-one takes any notice"
- " of you.\n",
- "Not surprisingly, no-one takes any notice"
- " of me.\n",
- "Not surprisingly, no-one takes any notice"
- " of %player%.\n");
- break;
- case 3:
- string = "Wow! That achieved a lot.\n";
- break;
- case 4:
- string = "Uh huh, yes, very interesting.\n";
- break;
- default:
- string = "That's the most interesting thing I've ever heard!\n";
- break;
- }
+sc_bool
+lib_cmd_sing(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You sing a little song.\n",
+ "I sing a little song.\n",
+ "%player% sings a little song.\n"));
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_sleep(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ pf_buffer_string(filter, "Zzzzz. Bored are you?\n");
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_talk(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, string);
- return TRUE;
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "No-one listens to your rabblings.\n",
+ "No-one listens to my rabblings.\n",
+ "No-one listens to %player%'s rabblings.\n"));
+ return TRUE;
}
sc_bool
-lib_cmd_sing (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- pf_buffer_string (filter,
- lib_select_response (game,
- "You sing a little song.\n",
- "I sing a little song.\n",
- "%player% sings a little song.\n"));
- return TRUE;
-}
-
-sc_bool
-lib_cmd_sleep (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- pf_buffer_string (filter, "Zzzzz. Bored are you?\n");
- return TRUE;
-}
-
-sc_bool
-lib_cmd_talk (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- pf_buffer_string (filter,
- lib_select_response (game,
- "No-one listens to your rabblings.\n",
- "No-one listens to my rabblings.\n",
- "No-one listens to %player%'s rabblings.\n"));
- return TRUE;
-}
-
-sc_bool
-lib_cmd_thank (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- pf_buffer_string (filter, "You're welcome.\n");
- return TRUE;
-}
-
-sc_bool
-lib_cmd_whistle (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- pf_buffer_string (filter,
- lib_select_response (game,
- "You whistle a little tune.\n",
- "I whistle a little tune.\n",
- "%player% whistles a little tune.\n"));
- return TRUE;
-}
-
-sc_bool
-lib_cmd_interrogation (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_char *string = NULL;
-
- switch (sc_randomint (1, 17))
- {
- case 1:
- string = "Why do you want to know?\n";
- break;
- case 2:
- string = "Interesting question.\n";
- break;
- case 3:
- string = "Let me think about that one...\n";
- break;
- case 4:
- string = "I haven't a clue!\n";
- break;
- case 5:
- string = "All these questions are hurting my head.\n";
- break;
- case 6:
- string = "I'm not going to tell you.\n";
- break;
- case 7:
- string = "Someday I'll know the answer to that one.\n";
- break;
- case 8:
- string = "I could tell you, but then I'd have to kill you.\n";
- break;
- case 9:
- string = "Ha, as if I'd tell you!\n";
- break;
- case 10:
- string = "Ask me again later.\n";
- break;
- case 11:
- string = "I don't know - could you ask anyone else?\n";
- break;
- case 12:
- string = "Err, yes?!?\n";
- break;
- case 13:
- string = "Let me just check my memory banks...\n";
- break;
- case 14:
- string = "Because that's just the way it is.\n";
- break;
- case 15:
- string = "Do I ask you all sorts of awkward questions?\n";
- break;
- case 16:
- string = "Questions, questions...\n";
- break;
- default:
- string = "Who cares.\n";
- break;
- }
-
- pf_buffer_string (filter, string);
- return TRUE;
-}
-
-sc_bool
-lib_cmd_xyzzy (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
-
- pf_buffer_string (filter,
- "I'm sorry, but XYZZY doesn't do anything special in"
- " this game!\n");
- return TRUE;
-}
-
-sc_bool
-lib_cmd_egotistic (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_thank(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ pf_buffer_string(filter, "You're welcome.\n");
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_whistle(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You whistle a little tune.\n",
+ "I whistle a little tune.\n",
+ "%player% whistles a little tune.\n"));
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_interrogation(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_char *string = NULL;
+
+ switch (sc_randomint(1, 17)) {
+ case 1:
+ string = "Why do you want to know?\n";
+ break;
+ case 2:
+ string = "Interesting question.\n";
+ break;
+ case 3:
+ string = "Let me think about that one...\n";
+ break;
+ case 4:
+ string = "I haven't a clue!\n";
+ break;
+ case 5:
+ string = "All these questions are hurting my head.\n";
+ break;
+ case 6:
+ string = "I'm not going to tell you.\n";
+ break;
+ case 7:
+ string = "Someday I'll know the answer to that one.\n";
+ break;
+ case 8:
+ string = "I could tell you, but then I'd have to kill you.\n";
+ break;
+ case 9:
+ string = "Ha, as if I'd tell you!\n";
+ break;
+ case 10:
+ string = "Ask me again later.\n";
+ break;
+ case 11:
+ string = "I don't know - could you ask anyone else?\n";
+ break;
+ case 12:
+ string = "Err, yes?!?\n";
+ break;
+ case 13:
+ string = "Let me just check my memory banks...\n";
+ break;
+ case 14:
+ string = "Because that's just the way it is.\n";
+ break;
+ case 15:
+ string = "Do I ask you all sorts of awkward questions?\n";
+ break;
+ case 16:
+ string = "Questions, questions...\n";
+ break;
+ default:
+ string = "Who cares.\n";
+ break;
+ }
+
+ pf_buffer_string(filter, string);
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_xyzzy(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+
+ pf_buffer_string(filter,
+ "I'm sorry, but XYZZY doesn't do anything special in"
+ " this game!\n");
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_egotistic(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
#if 0
- pf_buffer_string (filter,
- "Campbell wrote this Adrift Runner. It's pretty"
- " good huh!\n");
+ pf_buffer_string(filter,
+ "Campbell wrote this Adrift Runner. It's pretty"
+ " good huh!\n");
#else
- pf_buffer_string (filter, "No comment.\n");
+ pf_buffer_string(filter, "No comment.\n");
#endif
- return TRUE;
+ return TRUE;
}
sc_bool
-lib_cmd_yes_or_no (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_yes_or_no(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter,
- "That's interesting, but it doesn't mean much.\n");
- return TRUE;
+ pf_buffer_string(filter,
+ "That's interesting, but it doesn't mean much.\n");
+ return TRUE;
}
@@ -10039,56 +9168,53 @@ lib_cmd_yes_or_no (sc_gameref_t game)
* Malformed and rhetorical question responses.
*/
sc_bool
-lib_cmd_ask_npc (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int npc;
- sc_bool is_ambiguous;
+lib_cmd_ask_npc(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int npc;
+ sc_bool is_ambiguous;
- /* Get the referenced npc, and if none, consider complete. */
- npc = lib_disambiguate_npc (game, "ask", &is_ambiguous);
- if (npc == -1)
- return is_ambiguous;
+ /* Get the referenced npc, and if none, consider complete. */
+ npc = lib_disambiguate_npc(game, "ask", &is_ambiguous);
+ if (npc == -1)
+ return is_ambiguous;
- /* Incomplete ask command, so offer help and return. */
- pf_buffer_string (filter, "Use the format \"ask ");
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, " about [subject]\".\n");
- return TRUE;
+ /* Incomplete ask command, so offer help and return. */
+ pf_buffer_string(filter, "Use the format \"ask ");
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, " about [subject]\".\n");
+ return TRUE;
}
sc_bool
-lib_cmd_ask_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
+lib_cmd_ask_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
- /* Get the referenced object, and if none, consider complete. */
- object = lib_disambiguate_object (game, "ask", &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
+ /* Get the referenced object, and if none, consider complete. */
+ object = lib_disambiguate_object(game, "ask", &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
- /* No reply. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You get no reply from ",
- "I get no reply from ",
- "%player% gets no reply from "));
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+ /* No reply. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You get no reply from ",
+ "I get no reply from ",
+ "%player% gets no reply from "));
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
sc_bool
-lib_cmd_ask_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_ask_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- /* Incomplete ask command, so offer help and return. */
- pf_buffer_string (filter,
- "Use the format \"ask [character] about [subject]\".\n");
- return TRUE;
+ /* Incomplete ask command, so offer help and return. */
+ pf_buffer_string(filter,
+ "Use the format \"ask [character] about [subject]\".\n");
+ return TRUE;
}
@@ -10098,12 +9224,11 @@ lib_cmd_ask_other (sc_gameref_t game)
* Uninteresting kill message when no weaponry is involved.
*/
sc_bool
-lib_cmd_kill_other (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_cmd_kill_other(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, "Now that isn't very nice.\n");
- return TRUE;
+ pf_buffer_string(filter, "Now that isn't very nice.\n");
+ return TRUE;
}
@@ -10116,82 +9241,77 @@ lib_cmd_kill_other (sc_gameref_t game)
* uninteresting responses.
*/
static sc_bool
-lib_nothing_happens_common (sc_gameref_t game,
- const sc_char *verb_general,
- const sc_char *verb_third_person,
- sc_bool is_object)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_int perspective, object;
- const sc_char *person, *verb;
- sc_bool is_ambiguous;
-
- /* Use person and verb tense according to perspective. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "Perspective";
- perspective = prop_get_integer (bundle, "I<-ss", vt_key);
- switch (perspective)
- {
- case LIB_FIRST_PERSON:
- person = "I ";
- verb = verb_general;
- break;
- case LIB_SECOND_PERSON:
- person = "You ";
- verb = verb_general;
- break;
- case LIB_THIRD_PERSON:
- person = "%player% ";
- verb = verb_third_person;
- break;
- default:
- sc_error ("lib_nothing_happens: unknown perspective, %ld\n", perspective);
- person = "You ";
- verb = verb_general;
- break;
- }
-
- /* If the command target was not an object, end it here. */
- if (!is_object)
- {
- pf_buffer_string (filter, person);
- pf_buffer_string (filter, verb);
- pf_buffer_string (filter, ", but nothing happens.\n");
- return TRUE;
- }
-
- /* Get the referenced object. If none, return immediately. */
- object = lib_disambiguate_object (game, verb_general, &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Nothing happens. */
- pf_buffer_string (filter, person);
- pf_buffer_string (filter, verb);
- pf_buffer_character (filter, ' ');
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ", but nothing happens.\n");
- return TRUE;
+lib_nothing_happens_common(sc_gameref_t game,
+ const sc_char *verb_general,
+ const sc_char *verb_third_person,
+ sc_bool is_object) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_int perspective, object;
+ const sc_char *person, *verb;
+ sc_bool is_ambiguous;
+
+ /* Use person and verb tense according to perspective. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Perspective";
+ perspective = prop_get_integer(bundle, "I<-ss", vt_key);
+ switch (perspective) {
+ case LIB_FIRST_PERSON:
+ person = "I ";
+ verb = verb_general;
+ break;
+ case LIB_SECOND_PERSON:
+ person = "You ";
+ verb = verb_general;
+ break;
+ case LIB_THIRD_PERSON:
+ person = "%player% ";
+ verb = verb_third_person;
+ break;
+ default:
+ sc_error("lib_nothing_happens: unknown perspective, %ld\n", perspective);
+ person = "You ";
+ verb = verb_general;
+ break;
+ }
+
+ /* If the command target was not an object, end it here. */
+ if (!is_object) {
+ pf_buffer_string(filter, person);
+ pf_buffer_string(filter, verb);
+ pf_buffer_string(filter, ", but nothing happens.\n");
+ return TRUE;
+ }
+
+ /* Get the referenced object. If none, return immediately. */
+ object = lib_disambiguate_object(game, verb_general, &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Nothing happens. */
+ pf_buffer_string(filter, person);
+ pf_buffer_string(filter, verb);
+ pf_buffer_character(filter, ' ');
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ", but nothing happens.\n");
+ return TRUE;
}
static sc_bool
-lib_nothing_happens_object (sc_gameref_t game,
- const sc_char *verb_general,
- const sc_char *verb_third_person)
-{
- return lib_nothing_happens_common (game,
- verb_general, verb_third_person, TRUE);
+lib_nothing_happens_object(sc_gameref_t game,
+ const sc_char *verb_general,
+ const sc_char *verb_third_person) {
+ return lib_nothing_happens_common(game,
+ verb_general, verb_third_person, TRUE);
}
static sc_bool
-lib_nothing_happens_other (sc_gameref_t game,
- const sc_char *verb_general,
- const sc_char *verb_third_person)
-{
- return lib_nothing_happens_common (game,
- verb_general, verb_third_person, FALSE);
+lib_nothing_happens_other(sc_gameref_t game,
+ const sc_char *verb_general,
+ const sc_char *verb_third_person) {
+ return lib_nothing_happens_common(game,
+ verb_general, verb_third_person, FALSE);
}
@@ -10201,75 +9321,63 @@ lib_nothing_happens_other (sc_gameref_t game,
* Shake, rattle and roll, and assorted nothing-happens handlers.
*/
sc_bool
-lib_cmd_hit_object (sc_gameref_t game)
-{
- return lib_nothing_happens_object (game, "hit", "hits");
+lib_cmd_hit_object(sc_gameref_t game) {
+ return lib_nothing_happens_object(game, "hit", "hits");
}
sc_bool
-lib_cmd_kick_object (sc_gameref_t game)
-{
- return lib_nothing_happens_object (game, "kick", "kicks");
+lib_cmd_kick_object(sc_gameref_t game) {
+ return lib_nothing_happens_object(game, "kick", "kicks");
}
sc_bool
-lib_cmd_press_object (sc_gameref_t game)
-{
- return lib_nothing_happens_object (game, "press", "presses");
+lib_cmd_press_object(sc_gameref_t game) {
+ return lib_nothing_happens_object(game, "press", "presses");
}
sc_bool
-lib_cmd_push_object (sc_gameref_t game)
-{
- return lib_nothing_happens_object (game, "push", "pushes");
+lib_cmd_push_object(sc_gameref_t game) {
+ return lib_nothing_happens_object(game, "push", "pushes");
}
sc_bool
-lib_cmd_pull_object (sc_gameref_t game)
-{
- return lib_nothing_happens_object (game, "pull", "pulls");
+lib_cmd_pull_object(sc_gameref_t game) {
+ return lib_nothing_happens_object(game, "pull", "pulls");
}
sc_bool
-lib_cmd_shake_object (sc_gameref_t game)
-{
- return lib_nothing_happens_object (game, "shake", "shakes");
+lib_cmd_shake_object(sc_gameref_t game) {
+ return lib_nothing_happens_object(game, "shake", "shakes");
}
sc_bool
-lib_cmd_hit_other (sc_gameref_t game)
-{
- return lib_nothing_happens_other (game, "hit", "hits");
+lib_cmd_hit_other(sc_gameref_t game) {
+ return lib_nothing_happens_other(game, "hit", "hits");
}
sc_bool
-lib_cmd_kick_other (sc_gameref_t game)
-{
- return lib_nothing_happens_other (game, "kick", "kicks");
+lib_cmd_kick_other(sc_gameref_t game) {
+ return lib_nothing_happens_other(game, "kick", "kicks");
}
sc_bool
-lib_cmd_press_other (sc_gameref_t game)
-{
- return lib_nothing_happens_other (game, "press", "presses");
+lib_cmd_press_other(sc_gameref_t game) {
+ return lib_nothing_happens_other(game, "press", "presses");
}
sc_bool
-lib_cmd_push_other (sc_gameref_t game)
-{
- return lib_nothing_happens_other (game, "push", "pushes");
+lib_cmd_push_other(sc_gameref_t game) {
+ return lib_nothing_happens_other(game, "push", "pushes");
}
sc_bool
-lib_cmd_pull_other (sc_gameref_t game)
-{
- return lib_nothing_happens_other (game, "pull", "pulls");
+lib_cmd_pull_other(sc_gameref_t game) {
+ return lib_nothing_happens_other(game, "pull", "pulls");
}
sc_bool
-lib_cmd_shake_other (sc_gameref_t game)
-{
- return lib_nothing_happens_other (game, "shake", "shakes");
+lib_cmd_shake_other(sc_gameref_t game) {
+ return lib_nothing_happens_other(game, "shake", "shakes");
}
@@ -10282,52 +9390,48 @@ lib_cmd_shake_other (sc_gameref_t game)
* ing responses.
*/
static sc_bool
-lib_cant_do_common (sc_gameref_t game,
- const sc_char *verb, sc_bool is_object)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
-
- /* If the target is not an object, end it here. */
- if (!is_object)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't ",
- "I can't ", "%player% can't "));
- pf_buffer_string (filter, verb);
- pf_buffer_string (filter, " that.\n");
- return TRUE;
- }
-
- /* Get the referenced object. If none, return immediately. */
- object = lib_disambiguate_object (game, verb, &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Whatever it is, don't do it. */
- pf_buffer_string (filter,
- lib_select_response (game,
- "You can't ",
- "I can't ", "%player% can't "));
- pf_buffer_string (filter, verb);
- pf_buffer_character (filter, ' ');
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+lib_cant_do_common(sc_gameref_t game,
+ const sc_char *verb, sc_bool is_object) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
+
+ /* If the target is not an object, end it here. */
+ if (!is_object) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't ",
+ "I can't ", "%player% can't "));
+ pf_buffer_string(filter, verb);
+ pf_buffer_string(filter, " that.\n");
+ return TRUE;
+ }
+
+ /* Get the referenced object. If none, return immediately. */
+ object = lib_disambiguate_object(game, verb, &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Whatever it is, don't do it. */
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "You can't ",
+ "I can't ", "%player% can't "));
+ pf_buffer_string(filter, verb);
+ pf_buffer_character(filter, ' ');
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
static sc_bool
-lib_cant_do_object (sc_gameref_t game, const sc_char *verb)
-{
- return lib_cant_do_common (game, verb, TRUE);
+lib_cant_do_object(sc_gameref_t game, const sc_char *verb) {
+ return lib_cant_do_common(game, verb, TRUE);
}
static sc_bool
-lib_cant_do_other (sc_gameref_t game, const sc_char *verb)
-{
- return lib_cant_do_common (game, verb, FALSE);
+lib_cant_do_other(sc_gameref_t game, const sc_char *verb) {
+ return lib_cant_do_common(game, verb, FALSE);
}
@@ -10337,219 +9441,183 @@ lib_cant_do_other (sc_gameref_t game, const sc_char *verb)
* Assorted can't-do messages.
*/
sc_bool
-lib_cmd_block_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "block");
+lib_cmd_block_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "block");
}
sc_bool
-lib_cmd_climb_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "climb");
+lib_cmd_climb_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "climb");
}
sc_bool
-lib_cmd_clean_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "clean");
+lib_cmd_clean_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "clean");
}
sc_bool
-lib_cmd_cut_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "cut");
+lib_cmd_cut_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "cut");
}
sc_bool
-lib_cmd_drink_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "drink");
+lib_cmd_drink_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "drink");
}
sc_bool
-lib_cmd_light_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "light");
+lib_cmd_light_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "light");
}
sc_bool
-lib_cmd_lift_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "lift");
+lib_cmd_lift_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "lift");
}
sc_bool
-lib_cmd_move_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "move");
+lib_cmd_move_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "move");
}
sc_bool
-lib_cmd_rub_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "rub");
+lib_cmd_rub_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "rub");
}
sc_bool
-lib_cmd_stop_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "stop");
+lib_cmd_stop_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "stop");
}
sc_bool
-lib_cmd_suck_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "suck");
+lib_cmd_suck_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "suck");
}
sc_bool
-lib_cmd_touch_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "touch");
+lib_cmd_touch_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "touch");
}
sc_bool
-lib_cmd_turn_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "turn");
+lib_cmd_turn_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "turn");
}
sc_bool
-lib_cmd_unblock_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "unblock");
+lib_cmd_unblock_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "unblock");
}
sc_bool
-lib_cmd_wash_object (sc_gameref_t game)
-{
- return lib_cant_do_object (game, "wash");
+lib_cmd_wash_object(sc_gameref_t game) {
+ return lib_cant_do_object(game, "wash");
}
sc_bool
-lib_cmd_block_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "block");
+lib_cmd_block_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "block");
}
sc_bool
-lib_cmd_climb_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "climb");
+lib_cmd_climb_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "climb");
}
sc_bool
-lib_cmd_clean_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "clean");
+lib_cmd_clean_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "clean");
}
sc_bool
-lib_cmd_close_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "close");
+lib_cmd_close_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "close");
}
sc_bool
-lib_cmd_lock_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "lock");
+lib_cmd_lock_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "lock");
}
sc_bool
-lib_cmd_unlock_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "unlock");
+lib_cmd_unlock_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "unlock");
}
sc_bool
-lib_cmd_stand_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "stand on");
+lib_cmd_stand_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "stand on");
}
sc_bool
-lib_cmd_sit_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "sit on");
+lib_cmd_sit_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "sit on");
}
sc_bool
-lib_cmd_lie_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "lie on");
+lib_cmd_lie_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "lie on");
}
sc_bool
-lib_cmd_cut_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "cut");
+lib_cmd_cut_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "cut");
}
sc_bool
-lib_cmd_drink_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "drink");
+lib_cmd_drink_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "drink");
}
sc_bool
-lib_cmd_lift_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "lift");
+lib_cmd_lift_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "lift");
}
sc_bool
-lib_cmd_light_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "light");
+lib_cmd_light_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "light");
}
sc_bool
-lib_cmd_move_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "move");
+lib_cmd_move_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "move");
}
sc_bool
-lib_cmd_stop_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "stop");
+lib_cmd_stop_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "stop");
}
sc_bool
-lib_cmd_rub_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "rub");
+lib_cmd_rub_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "rub");
}
sc_bool
-lib_cmd_suck_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "suck");
+lib_cmd_suck_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "suck");
}
sc_bool
-lib_cmd_turn_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "turn");
+lib_cmd_turn_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "turn");
}
sc_bool
-lib_cmd_touch_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "touch");
+lib_cmd_touch_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "touch");
}
sc_bool
-lib_cmd_unblock_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "unblock");
+lib_cmd_unblock_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "unblock");
}
sc_bool
-lib_cmd_wash_other (sc_gameref_t game)
-{
- return lib_cant_do_other (game, "wash");
+lib_cmd_wash_other(sc_gameref_t game) {
+ return lib_cant_do_other(game, "wash");
}
@@ -10562,50 +9630,46 @@ lib_cmd_wash_other (sc_gameref_t game)
* uninteresting responses.
*/
static sc_bool
-lib_dont_think_common (sc_gameref_t game,
- const sc_char *verb, sc_bool is_object)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- sc_int object;
- sc_bool is_ambiguous;
-
- /* If the target is not an object, end it here. */
- if (!is_object)
- {
- pf_buffer_string (filter,
- lib_select_response (game,
- "I don't think you can ",
- "I don't think I can ",
- "I don't think %player% can "));
- pf_buffer_string (filter, verb);
- pf_buffer_string (filter, " that.\n");
- return TRUE;
- }
-
- /* Get the referenced object. If none, return immediately. */
- object = lib_disambiguate_object (game, verb, &is_ambiguous);
- if (object == -1)
- return is_ambiguous;
-
- /* Whatever it is, don't do it. */
- pf_buffer_string (filter, "I don't think you can ");
- pf_buffer_string (filter, verb);
- pf_buffer_character (filter, ' ');
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+lib_dont_think_common(sc_gameref_t game,
+ const sc_char *verb, sc_bool is_object) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ sc_int object;
+ sc_bool is_ambiguous;
+
+ /* If the target is not an object, end it here. */
+ if (!is_object) {
+ pf_buffer_string(filter,
+ lib_select_response(game,
+ "I don't think you can ",
+ "I don't think I can ",
+ "I don't think %player% can "));
+ pf_buffer_string(filter, verb);
+ pf_buffer_string(filter, " that.\n");
+ return TRUE;
+ }
+
+ /* Get the referenced object. If none, return immediately. */
+ object = lib_disambiguate_object(game, verb, &is_ambiguous);
+ if (object == -1)
+ return is_ambiguous;
+
+ /* Whatever it is, don't do it. */
+ pf_buffer_string(filter, "I don't think you can ");
+ pf_buffer_string(filter, verb);
+ pf_buffer_character(filter, ' ');
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
static sc_bool
-lib_dont_think_object (sc_gameref_t game, const sc_char *verb)
-{
- return lib_dont_think_common (game, verb, TRUE);
+lib_dont_think_object(sc_gameref_t game, const sc_char *verb) {
+ return lib_dont_think_common(game, verb, TRUE);
}
static sc_bool
-lib_dont_think_other (sc_gameref_t game, const sc_char *verb)
-{
- return lib_dont_think_common (game, verb, FALSE);
+lib_dont_think_other(sc_gameref_t game, const sc_char *verb) {
+ return lib_dont_think_common(game, verb, FALSE);
}
@@ -10615,39 +9679,33 @@ lib_dont_think_other (sc_gameref_t game, const sc_char *verb)
* Assorted don't-think messages.
*/
sc_bool
-lib_cmd_fix_object (sc_gameref_t game)
-{
- return lib_dont_think_object (game, "fix");
+lib_cmd_fix_object(sc_gameref_t game) {
+ return lib_dont_think_object(game, "fix");
}
sc_bool
-lib_cmd_mend_object (sc_gameref_t game)
-{
- return lib_dont_think_object (game, "mend");
+lib_cmd_mend_object(sc_gameref_t game) {
+ return lib_dont_think_object(game, "mend");
}
sc_bool
-lib_cmd_repair_object (sc_gameref_t game)
-{
- return lib_dont_think_object (game, "repair");
+lib_cmd_repair_object(sc_gameref_t game) {
+ return lib_dont_think_object(game, "repair");
}
sc_bool
-lib_cmd_fix_other (sc_gameref_t game)
-{
- return lib_dont_think_other (game, "fix");
+lib_cmd_fix_other(sc_gameref_t game) {
+ return lib_dont_think_other(game, "fix");
}
sc_bool
-lib_cmd_mend_other (sc_gameref_t game)
-{
- return lib_dont_think_other (game, "mend");
+lib_cmd_mend_other(sc_gameref_t game) {
+ return lib_dont_think_other(game, "mend");
}
sc_bool
-lib_cmd_repair_other (sc_gameref_t game)
-{
- return lib_dont_think_other (game, "repair");
+lib_cmd_repair_other(sc_gameref_t game) {
+ return lib_dont_think_other(game, "repair");
}
@@ -10657,13 +9715,12 @@ lib_cmd_repair_other (sc_gameref_t game)
* Central handler for doing something, but unsure to what.
*/
static sc_bool
-lib_what (sc_gameref_t game, const sc_char *verb)
-{
- const sc_filterref_t filter = gs_get_filter (game);
+lib_what(sc_gameref_t game, const sc_char *verb) {
+ const sc_filterref_t filter = gs_get_filter(game);
- pf_buffer_string (filter, verb);
- pf_buffer_string (filter, " what?\n");
- return TRUE;
+ pf_buffer_string(filter, verb);
+ pf_buffer_string(filter, " what?\n");
+ return TRUE;
}
@@ -10673,225 +9730,188 @@ lib_what (sc_gameref_t game, const sc_char *verb)
* Assorted "what?" messages.
*/
sc_bool
-lib_cmd_block_what (sc_gameref_t game)
-{
- return lib_what (game, "Block");
+lib_cmd_block_what(sc_gameref_t game) {
+ return lib_what(game, "Block");
}
sc_bool
-lib_cmd_break_what (sc_gameref_t game)
-{
- return lib_what (game, "Break");
+lib_cmd_break_what(sc_gameref_t game) {
+ return lib_what(game, "Break");
}
sc_bool
-lib_cmd_destroy_what (sc_gameref_t game)
-{
- return lib_what (game, "Destroy");
+lib_cmd_destroy_what(sc_gameref_t game) {
+ return lib_what(game, "Destroy");
}
sc_bool
-lib_cmd_smash_what (sc_gameref_t game)
-{
- return lib_what (game, "Smash");
+lib_cmd_smash_what(sc_gameref_t game) {
+ return lib_what(game, "Smash");
}
sc_bool
-lib_cmd_buy_what (sc_gameref_t game)
-{
- return lib_what (game, "Buy");
+lib_cmd_buy_what(sc_gameref_t game) {
+ return lib_what(game, "Buy");
}
sc_bool
-lib_cmd_clean_what (sc_gameref_t game)
-{
- return lib_what (game, "Clean");
+lib_cmd_clean_what(sc_gameref_t game) {
+ return lib_what(game, "Clean");
}
sc_bool
-lib_cmd_climb_what (sc_gameref_t game)
-{
- return lib_what (game, "Climb");
+lib_cmd_climb_what(sc_gameref_t game) {
+ return lib_what(game, "Climb");
}
sc_bool
-lib_cmd_cut_what (sc_gameref_t game)
-{
- return lib_what (game, "Cut");
+lib_cmd_cut_what(sc_gameref_t game) {
+ return lib_what(game, "Cut");
}
sc_bool
-lib_cmd_drink_what (sc_gameref_t game)
-{
- return lib_what (game, "Drink");
+lib_cmd_drink_what(sc_gameref_t game) {
+ return lib_what(game, "Drink");
}
sc_bool
-lib_cmd_fix_what (sc_gameref_t game)
-{
- return lib_what (game, "Fix");
+lib_cmd_fix_what(sc_gameref_t game) {
+ return lib_what(game, "Fix");
}
sc_bool
-lib_cmd_hit_what (sc_gameref_t game)
-{
- return lib_what (game, "Hit");
+lib_cmd_hit_what(sc_gameref_t game) {
+ return lib_what(game, "Hit");
}
sc_bool
-lib_cmd_kick_what (sc_gameref_t game)
-{
- return lib_what (game, "Kick");
+lib_cmd_kick_what(sc_gameref_t game) {
+ return lib_what(game, "Kick");
}
sc_bool
-lib_cmd_light_what (sc_gameref_t game)
-{
- return lib_what (game, "Light");
+lib_cmd_light_what(sc_gameref_t game) {
+ return lib_what(game, "Light");
}
sc_bool
-lib_cmd_lift_what (sc_gameref_t game)
-{
- return lib_what (game, "Lift");
+lib_cmd_lift_what(sc_gameref_t game) {
+ return lib_what(game, "Lift");
}
sc_bool
-lib_cmd_mend_what (sc_gameref_t game)
-{
- return lib_what (game, "Mend");
+lib_cmd_mend_what(sc_gameref_t game) {
+ return lib_what(game, "Mend");
}
sc_bool
-lib_cmd_move_what (sc_gameref_t game)
-{
- return lib_what (game, "Move");
+lib_cmd_move_what(sc_gameref_t game) {
+ return lib_what(game, "Move");
}
sc_bool
-lib_cmd_press_what (sc_gameref_t game)
-{
- return lib_what (game, "Press");
+lib_cmd_press_what(sc_gameref_t game) {
+ return lib_what(game, "Press");
}
sc_bool
-lib_cmd_pull_what (sc_gameref_t game)
-{
- return lib_what (game, "Pull");
+lib_cmd_pull_what(sc_gameref_t game) {
+ return lib_what(game, "Pull");
}
sc_bool
-lib_cmd_push_what (sc_gameref_t game)
-{
- return lib_what (game, "Push");
+lib_cmd_push_what(sc_gameref_t game) {
+ return lib_what(game, "Push");
}
sc_bool
-lib_cmd_repair_what (sc_gameref_t game)
-{
- return lib_what (game, "Repair");
+lib_cmd_repair_what(sc_gameref_t game) {
+ return lib_what(game, "Repair");
}
sc_bool
-lib_cmd_sell_what (sc_gameref_t game)
-{
- return lib_what (game, "Sell");
+lib_cmd_sell_what(sc_gameref_t game) {
+ return lib_what(game, "Sell");
}
sc_bool
-lib_cmd_shake_what (sc_gameref_t game)
-{
- return lib_what (game, "Shake");
+lib_cmd_shake_what(sc_gameref_t game) {
+ return lib_what(game, "Shake");
}
sc_bool
-lib_cmd_rub_what (sc_gameref_t game)
-{
- return lib_what (game, "Rub");
+lib_cmd_rub_what(sc_gameref_t game) {
+ return lib_what(game, "Rub");
}
sc_bool
-lib_cmd_stop_what (sc_gameref_t game)
-{
- return lib_what (game, "Stop");
+lib_cmd_stop_what(sc_gameref_t game) {
+ return lib_what(game, "Stop");
}
sc_bool
-lib_cmd_suck_what (sc_gameref_t game)
-{
- return lib_what (game, "Suck");
+lib_cmd_suck_what(sc_gameref_t game) {
+ return lib_what(game, "Suck");
}
sc_bool
-lib_cmd_touch_what (sc_gameref_t game)
-{
- return lib_what (game, "Touch");
+lib_cmd_touch_what(sc_gameref_t game) {
+ return lib_what(game, "Touch");
}
sc_bool
-lib_cmd_turn_what (sc_gameref_t game)
-{
- return lib_what (game, "Turn");
+lib_cmd_turn_what(sc_gameref_t game) {
+ return lib_what(game, "Turn");
}
sc_bool
-lib_cmd_unblock_what (sc_gameref_t game)
-{
- return lib_what (game, "Unblock");
+lib_cmd_unblock_what(sc_gameref_t game) {
+ return lib_what(game, "Unblock");
}
sc_bool
-lib_cmd_wash_what (sc_gameref_t game)
-{
- return lib_what (game, "Wash");
+lib_cmd_wash_what(sc_gameref_t game) {
+ return lib_what(game, "Wash");
}
sc_bool
-lib_cmd_drop_what (sc_gameref_t game)
-{
- return lib_what (game, "Drop");
+lib_cmd_drop_what(sc_gameref_t game) {
+ return lib_what(game, "Drop");
}
sc_bool
-lib_cmd_get_what (sc_gameref_t game)
-{
- return lib_what (game, "Take");
+lib_cmd_get_what(sc_gameref_t game) {
+ return lib_what(game, "Take");
}
sc_bool
-lib_cmd_give_what (sc_gameref_t game)
-{
- return lib_what (game, "Give");
+lib_cmd_give_what(sc_gameref_t game) {
+ return lib_what(game, "Give");
}
sc_bool
-lib_cmd_open_what (sc_gameref_t game)
-{
- return lib_what (game, "Open");
+lib_cmd_open_what(sc_gameref_t game) {
+ return lib_what(game, "Open");
}
sc_bool
-lib_cmd_remove_what (sc_gameref_t game)
-{
- return lib_what (game, "Remove");
+lib_cmd_remove_what(sc_gameref_t game) {
+ return lib_what(game, "Remove");
}
sc_bool
-lib_cmd_wear_what (sc_gameref_t game)
-{
- return lib_what (game, "Wear");
+lib_cmd_wear_what(sc_gameref_t game) {
+ return lib_what(game, "Wear");
}
sc_bool
-lib_cmd_lock_what (sc_gameref_t game)
-{
- return lib_what (game, "Lock");
+lib_cmd_lock_what(sc_gameref_t game) {
+ return lib_what(game, "Lock");
}
sc_bool
-lib_cmd_unlock_what (sc_gameref_t game)
-{
- return lib_what (game, "Unlock");
+lib_cmd_unlock_what(sc_gameref_t game) {
+ return lib_what(game, "Unlock");
}
@@ -10902,69 +9922,63 @@ lib_cmd_unlock_what (sc_gameref_t game)
* Handlers for unrecognized verbs with known object/NPC.
*/
sc_bool
-lib_cmd_verb_object (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int count, object, index_;
-
- /* Ensure the reference is unambiguous. */
- count = 0;
- object = -1;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (game->object_references[index_]
- && gs_object_seen (game, index_)
- && obj_indirectly_in_room (game, index_, gs_playerroom (game)))
- {
- count++;
- object = index_;
- }
- }
- if (count != 1)
- return FALSE;
-
- /* Save in variables. */
- var_set_ref_object (vars, object);
-
- /* Print don't understand message. */
- pf_buffer_string (filter, "I don't understand what you want me to do with ");
- lib_print_object_np (game, object);
- pf_buffer_string (filter, ".\n");
- return TRUE;
-}
-
-sc_bool
-lib_cmd_verb_npc (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int count, npc, index_;
-
- /* Ensure the reference is unambiguous. */
- count = 0;
- npc = -1;
- for (index_ = 0; index_ < gs_npc_count (game); index_++)
- {
- if (game->npc_references[index_]
- && gs_npc_seen (game, index_)
- && npc_in_room (game, index_, gs_playerroom (game)))
- {
- count++;
- npc = index_;
- }
- }
- if (count != 1)
- return FALSE;
-
- /* Save in variables. */
- var_set_ref_character (vars, npc);
-
- /* Print don't understand message; unlike objects, there's no "me" here. */
- pf_buffer_string (filter, "I don't understand what you want to do with ");
- lib_print_npc_np (game, npc);
- pf_buffer_string (filter, ".\n");
- return TRUE;
+lib_cmd_verb_object(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int count, object, index_;
+
+ /* Ensure the reference is unambiguous. */
+ count = 0;
+ object = -1;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (game->object_references[index_]
+ && gs_object_seen(game, index_)
+ && obj_indirectly_in_room(game, index_, gs_playerroom(game))) {
+ count++;
+ object = index_;
+ }
+ }
+ if (count != 1)
+ return FALSE;
+
+ /* Save in variables. */
+ var_set_ref_object(vars, object);
+
+ /* Print don't understand message. */
+ pf_buffer_string(filter, "I don't understand what you want me to do with ");
+ lib_print_object_np(game, object);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
+}
+
+sc_bool
+lib_cmd_verb_npc(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int count, npc, index_;
+
+ /* Ensure the reference is unambiguous. */
+ count = 0;
+ npc = -1;
+ for (index_ = 0; index_ < gs_npc_count(game); index_++) {
+ if (game->npc_references[index_]
+ && gs_npc_seen(game, index_)
+ && npc_in_room(game, index_, gs_playerroom(game))) {
+ count++;
+ npc = index_;
+ }
+ }
+ if (count != 1)
+ return FALSE;
+
+ /* Save in variables. */
+ var_set_ref_character(vars, npc);
+
+ /* Print don't understand message; unlike objects, there's no "me" here. */
+ pf_buffer_string(filter, "I don't understand what you want to do with ");
+ lib_print_npc_np(game, npc);
+ pf_buffer_string(filter, ".\n");
+ return TRUE;
}
@@ -10974,9 +9988,8 @@ lib_cmd_verb_npc (sc_gameref_t game)
* Set library tracing on/off.
*/
void
-lib_debug_trace (sc_bool flag)
-{
- lib_trace = flag;
+lib_debug_trace(sc_bool flag) {
+ lib_trace = flag;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sclocale.cpp b/engines/glk/adrift/sclocale.cpp
index 25cf4ed065..b201b7faa4 100644
--- a/engines/glk/adrift/sclocale.cpp
+++ b/engines/glk/adrift/sclocale.cpp
@@ -51,27 +51,23 @@ enum { TABLE_SIZE = 256 };
* inclusive to TRUE, and iterate this on a ranges array.
*/
static void
-loc_setrange_bool (sc_int start, sc_int end, sc_bool table[])
-{
- sc_int index_;
-
- for (index_ = start; index_ <= end; index_++)
- {
- assert (index_ > -1 && index_ < TABLE_SIZE);
- table[index_] = TRUE;
- }
+loc_setrange_bool(sc_int start, sc_int end, sc_bool table[]) {
+ sc_int index_;
+
+ for (index_ = start; index_ <= end; index_++) {
+ assert(index_ > -1 && index_ < TABLE_SIZE);
+ table[index_] = TRUE;
+ }
}
static void
-loc_setranges_bool (const sc_int ranges[], sc_bool table[])
-{
- sc_int index_;
-
- for (index_ = 0; ranges[index_] > -1; index_ += 2)
- {
- assert (ranges[index_] <= ranges[index_ + 1]);
- loc_setrange_bool (ranges[index_], ranges[index_ + 1], table);
- }
+loc_setranges_bool(const sc_int ranges[], sc_bool table[]) {
+ sc_int index_;
+
+ for (index_ = 0; ranges[index_] > -1; index_ += 2) {
+ assert(ranges[index_] <= ranges[index_ + 1]);
+ loc_setrange_bool(ranges[index_], ranges[index_ + 1], table);
+ }
}
@@ -84,29 +80,25 @@ loc_setranges_bool (const sc_int ranges[], sc_bool table[])
* this on a ranges array.
*/
static void
-loc_setrange_char (sc_int start, sc_int end, sc_int offset, sc_char table[])
-{
- sc_int index_;
-
- for (index_ = start; index_ <= end; index_++)
- {
- assert (index_ > -1 && index_ < TABLE_SIZE);
- assert (index_ + offset > -1 && index_ + offset < TABLE_SIZE);
- table[index_] = index_ + offset;
- }
+loc_setrange_char(sc_int start, sc_int end, sc_int offset, sc_char table[]) {
+ sc_int index_;
+
+ for (index_ = start; index_ <= end; index_++) {
+ assert(index_ > -1 && index_ < TABLE_SIZE);
+ assert(index_ + offset > -1 && index_ + offset < TABLE_SIZE);
+ table[index_] = index_ + offset;
+ }
}
static void
-loc_setranges_char (const sc_int ranges[], sc_char table[])
-{
- sc_int index_;
-
- for (index_ = 0; ranges[index_] > -1; index_ += 3)
- {
- assert (ranges[index_] <= ranges[index_ + 1]);
- loc_setrange_char (ranges[index_],
- ranges[index_ + 1], ranges[index_ + 2], table);
- }
+loc_setranges_char(const sc_int ranges[], sc_char table[]) {
+ sc_int index_;
+
+ for (index_ = 0; ranges[index_] > -1; index_ += 3) {
+ assert(ranges[index_] <= ranges[index_ + 1]);
+ loc_setrange_char(ranges[index_],
+ ranges[index_ + 1], ranges[index_ + 2], table);
+ }
}
@@ -117,15 +109,14 @@ loc_setranges_char (const sc_int ranges[], sc_char table[])
*/
enum { RANGES_LENGTH = 32 };
enum { SIGNATURE_COUNT = 24, SIGNATURE_LENGTH = 3 };
-typedef struct
-{
- const sc_char *const name;
- const sc_int isspace_ranges[RANGES_LENGTH];
- const sc_int isdigit_ranges[RANGES_LENGTH];
- const sc_int isalpha_ranges[RANGES_LENGTH];
- const sc_int toupper_ranges[RANGES_LENGTH];
- const sc_int tolower_ranges[RANGES_LENGTH];
- const sc_byte signature[SIGNATURE_COUNT][SIGNATURE_LENGTH];
+typedef struct {
+ const sc_char *const name;
+ const sc_int isspace_ranges[RANGES_LENGTH];
+ const sc_int isdigit_ranges[RANGES_LENGTH];
+ const sc_int isalpha_ranges[RANGES_LENGTH];
+ const sc_int toupper_ranges[RANGES_LENGTH];
+ const sc_int tolower_ranges[RANGES_LENGTH];
+ const sc_byte signature[SIGNATURE_COUNT][SIGNATURE_LENGTH];
} sc_locale_t;
@@ -135,14 +126,13 @@ typedef struct
* table, for synchronization with changed locales. This is the dynamic data
* portion of a locale.
*/
-typedef struct
-{
- const sc_locale_t *locale;
- sc_bool isspace[TABLE_SIZE];
- sc_bool isdigit[TABLE_SIZE];
- sc_bool isalpha[TABLE_SIZE];
- sc_char toupper[TABLE_SIZE];
- sc_char tolower[TABLE_SIZE];
+typedef struct {
+ const sc_locale_t *locale;
+ sc_bool isspace[TABLE_SIZE];
+ sc_bool isdigit[TABLE_SIZE];
+ sc_bool isalpha[TABLE_SIZE];
+ sc_char toupper[TABLE_SIZE];
+ sc_char tolower[TABLE_SIZE];
} sc_locale_table_t;
/*
@@ -160,26 +150,24 @@ static sc_locale_table_t loc_locale_tables = {NULL, {0}, {0}, {0}, {0}, {0}};
* and if not for the same locale, (re-)initialize.
*/
static void
-loc_synchronize_tables (const sc_locale_t *locale)
-{
- /* Clear all tables and the locale pointer. */
- memset (&loc_locale_tables, 0, sizeof (loc_locale_tables));
-
- /* Set ranges and attach the new locale. */
- loc_setranges_bool (locale->isspace_ranges, loc_locale_tables.isspace);
- loc_setranges_bool (locale->isdigit_ranges, loc_locale_tables.isdigit);
- loc_setranges_bool (locale->isalpha_ranges, loc_locale_tables.isalpha);
- loc_setranges_char (locale->toupper_ranges, loc_locale_tables.toupper);
- loc_setranges_char (locale->tolower_ranges, loc_locale_tables.tolower);
-
- loc_locale_tables.locale = locale;
+loc_synchronize_tables(const sc_locale_t *locale) {
+ /* Clear all tables and the locale pointer. */
+ memset(&loc_locale_tables, 0, sizeof(loc_locale_tables));
+
+ /* Set ranges and attach the new locale. */
+ loc_setranges_bool(locale->isspace_ranges, loc_locale_tables.isspace);
+ loc_setranges_bool(locale->isdigit_ranges, loc_locale_tables.isdigit);
+ loc_setranges_bool(locale->isalpha_ranges, loc_locale_tables.isalpha);
+ loc_setranges_char(locale->toupper_ranges, loc_locale_tables.toupper);
+ loc_setranges_char(locale->tolower_ranges, loc_locale_tables.tolower);
+
+ loc_locale_tables.locale = locale;
}
static void
-loc_check_tables_synchronized (const sc_locale_t *locale)
-{
- if (locale != loc_locale_tables.locale)
- loc_synchronize_tables (locale);
+loc_check_tables_synchronized(const sc_locale_t *locale) {
+ if (locale != loc_locale_tables.locale)
+ loc_synchronize_tables(locale);
}
@@ -190,16 +178,22 @@ loc_check_tables_synchronized (const sc_locale_t *locale)
* practice, it seems that only English and French Adrift Latin1 games exist).
*/
static const sc_locale_t LATIN1_LOCALE = {
- "Latin1",
- {9,13, 32,32, 160,160, -1},
- {48,57, -1},
- {65,90, 97,122, 192,214, 216,246, 248,255, 138,138, 140,140,
- 142,142, 154,154, 156,156, 158,158, 159,159, -1},
- {0,TABLE_SIZE-1,0, 97,122,-32, 224,246,-32, 248,254,-32, 154,154,-16,
- 156,156,-16, 158,158,-16, 255,255,-96, -1},
- {0,TABLE_SIZE-1,0, 65,90,32, 192,214,32, 216,222,32, 138,138,16,
- 140,140,16, 142,142,16, 159,159,96, -1},
- {{0}}
+ "Latin1",
+ {9, 13, 32, 32, 160, 160, -1},
+ {48, 57, -1},
+ {
+ 65, 90, 97, 122, 192, 214, 216, 246, 248, 255, 138, 138, 140, 140,
+ 142, 142, 154, 154, 156, 156, 158, 158, 159, 159, -1
+ },
+ {
+ 0, TABLE_SIZE - 1, 0, 97, 122, -32, 224, 246, -32, 248, 254, -32, 154, 154, -16,
+ 156, 156, -16, 158, 158, -16, 255, 255, -96, -1
+ },
+ {
+ 0, TABLE_SIZE - 1, 0, 65, 90, 32, 192, 214, 32, 216, 222, 32, 138, 138, 16,
+ 140, 140, 16, 142, 142, 16, 159, 159, 96, -1
+ },
+ {{0}}
};
@@ -208,29 +202,36 @@ static const sc_locale_t LATIN1_LOCALE = {
* both mixed case and lowercase Russian Cyrillic.
*/
static const sc_locale_t CYRILLIC_LOCALE = {
- "Cyrillic",
- {9,13, 32,32, 160,160, -1},
- {48,57, -1},
- {65,90, 97,122, 168,168, 184,184, 175,175, 191,191, 178,179,
- 192,255, -1},
- {0,TABLE_SIZE-1,0, 97,122,-32, 184,184,-16, 191,191,-16, 179,179,-1,
- 224,255,-32, -1},
- {0,TABLE_SIZE-1,0, 65,90,32, 168,168,16, 175,175,16, 178,178,1,
- 192,223,32, -1},
- {{223, 237, 226}, {212, 229, 226}, {204, 224, 240}, {192, 239, 240},
- {204, 224, 233}, {200, 254, 237}, {200, 254, 235}, {192, 226, 227},
- {209, 229, 237}, {206, 234, 242}, {205, 238, 255}, {196, 229, 234},
- {255, 237, 226}, {244, 229, 226}, {236, 224, 240}, {224, 239, 240},
- {236, 224, 233}, {232, 254, 237}, {232, 254, 235}, {224, 226, 227},
- {241, 229, 237}, {238, 234, 242}, {237, 238, 255}, {228, 229, 234}}
+ "Cyrillic",
+ {9, 13, 32, 32, 160, 160, -1},
+ {48, 57, -1},
+ {
+ 65, 90, 97, 122, 168, 168, 184, 184, 175, 175, 191, 191, 178, 179,
+ 192, 255, -1
+ },
+ {
+ 0, TABLE_SIZE - 1, 0, 97, 122, -32, 184, 184, -16, 191, 191, -16, 179, 179, -1,
+ 224, 255, -32, -1
+ },
+ {
+ 0, TABLE_SIZE - 1, 0, 65, 90, 32, 168, 168, 16, 175, 175, 16, 178, 178, 1,
+ 192, 223, 32, -1
+ },
+ { {223, 237, 226}, {212, 229, 226}, {204, 224, 240}, {192, 239, 240},
+ {204, 224, 233}, {200, 254, 237}, {200, 254, 235}, {192, 226, 227},
+ {209, 229, 237}, {206, 234, 242}, {205, 238, 255}, {196, 229, 234},
+ {255, 237, 226}, {244, 229, 226}, {236, 224, 240}, {224, 239, 240},
+ {236, 224, 233}, {232, 254, 237}, {232, 254, 235}, {224, 226, 227},
+ {241, 229, 237}, {238, 234, 242}, {237, 238, 255}, {228, 229, 234}
+ }
};
/* List of pointers to supported and available locales, NULL terminated. */
static const sc_locale_t *const AVAILABLE_LOCALES[] = {
- &LATIN1_LOCALE,
- &CYRILLIC_LOCALE,
- NULL
+ &LATIN1_LOCALE,
+ &CYRILLIC_LOCALE,
+ NULL
};
/*
@@ -250,20 +251,19 @@ static sc_bool loc_is_autodetect_enabled = TRUE;
* NULL if it doesn't match the expected format.
*/
static const sc_char *
-loc_locate_signature_in_date (const sc_char *date)
-{
- sc_int day, year, converted;
- sc_char signature[SIGNATURE_LENGTH + 1];
-
- /* Clear signature, and convert using a scanf format. */
- memset (signature, 0, sizeof (signature));
- converted = sscanf (date, "%2ld %3[^ 0-9] %4ld", &day, signature, &year);
-
- /* Valid if we converted three values, and month has three characters. */
- if (converted == 3 && strlen (signature) == SIGNATURE_LENGTH)
- return strstr (date, signature);
- else
- return NULL;
+loc_locate_signature_in_date(const sc_char *date) {
+ sc_int day, year, converted;
+ sc_char signature[SIGNATURE_LENGTH + 1];
+
+ /* Clear signature, and convert using a scanf format. */
+ memset(signature, 0, sizeof(signature));
+ converted = sscanf(date, "%2ld %3[^ 0-9] %4ld", &day, signature, &year);
+
+ /* Valid if we converted three values, and month has three characters. */
+ if (converted == 3 && strlen(signature) == SIGNATURE_LENGTH)
+ return strstr(date, signature);
+ else
+ return NULL;
}
@@ -276,24 +276,21 @@ loc_locate_signature_in_date (const sc_char *date)
* codepage, but the locale is not yet (by definition) set.
*/
static sc_bool
-loc_compare_locale_signatures (const char *signature, const sc_locale_t *locale)
-{
- sc_int index_;
- sc_bool is_matched;
-
- /* Compare signatures, stopping on the first match found. */
- is_matched = FALSE;
- for (index_ = 0; index_ < SIGNATURE_COUNT; index_++)
- {
- if (memcmp (locale->signature[index_],
- signature, sizeof (locale->signature[0])) == 0)
- {
- is_matched = TRUE;
- break;
- }
- }
-
- return is_matched;
+loc_compare_locale_signatures(const char *signature, const sc_locale_t *locale) {
+ sc_int index_;
+ sc_bool is_matched;
+
+ /* Compare signatures, stopping on the first match found. */
+ is_matched = FALSE;
+ for (index_ = 0; index_ < SIGNATURE_COUNT; index_++) {
+ if (memcmp(locale->signature[index_],
+ signature, sizeof(locale->signature[0])) == 0) {
+ is_matched = TRUE;
+ break;
+ }
+ }
+
+ return is_matched;
}
@@ -306,31 +303,27 @@ loc_compare_locale_signatures (const char *signature, const sc_locale_t *locale)
* first locale that matches, or NULL if none match.
*/
static const sc_locale_t *
-loc_find_matching_locale (const sc_char *date,
- const sc_locale_t *const *locales)
-{
- const sc_char *signature;
- const sc_locale_t *matched = NULL;
-
- /* Get the month part of date, and if valid, search locale signatures. */
- signature = loc_locate_signature_in_date (date);
- if (signature)
- {
- const sc_locale_t *const *iterator;
-
- /* Search for this signature in the locale's signatures. */
- for (iterator = locales; *iterator; iterator++)
- {
- if (loc_compare_locale_signatures (signature, *iterator))
- {
- matched = *iterator;
- break;
- }
- }
- }
-
- /* Return the matching locale, NULL if none matched. */
- return matched;
+loc_find_matching_locale(const sc_char *date,
+ const sc_locale_t *const *locales) {
+ const sc_char *signature;
+ const sc_locale_t *matched = NULL;
+
+ /* Get the month part of date, and if valid, search locale signatures. */
+ signature = loc_locate_signature_in_date(date);
+ if (signature) {
+ const sc_locale_t *const *iterator;
+
+ /* Search for this signature in the locale's signatures. */
+ for (iterator = locales; *iterator; iterator++) {
+ if (loc_compare_locale_signatures(signature, *iterator)) {
+ matched = *iterator;
+ break;
+ }
+ }
+ }
+
+ /* Return the matching locale, NULL if none matched. */
+ return matched;
}
@@ -341,28 +334,26 @@ loc_find_matching_locale (const sc_char *date,
* compilation date.
*/
void
-loc_detect_game_locale (sc_prop_setref_t bundle)
-{
- assert (bundle);
-
- /* If an explicit locale has already been set, ignore the call. */
- if (loc_is_autodetect_enabled)
- {
- sc_vartype_t vt_key[1];
- const sc_char *compile_date;
- const sc_locale_t *matched;
-
- /* Read the game's compilation date from the properties. */
- vt_key[0].string = "CompileDate";
- compile_date = prop_get_string (bundle, "S<-s", vt_key);
-
- /* Search for a matching locale based on the game compilation date. */
- matched = loc_find_matching_locale (compile_date, AVAILABLE_LOCALES);
-
- /* If a locale matched, set the global locale to it. */
- if (matched)
- loc_locale = matched;
- }
+loc_detect_game_locale(sc_prop_setref_t bundle) {
+ assert(bundle);
+
+ /* If an explicit locale has already been set, ignore the call. */
+ if (loc_is_autodetect_enabled) {
+ sc_vartype_t vt_key[1];
+ const sc_char *compile_date;
+ const sc_locale_t *matched;
+
+ /* Read the game's compilation date from the properties. */
+ vt_key[0].string = "CompileDate";
+ compile_date = prop_get_string(bundle, "S<-s", vt_key);
+
+ /* Search for a matching locale based on the game compilation date. */
+ matched = loc_find_matching_locale(compile_date, AVAILABLE_LOCALES);
+
+ /* If a locale matched, set the global locale to it. */
+ if (matched)
+ loc_locale = matched;
+ }
}
@@ -377,26 +368,23 @@ loc_detect_game_locale (sc_prop_setref_t bundle)
* of this function.
*/
static sc_char
-loc_ascii_tolower (sc_char ch)
-{
- return (ch >= 'A' && ch <= 'Z') ? ch - 'A' + 'a' : ch;
+loc_ascii_tolower(sc_char ch) {
+ return (ch >= 'A' && ch <= 'Z') ? ch - 'A' + 'a' : ch;
}
static sc_int
-loc_ascii_strncasecmp (const sc_char *s1, const sc_char *s2, sc_int n)
-{
- sc_int index_;
+loc_ascii_strncasecmp(const sc_char *s1, const sc_char *s2, sc_int n) {
+ sc_int index_;
- for (index_ = 0; index_ < n; index_++)
- {
- sc_int diff;
+ for (index_ = 0; index_ < n; index_++) {
+ sc_int diff;
- diff = loc_ascii_tolower (s1[index_]) - loc_ascii_tolower (s2[index_]);
- if (diff < 0 || diff > 0)
- return diff < 0 ? -1 : 1;
- }
+ diff = loc_ascii_tolower(s1[index_]) - loc_ascii_tolower(s2[index_]);
+ if (diff < 0 || diff > 0)
+ return diff < 0 ? -1 : 1;
+ }
- return 0;
+ return 0;
}
@@ -409,41 +397,36 @@ loc_ascii_strncasecmp (const sc_char *s1, const sc_char *s2, sc_int n)
* if none yet set.
*/
sc_bool
-loc_set_locale (const sc_char *name)
-{
- const sc_locale_t *matched = NULL;
- const sc_locale_t *const *iterator;
- assert (name);
-
- /*
- * Search locales for a matching name, abbreviated if necessary. Stop on
- * the first match found.
- */
- for (iterator = AVAILABLE_LOCALES; *iterator; iterator++)
- {
- const sc_locale_t *const locale = *iterator;
-
- if (loc_ascii_strncasecmp (name, locale->name, strlen (name)) == 0)
- {
- matched = locale;
- break;
- }
- }
-
- /* If matched, set the global locale, and lock out future autodetection. */
- if (matched)
- {
- loc_locale = matched;
- loc_is_autodetect_enabled = FALSE;
- }
-
- return matched ? TRUE : FALSE;
+loc_set_locale(const sc_char *name) {
+ const sc_locale_t *matched = NULL;
+ const sc_locale_t *const *iterator;
+ assert(name);
+
+ /*
+ * Search locales for a matching name, abbreviated if necessary. Stop on
+ * the first match found.
+ */
+ for (iterator = AVAILABLE_LOCALES; *iterator; iterator++) {
+ const sc_locale_t *const locale = *iterator;
+
+ if (loc_ascii_strncasecmp(name, locale->name, strlen(name)) == 0) {
+ matched = locale;
+ break;
+ }
+ }
+
+ /* If matched, set the global locale, and lock out future autodetection. */
+ if (matched) {
+ loc_locale = matched;
+ loc_is_autodetect_enabled = FALSE;
+ }
+
+ return matched ? TRUE : FALSE;
}
const sc_char *
-loc_get_locale (void)
-{
- return loc_locale->name;
+loc_get_locale(void) {
+ return loc_locale->name;
}
@@ -456,55 +439,49 @@ loc_get_locale (void)
* Print out locale tables.
*/
static int
-loc_debug_dump_new_line (sc_int index_, sc_int count)
-{
- return index_ < TABLE_SIZE - 1 && index_ % count == count - 1;
+loc_debug_dump_new_line(sc_int index_, sc_int count) {
+ return index_ < TABLE_SIZE - 1 && index_ % count == count - 1;
}
static void
-loc_debug_dump_bool_table (const sc_char *label,
- sc_int count, const sc_bool table[])
-{
- sc_int index_;
-
- sc_trace ("loc_locale_tables.%s = {\n ", label);
- for (index_ = 0; index_ < TABLE_SIZE; index_++)
- {
- sc_trace ("%s%s", table[index_] ? "T" : "F",
- loc_debug_dump_new_line (index_, count) ? "\n " : "");
- }
- sc_trace ("\n}\n");
+loc_debug_dump_bool_table(const sc_char *label,
+ sc_int count, const sc_bool table[]) {
+ sc_int index_;
+
+ sc_trace("loc_locale_tables.%s = {\n ", label);
+ for (index_ = 0; index_ < TABLE_SIZE; index_++) {
+ sc_trace("%s%s", table[index_] ? "T" : "F",
+ loc_debug_dump_new_line(index_, count) ? "\n " : "");
+ }
+ sc_trace("\n}\n");
}
static void
-loc_debug_dump_char_table (const sc_char *label,
- sc_int count, const sc_char table[])
-{
- sc_int index_;
-
- sc_trace ("loc_locale_tables.%s = {\n ", label);
- for (index_ = 0; index_ < TABLE_SIZE; index_++)
- {
- sc_trace ("%02lx%s", (sc_int) (sc_byte) table[index_],
- loc_debug_dump_new_line (index_, count) ? "\n " : " ");
- }
- sc_trace ("\n}\n");
+loc_debug_dump_char_table(const sc_char *label,
+ sc_int count, const sc_char table[]) {
+ sc_int index_;
+
+ sc_trace("loc_locale_tables.%s = {\n ", label);
+ for (index_ = 0; index_ < TABLE_SIZE; index_++) {
+ sc_trace("%02lx%s", (sc_int)(sc_byte) table[index_],
+ loc_debug_dump_new_line(index_, count) ? "\n " : " ");
+ }
+ sc_trace("\n}\n");
}
void
-loc_debug_dump (void)
-{
- sc_trace ("Locale: debug dump follows...\n");
-
- loc_check_tables_synchronized (loc_locale);
- sc_trace ("loc_locale_tables"
- ".locale->name = %s\n", loc_locale_tables.locale->name);
-
- loc_debug_dump_bool_table ("isspace", 64, loc_locale_tables.isspace);
- loc_debug_dump_bool_table ("isdigit", 64, loc_locale_tables.isdigit);
- loc_debug_dump_bool_table ("isalpha", 64, loc_locale_tables.isalpha);
- loc_debug_dump_char_table ("toupper", 16, loc_locale_tables.toupper);
- loc_debug_dump_char_table ("tolower", 16, loc_locale_tables.tolower);
+loc_debug_dump(void) {
+ sc_trace("Locale: debug dump follows...\n");
+
+ loc_check_tables_synchronized(loc_locale);
+ sc_trace("loc_locale_tables"
+ ".locale->name = %s\n", loc_locale_tables.locale->name);
+
+ loc_debug_dump_bool_table("isspace", 64, loc_locale_tables.isspace);
+ loc_debug_dump_bool_table("isdigit", 64, loc_locale_tables.isdigit);
+ loc_debug_dump_bool_table("isalpha", 64, loc_locale_tables.isalpha);
+ loc_debug_dump_char_table("toupper", 16, loc_locale_tables.toupper);
+ loc_debug_dump_char_table("tolower", 16, loc_locale_tables.tolower);
}
@@ -516,17 +493,15 @@ loc_debug_dump (void)
* tables to the currently set locale, and return the value from the table.
*/
static sc_bool
-loc_bool_template (sc_char character, const sc_bool table[])
-{
- loc_check_tables_synchronized (loc_locale);
- return table[(sc_byte) character];
+loc_bool_template(sc_char character, const sc_bool table[]) {
+ loc_check_tables_synchronized(loc_locale);
+ return table[(sc_byte) character];
}
static sc_char
-loc_char_template (sc_char character, const sc_char table[])
-{
- loc_check_tables_synchronized (loc_locale);
- return table[(sc_byte) character];
+loc_char_template(sc_char character, const sc_char table[]) {
+ loc_check_tables_synchronized(loc_locale);
+ return table[(sc_byte) character];
}
@@ -540,33 +515,28 @@ loc_char_template (sc_char character, const sc_char table[])
* Public entry points into locale variant ctype functions.
*/
sc_bool
-sc_isspace (sc_char character)
-{
- return loc_bool_template (character, loc_locale_tables.isspace);
+sc_isspace(sc_char character) {
+ return loc_bool_template(character, loc_locale_tables.isspace);
}
sc_bool
-sc_isalpha (sc_char character)
-{
- return loc_bool_template (character, loc_locale_tables.isalpha);
+sc_isalpha(sc_char character) {
+ return loc_bool_template(character, loc_locale_tables.isalpha);
}
sc_bool
-sc_isdigit (sc_char character)
-{
- return loc_bool_template (character, loc_locale_tables.isdigit);
+sc_isdigit(sc_char character) {
+ return loc_bool_template(character, loc_locale_tables.isdigit);
}
sc_char
-sc_toupper (sc_char character)
-{
- return loc_char_template (character, loc_locale_tables.toupper);
+sc_toupper(sc_char character) {
+ return loc_char_template(character, loc_locale_tables.toupper);
}
sc_char
-sc_tolower (sc_char character)
-{
- return loc_char_template (character, loc_locale_tables.tolower);
+sc_tolower(sc_char character) {
+ return loc_char_template(character, loc_locale_tables.tolower);
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scmemos.cpp b/engines/glk/adrift/scmemos.cpp
index 4809b2078f..9179783baa 100644
--- a/engines/glk/adrift/scmemos.cpp
+++ b/engines/glk/adrift/scmemos.cpp
@@ -34,11 +34,10 @@ enum { MEMO_ALLOCATION_BLOCK = 32 };
* Game memo structure, saves a serialized game. Allocation is preserved so
* that structures can be reused without requiring reallocation.
*/
-typedef struct sc_memo_s
-{
- sc_byte *serialized_game;
- sc_int allocation;
- sc_int length;
+typedef struct sc_memo_s {
+ sc_byte *serialized_game;
+ sc_int allocation;
+ sc_int length;
} sc_memo_t;
typedef sc_memo_t *sc_memoref_t;
@@ -46,14 +45,13 @@ typedef sc_memo_t *sc_memoref_t;
* Game command history structure, similar to a memo. Saves a player input
* command to create a history, reusing allocation where possible.
*/
-typedef struct sc_history_s
-{
- sc_char *command;
- sc_int sequence;
- sc_int timestamp;
- sc_int turns;
- sc_int allocation;
- sc_int length;
+typedef struct sc_history_s {
+ sc_char *command;
+ sc_int sequence;
+ sc_int timestamp;
+ sc_int turns;
+ sc_int allocation;
+ sc_int length;
} sc_history_t;
typedef sc_history_t *sc_historyref_t;
@@ -66,16 +64,15 @@ typedef sc_history_t *sc_historyref_t;
* also a ring with limited capacity.
*/
enum { MEMO_UNDO_TABLE_SIZE = 16, MEMO_HISTORY_TABLE_SIZE = 64 };
-typedef struct sc_memo_set_s
-{
- sc_uint magic;
- sc_memo_t memo[MEMO_UNDO_TABLE_SIZE];
- sc_int memo_cursor;
-
- sc_history_t history[MEMO_HISTORY_TABLE_SIZE];
- sc_int history_count;
- sc_int current_history;
- sc_bool is_at_start;
+typedef struct sc_memo_set_s {
+ sc_uint magic;
+ sc_memo_t memo[MEMO_UNDO_TABLE_SIZE];
+ sc_int memo_cursor;
+
+ sc_history_t history[MEMO_HISTORY_TABLE_SIZE];
+ sc_int history_count;
+ sc_int current_history;
+ sc_bool is_at_start;
} sc_memo_set_t;
@@ -85,9 +82,8 @@ typedef struct sc_memo_set_s
* Return TRUE if pointer is a valid memo set, FALSE otherwise.
*/
static sc_bool
-memo_is_valid (sc_memo_setref_t memento)
-{
- return memento && memento->magic == MEMENTO_MAGIC;
+memo_is_valid(sc_memo_setref_t memento) {
+ return memento && memento->magic == MEMENTO_MAGIC;
}
@@ -97,12 +93,11 @@ memo_is_valid (sc_memo_setref_t memento)
* Round up an allocation in bytes to the next allocation block.
*/
static sc_int
-memo_round_up (sc_int allocation)
-{
- sc_int extended;
+memo_round_up(sc_int allocation) {
+ sc_int extended;
- extended = allocation + MEMO_ALLOCATION_BLOCK - 1;
- return (extended / MEMO_ALLOCATION_BLOCK) * MEMO_ALLOCATION_BLOCK;
+ extended = allocation + MEMO_ALLOCATION_BLOCK - 1;
+ return (extended / MEMO_ALLOCATION_BLOCK) * MEMO_ALLOCATION_BLOCK;
}
@@ -112,23 +107,22 @@ memo_round_up (sc_int allocation)
* Create and return a new set of memos.
*/
sc_memo_setref_t
-memo_create (void)
-{
- sc_memo_setref_t memento;
+memo_create(void) {
+ sc_memo_setref_t memento;
- /* Create and initialize a clean set of memos. */
- memento = (sc_memo_setref_t)sc_malloc (sizeof (*memento));
- memento->magic = MEMENTO_MAGIC;
+ /* Create and initialize a clean set of memos. */
+ memento = (sc_memo_setref_t)sc_malloc(sizeof(*memento));
+ memento->magic = MEMENTO_MAGIC;
- memset (memento->memo, 0, sizeof (memento->memo));
- memento->memo_cursor = 0;
+ memset(memento->memo, 0, sizeof(memento->memo));
+ memento->memo_cursor = 0;
- memset (memento->history, 0, sizeof (memento->history));
- memento->history_count = 0;
- memento->current_history = 0;
- memento->is_at_start = FALSE;
+ memset(memento->history, 0, sizeof(memento->history));
+ memento->history_count = 0;
+ memento->current_history = 0;
+ memento->is_at_start = FALSE;
- return memento;
+ return memento;
}
@@ -138,30 +132,27 @@ memo_create (void)
* Destroy a memo set, and free its heap memory.
*/
void
-memo_destroy (sc_memo_setref_t memento)
-{
- sc_int index_;
- assert (memo_is_valid (memento));
-
- /* Free the content of any used memo and any used history. */
- for (index_ = 0; index_ < MEMO_UNDO_TABLE_SIZE; index_++)
- {
- sc_memoref_t memo;
-
- memo = memento->memo + index_;
- sc_free (memo->serialized_game);
- }
- for (index_ = 0; index_ < MEMO_HISTORY_TABLE_SIZE; index_++)
- {
- sc_historyref_t history;
-
- history = memento->history + index_;
- sc_free (history->command);
- }
-
- /* Poison and free the memo set itself. */
- memset (memento, 0xaa, sizeof (*memento));
- sc_free (memento);
+memo_destroy(sc_memo_setref_t memento) {
+ sc_int index_;
+ assert(memo_is_valid(memento));
+
+ /* Free the content of any used memo and any used history. */
+ for (index_ = 0; index_ < MEMO_UNDO_TABLE_SIZE; index_++) {
+ sc_memoref_t memo;
+
+ memo = memento->memo + index_;
+ sc_free(memo->serialized_game);
+ }
+ for (index_ = 0; index_ < MEMO_HISTORY_TABLE_SIZE; index_++) {
+ sc_historyref_t history;
+
+ history = memento->history + index_;
+ sc_free(history->command);
+ }
+
+ /* Poison and free the memo set itself. */
+ memset(memento, 0xaa, sizeof(*memento));
+ sc_free(memento);
}
@@ -172,28 +163,26 @@ memo_destroy (sc_memo_setref_t memento)
* that already stored in the memo.
*/
static void
-memo_save_game_callback (void *opaque, const sc_byte *buffer, sc_int length)
-{
- sc_memoref_t memo = (sc_memoref_t)opaque;
- sc_int required;
- assert (opaque && buffer && length > 0);
-
- /*
- * If necessary, increase the allocation for this memo. Serialized games
- * tend to grow slightly as the game progresses, so we add a bit of extra
- * to the actual allocation.
- */
- required = memo->length + length;
- if (required > memo->allocation)
- {
- required = memo_round_up (required + 2 * MEMO_ALLOCATION_BLOCK);
- memo->serialized_game = (sc_byte *)sc_realloc (memo->serialized_game, required);
- memo->allocation = required;
- }
-
- /* Add this block of data to the buffer. */
- memcpy (memo->serialized_game + memo->length, buffer, length);
- memo->length += length;
+memo_save_game_callback(void *opaque, const sc_byte *buffer, sc_int length) {
+ sc_memoref_t memo = (sc_memoref_t)opaque;
+ sc_int required;
+ assert(opaque && buffer && length > 0);
+
+ /*
+ * If necessary, increase the allocation for this memo. Serialized games
+ * tend to grow slightly as the game progresses, so we add a bit of extra
+ * to the actual allocation.
+ */
+ required = memo->length + length;
+ if (required > memo->allocation) {
+ required = memo_round_up(required + 2 * MEMO_ALLOCATION_BLOCK);
+ memo->serialized_game = (sc_byte *)sc_realloc(memo->serialized_game, required);
+ memo->allocation = required;
+ }
+
+ /* Add this block of data to the buffer. */
+ memcpy(memo->serialized_game + memo->length, buffer, length);
+ memo->length += length;
}
@@ -203,32 +192,29 @@ memo_save_game_callback (void *opaque, const sc_byte *buffer, sc_int length)
* Store a game in the next memo slot.
*/
void
-memo_save_game (sc_memo_setref_t memento, sc_gameref_t game)
-{
- sc_memoref_t memo;
- assert (memo_is_valid (memento));
-
- /*
- * If the current slot is in use, we can re-use its allocation. Saved
- * games will tend to be of roughly equal sizes, so it's worth doing.
- */
- memo = memento->memo + memento->memo_cursor;
- memo->length = 0;
-
- /* Serialize the given game into this memo. */
- ser_save_game (game, memo_save_game_callback, memo);
-
- /*
- * If serialization worked (failure would be a surprise), advance the
- * current memo cursor.
- */
- if (memo->length > 0)
- {
- memento->memo_cursor++;
- memento->memo_cursor %= MEMO_UNDO_TABLE_SIZE;
- }
- else
- sc_error ("memo_save_game: warning: game save failed\n");
+memo_save_game(sc_memo_setref_t memento, sc_gameref_t game) {
+ sc_memoref_t memo;
+ assert(memo_is_valid(memento));
+
+ /*
+ * If the current slot is in use, we can re-use its allocation. Saved
+ * games will tend to be of roughly equal sizes, so it's worth doing.
+ */
+ memo = memento->memo + memento->memo_cursor;
+ memo->length = 0;
+
+ /* Serialize the given game into this memo. */
+ ser_save_game(game, memo_save_game_callback, memo);
+
+ /*
+ * If serialization worked (failure would be a surprise), advance the
+ * current memo cursor.
+ */
+ if (memo->length > 0) {
+ memento->memo_cursor++;
+ memento->memo_cursor %= MEMO_UNDO_TABLE_SIZE;
+ } else
+ sc_error("memo_save_game: warning: game save failed\n");
}
@@ -239,23 +225,22 @@ memo_save_game (sc_memo_setref_t memento, sc_gameref_t game)
* until it's drained.
*/
static sc_int
-memo_load_game_callback (void *opaque, sc_byte *buffer, sc_int length)
-{
- sc_memoref_t memo = (sc_memoref_t)opaque;
- sc_int bytes;
- assert (opaque && buffer && length > 0);
-
- /* Send back either all the bytes, or as many as the buffer allows. */
- bytes = (memo->length < length) ? memo->length : length;
-
- /* Read and remove the first block of data (or all if less than length). */
- memcpy (buffer, memo->serialized_game, bytes);
- memmove (memo->serialized_game,
- memo->serialized_game + bytes, memo->length - bytes);
- memo->length -= bytes;
-
- /* Return the count of bytes placed in the buffer. */
- return bytes;
+memo_load_game_callback(void *opaque, sc_byte *buffer, sc_int length) {
+ sc_memoref_t memo = (sc_memoref_t)opaque;
+ sc_int bytes;
+ assert(opaque && buffer && length > 0);
+
+ /* Send back either all the bytes, or as many as the buffer allows. */
+ bytes = (memo->length < length) ? memo->length : length;
+
+ /* Read and remove the first block of data (or all if less than length). */
+ memcpy(buffer, memo->serialized_game, bytes);
+ memmove(memo->serialized_game,
+ memo->serialized_game + bytes, memo->length - bytes);
+ memo->length -= bytes;
+
+ /* Return the count of bytes placed in the buffer. */
+ return bytes;
}
@@ -265,48 +250,45 @@ memo_load_game_callback (void *opaque, sc_byte *buffer, sc_int length)
* Restore a game from the last memo slot used, if possible.
*/
sc_bool
-memo_load_game (sc_memo_setref_t memento, sc_gameref_t game)
-{
- sc_int cursor;
- sc_memoref_t memo;
- assert (memo_is_valid (memento));
-
- /* Look back one from the current memo cursor. */
- cursor = (memento->memo_cursor == 0)
- ? MEMO_UNDO_TABLE_SIZE - 1 : memento->memo_cursor - 1;
- memo = memento->memo + cursor;
-
- /* If this slot is not empty, restore the serialized game held in it. */
- if (memo->length > 0)
- {
- sc_bool status;
-
- /*
- * Deserialize the given game from this memo; failure would be somewhat
- * of a surprise here.
- */
- status = ser_load_game (game, memo_load_game_callback, memo);
- if (!status)
- sc_error ("memo_load_game: warning: game load failed\n");
-
- /*
- * This should have drained the memo of all data, but to be sure that
- * there's no chance of trying to restore from this slot again, we'll
- * force it anyway.
- */
- if (memo->length > 0)
- {
- sc_error ("memo_load_game: warning: data remains after loading\n");
- memo->length = 0;
- }
-
- /* Regress current memo, and return TRUE if we restored a memo. */
- memento->memo_cursor = cursor;
- return status;
- }
-
- /* There are no more memos to restore. */
- return FALSE;
+memo_load_game(sc_memo_setref_t memento, sc_gameref_t game) {
+ sc_int cursor;
+ sc_memoref_t memo;
+ assert(memo_is_valid(memento));
+
+ /* Look back one from the current memo cursor. */
+ cursor = (memento->memo_cursor == 0)
+ ? MEMO_UNDO_TABLE_SIZE - 1 : memento->memo_cursor - 1;
+ memo = memento->memo + cursor;
+
+ /* If this slot is not empty, restore the serialized game held in it. */
+ if (memo->length > 0) {
+ sc_bool status;
+
+ /*
+ * Deserialize the given game from this memo; failure would be somewhat
+ * of a surprise here.
+ */
+ status = ser_load_game(game, memo_load_game_callback, memo);
+ if (!status)
+ sc_error("memo_load_game: warning: game load failed\n");
+
+ /*
+ * This should have drained the memo of all data, but to be sure that
+ * there's no chance of trying to restore from this slot again, we'll
+ * force it anyway.
+ */
+ if (memo->length > 0) {
+ sc_error("memo_load_game: warning: data remains after loading\n");
+ memo->length = 0;
+ }
+
+ /* Regress current memo, and return TRUE if we restored a memo. */
+ memento->memo_cursor = cursor;
+ return status;
+ }
+
+ /* There are no more memos to restore. */
+ return FALSE;
}
@@ -317,20 +299,19 @@ memo_load_game (sc_memo_setref_t memento, sc_gameref_t game)
* otherwise.
*/
sc_bool
-memo_is_load_available (sc_memo_setref_t memento)
-{
- sc_int cursor;
- sc_memoref_t memo;
- assert (memo_is_valid (memento));
-
- /*
- * Look back one from the current memo cursor. Return TRUE if this slot
- * contains a serialized game.
- */
- cursor = (memento->memo_cursor == 0)
- ? MEMO_UNDO_TABLE_SIZE - 1 : memento->memo_cursor - 1;
- memo = memento->memo + cursor;
- return memo->length > 0;
+memo_is_load_available(sc_memo_setref_t memento) {
+ sc_int cursor;
+ sc_memoref_t memo;
+ assert(memo_is_valid(memento));
+
+ /*
+ * Look back one from the current memo cursor. Return TRUE if this slot
+ * contains a serialized game.
+ */
+ cursor = (memento->memo_cursor == 0)
+ ? MEMO_UNDO_TABLE_SIZE - 1 : memento->memo_cursor - 1;
+ memo = memento->memo + cursor;
+ return memo->length > 0;
}
@@ -340,23 +321,21 @@ memo_is_load_available (sc_memo_setref_t memento)
* Forget the memos of saved games.
*/
void
-memo_clear_games (sc_memo_setref_t memento)
-{
- sc_int index_;
- assert (memo_is_valid (memento));
-
- /* Deallocate every entry. */
- for (index_ = 0; index_ < MEMO_UNDO_TABLE_SIZE; index_++)
- {
- sc_memoref_t memo;
-
- memo = memento->memo + index_;
- sc_free (memo->serialized_game);
- }
-
- /* Reset all entries and the cursor. */
- memset (memento->memo, 0, sizeof (memento->memo));
- memento->memo_cursor = 0;
+memo_clear_games(sc_memo_setref_t memento) {
+ sc_int index_;
+ assert(memo_is_valid(memento));
+
+ /* Deallocate every entry. */
+ for (index_ = 0; index_ < MEMO_UNDO_TABLE_SIZE; index_++) {
+ sc_memoref_t memo;
+
+ memo = memento->memo + index_;
+ sc_free(memo->serialized_game);
+ }
+
+ /* Reset all entries and the cursor. */
+ memset(memento->memo, 0, sizeof(memento->memo));
+ memento->memo_cursor = 0;
}
@@ -367,41 +346,39 @@ memo_clear_games (sc_memo_setref_t memento)
* used item if necessary.
*/
void
-memo_save_command (sc_memo_setref_t memento,
- const sc_char *command, sc_int timestamp, sc_int turns)
-{
- sc_historyref_t history;
- sc_int length;
- assert (memo_is_valid (memento));
-
- /* As with memos, reuse the allocation of the next slot if it has one. */
- history = memento->history
- + memento->history_count % MEMO_HISTORY_TABLE_SIZE;
-
- /*
- * Resize the allocation for this slot if required. Strings tend to be
- * short, so round up to a block to avoid too many reallocs.
- */
- length = strlen (command) + 1;
- if (history->allocation < length)
- {
- sc_int required;
-
- required = memo_round_up (length);
- history->command = (sc_char *)sc_realloc (history->command, required);
- history->allocation = required;
- }
-
- /* Save the string into this slot, and normalize it for neatness. */
- strcpy (history->command, command);
- sc_normalize_string (history->command);
- history->sequence = memento->history_count + 1;
- history->timestamp = timestamp;
- history->turns = turns;
- history->length = length;
-
- /* Increment the count of histories handled. */
- memento->history_count++;
+memo_save_command(sc_memo_setref_t memento,
+ const sc_char *command, sc_int timestamp, sc_int turns) {
+ sc_historyref_t history;
+ sc_int length;
+ assert(memo_is_valid(memento));
+
+ /* As with memos, reuse the allocation of the next slot if it has one. */
+ history = memento->history
+ + memento->history_count % MEMO_HISTORY_TABLE_SIZE;
+
+ /*
+ * Resize the allocation for this slot if required. Strings tend to be
+ * short, so round up to a block to avoid too many reallocs.
+ */
+ length = strlen(command) + 1;
+ if (history->allocation < length) {
+ sc_int required;
+
+ required = memo_round_up(length);
+ history->command = (sc_char *)sc_realloc(history->command, required);
+ history->allocation = required;
+ }
+
+ /* Save the string into this slot, and normalize it for neatness. */
+ strcpy(history->command, command);
+ sc_normalize_string(history->command);
+ history->sequence = memento->history_count + 1;
+ history->timestamp = timestamp;
+ history->turns = turns;
+ history->length = length;
+
+ /* Increment the count of histories handled. */
+ memento->history_count++;
}
@@ -414,24 +391,22 @@ memo_save_command (sc_memo_setref_t memento,
* remove it again as the main runner loop will add the real thing.
*/
void
-memo_unsave_command (sc_memo_setref_t memento)
-{
- assert (memo_is_valid (memento));
-
- /* Do nothing if for some reason there's no history to unsave. */
- if (memento->history_count > 0)
- {
- sc_historyref_t history;
-
- /* Decrement the count of histories handled, erase the prior entry. */
- memento->history_count--;
- history = memento->history
- + memento->history_count % MEMO_HISTORY_TABLE_SIZE;
- history->sequence = 0;
- history->timestamp = 0;
- history->turns = 0;
- history->length = 0;
- }
+memo_unsave_command(sc_memo_setref_t memento) {
+ assert(memo_is_valid(memento));
+
+ /* Do nothing if for some reason there's no history to unsave. */
+ if (memento->history_count > 0) {
+ sc_historyref_t history;
+
+ /* Decrement the count of histories handled, erase the prior entry. */
+ memento->history_count--;
+ history = memento->history
+ + memento->history_count % MEMO_HISTORY_TABLE_SIZE;
+ history->sequence = 0;
+ history->timestamp = 0;
+ history->turns = 0;
+ history->length = 0;
+ }
}
@@ -441,15 +416,14 @@ memo_unsave_command (sc_memo_setref_t memento)
* Return a count of available saved commands.
*/
sc_int
-memo_get_command_count (sc_memo_setref_t memento)
-{
- assert (memo_is_valid (memento));
-
- /* Return the lesser of the history count and the history table size. */
- if (memento->history_count < MEMO_HISTORY_TABLE_SIZE)
- return memento->history_count;
- else
- return MEMO_HISTORY_TABLE_SIZE;
+memo_get_command_count(sc_memo_setref_t memento) {
+ assert(memo_is_valid(memento));
+
+ /* Return the lesser of the history count and the history table size. */
+ if (memento->history_count < MEMO_HISTORY_TABLE_SIZE)
+ return memento->history_count;
+ else
+ return MEMO_HISTORY_TABLE_SIZE;
}
@@ -459,23 +433,22 @@ memo_get_command_count (sc_memo_setref_t memento)
* Iterator rewind function, reset current location to the first command.
*/
void
-memo_first_command (sc_memo_setref_t memento)
-{
- sc_int cursor;
- sc_historyref_t history;
- assert (memo_is_valid (memento));
-
- /*
- * If the buffer has cycled, we have the full complement of saved commands,
- * so start iterating at the current cursor. Otherwise, start from index 0.
- * Detect cycling by looking at the current slot; if it's filled, we've
- * been here before. Set at_start flag to indicate the special case for
- * circular buffers.
- */
- cursor = memento->history_count % MEMO_HISTORY_TABLE_SIZE;
- history = memento->history + cursor;
- memento->current_history = (history->length > 0) ? cursor : 0;
- memento->is_at_start = TRUE;
+memo_first_command(sc_memo_setref_t memento) {
+ sc_int cursor;
+ sc_historyref_t history;
+ assert(memo_is_valid(memento));
+
+ /*
+ * If the buffer has cycled, we have the full complement of saved commands,
+ * so start iterating at the current cursor. Otherwise, start from index 0.
+ * Detect cycling by looking at the current slot; if it's filled, we've
+ * been here before. Set at_start flag to indicate the special case for
+ * circular buffers.
+ */
+ cursor = memento->history_count % MEMO_HISTORY_TABLE_SIZE;
+ history = memento->history + cursor;
+ memento->current_history = (history->length > 0) ? cursor : 0;
+ memento->is_at_start = TRUE;
}
@@ -486,37 +459,33 @@ memo_first_command (sc_memo_setref_t memento)
* starting at 1, and the timestamp and turns when the command was saved.
*/
void
-memo_next_command (sc_memo_setref_t memento,
- const sc_char **command, sc_int *sequence,
- sc_int *timestamp, sc_int *turns)
-{
- assert (memo_is_valid (memento));
-
- /* If valid, return the current command and advance. */
- if (memo_more_commands (memento))
- {
- sc_historyref_t history;
-
- /* Note the current history, and advance its index. */
- history = memento->history + memento->current_history;
- memento->current_history++;
- memento->current_history %= MEMO_HISTORY_TABLE_SIZE;
- memento->is_at_start = FALSE;
-
- /* Return details from the history noted above. */
- *command = history->command;
- *sequence = history->sequence;
- *timestamp = history->timestamp;
- *turns = history->turns;
- }
- else
- {
- /* Return NULL and zeroes if no more commands available. */
- *command = NULL;
- *sequence = 0;
- *timestamp = 0;
- *turns = 0;
- }
+memo_next_command(sc_memo_setref_t memento,
+ const sc_char **command, sc_int *sequence,
+ sc_int *timestamp, sc_int *turns) {
+ assert(memo_is_valid(memento));
+
+ /* If valid, return the current command and advance. */
+ if (memo_more_commands(memento)) {
+ sc_historyref_t history;
+
+ /* Note the current history, and advance its index. */
+ history = memento->history + memento->current_history;
+ memento->current_history++;
+ memento->current_history %= MEMO_HISTORY_TABLE_SIZE;
+ memento->is_at_start = FALSE;
+
+ /* Return details from the history noted above. */
+ *command = history->command;
+ *sequence = history->sequence;
+ *timestamp = history->timestamp;
+ *turns = history->turns;
+ } else {
+ /* Return NULL and zeroes if no more commands available. */
+ *command = NULL;
+ *sequence = 0;
+ *timestamp = 0;
+ *turns = 0;
+ }
}
@@ -526,25 +495,24 @@ memo_next_command (sc_memo_setref_t memento,
* Iterator end function, returns TRUE if more commands are readable.
*/
sc_bool
-memo_more_commands (sc_memo_setref_t memento)
-{
- sc_int cursor;
- sc_historyref_t history;
- assert (memo_is_valid (memento));
-
- /* Get the current effective write position, and the current history. */
- cursor = memento->history_count % MEMO_HISTORY_TABLE_SIZE;
- history = memento->history + memento->current_history;
-
- /*
- * More data if the current history is behind the write position and is
- * occupied, or if it matches and is occupied and we're at the start of
- * iteration (circular buffer special case).
- */
- if (memento->current_history == cursor)
- return (memento->is_at_start) ? history->length > 0 : FALSE;
- else
- return history->length > 0;
+memo_more_commands(sc_memo_setref_t memento) {
+ sc_int cursor;
+ sc_historyref_t history;
+ assert(memo_is_valid(memento));
+
+ /* Get the current effective write position, and the current history. */
+ cursor = memento->history_count % MEMO_HISTORY_TABLE_SIZE;
+ history = memento->history + memento->current_history;
+
+ /*
+ * More data if the current history is behind the write position and is
+ * occupied, or if it matches and is occupied and we're at the start of
+ * iteration (circular buffer special case).
+ */
+ if (memento->current_history == cursor)
+ return (memento->is_at_start) ? history->length > 0 : FALSE;
+ else
+ return history->length > 0;
}
@@ -555,39 +523,36 @@ memo_more_commands (sc_memo_setref_t memento)
* indicates an offset from the last defined), or NULL if not found.
*/
const sc_char *
-memo_find_command (sc_memo_setref_t memento, sc_int sequence)
-{
- sc_int target, index_;
- sc_historyref_t matched;
- assert (memo_is_valid (memento));
-
- /* Decide on a search target, depending on the sign of sequence. */
- target = (sequence < 0) ? memento->history_count + sequence + 1: sequence;
-
- /*
- * A backwards search starting at the write position would probably be more
- * efficient here, but this is a rarely called function so we'll do it the
- * simpler way.
- */
- matched = NULL;
- for (index_ = 0; index_ < MEMO_HISTORY_TABLE_SIZE; index_++)
- {
- sc_historyref_t history;
-
- history = memento->history + index_;
- if (history->sequence == target)
- {
- matched = history;
- break;
- }
- }
-
- /*
- * Return the command or NULL. If sequence passed in was zero, and the
- * history was not full, this will still return NULL as it should, since
- * this unused history's command found by the search above will be NULL.
- */
- return matched ? matched->command : NULL;
+memo_find_command(sc_memo_setref_t memento, sc_int sequence) {
+ sc_int target, index_;
+ sc_historyref_t matched;
+ assert(memo_is_valid(memento));
+
+ /* Decide on a search target, depending on the sign of sequence. */
+ target = (sequence < 0) ? memento->history_count + sequence + 1 : sequence;
+
+ /*
+ * A backwards search starting at the write position would probably be more
+ * efficient here, but this is a rarely called function so we'll do it the
+ * simpler way.
+ */
+ matched = NULL;
+ for (index_ = 0; index_ < MEMO_HISTORY_TABLE_SIZE; index_++) {
+ sc_historyref_t history;
+
+ history = memento->history + index_;
+ if (history->sequence == target) {
+ matched = history;
+ break;
+ }
+ }
+
+ /*
+ * Return the command or NULL. If sequence passed in was zero, and the
+ * history was not full, this will still return NULL as it should, since
+ * this unused history's command found by the search above will be NULL.
+ */
+ return matched ? matched->command : NULL;
}
@@ -597,25 +562,23 @@ memo_find_command (sc_memo_setref_t memento, sc_int sequence)
* Forget all saved commands.
*/
void
-memo_clear_commands (sc_memo_setref_t memento)
-{
- sc_int index_;
- assert (memo_is_valid (memento));
-
- /* Deallocate every entry. */
- for (index_ = 0; index_ < MEMO_HISTORY_TABLE_SIZE; index_++)
- {
- sc_historyref_t history;
-
- history = memento->history + index_;
- sc_free (history->command);
- }
-
- /* Reset all entries, the count, and the iteration variables. */
- memset (memento->history, 0, sizeof (memento->history));
- memento->history_count = 0;
- memento->current_history = 0;
- memento->is_at_start = FALSE;
+memo_clear_commands(sc_memo_setref_t memento) {
+ sc_int index_;
+ assert(memo_is_valid(memento));
+
+ /* Deallocate every entry. */
+ for (index_ = 0; index_ < MEMO_HISTORY_TABLE_SIZE; index_++) {
+ sc_historyref_t history;
+
+ history = memento->history + index_;
+ sc_free(history->command);
+ }
+
+ /* Reset all entries, the count, and the iteration variables. */
+ memset(memento->history, 0, sizeof(memento->history));
+ memento->history_count = 0;
+ memento->current_history = 0;
+ memento->is_at_start = FALSE;
}
} // End of namespace Adrift
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
diff --git a/engines/glk/adrift/scobjcts.cpp b/engines/glk/adrift/scobjcts.cpp
index 9bef9952e3..28a89abed3 100644
--- a/engines/glk/adrift/scobjcts.cpp
+++ b/engines/glk/adrift/scobjcts.cpp
@@ -42,45 +42,42 @@ static sc_bool obj_trace = FALSE;
* Convenience functions to return TRUE for given object attributes.
*/
sc_bool
-obj_is_static (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_bool bstatic;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Static";
- bstatic = prop_get_boolean (bundle, "B<-sis", vt_key);
- return bstatic;
+obj_is_static(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_bool bstatic;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Static";
+ bstatic = prop_get_boolean(bundle, "B<-sis", vt_key);
+ return bstatic;
}
sc_bool
-obj_is_container (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_bool is_container;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Container";
- is_container = prop_get_boolean (bundle, "B<-sis", vt_key);
- return is_container;
+obj_is_container(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_bool is_container;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Container";
+ is_container = prop_get_boolean(bundle, "B<-sis", vt_key);
+ return is_container;
}
sc_bool
-obj_is_surface (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_bool is_surface;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Surface";
- is_surface = prop_get_boolean (bundle, "B<-sis", vt_key);
- return is_surface;
+obj_is_surface(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_bool is_surface;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Surface";
+ is_surface = prop_get_boolean(bundle, "B<-sis", vt_key);
+ return is_surface;
}
@@ -90,18 +87,16 @@ obj_is_surface (sc_gameref_t game, sc_int object)
* Return the index of the n'th container object found.
*/
sc_int
-obj_container_object (sc_gameref_t game, sc_int n)
-{
- sc_int object, count;
-
- /* Progress through objects until n containers found. */
- count = n;
- for (object = 0; object < gs_object_count (game) && count >= 0; object++)
- {
- if (obj_is_container (game, object))
- count--;
- }
- return object - 1;
+obj_container_object(sc_gameref_t game, sc_int n) {
+ sc_int object, count;
+
+ /* Progress through objects until n containers found. */
+ count = n;
+ for (object = 0; object < gs_object_count(game) && count >= 0; object++) {
+ if (obj_is_container(game, object))
+ count--;
+ }
+ return object - 1;
}
@@ -111,18 +106,16 @@ obj_container_object (sc_gameref_t game, sc_int n)
* Return index such that obj_container_object(index) == objnum.
*/
sc_int
-obj_container_index (sc_gameref_t game, sc_int objnum)
-{
- sc_int object, count;
-
- /* Progress through objects up to objnum. */
- count = 0;
- for (object = 0; object < objnum; object++)
- {
- if (obj_is_container (game, object))
- count++;
- }
- return count;
+obj_container_index(sc_gameref_t game, sc_int objnum) {
+ sc_int object, count;
+
+ /* Progress through objects up to objnum. */
+ count = 0;
+ for (object = 0; object < objnum; object++) {
+ if (obj_is_container(game, object))
+ count++;
+ }
+ return count;
}
@@ -132,18 +125,16 @@ obj_container_index (sc_gameref_t game, sc_int objnum)
* Return the index of the n'th surface object found.
*/
sc_int
-obj_surface_object (sc_gameref_t game, sc_int n)
-{
- sc_int object, count;
-
- /* Progress through objects until n surfaces found. */
- count = n;
- for (object = 0; object < gs_object_count (game) && count >= 0; object++)
- {
- if (obj_is_surface (game, object))
- count--;
- }
- return object - 1;
+obj_surface_object(sc_gameref_t game, sc_int n) {
+ sc_int object, count;
+
+ /* Progress through objects until n surfaces found. */
+ count = n;
+ for (object = 0; object < gs_object_count(game) && count >= 0; object++) {
+ if (obj_is_surface(game, object))
+ count--;
+ }
+ return object - 1;
}
@@ -153,18 +144,16 @@ obj_surface_object (sc_gameref_t game, sc_int n)
* Return index such that obj_surface_object(index) == objnum.
*/
sc_int
-obj_surface_index (sc_gameref_t game, sc_int objnum)
-{
- sc_int object, count;
-
- /* Progress through objects up to objnum. */
- count = 0;
- for (object = 0; object < objnum; object++)
- {
- if (obj_is_surface (game, object))
- count++;
- }
- return count;
+obj_surface_index(sc_gameref_t game, sc_int objnum) {
+ sc_int object, count;
+
+ /* Progress through objects up to objnum. */
+ count = 0;
+ for (object = 0; object < objnum; object++) {
+ if (obj_is_surface(game, object))
+ count++;
+ }
+ return count;
}
@@ -174,28 +163,26 @@ obj_surface_index (sc_gameref_t game, sc_int objnum)
* Return the index of the n'th openable or statussed object found.
*/
sc_int
-obj_stateful_object (sc_gameref_t game, sc_int n)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, count;
-
- /* Progress through objects until n matches found. */
- count = n;
- for (object = 0; object < gs_object_count (game) && count >= 0; object++)
- {
- sc_vartype_t vt_key[3];
- sc_bool is_openable, is_statussed;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Openable";
- is_openable = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- vt_key[2].string = "CurrentState";
- is_statussed = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- if (is_openable || is_statussed)
- count--;
- }
- return object - 1;
+obj_stateful_object(sc_gameref_t game, sc_int n) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, count;
+
+ /* Progress through objects until n matches found. */
+ count = n;
+ for (object = 0; object < gs_object_count(game) && count >= 0; object++) {
+ sc_vartype_t vt_key[3];
+ sc_bool is_openable, is_statussed;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Openable";
+ is_openable = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ vt_key[2].string = "CurrentState";
+ is_statussed = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ if (is_openable || is_statussed)
+ count--;
+ }
+ return object - 1;
}
@@ -205,28 +192,26 @@ obj_stateful_object (sc_gameref_t game, sc_int n)
* Return index such that obj_stateful_object(index) == objnum.
*/
sc_int
-obj_stateful_index (sc_gameref_t game, sc_int objnum)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, count;
-
- /* Progress through objects up to objnum. */
- count = 0;
- for (object = 0; object < objnum; object++)
- {
- sc_vartype_t vt_key[3];
- sc_bool is_openable, is_statussed;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Openable";
- is_openable = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- vt_key[2].string = "CurrentState";
- is_statussed = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- if (is_openable || is_statussed)
- count++;
- }
- return count;
+obj_stateful_index(sc_gameref_t game, sc_int objnum) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, count;
+
+ /* Progress through objects up to objnum. */
+ count = 0;
+ for (object = 0; object < objnum; object++) {
+ sc_vartype_t vt_key[3];
+ sc_bool is_openable, is_statussed;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Openable";
+ is_openable = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ vt_key[2].string = "CurrentState";
+ is_statussed = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ if (is_openable || is_statussed)
+ count++;
+ }
+ return count;
}
@@ -238,44 +223,41 @@ obj_stateful_index (sc_gameref_t game, sc_int objnum)
* if no valid state string found.
*/
sc_char *
-obj_state_name (sc_gameref_t game, sc_int objnum)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *states;
- sc_int length, state, count, first, last;
- sc_char *string;
-
- /* Get the list of state strings for the object. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = objnum;
- vt_key[2].string = "States";
- states = prop_get_string (bundle, "S<-sis", vt_key);
-
- /* Find the start of the element for the current state. */
- state = gs_object_state (game, objnum);
- length = strlen (states);
- for (first = 0, count = state; first < length && count > 1; first++)
- {
- if (states[first] == '|')
- count--;
- }
- if (count != 1)
- return NULL;
-
- /* Find the end of the state string. */
- for (last = first; last < length; last++)
- {
- if (states[last] == '|')
- break;
- }
-
- /* Allocate and take a copy of the state string. */
- string = (sc_char *)sc_malloc (last - first + 1);
- memcpy (string, states + first, last - first);
- string[last - first] = NUL;
-
- return string;
+obj_state_name(sc_gameref_t game, sc_int objnum) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *states;
+ sc_int length, state, count, first, last;
+ sc_char *string;
+
+ /* Get the list of state strings for the object. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = objnum;
+ vt_key[2].string = "States";
+ states = prop_get_string(bundle, "S<-sis", vt_key);
+
+ /* Find the start of the element for the current state. */
+ state = gs_object_state(game, objnum);
+ length = strlen(states);
+ for (first = 0, count = state; first < length && count > 1; first++) {
+ if (states[first] == '|')
+ count--;
+ }
+ if (count != 1)
+ return NULL;
+
+ /* Find the end of the state string. */
+ for (last = first; last < length; last++) {
+ if (states[last] == '|')
+ break;
+ }
+
+ /* Allocate and take a copy of the state string. */
+ string = (sc_char *)sc_malloc(last - first + 1);
+ memcpy(string, states + first, last - first);
+ string[last - first] = NUL;
+
+ return string;
}
@@ -285,18 +267,16 @@ obj_state_name (sc_gameref_t game, sc_int objnum)
* Return the index of the n'th non-static object found.
*/
sc_int
-obj_dynamic_object (sc_gameref_t game, sc_int n)
-{
- sc_int object, count;
-
- /* Progress through objects until n matches found. */
- count = n;
- for (object = 0; object < gs_object_count (game) && count >= 0; object++)
- {
- if (!obj_is_static (game, object))
- count--;
- }
- return object - 1;
+obj_dynamic_object(sc_gameref_t game, sc_int n) {
+ sc_int object, count;
+
+ /* Progress through objects until n matches found. */
+ count = n;
+ for (object = 0; object < gs_object_count(game) && count >= 0; object++) {
+ if (!obj_is_static(game, object))
+ count--;
+ }
+ return object - 1;
}
@@ -306,27 +286,24 @@ obj_dynamic_object (sc_gameref_t game, sc_int n)
* Return the index of the n'th wearable object found.
*/
sc_int
-obj_wearable_object (sc_gameref_t game, sc_int n)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, count;
-
- /* Progress through objects until n matches found. */
- count = n;
- for (object = 0; object < gs_object_count (game) && count >= 0; object++)
- {
- if (!obj_is_static (game, object))
- {
- sc_vartype_t vt_key[3];
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Wearable";
- if (prop_get_boolean (bundle, "B<-sis", vt_key))
- count--;
- }
- }
- return object - 1;
+obj_wearable_object(sc_gameref_t game, sc_int n) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, count;
+
+ /* Progress through objects until n matches found. */
+ count = n;
+ for (object = 0; object < gs_object_count(game) && count >= 0; object++) {
+ if (!obj_is_static(game, object)) {
+ sc_vartype_t vt_key[3];
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Wearable";
+ if (prop_get_boolean(bundle, "B<-sis", vt_key))
+ count--;
+ }
+ }
+ return object - 1;
}
@@ -337,9 +314,9 @@ obj_wearable_object (sc_gameref_t game, sc_int n)
* are also used for the maximum size of object that can fit in a container,
* and the number of these that fit.
*/
-enum
-{ OBJ_DIMENSION_DIVISOR = 10,
- OBJ_DIMENSION_MULTIPLE = 3
+enum {
+ OBJ_DIMENSION_DIVISOR = 10,
+ OBJ_DIMENSION_MULTIPLE = 3
};
/*
@@ -353,83 +330,78 @@ enum
* by events -- how should these be handled, as they have no SizeWeight?
*/
sc_int
-obj_get_size (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int size, count;
-
- /* TODO For now, give static objects no size. */
- if (obj_is_static (game, object))
- return 0;
-
- /* Size is the 'tens' component of SizeWeight. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "SizeWeight";
- count = prop_get_integer (bundle, "I<-sis", vt_key) / OBJ_DIMENSION_DIVISOR;
-
- /*
- * Calculate base object size. Unlike weights below, we take this as simply
- * being the maximum size; that is, when a container carries other objects
- * its weight increases by the sum of objects carried, but its size remains
- * constant.
- */
- size = 1;
- for (; count > 0; count--)
- size *= OBJ_DIMENSION_MULTIPLE;
-
- if (obj_trace)
- sc_trace ("Object: object %ld is size %ld\n", object, size);
-
- /* Return total size. */
- return size;
+obj_get_size(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int size, count;
+
+ /* TODO For now, give static objects no size. */
+ if (obj_is_static(game, object))
+ return 0;
+
+ /* Size is the 'tens' component of SizeWeight. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "SizeWeight";
+ count = prop_get_integer(bundle, "I<-sis", vt_key) / OBJ_DIMENSION_DIVISOR;
+
+ /*
+ * Calculate base object size. Unlike weights below, we take this as simply
+ * being the maximum size; that is, when a container carries other objects
+ * its weight increases by the sum of objects carried, but its size remains
+ * constant.
+ */
+ size = 1;
+ for (; count > 0; count--)
+ size *= OBJ_DIMENSION_MULTIPLE;
+
+ if (obj_trace)
+ sc_trace("Object: object %ld is size %ld\n", object, size);
+
+ /* Return total size. */
+ return size;
}
sc_int
-obj_get_weight (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int weight, count;
-
- /* TODO For now, give static objects no weight. */
- if (obj_is_static (game, object))
- return 0;
-
- /* Weight is the 'units' component of SizeWeight. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "SizeWeight";
- count = prop_get_integer (bundle, "I<-sis", vt_key) % OBJ_DIMENSION_DIVISOR;
-
- /* Calculate base object weight. */
- weight = 1;
- for (; count > 0; count--)
- weight *= OBJ_DIMENSION_MULTIPLE;
-
- /* If this is a container or a surface, add weights of parented objects. */
- if (obj_is_container (game, object) || obj_is_surface (game, object))
- {
- sc_int other;
-
- /* Find and add contained or surface objects. */
- for (other = 0; other < gs_object_count (game); other++)
- {
- if ((gs_object_position (game, other) == OBJ_IN_OBJECT
- || gs_object_position (game, other) == OBJ_ON_OBJECT)
- && gs_object_parent (game, other) == object)
- {
- weight += obj_get_weight (game, other);
- }
- }
- }
-
- if (obj_trace)
- sc_trace ("Object: object %ld is weight %ld\n", object, weight);
-
- /* Return total weight. */
- return weight;
+obj_get_weight(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int weight, count;
+
+ /* TODO For now, give static objects no weight. */
+ if (obj_is_static(game, object))
+ return 0;
+
+ /* Weight is the 'units' component of SizeWeight. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "SizeWeight";
+ count = prop_get_integer(bundle, "I<-sis", vt_key) % OBJ_DIMENSION_DIVISOR;
+
+ /* Calculate base object weight. */
+ weight = 1;
+ for (; count > 0; count--)
+ weight *= OBJ_DIMENSION_MULTIPLE;
+
+ /* If this is a container or a surface, add weights of parented objects. */
+ if (obj_is_container(game, object) || obj_is_surface(game, object)) {
+ sc_int other;
+
+ /* Find and add contained or surface objects. */
+ for (other = 0; other < gs_object_count(game); other++) {
+ if ((gs_object_position(game, other) == OBJ_IN_OBJECT
+ || gs_object_position(game, other) == OBJ_ON_OBJECT)
+ && gs_object_parent(game, other) == object) {
+ weight += obj_get_weight(game, other);
+ }
+ }
+ }
+
+ if (obj_trace)
+ sc_trace("Object: object %ld is weight %ld\n", object, weight);
+
+ /* Return total weight. */
+ return weight;
}
@@ -442,44 +414,41 @@ obj_get_weight (sc_gameref_t game, sc_int object)
* really object-related except that they deal with sizing multiples.
*/
static sc_int
-obj_convert_player_limit (sc_int value)
-{
- sc_int retval, index_;
+obj_convert_player_limit(sc_int value) {
+ sc_int retval, index_;
- /* 'Tens' of value multiplied by 3 to the power 'units' of value. */
- retval = value / OBJ_DIMENSION_DIVISOR;
- for (index_ = 0; index_ < value % OBJ_DIMENSION_DIVISOR; index_++)
- retval *= OBJ_DIMENSION_MULTIPLE;
+ /* 'Tens' of value multiplied by 3 to the power 'units' of value. */
+ retval = value / OBJ_DIMENSION_DIVISOR;
+ for (index_ = 0; index_ < value % OBJ_DIMENSION_DIVISOR; index_++)
+ retval *= OBJ_DIMENSION_MULTIPLE;
- return retval;
+ return retval;
}
sc_int
-obj_get_player_size_limit (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_int max_size;
+obj_get_player_size_limit(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_int max_size;
- vt_key[0].string = "Globals";
- vt_key[1].string = "MaxSize";
- max_size = prop_get_integer (bundle, "I<-ss", vt_key);
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "MaxSize";
+ max_size = prop_get_integer(bundle, "I<-ss", vt_key);
- return obj_convert_player_limit (max_size);
+ return obj_convert_player_limit(max_size);
}
sc_int
-obj_get_player_weight_limit (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_int max_weight;
+obj_get_player_weight_limit(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_int max_weight;
- vt_key[0].string = "Globals";
- vt_key[1].string = "MaxWt";
- max_weight = prop_get_integer (bundle, "I<-ss", vt_key);
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "MaxWt";
+ max_weight = prop_get_integer(bundle, "I<-ss", vt_key);
- return obj_convert_player_limit (max_weight);
+ return obj_convert_player_limit(max_weight);
}
@@ -491,54 +460,52 @@ obj_get_player_weight_limit (sc_gameref_t game)
* and the number that will fit.
*/
sc_int
-obj_get_container_maxsize (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int maxsize, count;
-
- /* Maxsize is found from the 'units' component of Capacity. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Capacity";
- count = prop_get_integer (bundle, "I<-sis", vt_key) % OBJ_DIMENSION_DIVISOR;
-
- /* Calculate and return maximum size. */
- maxsize = 1;
- for (; count > 0; count--)
- maxsize *= OBJ_DIMENSION_MULTIPLE;
-
- if (obj_trace)
- sc_trace ("Object: object %ld has max size %ld\n", object, maxsize);
-
- return maxsize;
+obj_get_container_maxsize(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int maxsize, count;
+
+ /* Maxsize is found from the 'units' component of Capacity. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Capacity";
+ count = prop_get_integer(bundle, "I<-sis", vt_key) % OBJ_DIMENSION_DIVISOR;
+
+ /* Calculate and return maximum size. */
+ maxsize = 1;
+ for (; count > 0; count--)
+ maxsize *= OBJ_DIMENSION_MULTIPLE;
+
+ if (obj_trace)
+ sc_trace("Object: object %ld has max size %ld\n", object, maxsize);
+
+ return maxsize;
}
sc_int
-obj_get_container_capacity (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int capacity;
-
- /* The count of objects is in the 'tens' component of Capacity. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Capacity";
- capacity = prop_get_integer (bundle, "I<-sis", vt_key)
- / OBJ_DIMENSION_DIVISOR;
-
- if (obj_trace)
- sc_trace ("Object: object %ld has capacity %ld\n", object, capacity);
-
- return capacity;
+obj_get_container_capacity(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int capacity;
+
+ /* The count of objects is in the 'tens' component of Capacity. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Capacity";
+ capacity = prop_get_integer(bundle, "I<-sis", vt_key)
+ / OBJ_DIMENSION_DIVISOR;
+
+ if (obj_trace)
+ sc_trace("Object: object %ld has capacity %ld\n", object, capacity);
+
+ return capacity;
}
/* Sit/lie bit mask enumerations. */
-enum
-{ OBJ_STANDABLE_MASK = 1 << 0,
- OBJ_LIEABLE_MASK = 1 << 1
+enum {
+ OBJ_STANDABLE_MASK = 1 << 0,
+ OBJ_LIEABLE_MASK = 1 << 1
};
/*
@@ -547,26 +514,24 @@ enum
* Return the index of the n'th standable object found.
*/
sc_int
-obj_standable_object (sc_gameref_t game, sc_int n)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, count;
-
- /* Progress through objects until n standable found. */
- count = n;
- for (object = 0; object < gs_object_count (game) && count >= 0; object++)
- {
- sc_vartype_t vt_key[3];
- sc_int sit_lie_flags;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "SitLie";
- sit_lie_flags = prop_get_integer (bundle, "I<-sis", vt_key);
- if (sit_lie_flags & OBJ_STANDABLE_MASK)
- count--;
- }
- return object - 1;
+obj_standable_object(sc_gameref_t game, sc_int n) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, count;
+
+ /* Progress through objects until n standable found. */
+ count = n;
+ for (object = 0; object < gs_object_count(game) && count >= 0; object++) {
+ sc_vartype_t vt_key[3];
+ sc_int sit_lie_flags;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "SitLie";
+ sit_lie_flags = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (sit_lie_flags & OBJ_STANDABLE_MASK)
+ count--;
+ }
+ return object - 1;
}
@@ -576,26 +541,24 @@ obj_standable_object (sc_gameref_t game, sc_int n)
* Return the index of the n'th lieable object found.
*/
sc_int
-obj_lieable_object (sc_gameref_t game, sc_int n)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int object, count;
-
- /* Progress through objects until n lieable found. */
- count = n;
- for (object = 0; object < gs_object_count (game) && count >= 0; object++)
- {
- sc_vartype_t vt_key[3];
- sc_int sit_lie_flags;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "SitLie";
- sit_lie_flags = prop_get_integer (bundle, "I<-sis", vt_key);
- if (sit_lie_flags & OBJ_LIEABLE_MASK)
- count--;
- }
- return object - 1;
+obj_lieable_object(sc_gameref_t game, sc_int n) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int object, count;
+
+ /* Progress through objects until n lieable found. */
+ count = n;
+ for (object = 0; object < gs_object_count(game) && count >= 0; object++) {
+ sc_vartype_t vt_key[3];
+ sc_int sit_lie_flags;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "SitLie";
+ sit_lie_flags = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (sit_lie_flags & OBJ_LIEABLE_MASK)
+ count--;
+ }
+ return object - 1;
}
@@ -609,37 +572,35 @@ obj_lieable_object (sc_gameref_t game, sc_int n)
* that is not preceded by 'u'.
*/
sc_bool
-obj_appears_plural (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *prefix, *name;
-
- /* Check prefix for "a", "an", or empty. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
-
- if (!(sc_strempty (prefix)
- || sc_compare_word (prefix, "a", 1)
- || sc_compare_word (prefix, "an", 2)))
- {
- sc_int length;
-
- /* Check name for ending in 's', but not 'us'. */
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- length = strlen (name);
-
- if (!sc_strempty (name)
- && sc_tolower (name[length - 1]) == 's'
- && (length < 2 || sc_tolower (name[length - 2]) != 'u'))
- return TRUE;
- }
-
- /* Doesn't look plural. */
- return FALSE;
+obj_appears_plural(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *prefix, *name;
+
+ /* Check prefix for "a", "an", or empty. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+
+ if (!(sc_strempty(prefix)
+ || sc_compare_word(prefix, "a", 1)
+ || sc_compare_word(prefix, "an", 2))) {
+ sc_int length;
+
+ /* Check name for ending in 's', but not 'us'. */
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ length = strlen(name);
+
+ if (!sc_strempty(name)
+ && sc_tolower(name[length - 1]) == 's'
+ && (length < 2 || sc_tolower(name[length - 2]) != 'u'))
+ return TRUE;
+ }
+
+ /* Doesn't look plural. */
+ return FALSE;
}
@@ -650,73 +611,66 @@ obj_appears_plural (sc_gameref_t game, sc_int object)
* Return TRUE if a given object is currently on the floor of a given room.
*/
static sc_bool
-obj_directly_in_room_internal (sc_gameref_t game, sc_int object, sc_int room)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
-
- /* See if the object is static or dynamic. */
- if (obj_is_static (game, object))
- {
- sc_vartype_t vt_key[5];
- sc_int type;
-
- /* Static object moved to player or room by event? */
- if (!gs_object_static_unmoved (game, object))
- {
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER)
- return FALSE;
- else
- return gs_object_position (game, object) - 1 == room;
- }
-
- /* Check and return the room list for the object. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Where";
- vt_key[3].string = "Type";
- type = prop_get_integer (bundle, "I<-siss", vt_key);
- switch (type)
- {
- case ROOMLIST_ALL_ROOMS:
- return TRUE;
- case ROOMLIST_NO_ROOMS:
- case ROOMLIST_NPC_PART:
- return FALSE;
-
- case ROOMLIST_ONE_ROOM:
- vt_key[3].string = "Room";
- return prop_get_integer (bundle, "I<-siss", vt_key) == room + 1;
-
- case ROOMLIST_SOME_ROOMS:
- vt_key[3].string = "Rooms";
- vt_key[4].integer = room + 1;
- return prop_get_boolean (bundle, "B<-sissi", vt_key);
-
- default:
- sc_fatal ("obj_directly_in_room_internal:"
- " invalid type, %ld\n", type);
- return FALSE;
- }
- }
- else
- return gs_object_position (game, object) == room + 1;
+obj_directly_in_room_internal(sc_gameref_t game, sc_int object, sc_int room) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+
+ /* See if the object is static or dynamic. */
+ if (obj_is_static(game, object)) {
+ sc_vartype_t vt_key[5];
+ sc_int type;
+
+ /* Static object moved to player or room by event? */
+ if (!gs_object_static_unmoved(game, object)) {
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER)
+ return FALSE;
+ else
+ return gs_object_position(game, object) - 1 == room;
+ }
+
+ /* Check and return the room list for the object. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Where";
+ vt_key[3].string = "Type";
+ type = prop_get_integer(bundle, "I<-siss", vt_key);
+ switch (type) {
+ case ROOMLIST_ALL_ROOMS:
+ return TRUE;
+ case ROOMLIST_NO_ROOMS:
+ case ROOMLIST_NPC_PART:
+ return FALSE;
+
+ case ROOMLIST_ONE_ROOM:
+ vt_key[3].string = "Room";
+ return prop_get_integer(bundle, "I<-siss", vt_key) == room + 1;
+
+ case ROOMLIST_SOME_ROOMS:
+ vt_key[3].string = "Rooms";
+ vt_key[4].integer = room + 1;
+ return prop_get_boolean(bundle, "B<-sissi", vt_key);
+
+ default:
+ sc_fatal("obj_directly_in_room_internal:"
+ " invalid type, %ld\n", type);
+ return FALSE;
+ }
+ } else
+ return gs_object_position(game, object) == room + 1;
}
sc_bool
-obj_directly_in_room (sc_gameref_t game, sc_int object, sc_int room)
-{
- sc_bool result;
+obj_directly_in_room(sc_gameref_t game, sc_int object, sc_int room) {
+ sc_bool result;
- /* Check, trace result, and return. */
- result = obj_directly_in_room_internal (game, object, room);
+ /* Check, trace result, and return. */
+ result = obj_directly_in_room_internal(game, object, room);
- if (obj_trace)
- {
- sc_trace ("Object: checking for object %ld directly in room %ld, %s\n",
- object, room, result ? "true" : "false");
- }
+ if (obj_trace) {
+ sc_trace("Object: checking for object %ld directly in room %ld, %s\n",
+ object, room, result ? "true" : "false");
+ }
- return result;
+ return result;
}
@@ -729,132 +683,119 @@ obj_directly_in_room (sc_gameref_t game, sc_int object, sc_int room)
* carried by an NPC in the room.
*/
static sc_bool
-obj_indirectly_in_room_internal (sc_gameref_t game, sc_int object, sc_int room)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
-
- /* See if the object is static or dynamic. */
- if (obj_is_static (game, object))
- {
- sc_vartype_t vt_key[5];
- sc_int type;
-
- /* Static object moved to player or room by event? */
- if (!gs_object_static_unmoved (game, object))
- {
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER)
- return gs_player_in_room (game, room);
- else
- return gs_object_position (game, object) - 1 == room;
- }
-
- /* Check and return the room list for the object. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Where";
- vt_key[3].string = "Type";
- type = prop_get_integer (bundle, "I<-siss", vt_key);
- switch (type)
- {
- case ROOMLIST_ALL_ROOMS:
- return TRUE;
- case ROOMLIST_NO_ROOMS:
- return FALSE;
-
- case ROOMLIST_ONE_ROOM:
- vt_key[3].string = "Room";
- return prop_get_integer (bundle, "I<-siss", vt_key) == room + 1;
-
- case ROOMLIST_SOME_ROOMS:
- vt_key[3].string = "Rooms";
- vt_key[4].integer = room + 1;
- return prop_get_boolean (bundle, "B<-sissi", vt_key);
-
- case ROOMLIST_NPC_PART:
- {
- sc_int npc;
-
- vt_key[2].string = "Parent";
- npc = prop_get_integer (bundle, "I<-sis", vt_key);
- if (npc == 0)
- return gs_player_in_room (game, room);
- else
- return npc_in_room (game, npc - 1, room);
- }
-
- default:
- sc_fatal ("obj_indirectly_in_room_internal:"
- " invalid type, %ld\n", type);
- return FALSE;
- }
- }
- else
- {
- sc_int parent, position;
-
- /* Get dynamic object's parent and position. */
- parent = gs_object_parent (game, object);
- position = gs_object_position (game, object);
-
- /* Decide depending on positioning. */
- switch (position)
- {
- case OBJ_HIDDEN: /* Hidden. */
- return FALSE;
-
- case OBJ_HELD_PLAYER: /* Held by player. */
- case OBJ_WORN_PLAYER: /* Worn by player. */
- return gs_player_in_room (game, room);
-
- case OBJ_HELD_NPC: /* Held by NPC. */
- case OBJ_WORN_NPC: /* Worn by NPC. */
- return npc_in_room (game, parent, room);
-
- case OBJ_IN_OBJECT: /* In another object. */
- {
- sc_int openness;
-
- openness = gs_object_openness (game, parent);
- switch (openness)
- {
- case OBJ_WONTCLOSE:
- case OBJ_OPEN:
- return obj_indirectly_in_room (game, parent, room);
- default:
- return FALSE;
- }
- }
-
- case OBJ_ON_OBJECT: /* On another object. */
- return obj_indirectly_in_room (game, parent, room);
-
- default: /* Within a room. */
- if (position > gs_room_count (game) + 1)
- {
- sc_error ("sc_object_indirectly_in_room:"
- " position out of bounds, %ld\n", position);
- }
- return position - 1 == room;
- }
- }
+obj_indirectly_in_room_internal(sc_gameref_t game, sc_int object, sc_int room) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+
+ /* See if the object is static or dynamic. */
+ if (obj_is_static(game, object)) {
+ sc_vartype_t vt_key[5];
+ sc_int type;
+
+ /* Static object moved to player or room by event? */
+ if (!gs_object_static_unmoved(game, object)) {
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER)
+ return gs_player_in_room(game, room);
+ else
+ return gs_object_position(game, object) - 1 == room;
+ }
+
+ /* Check and return the room list for the object. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Where";
+ vt_key[3].string = "Type";
+ type = prop_get_integer(bundle, "I<-siss", vt_key);
+ switch (type) {
+ case ROOMLIST_ALL_ROOMS:
+ return TRUE;
+ case ROOMLIST_NO_ROOMS:
+ return FALSE;
+
+ case ROOMLIST_ONE_ROOM:
+ vt_key[3].string = "Room";
+ return prop_get_integer(bundle, "I<-siss", vt_key) == room + 1;
+
+ case ROOMLIST_SOME_ROOMS:
+ vt_key[3].string = "Rooms";
+ vt_key[4].integer = room + 1;
+ return prop_get_boolean(bundle, "B<-sissi", vt_key);
+
+ case ROOMLIST_NPC_PART: {
+ sc_int npc;
+
+ vt_key[2].string = "Parent";
+ npc = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (npc == 0)
+ return gs_player_in_room(game, room);
+ else
+ return npc_in_room(game, npc - 1, room);
+ }
+
+ default:
+ sc_fatal("obj_indirectly_in_room_internal:"
+ " invalid type, %ld\n", type);
+ return FALSE;
+ }
+ } else {
+ sc_int parent, position;
+
+ /* Get dynamic object's parent and position. */
+ parent = gs_object_parent(game, object);
+ position = gs_object_position(game, object);
+
+ /* Decide depending on positioning. */
+ switch (position) {
+ case OBJ_HIDDEN: /* Hidden. */
+ return FALSE;
+
+ case OBJ_HELD_PLAYER: /* Held by player. */
+ case OBJ_WORN_PLAYER: /* Worn by player. */
+ return gs_player_in_room(game, room);
+
+ case OBJ_HELD_NPC: /* Held by NPC. */
+ case OBJ_WORN_NPC: /* Worn by NPC. */
+ return npc_in_room(game, parent, room);
+
+ case OBJ_IN_OBJECT: { /* In another object. */
+ sc_int openness;
+
+ openness = gs_object_openness(game, parent);
+ switch (openness) {
+ case OBJ_WONTCLOSE:
+ case OBJ_OPEN:
+ return obj_indirectly_in_room(game, parent, room);
+ default:
+ return FALSE;
+ }
+ }
+
+ case OBJ_ON_OBJECT: /* On another object. */
+ return obj_indirectly_in_room(game, parent, room);
+
+ default: /* Within a room. */
+ if (position > gs_room_count(game) + 1) {
+ sc_error("sc_object_indirectly_in_room:"
+ " position out of bounds, %ld\n", position);
+ }
+ return position - 1 == room;
+ }
+ }
}
sc_bool
-obj_indirectly_in_room (sc_gameref_t game,
- sc_int object, sc_int room)
-{
- sc_bool result;
+obj_indirectly_in_room(sc_gameref_t game,
+ sc_int object, sc_int room) {
+ sc_bool result;
- /* Check, trace result, and return. */
- result = obj_indirectly_in_room_internal (game, object, room);
+ /* Check, trace result, and return. */
+ result = obj_indirectly_in_room_internal(game, object, room);
- if (obj_trace)
- {
- sc_trace ("Object: checking for object %ld indirectly in room %ld, %s\n",
- object, room, result ? "true" : "false");
- }
+ if (obj_trace) {
+ sc_trace("Object: checking for object %ld indirectly in room %ld, %s\n",
+ object, room, result ? "true" : "false");
+ }
- return result;
+ return result;
}
@@ -866,85 +807,75 @@ obj_indirectly_in_room (sc_gameref_t game,
* directly, on an object indirectly, or in an open object indirectly.
*/
static sc_bool
-obj_indirectly_held_by_player_internal (sc_gameref_t game,
- sc_int object)
-{
- /* See if the object is static or dynamic. */
- if (obj_is_static (game, object))
- {
- /* Static object moved to player or room by event? */
- if (!gs_object_static_unmoved (game, object))
- {
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER)
- return TRUE;
- else
- return FALSE;
- }
-
- /* An unmoved static object is not held by the player. */
- return FALSE;
- }
- else
- {
- sc_int parent, position;
-
- /* Get dynamic object's parent and position. */
- parent = gs_object_parent (game, object);
- position = gs_object_position (game, object);
-
- /* Decide depending on positioning. */
- switch (position)
- {
- case OBJ_HIDDEN: /* Hidden. */
- return FALSE;
-
- case OBJ_HELD_PLAYER: /* Held by player. */
- case OBJ_WORN_PLAYER: /* Worn by player. */
- return TRUE;
-
- case OBJ_HELD_NPC: /* Held by NPC. */
- case OBJ_WORN_NPC: /* Worn by NPC. */
- return FALSE;
-
- case OBJ_IN_OBJECT: /* In another object. */
- {
- sc_int openness;
-
- openness = gs_object_openness (game, parent);
- switch (openness)
- {
- case OBJ_WONTCLOSE:
- case OBJ_OPEN:
- return obj_indirectly_held_by_player (game, parent);
- default:
- return FALSE;
- }
- }
-
- case OBJ_ON_OBJECT: /* On another object. */
- return obj_indirectly_held_by_player (game, parent);
-
- default: /* Within a room. */
- return FALSE;
- }
- }
+obj_indirectly_held_by_player_internal(sc_gameref_t game,
+ sc_int object) {
+ /* See if the object is static or dynamic. */
+ if (obj_is_static(game, object)) {
+ /* Static object moved to player or room by event? */
+ if (!gs_object_static_unmoved(game, object)) {
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER)
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ /* An unmoved static object is not held by the player. */
+ return FALSE;
+ } else {
+ sc_int parent, position;
+
+ /* Get dynamic object's parent and position. */
+ parent = gs_object_parent(game, object);
+ position = gs_object_position(game, object);
+
+ /* Decide depending on positioning. */
+ switch (position) {
+ case OBJ_HIDDEN: /* Hidden. */
+ return FALSE;
+
+ case OBJ_HELD_PLAYER: /* Held by player. */
+ case OBJ_WORN_PLAYER: /* Worn by player. */
+ return TRUE;
+
+ case OBJ_HELD_NPC: /* Held by NPC. */
+ case OBJ_WORN_NPC: /* Worn by NPC. */
+ return FALSE;
+
+ case OBJ_IN_OBJECT: { /* In another object. */
+ sc_int openness;
+
+ openness = gs_object_openness(game, parent);
+ switch (openness) {
+ case OBJ_WONTCLOSE:
+ case OBJ_OPEN:
+ return obj_indirectly_held_by_player(game, parent);
+ default:
+ return FALSE;
+ }
+ }
+
+ case OBJ_ON_OBJECT: /* On another object. */
+ return obj_indirectly_held_by_player(game, parent);
+
+ default: /* Within a room. */
+ return FALSE;
+ }
+ }
}
sc_bool
-obj_indirectly_held_by_player (sc_gameref_t game, sc_int object)
-{
- sc_bool result;
+obj_indirectly_held_by_player(sc_gameref_t game, sc_int object) {
+ sc_bool result;
- /* Check, trace result, and return. */
- result = obj_indirectly_held_by_player_internal (game, object);
+ /* Check, trace result, and return. */
+ result = obj_indirectly_held_by_player_internal(game, object);
- if (obj_trace)
- {
- sc_trace ("Object: checking for object %ld indirectly"
- " held by player, %s\n", object, result ? "true" : "false");
- }
+ if (obj_trace) {
+ sc_trace("Object: checking for object %ld indirectly"
+ " held by player, %s\n", object, result ? "true" : "false");
+ }
- return result;
+ return result;
}
@@ -954,42 +885,39 @@ obj_indirectly_held_by_player (sc_gameref_t game, sc_int object)
* Return TRUE if this object should be listed as room content.
*/
sc_bool
-obj_shows_initial_description (sc_gameref_t game, sc_int object)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int onlywhennotmoved;
-
- /* Get only when moved property. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "OnlyWhenNotMoved";
- onlywhennotmoved = prop_get_integer (bundle, "I<-sis", vt_key);
-
- /* Combine this with game in mysterious ways. */
- switch (onlywhennotmoved)
- {
- case 0:
- return TRUE;
-
- case 1:
- return gs_object_unmoved (game, object);
-
- case 2:
- {
- sc_int initialposition;
-
- if (gs_object_unmoved (game, object))
- return TRUE;
-
- vt_key[2].string = "InitialPosition";
- initialposition = prop_get_integer (bundle, "I<-sis", vt_key) - 3;
- return gs_object_position (game, object) == initialposition;
- }
- }
-
- /* What you talkin' 'bout, Willis? */
- return FALSE;
+obj_shows_initial_description(sc_gameref_t game, sc_int object) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int onlywhennotmoved;
+
+ /* Get only when moved property. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "OnlyWhenNotMoved";
+ onlywhennotmoved = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ /* Combine this with game in mysterious ways. */
+ switch (onlywhennotmoved) {
+ case 0:
+ return TRUE;
+
+ case 1:
+ return gs_object_unmoved(game, object);
+
+ case 2: {
+ sc_int initialposition;
+
+ if (gs_object_unmoved(game, object))
+ return TRUE;
+
+ vt_key[2].string = "InitialPosition";
+ initialposition = prop_get_integer(bundle, "I<-sis", vt_key) - 3;
+ return gs_object_position(game, object) == initialposition;
+ }
+ }
+
+ /* What you talkin' 'bout, Willis? */
+ return FALSE;
}
@@ -1000,24 +928,21 @@ obj_shows_initial_description (sc_gameref_t game, sc_int object)
* Set initial values for object states, and update after a turn.
*/
void
-obj_turn_update (sc_gameref_t game)
-{
- sc_int index_;
-
- /* Update object seen flag to current state. */
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (!gs_object_seen (game, index_)
- && obj_indirectly_in_room (game, index_, gs_playerroom (game)))
- gs_set_object_seen (game, index_, TRUE);
- }
+obj_turn_update(sc_gameref_t game) {
+ sc_int index_;
+
+ /* Update object seen flag to current state. */
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (!gs_object_seen(game, index_)
+ && obj_indirectly_in_room(game, index_, gs_playerroom(game)))
+ gs_set_object_seen(game, index_, TRUE);
+ }
}
void
-obj_setup_initial (sc_gameref_t game)
-{
- /* Set initial seen states for objects. */
- obj_turn_update (game);
+obj_setup_initial(sc_gameref_t game) {
+ /* Set initial seen states for objects. */
+ obj_turn_update(game);
}
@@ -1027,9 +952,8 @@ obj_setup_initial (sc_gameref_t game)
* Set object tracing on/off.
*/
void
-obj_debug_trace (sc_bool flag)
-{
- obj_trace = flag;
+obj_debug_trace(sc_bool flag) {
+ obj_trace = flag;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scparser.cpp b/engines/glk/adrift/scparser.cpp
index 6f7642c3a7..9372b5e39e 100644
--- a/engines/glk/adrift/scparser.cpp
+++ b/engines/glk/adrift/scparser.cpp
@@ -48,37 +48,35 @@ static const sc_char *const WHITESPACE = "\t\n\v\f\r ";
static sc_bool uip_trace = FALSE;
/* Enumeration of tokens. TOK_NONE represents a non-occurring token. */
-typedef enum
-{
- TOK_NONE = 0,
- TOK_CHOICE, TOK_CHOICE_END, TOK_OPTIONAL, TOK_OPTIONAL_END,
- TOK_ALTERNATES_SEPARATOR,
- TOK_WILDCARD, TOK_WHITESPACE, TOK_WORD, TOK_VARIABLE,
- TOK_CHARACTER_REFERENCE, TOK_OBJECT_REFERENCE, TOK_NUMBER_REFERENCE,
- TOK_TEXT_REFERENCE, TOK_EOS
+typedef enum {
+ TOK_NONE = 0,
+ TOK_CHOICE, TOK_CHOICE_END, TOK_OPTIONAL, TOK_OPTIONAL_END,
+ TOK_ALTERNATES_SEPARATOR,
+ TOK_WILDCARD, TOK_WHITESPACE, TOK_WORD, TOK_VARIABLE,
+ TOK_CHARACTER_REFERENCE, TOK_OBJECT_REFERENCE, TOK_NUMBER_REFERENCE,
+ TOK_TEXT_REFERENCE, TOK_EOS
} sc_uip_tok_t;
/*
* Small table tying token strings to tokens. Anything not whitespace and
* not caught by the table is a plain TOK_WORD.
*/
-typedef struct
-{
- const sc_char *const name;
- const sc_int length;
- const sc_uip_tok_t token;
+typedef struct {
+ const sc_char *const name;
+ const sc_int length;
+ const sc_uip_tok_t token;
} sc_uip_token_entry_t;
static const sc_uip_token_entry_t UIP_TOKENS[] = {
- {"[", 1, TOK_CHOICE}, {"]", 1, TOK_CHOICE_END},
- {"{", 1, TOK_OPTIONAL}, {"}", 1, TOK_OPTIONAL_END},
- {"/", 1, TOK_ALTERNATES_SEPARATOR},
- {"*", 1, TOK_WILDCARD},
- {"%character%", 11, TOK_CHARACTER_REFERENCE},
- {"%object%", 8, TOK_OBJECT_REFERENCE},
- {"%number%", 8, TOK_NUMBER_REFERENCE},
- {"%text%", 6, TOK_TEXT_REFERENCE},
- {NULL, 0, TOK_NONE}
+ {"[", 1, TOK_CHOICE}, {"]", 1, TOK_CHOICE_END},
+ {"{", 1, TOK_OPTIONAL}, {"}", 1, TOK_OPTIONAL_END},
+ {"/", 1, TOK_ALTERNATES_SEPARATOR},
+ {"*", 1, TOK_WILDCARD},
+ {"%character%", 11, TOK_CHARACTER_REFERENCE},
+ {"%object%", 8, TOK_OBJECT_REFERENCE},
+ {"%number%", 8, TOK_NUMBER_REFERENCE},
+ {"%text%", 6, TOK_TEXT_REFERENCE},
+ {NULL, 0, TOK_NONE}
};
@@ -101,49 +99,44 @@ static sc_char *uip_temporary = NULL;
* Start and wrap up pattern string tokenization.
*/
static void
-uip_tokenize_start (const sc_char *pattern)
-{
- static sc_bool initialized = FALSE;
- sc_int required;
-
- /* On first call only, verify the string lengths in the table. */
- if (!initialized)
- {
- const sc_uip_token_entry_t *entry;
-
- /* Compare table lengths with string lengths. */
- for (entry = UIP_TOKENS; entry->name; entry++)
- {
- if (entry->length != (sc_int) strlen (entry->name))
- {
- sc_fatal ("uip_tokenize_start:"
- " table string length is wrong for \"%s\"\n",
- entry->name);
- }
- }
-
- initialized = TRUE;
- }
-
- /* Save pattern, and restart index. */
- uip_pattern = pattern;
- uip_index = 0;
-
- /* Set up temporary; static if long enough, otherwise allocated. */
- required = strlen (pattern) + 1;
- uip_temporary = (required > UIP_ALLOCATION_AVOIDANCE_SIZE)
- ? (sc_char *)sc_malloc (required) : uip_static_temporary;
+uip_tokenize_start(const sc_char *pattern) {
+ static sc_bool initialized = FALSE;
+ sc_int required;
+
+ /* On first call only, verify the string lengths in the table. */
+ if (!initialized) {
+ const sc_uip_token_entry_t *entry;
+
+ /* Compare table lengths with string lengths. */
+ for (entry = UIP_TOKENS; entry->name; entry++) {
+ if (entry->length != (sc_int) strlen(entry->name)) {
+ sc_fatal("uip_tokenize_start:"
+ " table string length is wrong for \"%s\"\n",
+ entry->name);
+ }
+ }
+
+ initialized = TRUE;
+ }
+
+ /* Save pattern, and restart index. */
+ uip_pattern = pattern;
+ uip_index = 0;
+
+ /* Set up temporary; static if long enough, otherwise allocated. */
+ required = strlen(pattern) + 1;
+ uip_temporary = (required > UIP_ALLOCATION_AVOIDANCE_SIZE)
+ ? (sc_char *)sc_malloc(required) : uip_static_temporary;
}
static void
-uip_tokenize_end (void)
-{
- /* Deallocate temporary if required, and clear pattern and index. */
- if (uip_temporary != uip_static_temporary)
- sc_free (uip_temporary);
- uip_temporary = NULL;
- uip_pattern = NULL;
- uip_index = 0;
+uip_tokenize_end(void) {
+ /* Deallocate temporary if required, and clear pattern and index. */
+ if (uip_temporary != uip_static_temporary)
+ sc_free(uip_temporary);
+ uip_temporary = NULL;
+ uip_pattern = NULL;
+ uip_index = 0;
}
@@ -153,68 +146,62 @@ uip_tokenize_end (void)
* Return the next token from the current pattern.
*/
static sc_uip_tok_t
-uip_next_token (void)
-{
- const sc_uip_token_entry_t *entry;
- sc_char close;
- assert (uip_pattern);
-
- /* Get next character, return EOS if at pattern end. */
- if (uip_pattern[uip_index] == NUL)
- {
- uip_token_value = NULL;
- return TOK_EOS;
- }
-
- /* If whitespace, skip it, then return a whitespace token. */
- if (sc_isspace (uip_pattern[uip_index]))
- {
- uip_index++;
- while (sc_isspace (uip_pattern[uip_index])
- && uip_pattern[uip_index] != NUL)
- uip_index++;
- uip_token_value = NULL;
- return TOK_WHITESPACE;
- }
-
- /* Search the table for matching strings. */
- for (entry = UIP_TOKENS; entry->name; entry++)
- {
- if (strncmp (uip_pattern + uip_index, entry->name, entry->length) == 0)
- break;
- }
- if (entry->name)
- {
- /* Advance over string, and return token. */
- uip_index += entry->length;
- uip_token_value = NULL;
- return entry->token;
- }
-
- /*
- * Search for a non-special variable reference. This is apparently an
- * Adrift extension to the standard pattern match, allowing %user_var% to
- * be used in patterns. If found, return a variable with the name as the
- * token value. We can't interpolate the value into the string either
- * here or earlier, so we have to save the variable's name, and retrieve
- * it when we come to try the match.
- */
- if (sscanf (uip_pattern + uip_index, "%%%[^%]%c", uip_temporary, &close) == 2
- && close == PERCENT)
- {
- uip_index += strlen (uip_temporary) + 2;
- uip_token_value = uip_temporary;
- return TOK_VARIABLE;
- }
-
- /*
- * Return a word. This is a contiguous run of non-pattern-special, non-
- * whitespace, non-percent characters
- */
- sscanf (uip_pattern + uip_index, "%[^][/{}*% \f\n\r\t\v]", uip_temporary);
- uip_token_value = uip_temporary;
- uip_index += strlen (uip_temporary);
- return TOK_WORD;
+uip_next_token(void) {
+ const sc_uip_token_entry_t *entry;
+ sc_char close;
+ assert(uip_pattern);
+
+ /* Get next character, return EOS if at pattern end. */
+ if (uip_pattern[uip_index] == NUL) {
+ uip_token_value = NULL;
+ return TOK_EOS;
+ }
+
+ /* If whitespace, skip it, then return a whitespace token. */
+ if (sc_isspace(uip_pattern[uip_index])) {
+ uip_index++;
+ while (sc_isspace(uip_pattern[uip_index])
+ && uip_pattern[uip_index] != NUL)
+ uip_index++;
+ uip_token_value = NULL;
+ return TOK_WHITESPACE;
+ }
+
+ /* Search the table for matching strings. */
+ for (entry = UIP_TOKENS; entry->name; entry++) {
+ if (strncmp(uip_pattern + uip_index, entry->name, entry->length) == 0)
+ break;
+ }
+ if (entry->name) {
+ /* Advance over string, and return token. */
+ uip_index += entry->length;
+ uip_token_value = NULL;
+ return entry->token;
+ }
+
+ /*
+ * Search for a non-special variable reference. This is apparently an
+ * Adrift extension to the standard pattern match, allowing %user_var% to
+ * be used in patterns. If found, return a variable with the name as the
+ * token value. We can't interpolate the value into the string either
+ * here or earlier, so we have to save the variable's name, and retrieve
+ * it when we come to try the match.
+ */
+ if (sscanf(uip_pattern + uip_index, "%%%[^%]%c", uip_temporary, &close) == 2
+ && close == PERCENT) {
+ uip_index += strlen(uip_temporary) + 2;
+ uip_token_value = uip_temporary;
+ return TOK_VARIABLE;
+ }
+
+ /*
+ * Return a word. This is a contiguous run of non-pattern-special, non-
+ * whitespace, non-percent characters
+ */
+ sscanf(uip_pattern + uip_index, "%[^][/{}*% \f\n\r\t\v]", uip_temporary);
+ uip_token_value = uip_temporary;
+ uip_index += strlen(uip_temporary);
+ return TOK_WORD;
}
@@ -225,17 +212,15 @@ uip_next_token (void)
* here if the current token is not a TOK_WORD or TOK_VARIABLE.
*/
static const sc_char *
-uip_current_token_value (void)
-{
- /* If the token value is NULL, the current token isn't a word. */
- if (!uip_token_value)
- {
- sc_fatal ("uip_current_token_value:"
- " attempt to take undefined token value\n");
- }
-
- /* Return value. */
- return uip_token_value;
+uip_current_token_value(void) {
+ /* If the token value is NULL, the current token isn't a word. */
+ if (!uip_token_value) {
+ sc_fatal("uip_current_token_value:"
+ " attempt to take undefined token value\n");
+ }
+
+ /* Return value. */
+ return uip_token_value;
}
@@ -245,21 +230,19 @@ uip_current_token_value (void)
* NODE_UNUSED must be zero to ensure that the statically allocated array that
* forms the node pool appears initially as containing only unused nodes.
*/
-typedef enum
-{
- NODE_UNUSED = 0,
- NODE_CHOICE, NODE_OPTIONAL, NODE_WILDCARD, NODE_WHITESPACE,
- NODE_CHARACTER_REFERENCE, NODE_OBJECT_REFERENCE, NODE_TEXT_REFERENCE,
- NODE_NUMBER_REFERENCE, NODE_WORD, NODE_VARIABLE, NODE_LIST, NODE_EOS
+typedef enum {
+ NODE_UNUSED = 0,
+ NODE_CHOICE, NODE_OPTIONAL, NODE_WILDCARD, NODE_WHITESPACE,
+ NODE_CHARACTER_REFERENCE, NODE_OBJECT_REFERENCE, NODE_TEXT_REFERENCE,
+ NODE_NUMBER_REFERENCE, NODE_WORD, NODE_VARIABLE, NODE_LIST, NODE_EOS
} sc_pttype_t;
-typedef struct sc_ptnode_s
-{
- struct sc_ptnode_s *left_child;
- struct sc_ptnode_s *right_sibling;
-
- sc_pttype_t type;
- sc_char *word;
- sc_bool is_allocated;
+typedef struct sc_ptnode_s {
+ struct sc_ptnode_s *left_child;
+ struct sc_ptnode_s *right_sibling;
+
+ sc_pttype_t type;
+ sc_char *word;
+ sc_bool is_allocated;
} sc_ptnode_t;
typedef sc_ptnode_t *sc_ptnoderef_t;
@@ -271,7 +254,7 @@ static jmp_buf uip_parse_error;
/* Parse tree for cleanup, and forward declaration of pattern list parser. */
static sc_ptnoderef_t uip_parse_tree = NULL;
-static void uip_parse_list (sc_ptnoderef_t list);
+static void uip_parse_list(sc_ptnoderef_t list);
/*
* Pool of statically allocated nodes, for faster allocations. Nodes are
@@ -290,10 +273,9 @@ static sc_int uip_node_pool_available = UIP_NODE_POOL_SIZE;
* first, then by straight malloc() should the pool empty.
*/
enum { UIP_WORD_POOL_SIZE = 64, UIP_SHORT_WORD_SIZE = 16 };
-typedef struct
-{
- sc_bool is_in_use;
- sc_char word[UIP_SHORT_WORD_SIZE];
+typedef struct {
+ sc_bool is_in_use;
+ sc_char word[UIP_SHORT_WORD_SIZE];
} sc_ptshortword_t;
typedef sc_ptshortword_t *sc_ptshortwordref_t;
static sc_ptshortword_t uip_word_pool[UIP_WORD_POOL_SIZE];
@@ -306,17 +288,15 @@ static sc_int uip_word_pool_available = UIP_WORD_POOL_SIZE;
* Match a token to the lookahead, then advance lookahead.
*/
static void
-uip_parse_match (sc_uip_tok_t token)
-{
- if (uip_parse_lookahead == token)
- uip_parse_lookahead = uip_next_token ();
- else
- {
- /* Syntax error. */
- sc_error ("uip_parse_match: syntax error, expected %ld, got %ld\n",
- (sc_int) uip_parse_lookahead, (sc_int) token);
- longjmp (uip_parse_error, 1);
- }
+uip_parse_match(sc_uip_tok_t token) {
+ if (uip_parse_lookahead == token)
+ uip_parse_lookahead = uip_next_token();
+ else {
+ /* Syntax error. */
+ sc_error("uip_parse_match: syntax error, expected %ld, got %ld\n",
+ (sc_int) uip_parse_lookahead, (sc_int) token);
+ longjmp(uip_parse_error, 1);
+ }
}
@@ -328,51 +308,46 @@ uip_parse_match (sc_uip_tok_t token)
* exhausted, backs off to standard allocation.
*/
static sc_char *
-uip_new_word (const sc_char *word)
-{
- sc_int required;
-
- /*
- * Unless the pool is empty, search forwards from the next cursor position
- * until an unused slot is found, or until the index wraps to the cursor.
- */
- required = strlen (word) + 1;
- if (uip_word_pool_available > 0 && required <= UIP_SHORT_WORD_SIZE)
- {
- sc_int index_;
- sc_ptshortwordref_t shortword;
-
- index_ = (uip_word_pool_cursor + 1) % UIP_WORD_POOL_SIZE;
- while (index_ != uip_word_pool_cursor)
- {
- if (!uip_word_pool[index_].is_in_use)
- break;
- index_ = (index_ + 1) % UIP_WORD_POOL_SIZE;
- }
-
- if (uip_word_pool[index_].is_in_use)
- sc_fatal ("uip_new_word: no free slot found in the words pool\n");
-
- /* Use the slot and update the pool cursor and free count. */
- shortword = uip_word_pool + index_;
- strcpy (shortword->word, word);
- shortword->is_in_use = TRUE;
-
- uip_word_pool_cursor = index_;
- uip_word_pool_available--;
-
- /* Return the address of the copied string. */
- return shortword->word;
- }
- else
- {
- sc_char *word_copy;
-
- /* Fall back to less efficient allocations. */
- word_copy = (sc_char *)sc_malloc (required);
- strcpy (word_copy, word);
- return word_copy;
- }
+uip_new_word(const sc_char *word) {
+ sc_int required;
+
+ /*
+ * Unless the pool is empty, search forwards from the next cursor position
+ * until an unused slot is found, or until the index wraps to the cursor.
+ */
+ required = strlen(word) + 1;
+ if (uip_word_pool_available > 0 && required <= UIP_SHORT_WORD_SIZE) {
+ sc_int index_;
+ sc_ptshortwordref_t shortword;
+
+ index_ = (uip_word_pool_cursor + 1) % UIP_WORD_POOL_SIZE;
+ while (index_ != uip_word_pool_cursor) {
+ if (!uip_word_pool[index_].is_in_use)
+ break;
+ index_ = (index_ + 1) % UIP_WORD_POOL_SIZE;
+ }
+
+ if (uip_word_pool[index_].is_in_use)
+ sc_fatal("uip_new_word: no free slot found in the words pool\n");
+
+ /* Use the slot and update the pool cursor and free count. */
+ shortword = uip_word_pool + index_;
+ strcpy(shortword->word, word);
+ shortword->is_in_use = TRUE;
+
+ uip_word_pool_cursor = index_;
+ uip_word_pool_available--;
+
+ /* Return the address of the copied string. */
+ return shortword->word;
+ } else {
+ sc_char *word_copy;
+
+ /* Fall back to less efficient allocations. */
+ word_copy = (sc_char *)sc_malloc(required);
+ strcpy(word_copy, word);
+ return word_copy;
+ }
}
@@ -383,33 +358,30 @@ uip_new_word (const sc_char *word)
* pool entry and return it to the pool.
*/
static void
-uip_free_word (sc_char *word)
-{
- const sc_char *first_in_pool, *last_in_pool;
-
- /* Obtain the range of valid addresses for words from the word pool. */
- first_in_pool = uip_word_pool[0].word;
- last_in_pool = uip_word_pool[UIP_WORD_POOL_SIZE - 1].word;
-
- /* If from the pool, mark the entry as no longer in use, otherwise free. */
- if (word >= first_in_pool && word <= last_in_pool)
- {
- sc_int index_;
- sc_ptshortwordref_t shortword;
-
- /*
- * Calculate the index to the word pool entry from which this short
- * word was allocated.
- */
- index_ = (word - first_in_pool) / sizeof (uip_word_pool[0]);
- shortword = uip_word_pool + index_;
- assert (shortword->word == word);
-
- shortword->is_in_use = FALSE;
- uip_word_pool_available++;
- }
- else
- sc_free (word);
+uip_free_word(sc_char *word) {
+ const sc_char *first_in_pool, *last_in_pool;
+
+ /* Obtain the range of valid addresses for words from the word pool. */
+ first_in_pool = uip_word_pool[0].word;
+ last_in_pool = uip_word_pool[UIP_WORD_POOL_SIZE - 1].word;
+
+ /* If from the pool, mark the entry as no longer in use, otherwise free. */
+ if (word >= first_in_pool && word <= last_in_pool) {
+ sc_int index_;
+ sc_ptshortwordref_t shortword;
+
+ /*
+ * Calculate the index to the word pool entry from which this short
+ * word was allocated.
+ */
+ index_ = (word - first_in_pool) / sizeof(uip_word_pool[0]);
+ shortword = uip_word_pool + index_;
+ assert(shortword->word == word);
+
+ shortword->is_in_use = FALSE;
+ uip_word_pool_available++;
+ } else
+ sc_free(word);
}
@@ -421,50 +393,45 @@ uip_free_word (sc_char *word)
* exhausted, backs off to standard allocation.
*/
static sc_ptnoderef_t
-uip_new_node (sc_pttype_t type)
-{
- sc_ptnoderef_t node;
-
- /*
- * Unless the pool is empty, search forwards from the next cursor position
- * until an unused slot is found, or until the index wraps to the cursor.
- */
- if (uip_node_pool_available > 0)
- {
- sc_int index_;
-
- index_ = (uip_node_pool_cursor + 1) % UIP_NODE_POOL_SIZE;
- while (index_ != uip_node_pool_cursor)
- {
- if (uip_node_pool[index_].type == NODE_UNUSED)
- break;
- index_ = (index_ + 1) % UIP_NODE_POOL_SIZE;
- }
-
- if (uip_node_pool[index_].type != NODE_UNUSED)
- sc_fatal ("uip_new_node: no free slot found in the nodes pool\n");
-
- /* Use the slot and update the pool cursor and free count. */
- node = uip_node_pool + index_;
- node->is_allocated = FALSE;
-
- uip_node_pool_cursor = index_;
- uip_node_pool_available--;
- }
- else
- {
- /* Fall back to less efficient allocations. */
- node = (sc_ptnoderef_t)sc_malloc(sizeof (*node));
- node->is_allocated = TRUE;
- }
-
- /* Fill in the remaining fields and return the new node. */
- node->left_child = NULL;
- node->right_sibling = NULL;
- node->type = type;
- node->word = NULL;
-
- return node;
+uip_new_node(sc_pttype_t type) {
+ sc_ptnoderef_t node;
+
+ /*
+ * Unless the pool is empty, search forwards from the next cursor position
+ * until an unused slot is found, or until the index wraps to the cursor.
+ */
+ if (uip_node_pool_available > 0) {
+ sc_int index_;
+
+ index_ = (uip_node_pool_cursor + 1) % UIP_NODE_POOL_SIZE;
+ while (index_ != uip_node_pool_cursor) {
+ if (uip_node_pool[index_].type == NODE_UNUSED)
+ break;
+ index_ = (index_ + 1) % UIP_NODE_POOL_SIZE;
+ }
+
+ if (uip_node_pool[index_].type != NODE_UNUSED)
+ sc_fatal("uip_new_node: no free slot found in the nodes pool\n");
+
+ /* Use the slot and update the pool cursor and free count. */
+ node = uip_node_pool + index_;
+ node->is_allocated = FALSE;
+
+ uip_node_pool_cursor = index_;
+ uip_node_pool_available--;
+ } else {
+ /* Fall back to less efficient allocations. */
+ node = (sc_ptnoderef_t)sc_malloc(sizeof(*node));
+ node->is_allocated = TRUE;
+ }
+
+ /* Fill in the remaining fields and return the new node. */
+ node->left_child = NULL;
+ node->right_sibling = NULL;
+ node->type = type;
+ node->word = NULL;
+
+ return node;
}
@@ -475,27 +442,23 @@ uip_new_node (sc_pttype_t type)
* free its memory; if not, return it to the pool.
*/
static void
-uip_destroy_node (sc_ptnoderef_t node)
-{
- /* Free any word contained at this node. */
- if (node->word)
- uip_free_word (node->word);
-
- /*
- * If the node was allocated, poison memory and free it. If it came from
- * the node pool, set it to unused and update the availability count for
- * the pool.
- */
- if (node->is_allocated)
- {
- memset (node, 0xaa, sizeof (*node));
- sc_free (node);
- }
- else
- {
- node->type = NODE_UNUSED;
- uip_node_pool_available++;
- }
+uip_destroy_node(sc_ptnoderef_t node) {
+ /* Free any word contained at this node. */
+ if (node->word)
+ uip_free_word(node->word);
+
+ /*
+ * If the node was allocated, poison memory and free it. If it came from
+ * the node pool, set it to unused and update the availability count for
+ * the pool.
+ */
+ if (node->is_allocated) {
+ memset(node, 0xaa, sizeof(*node));
+ sc_free(node);
+ } else {
+ node->type = NODE_UNUSED;
+ uip_node_pool_available++;
+ }
}
@@ -507,30 +470,27 @@ uip_destroy_node (sc_ptnoderef_t node)
* first function is a helper, returning a newly constructed parsed list.
*/
static sc_ptnoderef_t
-uip_parse_new_list (void)
-{
- sc_ptnoderef_t list;
-
- /* Create a new list node, parse into it, and return it. */
- list = uip_new_node (NODE_LIST);
- uip_parse_list (list);
- return list;
+uip_parse_new_list(void) {
+ sc_ptnoderef_t list;
+
+ /* Create a new list node, parse into it, and return it. */
+ list = uip_new_node(NODE_LIST);
+ uip_parse_list(list);
+ return list;
}
static void
-uip_parse_alternatives (sc_ptnoderef_t node)
-{
- sc_ptnoderef_t child;
-
- /* Parse initial alternative, then add other listed alternatives. */
- node->left_child = uip_parse_new_list ();
- child = node->left_child;
- while (uip_parse_lookahead == TOK_ALTERNATES_SEPARATOR)
- {
- uip_parse_match (TOK_ALTERNATES_SEPARATOR);
- child->right_sibling = uip_parse_new_list ();
- child = child->right_sibling;
- }
+uip_parse_alternatives(sc_ptnoderef_t node) {
+ sc_ptnoderef_t child;
+
+ /* Parse initial alternative, then add other listed alternatives. */
+ node->left_child = uip_parse_new_list();
+ child = node->left_child;
+ while (uip_parse_lookahead == TOK_ALTERNATES_SEPARATOR) {
+ uip_parse_match(TOK_ALTERNATES_SEPARATOR);
+ child->right_sibling = uip_parse_new_list();
+ child = child->right_sibling;
+ }
}
@@ -540,107 +500,102 @@ uip_parse_alternatives (sc_ptnoderef_t node)
* Parse a single pattern element.
*/
static sc_ptnoderef_t
-uip_parse_element (void)
-{
- sc_ptnoderef_t node = NULL;
- sc_uip_tok_t token;
-
- /* Handle pattern element based on lookahead token. */
- switch (uip_parse_lookahead)
- {
- case TOK_WHITESPACE:
- uip_parse_match (TOK_WHITESPACE);
- node = uip_new_node (NODE_WHITESPACE);
- break;
-
- case TOK_CHOICE:
- /* Parse a [...[/.../...]] choice. */
- uip_parse_match (TOK_CHOICE);
- node = uip_new_node (NODE_CHOICE);
- uip_parse_alternatives (node);
- uip_parse_match (TOK_CHOICE_END);
- break;
-
- case TOK_OPTIONAL:
- /* Parse a {...[/.../...]} optional element. */
- uip_parse_match (TOK_OPTIONAL);
- node = uip_new_node (NODE_OPTIONAL);
- uip_parse_alternatives (node);
- uip_parse_match (TOK_OPTIONAL_END);
- break;
-
- case TOK_WILDCARD:
- case TOK_CHARACTER_REFERENCE:
- case TOK_OBJECT_REFERENCE:
- case TOK_NUMBER_REFERENCE:
- case TOK_TEXT_REFERENCE:
- /* Parse %mumble% references and * wildcards. */
- token = uip_parse_lookahead;
- uip_parse_match (token);
- switch (token)
- {
- case TOK_WILDCARD:
- node = uip_new_node (NODE_WILDCARD);
- break;
- case TOK_CHARACTER_REFERENCE:
- node = uip_new_node (NODE_CHARACTER_REFERENCE);
- break;
- case TOK_OBJECT_REFERENCE:
- node = uip_new_node (NODE_OBJECT_REFERENCE);
- break;
- case TOK_NUMBER_REFERENCE:
- node = uip_new_node (NODE_NUMBER_REFERENCE);
- break;
- case TOK_TEXT_REFERENCE:
- node = uip_new_node (NODE_TEXT_REFERENCE);
- break;
- default:
- sc_fatal ("uip_parse_element: invalid token, %ld\n", (sc_int) token);
- }
- break;
-
- case TOK_WORD:
- {
- const sc_char *token_value;
- sc_char *word;
-
- /* Take a copy of the token's word value. */
- token_value = uip_current_token_value ();
- word = uip_new_word (token_value);
-
- /* Store details in a word node. */
- uip_parse_match (TOK_WORD);
- node = uip_new_node (NODE_WORD);
- node->word = word;
- break;
- }
-
- case TOK_VARIABLE:
- {
- const sc_char *token_value;
- sc_char *name;
-
- /* Take a copy of the token's variable name value. */
- token_value = uip_current_token_value ();
- name = uip_new_word (token_value);
-
- /* Store details in a variable node, overloading word. */
- uip_parse_match (TOK_VARIABLE);
- node = uip_new_node (NODE_VARIABLE);
- node->word = name;
- break;
- }
-
- default:
- /* Syntax error. */
- sc_error ("uip_parse_element: syntax error,"
- " unexpected token, %ld\n", (sc_int) uip_parse_lookahead);
- longjmp (uip_parse_error, 1);
- }
-
- /* Return the newly created node. */
- assert (node);
- return node;
+uip_parse_element(void) {
+ sc_ptnoderef_t node = NULL;
+ sc_uip_tok_t token;
+
+ /* Handle pattern element based on lookahead token. */
+ switch (uip_parse_lookahead) {
+ case TOK_WHITESPACE:
+ uip_parse_match(TOK_WHITESPACE);
+ node = uip_new_node(NODE_WHITESPACE);
+ break;
+
+ case TOK_CHOICE:
+ /* Parse a [...[/.../...]] choice. */
+ uip_parse_match(TOK_CHOICE);
+ node = uip_new_node(NODE_CHOICE);
+ uip_parse_alternatives(node);
+ uip_parse_match(TOK_CHOICE_END);
+ break;
+
+ case TOK_OPTIONAL:
+ /* Parse a {...[/.../...]} optional element. */
+ uip_parse_match(TOK_OPTIONAL);
+ node = uip_new_node(NODE_OPTIONAL);
+ uip_parse_alternatives(node);
+ uip_parse_match(TOK_OPTIONAL_END);
+ break;
+
+ case TOK_WILDCARD:
+ case TOK_CHARACTER_REFERENCE:
+ case TOK_OBJECT_REFERENCE:
+ case TOK_NUMBER_REFERENCE:
+ case TOK_TEXT_REFERENCE:
+ /* Parse %mumble% references and * wildcards. */
+ token = uip_parse_lookahead;
+ uip_parse_match(token);
+ switch (token) {
+ case TOK_WILDCARD:
+ node = uip_new_node(NODE_WILDCARD);
+ break;
+ case TOK_CHARACTER_REFERENCE:
+ node = uip_new_node(NODE_CHARACTER_REFERENCE);
+ break;
+ case TOK_OBJECT_REFERENCE:
+ node = uip_new_node(NODE_OBJECT_REFERENCE);
+ break;
+ case TOK_NUMBER_REFERENCE:
+ node = uip_new_node(NODE_NUMBER_REFERENCE);
+ break;
+ case TOK_TEXT_REFERENCE:
+ node = uip_new_node(NODE_TEXT_REFERENCE);
+ break;
+ default:
+ sc_fatal("uip_parse_element: invalid token, %ld\n", (sc_int) token);
+ }
+ break;
+
+ case TOK_WORD: {
+ const sc_char *token_value;
+ sc_char *word;
+
+ /* Take a copy of the token's word value. */
+ token_value = uip_current_token_value();
+ word = uip_new_word(token_value);
+
+ /* Store details in a word node. */
+ uip_parse_match(TOK_WORD);
+ node = uip_new_node(NODE_WORD);
+ node->word = word;
+ break;
+ }
+
+ case TOK_VARIABLE: {
+ const sc_char *token_value;
+ sc_char *name;
+
+ /* Take a copy of the token's variable name value. */
+ token_value = uip_current_token_value();
+ name = uip_new_word(token_value);
+
+ /* Store details in a variable node, overloading word. */
+ uip_parse_match(TOK_VARIABLE);
+ node = uip_new_node(NODE_VARIABLE);
+ node->word = name;
+ break;
+ }
+
+ default:
+ /* Syntax error. */
+ sc_error("uip_parse_element: syntax error,"
+ " unexpected token, %ld\n", (sc_int) uip_parse_lookahead);
+ longjmp(uip_parse_error, 1);
+ }
+
+ /* Return the newly created node. */
+ assert(node);
+ return node;
}
@@ -650,63 +605,56 @@ uip_parse_element (void)
* Parse a list of pattern elements.
*/
static void
-uip_parse_list (sc_ptnoderef_t list)
-{
- sc_ptnoderef_t child, node;
-
- /* Add elements until a list terminator token is encountered. */
- child = list;
- while (TRUE)
- {
- switch (uip_parse_lookahead)
- {
- case TOK_CHOICE_END:
- case TOK_OPTIONAL_END:
- case TOK_ALTERNATES_SEPARATOR:
- /* Terminate list building and return. */
- return;
-
- case TOK_EOS:
- /* Place EOS at the appropriate link and return. */
- node = uip_new_node (NODE_EOS);
- if (child == list)
- child->left_child = node;
- else
- child->right_sibling = node;
- return;
-
- default:
- /* Add the next node at the appropriate link. */
- node = uip_parse_element ();
- if (child == list)
- {
- child->left_child = node;
- child = child->left_child;
- }
- else
- {
- /*
- * Make a special case of a choice or option next to another
- * choice or option. In this case, add an (invented) whitespace
- * node, to ensure a match with suitable input.
- */
- if ((child->type == NODE_OPTIONAL || child->type == NODE_CHOICE)
- && (node->type == NODE_OPTIONAL || node->type == NODE_CHOICE))
- {
- sc_ptnoderef_t whitespace;
-
- /* Interpose invented whitespace. */
- whitespace = uip_new_node (NODE_WHITESPACE);
- child->right_sibling = whitespace;
- child = child->right_sibling;
- }
-
- child->right_sibling = node;
- child = child->right_sibling;
- }
- continue;
- }
- }
+uip_parse_list(sc_ptnoderef_t list) {
+ sc_ptnoderef_t child, node;
+
+ /* Add elements until a list terminator token is encountered. */
+ child = list;
+ while (TRUE) {
+ switch (uip_parse_lookahead) {
+ case TOK_CHOICE_END:
+ case TOK_OPTIONAL_END:
+ case TOK_ALTERNATES_SEPARATOR:
+ /* Terminate list building and return. */
+ return;
+
+ case TOK_EOS:
+ /* Place EOS at the appropriate link and return. */
+ node = uip_new_node(NODE_EOS);
+ if (child == list)
+ child->left_child = node;
+ else
+ child->right_sibling = node;
+ return;
+
+ default:
+ /* Add the next node at the appropriate link. */
+ node = uip_parse_element();
+ if (child == list) {
+ child->left_child = node;
+ child = child->left_child;
+ } else {
+ /*
+ * Make a special case of a choice or option next to another
+ * choice or option. In this case, add an (invented) whitespace
+ * node, to ensure a match with suitable input.
+ */
+ if ((child->type == NODE_OPTIONAL || child->type == NODE_CHOICE)
+ && (node->type == NODE_OPTIONAL || node->type == NODE_CHOICE)) {
+ sc_ptnoderef_t whitespace;
+
+ /* Interpose invented whitespace. */
+ whitespace = uip_new_node(NODE_WHITESPACE);
+ child->right_sibling = whitespace;
+ child = child->right_sibling;
+ }
+
+ child->right_sibling = node;
+ child = child->right_sibling;
+ }
+ continue;
+ }
+ }
}
@@ -716,17 +664,15 @@ uip_parse_list (sc_ptnoderef_t list)
* Free and destroy a parsed pattern tree.
*/
static void
-uip_destroy_tree (sc_ptnoderef_t node)
-{
- if (node)
- {
- /* Recursively destroy siblings, then left child. */
- uip_destroy_tree (node->right_sibling);
- uip_destroy_tree (node->left_child);
-
- /* Destroy the node itself. */
- uip_destroy_node (node);
- }
+uip_destroy_tree(sc_ptnoderef_t node) {
+ if (node) {
+ /* Recursively destroy siblings, then left child. */
+ uip_destroy_tree(node->right_sibling);
+ uip_destroy_tree(node->left_child);
+
+ /* Destroy the node itself. */
+ uip_destroy_node(node);
+ }
}
@@ -737,84 +683,78 @@ uip_destroy_tree (sc_ptnoderef_t node)
* Print out a pattern match tree.
*/
static void
-uip_debug_dump_node (sc_ptnoderef_t node, sc_int depth)
-{
- /* End recursion on null node. */
- if (node)
- {
- sc_int index_;
-
- sc_trace (" ");
- for (index_ = 0; index_ < depth; index_++)
- sc_trace (" ");
-
- sc_trace ("%p", (void *) node);
- switch (node->type)
- {
- case NODE_CHOICE:
- sc_trace (", choice");
- break;
- case NODE_OPTIONAL:
- sc_trace (", optional");
- break;
- case NODE_WILDCARD:
- sc_trace (", wildcard");
- break;
- case NODE_WHITESPACE:
- sc_trace (", whitespace");
- break;
- case NODE_CHARACTER_REFERENCE:
- sc_trace (", character");
- break;
- case NODE_OBJECT_REFERENCE:
- sc_trace (", object");
- break;
- case NODE_TEXT_REFERENCE:
- sc_trace (", text");
- break;
- case NODE_NUMBER_REFERENCE:
- sc_trace (", number");
- break;
- case NODE_WORD:
- sc_trace (", word \"%s\"", node->word);
- break;
- case NODE_VARIABLE:
- sc_trace (", variable \"%s\"", node->word);
- break;
- case NODE_LIST:
- sc_trace (", list");
- break;
- case NODE_EOS:
- sc_trace (", <eos>");
- break;
- default:
- sc_trace (", unknown type %ld", (sc_int) node->type);
- break;
- }
- if (node->left_child)
- sc_trace (", left child %p", (void *) node->left_child);
- if (node->right_sibling)
- sc_trace (", right sibling %p", (void *) node->right_sibling);
- sc_trace ("\n");
-
- /* Recursively dump left child, then siblings. */
- uip_debug_dump_node (node->left_child, depth + 1);
- uip_debug_dump_node (node->right_sibling, depth);
- }
+uip_debug_dump_node(sc_ptnoderef_t node, sc_int depth) {
+ /* End recursion on null node. */
+ if (node) {
+ sc_int index_;
+
+ sc_trace(" ");
+ for (index_ = 0; index_ < depth; index_++)
+ sc_trace(" ");
+
+ sc_trace("%p", (void *) node);
+ switch (node->type) {
+ case NODE_CHOICE:
+ sc_trace(", choice");
+ break;
+ case NODE_OPTIONAL:
+ sc_trace(", optional");
+ break;
+ case NODE_WILDCARD:
+ sc_trace(", wildcard");
+ break;
+ case NODE_WHITESPACE:
+ sc_trace(", whitespace");
+ break;
+ case NODE_CHARACTER_REFERENCE:
+ sc_trace(", character");
+ break;
+ case NODE_OBJECT_REFERENCE:
+ sc_trace(", object");
+ break;
+ case NODE_TEXT_REFERENCE:
+ sc_trace(", text");
+ break;
+ case NODE_NUMBER_REFERENCE:
+ sc_trace(", number");
+ break;
+ case NODE_WORD:
+ sc_trace(", word \"%s\"", node->word);
+ break;
+ case NODE_VARIABLE:
+ sc_trace(", variable \"%s\"", node->word);
+ break;
+ case NODE_LIST:
+ sc_trace(", list");
+ break;
+ case NODE_EOS:
+ sc_trace(", <eos>");
+ break;
+ default:
+ sc_trace(", unknown type %ld", (sc_int) node->type);
+ break;
+ }
+ if (node->left_child)
+ sc_trace(", left child %p", (void *) node->left_child);
+ if (node->right_sibling)
+ sc_trace(", right sibling %p", (void *) node->right_sibling);
+ sc_trace("\n");
+
+ /* Recursively dump left child, then siblings. */
+ uip_debug_dump_node(node->left_child, depth + 1);
+ uip_debug_dump_node(node->right_sibling, depth);
+ }
}
static void
-uip_debug_dump (void)
-{
- sc_trace ("UIParser: debug dump follows...\n");
- if (uip_parse_tree)
- {
- sc_trace ("uip_parse_tree = {\n");
- uip_debug_dump_node (uip_parse_tree, 0);
- sc_trace ("}\n");
- }
- else
- sc_trace ("uip_parse_tree = (nil)\n");
+uip_debug_dump(void) {
+ sc_trace("UIParser: debug dump follows...\n");
+ if (uip_parse_tree) {
+ sc_trace("uip_parse_tree = {\n");
+ uip_debug_dump_node(uip_parse_tree, 0);
+ sc_trace("}\n");
+ } else
+ sc_trace("uip_parse_tree = (nil)\n");
}
@@ -830,23 +770,21 @@ static sc_gameref_t uip_game = NULL;
* Set up a string for matching to a pattern tree, and wrap up matching.
*/
static void
-uip_match_start (const sc_char *string, sc_gameref_t game)
-{
- /* Save string, and restart index. */
- uip_string = string;
- uip_posn = 0;
-
- /* Save the game we're working on. */
- uip_game = game;
+uip_match_start(const sc_char *string, sc_gameref_t game) {
+ /* Save string, and restart index. */
+ uip_string = string;
+ uip_posn = 0;
+
+ /* Save the game we're working on. */
+ uip_game = game;
}
static void
-uip_match_end (void)
-{
- /* Clear match target string, and variable set. */
- uip_string = NULL;
- uip_posn = 0;
- uip_game = NULL;
+uip_match_end(void) {
+ /* Clear match target string, and variable set. */
+ uip_string = NULL;
+ uip_posn = 0;
+ uip_game = NULL;
}
@@ -857,15 +795,14 @@ uip_match_end (void)
* one.
*/
static sc_gameref_t
-uip_get_game (void)
-{
- assert (gs_is_game_valid (uip_game));
- return uip_game;
+uip_get_game(void) {
+ assert(gs_is_game_valid(uip_game));
+ return uip_game;
}
/* Forward declaration of low level node matcher. */
-static sc_bool uip_match_node (sc_ptnoderef_t node);
+static sc_bool uip_match_node(sc_ptnoderef_t node);
/*
* uip_match_eos()
@@ -883,298 +820,276 @@ static sc_bool uip_match_node (sc_ptnoderef_t node);
* unchanged.
*/
static sc_bool
-uip_match_eos (void)
-{
- /* Check that we hit the string's end. */
- return uip_string[uip_posn] == NUL;
+uip_match_eos(void) {
+ /* Check that we hit the string's end. */
+ return uip_string[uip_posn] == NUL;
}
static sc_bool
-uip_match_word (sc_ptnoderef_t node)
-{
- sc_int length;
- const sc_char *word;
-
- /* Get the word to match. */
- assert (node->word);
- word = node->word;
-
- /* Compare string text with this node's word, ignore case. */
- length = strlen (word);
- if (sc_strncasecmp (uip_string + uip_posn, word, length) == 0)
- {
- /* Word match, advance position and return. */
- uip_posn += length;
- return TRUE;
- }
-
- /* No match. */
- return FALSE;
+uip_match_word(sc_ptnoderef_t node) {
+ sc_int length;
+ const sc_char *word;
+
+ /* Get the word to match. */
+ assert(node->word);
+ word = node->word;
+
+ /* Compare string text with this node's word, ignore case. */
+ length = strlen(word);
+ if (sc_strncasecmp(uip_string + uip_posn, word, length) == 0) {
+ /* Word match, advance position and return. */
+ uip_posn += length;
+ return TRUE;
+ }
+
+ /* No match. */
+ return FALSE;
}
static sc_bool
-uip_match_variable (sc_ptnoderef_t node)
-{
- const sc_gameref_t game = uip_get_game ();
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int type;
- sc_vartype_t vt_rvalue;
- const sc_char *name;
-
- /* Get the variable name to match, from overloaded word. */
- assert (node->word);
- name = node->word;
-
- /* Get the variable's value. */
- if (var_get (vars, name, &type, &vt_rvalue))
- {
- sc_int length;
-
- /* Compare the value against the current string position. */
- switch (type)
- {
- case VAR_INTEGER:
- {
- sc_char value[32];
-
- /* Compare numeric against the current string position. */
- sprintf (value, "%ld", vt_rvalue.integer);
- length = strlen (value);
- if (strncmp (uip_string + uip_posn, value, length) == 0)
- {
- /* Integer match, advance position and return. */
- uip_posn += length;
- return TRUE;
- }
- break;
- }
-
- case VAR_STRING:
- /* Compare string value against the current string position. */
- length = strlen (vt_rvalue.string);
- if (sc_strncasecmp (uip_string + uip_posn,
- vt_rvalue.string, length) == 0)
- {
- /* String match, advance position and return. */
- uip_posn += length;
- return TRUE;
- }
- break;
-
- default:
- sc_fatal ("uip_match_variable: invalid variable type, %ld\n", type);
- }
- }
-
- /* No match, or no such variable. */
- return FALSE;
+uip_match_variable(sc_ptnoderef_t node) {
+ const sc_gameref_t game = uip_get_game();
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int type;
+ sc_vartype_t vt_rvalue;
+ const sc_char *name;
+
+ /* Get the variable name to match, from overloaded word. */
+ assert(node->word);
+ name = node->word;
+
+ /* Get the variable's value. */
+ if (var_get(vars, name, &type, &vt_rvalue)) {
+ sc_int length;
+
+ /* Compare the value against the current string position. */
+ switch (type) {
+ case VAR_INTEGER: {
+ sc_char value[32];
+
+ /* Compare numeric against the current string position. */
+ sprintf(value, "%ld", vt_rvalue.integer);
+ length = strlen(value);
+ if (strncmp(uip_string + uip_posn, value, length) == 0) {
+ /* Integer match, advance position and return. */
+ uip_posn += length;
+ return TRUE;
+ }
+ break;
+ }
+
+ case VAR_STRING:
+ /* Compare string value against the current string position. */
+ length = strlen(vt_rvalue.string);
+ if (sc_strncasecmp(uip_string + uip_posn,
+ vt_rvalue.string, length) == 0) {
+ /* String match, advance position and return. */
+ uip_posn += length;
+ return TRUE;
+ }
+ break;
+
+ default:
+ sc_fatal("uip_match_variable: invalid variable type, %ld\n", type);
+ }
+ }
+
+ /* No match, or no such variable. */
+ return FALSE;
}
static sc_bool
-uip_match_whitespace (void)
-{
- /* If next character is space, read whitespace and return. */
- if (sc_isspace (uip_string[uip_posn]))
- {
- /* Space match, advance position and return. */
- while (uip_string[uip_posn] != NUL && sc_isspace (uip_string[uip_posn]))
- uip_posn++;
- return TRUE;
- }
-
- /*
- * No match. However, if we're trying to match space, this is a word
- * boundary. So... even though we're not sitting on a space, if the string
- * prior character is whitespace, "double-match" the space.
- *
- * Also, match if we haven't yet matched any text. In effect, this means
- * leading spaces on patterns will be ignored.
- *
- * TODO Is this what we want to happen? It seems harmless, even useful.
- */
- if (uip_posn == 0 || sc_isspace (uip_string[uip_posn - 1]))
- return TRUE;
-
- /*
- * And that's not all. We also want to match whitespace if we're at the end
- * of a string (another word boundary). This will permit patterns that end
- * in optional elements to succeed since options and wildcards always match,
- * even if to no text.
- */
- if (uip_string[uip_posn] == NUL)
- return TRUE;
-
- /* No match. Really. */
- return FALSE;
+uip_match_whitespace(void) {
+ /* If next character is space, read whitespace and return. */
+ if (sc_isspace(uip_string[uip_posn])) {
+ /* Space match, advance position and return. */
+ while (uip_string[uip_posn] != NUL && sc_isspace(uip_string[uip_posn]))
+ uip_posn++;
+ return TRUE;
+ }
+
+ /*
+ * No match. However, if we're trying to match space, this is a word
+ * boundary. So... even though we're not sitting on a space, if the string
+ * prior character is whitespace, "double-match" the space.
+ *
+ * Also, match if we haven't yet matched any text. In effect, this means
+ * leading spaces on patterns will be ignored.
+ *
+ * TODO Is this what we want to happen? It seems harmless, even useful.
+ */
+ if (uip_posn == 0 || sc_isspace(uip_string[uip_posn - 1]))
+ return TRUE;
+
+ /*
+ * And that's not all. We also want to match whitespace if we're at the end
+ * of a string (another word boundary). This will permit patterns that end
+ * in optional elements to succeed since options and wildcards always match,
+ * even if to no text.
+ */
+ if (uip_string[uip_posn] == NUL)
+ return TRUE;
+
+ /* No match. Really. */
+ return FALSE;
}
static sc_bool
-uip_match_list (sc_ptnoderef_t node)
-{
- sc_ptnoderef_t child;
-
- /*
- * If this list is empty, fail the match. This special-case handling is
- * what catches constructed temporary lists for wildcard-like items that
- * don't actually encompass anything.
- */
- if (!node->left_child)
- return FALSE;
-
- /* Match everything listed sequentially. */
- for (child = node->left_child; child; child = child->right_sibling)
- {
- if (!uip_match_node (child))
- {
- /* No match. */
- return FALSE;
- }
- }
-
- /* Matched. */
- return TRUE;
+uip_match_list(sc_ptnoderef_t node) {
+ sc_ptnoderef_t child;
+
+ /*
+ * If this list is empty, fail the match. This special-case handling is
+ * what catches constructed temporary lists for wildcard-like items that
+ * don't actually encompass anything.
+ */
+ if (!node->left_child)
+ return FALSE;
+
+ /* Match everything listed sequentially. */
+ for (child = node->left_child; child; child = child->right_sibling) {
+ if (!uip_match_node(child)) {
+ /* No match. */
+ return FALSE;
+ }
+ }
+
+ /* Matched. */
+ return TRUE;
}
static sc_bool
-uip_match_alternatives (sc_ptnoderef_t node)
-{
- sc_ptnoderef_t child;
- sc_int start_posn, extent;
- sc_bool matched;
-
- /* Note the start position for rewind between tries. */
- start_posn = uip_posn;
-
- /*
- * Try a match on each of the children, looking to see which one moves the
- * position on the furthest. Match on this one. This is a "maximal munch".
- */
- extent = uip_posn;
- matched = FALSE;
- for (child = node->left_child; child; child = child->right_sibling)
- {
- uip_posn = start_posn;
- if (uip_match_node (child))
- {
- /* Matched. */
- matched = TRUE;
- if (uip_posn > extent)
- extent = uip_posn;
- }
- }
-
- /* If matched, set position to extent; if not, back to start. */
- uip_posn = matched ? extent : start_posn;
-
- /* Return match status. */
- return matched;
+uip_match_alternatives(sc_ptnoderef_t node) {
+ sc_ptnoderef_t child;
+ sc_int start_posn, extent;
+ sc_bool matched;
+
+ /* Note the start position for rewind between tries. */
+ start_posn = uip_posn;
+
+ /*
+ * Try a match on each of the children, looking to see which one moves the
+ * position on the furthest. Match on this one. This is a "maximal munch".
+ */
+ extent = uip_posn;
+ matched = FALSE;
+ for (child = node->left_child; child; child = child->right_sibling) {
+ uip_posn = start_posn;
+ if (uip_match_node(child)) {
+ /* Matched. */
+ matched = TRUE;
+ if (uip_posn > extent)
+ extent = uip_posn;
+ }
+ }
+
+ /* If matched, set position to extent; if not, back to start. */
+ uip_posn = matched ? extent : start_posn;
+
+ /* Return match status. */
+ return matched;
}
static sc_bool
-uip_match_choice (sc_ptnoderef_t node)
-{
- /*
- * Return the result of matching alternatives. The choice will therefore
- * fail if none of the alternatives match.
- */
- return uip_match_alternatives (node);
+uip_match_choice(sc_ptnoderef_t node) {
+ /*
+ * Return the result of matching alternatives. The choice will therefore
+ * fail if none of the alternatives match.
+ */
+ return uip_match_alternatives(node);
}
static sc_bool
-uip_match_optional (sc_ptnoderef_t node)
-{
- sc_int start_posn;
- sc_ptnoderef_t list;
- sc_bool matched;
-
- /* Note the start position for rewind on empty match. */
- start_posn = uip_posn;
-
- /*
- * Look ahead to see if we can match to nothing, and still have the main
- * pattern match. If we can, we'll go with this. It's a "minimal munch"-ish
- * strategy, but seems to be what Adrift does in this situation.
- */
- list = uip_new_node (NODE_LIST);
- list->left_child = node->right_sibling;
-
- /* Match on the temporary list. */
- matched = uip_match_node (list);
-
- /* Free the temporary list node. */
- uip_destroy_node (list);
-
- /*
- * If the temporary matched and consumed text, rewind position to match
- * nothing. If it didn't, match alternatives to consume anything that may
- * match our options.
- */
- if (matched && uip_posn > start_posn)
- uip_posn = start_posn;
- else
- uip_match_alternatives (node);
-
- /* Return TRUE no matter what. */
- return TRUE;
+uip_match_optional(sc_ptnoderef_t node) {
+ sc_int start_posn;
+ sc_ptnoderef_t list;
+ sc_bool matched;
+
+ /* Note the start position for rewind on empty match. */
+ start_posn = uip_posn;
+
+ /*
+ * Look ahead to see if we can match to nothing, and still have the main
+ * pattern match. If we can, we'll go with this. It's a "minimal munch"-ish
+ * strategy, but seems to be what Adrift does in this situation.
+ */
+ list = uip_new_node(NODE_LIST);
+ list->left_child = node->right_sibling;
+
+ /* Match on the temporary list. */
+ matched = uip_match_node(list);
+
+ /* Free the temporary list node. */
+ uip_destroy_node(list);
+
+ /*
+ * If the temporary matched and consumed text, rewind position to match
+ * nothing. If it didn't, match alternatives to consume anything that may
+ * match our options.
+ */
+ if (matched && uip_posn > start_posn)
+ uip_posn = start_posn;
+ else
+ uip_match_alternatives(node);
+
+ /* Return TRUE no matter what. */
+ return TRUE;
}
static sc_bool
-uip_match_wildcard (sc_ptnoderef_t node)
-{
- sc_int start_posn, limit, index_;
- sc_bool matched;
- sc_ptnoderef_t list;
-
- /*
- * At least one game uses patterns like "thing******...". Why? Who knows.
- * But if we're in a list of wildcards, and not the first, ignore the call;
- * only the final one needs handling.
- */
- if (node->right_sibling && node->right_sibling->type == NODE_WILDCARD)
- return TRUE;
-
- /* Note the start position for rewind on no match. */
- start_posn = uip_posn;
-
- /*
- * To make life a little easier, we'll match on the tree to the right of
- * this node by constructing a temporary list node, containing stuff to the
- * right of the wildcard, and then matching on that.
- */
- list = uip_new_node (NODE_LIST);
- list->left_child = node->right_sibling;
-
- /*
- * Repeatedly try to match the rest of the tree at successive character
- * positions, and stop if we succeed. This is a "minimal munch", which may
- * or may not be the right thing to be doing here.
- *
- * When scanning forward, take care to include the NUL, needed to match
- * TOK_EOS.
- */
- matched = FALSE;
- limit = strlen (uip_string) + 1;
- for (index_ = uip_posn + 1; index_ < limit; index_++)
- {
- uip_posn = index_;
- if (uip_match_node (list))
- {
- /* Wildcard match at this point. */
- uip_posn = index_;
- matched = TRUE;
- break;
- }
- }
-
- /* Free the temporary list node. */
- uip_destroy_node (list);
-
- /* If we didn't match in the loop, restore position. */
- if (!matched)
- uip_posn = start_posn;
-
- /* Return TRUE whether we matched text or not. */
- return TRUE;
+uip_match_wildcard(sc_ptnoderef_t node) {
+ sc_int start_posn, limit, index_;
+ sc_bool matched;
+ sc_ptnoderef_t list;
+
+ /*
+ * At least one game uses patterns like "thing******...". Why? Who knows.
+ * But if we're in a list of wildcards, and not the first, ignore the call;
+ * only the final one needs handling.
+ */
+ if (node->right_sibling && node->right_sibling->type == NODE_WILDCARD)
+ return TRUE;
+
+ /* Note the start position for rewind on no match. */
+ start_posn = uip_posn;
+
+ /*
+ * To make life a little easier, we'll match on the tree to the right of
+ * this node by constructing a temporary list node, containing stuff to the
+ * right of the wildcard, and then matching on that.
+ */
+ list = uip_new_node(NODE_LIST);
+ list->left_child = node->right_sibling;
+
+ /*
+ * Repeatedly try to match the rest of the tree at successive character
+ * positions, and stop if we succeed. This is a "minimal munch", which may
+ * or may not be the right thing to be doing here.
+ *
+ * When scanning forward, take care to include the NUL, needed to match
+ * TOK_EOS.
+ */
+ matched = FALSE;
+ limit = strlen(uip_string) + 1;
+ for (index_ = uip_posn + 1; index_ < limit; index_++) {
+ uip_posn = index_;
+ if (uip_match_node(list)) {
+ /* Wildcard match at this point. */
+ uip_posn = index_;
+ matched = TRUE;
+ break;
+ }
+ }
+
+ /* Free the temporary list node. */
+ uip_destroy_node(list);
+
+ /* If we didn't match in the loop, restore position. */
+ if (!matched)
+ uip_posn = start_posn;
+
+ /* Return TRUE whether we matched text or not. */
+ return TRUE;
}
@@ -1185,100 +1100,92 @@ uip_match_wildcard (sc_ptnoderef_t node)
* Attempt to match a number, or a word, from the string.
*/
static sc_bool
-uip_match_number (void)
-{
- const sc_gameref_t game = uip_get_game ();
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int number;
-
- /* Attempt to read a number from input. */
- if (sscanf (uip_string + uip_posn, "%ld", &number) == 1)
- {
- /* Advance position over the number. */
- while (uip_string[uip_posn] == MINUS || uip_string[uip_posn] == PLUS)
- uip_posn++;
- while (sc_isdigit (uip_string[uip_posn]))
- uip_posn++;
-
- /* Set number reference in variables and return. */
- var_set_ref_number (vars, number);
- return TRUE;
- }
-
- /* No match. */
- return FALSE;
+uip_match_number(void) {
+ const sc_gameref_t game = uip_get_game();
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int number;
+
+ /* Attempt to read a number from input. */
+ if (sscanf(uip_string + uip_posn, "%ld", &number) == 1) {
+ /* Advance position over the number. */
+ while (uip_string[uip_posn] == MINUS || uip_string[uip_posn] == PLUS)
+ uip_posn++;
+ while (sc_isdigit(uip_string[uip_posn]))
+ uip_posn++;
+
+ /* Set number reference in variables and return. */
+ var_set_ref_number(vars, number);
+ return TRUE;
+ }
+
+ /* No match. */
+ return FALSE;
}
static sc_bool
-uip_match_text (sc_ptnoderef_t node)
-{
- const sc_gameref_t game = uip_get_game ();
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int start_posn, limit, index_;
- sc_bool matched;
- sc_ptnoderef_t list;
-
- /* Note the start position for rewind on no match. */
- start_posn = uip_posn;
-
- /*
- * As with wildcards, create a temporary list of the stuff to the right of
- * the reference node, and match on that.
- */
- list = uip_new_node (NODE_LIST);
- list->left_child = node->right_sibling;
-
- /*
- * Again, as with wildcards, repeatedly try to match the rest of the tree at
- * successive character positions, stopping if we succeed.
- */
- matched = FALSE;
- limit = strlen (uip_string) + 1;
- for (index_ = uip_posn + 1; index_ < limit; index_++)
- {
- uip_posn = index_;
- if (uip_match_node (list))
- {
- /* Text reference match at this point. */
- uip_posn = index_;
- matched = TRUE;
- break;
- }
- }
-
- /* Free the temporary list node. */
- uip_destroy_node (list);
-
- /* See if we found a match in the loop. */
- if (matched)
- {
- sc_char *string;
-
- /* Found a match; create a string and save the text. */
- string = (sc_char *)sc_malloc (uip_posn - start_posn + 1);
- memcpy (string, uip_string + start_posn, uip_posn - start_posn);
- string[uip_posn - start_posn] = NUL;
-
- /*
- * Adrift seems to save referenced text as all-lowercase; we need to do
- * the same.
- */
- for (index_ = 0; string[index_] != NUL; index_++)
- string[index_] = sc_tolower (string[index_]);
- var_set_ref_text (vars, string);
- sc_free (string);
-
- /* Return TRUE since we matched text. */
- return TRUE;
- }
- else
- {
- /* We didn't match in the loop; restore position. */
- uip_posn = start_posn;
-
- /* Return FALSE on no match. */
- return FALSE;
- }
+uip_match_text(sc_ptnoderef_t node) {
+ const sc_gameref_t game = uip_get_game();
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int start_posn, limit, index_;
+ sc_bool matched;
+ sc_ptnoderef_t list;
+
+ /* Note the start position for rewind on no match. */
+ start_posn = uip_posn;
+
+ /*
+ * As with wildcards, create a temporary list of the stuff to the right of
+ * the reference node, and match on that.
+ */
+ list = uip_new_node(NODE_LIST);
+ list->left_child = node->right_sibling;
+
+ /*
+ * Again, as with wildcards, repeatedly try to match the rest of the tree at
+ * successive character positions, stopping if we succeed.
+ */
+ matched = FALSE;
+ limit = strlen(uip_string) + 1;
+ for (index_ = uip_posn + 1; index_ < limit; index_++) {
+ uip_posn = index_;
+ if (uip_match_node(list)) {
+ /* Text reference match at this point. */
+ uip_posn = index_;
+ matched = TRUE;
+ break;
+ }
+ }
+
+ /* Free the temporary list node. */
+ uip_destroy_node(list);
+
+ /* See if we found a match in the loop. */
+ if (matched) {
+ sc_char *string;
+
+ /* Found a match; create a string and save the text. */
+ string = (sc_char *)sc_malloc(uip_posn - start_posn + 1);
+ memcpy(string, uip_string + start_posn, uip_posn - start_posn);
+ string[uip_posn - start_posn] = NUL;
+
+ /*
+ * Adrift seems to save referenced text as all-lowercase; we need to do
+ * the same.
+ */
+ for (index_ = 0; string[index_] != NUL; index_++)
+ string[index_] = sc_tolower(string[index_]);
+ var_set_ref_text(vars, string);
+ sc_free(string);
+
+ /* Return TRUE since we matched text. */
+ return TRUE;
+ } else {
+ /* We didn't match in the loop; restore position. */
+ uip_posn = start_posn;
+
+ /* Return FALSE on no match. */
+ return FALSE;
+ }
}
@@ -1289,25 +1196,24 @@ uip_match_text (sc_ptnoderef_t node)
* %character% and %object% matchers. Returns the revised string position.
*/
static sc_int
-uip_skip_article (const sc_char *string, sc_int start)
-{
- sc_int posn;
-
- /* Skip over articles. */
- posn = start;
- if (sc_compare_word (string + posn, "a", 1))
- posn += 1;
- else if (sc_compare_word (string + posn, "an", 2))
- posn += 2;
- else if (sc_compare_word (string + posn, "the", 3))
- posn += 3;
- else if (sc_compare_word (string + posn, "some", 4))
- posn += 4;
-
- /* Skip any whitespace, and return. */
- while (sc_isspace (string[posn]) && string[posn] != NUL)
- posn++;
- return posn;
+uip_skip_article(const sc_char *string, sc_int start) {
+ sc_int posn;
+
+ /* Skip over articles. */
+ posn = start;
+ if (sc_compare_word(string + posn, "a", 1))
+ posn += 1;
+ else if (sc_compare_word(string + posn, "an", 2))
+ posn += 2;
+ else if (sc_compare_word(string + posn, "the", 3))
+ posn += 3;
+ else if (sc_compare_word(string + posn, "some", 4))
+ posn += 4;
+
+ /* Skip any whitespace, and return. */
+ while (sc_isspace(string[posn]) && string[posn] != NUL)
+ posn++;
+ return posn;
}
@@ -1320,51 +1226,49 @@ uip_skip_article (const sc_char *string, sc_int start)
* the words passed in (the new value of uip_posn on match).
*/
static sc_int
-uip_compare_reference (const sc_char *words)
-{
- sc_int wpos, posn;
-
- /* Skip articles and lead in space on words and string. */
- wpos = uip_skip_article (words, 0);
- posn = uip_skip_article (uip_string, uip_posn);
-
- /* Match characters from words with the string at position. */
- while (TRUE)
- {
- /* Any character mismatch means no words match. */
- if (sc_tolower (words[wpos]) != sc_tolower (uip_string[posn]))
- return 0;
-
- /* Move to next character in each. */
- wpos++;
- posn++;
-
- /*
- * If at space, advance over whitespace in words list. Stop when we
- * hit the end of the words list.
- */
- while (sc_isspace (words[wpos]) && words[wpos] != NUL)
- wpos++;
- if (words[wpos] == NUL)
- break;
-
- /*
- * About to match another word, so advance over whitespace in the
- * current string too.
- */
- while (sc_isspace (uip_string[posn]) && uip_string[posn] != NUL)
- posn++;
- }
-
- /*
- * We reached the end of words. If we're at the end of the match string, or
- * at spaces, we've matched.
- */
- if (sc_isspace (uip_string[posn]) || uip_string[posn] == NUL)
- return posn;
-
- /* More text after the match, so it's not quite a match. */
- return 0;
+uip_compare_reference(const sc_char *words) {
+ sc_int wpos, posn;
+
+ /* Skip articles and lead in space on words and string. */
+ wpos = uip_skip_article(words, 0);
+ posn = uip_skip_article(uip_string, uip_posn);
+
+ /* Match characters from words with the string at position. */
+ while (TRUE) {
+ /* Any character mismatch means no words match. */
+ if (sc_tolower(words[wpos]) != sc_tolower(uip_string[posn]))
+ return 0;
+
+ /* Move to next character in each. */
+ wpos++;
+ posn++;
+
+ /*
+ * If at space, advance over whitespace in words list. Stop when we
+ * hit the end of the words list.
+ */
+ while (sc_isspace(words[wpos]) && words[wpos] != NUL)
+ wpos++;
+ if (words[wpos] == NUL)
+ break;
+
+ /*
+ * About to match another word, so advance over whitespace in the
+ * current string too.
+ */
+ while (sc_isspace(uip_string[posn]) && uip_string[posn] != NUL)
+ posn++;
+ }
+
+ /*
+ * We reached the end of words. If we're at the end of the match string, or
+ * at spaces, we've matched.
+ */
+ if (sc_isspace(uip_string[posn]) || uip_string[posn] == NUL)
+ return posn;
+
+ /* More text after the match, so it's not quite a match. */
+ return 0;
}
@@ -1376,28 +1280,27 @@ uip_compare_reference (const sc_char *words)
* Returns the extent of the match, or zero if no match.
*/
static sc_int
-uip_compare_prefixed_name (const sc_char *prefix, const sc_char *name)
-{
- sc_char buffer[UIP_SHORT_WORD_SIZE + UIP_SHORT_WORD_SIZE + 1];
- sc_char *string;
- sc_int required, extent;
-
- /* Create a prefixed string, using the local buffer if possible. */
- required = strlen (prefix) + strlen (name) + 2;
- string = required > (sc_int) sizeof (buffer) ? (sc_char *)sc_malloc (required) : buffer;
- sprintf (string, "%s %s", prefix, name);
-
- /* Check against the prefixed name first, free string if required. */
- extent = uip_compare_reference (string);
- if (string != buffer)
- sc_free (string);
-
- /* If no match there, retry with just the plain name. */
- if (extent == 0)
- extent = uip_compare_reference (name);
-
- /* Return the count of characters consumed in matching. */
- return extent;
+uip_compare_prefixed_name(const sc_char *prefix, const sc_char *name) {
+ sc_char buffer[UIP_SHORT_WORD_SIZE + UIP_SHORT_WORD_SIZE + 1];
+ sc_char *string;
+ sc_int required, extent;
+
+ /* Create a prefixed string, using the local buffer if possible. */
+ required = strlen(prefix) + strlen(name) + 2;
+ string = required > (sc_int) sizeof(buffer) ? (sc_char *)sc_malloc(required) : buffer;
+ sprintf(string, "%s %s", prefix, name);
+
+ /* Check against the prefixed name first, free string if required. */
+ extent = uip_compare_reference(string);
+ if (string != buffer)
+ sc_free(string);
+
+ /* If no match there, retry with just the plain name. */
+ if (extent == 0)
+ extent = uip_compare_reference(name);
+
+ /* Return the count of characters consumed in matching. */
+ return extent;
}
@@ -1409,32 +1312,31 @@ uip_compare_prefixed_name (const sc_char *prefix, const sc_char *name)
* "table".
*/
static sc_bool
-uip_match_remainder (sc_ptnoderef_t node, sc_int extent)
-{
- sc_ptnoderef_t list;
- sc_int start_posn;
- sc_bool matched;
-
- /* Note the start position, then advance to the given extent. */
- start_posn = uip_posn;
- uip_posn = extent;
-
- /*
- * Try to match everything after the node passed in, at this position in the
- * string.
- */
- list = uip_new_node (NODE_LIST);
- list->left_child = node->right_sibling;
-
- /* Match on the temporary list. */
- matched = uip_match_node (list);
-
- /* Free the temporary list node, and restore position. */
- uip_destroy_node (list);
- uip_posn = start_posn;
-
- /* Return TRUE if the pattern remainder matched. */
- return matched;
+uip_match_remainder(sc_ptnoderef_t node, sc_int extent) {
+ sc_ptnoderef_t list;
+ sc_int start_posn;
+ sc_bool matched;
+
+ /* Note the start position, then advance to the given extent. */
+ start_posn = uip_posn;
+ uip_posn = extent;
+
+ /*
+ * Try to match everything after the node passed in, at this position in the
+ * string.
+ */
+ list = uip_new_node(NODE_LIST);
+ list->left_child = node->right_sibling;
+
+ /* Match on the temporary list. */
+ matched = uip_match_node(list);
+
+ /* Free the temporary list node, and restore position. */
+ uip_destroy_node(list);
+ uip_posn = start_posn;
+
+ /* Return TRUE if the pattern remainder matched. */
+ return matched;
}
@@ -1446,100 +1348,94 @@ uip_match_remainder (sc_ptnoderef_t node, sc_int extent)
* for any that match. The final one to match is also stored in variables.
*/
static sc_bool
-uip_match_character (sc_ptnoderef_t node)
-{
- const sc_gameref_t game = uip_get_game ();
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int npc_count, npc, max_extent;
-
- if (uip_trace)
- sc_trace ("UIParser: attempting to match %%character%%\n");
-
- /* Clear all current character references. */
- gs_clear_npc_references (game);
-
- /* Iterate characters, looking for a name or alias match. */
- max_extent = 0;
- npc_count = gs_npc_count (game);
- for (npc = 0; npc < npc_count; npc++)
- {
- sc_vartype_t vt_key[4];
- const sc_char *prefix, *name;
- sc_int alias_count, alias, extent;
-
- /* Get the NPC's prefix and name. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- if (uip_trace)
- sc_trace ("UIParser: trying %s\n", name);
-
- /* Compare this name, both prefixed and not. */
- extent = uip_compare_prefixed_name (prefix, name);
- if (extent > 0 && uip_match_remainder (node, extent))
- {
- if (uip_trace)
- sc_trace ("UIParser: matched\n");
-
- /* Increase the maximum match extent if required. */
- max_extent = (extent > max_extent) ? extent : max_extent;
-
- /* Save match in variables and game. */
- var_set_ref_character (vars, npc);
- game->npc_references[npc] = TRUE;
- }
-
- /* Now compare against all NPC aliases. */
- vt_key[2].string = "Alias";
- alias_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- for (alias = 0; alias < alias_count; alias++)
- {
- const sc_char *alias_name;
-
- /*
- * Get the NPC alias. Version 3.9 games introduce empty aliases,
- * so check here.
- */
- vt_key[3].integer = alias;
- alias_name = prop_get_string (bundle, "S<-sisi", vt_key);
- if (sc_strempty (alias_name))
- continue;
-
- if (uip_trace)
- sc_trace ("UIParser: trying alias %s\n", alias_name);
-
- /* Compare this alias name, both prefixed and not. */
- extent = uip_compare_prefixed_name (prefix, alias_name);
- if (extent > 0 && uip_match_remainder (node, extent))
- {
- if (uip_trace)
- sc_trace ("UIParser: matched\n");
-
- /* Increase the maximum match extent if required. */
- max_extent = (extent > max_extent) ? extent : max_extent;
-
- /* Save match in variables and game. */
- var_set_ref_character (vars, npc);
- game->npc_references[npc] = TRUE;
- }
- }
- }
-
- /* On match, advance position and return successfully. */
- if (max_extent > 0)
- {
- uip_posn = max_extent;
- return TRUE;
- }
-
- /* No match. */
- return FALSE;
+uip_match_character(sc_ptnoderef_t node) {
+ const sc_gameref_t game = uip_get_game();
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int npc_count, npc, max_extent;
+
+ if (uip_trace)
+ sc_trace("UIParser: attempting to match %%character%%\n");
+
+ /* Clear all current character references. */
+ gs_clear_npc_references(game);
+
+ /* Iterate characters, looking for a name or alias match. */
+ max_extent = 0;
+ npc_count = gs_npc_count(game);
+ for (npc = 0; npc < npc_count; npc++) {
+ sc_vartype_t vt_key[4];
+ const sc_char *prefix, *name;
+ sc_int alias_count, alias, extent;
+
+ /* Get the NPC's prefix and name. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ if (uip_trace)
+ sc_trace("UIParser: trying %s\n", name);
+
+ /* Compare this name, both prefixed and not. */
+ extent = uip_compare_prefixed_name(prefix, name);
+ if (extent > 0 && uip_match_remainder(node, extent)) {
+ if (uip_trace)
+ sc_trace("UIParser: matched\n");
+
+ /* Increase the maximum match extent if required. */
+ max_extent = (extent > max_extent) ? extent : max_extent;
+
+ /* Save match in variables and game. */
+ var_set_ref_character(vars, npc);
+ game->npc_references[npc] = TRUE;
+ }
+
+ /* Now compare against all NPC aliases. */
+ vt_key[2].string = "Alias";
+ alias_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ for (alias = 0; alias < alias_count; alias++) {
+ const sc_char *alias_name;
+
+ /*
+ * Get the NPC alias. Version 3.9 games introduce empty aliases,
+ * so check here.
+ */
+ vt_key[3].integer = alias;
+ alias_name = prop_get_string(bundle, "S<-sisi", vt_key);
+ if (sc_strempty(alias_name))
+ continue;
+
+ if (uip_trace)
+ sc_trace("UIParser: trying alias %s\n", alias_name);
+
+ /* Compare this alias name, both prefixed and not. */
+ extent = uip_compare_prefixed_name(prefix, alias_name);
+ if (extent > 0 && uip_match_remainder(node, extent)) {
+ if (uip_trace)
+ sc_trace("UIParser: matched\n");
+
+ /* Increase the maximum match extent if required. */
+ max_extent = (extent > max_extent) ? extent : max_extent;
+
+ /* Save match in variables and game. */
+ var_set_ref_character(vars, npc);
+ game->npc_references[npc] = TRUE;
+ }
+ }
+ }
+
+ /* On match, advance position and return successfully. */
+ if (max_extent > 0) {
+ uip_posn = max_extent;
+ return TRUE;
+ }
+
+ /* No match. */
+ return FALSE;
}
@@ -1551,100 +1447,94 @@ uip_match_character (sc_ptnoderef_t node)
* for any that match. The final one to match is also stored in variables.
*/
static sc_bool
-uip_match_object (sc_ptnoderef_t node)
-{
- const sc_gameref_t game = uip_get_game ();
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int object_count, object, max_extent;
-
- if (uip_trace)
- sc_trace ("UIParser: attempting to match %%object%%\n");
-
- /* Clear all current object references. */
- gs_clear_object_references (game);
-
- /* Iterate objects, looking for a name or alias match. */
- max_extent = 0;
- object_count = gs_object_count (game);
- for (object = 0; object < object_count; object++)
- {
- sc_vartype_t vt_key[4];
- const sc_char *prefix, *name;
- sc_int alias_count, alias, extent;
-
- /* Get the object's prefix and name. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- if (uip_trace)
- sc_trace ("UIParser: trying %s\n", name);
-
- /* Compare this name, both prefixed and not. */
- extent = uip_compare_prefixed_name (prefix, name);
- if (extent > 0 && uip_match_remainder (node, extent))
- {
- if (uip_trace)
- sc_trace ("UIParser: matched\n");
-
- /* Increase the maximum match extent if required. */
- max_extent = (extent > max_extent) ? extent : max_extent;
-
- /* Save match in variables and game. */
- var_set_ref_object (vars, object);
- game->object_references[object] = TRUE;
- }
-
- /* Now compare against all object aliases. */
- vt_key[2].string = "Alias";
- alias_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- for (alias = 0; alias < alias_count; alias++)
- {
- const sc_char *alias_name;
-
- /*
- * Get the object alias. Version 3.9 games introduce empty aliases,
- * so check here.
- */
- vt_key[3].integer = alias;
- alias_name = prop_get_string (bundle, "S<-sisi", vt_key);
- if (sc_strempty (alias_name))
- continue;
-
- if (uip_trace)
- sc_trace ("UIParser: trying alias %s\n", alias_name);
-
- /* Compare this alias name, both prefixed and not. */
- extent = uip_compare_prefixed_name (prefix, alias_name);
- if (extent > 0 && uip_match_remainder (node, extent))
- {
- if (uip_trace)
- sc_trace ("UIParser: matched\n");
-
- /* Increase the maximum match extent if required. */
- max_extent = (extent > max_extent) ? extent : max_extent;
-
- /* Save match in variables and game. */
- var_set_ref_object (vars, object);
- game->object_references[object] = TRUE;
- }
- }
- }
-
- /* On match, advance position and return successfully. */
- if (max_extent > 0)
- {
- uip_posn = max_extent;
- return TRUE;
- }
-
- /* No match. */
- return FALSE;
+uip_match_object(sc_ptnoderef_t node) {
+ const sc_gameref_t game = uip_get_game();
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int object_count, object, max_extent;
+
+ if (uip_trace)
+ sc_trace("UIParser: attempting to match %%object%%\n");
+
+ /* Clear all current object references. */
+ gs_clear_object_references(game);
+
+ /* Iterate objects, looking for a name or alias match. */
+ max_extent = 0;
+ object_count = gs_object_count(game);
+ for (object = 0; object < object_count; object++) {
+ sc_vartype_t vt_key[4];
+ const sc_char *prefix, *name;
+ sc_int alias_count, alias, extent;
+
+ /* Get the object's prefix and name. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ if (uip_trace)
+ sc_trace("UIParser: trying %s\n", name);
+
+ /* Compare this name, both prefixed and not. */
+ extent = uip_compare_prefixed_name(prefix, name);
+ if (extent > 0 && uip_match_remainder(node, extent)) {
+ if (uip_trace)
+ sc_trace("UIParser: matched\n");
+
+ /* Increase the maximum match extent if required. */
+ max_extent = (extent > max_extent) ? extent : max_extent;
+
+ /* Save match in variables and game. */
+ var_set_ref_object(vars, object);
+ game->object_references[object] = TRUE;
+ }
+
+ /* Now compare against all object aliases. */
+ vt_key[2].string = "Alias";
+ alias_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ for (alias = 0; alias < alias_count; alias++) {
+ const sc_char *alias_name;
+
+ /*
+ * Get the object alias. Version 3.9 games introduce empty aliases,
+ * so check here.
+ */
+ vt_key[3].integer = alias;
+ alias_name = prop_get_string(bundle, "S<-sisi", vt_key);
+ if (sc_strempty(alias_name))
+ continue;
+
+ if (uip_trace)
+ sc_trace("UIParser: trying alias %s\n", alias_name);
+
+ /* Compare this alias name, both prefixed and not. */
+ extent = uip_compare_prefixed_name(prefix, alias_name);
+ if (extent > 0 && uip_match_remainder(node, extent)) {
+ if (uip_trace)
+ sc_trace("UIParser: matched\n");
+
+ /* Increase the maximum match extent if required. */
+ max_extent = (extent > max_extent) ? extent : max_extent;
+
+ /* Save match in variables and game. */
+ var_set_ref_object(vars, object);
+ game->object_references[object] = TRUE;
+ }
+ }
+ }
+
+ /* On match, advance position and return successfully. */
+ if (max_extent > 0) {
+ uip_posn = max_extent;
+ return TRUE;
+ }
+
+ /* No match. */
+ return FALSE;
}
@@ -1656,54 +1546,52 @@ uip_match_object (sc_ptnoderef_t node)
* position unchanged.
*/
static sc_bool
-uip_match_node (sc_ptnoderef_t node)
-{
- sc_bool match = FALSE;
-
- /* Match depending on node type. */
- switch (node->type)
- {
- case NODE_EOS:
- match = uip_match_eos ();
- break;
- case NODE_WORD:
- match = uip_match_word (node);
- break;
- case NODE_VARIABLE:
- match = uip_match_variable (node);
- break;
- case NODE_WHITESPACE:
- match = uip_match_whitespace ();
- break;
- case NODE_LIST:
- match = uip_match_list (node);
- break;
- case NODE_CHOICE:
- match = uip_match_choice (node);
- break;
- case NODE_OPTIONAL:
- match = uip_match_optional (node);
- break;
- case NODE_WILDCARD:
- match = uip_match_wildcard (node);
- break;
- case NODE_CHARACTER_REFERENCE:
- match = uip_match_character (node);
- break;
- case NODE_OBJECT_REFERENCE:
- match = uip_match_object (node);
- break;
- case NODE_NUMBER_REFERENCE:
- match = uip_match_number ();
- break;
- case NODE_TEXT_REFERENCE:
- match = uip_match_text (node);
- break;
- default:
- sc_fatal ("uip_match_node: invalid type, %ld\n", (sc_int) node->type);
- }
-
- return match;
+uip_match_node(sc_ptnoderef_t node) {
+ sc_bool match = FALSE;
+
+ /* Match depending on node type. */
+ switch (node->type) {
+ case NODE_EOS:
+ match = uip_match_eos();
+ break;
+ case NODE_WORD:
+ match = uip_match_word(node);
+ break;
+ case NODE_VARIABLE:
+ match = uip_match_variable(node);
+ break;
+ case NODE_WHITESPACE:
+ match = uip_match_whitespace();
+ break;
+ case NODE_LIST:
+ match = uip_match_list(node);
+ break;
+ case NODE_CHOICE:
+ match = uip_match_choice(node);
+ break;
+ case NODE_OPTIONAL:
+ match = uip_match_optional(node);
+ break;
+ case NODE_WILDCARD:
+ match = uip_match_wildcard(node);
+ break;
+ case NODE_CHARACTER_REFERENCE:
+ match = uip_match_character(node);
+ break;
+ case NODE_OBJECT_REFERENCE:
+ match = uip_match_object(node);
+ break;
+ case NODE_NUMBER_REFERENCE:
+ match = uip_match_number();
+ break;
+ case NODE_TEXT_REFERENCE:
+ match = uip_match_text(node);
+ break;
+ default:
+ sc_fatal("uip_match_node: invalid type, %ld\n", (sc_int) node->type);
+ }
+
+ return match;
}
@@ -1718,33 +1606,31 @@ uip_match_node (sc_ptnoderef_t node)
* buffer passed in), or call uip_free_cleansed_string.
*/
static sc_char *
-uip_cleanse_string (const sc_char *original, sc_char *buffer, sc_int length)
-{
- sc_int required;
- sc_char *string;
-
- /*
- * Use the supplied buffer if it is long enough, otherwise allocate, and
- * copy the string.
- */
- required = strlen (original) + 1;
- string = (required < length) ? buffer : (sc_char *)sc_malloc (required);
- strcpy (string, original);
-
- /* Trim, and return the string. */
- sc_trim_string (string);
- return string;
+uip_cleanse_string(const sc_char *original, sc_char *buffer, sc_int length) {
+ sc_int required;
+ sc_char *string;
+
+ /*
+ * Use the supplied buffer if it is long enough, otherwise allocate, and
+ * copy the string.
+ */
+ required = strlen(original) + 1;
+ string = (required < length) ? buffer : (sc_char *)sc_malloc(required);
+ strcpy(string, original);
+
+ /* Trim, and return the string. */
+ sc_trim_string(string);
+ return string;
}
static sc_char *
-uip_free_cleansed_string (sc_char *string, const sc_char *buffer)
-{
- /* Free if the string was allocated by the function above. */
- if (string != buffer)
- sc_free (string);
-
- /* Always returns NULL, for the syntactic convenience of the caller. */
- return NULL;
+uip_free_cleansed_string(sc_char *string, const sc_char *buffer) {
+ /* Free if the string was allocated by the function above. */
+ if (string != buffer)
+ sc_free(string);
+
+ /* Always returns NULL, for the syntactic convenience of the caller. */
+ return NULL;
}
@@ -1754,9 +1640,8 @@ uip_free_cleansed_string (sc_char *string, const sc_char *buffer)
* Set pattern match tracing on/off.
*/
void
-uip_debug_trace (sc_bool flag)
-{
- uip_trace = flag;
+uip_debug_trace(sc_bool flag) {
+ uip_trace = flag;
}
@@ -1768,60 +1653,56 @@ uip_debug_trace (sc_bool flag)
* need to copy each of the pattern and match strings passed in.
*/
sc_bool
-uip_match (const sc_char *pattern, const sc_char *string, sc_gameref_t game)
-{
- static sc_char *cleansed; /* For setjmp safety. */
- sc_char buffer[UIP_ALLOCATION_AVOIDANCE_SIZE];
- sc_bool match;
- assert (pattern && string && game);
-
- /* Start tokenizer. */
- cleansed = uip_cleanse_string (pattern, buffer, sizeof (buffer));
- if (uip_trace)
- sc_trace ("UIParser: pattern \"%s\"\n", cleansed);
- uip_tokenize_start (cleansed);
-
- /* Try parsing the pattern, and catch errors. */
- if (setjmp (uip_parse_error) == 0)
- {
- /* Parse the pattern into a match tree. */
- uip_parse_lookahead = uip_next_token ();
- uip_parse_tree = uip_new_node (NODE_LIST);
- uip_parse_list (uip_parse_tree);
- uip_tokenize_end ();
- cleansed = uip_free_cleansed_string (cleansed, buffer);
- }
- else
- {
- /* Parse error -- clean up and fail. */
- uip_tokenize_end ();
- uip_destroy_tree (uip_parse_tree);
- uip_parse_tree = NULL;
- cleansed = uip_free_cleansed_string (cleansed, buffer);
- return FALSE;
- }
-
- /* Dump out the pattern tree if requested. */
- if (if_get_trace_flag (SC_DUMP_PARSER_TREES))
- uip_debug_dump ();
-
- /* Match the string to the pattern tree. */
- cleansed = uip_cleanse_string (string, buffer, sizeof (buffer));
- if (uip_trace)
- sc_trace ("UIParser: string \"%s\"\n", cleansed);
- uip_match_start (cleansed, game);
- match = uip_match_node (uip_parse_tree);
-
- /* Clean up matching and free the parsed pattern tree. */
- uip_match_end ();
- cleansed = uip_free_cleansed_string (cleansed, buffer);
- uip_destroy_tree (uip_parse_tree);
- uip_parse_tree = NULL;
-
- /* Return result of matching. */
- if (uip_trace)
- sc_trace ("UIParser: %s\n", match ? "MATCHED!" : "No match");
- return match;
+uip_match(const sc_char *pattern, const sc_char *string, sc_gameref_t game) {
+ static sc_char *cleansed; /* For setjmp safety. */
+ sc_char buffer[UIP_ALLOCATION_AVOIDANCE_SIZE];
+ sc_bool match;
+ assert(pattern && string && game);
+
+ /* Start tokenizer. */
+ cleansed = uip_cleanse_string(pattern, buffer, sizeof(buffer));
+ if (uip_trace)
+ sc_trace("UIParser: pattern \"%s\"\n", cleansed);
+ uip_tokenize_start(cleansed);
+
+ /* Try parsing the pattern, and catch errors. */
+ if (setjmp(uip_parse_error) == 0) {
+ /* Parse the pattern into a match tree. */
+ uip_parse_lookahead = uip_next_token();
+ uip_parse_tree = uip_new_node(NODE_LIST);
+ uip_parse_list(uip_parse_tree);
+ uip_tokenize_end();
+ cleansed = uip_free_cleansed_string(cleansed, buffer);
+ } else {
+ /* Parse error -- clean up and fail. */
+ uip_tokenize_end();
+ uip_destroy_tree(uip_parse_tree);
+ uip_parse_tree = NULL;
+ cleansed = uip_free_cleansed_string(cleansed, buffer);
+ return FALSE;
+ }
+
+ /* Dump out the pattern tree if requested. */
+ if (if_get_trace_flag(SC_DUMP_PARSER_TREES))
+ uip_debug_dump();
+
+ /* Match the string to the pattern tree. */
+ cleansed = uip_cleanse_string(string, buffer, sizeof(buffer));
+ if (uip_trace)
+ sc_trace("UIParser: string \"%s\"\n", cleansed);
+ uip_match_start(cleansed, game);
+ match = uip_match_node(uip_parse_tree);
+
+ /* Clean up matching and free the parsed pattern tree. */
+ uip_match_end();
+ cleansed = uip_free_cleansed_string(cleansed, buffer);
+ uip_destroy_tree(uip_parse_tree);
+ uip_parse_tree = NULL;
+
+ /* Return result of matching. */
+ if (uip_trace)
+ sc_trace("UIParser: %s\n", match ? "MATCHED!" : "No match");
+ return match;
}
@@ -1833,157 +1714,137 @@ uip_match (const sc_char *pattern, const sc_char *string, sc_gameref_t game)
* return string is malloc'ed, so the caller needs to remember to free it.
*/
sc_char *
-uip_replace_pronouns (sc_gameref_t game, const sc_char *string)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_int buffer_allocation;
- sc_char *buffer;
- const sc_char *current;
- assert (string);
-
- if (uip_trace)
- sc_trace ("UIParser: pronoun search \"%s\"\n", string);
-
- /* Begin with a NULL buffer for lazy allocation. */
- buffer_allocation = 0;
- buffer = NULL;
-
- /* Search for pronouns until no more string remains. */
- current = string + strspn (string, WHITESPACE);
- while (current[0] != NUL)
- {
- sc_vartype_t vt_key[3];
- sc_int object, npc, extent;
- const sc_char *prefix, *name;
-
- /* Initially, no object or NPC, no names, and a zero extent. */
- object = npc = -1;
- prefix = name = NULL;
- extent = 0;
-
- /*
- * Search for pronouns where we have an assigned object or NPC. We
- * can't be sure of getting plurality right, and it's not always
- * intuitive even in English -- is "a pair of scissors" an "it", or
- * a "them"? Because of this, we just treat "it" and "them" equally
- * for now.
- */
- if (game->it_object != -1 && sc_compare_word (current, "it", 2))
- {
- object = game->it_object;
- extent = 2;
- }
- else if (game->it_object != -1 && sc_compare_word (current, "them", 4))
- {
- object = game->it_object;
- extent = 4;
- }
- else if (game->him_npc != -1 && sc_compare_word (current, "him", 3))
- {
- npc = game->him_npc;
- extent = 3;
- }
- else if (game->her_npc != -1 && sc_compare_word (current, "her", 3))
- {
- npc = game->her_npc;
- extent = 3;
- }
- else if (game->it_npc != -1 && sc_compare_word (current, "it", 2))
- {
- npc = game->it_npc;
- extent = 2;
- }
-
- /* Assign prefix and name to the full object or NPC name, if any. */
- if (object > -1)
- {
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- }
- else if (npc > -1)
- {
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- }
-
- /*
- * If a pronoun was found, prefix and name indicate what to insert, and
- * extent shows how much of the buffer to replace with them.
- */
- if (prefix && name && extent > 0)
- {
- sc_char *position;
- sc_int prefix_length, name_length, length, final;
-
- /*
- * If not yet allocated, allocate a buffer now, and copy the input
- * string into it. Then switch current to the equivalent location
- * in the allocated buffer; basic copy-on-write.
- */
- if (!buffer)
- {
- buffer_allocation = strlen (string) + 1;
- buffer = (sc_char *)sc_malloc (buffer_allocation);
- strcpy (buffer, string);
- current = buffer + (current - string);
- }
-
- /*
- * If necessary, grow the output buffer for the replacement,
- * remembering to adjust current for the new buffer allocated.
- * At the same time, note the last character index for the move.
- */
- prefix_length = strlen (prefix);
- name_length = strlen (name);
- length = prefix_length + name_length + 1;
- if (length > extent)
- {
- sc_int offset;
-
- offset = current - buffer;
- buffer_allocation += length - extent;
- buffer = (sc_char *)sc_realloc (buffer, buffer_allocation);
- current = buffer + offset;
- final = length;
- }
- else
- final = extent;
-
- /* Insert the replacement strings into the buffer. */
- position = buffer + (current - buffer);
- memmove (position + length,
- position + extent,
- buffer_allocation - (current - buffer) - final);
- memcpy (position, prefix, prefix_length);
- position[prefix_length] = ' ';
- memcpy (position + prefix_length + 1, name, name_length);
-
- /* Adjust current to skip over the replacement. */
- current += length;
-
- if (uip_trace)
- sc_trace ("Parser: pronoun \"%s\"\n", buffer);
- }
- else
- {
- /* If no match, advance current over the unmatched word. */
- current += strcspn (current, WHITESPACE);
- }
-
- /* Set current to the next word start. */
- current += strspn (current, WHITESPACE);
- }
-
- /* Return the final string, or NULL if no pronoun replacements. */
- return buffer;
+uip_replace_pronouns(sc_gameref_t game, const sc_char *string) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_int buffer_allocation;
+ sc_char *buffer;
+ const sc_char *current;
+ assert(string);
+
+ if (uip_trace)
+ sc_trace("UIParser: pronoun search \"%s\"\n", string);
+
+ /* Begin with a NULL buffer for lazy allocation. */
+ buffer_allocation = 0;
+ buffer = NULL;
+
+ /* Search for pronouns until no more string remains. */
+ current = string + strspn(string, WHITESPACE);
+ while (current[0] != NUL) {
+ sc_vartype_t vt_key[3];
+ sc_int object, npc, extent;
+ const sc_char *prefix, *name;
+
+ /* Initially, no object or NPC, no names, and a zero extent. */
+ object = npc = -1;
+ prefix = name = NULL;
+ extent = 0;
+
+ /*
+ * Search for pronouns where we have an assigned object or NPC. We
+ * can't be sure of getting plurality right, and it's not always
+ * intuitive even in English -- is "a pair of scissors" an "it", or
+ * a "them"? Because of this, we just treat "it" and "them" equally
+ * for now.
+ */
+ if (game->it_object != -1 && sc_compare_word(current, "it", 2)) {
+ object = game->it_object;
+ extent = 2;
+ } else if (game->it_object != -1 && sc_compare_word(current, "them", 4)) {
+ object = game->it_object;
+ extent = 4;
+ } else if (game->him_npc != -1 && sc_compare_word(current, "him", 3)) {
+ npc = game->him_npc;
+ extent = 3;
+ } else if (game->her_npc != -1 && sc_compare_word(current, "her", 3)) {
+ npc = game->her_npc;
+ extent = 3;
+ } else if (game->it_npc != -1 && sc_compare_word(current, "it", 2)) {
+ npc = game->it_npc;
+ extent = 2;
+ }
+
+ /* Assign prefix and name to the full object or NPC name, if any. */
+ if (object > -1) {
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ } else if (npc > -1) {
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ }
+
+ /*
+ * If a pronoun was found, prefix and name indicate what to insert, and
+ * extent shows how much of the buffer to replace with them.
+ */
+ if (prefix && name && extent > 0) {
+ sc_char *position;
+ sc_int prefix_length, name_length, length, final;
+
+ /*
+ * If not yet allocated, allocate a buffer now, and copy the input
+ * string into it. Then switch current to the equivalent location
+ * in the allocated buffer; basic copy-on-write.
+ */
+ if (!buffer) {
+ buffer_allocation = strlen(string) + 1;
+ buffer = (sc_char *)sc_malloc(buffer_allocation);
+ strcpy(buffer, string);
+ current = buffer + (current - string);
+ }
+
+ /*
+ * If necessary, grow the output buffer for the replacement,
+ * remembering to adjust current for the new buffer allocated.
+ * At the same time, note the last character index for the move.
+ */
+ prefix_length = strlen(prefix);
+ name_length = strlen(name);
+ length = prefix_length + name_length + 1;
+ if (length > extent) {
+ sc_int offset;
+
+ offset = current - buffer;
+ buffer_allocation += length - extent;
+ buffer = (sc_char *)sc_realloc(buffer, buffer_allocation);
+ current = buffer + offset;
+ final = length;
+ } else
+ final = extent;
+
+ /* Insert the replacement strings into the buffer. */
+ position = buffer + (current - buffer);
+ memmove(position + length,
+ position + extent,
+ buffer_allocation - (current - buffer) - final);
+ memcpy(position, prefix, prefix_length);
+ position[prefix_length] = ' ';
+ memcpy(position + prefix_length + 1, name, name_length);
+
+ /* Adjust current to skip over the replacement. */
+ current += length;
+
+ if (uip_trace)
+ sc_trace("Parser: pronoun \"%s\"\n", buffer);
+ } else {
+ /* If no match, advance current over the unmatched word. */
+ current += strcspn(current, WHITESPACE);
+ }
+
+ /* Set current to the next word start. */
+ current += strspn(current, WHITESPACE);
+ }
+
+ /* Return the final string, or NULL if no pronoun replacements. */
+ return buffer;
}
@@ -1996,143 +1857,128 @@ uip_replace_pronouns (sc_gameref_t game, const sc_char *string)
* earlier ones if there is more than one in the string.
*/
void
-uip_assign_pronouns (sc_gameref_t game, const sc_char *string)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_char *current;
- sc_int saved_ref_object, saved_ref_character;
- assert (string);
-
- if (uip_trace)
- sc_trace ("UIParser: pronoun assignment \"%s\"\n", string);
-
- /* Save var references so we can restore them later. */
- saved_ref_object = var_get_ref_object (vars);
- saved_ref_character = var_get_ref_character (vars);
-
- /* Search for object and NPC names until no more string remains. */
- current = string + strspn (string, WHITESPACE);
- while (current[0] != NUL)
- {
- if (uip_match ("%object% *", current, game))
- {
- sc_int count, index_, object;
-
- /*
- * "Disambiguate" by rejecting objects that the player hasn't seen
- * or can't see. If the reference is unique, assign to the 'it'
- * object pronoun.
- */
- count = 0;
- object = -1;
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- if (game->object_references[index_]
- && gs_object_seen (game, index_)
- && obj_indirectly_in_room (game,
- index_, gs_playerroom (game)))
- {
- count++;
- object = index_;
- }
- }
-
- if (count == 1)
- {
- game->it_object = object;
- game->it_npc = -1;
-
- if (uip_trace)
- sc_trace ("UIParser: object 'it/them' assigned %ld\n", object);
- }
- }
-
- if (uip_match ("%character% *", current, game))
- {
- sc_int count, index_, npc;
-
- /* Do the same "disambiguation" as for objects above. */
- count = 0;
- npc = -1;
- for (index_ = 0; index_ < gs_npc_count (game); index_++)
- {
- if (game->npc_references[index_]
- && gs_npc_seen (game, index_)
- && npc_in_room (game, index_, gs_playerroom (game)))
- {
- count++;
- npc = index_;
- }
- }
-
- if (count == 1)
- {
- sc_vartype_t vt_key[3];
- sc_int version, gender;
-
- /*
- * Version 3.8 games lack NPC gender information, so for this
- * case set "him"/"her" on each match, and never set "it"; this
- * matches the version 3.8 runner.
- */
- vt_key[0].string = "Version";
- version = prop_get_integer (bundle, "I<-s", vt_key);
- if (version == TAF_VERSION_380)
- {
- game->him_npc = npc;
- game->her_npc = npc;
- game->it_npc = -1;
-
- if (uip_trace)
- {
- sc_trace ("UIParser: 3.8 pronouns"
- " 'him' and 'her' assigned %ld\n", npc);
- }
- }
- else
- {
- /* Find the NPC gender, so we know the pronoun to assign. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = npc;
- vt_key[2].string = "Gender";
- gender = prop_get_integer (bundle, "I<-sis", vt_key);
-
- switch (gender)
- {
- case NPC_MALE:
- game->him_npc = npc;
- break;
- case NPC_FEMALE:
- game->her_npc = npc;
- break;
- case NPC_NEUTER:
- game->it_npc = npc;
- game->it_object = -1;
- break;
- default:
- sc_error ("uip_assign_pronouns:"
- " unknown gender, %ld\n", gender);
- }
-
- if (uip_trace)
- sc_trace ("UIParser: NPC 'him/her/it' assigned %ld\n", npc);
- }
- }
- }
-
- /*
- * Advance the string position by a complete word. This saves a lot
- * of time -- there's no point looking for an object or NPC name in
- * mid-word, and anyway it's not the right thing to do.
- */
- current += strcspn (current, WHITESPACE);
- current += strspn (current, WHITESPACE);
- }
-
- /* Restore variables references. */
- var_set_ref_object (vars, saved_ref_object);
- var_set_ref_character (vars, saved_ref_character);
+uip_assign_pronouns(sc_gameref_t game, const sc_char *string) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_char *current;
+ sc_int saved_ref_object, saved_ref_character;
+ assert(string);
+
+ if (uip_trace)
+ sc_trace("UIParser: pronoun assignment \"%s\"\n", string);
+
+ /* Save var references so we can restore them later. */
+ saved_ref_object = var_get_ref_object(vars);
+ saved_ref_character = var_get_ref_character(vars);
+
+ /* Search for object and NPC names until no more string remains. */
+ current = string + strspn(string, WHITESPACE);
+ while (current[0] != NUL) {
+ if (uip_match("%object% *", current, game)) {
+ sc_int count, index_, object;
+
+ /*
+ * "Disambiguate" by rejecting objects that the player hasn't seen
+ * or can't see. If the reference is unique, assign to the 'it'
+ * object pronoun.
+ */
+ count = 0;
+ object = -1;
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ if (game->object_references[index_]
+ && gs_object_seen(game, index_)
+ && obj_indirectly_in_room(game,
+ index_, gs_playerroom(game))) {
+ count++;
+ object = index_;
+ }
+ }
+
+ if (count == 1) {
+ game->it_object = object;
+ game->it_npc = -1;
+
+ if (uip_trace)
+ sc_trace("UIParser: object 'it/them' assigned %ld\n", object);
+ }
+ }
+
+ if (uip_match("%character% *", current, game)) {
+ sc_int count, index_, npc;
+
+ /* Do the same "disambiguation" as for objects above. */
+ count = 0;
+ npc = -1;
+ for (index_ = 0; index_ < gs_npc_count(game); index_++) {
+ if (game->npc_references[index_]
+ && gs_npc_seen(game, index_)
+ && npc_in_room(game, index_, gs_playerroom(game))) {
+ count++;
+ npc = index_;
+ }
+ }
+
+ if (count == 1) {
+ sc_vartype_t vt_key[3];
+ sc_int version, gender;
+
+ /*
+ * Version 3.8 games lack NPC gender information, so for this
+ * case set "him"/"her" on each match, and never set "it"; this
+ * matches the version 3.8 runner.
+ */
+ vt_key[0].string = "Version";
+ version = prop_get_integer(bundle, "I<-s", vt_key);
+ if (version == TAF_VERSION_380) {
+ game->him_npc = npc;
+ game->her_npc = npc;
+ game->it_npc = -1;
+
+ if (uip_trace) {
+ sc_trace("UIParser: 3.8 pronouns"
+ " 'him' and 'her' assigned %ld\n", npc);
+ }
+ } else {
+ /* Find the NPC gender, so we know the pronoun to assign. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Gender";
+ gender = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ switch (gender) {
+ case NPC_MALE:
+ game->him_npc = npc;
+ break;
+ case NPC_FEMALE:
+ game->her_npc = npc;
+ break;
+ case NPC_NEUTER:
+ game->it_npc = npc;
+ game->it_object = -1;
+ break;
+ default:
+ sc_error("uip_assign_pronouns:"
+ " unknown gender, %ld\n", gender);
+ }
+
+ if (uip_trace)
+ sc_trace("UIParser: NPC 'him/her/it' assigned %ld\n", npc);
+ }
+ }
+ }
+
+ /*
+ * Advance the string position by a complete word. This saves a lot
+ * of time -- there's no point looking for an object or NPC name in
+ * mid-word, and anyway it's not the right thing to do.
+ */
+ current += strcspn(current, WHITESPACE);
+ current += strspn(current, WHITESPACE);
+ }
+
+ /* Restore variables references. */
+ var_set_ref_object(vars, saved_ref_object);
+ var_set_ref_character(vars, saved_ref_character);
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scprintf.cpp b/engines/glk/adrift/scprintf.cpp
index 91ee94e94f..1ea93e880a 100644
--- a/engines/glk/adrift/scprintf.cpp
+++ b/engines/glk/adrift/scprintf.cpp
@@ -37,20 +37,20 @@ namespace Adrift {
/* Assorted definitions and constants. */
static const sc_uint PRINTFILTER_MAGIC = 0xb4736417;
-enum
-{ BUFFER_GROW_INCREMENT = 32,
- ITERATION_LIMIT = 32
+enum {
+ BUFFER_GROW_INCREMENT = 32,
+ ITERATION_LIMIT = 32
};
static const sc_char NUL = '\0';
static const sc_char LESSTHAN = '<';
static const sc_char GREATERTHAN = '>';
static const sc_char PERCENT = '%';
static const sc_char *const ENTITY_LESSTHAN = "&lt;",
- *const ENTITY_GREATERTHAN = "&gt;",
- *const ENTITY_PERCENT = "+percent+";
-enum
-{ ENTITY_LENGTH = 4,
- PERCENT_LENGTH = 9
+ *const ENTITY_GREATERTHAN = "&gt;",
+ *const ENTITY_PERCENT = "+percent+";
+enum {
+ ENTITY_LENGTH = 4,
+ PERCENT_LENGTH = 9
};
static const sc_char *const ESCAPES = "<>%&+";
static const sc_char *const WHITESPACE = "\t\n\v\f\r ";
@@ -65,26 +65,25 @@ static sc_bool pf_trace = FALSE;
* come before shorter ones. The <br> tag is missing because this is
* handled separately, as a simple put of '\n'.
*/
-typedef struct
-{
- const sc_char *const name;
- const sc_int length;
- const sc_int tag;
+typedef struct {
+ const sc_char *const name;
+ const sc_int length;
+ const sc_int tag;
} sc_html_tags_t;
static const sc_html_tags_t HTML_TAGS_TABLE[] = {
- {"bgcolour", 8, SC_TAG_BGCOLOR}, {"bgcolor", 7, SC_TAG_BGCOLOR},
- {"waitkey", 7, SC_TAG_WAITKEY},
- {"center", 6, SC_TAG_CENTER}, {"/center", 7, SC_TAG_ENDCENTER},
- {"centre", 6, SC_TAG_CENTER}, {"/centre", 7, SC_TAG_ENDCENTER},
- {"right", 5, SC_TAG_RIGHT}, {"/right", 6, SC_TAG_ENDRIGHT},
- {"font", 4, SC_TAG_FONT}, {"/font", 5, SC_TAG_ENDFONT},
- {"wait", 4, SC_TAG_WAIT}, {"cls", 3, SC_TAG_CLS},
- {"i", 1, SC_TAG_ITALICS}, {"/i", 2, SC_TAG_ENDITALICS},
- {"b", 1, SC_TAG_BOLD}, {"/b", 2, SC_TAG_ENDBOLD},
- {"u", 1, SC_TAG_UNDERLINE}, {"/u", 2, SC_TAG_ENDUNDERLINE},
- {"c", 1, SC_TAG_COLOR}, {"/c", 2, SC_TAG_ENDCOLOR},
- {NULL, 0, SC_TAG_UNKNOWN}
+ {"bgcolour", 8, SC_TAG_BGCOLOR}, {"bgcolor", 7, SC_TAG_BGCOLOR},
+ {"waitkey", 7, SC_TAG_WAITKEY},
+ {"center", 6, SC_TAG_CENTER}, {"/center", 7, SC_TAG_ENDCENTER},
+ {"centre", 6, SC_TAG_CENTER}, {"/centre", 7, SC_TAG_ENDCENTER},
+ {"right", 5, SC_TAG_RIGHT}, {"/right", 6, SC_TAG_ENDRIGHT},
+ {"font", 4, SC_TAG_FONT}, {"/font", 5, SC_TAG_ENDFONT},
+ {"wait", 4, SC_TAG_WAIT}, {"cls", 3, SC_TAG_CLS},
+ {"i", 1, SC_TAG_ITALICS}, {"/i", 2, SC_TAG_ENDITALICS},
+ {"b", 1, SC_TAG_BOLD}, {"/b", 2, SC_TAG_ENDBOLD},
+ {"u", 1, SC_TAG_UNDERLINE}, {"/u", 2, SC_TAG_ENDUNDERLINE},
+ {"c", 1, SC_TAG_COLOR}, {"/c", 2, SC_TAG_ENDCOLOR},
+ {NULL, 0, SC_TAG_UNKNOWN}
};
/*
@@ -92,15 +91,14 @@ static const sc_html_tags_t HTML_TAGS_TABLE[] = {
* associated size and length, a note of any conversion to apply to the next
* buffered character, and a flag to let the filter ignore incoming text.
*/
-typedef struct sc_filter_s
-{
- sc_uint magic;
- sc_int buffer_length;
- sc_int buffer_allocation;
- sc_char *buffer;
- sc_bool new_sentence;
- sc_bool is_muted;
- sc_bool needs_filtering;
+typedef struct sc_filter_s {
+ sc_uint magic;
+ sc_int buffer_length;
+ sc_int buffer_allocation;
+ sc_char *buffer;
+ sc_bool new_sentence;
+ sc_bool is_muted;
+ sc_bool needs_filtering;
} sc_filter_t;
@@ -110,9 +108,8 @@ typedef struct sc_filter_s
* Return TRUE if pointer is a valid printfilter, FALSE otherwise.
*/
static sc_bool
-pf_is_valid (sc_filterref_t filter)
-{
- return filter && filter->magic == PRINTFILTER_MAGIC;
+pf_is_valid(sc_filterref_t filter) {
+ return filter && filter->magic == PRINTFILTER_MAGIC;
}
@@ -122,42 +119,38 @@ pf_is_valid (sc_filterref_t filter)
* Create and return a new printfilter.
*/
sc_filterref_t
-pf_create (void)
-{
- static sc_bool initialized = FALSE;
-
- sc_filterref_t filter;
-
- /* On first call only, verify the string lengths in the table. */
- if (!initialized)
- {
- const sc_html_tags_t *entry;
-
- /* Compare table lengths with string lengths. */
- for (entry = HTML_TAGS_TABLE; entry->name; entry++)
- {
- if (entry->length != (sc_int) strlen (entry->name))
- {
- sc_fatal ("pf_create:"
- " table string length is wrong for \"%s\"\n",
- entry->name);
- }
- }
-
- initialized = TRUE;
- }
-
- /* Create a new printfilter. */
- filter = (sc_filterref_t)sc_malloc(sizeof (*filter));
- filter->magic = PRINTFILTER_MAGIC;
- filter->buffer_length = 0;
- filter->buffer_allocation = 0;
- filter->buffer = NULL;
- filter->new_sentence = FALSE;
- filter->is_muted = FALSE;
- filter->needs_filtering = FALSE;
-
- return filter;
+pf_create(void) {
+ static sc_bool initialized = FALSE;
+
+ sc_filterref_t filter;
+
+ /* On first call only, verify the string lengths in the table. */
+ if (!initialized) {
+ const sc_html_tags_t *entry;
+
+ /* Compare table lengths with string lengths. */
+ for (entry = HTML_TAGS_TABLE; entry->name; entry++) {
+ if (entry->length != (sc_int) strlen(entry->name)) {
+ sc_fatal("pf_create:"
+ " table string length is wrong for \"%s\"\n",
+ entry->name);
+ }
+ }
+
+ initialized = TRUE;
+ }
+
+ /* Create a new printfilter. */
+ filter = (sc_filterref_t)sc_malloc(sizeof(*filter));
+ filter->magic = PRINTFILTER_MAGIC;
+ filter->buffer_length = 0;
+ filter->buffer_allocation = 0;
+ filter->buffer = NULL;
+ filter->new_sentence = FALSE;
+ filter->is_muted = FALSE;
+ filter->needs_filtering = FALSE;
+
+ return filter;
}
@@ -167,14 +160,13 @@ pf_create (void)
* Destroy a printfilter and free its allocated memory.
*/
void
-pf_destroy (sc_filterref_t filter)
-{
- assert (pf_is_valid (filter));
-
- /* Free buffer space, and poison and free the printfilter. */
- sc_free (filter->buffer);
- memset (filter, 0xaa, sizeof (*filter));
- sc_free (filter);
+pf_destroy(sc_filterref_t filter) {
+ assert(pf_is_valid(filter));
+
+ /* Free buffer space, and poison and free the printfilter. */
+ sc_free(filter->buffer);
+ memset(filter, 0xaa, sizeof(*filter));
+ sc_free(filter);
}
@@ -192,115 +184,103 @@ pf_destroy (sc_filterref_t filter)
* this is probably all that can be done.
*/
static sc_char *
-pf_interpolate_vars (const sc_char *string, sc_var_setref_t vars)
-{
- sc_char *buffer, *name;
- const sc_char *cursor;
- const sc_char *marker;
- sc_bool is_interpolated;
-
- /*
- * Begin with NULL buffer and name strings for lazy allocation, and clear
- * interpolation detection flag.
- */
- buffer = NULL;
- name = NULL;
- is_interpolated = FALSE;
-
- /* Run through the string looking for variables. */
- marker = string;
- for (cursor = (const sc_char *)strchr (marker, PERCENT);
- cursor; cursor = (const sc_char *)strchr(marker, PERCENT))
- {
- sc_int type;
- sc_vartype_t vt_rvalue;
- sc_char close;
-
- /*
- * If not yet allocated, allocate a buffer for the return string and
- * copy up to the percent character into it; otherwise append to buffer
- * up to percent character. And if not yet done, allocate a name
- * buffer guaranteed long enough.
- */
- if (!buffer)
- {
- buffer = (sc_char *)sc_malloc (cursor - marker + 1);
- memcpy (buffer, marker, cursor - marker);
- buffer[cursor - marker] = NUL;
- }
- else
- {
- buffer = (sc_char *)sc_realloc (buffer, strlen (buffer) + cursor - marker + 1);
- strncat (buffer, marker, cursor - marker);
- }
- if (!name)
- name = (sc_char *)sc_malloc (strlen (string) + 1);
-
- /*
- * Get the variable name, and from that, the value. If we encounter a
- * mismatched '%' or unknown variable, skip it.
- */
- if (sscanf (cursor, "%%%[^%]%c", name, &close) != 2
- || close != PERCENT
- || !var_get (vars, name, &type, &vt_rvalue))
- {
- buffer = (sc_char *)sc_realloc (buffer, strlen (buffer) + 2);
- strncat (buffer, cursor, 1);
- marker = cursor + 1;
- continue;
- }
-
- /* Get variable value and append to the string. */
- switch (type)
- {
- case VAR_INTEGER:
- {
- sc_char value[32];
-
- sprintf (value, "%ld", vt_rvalue.integer);
- buffer = (sc_char *)sc_realloc (buffer, strlen (buffer) + strlen (value) + 1);
- strcat (buffer, value);
- break;
- }
-
- case VAR_STRING:
- buffer = (sc_char *)sc_realloc (buffer,
- strlen (buffer) + strlen (vt_rvalue.string) + 1);
- strcat (buffer, vt_rvalue.string);
- break;
-
- default:
- sc_fatal ("pf_interpolate_vars: invalid variable type, %ld\n", type);
- }
-
- /* Advance over the %...% variable name, and note success. */
- marker = cursor + strlen (name) + 2;
- is_interpolated = TRUE;
- }
-
- /*
- * If we allocated a buffer and interpolated into it, append the remainder
- * of the string. If we didn't interpolate successfully (the input contained
- * a rogue '%' character), throw out the buffer as it will be the same as
- * our input.
- */
- if (buffer)
- {
- if (is_interpolated)
- {
- buffer = (sc_char *)sc_realloc (buffer, strlen (buffer) + strlen (marker) + 1);
- strcat (buffer, marker);
- }
- else
- {
- sc_free (buffer);
- buffer = NULL;
- }
- }
-
- /* Clean up, and return either the updated string or NULL. */
- sc_free (name);
- return buffer;
+pf_interpolate_vars(const sc_char *string, sc_var_setref_t vars) {
+ sc_char *buffer, *name;
+ const sc_char *cursor;
+ const sc_char *marker;
+ sc_bool is_interpolated;
+
+ /*
+ * Begin with NULL buffer and name strings for lazy allocation, and clear
+ * interpolation detection flag.
+ */
+ buffer = NULL;
+ name = NULL;
+ is_interpolated = FALSE;
+
+ /* Run through the string looking for variables. */
+ marker = string;
+ for (cursor = (const sc_char *)strchr(marker, PERCENT);
+ cursor; cursor = (const sc_char *)strchr(marker, PERCENT)) {
+ sc_int type;
+ sc_vartype_t vt_rvalue;
+ sc_char close;
+
+ /*
+ * If not yet allocated, allocate a buffer for the return string and
+ * copy up to the percent character into it; otherwise append to buffer
+ * up to percent character. And if not yet done, allocate a name
+ * buffer guaranteed long enough.
+ */
+ if (!buffer) {
+ buffer = (sc_char *)sc_malloc(cursor - marker + 1);
+ memcpy(buffer, marker, cursor - marker);
+ buffer[cursor - marker] = NUL;
+ } else {
+ buffer = (sc_char *)sc_realloc(buffer, strlen(buffer) + cursor - marker + 1);
+ strncat(buffer, marker, cursor - marker);
+ }
+ if (!name)
+ name = (sc_char *)sc_malloc(strlen(string) + 1);
+
+ /*
+ * Get the variable name, and from that, the value. If we encounter a
+ * mismatched '%' or unknown variable, skip it.
+ */
+ if (sscanf(cursor, "%%%[^%]%c", name, &close) != 2
+ || close != PERCENT
+ || !var_get(vars, name, &type, &vt_rvalue)) {
+ buffer = (sc_char *)sc_realloc(buffer, strlen(buffer) + 2);
+ strncat(buffer, cursor, 1);
+ marker = cursor + 1;
+ continue;
+ }
+
+ /* Get variable value and append to the string. */
+ switch (type) {
+ case VAR_INTEGER: {
+ sc_char value[32];
+
+ sprintf(value, "%ld", vt_rvalue.integer);
+ buffer = (sc_char *)sc_realloc(buffer, strlen(buffer) + strlen(value) + 1);
+ strcat(buffer, value);
+ break;
+ }
+
+ case VAR_STRING:
+ buffer = (sc_char *)sc_realloc(buffer,
+ strlen(buffer) + strlen(vt_rvalue.string) + 1);
+ strcat(buffer, vt_rvalue.string);
+ break;
+
+ default:
+ sc_fatal("pf_interpolate_vars: invalid variable type, %ld\n", type);
+ }
+
+ /* Advance over the %...% variable name, and note success. */
+ marker = cursor + strlen(name) + 2;
+ is_interpolated = TRUE;
+ }
+
+ /*
+ * If we allocated a buffer and interpolated into it, append the remainder
+ * of the string. If we didn't interpolate successfully (the input contained
+ * a rogue '%' character), throw out the buffer as it will be the same as
+ * our input.
+ */
+ if (buffer) {
+ if (is_interpolated) {
+ buffer = (sc_char *)sc_realloc(buffer, strlen(buffer) + strlen(marker) + 1);
+ strcat(buffer, marker);
+ } else {
+ sc_free(buffer);
+ buffer = NULL;
+ }
+ }
+
+ /* Clean up, and return either the updated string or NULL. */
+ sc_free(name);
+ return buffer;
}
@@ -312,69 +292,62 @@ pf_interpolate_vars (const sc_char *string, sc_var_setref_t vars)
* reallocating if necessary. Return TRUE if the buffer was changed.
*/
static sc_bool
-pf_replace_alr (const sc_char *string,
- sc_char **buffer, sc_int alr, sc_prop_setref_t bundle)
-{
- sc_vartype_t vt_key[3];
- const sc_char *marker, *cursor, *original, *replacement;
- sc_char *buffer_ = *buffer;
-
- /* Retrieve the ALR original string, set replacement to NULL for now. */
- vt_key[0].string = "ALRs";
- vt_key[1].integer = alr;
- vt_key[2].string = "Original";
- original = prop_get_string (bundle, "S<-sis", vt_key);
- replacement = NULL;
-
- /* Ignore pathological empty originals. */
- if (original[0] == NUL)
- return FALSE;
-
- /* Run through the marker string looking for things to replace. */
- marker = string;
- for (cursor = strstr (marker, original);
- cursor; cursor = strstr (marker, original))
- {
- /* Optimize by retrieving the replacement string only on demand. */
- if (!replacement)
- {
- vt_key[2].string = "Replacement";
- replacement = prop_get_string (bundle, "S<-sis", vt_key);
- }
-
- /*
- * If not yet allocated, allocate a buffer for the return string and
- * copy; else append to the existing buffer: basic copy-on-write.
- */
- if (!buffer_)
- {
- buffer_ = (sc_char *)sc_malloc (cursor - marker + strlen (replacement) + 1);
- memcpy (buffer_, marker, cursor - marker);
- buffer_[cursor - marker] = NUL;
- strcat (buffer_, replacement);
- }
- else
- {
- buffer_ = (sc_char *)sc_realloc (buffer_, strlen (buffer_) +
- cursor - marker + strlen (replacement) + 1);
- strncat (buffer_, marker, cursor - marker);
- strcat (buffer_, replacement);
- }
-
- /* Advance over the original. */
- marker = cursor + strlen (original);
- }
-
- /* If any pending text, append it to the buffer. */
- if (replacement)
- {
- buffer_ = (sc_char *)sc_realloc (buffer_, strlen (buffer_) + strlen (marker) + 1);
- strcat (buffer_, marker);
- }
-
- /* Write back buffer, and if replacement set, the buffer was altered. */
- *buffer = buffer_;
- return replacement != NULL;
+pf_replace_alr(const sc_char *string,
+ sc_char **buffer, sc_int alr, sc_prop_setref_t bundle) {
+ sc_vartype_t vt_key[3];
+ const sc_char *marker, *cursor, *original, *replacement;
+ sc_char *buffer_ = *buffer;
+
+ /* Retrieve the ALR original string, set replacement to NULL for now. */
+ vt_key[0].string = "ALRs";
+ vt_key[1].integer = alr;
+ vt_key[2].string = "Original";
+ original = prop_get_string(bundle, "S<-sis", vt_key);
+ replacement = NULL;
+
+ /* Ignore pathological empty originals. */
+ if (original[0] == NUL)
+ return FALSE;
+
+ /* Run through the marker string looking for things to replace. */
+ marker = string;
+ for (cursor = strstr(marker, original);
+ cursor; cursor = strstr(marker, original)) {
+ /* Optimize by retrieving the replacement string only on demand. */
+ if (!replacement) {
+ vt_key[2].string = "Replacement";
+ replacement = prop_get_string(bundle, "S<-sis", vt_key);
+ }
+
+ /*
+ * If not yet allocated, allocate a buffer for the return string and
+ * copy; else append to the existing buffer: basic copy-on-write.
+ */
+ if (!buffer_) {
+ buffer_ = (sc_char *)sc_malloc(cursor - marker + strlen(replacement) + 1);
+ memcpy(buffer_, marker, cursor - marker);
+ buffer_[cursor - marker] = NUL;
+ strcat(buffer_, replacement);
+ } else {
+ buffer_ = (sc_char *)sc_realloc(buffer_, strlen(buffer_) +
+ cursor - marker + strlen(replacement) + 1);
+ strncat(buffer_, marker, cursor - marker);
+ strcat(buffer_, replacement);
+ }
+
+ /* Advance over the original. */
+ marker = cursor + strlen(original);
+ }
+
+ /* If any pending text, append it to the buffer. */
+ if (replacement) {
+ buffer_ = (sc_char *)sc_realloc(buffer_, strlen(buffer_) + strlen(marker) + 1);
+ strcat(buffer_, marker);
+ }
+
+ /* Write back buffer, and if replacement set, the buffer was altered. */
+ *buffer = buffer_;
+ return replacement != NULL;
}
@@ -386,82 +359,75 @@ pf_replace_alr (const sc_char *string,
* otherwise returns NULL.
*/
static sc_char *
-pf_replace_alrs (const sc_char *string, sc_prop_setref_t bundle,
- sc_bool alr_applied[], sc_int alr_count)
-{
- sc_int index_;
- sc_char *buffer1, *buffer2, **buffer;
- const sc_char *marker;
-
- /*
- * Begin with NULL buffers and alternate for lazy allocation. To avoid a
- * lot of allocation and copying, we use two buffers to help with repeated
- * ALR replacement.
- */
- buffer1 = buffer2 = NULL;
- buffer = &buffer1;
-
- /* Run through each ALR that exists. */
- marker = string;
- for (index_ = 0; index_ < alr_count; index_++)
- {
- sc_vartype_t vt_key[3];
- sc_int alr;
-
- /*
- * Ignore ALR indexes that have already been applied. This prevents
- * endless loops in ALR replacement.
- */
- if (alr_applied[index_])
- continue;
-
- /*
- * Get the actual ALR number for the ALR. This comes from the index
- * that we sorted earlier by length of original string. Try replacing
- * that ALR in the current marker string.
- */
- vt_key[0].string = "ALRs2";
- vt_key[1].integer = index_;
- vt_key[2].string = "ALRIndex";
- alr = prop_get_integer (bundle, "I<-sis", vt_key);
-
- if (pf_replace_alr (marker, buffer, alr, bundle))
- {
- /*
- * The current buffer in use has been altered. This means that we
- * have to switch the marker string to the buffer containing the
- * replacement, and switch 'buffer' to the other one for the next
- * ALR iteration.
- */
- marker = *buffer;
- buffer = (buffer == &buffer1) ? &buffer2 : &buffer1;
-
- /* Discard any content in the buffer switched to above. */
- if (*buffer)
- (*buffer)[0] = NUL;
-
- /* Note this ALR as "used up", and unavailable for future passes. */
- alr_applied[index_] = TRUE;
- }
- }
-
- /*
- * If marker points to one or other of the buffers, that buffer is the
- * return string, and the other is garbage, and should now be freed (or
- * was never used, in which case it is NULL).
- */
- if (marker == buffer1)
- {
- sc_free (buffer2);
- return buffer1;
- }
- else if (marker == buffer2)
- {
- sc_free (buffer1);
- return buffer2;
- }
- else
- return NULL;
+pf_replace_alrs(const sc_char *string, sc_prop_setref_t bundle,
+ sc_bool alr_applied[], sc_int alr_count) {
+ sc_int index_;
+ sc_char *buffer1, *buffer2, **buffer;
+ const sc_char *marker;
+
+ /*
+ * Begin with NULL buffers and alternate for lazy allocation. To avoid a
+ * lot of allocation and copying, we use two buffers to help with repeated
+ * ALR replacement.
+ */
+ buffer1 = buffer2 = NULL;
+ buffer = &buffer1;
+
+ /* Run through each ALR that exists. */
+ marker = string;
+ for (index_ = 0; index_ < alr_count; index_++) {
+ sc_vartype_t vt_key[3];
+ sc_int alr;
+
+ /*
+ * Ignore ALR indexes that have already been applied. This prevents
+ * endless loops in ALR replacement.
+ */
+ if (alr_applied[index_])
+ continue;
+
+ /*
+ * Get the actual ALR number for the ALR. This comes from the index
+ * that we sorted earlier by length of original string. Try replacing
+ * that ALR in the current marker string.
+ */
+ vt_key[0].string = "ALRs2";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "ALRIndex";
+ alr = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ if (pf_replace_alr(marker, buffer, alr, bundle)) {
+ /*
+ * The current buffer in use has been altered. This means that we
+ * have to switch the marker string to the buffer containing the
+ * replacement, and switch 'buffer' to the other one for the next
+ * ALR iteration.
+ */
+ marker = *buffer;
+ buffer = (buffer == &buffer1) ? &buffer2 : &buffer1;
+
+ /* Discard any content in the buffer switched to above. */
+ if (*buffer)
+ (*buffer)[0] = NUL;
+
+ /* Note this ALR as "used up", and unavailable for future passes. */
+ alr_applied[index_] = TRUE;
+ }
+ }
+
+ /*
+ * If marker points to one or other of the buffers, that buffer is the
+ * return string, and the other is garbage, and should now be freed (or
+ * was never used, in which case it is NULL).
+ */
+ if (marker == buffer1) {
+ sc_free(buffer2);
+ return buffer1;
+ } else if (marker == buffer2) {
+ sc_free(buffer1);
+ return buffer2;
+ } else
+ return NULL;
}
@@ -472,56 +438,47 @@ pf_replace_alrs (const sc_char *string, sc_prop_setref_t bundle,
* +percent+ with < > %, then send to the OS-specific output functions.
*/
static void
-pf_output_text (const sc_char *string)
-{
- sc_int index_, b_index;
- sc_char *buffer;
-
- /* Optimize away the allocation and copy if possible. */
- if (!(strstr (string, ENTITY_LESSTHAN)
- || strstr (string, ENTITY_GREATERTHAN)
- || strstr (string, ENTITY_PERCENT)))
- {
- if_print_string (string);
- return;
- }
-
- /*
- * Copy characters from the string into the buffer, replacing any &..;
- * elements by their single-character equivalents. We also replace any
- * +percent+ elements by percent characters; apparently an undocumented
- * Adrift Runner extension.
- */
- buffer = (sc_char *)sc_malloc (strlen (string) + 1);
- for (index_ = 0, b_index = 0;
- string[index_] != NUL; index_++, b_index++)
- {
- if (sc_strncasecmp (string + index_,
- ENTITY_LESSTHAN, ENTITY_LENGTH) == 0)
- {
- buffer[b_index] = LESSTHAN;
- index_ += ENTITY_LENGTH - 1;
- }
- else if (sc_strncasecmp (string + index_,
- ENTITY_GREATERTHAN, ENTITY_LENGTH) == 0)
- {
- buffer[b_index] = GREATERTHAN;
- index_ += ENTITY_LENGTH - 1;
- }
- else if (sc_strncasecmp (string + index_,
- ENTITY_PERCENT, PERCENT_LENGTH) == 0)
- {
- buffer[b_index] = PERCENT;
- index_ += PERCENT_LENGTH - 1;
- }
- else
- buffer[b_index] = string[index_];
- }
-
- /* Terminate, print, and free the buffer. */
- buffer[b_index] = NUL;
- if_print_string (buffer);
- sc_free (buffer);
+pf_output_text(const sc_char *string) {
+ sc_int index_, b_index;
+ sc_char *buffer;
+
+ /* Optimize away the allocation and copy if possible. */
+ if (!(strstr(string, ENTITY_LESSTHAN)
+ || strstr(string, ENTITY_GREATERTHAN)
+ || strstr(string, ENTITY_PERCENT))) {
+ if_print_string(string);
+ return;
+ }
+
+ /*
+ * Copy characters from the string into the buffer, replacing any &..;
+ * elements by their single-character equivalents. We also replace any
+ * +percent+ elements by percent characters; apparently an undocumented
+ * Adrift Runner extension.
+ */
+ buffer = (sc_char *)sc_malloc(strlen(string) + 1);
+ for (index_ = 0, b_index = 0;
+ string[index_] != NUL; index_++, b_index++) {
+ if (sc_strncasecmp(string + index_,
+ ENTITY_LESSTHAN, ENTITY_LENGTH) == 0) {
+ buffer[b_index] = LESSTHAN;
+ index_ += ENTITY_LENGTH - 1;
+ } else if (sc_strncasecmp(string + index_,
+ ENTITY_GREATERTHAN, ENTITY_LENGTH) == 0) {
+ buffer[b_index] = GREATERTHAN;
+ index_ += ENTITY_LENGTH - 1;
+ } else if (sc_strncasecmp(string + index_,
+ ENTITY_PERCENT, PERCENT_LENGTH) == 0) {
+ buffer[b_index] = PERCENT;
+ index_ += PERCENT_LENGTH - 1;
+ } else
+ buffer[b_index] = string[index_];
+ }
+
+ /* Terminate, print, and free the buffer. */
+ buffer[b_index] = NUL;
+ if_print_string(buffer);
+ sc_free(buffer);
}
@@ -531,53 +488,48 @@ pf_output_text (const sc_char *string)
* Output an HTML-like tag element to the OS-specific tag handling function.
*/
static void
-pf_output_tag (const sc_char *contents)
-{
- const sc_html_tags_t *entry;
- const sc_char *argument;
-
- /* For a simple <br> tag, just print out a newline. */
- if (sc_compare_word (contents, "br", 2))
- {
- if_print_character ('\n');
- return;
- }
-
- /*
- * Search for the name in the HTML tags table. It should be a full match,
- * that is, the character after the matched name must be space or NUL.
- * The <bgcolour="xyz"> tag is the exception; here the terminator is '='.
- */
- for (entry = HTML_TAGS_TABLE; entry->name; entry++)
- {
- if (sc_strncasecmp (contents, entry->name, entry->length) == 0)
- {
- sc_char next;
-
- next = contents[entry->length];
- if (next == NUL || sc_isspace (next)
- || (entry->tag == SC_TAG_BGCOLOR && next == '='))
- break;
- }
- }
-
- /* If not matched, output an unknown tag with contents as its argument. */
- if (!entry->name)
- {
- if_print_tag (SC_TAG_UNKNOWN, contents);
- return;
- }
-
- /*
- * Find the argument by skipping the tag name and any spaces. Again, for
- * <bgcolour="xyz">, make a special case, passing the complete contents as
- * argument (to match <font colour=...> for the client.
- */
- argument = contents;
- argument += (entry->tag != SC_TAG_BGCOLOR) ? entry->length : 0;
- while (sc_isspace (argument[0]))
- argument++;
- if_print_tag (entry->tag, argument);
+pf_output_tag(const sc_char *contents) {
+ const sc_html_tags_t *entry;
+ const sc_char *argument;
+
+ /* For a simple <br> tag, just print out a newline. */
+ if (sc_compare_word(contents, "br", 2)) {
+ if_print_character('\n');
+ return;
+ }
+
+ /*
+ * Search for the name in the HTML tags table. It should be a full match,
+ * that is, the character after the matched name must be space or NUL.
+ * The <bgcolour="xyz"> tag is the exception; here the terminator is '='.
+ */
+ for (entry = HTML_TAGS_TABLE; entry->name; entry++) {
+ if (sc_strncasecmp(contents, entry->name, entry->length) == 0) {
+ sc_char next;
+
+ next = contents[entry->length];
+ if (next == NUL || sc_isspace(next)
+ || (entry->tag == SC_TAG_BGCOLOR && next == '='))
+ break;
+ }
+ }
+
+ /* If not matched, output an unknown tag with contents as its argument. */
+ if (!entry->name) {
+ if_print_tag(SC_TAG_UNKNOWN, contents);
+ return;
+ }
+
+ /*
+ * Find the argument by skipping the tag name and any spaces. Again, for
+ * <bgcolour="xyz">, make a special case, passing the complete contents as
+ * argument (to match <font colour=...> for the client.
+ */
+ argument = contents;
+ argument += (entry->tag != SC_TAG_BGCOLOR) ? entry->length : 0;
+ while (sc_isspace(argument[0]))
+ argument++;
+ if_print_tag(entry->tag, argument);
}
@@ -588,79 +540,73 @@ pf_output_tag (const sc_char *contents)
* tags.
*/
static void
-pf_output_untagged (const sc_char *string)
-{
+pf_output_untagged(const sc_char *string) {
sc_char *temporary, *untagged, *contents;
const sc_char *cursor;
- const sc_char *marker;
-
- /*
- * Optimize away the allocation and copy if possible. We need to check
- * here both for tags and for entities; only if neither occurs is it safe
- * to output the string directly.
- */
- if (!strchr (string, LESSTHAN)
- && !(strstr (string, ENTITY_LESSTHAN)
- || strstr (string, ENTITY_GREATERTHAN)
- || strstr (string, ENTITY_PERCENT)))
- {
- if_print_string (string);
- return;
- }
-
- /*
- * Create a general temporary string, and alias it to both untagged text
- * and the tag name, for sharing inside the loop.
- */
- temporary = (sc_char *)sc_malloc (strlen (string) + 1);
- untagged = contents = temporary;
-
- /* Run through the string looking for <...> tags. */
- marker = string;
- for (cursor = (const sc_char *)strchr (marker, LESSTHAN);
- cursor; cursor = (const sc_char *)strchr (marker, LESSTHAN))
- {
- sc_char close;
-
- /* Handle characters up to the tag start; untagged text. */
- memcpy (untagged, marker, cursor - marker);
- untagged[cursor - marker] = NUL;
- pf_output_text (untagged);
-
- /* Catch and ignore completely empty tags. */
- if (cursor[1] == GREATERTHAN)
- {
- marker = cursor + 2;
- continue;
- }
-
- /*
- * Get the text within the tag, reusing the temporary buffer. If this
- * fails, allow the remainder of the line to be delivered as a tag;
- * unknown, probably.
- */
- if (sscanf (cursor, "<%[^>]%c", contents, &close) != 2
- || close != GREATERTHAN)
- {
- if (sscanf (cursor, "<%[^>]", contents) != 1)
- {
- sc_error ("pf_output_untagged: mismatched '%c'\n", LESSTHAN);
- if_print_character (LESSTHAN);
- marker = cursor + 1;
- continue;
- }
- }
-
- /* Output tag, and advance marker over the <...> tag. */
- if (!sc_strempty (contents))
- pf_output_tag (contents);
- marker = cursor + strlen (contents) + 1;
- marker += (marker[0] == GREATERTHAN) ? 1 : 0;
- }
-
- /* Output any remaining string text, and free the temporary buffer. */
- pf_output_text (marker);
- sc_free (temporary);
+ const sc_char *marker;
+
+ /*
+ * Optimize away the allocation and copy if possible. We need to check
+ * here both for tags and for entities; only if neither occurs is it safe
+ * to output the string directly.
+ */
+ if (!strchr(string, LESSTHAN)
+ && !(strstr(string, ENTITY_LESSTHAN)
+ || strstr(string, ENTITY_GREATERTHAN)
+ || strstr(string, ENTITY_PERCENT))) {
+ if_print_string(string);
+ return;
+ }
+
+ /*
+ * Create a general temporary string, and alias it to both untagged text
+ * and the tag name, for sharing inside the loop.
+ */
+ temporary = (sc_char *)sc_malloc(strlen(string) + 1);
+ untagged = contents = temporary;
+
+ /* Run through the string looking for <...> tags. */
+ marker = string;
+ for (cursor = (const sc_char *)strchr(marker, LESSTHAN);
+ cursor; cursor = (const sc_char *)strchr(marker, LESSTHAN)) {
+ sc_char close;
+
+ /* Handle characters up to the tag start; untagged text. */
+ memcpy(untagged, marker, cursor - marker);
+ untagged[cursor - marker] = NUL;
+ pf_output_text(untagged);
+
+ /* Catch and ignore completely empty tags. */
+ if (cursor[1] == GREATERTHAN) {
+ marker = cursor + 2;
+ continue;
+ }
+
+ /*
+ * Get the text within the tag, reusing the temporary buffer. If this
+ * fails, allow the remainder of the line to be delivered as a tag;
+ * unknown, probably.
+ */
+ if (sscanf(cursor, "<%[^>]%c", contents, &close) != 2
+ || close != GREATERTHAN) {
+ if (sscanf(cursor, "<%[^>]", contents) != 1) {
+ sc_error("pf_output_untagged: mismatched '%c'\n", LESSTHAN);
+ if_print_character(LESSTHAN);
+ marker = cursor + 1;
+ continue;
+ }
+ }
+
+ /* Output tag, and advance marker over the <...> tag. */
+ if (!sc_strempty(contents))
+ pf_output_tag(contents);
+ marker = cursor + strlen(contents) + 1;
+ marker += (marker[0] == GREATERTHAN) ? 1 : 0;
+ }
+
+ /* Output any remaining string text, and free the temporary buffer. */
+ pf_output_text(marker);
+ sc_free(temporary);
}
@@ -691,118 +637,102 @@ pf_output_untagged (const sc_char *string)
*
*/
static sc_char *
-pf_filter_internal (const sc_char *string,
- sc_var_setref_t vars, sc_prop_setref_t bundle)
-{
- sc_int alr_count, iteration;
- sc_char *current;
- sc_bool *alr_applied;
- assert (string && vars);
-
- if (pf_trace)
- sc_trace ("Printfilter: initial \"%s\"\n", string);
-
- /* If including ALRs, create a common set of ALR application flags. */
- if (bundle)
- {
- sc_vartype_t vt_key;
-
- /* Obtain a count of ALRs. */
- vt_key.string = "ALRs";
- alr_count = prop_get_child_count (bundle, "I<-s", &vt_key);
-
- /*
- * Create a new set of ALR application flags. These are used to ensure
- * that a given ALR is applied only once on a given pass. If the game
- * has no ALRs, don't create a flag set.
- */
- if (alr_count > 0)
- {
- alr_applied = (sc_bool *)sc_malloc (alr_count * sizeof (*alr_applied));
- memset (alr_applied, FALSE, alr_count * sizeof (*alr_applied));
- }
- else
- alr_applied = NULL;
- }
- else
- {
- /* Not including ALRs, so set alr count to 0, and flags to NULL. */
- alr_count = 0;
- alr_applied = NULL;
- }
-
- /* Loop for a sort-of arbitrary number of passes; probably enough. */
- current = NULL;
- for (iteration = 0; iteration < ITERATION_LIMIT; iteration++)
- {
- sc_int inner_iteration;
- const sc_char *initial;
- sc_char *intermediate;
-
- /* Note the initial string, so we can check for no change. */
- initial = current;
-
- for (inner_iteration = 0;
- inner_iteration < ITERATION_LIMIT; inner_iteration++)
- {
- /*
- * Interpolate variables. If any changes were made, advance current
- * to the interpolated version, and free the old current if required.
- * Work on the current string, if any, otherwise the input string.
- */
- intermediate = pf_interpolate_vars (current ? current : string, vars);
- if (intermediate)
- {
- sc_free (current);
- current = intermediate;
- if (pf_trace)
- {
- sc_trace ("Printfilter: interpolated [%ld,%ld] \"%s\"\n",
- iteration, inner_iteration, current);
- }
- }
- else
- break;
- }
-
- /* If we have ALRs to process, search out and replace all findable. */
- if (alr_count > 0)
- {
- /* Replace ALRs until no more ALRs can be found. */
- inner_iteration = 0;
- while (TRUE)
- {
- /*
- * Replace ALRs, and advance current as for variables above.
- * Leave the loop when ALR replacements stop. Again, work on
- * the current string if any, otherwise the input string.
- */
- intermediate = pf_replace_alrs (current ? current : string,
- bundle, alr_applied, alr_count);
- if (intermediate)
- {
- sc_free (current);
- current = intermediate;
- if (pf_trace)
- {
- sc_trace ("Printfilter: replaced [%ld,%ld] \"%s\"\n",
- iteration, inner_iteration, current);
- }
- }
- else
- break;
- inner_iteration++;
- }
- }
-
- /* If nothing changed this iteration, stop now. */
- if (current == initial)
- break;
- }
-
- /* Free any ALR application flags, and return current, NULL if no change. */
- sc_free (alr_applied);
- return current;
+pf_filter_internal(const sc_char *string,
+ sc_var_setref_t vars, sc_prop_setref_t bundle) {
+ sc_int alr_count, iteration;
+ sc_char *current;
+ sc_bool *alr_applied;
+ assert(string && vars);
+
+ if (pf_trace)
+ sc_trace("Printfilter: initial \"%s\"\n", string);
+
+ /* If including ALRs, create a common set of ALR application flags. */
+ if (bundle) {
+ sc_vartype_t vt_key;
+
+ /* Obtain a count of ALRs. */
+ vt_key.string = "ALRs";
+ alr_count = prop_get_child_count(bundle, "I<-s", &vt_key);
+
+ /*
+ * Create a new set of ALR application flags. These are used to ensure
+ * that a given ALR is applied only once on a given pass. If the game
+ * has no ALRs, don't create a flag set.
+ */
+ if (alr_count > 0) {
+ alr_applied = (sc_bool *)sc_malloc(alr_count * sizeof(*alr_applied));
+ memset(alr_applied, FALSE, alr_count * sizeof(*alr_applied));
+ } else
+ alr_applied = NULL;
+ } else {
+ /* Not including ALRs, so set alr count to 0, and flags to NULL. */
+ alr_count = 0;
+ alr_applied = NULL;
+ }
+
+ /* Loop for a sort-of arbitrary number of passes; probably enough. */
+ current = NULL;
+ for (iteration = 0; iteration < ITERATION_LIMIT; iteration++) {
+ sc_int inner_iteration;
+ const sc_char *initial;
+ sc_char *intermediate;
+
+ /* Note the initial string, so we can check for no change. */
+ initial = current;
+
+ for (inner_iteration = 0;
+ inner_iteration < ITERATION_LIMIT; inner_iteration++) {
+ /*
+ * Interpolate variables. If any changes were made, advance current
+ * to the interpolated version, and free the old current if required.
+ * Work on the current string, if any, otherwise the input string.
+ */
+ intermediate = pf_interpolate_vars(current ? current : string, vars);
+ if (intermediate) {
+ sc_free(current);
+ current = intermediate;
+ if (pf_trace) {
+ sc_trace("Printfilter: interpolated [%ld,%ld] \"%s\"\n",
+ iteration, inner_iteration, current);
+ }
+ } else
+ break;
+ }
+
+ /* If we have ALRs to process, search out and replace all findable. */
+ if (alr_count > 0) {
+ /* Replace ALRs until no more ALRs can be found. */
+ inner_iteration = 0;
+ while (TRUE) {
+ /*
+ * Replace ALRs, and advance current as for variables above.
+ * Leave the loop when ALR replacements stop. Again, work on
+ * the current string if any, otherwise the input string.
+ */
+ intermediate = pf_replace_alrs(current ? current : string,
+ bundle, alr_applied, alr_count);
+ if (intermediate) {
+ sc_free(current);
+ current = intermediate;
+ if (pf_trace) {
+ sc_trace("Printfilter: replaced [%ld,%ld] \"%s\"\n",
+ iteration, inner_iteration, current);
+ }
+ } else
+ break;
+ inner_iteration++;
+ }
+ }
+
+ /* If nothing changed this iteration, stop now. */
+ if (current == initial)
+ break;
+ }
+
+ /* Free any ALR application flags, and return current, NULL if no change. */
+ sc_free(alr_applied);
+ return current;
}
@@ -814,22 +744,20 @@ pf_filter_internal (const sc_char *string,
* needs to free.
*/
sc_char *
-pf_filter (const sc_char *string,
- sc_var_setref_t vars, sc_prop_setref_t bundle)
-{
- sc_char *current;
-
- /* Filter this string, including ALRs replacements. */
- current = pf_filter_internal (string, vars, bundle);
-
- /* Our contract is to return an allocated string; copy if required. */
- if (!current)
- {
- current = (sc_char *)sc_malloc (strlen (string) + 1);
- strcpy (current, string);
- }
-
- return current;
+pf_filter(const sc_char *string,
+ sc_var_setref_t vars, sc_prop_setref_t bundle) {
+ sc_char *current;
+
+ /* Filter this string, including ALRs replacements. */
+ current = pf_filter_internal(string, vars, bundle);
+
+ /* Our contract is to return an allocated string; copy if required. */
+ if (!current) {
+ current = (sc_char *)sc_malloc(strlen(string) + 1);
+ strcpy(current, string);
+ }
+
+ return current;
}
@@ -842,21 +770,19 @@ pf_filter (const sc_char *string,
* an allocated string that the caller needs to free.
*/
sc_char *
-pf_filter_for_info (const sc_char *string, sc_var_setref_t vars)
-{
- sc_char *current;
+pf_filter_for_info(const sc_char *string, sc_var_setref_t vars) {
+ sc_char *current;
- /* Filter this string, excluding ALRs replacements. */
- current = pf_filter_internal (string, vars, NULL);
+ /* Filter this string, excluding ALRs replacements. */
+ current = pf_filter_internal(string, vars, NULL);
- /* Our contract is to return an allocated string; copy if required. */
- if (!current)
- {
- current = (sc_char *)sc_malloc (strlen (string) + 1);
- strcpy (current, string);
- }
+ /* Our contract is to return an allocated string; copy if required. */
+ if (!current) {
+ current = (sc_char *)sc_malloc(strlen(string) + 1);
+ strcpy(current, string);
+ }
- return current;
+ return current;
}
@@ -867,45 +793,39 @@ pf_filter_for_info (const sc_char *string, sc_var_setref_t vars)
* send the resulting string to the output channel.
*/
void
-pf_flush (sc_filterref_t filter,
- sc_var_setref_t vars, sc_prop_setref_t bundle)
-{
- assert (pf_is_valid (filter));
- assert (vars && bundle);
-
- /* See if there is any buffered data to flush. */
- if (filter->buffer_length > 0)
- {
- /*
- * Filter the buffered string, then print it untagged. Remember to free
- * the filtered version. If filtering made no difference, or if the
- * buffer was already filtered by, say, checkpointing, just print the
- * original buffer untagged instead.
- */
- if (filter->needs_filtering)
- {
- sc_char *filtered;
-
- filtered = pf_filter_internal (filter->buffer, vars, bundle);
- if (filtered)
- {
- pf_output_untagged (filtered);
- sc_free (filtered);
- }
- else
- pf_output_untagged (filter->buffer);
- }
- else
- pf_output_untagged (filter->buffer);
-
- /* Remove buffered data by resetting length to zero. */
- filter->buffer_length = 0;
- filter->needs_filtering = FALSE;
- }
-
- /* Reset new sentence and mute flags. */
- filter->new_sentence = FALSE;
- filter->is_muted = FALSE;
+pf_flush(sc_filterref_t filter,
+ sc_var_setref_t vars, sc_prop_setref_t bundle) {
+ assert(pf_is_valid(filter));
+ assert(vars && bundle);
+
+ /* See if there is any buffered data to flush. */
+ if (filter->buffer_length > 0) {
+ /*
+ * Filter the buffered string, then print it untagged. Remember to free
+ * the filtered version. If filtering made no difference, or if the
+ * buffer was already filtered by, say, checkpointing, just print the
+ * original buffer untagged instead.
+ */
+ if (filter->needs_filtering) {
+ sc_char *filtered;
+
+ filtered = pf_filter_internal(filter->buffer, vars, bundle);
+ if (filtered) {
+ pf_output_untagged(filtered);
+ sc_free(filtered);
+ } else
+ pf_output_untagged(filter->buffer);
+ } else
+ pf_output_untagged(filter->buffer);
+
+ /* Remove buffered data by resetting length to zero. */
+ filter->buffer_length = 0;
+ filter->needs_filtering = FALSE;
+ }
+
+ /* Reset new sentence and mute flags. */
+ filter->new_sentence = FALSE;
+ filter->is_muted = FALSE;
}
@@ -915,38 +835,36 @@ pf_flush (sc_filterref_t filter,
* Append a string to the filter buffer.
*/
static void
-pf_append_string (sc_filterref_t filter, const sc_char *string)
-{
- sc_int length, required;
-
- /*
- * Calculate the required buffer size to append string. Remember to add
- * one for the terminating NUL.
- */
- length = strlen (string);
- required = filter->buffer_length + length + 1;
-
- /* If this is more than the current buffer allocation, resize it. */
- if (required > filter->buffer_allocation)
- {
- sc_int new_allocation;
-
- /* Calculate the new malloc size, in increment chunks. */
- new_allocation = ((required + BUFFER_GROW_INCREMENT - 1)
- / BUFFER_GROW_INCREMENT) * BUFFER_GROW_INCREMENT;
-
- /* Grow the buffer. */
- filter->buffer = (sc_char *)sc_realloc (filter->buffer, new_allocation);
- filter->buffer_allocation = new_allocation;
- }
-
- /* If empty, put a NUL into the buffer to permit strcat. */
- if (filter->buffer_length == 0)
- filter->buffer[0] = NUL;
-
- /* Append the string to the buffer and extend length. */
- strcat (filter->buffer, string);
- filter->buffer_length += length;
+pf_append_string(sc_filterref_t filter, const sc_char *string) {
+ sc_int length, required;
+
+ /*
+ * Calculate the required buffer size to append string. Remember to add
+ * one for the terminating NUL.
+ */
+ length = strlen(string);
+ required = filter->buffer_length + length + 1;
+
+ /* If this is more than the current buffer allocation, resize it. */
+ if (required > filter->buffer_allocation) {
+ sc_int new_allocation;
+
+ /* Calculate the new malloc size, in increment chunks. */
+ new_allocation = ((required + BUFFER_GROW_INCREMENT - 1)
+ / BUFFER_GROW_INCREMENT) * BUFFER_GROW_INCREMENT;
+
+ /* Grow the buffer. */
+ filter->buffer = (sc_char *)sc_realloc(filter->buffer, new_allocation);
+ filter->buffer_allocation = new_allocation;
+ }
+
+ /* If empty, put a NUL into the buffer to permit strcat. */
+ if (filter->buffer_length == 0)
+ filter->buffer[0] = NUL;
+
+ /* Append the string to the buffer and extend length. */
+ strcat(filter->buffer, string);
+ filter->buffer_length += length;
}
@@ -959,37 +877,33 @@ pf_append_string (sc_filterref_t filter, const sc_char *string)
* values before those values are updated by task actions.
*/
void
-pf_checkpoint (sc_filterref_t filter,
- sc_var_setref_t vars, sc_prop_setref_t bundle)
-{
- assert (pf_is_valid (filter));
- assert (vars && bundle);
-
- /* See if there is any buffered data to filter. */
- if (filter->buffer_length > 0)
- {
- /*
- * Filter the buffered string, and place the filtered result, if any,
- * back into the filter buffer. We do this by setting the buffer length
- * back to zero, then appending the filtered string; this keeps the
- * grown buffer intact.
- */
- if (filter->needs_filtering)
- {
- sc_char *filtered;
-
- filtered = pf_filter_internal (filter->buffer, vars, bundle);
- if (filtered)
- {
- filter->buffer_length = 0;
- pf_append_string (filter, filtered);
- sc_free (filtered);
- }
- }
-
- /* Note the buffer as filtered, to avoid pointless filtering. */
- filter->needs_filtering = FALSE;
- }
+pf_checkpoint(sc_filterref_t filter,
+ sc_var_setref_t vars, sc_prop_setref_t bundle) {
+ assert(pf_is_valid(filter));
+ assert(vars && bundle);
+
+ /* See if there is any buffered data to filter. */
+ if (filter->buffer_length > 0) {
+ /*
+ * Filter the buffered string, and place the filtered result, if any,
+ * back into the filter buffer. We do this by setting the buffer length
+ * back to zero, then appending the filtered string; this keeps the
+ * grown buffer intact.
+ */
+ if (filter->needs_filtering) {
+ sc_char *filtered;
+
+ filtered = pf_filter_internal(filter->buffer, vars, bundle);
+ if (filtered) {
+ filter->buffer_length = 0;
+ pf_append_string(filter, filtered);
+ sc_free(filtered);
+ }
+ }
+
+ /* Note the buffer as filtered, to avoid pointless filtering. */
+ filter->needs_filtering = FALSE;
+ }
}
@@ -1005,54 +919,48 @@ pf_checkpoint (sc_filterref_t filter,
* in client code.
*/
const sc_char *
-pf_get_buffer (sc_filterref_t filter)
-{
- assert (pf_is_valid (filter));
-
- /*
- * Return buffer if filter length is greater than zero. Note that this
- * assumes that the buffer is a nul-terminated string.
- */
- if (filter->buffer_length > 0)
- {
- assert (filter->buffer[filter->buffer_length] == NUL);
- return filter->buffer;
- }
- else
- return NULL;
+pf_get_buffer(sc_filterref_t filter) {
+ assert(pf_is_valid(filter));
+
+ /*
+ * Return buffer if filter length is greater than zero. Note that this
+ * assumes that the buffer is a nul-terminated string.
+ */
+ if (filter->buffer_length > 0) {
+ assert(filter->buffer[filter->buffer_length] == NUL);
+ return filter->buffer;
+ } else
+ return NULL;
}
sc_char *
-pf_transfer_buffer (sc_filterref_t filter)
-{
- assert (pf_is_valid (filter));
-
- /*
- * If the filter length is greater than zero, pass out the buffer (a nul-
- * terminated string) and zero our length, allocation, and set the buffer
- * back to NULL; an empty in all except the free-ing.
- */
- if (filter->buffer_length > 0)
- {
- sc_char *retval;
-
- /* Set the return value to be the buffered text. */
- assert (filter->buffer[filter->buffer_length] == NUL);
- retval = filter->buffer;
-
- /* Clear all filter fields down to empty values. */
- filter->buffer_length = 0;
- filter->buffer_allocation = 0;
- filter->buffer = NULL;
- filter->new_sentence = FALSE;
- filter->is_muted = FALSE;
- filter->needs_filtering = FALSE;
-
- /* Return the allocated buffered text. */
- return retval;
- }
- else
- return NULL;
+pf_transfer_buffer(sc_filterref_t filter) {
+ assert(pf_is_valid(filter));
+
+ /*
+ * If the filter length is greater than zero, pass out the buffer (a nul-
+ * terminated string) and zero our length, allocation, and set the buffer
+ * back to NULL; an empty in all except the free-ing.
+ */
+ if (filter->buffer_length > 0) {
+ sc_char *retval;
+
+ /* Set the return value to be the buffered text. */
+ assert(filter->buffer[filter->buffer_length] == NUL);
+ retval = filter->buffer;
+
+ /* Clear all filter fields down to empty values. */
+ filter->buffer_length = 0;
+ filter->buffer_allocation = 0;
+ filter->buffer = NULL;
+ filter->new_sentence = FALSE;
+ filter->is_muted = FALSE;
+ filter->needs_filtering = FALSE;
+
+ /* Return the allocated buffered text. */
+ return retval;
+ } else
+ return NULL;
}
@@ -1062,18 +970,17 @@ pf_transfer_buffer (sc_filterref_t filter)
* Empty any text currently buffered in the filter.
*/
void
-pf_empty (sc_filterref_t filter)
-{
- assert (pf_is_valid (filter));
-
- /* Free any allocation, and return the filter to initialization state. */
- filter->buffer_length = 0;
- filter->buffer_allocation = 0;
- sc_free (filter->buffer);
- filter->buffer = NULL;
- filter->new_sentence = FALSE;
- filter->is_muted = FALSE;
- filter->needs_filtering = FALSE;
+pf_empty(sc_filterref_t filter) {
+ assert(pf_is_valid(filter));
+
+ /* Free any allocation, and return the filter to initialization state. */
+ filter->buffer_length = 0;
+ filter->buffer_allocation = 0;
+ sc_free(filter->buffer);
+ filter->buffer = NULL;
+ filter->new_sentence = FALSE;
+ filter->is_muted = FALSE;
+ filter->needs_filtering = FALSE;
}
@@ -1085,39 +992,36 @@ pf_empty (sc_filterref_t filter)
* these functions do nothing.
*/
void
-pf_buffer_string (sc_filterref_t filter, const sc_char *string)
-{
- assert (pf_is_valid (filter));
- assert (string);
-
- /* Ignore the call if the printfilter is muted. */
- if (!filter->is_muted)
- {
- sc_int noted;
-
- /* Note append start, then append the string to the buffer. */
- noted = filter->buffer_length;
- pf_append_string (filter, string);
-
- /* Adjust the first character of the appended string if flagged. */
- if (filter->new_sentence)
- filter->buffer[noted] = sc_toupper (filter->buffer[noted]);
-
- /* Clear new sentence, and note as currently needing filtering. */
- filter->needs_filtering = TRUE;
- filter->new_sentence = FALSE;
- }
+pf_buffer_string(sc_filterref_t filter, const sc_char *string) {
+ assert(pf_is_valid(filter));
+ assert(string);
+
+ /* Ignore the call if the printfilter is muted. */
+ if (!filter->is_muted) {
+ sc_int noted;
+
+ /* Note append start, then append the string to the buffer. */
+ noted = filter->buffer_length;
+ pf_append_string(filter, string);
+
+ /* Adjust the first character of the appended string if flagged. */
+ if (filter->new_sentence)
+ filter->buffer[noted] = sc_toupper(filter->buffer[noted]);
+
+ /* Clear new sentence, and note as currently needing filtering. */
+ filter->needs_filtering = TRUE;
+ filter->new_sentence = FALSE;
+ }
}
void
-pf_buffer_character (sc_filterref_t filter, sc_char character)
-{
- sc_char buffer[2];
- assert (pf_is_valid (filter));
-
- buffer[0] = character;
- buffer[1] = NUL;
- pf_buffer_string (filter, buffer);
+pf_buffer_character(sc_filterref_t filter, sc_char character) {
+ sc_char buffer[2];
+ assert(pf_is_valid(filter));
+
+ buffer[0] = character;
+ buffer[1] = NUL;
+ pf_buffer_string(filter, buffer);
}
@@ -1130,47 +1034,43 @@ pf_buffer_character (sc_filterref_t filter, sc_char character)
* completion text. If muted, this function does nothing.
*/
void
-pf_prepend_string (sc_filterref_t filter, const sc_char *string)
-{
- assert (pf_is_valid (filter));
- assert (string);
-
- /* Ignore the call if the printfilter is muted. */
- if (!filter->is_muted)
- {
- if (filter->buffer_length > 0)
- {
- sc_char *copy;
-
- /* Take a copy of the current buffered string. */
- assert (filter->buffer[filter->buffer_length] == NUL);
- copy = (sc_char *)sc_malloc (filter->buffer_length + 1);
- strcpy (copy, filter->buffer);
-
- /*
- * Now restart buffering with the input string passed in. Removing
- * the current content by zeroing the length preserves the grown
- * allocation of the main buffer.
- */
- filter->buffer_length = 0;
- pf_append_string (filter, string);
-
- /* Append the string saved above and then free it. */
- pf_append_string (filter, copy);
- sc_free (copy);
-
- /* Adjust the first character of the prepended string if flagged. */
- if (filter->new_sentence)
- filter->buffer[0] = sc_toupper (filter->buffer[0]);
-
- /* Clear new sentence, and note as currently needing filtering. */
- filter->needs_filtering = TRUE;
- filter->new_sentence = FALSE;
- }
- else
- /* No data, so the call is equivalent to a normal buffer. */
- pf_buffer_string (filter, string);
- }
+pf_prepend_string(sc_filterref_t filter, const sc_char *string) {
+ assert(pf_is_valid(filter));
+ assert(string);
+
+ /* Ignore the call if the printfilter is muted. */
+ if (!filter->is_muted) {
+ if (filter->buffer_length > 0) {
+ sc_char *copy;
+
+ /* Take a copy of the current buffered string. */
+ assert(filter->buffer[filter->buffer_length] == NUL);
+ copy = (sc_char *)sc_malloc(filter->buffer_length + 1);
+ strcpy(copy, filter->buffer);
+
+ /*
+ * Now restart buffering with the input string passed in. Removing
+ * the current content by zeroing the length preserves the grown
+ * allocation of the main buffer.
+ */
+ filter->buffer_length = 0;
+ pf_append_string(filter, string);
+
+ /* Append the string saved above and then free it. */
+ pf_append_string(filter, copy);
+ sc_free(copy);
+
+ /* Adjust the first character of the prepended string if flagged. */
+ if (filter->new_sentence)
+ filter->buffer[0] = sc_toupper(filter->buffer[0]);
+
+ /* Clear new sentence, and note as currently needing filtering. */
+ filter->needs_filtering = TRUE;
+ filter->new_sentence = FALSE;
+ } else
+ /* No data, so the call is equivalent to a normal buffer. */
+ pf_buffer_string(filter, string);
+ }
}
@@ -1181,12 +1081,11 @@ pf_prepend_string (sc_filterref_t filter, const sc_char *string)
* Ignored if the printfilter is muted.
*/
void
-pf_new_sentence (sc_filterref_t filter)
-{
- assert (pf_is_valid (filter));
+pf_new_sentence(sc_filterref_t filter) {
+ assert(pf_is_valid(filter));
- if (!filter->is_muted)
- filter->new_sentence = TRUE;
+ if (!filter->is_muted)
+ filter->new_sentence = TRUE;
}
@@ -1197,19 +1096,17 @@ pf_new_sentence (sc_filterref_t filter)
* A muted printfilter ignores all new text additions.
*/
void
-pf_mute (sc_filterref_t filter)
-{
- assert (pf_is_valid (filter));
+pf_mute(sc_filterref_t filter) {
+ assert(pf_is_valid(filter));
- filter->is_muted = TRUE;
+ filter->is_muted = TRUE;
}
void
-pf_clear_mute (sc_filterref_t filter)
-{
- assert (pf_is_valid (filter));
+pf_clear_mute(sc_filterref_t filter) {
+ assert(pf_is_valid(filter));
- filter->is_muted = FALSE;
+ filter->is_muted = FALSE;
}
@@ -1220,27 +1117,23 @@ pf_clear_mute (sc_filterref_t filter)
* if the printfilter is muted.
*/
void
-pf_buffer_tag (sc_filterref_t filter, sc_int tag)
-{
- const sc_html_tags_t *entry;
- assert (pf_is_valid (filter));
-
- /* Search the tags table for this tag. */
- for (entry = HTML_TAGS_TABLE; entry->name; entry++)
- {
- if (tag == entry->tag)
- break;
- }
-
- /* If found, output the equivalent string, enclosed in '<>' characters. */
- if (entry->name)
- {
- pf_buffer_character (filter, LESSTHAN);
- pf_buffer_string (filter, entry->name);
- pf_buffer_character (filter, GREATERTHAN);
- }
- else
- sc_error ("pf_buffer_tag: invalid tag, %ld\n", tag);
+pf_buffer_tag(sc_filterref_t filter, sc_int tag) {
+ const sc_html_tags_t *entry;
+ assert(pf_is_valid(filter));
+
+ /* Search the tags table for this tag. */
+ for (entry = HTML_TAGS_TABLE; entry->name; entry++) {
+ if (tag == entry->tag)
+ break;
+ }
+
+ /* If found, output the equivalent string, enclosed in '<>' characters. */
+ if (entry->name) {
+ pf_buffer_character(filter, LESSTHAN);
+ pf_buffer_string(filter, entry->name);
+ pf_buffer_character(filter, GREATERTHAN);
+ } else
+ sc_error("pf_buffer_tag: invalid tag, %ld\n", tag);
}
@@ -1253,34 +1146,31 @@ pf_buffer_tag (sc_filterref_t filter, sc_int tag)
* a newline if requested by allow_newlines.
*/
static void
-pf_strip_tags_common (sc_char *string, sc_bool allow_newlines)
-{
- sc_char *marker, *cursor;
-
- /* Run through the string looking for <...> tags. */
- marker = string;
- for (cursor = strchr (marker, LESSTHAN);
- cursor; cursor = strchr (marker, LESSTHAN))
- {
- sc_char *tag_end;
-
- /* Locate tag end, and break if unterminated. */
- tag_end = strchr (cursor, GREATERTHAN);
- if (!tag_end)
- break;
-
- /* If the tag is <br>, replace with newline if requested. */
- if (allow_newlines)
- {
- if (tag_end - cursor == 3
- && sc_strncasecmp (cursor + 1, "br", 2) == 0)
- *cursor++ = '\n';
- }
-
- /* Remove the tag from the string, then advance input. */
- memmove (cursor, tag_end + 1, strlen (tag_end));
- marker = cursor;
- }
+pf_strip_tags_common(sc_char *string, sc_bool allow_newlines) {
+ sc_char *marker, *cursor;
+
+ /* Run through the string looking for <...> tags. */
+ marker = string;
+ for (cursor = strchr(marker, LESSTHAN);
+ cursor; cursor = strchr(marker, LESSTHAN)) {
+ sc_char *tag_end;
+
+ /* Locate tag end, and break if unterminated. */
+ tag_end = strchr(cursor, GREATERTHAN);
+ if (!tag_end)
+ break;
+
+ /* If the tag is <br>, replace with newline if requested. */
+ if (allow_newlines) {
+ if (tag_end - cursor == 3
+ && sc_strncasecmp(cursor + 1, "br", 2) == 0)
+ *cursor++ = '\n';
+ }
+
+ /* Remove the tag from the string, then advance input. */
+ memmove(cursor, tag_end + 1, strlen(tag_end));
+ marker = cursor;
+ }
}
@@ -1292,15 +1182,13 @@ pf_strip_tags_common (sc_char *string, sc_bool allow_newlines)
* allow <br> tags to map into newlines in hints strings.
*/
void
-pf_strip_tags (sc_char *string)
-{
- pf_strip_tags_common (string, FALSE);
+pf_strip_tags(sc_char *string) {
+ pf_strip_tags_common(string, FALSE);
}
void
-pf_strip_tags_for_hints (sc_char *string)
-{
- pf_strip_tags_common (string, TRUE);
+pf_strip_tags_for_hints(sc_char *string) {
+ pf_strip_tags_common(string, TRUE);
}
@@ -1315,78 +1203,71 @@ pf_strip_tags_for_hints (sc_char *string)
* so the caller needs to remember to free it.
*/
sc_char *
-pf_escape (const sc_char *string)
-{
- const sc_char *marker, *cursor;
- sc_char *buffer;
-
- /* Start with an empty return buffer. */
- buffer = (sc_char *)sc_malloc (strlen (string) + 1);
- buffer[0] = NUL;
-
- /* Run through the string looking for <, >, %, or other escapes. */
- marker = string;
- for (cursor = marker + strcspn (marker, ESCAPES);
- cursor[0] != NUL; cursor = marker + strcspn (marker, ESCAPES))
- {
- const sc_char *escape;
- sc_char escape_buffer[3];
-
- /* Extend buffer to hold the string so far. */
- if (cursor > marker)
- {
- buffer = (sc_char *)sc_realloc (buffer, strlen (buffer) + cursor - marker + 1);
- buffer[strlen (buffer) + cursor - marker] = NUL;
- memcpy (buffer + strlen (buffer), marker, cursor - marker);
- }
-
- /* Determine the appropriate character escape. */
- if (cursor[0] == LESSTHAN)
- escape = ENTITY_LESSTHAN;
- else if (cursor[0] == GREATERTHAN)
- escape = ENTITY_GREATERTHAN;
- else if (cursor[0] == PERCENT)
- escape = ENTITY_PERCENT;
- else
- {
- /*
- * No real escape available, so fake, badly, by appending a space
- * for cases where we've encountered a character entity; leave
- * others untouched.
- */
- escape_buffer[0] = cursor[0];
- if (sc_strncasecmp (cursor,
- ENTITY_LESSTHAN, ENTITY_LENGTH) == 0
- || sc_strncasecmp (cursor,
- ENTITY_GREATERTHAN, ENTITY_LENGTH) == 0
- || sc_strncasecmp (cursor,
- ENTITY_PERCENT, PERCENT_LENGTH) == 0)
- {
- escape_buffer[1] = ' ';
- escape_buffer[2] = NUL;
- }
- else
- escape_buffer[1] = NUL;
- escape = escape_buffer;
- }
-
- buffer = (sc_char *)sc_realloc (buffer, strlen (buffer) + strlen (escape) + 1);
- strcat (buffer, escape);
-
- /* Pass over character escaped and continue. */
- cursor++;
- marker = cursor;
- }
-
- /* Add all remaining characters to the buffer. */
- if (cursor > marker)
- {
- buffer = (sc_char *)sc_realloc (buffer, strlen (buffer) + cursor - marker + 1);
- buffer[strlen (buffer) + cursor - marker] = NUL;
- memcpy (buffer + strlen (buffer), marker, cursor - marker);
- }
-
- return buffer;
+pf_escape(const sc_char *string) {
+ const sc_char *marker, *cursor;
+ sc_char *buffer;
+
+ /* Start with an empty return buffer. */
+ buffer = (sc_char *)sc_malloc(strlen(string) + 1);
+ buffer[0] = NUL;
+
+ /* Run through the string looking for <, >, %, or other escapes. */
+ marker = string;
+ for (cursor = marker + strcspn(marker, ESCAPES);
+ cursor[0] != NUL; cursor = marker + strcspn(marker, ESCAPES)) {
+ const sc_char *escape;
+ sc_char escape_buffer[3];
+
+ /* Extend buffer to hold the string so far. */
+ if (cursor > marker) {
+ buffer = (sc_char *)sc_realloc(buffer, strlen(buffer) + cursor - marker + 1);
+ buffer[strlen(buffer) + cursor - marker] = NUL;
+ memcpy(buffer + strlen(buffer), marker, cursor - marker);
+ }
+
+ /* Determine the appropriate character escape. */
+ if (cursor[0] == LESSTHAN)
+ escape = ENTITY_LESSTHAN;
+ else if (cursor[0] == GREATERTHAN)
+ escape = ENTITY_GREATERTHAN;
+ else if (cursor[0] == PERCENT)
+ escape = ENTITY_PERCENT;
+ else {
+ /*
+ * No real escape available, so fake, badly, by appending a space
+ * for cases where we've encountered a character entity; leave
+ * others untouched.
+ */
+ escape_buffer[0] = cursor[0];
+ if (sc_strncasecmp(cursor,
+ ENTITY_LESSTHAN, ENTITY_LENGTH) == 0
+ || sc_strncasecmp(cursor,
+ ENTITY_GREATERTHAN, ENTITY_LENGTH) == 0
+ || sc_strncasecmp(cursor,
+ ENTITY_PERCENT, PERCENT_LENGTH) == 0) {
+ escape_buffer[1] = ' ';
+ escape_buffer[2] = NUL;
+ } else
+ escape_buffer[1] = NUL;
+ escape = escape_buffer;
+ }
+
+ buffer = (sc_char *)sc_realloc(buffer, strlen(buffer) + strlen(escape) + 1);
+ strcat(buffer, escape);
+
+ /* Pass over character escaped and continue. */
+ cursor++;
+ marker = cursor;
+ }
+
+ /* Add all remaining characters to the buffer. */
+ if (cursor > marker) {
+ buffer = (sc_char *)sc_realloc(buffer, strlen(buffer) + cursor - marker + 1);
+ buffer[strlen(buffer) + cursor - marker] = NUL;
+ memcpy(buffer + strlen(buffer), marker, cursor - marker);
+ }
+
+ return buffer;
}
@@ -1397,52 +1278,50 @@ pf_escape (const sc_char *string)
* the match if the string matched, 0 otherwise.
*/
static sc_int
-pf_compare_words (const sc_char *string, const sc_char *words)
-{
- sc_int word_posn, posn;
-
- /* None expected, but skip leading space. */
- for (word_posn = 0; sc_isspace (words[word_posn]) && words[word_posn] != NUL;)
- word_posn++;
-
- /* Match characters from words with the string at position. */
- posn = 0;
- while (TRUE)
- {
- /* Any character mismatch means no words match. */
- if (sc_tolower (words[word_posn]) != sc_tolower (string[posn]))
- return 0;
-
- /* Move to next character in each. */
- word_posn++;
- posn++;
-
- /*
- * If at space, advance over whitespace in words list. Stop when we
- * hit the end of the words list.
- */
- while (sc_isspace (words[word_posn]) && words[word_posn] != NUL)
- word_posn++;
- if (words[word_posn] == NUL)
- break;
-
- /*
- * About to match another word, so advance over whitespace in the
- * current string too.
- */
- while (sc_isspace (string[posn]) && string[posn] != NUL)
- posn++;
- }
-
- /*
- * We reached the end of words. If we're at the end of the match string,
- * or at spaces, we've matched.
- */
- if (sc_isspace (string[posn]) || string[posn] == NUL)
- return posn;
-
- /* More text after the match, so it's not quite a match. */
- return 0;
+pf_compare_words(const sc_char *string, const sc_char *words) {
+ sc_int word_posn, posn;
+
+ /* None expected, but skip leading space. */
+ for (word_posn = 0; sc_isspace(words[word_posn]) && words[word_posn] != NUL;)
+ word_posn++;
+
+ /* Match characters from words with the string at position. */
+ posn = 0;
+ while (TRUE) {
+ /* Any character mismatch means no words match. */
+ if (sc_tolower(words[word_posn]) != sc_tolower(string[posn]))
+ return 0;
+
+ /* Move to next character in each. */
+ word_posn++;
+ posn++;
+
+ /*
+ * If at space, advance over whitespace in words list. Stop when we
+ * hit the end of the words list.
+ */
+ while (sc_isspace(words[word_posn]) && words[word_posn] != NUL)
+ word_posn++;
+ if (words[word_posn] == NUL)
+ break;
+
+ /*
+ * About to match another word, so advance over whitespace in the
+ * current string too.
+ */
+ while (sc_isspace(string[posn]) && string[posn] != NUL)
+ posn++;
+ }
+
+ /*
+ * We reached the end of words. If we're at the end of the match string,
+ * or at spaces, we've matched.
+ */
+ if (sc_isspace(string[posn]) || string[posn] == NUL)
+ return posn;
+
+ /* More text after the match, so it's not quite a match. */
+ return 0;
}
@@ -1454,122 +1333,113 @@ pf_compare_words (const sc_char *string, const sc_char *words)
* return string is malloc'ed, so the caller needs to remember to free it.
*/
sc_char *
-pf_filter_input (const sc_char *string, sc_prop_setref_t bundle)
-{
- sc_vartype_t vt_key[3];
- sc_int synonym_count, buffer_allocation;
- sc_char *buffer;
- const sc_char *current;
- assert (string && bundle);
-
- if (pf_trace)
- sc_trace ("Printfilter: input \"%s\"\n", string);
-
- /* Obtain a count of synonyms. */
- vt_key[0].string = "Synonyms";
- synonym_count = prop_get_child_count (bundle, "I<-s", vt_key);
-
- /* Begin with a NULL buffer for lazy allocation. */
- buffer_allocation = 0;
- buffer = NULL;
-
- /* Loop over each word in the string. */
- current = string + strspn (string, WHITESPACE);
- while (current[0] != NUL)
- {
- sc_int index_, extent;
-
- /* Search for a synonym match at this index into the buffer. */
- extent = 0;
- for (index_ = 0; index_ < synonym_count; index_++)
- {
- const sc_char *original;
-
- /* Retrieve the synonym original string. */
- vt_key[0].string = "Synonyms";
- vt_key[1].integer = index_;
- vt_key[2].string = "Original";
- original = prop_get_string (bundle, "S<-sis", vt_key);
-
- /* Compare the original at this point. */
- extent = pf_compare_words (current, original);
- if (extent > 0)
- break;
- }
-
- /*
- * If a synonym found was, index_ indicates it, and extent shows how
- * much of the buffer to replace with it.
- */
- if (index_ < synonym_count && extent > 0)
- {
- const sc_char *replacement;
- sc_char *position;
- sc_int length, final;
-
- /*
- * If not yet allocated, allocate a buffer now, and copy the input
- * string into it. Then switch current to the equivalent location
- * in the allocated buffer. More basic copy-on-write.
- */
- if (!buffer)
- {
- buffer_allocation = strlen (string) + 1;
- buffer = (sc_char *)sc_malloc (buffer_allocation);
- strcpy (buffer, string);
- current = buffer + (current - string);
- }
-
- /* Find the replacement text for this synonym. */
- vt_key[0].string = "Synonyms";
- vt_key[1].integer = index_;
- vt_key[2].string = "Replacement";
- replacement = prop_get_string (bundle, "S<-sis", vt_key);
- length = strlen (replacement);
-
- /*
- * If necessary, grow the output buffer for the replacement,
- * remembering to adjust current for the new buffer allocated.
- * At the same time, note the last character index for the move.
- */
- if (length > extent)
- {
- sc_int offset;
-
- offset = current - buffer;
- buffer_allocation += length - extent;
- buffer = (sc_char *)sc_realloc (buffer, buffer_allocation);
- current = buffer + offset;
- final = length;
- }
- else
- final = extent;
-
- /* Insert the replacement string into the buffer. */
- position = buffer + (current - buffer);
- memmove (position + length,
- position + extent,
- buffer_allocation - (current - buffer) - final);
- memcpy (position, replacement, length);
-
- /* Adjust current to skip over the replacement. */
- current += length;
-
- if (pf_trace)
- sc_trace ("Printfilter: synonym \"%s\"\n", buffer);
- }
- else
- {
- /* If no match, advance current over the unmatched word. */
- current += strcspn (current, WHITESPACE);
- }
-
- /* Set current to the next word start. */
- current += strspn (current, WHITESPACE);
- }
-
- /* Return the final string, or NULL if no synonym replacements. */
- return buffer;
+pf_filter_input(const sc_char *string, sc_prop_setref_t bundle) {
+ sc_vartype_t vt_key[3];
+ sc_int synonym_count, buffer_allocation;
+ sc_char *buffer;
+ const sc_char *current;
+ assert(string && bundle);
+
+ if (pf_trace)
+ sc_trace("Printfilter: input \"%s\"\n", string);
+
+ /* Obtain a count of synonyms. */
+ vt_key[0].string = "Synonyms";
+ synonym_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ /* Begin with a NULL buffer for lazy allocation. */
+ buffer_allocation = 0;
+ buffer = NULL;
+
+ /* Loop over each word in the string. */
+ current = string + strspn(string, WHITESPACE);
+ while (current[0] != NUL) {
+ sc_int index_, extent;
+
+ /* Search for a synonym match at this index into the buffer. */
+ extent = 0;
+ for (index_ = 0; index_ < synonym_count; index_++) {
+ const sc_char *original;
+
+ /* Retrieve the synonym original string. */
+ vt_key[0].string = "Synonyms";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "Original";
+ original = prop_get_string(bundle, "S<-sis", vt_key);
+
+ /* Compare the original at this point. */
+ extent = pf_compare_words(current, original);
+ if (extent > 0)
+ break;
+ }
+
+ /*
+ * If a synonym found was, index_ indicates it, and extent shows how
+ * much of the buffer to replace with it.
+ */
+ if (index_ < synonym_count && extent > 0) {
+ const sc_char *replacement;
+ sc_char *position;
+ sc_int length, final;
+
+ /*
+ * If not yet allocated, allocate a buffer now, and copy the input
+ * string into it. Then switch current to the equivalent location
+ * in the allocated buffer. More basic copy-on-write.
+ */
+ if (!buffer) {
+ buffer_allocation = strlen(string) + 1;
+ buffer = (sc_char *)sc_malloc(buffer_allocation);
+ strcpy(buffer, string);
+ current = buffer + (current - string);
+ }
+
+ /* Find the replacement text for this synonym. */
+ vt_key[0].string = "Synonyms";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "Replacement";
+ replacement = prop_get_string(bundle, "S<-sis", vt_key);
+ length = strlen(replacement);
+
+ /*
+ * If necessary, grow the output buffer for the replacement,
+ * remembering to adjust current for the new buffer allocated.
+ * At the same time, note the last character index for the move.
+ */
+ if (length > extent) {
+ sc_int offset;
+
+ offset = current - buffer;
+ buffer_allocation += length - extent;
+ buffer = (sc_char *)sc_realloc(buffer, buffer_allocation);
+ current = buffer + offset;
+ final = length;
+ } else
+ final = extent;
+
+ /* Insert the replacement string into the buffer. */
+ position = buffer + (current - buffer);
+ memmove(position + length,
+ position + extent,
+ buffer_allocation - (current - buffer) - final);
+ memcpy(position, replacement, length);
+
+ /* Adjust current to skip over the replacement. */
+ current += length;
+
+ if (pf_trace)
+ sc_trace("Printfilter: synonym \"%s\"\n", buffer);
+ } else {
+ /* If no match, advance current over the unmatched word. */
+ current += strcspn(current, WHITESPACE);
+ }
+
+ /* Set current to the next word start. */
+ current += strspn(current, WHITESPACE);
+ }
+
+ /* Return the final string, or NULL if no synonym replacements. */
+ return buffer;
}
@@ -1579,9 +1449,8 @@ pf_filter_input (const sc_char *string, sc_prop_setref_t bundle)
* Set filter tracing on/off.
*/
void
-pf_debug_trace (sc_bool flag)
-{
- pf_trace = flag;
+pf_debug_trace(sc_bool flag) {
+ pf_trace = flag;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scprops.cpp b/engines/glk/adrift/scprops.cpp
index bdf51dc4db..aeb0d24db0 100644
--- a/engines/glk/adrift/scprops.cpp
+++ b/engines/glk/adrift/scprops.cpp
@@ -28,10 +28,10 @@ namespace Adrift {
/* Assorted definitions and constants. */
static const sc_uint PROP_MAGIC = 0x7927b2e0;
-enum
-{ PROP_GROW_INCREMENT = 32,
- MAX_INTEGER_KEY = 65535,
- NODE_POOL_CAPACITY = 512
+enum {
+ PROP_GROW_INCREMENT = 32,
+ MAX_INTEGER_KEY = 65535,
+ NODE_POOL_CAPACITY = 512
};
static const sc_char NUL = '\0';
@@ -81,9 +81,8 @@ typedef sc_prop_set_s sc_prop_set_t;
* Return TRUE if pointer is a valid properties set, FALSE otherwise.
*/
static sc_bool
-prop_is_valid (sc_prop_setref_t bundle)
-{
- return bundle && bundle->magic == PROP_MAGIC;
+prop_is_valid(sc_prop_setref_t bundle) {
+ return bundle && bundle->magic == PROP_MAGIC;
}
@@ -93,12 +92,11 @@ prop_is_valid (sc_prop_setref_t bundle)
* Round up a count of elements to the next block of grow increments.
*/
static sc_int
-prop_round_up (sc_int elements)
-{
- sc_int extended;
+prop_round_up(sc_int elements) {
+ sc_int extended;
- extended = elements + PROP_GROW_INCREMENT - 1;
- return (extended / PROP_GROW_INCREMENT) * PROP_GROW_INCREMENT;
+ extended = elements + PROP_GROW_INCREMENT - 1;
+ return (extended / PROP_GROW_INCREMENT) * PROP_GROW_INCREMENT;
}
@@ -114,31 +112,29 @@ prop_round_up (sc_int elements)
* frequently.
*/
static void *
-prop_ensure_capacity (void *array,
- sc_int old_size, sc_int new_size, sc_int element_size)
-{
- sc_int current, required;
-
- /*
- * See if there's any resize necessary, that is, does the new size round up
- * to a larger number of elements than the old size.
- */
- current = prop_round_up (old_size);
- required = prop_round_up (new_size);
- if (required > current)
- {
- sc_byte *new_array, *start_clearing;
-
- /* Grow array to the required size, and zero new elements. */
- new_array = (sc_byte *)sc_realloc (array, required * element_size);
- start_clearing = new_array + current * element_size;
- memset (start_clearing, 0, (required - current) * element_size);
-
- return new_array;
- }
-
- /* No resize necessary. */
- return array;
+prop_ensure_capacity(void *array,
+ sc_int old_size, sc_int new_size, sc_int element_size) {
+ sc_int current, required;
+
+ /*
+ * See if there's any resize necessary, that is, does the new size round up
+ * to a larger number of elements than the old size.
+ */
+ current = prop_round_up(old_size);
+ required = prop_round_up(new_size);
+ if (required > current) {
+ sc_byte *new_array, *start_clearing;
+
+ /* Grow array to the required size, and zero new elements. */
+ new_array = (sc_byte *)sc_realloc(array, required * element_size);
+ start_clearing = new_array + current * element_size;
+ memset(start_clearing, 0, (required - current) * element_size);
+
+ return new_array;
+ }
+
+ /* No resize necessary. */
+ return array;
}
@@ -150,12 +146,11 @@ prop_ensure_capacity (void *array,
* the array cannot ever be grown safely again.
*/
static void *
-prop_trim_capacity (void *array, sc_int size, sc_int element_size)
-{
- if (prop_round_up (size) > size)
- return sc_realloc (array, size * element_size);
- else
- return array;
+prop_trim_capacity(void *array, sc_int size, sc_int element_size) {
+ if (prop_round_up(size) > size)
+ return sc_realloc(array, size * element_size);
+ else
+ return array;
}
@@ -167,9 +162,8 @@ prop_trim_capacity (void *array, sc_int size, sc_int element_size)
* bsearch() and qsort().
*/
static int
-prop_compare (const void *string1, const void *string2)
-{
- return strcmp (*(sc_char *const *) string1, *(sc_char *const *) string2);
+prop_compare(const void *string1, const void *string2) {
+ return strcmp(*(sc_char * const *) string1, *(sc_char * const *) string2);
}
@@ -182,44 +176,42 @@ prop_compare (const void *string1, const void *string2)
* contain a malloced copy of the string passed in.
*/
static const sc_char *
-prop_dictionary_lookup (sc_prop_setref_t bundle, const sc_char *string)
-{
- sc_char *dict_string;
-
- /*
- * Search the existing dictionary for the string. Although not GNU libc,
- * some libc's loop or crash when given a list of zero length, so we need to
- * trap that here.
- */
- if (bundle->dictionary_length > 0)
- {
- const sc_char *const *dict_search;
-
- dict_search = (const sc_char *const *)bsearch (&string, bundle->dictionary,
- bundle->dictionary_length,
- sizeof (bundle->dictionary[0]), prop_compare);
- if (dict_search)
- return *dict_search;
- }
-
- /* Not found, so copy the string for dictionary insertion. */
- dict_string = (sc_char *)sc_malloc (strlen (string) + 1);
- strcpy (dict_string, string);
-
- /* Extend the dictionary if necessary. */
- bundle->dictionary = (sc_char **)prop_ensure_capacity (bundle->dictionary,
- bundle->dictionary_length,
- bundle->dictionary_length + 1,
- sizeof (bundle->dictionary[0]));
-
- /* Add the new entry to the end of the dictionary array, and sort. */
- bundle->dictionary[bundle->dictionary_length++] = dict_string;
- qsort (bundle->dictionary,
- bundle->dictionary_length,
- sizeof (bundle->dictionary[0]), prop_compare);
-
- /* Return the address of the new string. */
- return dict_string;
+prop_dictionary_lookup(sc_prop_setref_t bundle, const sc_char *string) {
+ sc_char *dict_string;
+
+ /*
+ * Search the existing dictionary for the string. Although not GNU libc,
+ * some libc's loop or crash when given a list of zero length, so we need to
+ * trap that here.
+ */
+ if (bundle->dictionary_length > 0) {
+ const sc_char *const *dict_search;
+
+ dict_search = (const sc_char * const *)bsearch(&string, bundle->dictionary,
+ bundle->dictionary_length,
+ sizeof(bundle->dictionary[0]), prop_compare);
+ if (dict_search)
+ return *dict_search;
+ }
+
+ /* Not found, so copy the string for dictionary insertion. */
+ dict_string = (sc_char *)sc_malloc(strlen(string) + 1);
+ strcpy(dict_string, string);
+
+ /* Extend the dictionary if necessary. */
+ bundle->dictionary = (sc_char **)prop_ensure_capacity(bundle->dictionary,
+ bundle->dictionary_length,
+ bundle->dictionary_length + 1,
+ sizeof(bundle->dictionary[0]));
+
+ /* Add the new entry to the end of the dictionary array, and sort. */
+ bundle->dictionary[bundle->dictionary_length++] = dict_string;
+ qsort(bundle->dictionary,
+ bundle->dictionary_length,
+ sizeof(bundle->dictionary[0]), prop_compare);
+
+ /* Return the address of the new string. */
+ return dict_string;
}
@@ -232,36 +224,34 @@ prop_dictionary_lookup (sc_prop_setref_t bundle, const sc_char *string)
* malloc's of small individual nodes.
*/
static sc_prop_noderef_t
-prop_new_node (sc_prop_setref_t bundle)
-{
- sc_int node_index;
- sc_prop_noderef_t node;
-
- /* See if we need to create a new node pool. */
- node_index = bundle->node_count % NODE_POOL_CAPACITY;
- if (node_index == 0)
- {
- sc_int required;
-
- /* Extend the node pools array if necessary. */
- bundle->node_pools = (sc_prop_noderef_t *)prop_ensure_capacity (bundle->node_pools,
- bundle->node_pools_length,
- bundle->node_pools_length + 1,
- sizeof (bundle->
- node_pools[0]));
-
- /* Create a new node pool, and increment the length. */
- required = NODE_POOL_CAPACITY * sizeof (*bundle->node_pools[0]);
- bundle->node_pools[bundle->node_pools_length] = (sc_prop_noderef_t)sc_malloc(required);
- bundle->node_pools_length++;
- }
-
- /* Find the next node address, and increment the node counter. */
- node = bundle->node_pools[bundle->node_pools_length - 1] + node_index;
- bundle->node_count++;
-
- /* Return the new node. */
- return node;
+prop_new_node(sc_prop_setref_t bundle) {
+ sc_int node_index;
+ sc_prop_noderef_t node;
+
+ /* See if we need to create a new node pool. */
+ node_index = bundle->node_count % NODE_POOL_CAPACITY;
+ if (node_index == 0) {
+ sc_int required;
+
+ /* Extend the node pools array if necessary. */
+ bundle->node_pools = (sc_prop_noderef_t *)prop_ensure_capacity(bundle->node_pools,
+ bundle->node_pools_length,
+ bundle->node_pools_length + 1,
+ sizeof(bundle->
+ node_pools[0]));
+
+ /* Create a new node pool, and increment the length. */
+ required = NODE_POOL_CAPACITY * sizeof(*bundle->node_pools[0]);
+ bundle->node_pools[bundle->node_pools_length] = (sc_prop_noderef_t)sc_malloc(required);
+ bundle->node_pools_length++;
+ }
+
+ /* Find the next node address, and increment the node counter. */
+ node = bundle->node_pools[bundle->node_pools_length - 1] + node_index;
+ bundle->node_count++;
+
+ /* Return the new node. */
+ return node;
}
@@ -271,73 +261,66 @@ prop_new_node (sc_prop_setref_t bundle)
* Find a child node of the given parent whose name matches that passed in.
*/
static sc_prop_noderef_t
-prop_find_child (sc_prop_noderef_t parent, sc_int type, sc_vartype_t name)
-{
- /* See if this node has any children. */
- if (parent->child_list)
- {
- sc_int index_;
- sc_prop_noderef_t child;
-
- /* Do the lookup based on name type. */
- switch (type)
- {
- case PROP_KEY_INTEGER:
- /*
- * As with adding a child below, here we'll range-check an integer
- * key just to make sure nobody has any unreal expectations of us.
- */
- if (name.integer < 0)
- sc_fatal ("prop_find_child: integer key cannot be negative\n");
- else if (name.integer > MAX_INTEGER_KEY)
- sc_fatal ("prop_find_child: integer key is too large\n");
-
- /*
- * For integer lookups, return the child at the indexed offset
- * directly, provided it exists.
- */
- if (name.integer >= 0 && name.integer < parent->property.integer)
- {
- child = parent->child_list[name.integer];
- return child;
- }
- break;
-
- case PROP_KEY_STRING:
- /* Scan children for a string name match. */
- for (index_ = 0; index_ < parent->property.integer; index_++)
- {
- child = parent->child_list[index_];
- if (strcmp (child->name.string, name.string) == 0)
- break;
- }
-
- /* Return child if we found a match. */
- if (index_ < parent->property.integer)
- {
- /*
- * Before returning the child, try to improve future scans by
- * moving the matched entry to index_ 0 -- this gives a key set
- * sorted by recent usage, helpful as the same string key is
- * used repeatedly in loops.
- */
- if (index_ > 0)
- {
- memmove (parent->child_list + 1,
- parent->child_list, index_ * sizeof (child));
- parent->child_list[0] = child;
- }
- return child;
- }
- break;
-
- default:
- sc_fatal ("prop_find_child: invalid key type\n");
- }
- }
-
- /* No matching child found. */
- return NULL;
+prop_find_child(sc_prop_noderef_t parent, sc_int type, sc_vartype_t name) {
+ /* See if this node has any children. */
+ if (parent->child_list) {
+ sc_int index_;
+ sc_prop_noderef_t child;
+
+ /* Do the lookup based on name type. */
+ switch (type) {
+ case PROP_KEY_INTEGER:
+ /*
+ * As with adding a child below, here we'll range-check an integer
+ * key just to make sure nobody has any unreal expectations of us.
+ */
+ if (name.integer < 0)
+ sc_fatal("prop_find_child: integer key cannot be negative\n");
+ else if (name.integer > MAX_INTEGER_KEY)
+ sc_fatal("prop_find_child: integer key is too large\n");
+
+ /*
+ * For integer lookups, return the child at the indexed offset
+ * directly, provided it exists.
+ */
+ if (name.integer >= 0 && name.integer < parent->property.integer) {
+ child = parent->child_list[name.integer];
+ return child;
+ }
+ break;
+
+ case PROP_KEY_STRING:
+ /* Scan children for a string name match. */
+ for (index_ = 0; index_ < parent->property.integer; index_++) {
+ child = parent->child_list[index_];
+ if (strcmp(child->name.string, name.string) == 0)
+ break;
+ }
+
+ /* Return child if we found a match. */
+ if (index_ < parent->property.integer) {
+ /*
+ * Before returning the child, try to improve future scans by
+ * moving the matched entry to index_ 0 -- this gives a key set
+ * sorted by recent usage, helpful as the same string key is
+ * used repeatedly in loops.
+ */
+ if (index_ > 0) {
+ memmove(parent->child_list + 1,
+ parent->child_list, index_ * sizeof(child));
+ parent->child_list[0] = child;
+ }
+ return child;
+ }
+ break;
+
+ default:
+ sc_fatal("prop_find_child: invalid key type\n");
+ }
+ }
+
+ /* No matching child found. */
+ return NULL;
}
@@ -348,83 +331,80 @@ prop_find_child (sc_prop_noderef_t parent, sc_int type, sc_vartype_t name)
* needs to be passed so that string names can be added to the dictionary.
*/
static sc_prop_noderef_t
-prop_add_child (sc_prop_noderef_t parent,
- sc_int type, sc_vartype_t name, sc_prop_setref_t bundle)
-{
- sc_prop_noderef_t child;
-
- /* Not possible if growable allocations have been trimmed. */
- if (bundle->is_readonly)
- sc_fatal ("prop_add_child: can't add to readonly properties\n");
-
- /* Create the new node. */
- child = prop_new_node (bundle);
- switch (type)
- {
- case PROP_KEY_INTEGER:
- child->name.integer = name.integer;
- break;
- case PROP_KEY_STRING:
- child->name.string = prop_dictionary_lookup (bundle, name.string);
- break;
-
- default:
- sc_fatal ("prop_add_child: invalid key type\n");
- }
-
- /* Initialize property and child list to visible nulls. */
- child->property.voidp = NULL;
- child->child_list = NULL;
-
- /* Make a brief check for obvious overwrites. */
- if (!parent->child_list && parent->property.voidp)
- sc_error ("prop_add_child: node overwritten, probable data loss\n");
-
- /* Add the child to the parent, position dependent on key type. */
- switch (type)
- {
- case PROP_KEY_INTEGER:
- /*
- * Range check on integer keys, must be >= 0 for direct indexing to work,
- * and we'll also apply a reasonableness constraint, to try to catch
- * errors where string pointers are passed in as integers, which would
- * otherwise lead to some extreme malloc() attempts.
- */
- if (name.integer < 0)
- sc_fatal ("prop_add_child: integer key cannot be negative\n");
- else if (name.integer > MAX_INTEGER_KEY)
- sc_fatal ("prop_add_child: integer key is too large\n");
-
- /* Resize the parent's child list if necessary. */
- parent->child_list = (sc_prop_noderef_t *)prop_ensure_capacity (parent->child_list,
- parent->property.integer,
- name.integer + 1,
- sizeof (*parent->child_list));
-
- /* Update the child count if the new node increases it. */
- if (parent->property.integer <= name.integer)
- parent->property.integer = name.integer + 1;
-
- /* Store the child in its indexed list location. */
- parent->child_list[name.integer] = child;
- break;
-
- case PROP_KEY_STRING:
- /* Add a single entry to the child list, and resize. */
- parent->child_list = (sc_prop_noderef_t *)prop_ensure_capacity (parent->child_list,
- parent->property.integer,
- parent->property.integer + 1,
- sizeof (*parent->child_list));
-
- /* Store the child at the end of the list. */
- parent->child_list[parent->property.integer++] = child;
- break;
-
- default:
- sc_fatal ("prop_add_child: invalid key type\n");
- }
-
- return child;
+prop_add_child(sc_prop_noderef_t parent,
+ sc_int type, sc_vartype_t name, sc_prop_setref_t bundle) {
+ sc_prop_noderef_t child;
+
+ /* Not possible if growable allocations have been trimmed. */
+ if (bundle->is_readonly)
+ sc_fatal("prop_add_child: can't add to readonly properties\n");
+
+ /* Create the new node. */
+ child = prop_new_node(bundle);
+ switch (type) {
+ case PROP_KEY_INTEGER:
+ child->name.integer = name.integer;
+ break;
+ case PROP_KEY_STRING:
+ child->name.string = prop_dictionary_lookup(bundle, name.string);
+ break;
+
+ default:
+ sc_fatal("prop_add_child: invalid key type\n");
+ }
+
+ /* Initialize property and child list to visible nulls. */
+ child->property.voidp = NULL;
+ child->child_list = NULL;
+
+ /* Make a brief check for obvious overwrites. */
+ if (!parent->child_list && parent->property.voidp)
+ sc_error("prop_add_child: node overwritten, probable data loss\n");
+
+ /* Add the child to the parent, position dependent on key type. */
+ switch (type) {
+ case PROP_KEY_INTEGER:
+ /*
+ * Range check on integer keys, must be >= 0 for direct indexing to work,
+ * and we'll also apply a reasonableness constraint, to try to catch
+ * errors where string pointers are passed in as integers, which would
+ * otherwise lead to some extreme malloc() attempts.
+ */
+ if (name.integer < 0)
+ sc_fatal("prop_add_child: integer key cannot be negative\n");
+ else if (name.integer > MAX_INTEGER_KEY)
+ sc_fatal("prop_add_child: integer key is too large\n");
+
+ /* Resize the parent's child list if necessary. */
+ parent->child_list = (sc_prop_noderef_t *)prop_ensure_capacity(parent->child_list,
+ parent->property.integer,
+ name.integer + 1,
+ sizeof(*parent->child_list));
+
+ /* Update the child count if the new node increases it. */
+ if (parent->property.integer <= name.integer)
+ parent->property.integer = name.integer + 1;
+
+ /* Store the child in its indexed list location. */
+ parent->child_list[name.integer] = child;
+ break;
+
+ case PROP_KEY_STRING:
+ /* Add a single entry to the child list, and resize. */
+ parent->child_list = (sc_prop_noderef_t *)prop_ensure_capacity(parent->child_list,
+ parent->property.integer,
+ parent->property.integer + 1,
+ sizeof(*parent->child_list));
+
+ /* Store the child at the end of the list. */
+ parent->child_list[parent->property.integer++] = child;
+ break;
+
+ default:
+ sc_fatal("prop_add_child: invalid key type\n");
+ }
+
+ return child;
}
@@ -443,104 +423,97 @@ prop_add_child (sc_prop_noderef_t parent,
* integer, and another string.
*/
void
-prop_put (sc_prop_setref_t bundle, const sc_char *format,
- sc_vartype_t vt_value, const sc_vartype_t vt_key[])
-{
- sc_prop_noderef_t node;
- sc_int index_;
- assert (prop_is_valid (bundle));
-
- /* Format check. */
- if (!format || format[0] == NUL
- || format[1] != '-' || format[2] != '>' || format[3] == NUL)
- sc_fatal ("prop_put: format error\n");
-
- /* Trace property put. */
- if (prop_trace)
- {
- sc_trace ("Property: put ");
- switch (format[0])
- {
- case PROP_STRING:
- sc_trace ("\"%s\"", vt_value.string);
- break;
- case PROP_INTEGER:
- sc_trace ("%ld", vt_value.integer);
- break;
- case PROP_BOOLEAN:
- sc_trace ("%s", vt_value.boolean ? "true" : "false");
- break;
-
- default:
- sc_trace ("%p [invalid type]", vt_value.voidp);
- break;
- }
- sc_trace (", key \"%s\" : ", format);
- for (index_ = 0; format[index_ + 3] != NUL; index_++)
- {
- sc_trace ("%s", index_ > 0 ? "," : "");
- switch (format[index_ + 3])
- {
- case PROP_KEY_STRING:
- sc_trace ("\"%s\"", vt_key[index_].string);
- break;
- case PROP_KEY_INTEGER:
- sc_trace ("%ld", vt_key[index_].integer);
- break;
-
- default:
- sc_trace ("%p [invalid type]", vt_key[index_].voidp);
- break;
- }
- }
- sc_trace ("\n");
- }
-
- /*
- * Iterate keys, finding matching child nodes at each level. If no matching
- * child is found, insert one and continue.
- */
- node = bundle->root_node;
- for (index_ = 0; format[index_ + 3] != NUL; index_++)
- {
- sc_prop_noderef_t child;
- sc_int type;
-
- /*
- * Search this level for a name matching the key. If found, advance
- * to that child node. Otherwise, add the node to the tree, including
- * the set so that the dictionary can be extended.
- */
- type = format[index_ + 3];
- child = prop_find_child (node, type, vt_key[index_]);
- if (child)
- node = child;
- else
- node = prop_add_child (node, type, vt_key[index_], bundle);
- }
-
- /*
- * Ensure that we're not about to overwrite an internal node child count.
- */
- if (node->child_list)
- sc_fatal ("prop_put: overwrite of internal node\n");
-
- /* Set our properties in the final node. */
- switch (format[0])
- {
- case PROP_INTEGER:
- node->property.integer = vt_value.integer;
- break;
- case PROP_BOOLEAN:
- node->property.boolean = vt_value.boolean;
- break;
- case PROP_STRING:
- node->property.string = vt_value.string;
- break;
-
- default:
- sc_fatal ("prop_put: invalid property type\n");
- }
+prop_put(sc_prop_setref_t bundle, const sc_char *format,
+ sc_vartype_t vt_value, const sc_vartype_t vt_key[]) {
+ sc_prop_noderef_t node;
+ sc_int index_;
+ assert(prop_is_valid(bundle));
+
+ /* Format check. */
+ if (!format || format[0] == NUL
+ || format[1] != '-' || format[2] != '>' || format[3] == NUL)
+ sc_fatal("prop_put: format error\n");
+
+ /* Trace property put. */
+ if (prop_trace) {
+ sc_trace("Property: put ");
+ switch (format[0]) {
+ case PROP_STRING:
+ sc_trace("\"%s\"", vt_value.string);
+ break;
+ case PROP_INTEGER:
+ sc_trace("%ld", vt_value.integer);
+ break;
+ case PROP_BOOLEAN:
+ sc_trace("%s", vt_value.boolean ? "true" : "false");
+ break;
+
+ default:
+ sc_trace("%p [invalid type]", vt_value.voidp);
+ break;
+ }
+ sc_trace(", key \"%s\" : ", format);
+ for (index_ = 0; format[index_ + 3] != NUL; index_++) {
+ sc_trace("%s", index_ > 0 ? "," : "");
+ switch (format[index_ + 3]) {
+ case PROP_KEY_STRING:
+ sc_trace("\"%s\"", vt_key[index_].string);
+ break;
+ case PROP_KEY_INTEGER:
+ sc_trace("%ld", vt_key[index_].integer);
+ break;
+
+ default:
+ sc_trace("%p [invalid type]", vt_key[index_].voidp);
+ break;
+ }
+ }
+ sc_trace("\n");
+ }
+
+ /*
+ * Iterate keys, finding matching child nodes at each level. If no matching
+ * child is found, insert one and continue.
+ */
+ node = bundle->root_node;
+ for (index_ = 0; format[index_ + 3] != NUL; index_++) {
+ sc_prop_noderef_t child;
+ sc_int type;
+
+ /*
+ * Search this level for a name matching the key. If found, advance
+ * to that child node. Otherwise, add the node to the tree, including
+ * the set so that the dictionary can be extended.
+ */
+ type = format[index_ + 3];
+ child = prop_find_child(node, type, vt_key[index_]);
+ if (child)
+ node = child;
+ else
+ node = prop_add_child(node, type, vt_key[index_], bundle);
+ }
+
+ /*
+ * Ensure that we're not about to overwrite an internal node child count.
+ */
+ if (node->child_list)
+ sc_fatal("prop_put: overwrite of internal node\n");
+
+ /* Set our properties in the final node. */
+ switch (format[0]) {
+ case PROP_INTEGER:
+ node->property.integer = vt_value.integer;
+ break;
+ case PROP_BOOLEAN:
+ node->property.boolean = vt_value.boolean;
+ break;
+ case PROP_STRING:
+ node->property.string = vt_value.string;
+ break;
+
+ default:
+ sc_fatal("prop_put: invalid property type\n");
+ }
}
@@ -551,114 +524,105 @@ prop_put (sc_prop_setref_t bundle, const sc_char *format,
* with "->" replaced with "<-". Returns FALSE if no such property exists.
*/
sc_bool
-prop_get (sc_prop_setref_t bundle, const sc_char *format,
- sc_vartype_t *vt_rvalue, const sc_vartype_t vt_key[])
-{
- sc_prop_noderef_t node;
- sc_int index_;
- assert (prop_is_valid (bundle));
-
- /* Format check. */
- if (!format || format[0] == NUL
- || format[1] != '<' || format[2] != '-' || format[3] == NUL)
- sc_fatal ("prop_get: format error\n");
-
- /* Trace property get. */
- if (prop_trace)
- {
- sc_trace ("Property: get, key \"%s\" : ", format);
- for (index_ = 0; format[index_ + 3] != NUL; index_++)
- {
- sc_trace ("%s", index_ > 0 ? "," : "");
- switch (format[index_ + 3])
- {
- case PROP_KEY_STRING:
- sc_trace ("\"%s\"", vt_key[index_].string);
- break;
- case PROP_KEY_INTEGER:
- sc_trace ("%ld", vt_key[index_].integer);
- break;
-
- default:
- sc_trace ("%p [invalid type]", vt_key[index_].voidp);
- break;
- }
- }
- sc_trace ("\n");
- }
-
- /*
- * Iterate keys, finding matching child nodes at each level. Stop if no
- * matching child is found.
- */
- node = bundle->root_node;
- for (index_ = 0; format[index_ + 3] != NUL; index_++)
- {
- sc_int type;
-
- /* Move node down to the matching child, NULL if no match. */
- type = format[index_ + 3 ];
- node = prop_find_child (node, type, vt_key[index_]);
- if (!node)
- break;
- }
-
- /* If key iteration halted because no child was found, return FALSE. */
- if (!node)
- {
- if (prop_trace)
- sc_trace ("Property: ...get FAILED\n");
-
- return FALSE;
- }
-
- /*
- * Enforce integer-only queries on internal nodes, since this is the only
- * type of query that makes sense -- any other type is probably a mistake.
- */
- if (node->child_list && format[0] != PROP_INTEGER)
- sc_fatal ("prop_get: only integer gets on internal nodes\n");
-
- /* Return the properties of the final node. */
- switch (format[0])
- {
- case PROP_INTEGER:
- vt_rvalue->integer = node->property.integer;
- break;
- case PROP_BOOLEAN:
- vt_rvalue->boolean = node->property.boolean;
- break;
- case PROP_STRING:
- vt_rvalue->string = node->property.string;
- break;
-
- default:
- sc_fatal ("prop_get: invalid property type\n");
- }
-
- /* Complete tracing property get. */
- if (prop_trace)
- {
- sc_trace ("Property: ...get returned : ");
- switch (format[0])
- {
- case PROP_STRING:
- sc_trace ("\"%s\"", vt_rvalue->string);
- break;
- case PROP_INTEGER:
- sc_trace ("%ld", vt_rvalue->integer);
- break;
- case PROP_BOOLEAN:
- sc_trace ("%s", vt_rvalue->boolean ? "true" : "false");
- break;
-
- default:
- sc_trace ("%p [invalid type]", vt_rvalue->voidp);
- break;
- }
- sc_trace ("\n");
- }
- return TRUE;
+prop_get(sc_prop_setref_t bundle, const sc_char *format,
+ sc_vartype_t *vt_rvalue, const sc_vartype_t vt_key[]) {
+ sc_prop_noderef_t node;
+ sc_int index_;
+ assert(prop_is_valid(bundle));
+
+ /* Format check. */
+ if (!format || format[0] == NUL
+ || format[1] != '<' || format[2] != '-' || format[3] == NUL)
+ sc_fatal("prop_get: format error\n");
+
+ /* Trace property get. */
+ if (prop_trace) {
+ sc_trace("Property: get, key \"%s\" : ", format);
+ for (index_ = 0; format[index_ + 3] != NUL; index_++) {
+ sc_trace("%s", index_ > 0 ? "," : "");
+ switch (format[index_ + 3]) {
+ case PROP_KEY_STRING:
+ sc_trace("\"%s\"", vt_key[index_].string);
+ break;
+ case PROP_KEY_INTEGER:
+ sc_trace("%ld", vt_key[index_].integer);
+ break;
+
+ default:
+ sc_trace("%p [invalid type]", vt_key[index_].voidp);
+ break;
+ }
+ }
+ sc_trace("\n");
+ }
+
+ /*
+ * Iterate keys, finding matching child nodes at each level. Stop if no
+ * matching child is found.
+ */
+ node = bundle->root_node;
+ for (index_ = 0; format[index_ + 3] != NUL; index_++) {
+ sc_int type;
+
+ /* Move node down to the matching child, NULL if no match. */
+ type = format[index_ + 3 ];
+ node = prop_find_child(node, type, vt_key[index_]);
+ if (!node)
+ break;
+ }
+
+ /* If key iteration halted because no child was found, return FALSE. */
+ if (!node) {
+ if (prop_trace)
+ sc_trace("Property: ...get FAILED\n");
+
+ return FALSE;
+ }
+
+ /*
+ * Enforce integer-only queries on internal nodes, since this is the only
+ * type of query that makes sense -- any other type is probably a mistake.
+ */
+ if (node->child_list && format[0] != PROP_INTEGER)
+ sc_fatal("prop_get: only integer gets on internal nodes\n");
+
+ /* Return the properties of the final node. */
+ switch (format[0]) {
+ case PROP_INTEGER:
+ vt_rvalue->integer = node->property.integer;
+ break;
+ case PROP_BOOLEAN:
+ vt_rvalue->boolean = node->property.boolean;
+ break;
+ case PROP_STRING:
+ vt_rvalue->string = node->property.string;
+ break;
+
+ default:
+ sc_fatal("prop_get: invalid property type\n");
+ }
+
+ /* Complete tracing property get. */
+ if (prop_trace) {
+ sc_trace("Property: ...get returned : ");
+ switch (format[0]) {
+ case PROP_STRING:
+ sc_trace("\"%s\"", vt_rvalue->string);
+ break;
+ case PROP_INTEGER:
+ sc_trace("%ld", vt_rvalue->integer);
+ break;
+ case PROP_BOOLEAN:
+ sc_trace("%s", vt_rvalue->boolean ? "true" : "false");
+ break;
+
+ default:
+ sc_trace("%p [invalid type]", vt_rvalue->voidp);
+ break;
+ }
+ sc_trace("\n");
+ }
+ return TRUE;
}
@@ -670,49 +634,46 @@ prop_get (sc_prop_setref_t bundle, const sc_char *format,
* so that no further property insertions are allowed.
*/
static void
-prop_trim_node (sc_prop_noderef_t node)
-{
- /* End recursion on null or childless node. */
- if (node && node->child_list)
- {
- sc_int index_;
-
- /* Recursively trim allocation on children. */
- for (index_ = 0; index_ < node->property.integer; index_++)
- prop_trim_node (node->child_list[index_]);
-
- /* Trim allocation on this node. */
- node->child_list = (sc_prop_noderef_t *)prop_trim_capacity (node->child_list,
- node->property.integer,
- sizeof (*node->child_list));
- }
+prop_trim_node(sc_prop_noderef_t node) {
+ /* End recursion on null or childless node. */
+ if (node && node->child_list) {
+ sc_int index_;
+
+ /* Recursively trim allocation on children. */
+ for (index_ = 0; index_ < node->property.integer; index_++)
+ prop_trim_node(node->child_list[index_]);
+
+ /* Trim allocation on this node. */
+ node->child_list = (sc_prop_noderef_t *)prop_trim_capacity(node->child_list,
+ node->property.integer,
+ sizeof(*node->child_list));
+ }
}
void
-prop_solidify (sc_prop_setref_t bundle)
-{
- assert (prop_is_valid (bundle));
-
- /*
- * Trim back the dictionary, orphans, pools array, and every internal tree
- * node. The one thing _not_ to trim is the final node pool -- there are
- * references to nodes within it strewn all over the properties tree, and
- * it's a large job to try to find and update them; instead, we just live
- * with a little wasted heap memory.
- */
- bundle->dictionary = (sc_char **)prop_trim_capacity (bundle->dictionary,
- bundle->dictionary_length,
- sizeof (bundle->dictionary[0]));
- bundle->node_pools = (sc_prop_noderef_t *)prop_trim_capacity (bundle->node_pools,
- bundle->node_pools_length,
- sizeof (bundle->node_pools[0]));
- bundle->orphans = (void **)prop_trim_capacity (bundle->orphans,
- bundle->orphans_length,
- sizeof (bundle->orphans[0]));
- prop_trim_node (bundle->root_node);
-
- /* Set the bundle so that no more properties can be added. */
- bundle->is_readonly = TRUE;
+prop_solidify(sc_prop_setref_t bundle) {
+ assert(prop_is_valid(bundle));
+
+ /*
+ * Trim back the dictionary, orphans, pools array, and every internal tree
+ * node. The one thing _not_ to trim is the final node pool -- there are
+ * references to nodes within it strewn all over the properties tree, and
+ * it's a large job to try to find and update them; instead, we just live
+ * with a little wasted heap memory.
+ */
+ bundle->dictionary = (sc_char **)prop_trim_capacity(bundle->dictionary,
+ bundle->dictionary_length,
+ sizeof(bundle->dictionary[0]));
+ bundle->node_pools = (sc_prop_noderef_t *)prop_trim_capacity(bundle->node_pools,
+ bundle->node_pools_length,
+ sizeof(bundle->node_pools[0]));
+ bundle->orphans = (void **)prop_trim_capacity(bundle->orphans,
+ bundle->orphans_length,
+ sizeof(bundle->orphans[0]));
+ prop_trim_node(bundle->root_node);
+
+ /* Set the bundle so that no more properties can be added. */
+ bundle->is_readonly = TRUE;
}
@@ -725,42 +686,39 @@ prop_solidify (sc_prop_setref_t bundle)
* It is an error for the property not to exist on retrieval.
*/
sc_int
-prop_get_integer (sc_prop_setref_t bundle,
- const sc_char *format, const sc_vartype_t vt_key[])
-{
- sc_vartype_t vt_rvalue;
- assert (format[0] == PROP_INTEGER);
+prop_get_integer(sc_prop_setref_t bundle,
+ const sc_char *format, const sc_vartype_t vt_key[]) {
+ sc_vartype_t vt_rvalue;
+ assert(format[0] == PROP_INTEGER);
- if (!prop_get (bundle, format, &vt_rvalue, vt_key))
- sc_fatal ("prop_get_integer: can't retrieve property\n");
+ if (!prop_get(bundle, format, &vt_rvalue, vt_key))
+ sc_fatal("prop_get_integer: can't retrieve property\n");
- return vt_rvalue.integer;
+ return vt_rvalue.integer;
}
sc_bool
-prop_get_boolean (sc_prop_setref_t bundle,
- const sc_char *format, const sc_vartype_t vt_key[])
-{
- sc_vartype_t vt_rvalue;
- assert (format[0] == PROP_BOOLEAN);
+prop_get_boolean(sc_prop_setref_t bundle,
+ const sc_char *format, const sc_vartype_t vt_key[]) {
+ sc_vartype_t vt_rvalue;
+ assert(format[0] == PROP_BOOLEAN);
- if (!prop_get (bundle, format, &vt_rvalue, vt_key))
- sc_fatal ("prop_get_boolean: can't retrieve property\n");
+ if (!prop_get(bundle, format, &vt_rvalue, vt_key))
+ sc_fatal("prop_get_boolean: can't retrieve property\n");
- return vt_rvalue.boolean;
+ return vt_rvalue.boolean;
}
const sc_char *
-prop_get_string (sc_prop_setref_t bundle,
- const sc_char *format, const sc_vartype_t vt_key[])
-{
- sc_vartype_t vt_rvalue;
- assert (format[0] == PROP_STRING);
+prop_get_string(sc_prop_setref_t bundle,
+ const sc_char *format, const sc_vartype_t vt_key[]) {
+ sc_vartype_t vt_rvalue;
+ assert(format[0] == PROP_STRING);
- if (!prop_get (bundle, format, &vt_rvalue, vt_key))
- sc_fatal ("prop_get_string: can't retrieve property\n");
+ if (!prop_get(bundle, format, &vt_rvalue, vt_key))
+ sc_fatal("prop_get_string: can't retrieve property\n");
- return vt_rvalue.string;
+ return vt_rvalue.string;
}
@@ -771,17 +729,16 @@ prop_get_string (sc_prop_setref_t bundle,
* for a given property. Returns zero if the property does not exist.
*/
sc_int
-prop_get_child_count (sc_prop_setref_t bundle,
- const sc_char *format, const sc_vartype_t vt_key[])
-{
- sc_vartype_t vt_rvalue;
- assert (format[0] == PROP_INTEGER);
+prop_get_child_count(sc_prop_setref_t bundle,
+ const sc_char *format, const sc_vartype_t vt_key[]) {
+ sc_vartype_t vt_rvalue;
+ assert(format[0] == PROP_INTEGER);
- if (!prop_get (bundle, format, &vt_rvalue, vt_key))
- return 0;
+ if (!prop_get(bundle, format, &vt_rvalue, vt_key))
+ return 0;
- /* Return overloaded integer property value, the child count. */
- return vt_rvalue.integer;
+ /* Return overloaded integer property value, the child count. */
+ return vt_rvalue.integer;
}
@@ -792,41 +749,41 @@ prop_get_child_count (sc_prop_setref_t bundle,
*/
static sc_prop_setref_t
prop_create_empty() {
- sc_prop_setref_t bundle;
+ sc_prop_setref_t bundle;
- /* Create a new, empty set. */
- bundle = (sc_prop_setref_t)sc_malloc(sizeof (*bundle));
- bundle->magic = PROP_MAGIC;
+ /* Create a new, empty set. */
+ bundle = (sc_prop_setref_t)sc_malloc(sizeof(*bundle));
+ bundle->magic = PROP_MAGIC;
- /* Begin with an empty strings dictionary. */
- bundle->dictionary_length = 0;
- bundle->dictionary = NULL;
+ /* Begin with an empty strings dictionary. */
+ bundle->dictionary_length = 0;
+ bundle->dictionary = NULL;
- /* Begin with no allocated node pools. */
- bundle->node_pools_length = 0;
- bundle->node_pools = NULL;
- bundle->node_count = 0;
+ /* Begin with no allocated node pools. */
+ bundle->node_pools_length = 0;
+ bundle->node_pools = NULL;
+ bundle->node_count = 0;
- /* Begin with no adopted addresses. */
- bundle->orphans_length = 0;
- bundle->orphans = NULL;
+ /* Begin with no adopted addresses. */
+ bundle->orphans_length = 0;
+ bundle->orphans = NULL;
- /* Leave open for insertions. */
- bundle->is_readonly = FALSE;
+ /* Leave open for insertions. */
+ bundle->is_readonly = FALSE;
- /*
- * Start the set off with a root node. This will also kick off node pools,
- * ensuring that every set has at least one node and one allocated pool.
- */
- bundle->root_node = prop_new_node (bundle);
- bundle->root_node->child_list = NULL;
- bundle->root_node->name.string = "ROOT";
- bundle->root_node->property.voidp = NULL;
+ /*
+ * Start the set off with a root node. This will also kick off node pools,
+ * ensuring that every set has at least one node and one allocated pool.
+ */
+ bundle->root_node = prop_new_node(bundle);
+ bundle->root_node->child_list = NULL;
+ bundle->root_node->name.string = "ROOT";
+ bundle->root_node->property.voidp = NULL;
- /* No taf is yet connected with this set. */
- bundle->taf = NULL;
+ /* No taf is yet connected with this set. */
+ bundle->taf = NULL;
- return bundle;
+ return bundle;
}
@@ -837,60 +794,57 @@ prop_create_empty() {
* Free set memory, and destroy a properties set structure.
*/
static void
-prop_destroy_child_list (sc_prop_noderef_t node)
-{
- /* End recursion on null or childless node. */
- if (node && node->child_list)
- {
- sc_int index_;
-
- /* Recursively destroy the children's child lists. */
- for (index_ = 0; index_ < node->property.integer; index_++)
- prop_destroy_child_list (node->child_list[index_]);
-
- /* Free our own child list. */
- sc_free (node->child_list);
- }
+prop_destroy_child_list(sc_prop_noderef_t node) {
+ /* End recursion on null or childless node. */
+ if (node && node->child_list) {
+ sc_int index_;
+
+ /* Recursively destroy the children's child lists. */
+ for (index_ = 0; index_ < node->property.integer; index_++)
+ prop_destroy_child_list(node->child_list[index_]);
+
+ /* Free our own child list. */
+ sc_free(node->child_list);
+ }
}
void
-prop_destroy (sc_prop_setref_t bundle)
-{
- sc_int index_;
- assert (prop_is_valid (bundle));
-
- /* Destroy the dictionary, and free it. */
- for (index_ = 0; index_ < bundle->dictionary_length; index_++)
- sc_free (bundle->dictionary[index_]);
- bundle->dictionary_length = 0;
- sc_free (bundle->dictionary);
- bundle->dictionary = NULL;
-
- /* Free adopted addresses. */
- for (index_ = 0; index_ < bundle->orphans_length; index_++)
- sc_free (bundle->orphans[index_]);
- bundle->orphans_length = 0;
- sc_free (bundle->orphans);
- bundle->orphans = NULL;
-
- /* Walk the tree, destroying the child list for each node found. */
- prop_destroy_child_list (bundle->root_node);
- bundle->root_node = NULL;
-
- /* Destroy each node pool. */
- for (index_ = 0; index_ < bundle->node_pools_length; index_++)
- sc_free (bundle->node_pools[index_]);
- bundle->node_pools_length = 0;
- sc_free (bundle->node_pools);
- bundle->node_pools = NULL;
-
- /* Destroy any taf associated with the bundle. */
- if (bundle->taf)
- taf_destroy (bundle->taf);
-
- /* Poison and free the bundle. */
- memset (bundle, 0xaa, sizeof (*bundle));
- sc_free (bundle);
+prop_destroy(sc_prop_setref_t bundle) {
+ sc_int index_;
+ assert(prop_is_valid(bundle));
+
+ /* Destroy the dictionary, and free it. */
+ for (index_ = 0; index_ < bundle->dictionary_length; index_++)
+ sc_free(bundle->dictionary[index_]);
+ bundle->dictionary_length = 0;
+ sc_free(bundle->dictionary);
+ bundle->dictionary = NULL;
+
+ /* Free adopted addresses. */
+ for (index_ = 0; index_ < bundle->orphans_length; index_++)
+ sc_free(bundle->orphans[index_]);
+ bundle->orphans_length = 0;
+ sc_free(bundle->orphans);
+ bundle->orphans = NULL;
+
+ /* Walk the tree, destroying the child list for each node found. */
+ prop_destroy_child_list(bundle->root_node);
+ bundle->root_node = NULL;
+
+ /* Destroy each node pool. */
+ for (index_ = 0; index_ < bundle->node_pools_length; index_++)
+ sc_free(bundle->node_pools[index_]);
+ bundle->node_pools_length = 0;
+ sc_free(bundle->node_pools);
+ bundle->node_pools = NULL;
+
+ /* Destroy any taf associated with the bundle. */
+ if (bundle->taf)
+ taf_destroy(bundle->taf);
+
+ /* Poison and free the bundle. */
+ memset(bundle, 0xaa, sizeof(*bundle));
+ sc_free(bundle);
}
@@ -900,23 +854,21 @@ prop_destroy (sc_prop_setref_t bundle)
* Create a new properties set based on a taf, and return it.
*/
sc_prop_setref_t
-prop_create (const sc_tafref_t taf)
-{
- sc_prop_setref_t bundle;
-
- /* Create a new, empty set. */
- bundle = prop_create_empty ();
-
- /* Populate it with data parsed from the taf file. */
- if (!parse_game (taf, bundle))
- {
- prop_destroy (bundle);
- return NULL;
- }
-
- /* Note the taf for destruction later, and return the new set. */
- bundle->taf = taf;
- return bundle;
+prop_create(const sc_tafref_t taf) {
+ sc_prop_setref_t bundle;
+
+ /* Create a new, empty set. */
+ bundle = prop_create_empty();
+
+ /* Populate it with data parsed from the taf file. */
+ if (!parse_game(taf, bundle)) {
+ prop_destroy(bundle);
+ return NULL;
+ }
+
+ /* Note the taf for destruction later, and return the new set. */
+ bundle->taf = taf;
+ return bundle;
}
@@ -926,18 +878,17 @@ prop_create (const sc_tafref_t taf)
* Adopt a memory address for free'ing on destroy.
*/
void
-prop_adopt (sc_prop_setref_t bundle, void *addr)
-{
- assert (prop_is_valid (bundle));
-
- /* Extend the orphans array if necessary. */
- bundle->orphans = (void **)prop_ensure_capacity (bundle->orphans,
- bundle->orphans_length,
- bundle->orphans_length + 1,
- sizeof (bundle->orphans[0]));
-
- /* Add the new address to the end of the array. */
- bundle->orphans[bundle->orphans_length++] = addr;
+prop_adopt(sc_prop_setref_t bundle, void *addr) {
+ assert(prop_is_valid(bundle));
+
+ /* Extend the orphans array if necessary. */
+ bundle->orphans = (void **)prop_ensure_capacity(bundle->orphans,
+ bundle->orphans_length,
+ bundle->orphans_length + 1,
+ sizeof(bundle->orphans[0]));
+
+ /* Add the new address to the end of the array. */
+ bundle->orphans[bundle->orphans_length++] = addr;
}
@@ -949,98 +900,86 @@ prop_adopt (sc_prop_setref_t bundle, void *addr)
* Print out a complete properties set.
*/
static sc_bool
-prop_debug_is_dictionary_string (sc_prop_setref_t bundle, const void *pointer)
-{
- const sc_char *const pointer_ = (const sc_char *const )pointer;
- sc_int index_;
-
- /* Compare by pointer directly, not by string value comparisons. */
- for (index_ = 0; index_ < bundle->dictionary_length; index_++)
- {
- if (bundle->dictionary[index_] == pointer_)
- return TRUE;
- }
-
- return FALSE;
+prop_debug_is_dictionary_string(sc_prop_setref_t bundle, const void *pointer) {
+ const sc_char *const pointer_ = (const sc_char * const)pointer;
+ sc_int index_;
+
+ /* Compare by pointer directly, not by string value comparisons. */
+ for (index_ = 0; index_ < bundle->dictionary_length; index_++) {
+ if (bundle->dictionary[index_] == pointer_)
+ return TRUE;
+ }
+
+ return FALSE;
}
static void
-prop_debug_dump_node (sc_prop_setref_t bundle,
- sc_int depth, sc_int child_index, sc_prop_noderef_t node)
-{
- sc_int index_;
-
- /* Write node preamble, indented two spaces for each depth count. */
- for (index_ = 0; index_ < depth; index_++)
- sc_trace (" ");
- sc_trace ("%ld : %p", child_index, (void *) node);
-
- /* Write node, or just a newline if none. */
- if (node)
- {
- /* Print out the node's key, as hex and either string or decimal. */
- sc_trace (", name %p", node->name.voidp);
- if (node != bundle->root_node)
- {
- if (prop_debug_is_dictionary_string (bundle, node->name.string))
- sc_trace (" \"%s\"", node->name.string);
- else
- sc_trace (" %ld", node->name.integer);
- }
-
- if (node->child_list)
- {
- /* Recursively dump children. */
- sc_trace (", child count %ld\n", node->property.integer);
- for (index_ = 0; index_ < node->property.integer; index_++)
- {
- prop_debug_dump_node (bundle, depth + 1,
- index_, node->child_list[index_]);
- }
- }
- else
- {
- /* Print out the node's property, again hex and string or decimal. */
- sc_trace (", property %p", node->property.voidp);
- if (taf_debug_is_taf_string (bundle->taf, node->property.string))
- sc_trace (" \"%s\"\n", node->property.string);
- else
- sc_trace (" %ld\n", node->property.integer);
- }
- }
- else
- sc_trace ("\n");
+prop_debug_dump_node(sc_prop_setref_t bundle,
+ sc_int depth, sc_int child_index, sc_prop_noderef_t node) {
+ sc_int index_;
+
+ /* Write node preamble, indented two spaces for each depth count. */
+ for (index_ = 0; index_ < depth; index_++)
+ sc_trace(" ");
+ sc_trace("%ld : %p", child_index, (void *) node);
+
+ /* Write node, or just a newline if none. */
+ if (node) {
+ /* Print out the node's key, as hex and either string or decimal. */
+ sc_trace(", name %p", node->name.voidp);
+ if (node != bundle->root_node) {
+ if (prop_debug_is_dictionary_string(bundle, node->name.string))
+ sc_trace(" \"%s\"", node->name.string);
+ else
+ sc_trace(" %ld", node->name.integer);
+ }
+
+ if (node->child_list) {
+ /* Recursively dump children. */
+ sc_trace(", child count %ld\n", node->property.integer);
+ for (index_ = 0; index_ < node->property.integer; index_++) {
+ prop_debug_dump_node(bundle, depth + 1,
+ index_, node->child_list[index_]);
+ }
+ } else {
+ /* Print out the node's property, again hex and string or decimal. */
+ sc_trace(", property %p", node->property.voidp);
+ if (taf_debug_is_taf_string(bundle->taf, node->property.string))
+ sc_trace(" \"%s\"\n", node->property.string);
+ else
+ sc_trace(" %ld\n", node->property.integer);
+ }
+ } else
+ sc_trace("\n");
}
void
-prop_debug_dump (sc_prop_setref_t bundle)
-{
- sc_int index_;
- assert (prop_is_valid (bundle));
-
- /* Dump complete structure. */
- sc_trace ("Property: debug dump follows...\n");
- sc_trace ("bundle->is_readonly = %s\n",
- bundle->is_readonly ? "true" : "false");
- sc_trace ("bundle->dictionary_length = %ld\n", bundle->dictionary_length);
-
- sc_trace ("bundle->dictionary =\n");
- for (index_ = 0; index_ < bundle->dictionary_length; index_++)
- {
- sc_trace ("%3ld : %p \"%s\"\n", index_,
- bundle->dictionary[index_], bundle->dictionary[index_]);
- }
-
- sc_trace ("bundle->node_pools_length = %ld\n", bundle->node_pools_length);
-
- sc_trace ("bundle->node_pools =\n");
- for (index_ = 0; index_ < bundle->node_pools_length; index_++)
- sc_trace ("%3ld : %p\n", index_, (void *) bundle->node_pools[index_]);
-
- sc_trace ("bundle->node_count = %ld\n", bundle->node_count);
- sc_trace ("bundle->root_node = {\n");
- prop_debug_dump_node (bundle, 0, 0, bundle->root_node);
- sc_trace ("}\nbundle->taf = %p\n", (void *) bundle->taf);
+prop_debug_dump(sc_prop_setref_t bundle) {
+ sc_int index_;
+ assert(prop_is_valid(bundle));
+
+ /* Dump complete structure. */
+ sc_trace("Property: debug dump follows...\n");
+ sc_trace("bundle->is_readonly = %s\n",
+ bundle->is_readonly ? "true" : "false");
+ sc_trace("bundle->dictionary_length = %ld\n", bundle->dictionary_length);
+
+ sc_trace("bundle->dictionary =\n");
+ for (index_ = 0; index_ < bundle->dictionary_length; index_++) {
+ sc_trace("%3ld : %p \"%s\"\n", index_,
+ bundle->dictionary[index_], bundle->dictionary[index_]);
+ }
+
+ sc_trace("bundle->node_pools_length = %ld\n", bundle->node_pools_length);
+
+ sc_trace("bundle->node_pools =\n");
+ for (index_ = 0; index_ < bundle->node_pools_length; index_++)
+ sc_trace("%3ld : %p\n", index_, (void *) bundle->node_pools[index_]);
+
+ sc_trace("bundle->node_count = %ld\n", bundle->node_count);
+ sc_trace("bundle->root_node = {\n");
+ prop_debug_dump_node(bundle, 0, 0, bundle->root_node);
+ sc_trace("}\nbundle->taf = %p\n", (void *) bundle->taf);
}
@@ -1050,9 +989,8 @@ prop_debug_dump (sc_prop_setref_t bundle)
* Set property tracing on/off.
*/
void
-prop_debug_trace (sc_bool flag)
-{
- prop_trace = flag;
+prop_debug_trace(sc_bool flag) {
+ prop_trace = flag;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scprotos.h b/engines/glk/adrift/scprotos.h
index 549a0144fe..24103b93f8 100644
--- a/engines/glk/adrift/scprotos.h
+++ b/engines/glk/adrift/scprotos.h
@@ -48,18 +48,17 @@ namespace Adrift {
#endif
/* Vartype typedef, supports relaxed typing. */
-typedef union
-{
- sc_int integer;
- sc_bool boolean;
- const sc_char *string;
- sc_char *mutable_string;
- void *voidp;
+typedef union {
+ sc_int integer;
+ sc_bool boolean;
+ const sc_char *string;
+ sc_char *mutable_string;
+ void *voidp;
} sc_vartype_t;
/* Standard reader and writer callback function typedefs. */
-typedef sc_int (*sc_read_callbackref_t) (void *, sc_byte *, sc_int);
-typedef void (*sc_write_callbackref_t) (void *, const sc_byte *, sc_int);
+typedef sc_int(*sc_read_callbackref_t)(void *, sc_byte *, sc_int);
+typedef void (*sc_write_callbackref_t)(void *, const sc_byte *, sc_int);
/*
* Small utility and wrapper functions. For printf wrappers, try to apply
@@ -67,102 +66,102 @@ typedef void (*sc_write_callbackref_t) (void *, const sc_byte *, sc_int);
* checks.
*/
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
-extern void sc_trace (const sc_char *format, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
-extern void sc_error (const sc_char *format, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
-extern void sc_fatal (const sc_char *format, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
+extern void sc_trace(const sc_char *format, ...)
+__attribute__((__format__(__printf__, 1, 2)));
+extern void sc_error(const sc_char *format, ...)
+__attribute__((__format__(__printf__, 1, 2)));
+extern void sc_fatal(const sc_char *format, ...)
+__attribute__((__format__(__printf__, 1, 2)));
#else
-extern void sc_trace (const sc_char *format, ...);
-extern void sc_error (const sc_char *format, ...);
-extern void sc_fatal (const sc_char *format, ...);
+extern void sc_trace(const sc_char *format, ...);
+extern void sc_error(const sc_char *format, ...);
+extern void sc_fatal(const sc_char *format, ...);
#endif
-extern void *sc_malloc (size_t size);
-extern void *sc_realloc (void *pointer, size_t size);
-extern void sc_free (void *pointer);
-extern void sc_set_congruential_random (void);
-extern void sc_set_platform_random (void);
-extern sc_bool sc_is_congruential_random (void);
-extern void sc_seed_random (sc_uint new_seed);
-extern sc_int sc_rand (void);
-extern sc_int sc_randomint (sc_int low, sc_int high);
-extern sc_bool sc_strempty (const sc_char *string);
-extern sc_char *sc_trim_string (sc_char *string);
-extern sc_char *sc_normalize_string (sc_char *string);
-extern sc_bool sc_compare_word (const sc_char *string,
- const sc_char *word, sc_int length);
-extern sc_uint sc_hash (const sc_char *string);
+extern void *sc_malloc(size_t size);
+extern void *sc_realloc(void *pointer, size_t size);
+extern void sc_free(void *pointer);
+extern void sc_set_congruential_random(void);
+extern void sc_set_platform_random(void);
+extern sc_bool sc_is_congruential_random(void);
+extern void sc_seed_random(sc_uint new_seed);
+extern sc_int sc_rand(void);
+extern sc_int sc_randomint(sc_int low, sc_int high);
+extern sc_bool sc_strempty(const sc_char *string);
+extern sc_char *sc_trim_string(sc_char *string);
+extern sc_char *sc_normalize_string(sc_char *string);
+extern sc_bool sc_compare_word(const sc_char *string,
+ const sc_char *word, sc_int length);
+extern sc_uint sc_hash(const sc_char *string);
/* TAF file reader/decompressor enumerations, opaque typedef and functions. */
-enum
-{ TAF_VERSION_NONE = 0,
- TAF_VERSION_400 = 400,
- TAF_VERSION_390 = 390,
- TAF_VERSION_380 = 380
+enum {
+ TAF_VERSION_NONE = 0,
+ TAF_VERSION_400 = 400,
+ TAF_VERSION_390 = 390,
+ TAF_VERSION_380 = 380
};
typedef struct sc_taf_s *sc_tafref_t;
-extern void taf_destroy (sc_tafref_t taf);
-extern sc_tafref_t taf_create (sc_read_callbackref_t callback, void *opaque);
-extern sc_tafref_t taf_create_tas (sc_read_callbackref_t callback,
- void *opaque);
-extern void taf_first_line (sc_tafref_t taf);
-extern const sc_char *taf_next_line (sc_tafref_t taf);
-extern sc_bool taf_more_lines (sc_tafref_t taf);
-extern sc_int taf_get_game_data_length (sc_tafref_t taf);
-extern sc_int taf_get_version (sc_tafref_t taf);
-extern sc_bool taf_debug_is_taf_string (sc_tafref_t taf, const void *addr);
-extern void taf_debug_dump (sc_tafref_t taf);
+extern void taf_destroy(sc_tafref_t taf);
+extern sc_tafref_t taf_create(sc_read_callbackref_t callback, void *opaque);
+extern sc_tafref_t taf_create_tas(sc_read_callbackref_t callback,
+ void *opaque);
+extern void taf_first_line(sc_tafref_t taf);
+extern const sc_char *taf_next_line(sc_tafref_t taf);
+extern sc_bool taf_more_lines(sc_tafref_t taf);
+extern sc_int taf_get_game_data_length(sc_tafref_t taf);
+extern sc_int taf_get_version(sc_tafref_t taf);
+extern sc_bool taf_debug_is_taf_string(sc_tafref_t taf, const void *addr);
+extern void taf_debug_dump(sc_tafref_t taf);
/* Properties store enumerations, opaque typedef, and functions. */
-enum
-{ PROP_KEY_STRING = 's',
- PROP_KEY_INTEGER = 'i'
+enum {
+ PROP_KEY_STRING = 's',
+ PROP_KEY_INTEGER = 'i'
};
-enum
-{ PROP_INTEGER = 'I',
- PROP_BOOLEAN = 'B',
- PROP_STRING = 'S'
+enum {
+ PROP_INTEGER = 'I',
+ PROP_BOOLEAN = 'B',
+ PROP_STRING = 'S'
};
typedef struct sc_prop_set_s *sc_prop_setref_t;
-extern sc_prop_setref_t prop_create (const sc_tafref_t taf);
-extern void prop_destroy (sc_prop_setref_t bundle);
-extern void prop_put (sc_prop_setref_t bundle,
- const sc_char *format, sc_vartype_t vt_value,
- const sc_vartype_t vt_key[]);
-extern sc_bool prop_get (sc_prop_setref_t bundle,
- const sc_char *format, sc_vartype_t *vt_value,
- const sc_vartype_t vt_key[]);
-extern void prop_solidify (sc_prop_setref_t bundle);
-extern sc_int prop_get_integer (sc_prop_setref_t bundle,
+extern sc_prop_setref_t prop_create(const sc_tafref_t taf);
+extern void prop_destroy(sc_prop_setref_t bundle);
+extern void prop_put(sc_prop_setref_t bundle,
+ const sc_char *format, sc_vartype_t vt_value,
+ const sc_vartype_t vt_key[]);
+extern sc_bool prop_get(sc_prop_setref_t bundle,
+ const sc_char *format, sc_vartype_t *vt_value,
+ const sc_vartype_t vt_key[]);
+extern void prop_solidify(sc_prop_setref_t bundle);
+extern sc_int prop_get_integer(sc_prop_setref_t bundle,
+ const sc_char *format,
+ const sc_vartype_t vt_key[]);
+extern sc_bool prop_get_boolean(sc_prop_setref_t bundle,
const sc_char *format,
const sc_vartype_t vt_key[]);
-extern sc_bool prop_get_boolean (sc_prop_setref_t bundle,
- const sc_char *format,
- const sc_vartype_t vt_key[]);
-extern const sc_char *prop_get_string (sc_prop_setref_t bundle,
- const sc_char *format,
- const sc_vartype_t vt_key[]);
-extern sc_int prop_get_child_count (sc_prop_setref_t bundle,
- const sc_char *format,
- const sc_vartype_t vt_key[]);
-extern void prop_adopt (sc_prop_setref_t bundle, void *addr);
-extern void prop_debug_trace (sc_bool flag);
-extern void prop_debug_dump (sc_prop_setref_t bundle);
+extern const sc_char *prop_get_string(sc_prop_setref_t bundle,
+ const sc_char *format,
+ const sc_vartype_t vt_key[]);
+extern sc_int prop_get_child_count(sc_prop_setref_t bundle,
+ const sc_char *format,
+ const sc_vartype_t vt_key[]);
+extern void prop_adopt(sc_prop_setref_t bundle, void *addr);
+extern void prop_debug_trace(sc_bool flag);
+extern void prop_debug_dump(sc_prop_setref_t bundle);
/* Game parser enumeration and functions. */
-enum
-{ ROOMLIST_NO_ROOMS = 0,
- ROOMLIST_ONE_ROOM = 1,
- ROOMLIST_SOME_ROOMS = 2,
- ROOMLIST_ALL_ROOMS = 3,
- ROOMLIST_NPC_PART = 4
+enum {
+ ROOMLIST_NO_ROOMS = 0,
+ ROOMLIST_ONE_ROOM = 1,
+ ROOMLIST_SOME_ROOMS = 2,
+ ROOMLIST_ALL_ROOMS = 3,
+ ROOMLIST_NPC_PART = 4
};
-extern sc_bool parse_game (sc_tafref_t taf, sc_prop_setref_t bundle);
-extern void parse_debug_trace (sc_bool flag);
+extern sc_bool parse_game(sc_tafref_t taf, sc_prop_setref_t bundle);
+extern void parse_debug_trace(sc_bool flag);
/* Game state structure for modules that use it. */
typedef struct sc_game_s *sc_gameref_t;
@@ -171,627 +170,627 @@ typedef struct sc_game_s *sc_gameref_t;
typedef struct sc_taskstate_s *sc_hintref_t;
/* Variables set enumerations, opaque typedef, and functions. */
-enum
-{ TAFVAR_NUMERIC = 0,
- TAFVAR_STRING = 1
+enum {
+ TAFVAR_NUMERIC = 0,
+ TAFVAR_STRING = 1
};
-enum
-{ VAR_INTEGER = 'I',
- VAR_STRING = 'S'
+enum {
+ VAR_INTEGER = 'I',
+ VAR_STRING = 'S'
};
typedef struct sc_var_set_s *sc_var_setref_t;
-extern void var_put (sc_var_setref_t vars,
- const sc_char *name, sc_int type, sc_vartype_t vt_value);
-extern sc_bool var_get (sc_var_setref_t vars,
- const sc_char *name, sc_int *type,
- sc_vartype_t *vt_rvalue);
-extern void var_put_integer (sc_var_setref_t vars,
- const sc_char *name, sc_int value);
-extern sc_int var_get_integer (sc_var_setref_t vars, const sc_char *name);
-extern void var_put_string (sc_var_setref_t vars,
- const sc_char *name, const sc_char *string);
-extern const sc_char *var_get_string (sc_var_setref_t vars,
- const sc_char *name);
-extern sc_var_setref_t var_create (sc_prop_setref_t bundle);
-extern void var_destroy (sc_var_setref_t vars);
-extern void var_register_game (sc_var_setref_t vars, sc_gameref_t game);
-extern void var_set_ref_character (sc_var_setref_t vars, sc_int character);
-extern void var_set_ref_object (sc_var_setref_t vars, sc_int object);
-extern void var_set_ref_number (sc_var_setref_t vars, sc_int number);
-extern void var_set_ref_text (sc_var_setref_t vars, const sc_char *text);
-extern sc_int var_get_ref_character (sc_var_setref_t vars);
-extern sc_int var_get_ref_object (sc_var_setref_t vars);
-extern sc_int var_get_ref_number (sc_var_setref_t vars);
-extern const sc_char *var_get_ref_text (sc_var_setref_t vars);
-extern sc_uint var_get_elapsed_seconds (sc_var_setref_t vars);
-extern void var_set_elapsed_seconds (sc_var_setref_t vars, sc_uint seconds);
-extern void var_debug_trace (sc_bool flag);
-extern void var_debug_dump (sc_var_setref_t vars);
+extern void var_put(sc_var_setref_t vars,
+ const sc_char *name, sc_int type, sc_vartype_t vt_value);
+extern sc_bool var_get(sc_var_setref_t vars,
+ const sc_char *name, sc_int *type,
+ sc_vartype_t *vt_rvalue);
+extern void var_put_integer(sc_var_setref_t vars,
+ const sc_char *name, sc_int value);
+extern sc_int var_get_integer(sc_var_setref_t vars, const sc_char *name);
+extern void var_put_string(sc_var_setref_t vars,
+ const sc_char *name, const sc_char *string);
+extern const sc_char *var_get_string(sc_var_setref_t vars,
+ const sc_char *name);
+extern sc_var_setref_t var_create(sc_prop_setref_t bundle);
+extern void var_destroy(sc_var_setref_t vars);
+extern void var_register_game(sc_var_setref_t vars, sc_gameref_t game);
+extern void var_set_ref_character(sc_var_setref_t vars, sc_int character);
+extern void var_set_ref_object(sc_var_setref_t vars, sc_int object);
+extern void var_set_ref_number(sc_var_setref_t vars, sc_int number);
+extern void var_set_ref_text(sc_var_setref_t vars, const sc_char *text);
+extern sc_int var_get_ref_character(sc_var_setref_t vars);
+extern sc_int var_get_ref_object(sc_var_setref_t vars);
+extern sc_int var_get_ref_number(sc_var_setref_t vars);
+extern const sc_char *var_get_ref_text(sc_var_setref_t vars);
+extern sc_uint var_get_elapsed_seconds(sc_var_setref_t vars);
+extern void var_set_elapsed_seconds(sc_var_setref_t vars, sc_uint seconds);
+extern void var_debug_trace(sc_bool flag);
+extern void var_debug_dump(sc_var_setref_t vars);
/* Expression evaluation functions. */
-extern sc_bool expr_eval_numeric_expression (const sc_char *expression,
- sc_var_setref_t vars,
- sc_int *rvalue);
-extern sc_bool expr_eval_string_expression (const sc_char *expression,
- sc_var_setref_t vars,
- sc_char **rvalue);
+extern sc_bool expr_eval_numeric_expression(const sc_char *expression,
+ sc_var_setref_t vars,
+ sc_int *rvalue);
+extern sc_bool expr_eval_string_expression(const sc_char *expression,
+ sc_var_setref_t vars,
+ sc_char **rvalue);
/* Print filtering opaque typedef and functions. */
typedef struct sc_filter_s *sc_filterref_t;
-extern sc_filterref_t pf_create (void);
-extern void pf_destroy (sc_filterref_t filter);
-extern void pf_buffer_string (sc_filterref_t filter,
+extern sc_filterref_t pf_create(void);
+extern void pf_destroy(sc_filterref_t filter);
+extern void pf_buffer_string(sc_filterref_t filter,
+ const sc_char *string);
+extern void pf_buffer_character(sc_filterref_t filter,
+ sc_char character);
+extern void pf_prepend_string(sc_filterref_t filter,
const sc_char *string);
-extern void pf_buffer_character (sc_filterref_t filter,
- sc_char character);
-extern void pf_prepend_string (sc_filterref_t filter,
- const sc_char *string);
-extern void pf_new_sentence (sc_filterref_t filter);
-extern void pf_mute (sc_filterref_t filter);
-extern void pf_clear_mute (sc_filterref_t filter);
-extern void pf_buffer_tag (sc_filterref_t filter, sc_int tag);
-extern void pf_strip_tags (sc_char *string);
-extern void pf_strip_tags_for_hints (sc_char *string);
-extern sc_char *pf_filter (const sc_char *string,
- sc_var_setref_t vars, sc_prop_setref_t bundle);
-extern sc_char *pf_filter_for_info (const sc_char *string,
- sc_var_setref_t vars);
-extern void pf_flush (sc_filterref_t filter,
- sc_var_setref_t vars, sc_prop_setref_t bundle);
-extern void pf_checkpoint (sc_filterref_t filter,
- sc_var_setref_t vars, sc_prop_setref_t bundle);
-extern const sc_char *pf_get_buffer (sc_filterref_t filter);
-extern sc_char *pf_transfer_buffer (sc_filterref_t filter);
-extern void pf_empty (sc_filterref_t filter);
-extern sc_char *pf_escape (const sc_char *string);
-extern sc_char *pf_filter_input (const sc_char *string,
- sc_prop_setref_t bundle);
-extern void pf_debug_trace (sc_bool flag);
+extern void pf_new_sentence(sc_filterref_t filter);
+extern void pf_mute(sc_filterref_t filter);
+extern void pf_clear_mute(sc_filterref_t filter);
+extern void pf_buffer_tag(sc_filterref_t filter, sc_int tag);
+extern void pf_strip_tags(sc_char *string);
+extern void pf_strip_tags_for_hints(sc_char *string);
+extern sc_char *pf_filter(const sc_char *string,
+ sc_var_setref_t vars, sc_prop_setref_t bundle);
+extern sc_char *pf_filter_for_info(const sc_char *string,
+ sc_var_setref_t vars);
+extern void pf_flush(sc_filterref_t filter,
+ sc_var_setref_t vars, sc_prop_setref_t bundle);
+extern void pf_checkpoint(sc_filterref_t filter,
+ sc_var_setref_t vars, sc_prop_setref_t bundle);
+extern const sc_char *pf_get_buffer(sc_filterref_t filter);
+extern sc_char *pf_transfer_buffer(sc_filterref_t filter);
+extern void pf_empty(sc_filterref_t filter);
+extern sc_char *pf_escape(const sc_char *string);
+extern sc_char *pf_filter_input(const sc_char *string,
+ sc_prop_setref_t bundle);
+extern void pf_debug_trace(sc_bool flag);
/* Game memo opaque typedef and functions. */
typedef struct sc_memo_set_s *sc_memo_setref_t;
-extern sc_memo_setref_t memo_create (void);
-extern void memo_destroy (sc_memo_setref_t memento);
-extern void memo_save_game (sc_memo_setref_t memento, sc_gameref_t game);
-extern sc_bool memo_load_game (sc_memo_setref_t memento, sc_gameref_t game);
-extern sc_bool memo_is_load_available (sc_memo_setref_t memento);
-extern void memo_clear_games (sc_memo_setref_t memento);
-extern void memo_save_command (sc_memo_setref_t memento,
- const sc_char *command, sc_int timestamp,
- sc_int turns);
-extern void memo_unsave_command (sc_memo_setref_t memento);
-extern sc_int memo_get_command_count (sc_memo_setref_t memento);
-extern void memo_first_command (sc_memo_setref_t memento);
-extern void memo_next_command (sc_memo_setref_t memento,
- const sc_char **command, sc_int *sequence,
- sc_int *timestamp, sc_int *turns);
-extern sc_bool memo_more_commands (sc_memo_setref_t memento);
-extern const sc_char *memo_find_command (sc_memo_setref_t memento,
- sc_int sequence);
-extern void memo_clear_commands (sc_memo_setref_t memento);
+extern sc_memo_setref_t memo_create(void);
+extern void memo_destroy(sc_memo_setref_t memento);
+extern void memo_save_game(sc_memo_setref_t memento, sc_gameref_t game);
+extern sc_bool memo_load_game(sc_memo_setref_t memento, sc_gameref_t game);
+extern sc_bool memo_is_load_available(sc_memo_setref_t memento);
+extern void memo_clear_games(sc_memo_setref_t memento);
+extern void memo_save_command(sc_memo_setref_t memento,
+ const sc_char *command, sc_int timestamp,
+ sc_int turns);
+extern void memo_unsave_command(sc_memo_setref_t memento);
+extern sc_int memo_get_command_count(sc_memo_setref_t memento);
+extern void memo_first_command(sc_memo_setref_t memento);
+extern void memo_next_command(sc_memo_setref_t memento,
+ const sc_char **command, sc_int *sequence,
+ sc_int *timestamp, sc_int *turns);
+extern sc_bool memo_more_commands(sc_memo_setref_t memento);
+extern const sc_char *memo_find_command(sc_memo_setref_t memento,
+ sc_int sequence);
+extern void memo_clear_commands(sc_memo_setref_t memento);
/* Game state functions. */
-extern sc_gameref_t gs_create (sc_var_setref_t vars, sc_prop_setref_t bundle,
- sc_filterref_t filter);
-extern sc_bool gs_is_game_valid (sc_gameref_t game);
-extern void gs_copy (sc_gameref_t to, sc_gameref_t from);
-extern void gs_destroy (sc_gameref_t game);
+extern sc_gameref_t gs_create(sc_var_setref_t vars, sc_prop_setref_t bundle,
+ sc_filterref_t filter);
+extern sc_bool gs_is_game_valid(sc_gameref_t game);
+extern void gs_copy(sc_gameref_t to, sc_gameref_t from);
+extern void gs_destroy(sc_gameref_t game);
/* Game state accessors and mutators. */
-extern void gs_move_player_to_room (sc_gameref_t game, sc_int room);
-extern sc_bool gs_player_in_room (sc_gameref_t game, sc_int room);
-extern sc_var_setref_t gs_get_vars (sc_gameref_t gs);
-extern sc_prop_setref_t gs_get_bundle (sc_gameref_t gs);
-extern sc_filterref_t gs_get_filter (sc_gameref_t gs);
-extern sc_memo_setref_t gs_get_memento (sc_gameref_t gs);
-extern void gs_set_playerroom (sc_gameref_t gs, sc_int room);
-extern void gs_set_playerposition (sc_gameref_t gs, sc_int position);
-extern void gs_set_playerparent (sc_gameref_t gs, sc_int parent);
-extern sc_int gs_playerroom (sc_gameref_t gs);
-extern sc_int gs_playerposition (sc_gameref_t gs);
-extern sc_int gs_playerparent (sc_gameref_t gs);
-extern sc_int gs_event_count (sc_gameref_t gs);
-extern void gs_set_event_state (sc_gameref_t gs, sc_int event, sc_int state);
-extern void gs_set_event_time (sc_gameref_t gs, sc_int event, sc_int etime);
-extern sc_int gs_event_state (sc_gameref_t gs, sc_int event);
-extern sc_int gs_event_time (sc_gameref_t gs, sc_int event);
-extern void gs_decrement_event_time (sc_gameref_t gs, sc_int event);
-extern sc_int gs_room_count (sc_gameref_t gs);
-extern void gs_set_room_seen (sc_gameref_t gs, sc_int room, sc_bool seen);
-extern sc_bool gs_room_seen (sc_gameref_t gs, sc_int room);
-extern sc_int gs_task_count (sc_gameref_t gs);
-extern void gs_set_task_done (sc_gameref_t gs, sc_int task, sc_bool done);
-extern void gs_set_task_scored (sc_gameref_t gs, sc_int task, sc_bool scored);
-extern sc_bool gs_task_done (sc_gameref_t gs, sc_int task);
-extern sc_bool gs_task_scored (sc_gameref_t gs, sc_int task);
-extern sc_int gs_object_count (sc_gameref_t gs);
-extern void gs_set_object_openness (sc_gameref_t gs,
- sc_int object, sc_int openness);
-extern void gs_set_object_state (sc_gameref_t gs, sc_int object, sc_int state);
-extern void gs_set_object_seen (sc_gameref_t gs, sc_int object, sc_bool seen);
-extern void gs_set_object_unmoved (sc_gameref_t gs,
- sc_int object, sc_bool unmoved);
-extern void gs_set_object_static_unmoved (sc_gameref_t gs,
- sc_int object, sc_bool unmoved);
-extern sc_int gs_object_openness (sc_gameref_t gs, sc_int object);
-extern sc_int gs_object_state (sc_gameref_t gs, sc_int object);
-extern sc_bool gs_object_seen (sc_gameref_t gs, sc_int object);
-extern sc_bool gs_object_unmoved (sc_gameref_t gs, sc_int object);
-extern sc_bool gs_object_static_unmoved (sc_gameref_t gs, sc_int object);
-extern sc_int gs_object_position (sc_gameref_t gs, sc_int object);
-extern sc_int gs_object_parent (sc_gameref_t gs, sc_int object);
-extern void gs_object_move_onto (sc_gameref_t gs, sc_int object, sc_int onto);
-extern void gs_object_move_into (sc_gameref_t gs, sc_int object, sc_int into);
-extern void gs_object_make_hidden (sc_gameref_t gs, sc_int object);
-extern void gs_object_player_get (sc_gameref_t gs, sc_int object);
-extern void gs_object_npc_get (sc_gameref_t gs, sc_int object, sc_int npc);
-extern void gs_object_player_wear (sc_gameref_t gs, sc_int object);
-extern void gs_object_npc_wear (sc_gameref_t gs, sc_int object, sc_int npc);
-extern void gs_object_to_room (sc_gameref_t gs, sc_int object, sc_int room);
-extern sc_int gs_npc_count (sc_gameref_t gs);
-extern void gs_set_npc_location (sc_gameref_t gs, sc_int npc, sc_int location);
-extern sc_int gs_npc_location (sc_gameref_t gs, sc_int npc);
-extern void gs_set_npc_position (sc_gameref_t gs, sc_int npc, sc_int position);
-extern sc_int gs_npc_position (sc_gameref_t gs, sc_int npc);
-extern void gs_set_npc_parent (sc_gameref_t gs, sc_int npc, sc_int parent);
-extern sc_int gs_npc_parent (sc_gameref_t gs, sc_int npc);
-extern void gs_set_npc_seen (sc_gameref_t gs, sc_int npc, sc_bool seen);
-extern sc_bool gs_npc_seen (sc_gameref_t gs, sc_int npc);
-extern sc_int gs_npc_walkstep_count (sc_gameref_t gs, sc_int npc);
-extern void gs_set_npc_walkstep (sc_gameref_t gs, sc_int npc,
- sc_int walk, sc_int walkstep);
-extern sc_int gs_npc_walkstep (sc_gameref_t gs, sc_int npc, sc_int walk);
-extern void gs_decrement_npc_walkstep (sc_gameref_t gs,
- sc_int npc, sc_int walkstep);
-extern void gs_clear_npc_references (sc_gameref_t gs);
-extern void gs_clear_object_references (sc_gameref_t gs);
-extern void gs_set_multiple_references (sc_gameref_t gs);
-extern void gs_clear_multiple_references (sc_gameref_t gs);
+extern void gs_move_player_to_room(sc_gameref_t game, sc_int room);
+extern sc_bool gs_player_in_room(sc_gameref_t game, sc_int room);
+extern sc_var_setref_t gs_get_vars(sc_gameref_t gs);
+extern sc_prop_setref_t gs_get_bundle(sc_gameref_t gs);
+extern sc_filterref_t gs_get_filter(sc_gameref_t gs);
+extern sc_memo_setref_t gs_get_memento(sc_gameref_t gs);
+extern void gs_set_playerroom(sc_gameref_t gs, sc_int room);
+extern void gs_set_playerposition(sc_gameref_t gs, sc_int position);
+extern void gs_set_playerparent(sc_gameref_t gs, sc_int parent);
+extern sc_int gs_playerroom(sc_gameref_t gs);
+extern sc_int gs_playerposition(sc_gameref_t gs);
+extern sc_int gs_playerparent(sc_gameref_t gs);
+extern sc_int gs_event_count(sc_gameref_t gs);
+extern void gs_set_event_state(sc_gameref_t gs, sc_int event, sc_int state);
+extern void gs_set_event_time(sc_gameref_t gs, sc_int event, sc_int etime);
+extern sc_int gs_event_state(sc_gameref_t gs, sc_int event);
+extern sc_int gs_event_time(sc_gameref_t gs, sc_int event);
+extern void gs_decrement_event_time(sc_gameref_t gs, sc_int event);
+extern sc_int gs_room_count(sc_gameref_t gs);
+extern void gs_set_room_seen(sc_gameref_t gs, sc_int room, sc_bool seen);
+extern sc_bool gs_room_seen(sc_gameref_t gs, sc_int room);
+extern sc_int gs_task_count(sc_gameref_t gs);
+extern void gs_set_task_done(sc_gameref_t gs, sc_int task, sc_bool done);
+extern void gs_set_task_scored(sc_gameref_t gs, sc_int task, sc_bool scored);
+extern sc_bool gs_task_done(sc_gameref_t gs, sc_int task);
+extern sc_bool gs_task_scored(sc_gameref_t gs, sc_int task);
+extern sc_int gs_object_count(sc_gameref_t gs);
+extern void gs_set_object_openness(sc_gameref_t gs,
+ sc_int object, sc_int openness);
+extern void gs_set_object_state(sc_gameref_t gs, sc_int object, sc_int state);
+extern void gs_set_object_seen(sc_gameref_t gs, sc_int object, sc_bool seen);
+extern void gs_set_object_unmoved(sc_gameref_t gs,
+ sc_int object, sc_bool unmoved);
+extern void gs_set_object_static_unmoved(sc_gameref_t gs,
+ sc_int object, sc_bool unmoved);
+extern sc_int gs_object_openness(sc_gameref_t gs, sc_int object);
+extern sc_int gs_object_state(sc_gameref_t gs, sc_int object);
+extern sc_bool gs_object_seen(sc_gameref_t gs, sc_int object);
+extern sc_bool gs_object_unmoved(sc_gameref_t gs, sc_int object);
+extern sc_bool gs_object_static_unmoved(sc_gameref_t gs, sc_int object);
+extern sc_int gs_object_position(sc_gameref_t gs, sc_int object);
+extern sc_int gs_object_parent(sc_gameref_t gs, sc_int object);
+extern void gs_object_move_onto(sc_gameref_t gs, sc_int object, sc_int onto);
+extern void gs_object_move_into(sc_gameref_t gs, sc_int object, sc_int into);
+extern void gs_object_make_hidden(sc_gameref_t gs, sc_int object);
+extern void gs_object_player_get(sc_gameref_t gs, sc_int object);
+extern void gs_object_npc_get(sc_gameref_t gs, sc_int object, sc_int npc);
+extern void gs_object_player_wear(sc_gameref_t gs, sc_int object);
+extern void gs_object_npc_wear(sc_gameref_t gs, sc_int object, sc_int npc);
+extern void gs_object_to_room(sc_gameref_t gs, sc_int object, sc_int room);
+extern sc_int gs_npc_count(sc_gameref_t gs);
+extern void gs_set_npc_location(sc_gameref_t gs, sc_int npc, sc_int location);
+extern sc_int gs_npc_location(sc_gameref_t gs, sc_int npc);
+extern void gs_set_npc_position(sc_gameref_t gs, sc_int npc, sc_int position);
+extern sc_int gs_npc_position(sc_gameref_t gs, sc_int npc);
+extern void gs_set_npc_parent(sc_gameref_t gs, sc_int npc, sc_int parent);
+extern sc_int gs_npc_parent(sc_gameref_t gs, sc_int npc);
+extern void gs_set_npc_seen(sc_gameref_t gs, sc_int npc, sc_bool seen);
+extern sc_bool gs_npc_seen(sc_gameref_t gs, sc_int npc);
+extern sc_int gs_npc_walkstep_count(sc_gameref_t gs, sc_int npc);
+extern void gs_set_npc_walkstep(sc_gameref_t gs, sc_int npc,
+ sc_int walk, sc_int walkstep);
+extern sc_int gs_npc_walkstep(sc_gameref_t gs, sc_int npc, sc_int walk);
+extern void gs_decrement_npc_walkstep(sc_gameref_t gs,
+ sc_int npc, sc_int walkstep);
+extern void gs_clear_npc_references(sc_gameref_t gs);
+extern void gs_clear_object_references(sc_gameref_t gs);
+extern void gs_set_multiple_references(sc_gameref_t gs);
+extern void gs_clear_multiple_references(sc_gameref_t gs);
/* Pattern matching functions. */
-extern sc_bool uip_match (const sc_char *pattern,
- const sc_char *string, sc_gameref_t game);
-extern sc_char *uip_replace_pronouns (sc_gameref_t game, const sc_char *string);
-extern void uip_assign_pronouns (sc_gameref_t game, const sc_char *string);
-extern void uip_debug_trace (sc_bool flag);
+extern sc_bool uip_match(const sc_char *pattern,
+ const sc_char *string, sc_gameref_t game);
+extern sc_char *uip_replace_pronouns(sc_gameref_t game, const sc_char *string);
+extern void uip_assign_pronouns(sc_gameref_t game, const sc_char *string);
+extern void uip_debug_trace(sc_bool flag);
/* Library perspective enumeration and functions. */
-enum
-{ LIB_FIRST_PERSON = 0,
- LIB_SECOND_PERSON = 1,
- LIB_THIRD_PERSON = 2
+enum {
+ LIB_FIRST_PERSON = 0,
+ LIB_SECOND_PERSON = 1,
+ LIB_THIRD_PERSON = 2
};
-extern void lib_warn_battle_system (void);
-extern sc_int lib_random_roomgroup_member (sc_gameref_t game, sc_int roomgroup);
-extern const sc_char *lib_get_room_name (sc_gameref_t game, sc_int room);
-extern void lib_print_room_name (sc_gameref_t game, sc_int room);
-extern void lib_print_room_description (sc_gameref_t game, sc_int room);
-extern sc_bool lib_cmd_go_north (sc_gameref_t game);
-extern sc_bool lib_cmd_go_east (sc_gameref_t game);
-extern sc_bool lib_cmd_go_south (sc_gameref_t game);
-extern sc_bool lib_cmd_go_west (sc_gameref_t game);
-extern sc_bool lib_cmd_go_up (sc_gameref_t game);
-extern sc_bool lib_cmd_go_down (sc_gameref_t game);
-extern sc_bool lib_cmd_go_in (sc_gameref_t game);
-extern sc_bool lib_cmd_go_out (sc_gameref_t game);
-extern sc_bool lib_cmd_go_northeast (sc_gameref_t game);
-extern sc_bool lib_cmd_go_southeast (sc_gameref_t game);
-extern sc_bool lib_cmd_go_northwest (sc_gameref_t game);
-extern sc_bool lib_cmd_go_southwest (sc_gameref_t game);
-extern sc_bool lib_cmd_go_room (sc_gameref_t game);
-extern sc_bool lib_cmd_verbose (sc_gameref_t game);
-extern sc_bool lib_cmd_brief (sc_gameref_t game);
-extern sc_bool lib_cmd_notify_on_off (sc_gameref_t game);
-extern sc_bool lib_cmd_notify (sc_gameref_t game);
-extern sc_bool lib_cmd_time (sc_gameref_t game);
-extern sc_bool lib_cmd_date (sc_gameref_t game);
-extern sc_bool lib_cmd_quit (sc_gameref_t game);
-extern sc_bool lib_cmd_restart (sc_gameref_t game);
-extern sc_bool lib_cmd_undo (sc_gameref_t game);
-extern sc_bool lib_cmd_history (sc_gameref_t game);
-extern sc_bool lib_cmd_history_number (sc_gameref_t game);
-extern sc_bool lib_cmd_again (sc_gameref_t game);
-extern sc_bool lib_cmd_redo_number (sc_gameref_t game);
-extern sc_bool lib_cmd_redo_text (sc_gameref_t game);
-extern sc_bool lib_cmd_redo_last (sc_gameref_t game);
-extern sc_bool lib_cmd_hints (sc_gameref_t game);
-extern sc_bool lib_cmd_help (sc_gameref_t game);
-extern sc_bool lib_cmd_license (sc_gameref_t game);
-extern sc_bool lib_cmd_information (sc_gameref_t game);
-extern sc_bool lib_cmd_clear (sc_gameref_t game);
-extern sc_bool lib_cmd_statusline (sc_gameref_t game);
-extern sc_bool lib_cmd_version (sc_gameref_t game);
-extern sc_bool lib_cmd_look (sc_gameref_t game);
-extern sc_bool lib_cmd_print_room_exits (sc_gameref_t game);
-extern sc_bool lib_cmd_wait (sc_gameref_t game);
-extern sc_bool lib_cmd_wait_number (sc_gameref_t game);
-extern sc_bool lib_cmd_examine_self (sc_gameref_t game);
-extern sc_bool lib_cmd_examine_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_examine_object (sc_gameref_t game);
-extern sc_bool lib_cmd_count (sc_gameref_t game);
-extern sc_bool lib_cmd_take_all (sc_gameref_t game);
-extern sc_bool lib_cmd_take_except_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_take_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_take_all_from (sc_gameref_t game);
-extern sc_bool lib_cmd_take_from_except_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_take_from_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_take_all_from_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_take_from_npc_except_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_take_from_npc_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_take_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_drop_all (sc_gameref_t game);
-extern sc_bool lib_cmd_drop_except_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_drop_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_wear_all (sc_gameref_t game);
-extern sc_bool lib_cmd_wear_except_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_wear_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_remove_all (sc_gameref_t game);
-extern sc_bool lib_cmd_remove_except_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_remove_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_kiss_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_kiss_object (sc_gameref_t game);
-extern sc_bool lib_cmd_kiss_other (sc_gameref_t game);
-extern sc_bool lib_cmd_kill_other (sc_gameref_t game);
-extern sc_bool lib_cmd_eat_object (sc_gameref_t game);
-extern sc_bool lib_cmd_give_object_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_inventory (sc_gameref_t game);
-extern sc_bool lib_cmd_open_object (sc_gameref_t game);
-extern sc_bool lib_cmd_close_object (sc_gameref_t game);
-extern sc_bool lib_cmd_unlock_object_with (sc_gameref_t game);
-extern sc_bool lib_cmd_lock_object_with (sc_gameref_t game);
-extern sc_bool lib_cmd_unlock_object (sc_gameref_t game);
-extern sc_bool lib_cmd_lock_object (sc_gameref_t game);
-extern sc_bool lib_cmd_ask_npc_about (sc_gameref_t game);
-extern sc_bool lib_cmd_put_all_in (sc_gameref_t game);
-extern sc_bool lib_cmd_put_in_except_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_put_in_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_put_all_on (sc_gameref_t game);
-extern sc_bool lib_cmd_put_on_except_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_put_on_multiple (sc_gameref_t game);
-extern sc_bool lib_cmd_read_object (sc_gameref_t game);
-extern sc_bool lib_cmd_read_other (sc_gameref_t game);
-extern sc_bool lib_cmd_stand_on_object (sc_gameref_t game);
-extern sc_bool lib_cmd_stand_on_floor (sc_gameref_t game);
-extern sc_bool lib_cmd_attack_npc_with (sc_gameref_t game);
-extern sc_bool lib_cmd_sit_on_object (sc_gameref_t game);
-extern sc_bool lib_cmd_sit_on_floor (sc_gameref_t game);
-extern sc_bool lib_cmd_lie_on_object (sc_gameref_t game);
-extern sc_bool lib_cmd_lie_on_floor (sc_gameref_t game);
-extern sc_bool lib_cmd_get_off_object (sc_gameref_t game);
-extern sc_bool lib_cmd_get_off (sc_gameref_t game);
-extern sc_bool lib_cmd_save (sc_gameref_t game);
-extern sc_bool lib_cmd_restore (sc_gameref_t game);
-extern sc_bool lib_cmd_locate_object (sc_gameref_t game);
-extern sc_bool lib_cmd_locate_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_turns (sc_gameref_t game);
-extern sc_bool lib_cmd_score (sc_gameref_t game);
-extern sc_bool lib_cmd_get_what (sc_gameref_t game);
-extern sc_bool lib_cmd_open_what (sc_gameref_t game);
-extern sc_bool lib_cmd_close_other (sc_gameref_t game);
-extern sc_bool lib_cmd_lock_other (sc_gameref_t game);
-extern sc_bool lib_cmd_lock_what (sc_gameref_t game);
-extern sc_bool lib_cmd_unlock_other (sc_gameref_t game);
-extern sc_bool lib_cmd_unlock_what (sc_gameref_t game);
-extern sc_bool lib_cmd_stand_other (sc_gameref_t game);
-extern sc_bool lib_cmd_sit_other (sc_gameref_t game);
-extern sc_bool lib_cmd_lie_other (sc_gameref_t game);
-extern sc_bool lib_cmd_give_object (sc_gameref_t game);
-extern sc_bool lib_cmd_give_what (sc_gameref_t game);
-extern sc_bool lib_cmd_remove_what (sc_gameref_t game);
-extern sc_bool lib_cmd_drop_what (sc_gameref_t game);
-extern sc_bool lib_cmd_wear_what (sc_gameref_t game);
-extern sc_bool lib_cmd_profanity (sc_gameref_t game);
-extern sc_bool lib_cmd_examine_all (sc_gameref_t game);
-extern sc_bool lib_cmd_examine_other (sc_gameref_t game);
-extern sc_bool lib_cmd_locate_other (sc_gameref_t game);
-extern sc_bool lib_cmd_unix_like (sc_gameref_t game);
-extern sc_bool lib_cmd_dos_like (sc_gameref_t game);
-extern sc_bool lib_cmd_ask_object (sc_gameref_t game);
-extern sc_bool lib_cmd_ask_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_ask_other (sc_gameref_t game);
-extern sc_bool lib_cmd_block_object (sc_gameref_t game);
-extern sc_bool lib_cmd_block_other (sc_gameref_t game);
-extern sc_bool lib_cmd_block_what (sc_gameref_t game);
-extern sc_bool lib_cmd_break_object (sc_gameref_t game);
-extern sc_bool lib_cmd_break_other (sc_gameref_t game);
-extern sc_bool lib_cmd_break_what (sc_gameref_t game);
-extern sc_bool lib_cmd_destroy_what (sc_gameref_t game);
-extern sc_bool lib_cmd_smash_what (sc_gameref_t game);
-extern sc_bool lib_cmd_buy_object (sc_gameref_t game);
-extern sc_bool lib_cmd_buy_other (sc_gameref_t game);
-extern sc_bool lib_cmd_buy_what (sc_gameref_t game);
-extern sc_bool lib_cmd_clean_object (sc_gameref_t game);
-extern sc_bool lib_cmd_clean_other (sc_gameref_t game);
-extern sc_bool lib_cmd_clean_what (sc_gameref_t game);
-extern sc_bool lib_cmd_climb_object (sc_gameref_t game);
-extern sc_bool lib_cmd_climb_other (sc_gameref_t game);
-extern sc_bool lib_cmd_climb_what (sc_gameref_t game);
-extern sc_bool lib_cmd_cry (sc_gameref_t game);
-extern sc_bool lib_cmd_cut_object (sc_gameref_t game);
-extern sc_bool lib_cmd_cut_other (sc_gameref_t game);
-extern sc_bool lib_cmd_cut_what (sc_gameref_t game);
-extern sc_bool lib_cmd_drink_object (sc_gameref_t game);
-extern sc_bool lib_cmd_drink_other (sc_gameref_t game);
-extern sc_bool lib_cmd_drink_what (sc_gameref_t game);
-extern sc_bool lib_cmd_dance (sc_gameref_t game);
-extern sc_bool lib_cmd_eat_other (sc_gameref_t game);
-extern sc_bool lib_cmd_feed (sc_gameref_t game);
-extern sc_bool lib_cmd_fight (sc_gameref_t game);
-extern sc_bool lib_cmd_feel (sc_gameref_t game);
-extern sc_bool lib_cmd_fix_object (sc_gameref_t game);
-extern sc_bool lib_cmd_fix_other (sc_gameref_t game);
-extern sc_bool lib_cmd_fix_what (sc_gameref_t game);
-extern sc_bool lib_cmd_fly (sc_gameref_t game);
-extern sc_bool lib_cmd_hint (sc_gameref_t game);
-extern sc_bool lib_cmd_attack_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_hit_object (sc_gameref_t game);
-extern sc_bool lib_cmd_hit_other (sc_gameref_t game);
-extern sc_bool lib_cmd_hit_what (sc_gameref_t game);
-extern sc_bool lib_cmd_hum (sc_gameref_t game);
-extern sc_bool lib_cmd_jump (sc_gameref_t game);
-extern sc_bool lib_cmd_kick_object (sc_gameref_t game);
-extern sc_bool lib_cmd_kick_other (sc_gameref_t game);
-extern sc_bool lib_cmd_kick_what (sc_gameref_t game);
-extern sc_bool lib_cmd_light_object (sc_gameref_t game);
-extern sc_bool lib_cmd_light_other (sc_gameref_t game);
-extern sc_bool lib_cmd_light_what (sc_gameref_t game);
-extern sc_bool lib_cmd_lift_object (sc_gameref_t game);
-extern sc_bool lib_cmd_lift_other (sc_gameref_t game);
-extern sc_bool lib_cmd_lift_what (sc_gameref_t game);
-extern sc_bool lib_cmd_listen (sc_gameref_t game);
-extern sc_bool lib_cmd_mend_object (sc_gameref_t game);
-extern sc_bool lib_cmd_mend_other (sc_gameref_t game);
-extern sc_bool lib_cmd_mend_what (sc_gameref_t game);
-extern sc_bool lib_cmd_move_object (sc_gameref_t game);
-extern sc_bool lib_cmd_move_other (sc_gameref_t game);
-extern sc_bool lib_cmd_move_what (sc_gameref_t game);
-extern sc_bool lib_cmd_please (sc_gameref_t game);
-extern sc_bool lib_cmd_press_object (sc_gameref_t game);
-extern sc_bool lib_cmd_press_other (sc_gameref_t game);
-extern sc_bool lib_cmd_press_what (sc_gameref_t game);
-extern sc_bool lib_cmd_pull_object (sc_gameref_t game);
-extern sc_bool lib_cmd_pull_other (sc_gameref_t game);
-extern sc_bool lib_cmd_pull_what (sc_gameref_t game);
-extern sc_bool lib_cmd_punch (sc_gameref_t game);
-extern sc_bool lib_cmd_push_object (sc_gameref_t game);
-extern sc_bool lib_cmd_push_other (sc_gameref_t game);
-extern sc_bool lib_cmd_push_what (sc_gameref_t game);
-extern sc_bool lib_cmd_repair_object (sc_gameref_t game);
-extern sc_bool lib_cmd_repair_other (sc_gameref_t game);
-extern sc_bool lib_cmd_repair_what (sc_gameref_t game);
-extern sc_bool lib_cmd_rub_object (sc_gameref_t game);
-extern sc_bool lib_cmd_rub_other (sc_gameref_t game);
-extern sc_bool lib_cmd_rub_what (sc_gameref_t game);
-extern sc_bool lib_cmd_run (sc_gameref_t game);
-extern sc_bool lib_cmd_say (sc_gameref_t game);
-extern sc_bool lib_cmd_sell_object (sc_gameref_t game);
-extern sc_bool lib_cmd_sell_other (sc_gameref_t game);
-extern sc_bool lib_cmd_sell_what (sc_gameref_t game);
-extern sc_bool lib_cmd_shake_object (sc_gameref_t game);
-extern sc_bool lib_cmd_shake_npc (sc_gameref_t game);
-extern sc_bool lib_cmd_shake_other (sc_gameref_t game);
-extern sc_bool lib_cmd_shake_what (sc_gameref_t game);
-extern sc_bool lib_cmd_shout (sc_gameref_t game);
-extern sc_bool lib_cmd_sing (sc_gameref_t game);
-extern sc_bool lib_cmd_sleep (sc_gameref_t game);
-extern sc_bool lib_cmd_smell_object (sc_gameref_t game);
-extern sc_bool lib_cmd_smell_other (sc_gameref_t game);
-extern sc_bool lib_cmd_stop_object (sc_gameref_t game);
-extern sc_bool lib_cmd_stop_other (sc_gameref_t game);
-extern sc_bool lib_cmd_stop_what (sc_gameref_t game);
-extern sc_bool lib_cmd_suck_object (sc_gameref_t game);
-extern sc_bool lib_cmd_suck_other (sc_gameref_t game);
-extern sc_bool lib_cmd_suck_what (sc_gameref_t game);
-extern sc_bool lib_cmd_talk (sc_gameref_t game);
-extern sc_bool lib_cmd_thank (sc_gameref_t game);
-extern sc_bool lib_cmd_touch_object (sc_gameref_t game);
-extern sc_bool lib_cmd_touch_other (sc_gameref_t game);
-extern sc_bool lib_cmd_touch_what (sc_gameref_t game);
-extern sc_bool lib_cmd_turn_object (sc_gameref_t game);
-extern sc_bool lib_cmd_turn_other (sc_gameref_t game);
-extern sc_bool lib_cmd_turn_what (sc_gameref_t game);
-extern sc_bool lib_cmd_unblock_object (sc_gameref_t game);
-extern sc_bool lib_cmd_unblock_other (sc_gameref_t game);
-extern sc_bool lib_cmd_unblock_what (sc_gameref_t game);
-extern sc_bool lib_cmd_wash_object (sc_gameref_t game);
-extern sc_bool lib_cmd_wash_other (sc_gameref_t game);
-extern sc_bool lib_cmd_wash_what (sc_gameref_t game);
-extern sc_bool lib_cmd_whistle (sc_gameref_t game);
-extern sc_bool lib_cmd_interrogation (sc_gameref_t game);
-extern sc_bool lib_cmd_xyzzy (sc_gameref_t game);
-extern sc_bool lib_cmd_egotistic (sc_gameref_t game);
-extern sc_bool lib_cmd_yes_or_no (sc_gameref_t game);
-extern sc_bool lib_cmd_verb_object (sc_gameref_t game);
-extern sc_bool lib_cmd_verb_npc (sc_gameref_t game);
-extern void lib_debug_trace (sc_bool flag);
+extern void lib_warn_battle_system(void);
+extern sc_int lib_random_roomgroup_member(sc_gameref_t game, sc_int roomgroup);
+extern const sc_char *lib_get_room_name(sc_gameref_t game, sc_int room);
+extern void lib_print_room_name(sc_gameref_t game, sc_int room);
+extern void lib_print_room_description(sc_gameref_t game, sc_int room);
+extern sc_bool lib_cmd_go_north(sc_gameref_t game);
+extern sc_bool lib_cmd_go_east(sc_gameref_t game);
+extern sc_bool lib_cmd_go_south(sc_gameref_t game);
+extern sc_bool lib_cmd_go_west(sc_gameref_t game);
+extern sc_bool lib_cmd_go_up(sc_gameref_t game);
+extern sc_bool lib_cmd_go_down(sc_gameref_t game);
+extern sc_bool lib_cmd_go_in(sc_gameref_t game);
+extern sc_bool lib_cmd_go_out(sc_gameref_t game);
+extern sc_bool lib_cmd_go_northeast(sc_gameref_t game);
+extern sc_bool lib_cmd_go_southeast(sc_gameref_t game);
+extern sc_bool lib_cmd_go_northwest(sc_gameref_t game);
+extern sc_bool lib_cmd_go_southwest(sc_gameref_t game);
+extern sc_bool lib_cmd_go_room(sc_gameref_t game);
+extern sc_bool lib_cmd_verbose(sc_gameref_t game);
+extern sc_bool lib_cmd_brief(sc_gameref_t game);
+extern sc_bool lib_cmd_notify_on_off(sc_gameref_t game);
+extern sc_bool lib_cmd_notify(sc_gameref_t game);
+extern sc_bool lib_cmd_time(sc_gameref_t game);
+extern sc_bool lib_cmd_date(sc_gameref_t game);
+extern sc_bool lib_cmd_quit(sc_gameref_t game);
+extern sc_bool lib_cmd_restart(sc_gameref_t game);
+extern sc_bool lib_cmd_undo(sc_gameref_t game);
+extern sc_bool lib_cmd_history(sc_gameref_t game);
+extern sc_bool lib_cmd_history_number(sc_gameref_t game);
+extern sc_bool lib_cmd_again(sc_gameref_t game);
+extern sc_bool lib_cmd_redo_number(sc_gameref_t game);
+extern sc_bool lib_cmd_redo_text(sc_gameref_t game);
+extern sc_bool lib_cmd_redo_last(sc_gameref_t game);
+extern sc_bool lib_cmd_hints(sc_gameref_t game);
+extern sc_bool lib_cmd_help(sc_gameref_t game);
+extern sc_bool lib_cmd_license(sc_gameref_t game);
+extern sc_bool lib_cmd_information(sc_gameref_t game);
+extern sc_bool lib_cmd_clear(sc_gameref_t game);
+extern sc_bool lib_cmd_statusline(sc_gameref_t game);
+extern sc_bool lib_cmd_version(sc_gameref_t game);
+extern sc_bool lib_cmd_look(sc_gameref_t game);
+extern sc_bool lib_cmd_print_room_exits(sc_gameref_t game);
+extern sc_bool lib_cmd_wait(sc_gameref_t game);
+extern sc_bool lib_cmd_wait_number(sc_gameref_t game);
+extern sc_bool lib_cmd_examine_self(sc_gameref_t game);
+extern sc_bool lib_cmd_examine_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_examine_object(sc_gameref_t game);
+extern sc_bool lib_cmd_count(sc_gameref_t game);
+extern sc_bool lib_cmd_take_all(sc_gameref_t game);
+extern sc_bool lib_cmd_take_except_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_take_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_take_all_from(sc_gameref_t game);
+extern sc_bool lib_cmd_take_from_except_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_take_from_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_take_all_from_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_take_from_npc_except_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_take_from_npc_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_take_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_drop_all(sc_gameref_t game);
+extern sc_bool lib_cmd_drop_except_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_drop_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_wear_all(sc_gameref_t game);
+extern sc_bool lib_cmd_wear_except_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_wear_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_remove_all(sc_gameref_t game);
+extern sc_bool lib_cmd_remove_except_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_remove_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_kiss_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_kiss_object(sc_gameref_t game);
+extern sc_bool lib_cmd_kiss_other(sc_gameref_t game);
+extern sc_bool lib_cmd_kill_other(sc_gameref_t game);
+extern sc_bool lib_cmd_eat_object(sc_gameref_t game);
+extern sc_bool lib_cmd_give_object_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_inventory(sc_gameref_t game);
+extern sc_bool lib_cmd_open_object(sc_gameref_t game);
+extern sc_bool lib_cmd_close_object(sc_gameref_t game);
+extern sc_bool lib_cmd_unlock_object_with(sc_gameref_t game);
+extern sc_bool lib_cmd_lock_object_with(sc_gameref_t game);
+extern sc_bool lib_cmd_unlock_object(sc_gameref_t game);
+extern sc_bool lib_cmd_lock_object(sc_gameref_t game);
+extern sc_bool lib_cmd_ask_npc_about(sc_gameref_t game);
+extern sc_bool lib_cmd_put_all_in(sc_gameref_t game);
+extern sc_bool lib_cmd_put_in_except_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_put_in_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_put_all_on(sc_gameref_t game);
+extern sc_bool lib_cmd_put_on_except_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_put_on_multiple(sc_gameref_t game);
+extern sc_bool lib_cmd_read_object(sc_gameref_t game);
+extern sc_bool lib_cmd_read_other(sc_gameref_t game);
+extern sc_bool lib_cmd_stand_on_object(sc_gameref_t game);
+extern sc_bool lib_cmd_stand_on_floor(sc_gameref_t game);
+extern sc_bool lib_cmd_attack_npc_with(sc_gameref_t game);
+extern sc_bool lib_cmd_sit_on_object(sc_gameref_t game);
+extern sc_bool lib_cmd_sit_on_floor(sc_gameref_t game);
+extern sc_bool lib_cmd_lie_on_object(sc_gameref_t game);
+extern sc_bool lib_cmd_lie_on_floor(sc_gameref_t game);
+extern sc_bool lib_cmd_get_off_object(sc_gameref_t game);
+extern sc_bool lib_cmd_get_off(sc_gameref_t game);
+extern sc_bool lib_cmd_save(sc_gameref_t game);
+extern sc_bool lib_cmd_restore(sc_gameref_t game);
+extern sc_bool lib_cmd_locate_object(sc_gameref_t game);
+extern sc_bool lib_cmd_locate_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_turns(sc_gameref_t game);
+extern sc_bool lib_cmd_score(sc_gameref_t game);
+extern sc_bool lib_cmd_get_what(sc_gameref_t game);
+extern sc_bool lib_cmd_open_what(sc_gameref_t game);
+extern sc_bool lib_cmd_close_other(sc_gameref_t game);
+extern sc_bool lib_cmd_lock_other(sc_gameref_t game);
+extern sc_bool lib_cmd_lock_what(sc_gameref_t game);
+extern sc_bool lib_cmd_unlock_other(sc_gameref_t game);
+extern sc_bool lib_cmd_unlock_what(sc_gameref_t game);
+extern sc_bool lib_cmd_stand_other(sc_gameref_t game);
+extern sc_bool lib_cmd_sit_other(sc_gameref_t game);
+extern sc_bool lib_cmd_lie_other(sc_gameref_t game);
+extern sc_bool lib_cmd_give_object(sc_gameref_t game);
+extern sc_bool lib_cmd_give_what(sc_gameref_t game);
+extern sc_bool lib_cmd_remove_what(sc_gameref_t game);
+extern sc_bool lib_cmd_drop_what(sc_gameref_t game);
+extern sc_bool lib_cmd_wear_what(sc_gameref_t game);
+extern sc_bool lib_cmd_profanity(sc_gameref_t game);
+extern sc_bool lib_cmd_examine_all(sc_gameref_t game);
+extern sc_bool lib_cmd_examine_other(sc_gameref_t game);
+extern sc_bool lib_cmd_locate_other(sc_gameref_t game);
+extern sc_bool lib_cmd_unix_like(sc_gameref_t game);
+extern sc_bool lib_cmd_dos_like(sc_gameref_t game);
+extern sc_bool lib_cmd_ask_object(sc_gameref_t game);
+extern sc_bool lib_cmd_ask_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_ask_other(sc_gameref_t game);
+extern sc_bool lib_cmd_block_object(sc_gameref_t game);
+extern sc_bool lib_cmd_block_other(sc_gameref_t game);
+extern sc_bool lib_cmd_block_what(sc_gameref_t game);
+extern sc_bool lib_cmd_break_object(sc_gameref_t game);
+extern sc_bool lib_cmd_break_other(sc_gameref_t game);
+extern sc_bool lib_cmd_break_what(sc_gameref_t game);
+extern sc_bool lib_cmd_destroy_what(sc_gameref_t game);
+extern sc_bool lib_cmd_smash_what(sc_gameref_t game);
+extern sc_bool lib_cmd_buy_object(sc_gameref_t game);
+extern sc_bool lib_cmd_buy_other(sc_gameref_t game);
+extern sc_bool lib_cmd_buy_what(sc_gameref_t game);
+extern sc_bool lib_cmd_clean_object(sc_gameref_t game);
+extern sc_bool lib_cmd_clean_other(sc_gameref_t game);
+extern sc_bool lib_cmd_clean_what(sc_gameref_t game);
+extern sc_bool lib_cmd_climb_object(sc_gameref_t game);
+extern sc_bool lib_cmd_climb_other(sc_gameref_t game);
+extern sc_bool lib_cmd_climb_what(sc_gameref_t game);
+extern sc_bool lib_cmd_cry(sc_gameref_t game);
+extern sc_bool lib_cmd_cut_object(sc_gameref_t game);
+extern sc_bool lib_cmd_cut_other(sc_gameref_t game);
+extern sc_bool lib_cmd_cut_what(sc_gameref_t game);
+extern sc_bool lib_cmd_drink_object(sc_gameref_t game);
+extern sc_bool lib_cmd_drink_other(sc_gameref_t game);
+extern sc_bool lib_cmd_drink_what(sc_gameref_t game);
+extern sc_bool lib_cmd_dance(sc_gameref_t game);
+extern sc_bool lib_cmd_eat_other(sc_gameref_t game);
+extern sc_bool lib_cmd_feed(sc_gameref_t game);
+extern sc_bool lib_cmd_fight(sc_gameref_t game);
+extern sc_bool lib_cmd_feel(sc_gameref_t game);
+extern sc_bool lib_cmd_fix_object(sc_gameref_t game);
+extern sc_bool lib_cmd_fix_other(sc_gameref_t game);
+extern sc_bool lib_cmd_fix_what(sc_gameref_t game);
+extern sc_bool lib_cmd_fly(sc_gameref_t game);
+extern sc_bool lib_cmd_hint(sc_gameref_t game);
+extern sc_bool lib_cmd_attack_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_hit_object(sc_gameref_t game);
+extern sc_bool lib_cmd_hit_other(sc_gameref_t game);
+extern sc_bool lib_cmd_hit_what(sc_gameref_t game);
+extern sc_bool lib_cmd_hum(sc_gameref_t game);
+extern sc_bool lib_cmd_jump(sc_gameref_t game);
+extern sc_bool lib_cmd_kick_object(sc_gameref_t game);
+extern sc_bool lib_cmd_kick_other(sc_gameref_t game);
+extern sc_bool lib_cmd_kick_what(sc_gameref_t game);
+extern sc_bool lib_cmd_light_object(sc_gameref_t game);
+extern sc_bool lib_cmd_light_other(sc_gameref_t game);
+extern sc_bool lib_cmd_light_what(sc_gameref_t game);
+extern sc_bool lib_cmd_lift_object(sc_gameref_t game);
+extern sc_bool lib_cmd_lift_other(sc_gameref_t game);
+extern sc_bool lib_cmd_lift_what(sc_gameref_t game);
+extern sc_bool lib_cmd_listen(sc_gameref_t game);
+extern sc_bool lib_cmd_mend_object(sc_gameref_t game);
+extern sc_bool lib_cmd_mend_other(sc_gameref_t game);
+extern sc_bool lib_cmd_mend_what(sc_gameref_t game);
+extern sc_bool lib_cmd_move_object(sc_gameref_t game);
+extern sc_bool lib_cmd_move_other(sc_gameref_t game);
+extern sc_bool lib_cmd_move_what(sc_gameref_t game);
+extern sc_bool lib_cmd_please(sc_gameref_t game);
+extern sc_bool lib_cmd_press_object(sc_gameref_t game);
+extern sc_bool lib_cmd_press_other(sc_gameref_t game);
+extern sc_bool lib_cmd_press_what(sc_gameref_t game);
+extern sc_bool lib_cmd_pull_object(sc_gameref_t game);
+extern sc_bool lib_cmd_pull_other(sc_gameref_t game);
+extern sc_bool lib_cmd_pull_what(sc_gameref_t game);
+extern sc_bool lib_cmd_punch(sc_gameref_t game);
+extern sc_bool lib_cmd_push_object(sc_gameref_t game);
+extern sc_bool lib_cmd_push_other(sc_gameref_t game);
+extern sc_bool lib_cmd_push_what(sc_gameref_t game);
+extern sc_bool lib_cmd_repair_object(sc_gameref_t game);
+extern sc_bool lib_cmd_repair_other(sc_gameref_t game);
+extern sc_bool lib_cmd_repair_what(sc_gameref_t game);
+extern sc_bool lib_cmd_rub_object(sc_gameref_t game);
+extern sc_bool lib_cmd_rub_other(sc_gameref_t game);
+extern sc_bool lib_cmd_rub_what(sc_gameref_t game);
+extern sc_bool lib_cmd_run(sc_gameref_t game);
+extern sc_bool lib_cmd_say(sc_gameref_t game);
+extern sc_bool lib_cmd_sell_object(sc_gameref_t game);
+extern sc_bool lib_cmd_sell_other(sc_gameref_t game);
+extern sc_bool lib_cmd_sell_what(sc_gameref_t game);
+extern sc_bool lib_cmd_shake_object(sc_gameref_t game);
+extern sc_bool lib_cmd_shake_npc(sc_gameref_t game);
+extern sc_bool lib_cmd_shake_other(sc_gameref_t game);
+extern sc_bool lib_cmd_shake_what(sc_gameref_t game);
+extern sc_bool lib_cmd_shout(sc_gameref_t game);
+extern sc_bool lib_cmd_sing(sc_gameref_t game);
+extern sc_bool lib_cmd_sleep(sc_gameref_t game);
+extern sc_bool lib_cmd_smell_object(sc_gameref_t game);
+extern sc_bool lib_cmd_smell_other(sc_gameref_t game);
+extern sc_bool lib_cmd_stop_object(sc_gameref_t game);
+extern sc_bool lib_cmd_stop_other(sc_gameref_t game);
+extern sc_bool lib_cmd_stop_what(sc_gameref_t game);
+extern sc_bool lib_cmd_suck_object(sc_gameref_t game);
+extern sc_bool lib_cmd_suck_other(sc_gameref_t game);
+extern sc_bool lib_cmd_suck_what(sc_gameref_t game);
+extern sc_bool lib_cmd_talk(sc_gameref_t game);
+extern sc_bool lib_cmd_thank(sc_gameref_t game);
+extern sc_bool lib_cmd_touch_object(sc_gameref_t game);
+extern sc_bool lib_cmd_touch_other(sc_gameref_t game);
+extern sc_bool lib_cmd_touch_what(sc_gameref_t game);
+extern sc_bool lib_cmd_turn_object(sc_gameref_t game);
+extern sc_bool lib_cmd_turn_other(sc_gameref_t game);
+extern sc_bool lib_cmd_turn_what(sc_gameref_t game);
+extern sc_bool lib_cmd_unblock_object(sc_gameref_t game);
+extern sc_bool lib_cmd_unblock_other(sc_gameref_t game);
+extern sc_bool lib_cmd_unblock_what(sc_gameref_t game);
+extern sc_bool lib_cmd_wash_object(sc_gameref_t game);
+extern sc_bool lib_cmd_wash_other(sc_gameref_t game);
+extern sc_bool lib_cmd_wash_what(sc_gameref_t game);
+extern sc_bool lib_cmd_whistle(sc_gameref_t game);
+extern sc_bool lib_cmd_interrogation(sc_gameref_t game);
+extern sc_bool lib_cmd_xyzzy(sc_gameref_t game);
+extern sc_bool lib_cmd_egotistic(sc_gameref_t game);
+extern sc_bool lib_cmd_yes_or_no(sc_gameref_t game);
+extern sc_bool lib_cmd_verb_object(sc_gameref_t game);
+extern sc_bool lib_cmd_verb_npc(sc_gameref_t game);
+extern void lib_debug_trace(sc_bool flag);
/* Resource opaque typedef and control functions. */
typedef struct sc_resource_s *sc_resourceref_t;
-extern sc_bool res_has_sound (sc_gameref_t game);
-extern sc_bool res_has_graphics (sc_gameref_t game);
-extern void res_clear_resource (sc_resourceref_t resource);
-extern sc_bool res_compare_resource (sc_resourceref_t from,
- sc_resourceref_t with);
-extern void res_handle_resource (sc_gameref_t game,
- const sc_char *partial_format,
- const sc_vartype_t vt_partial[]);
-extern void res_sync_resources (sc_gameref_t game);
-extern void res_cancel_resources (sc_gameref_t game);
+extern sc_bool res_has_sound(sc_gameref_t game);
+extern sc_bool res_has_graphics(sc_gameref_t game);
+extern void res_clear_resource(sc_resourceref_t resource);
+extern sc_bool res_compare_resource(sc_resourceref_t from,
+ sc_resourceref_t with);
+extern void res_handle_resource(sc_gameref_t game,
+ const sc_char *partial_format,
+ const sc_vartype_t vt_partial[]);
+extern void res_sync_resources(sc_gameref_t game);
+extern void res_cancel_resources(sc_gameref_t game);
/* Game runner functions. */
-extern sc_bool run_game_task_commands (sc_gameref_t game,
- const sc_char *string);
-extern sc_gameref_t run_create (sc_read_callbackref_t callback, void *opaque);
-extern void run_interpret (sc_gameref_t game);
-extern void run_destroy (sc_gameref_t game);
-extern void run_restart (sc_gameref_t game);
-extern void run_save (sc_gameref_t game,
- sc_write_callbackref_t callback, void *opaque);
-extern sc_bool run_save_prompted (sc_gameref_t game);
-extern sc_bool run_restore (sc_gameref_t game,
- sc_read_callbackref_t callback, void *opaque);
-extern sc_bool run_restore_prompted (sc_gameref_t game);
-extern sc_bool run_undo (sc_gameref_t game);
-extern void run_quit (sc_gameref_t game);
-extern sc_bool run_is_running (sc_gameref_t game);
-extern sc_bool run_has_completed (sc_gameref_t game);
-extern sc_bool run_is_undo_available (sc_gameref_t game);
-extern void run_debug_trace (sc_bool flag);
-extern void run_get_attributes (sc_gameref_t game,
- const sc_char **game_name,
- const sc_char **game_author,
- const sc_char **game_compile_date,
- sc_int *turns, sc_int *score,
- sc_int *max_score,
- const sc_char **current_room_name,
- const sc_char **status_line,
- const sc_char **preferred_font,
- sc_bool *bold_room_names, sc_bool *verbose,
- sc_bool *notify_score_change);
-extern void run_set_attributes (sc_gameref_t game,
- sc_bool bold_room_names, sc_bool verbose,
- sc_bool notify_score_change);
-extern sc_hintref_t run_hint_iterate (sc_gameref_t game, sc_hintref_t hint);
-extern const sc_char *run_get_hint_question (sc_gameref_t game,
- sc_hintref_t hint);
-extern const sc_char *run_get_subtle_hint (sc_gameref_t game,
- sc_hintref_t hint);
-extern const sc_char *run_get_unsubtle_hint (sc_gameref_t game,
- sc_hintref_t hint);
+extern sc_bool run_game_task_commands(sc_gameref_t game,
+ const sc_char *string);
+extern sc_gameref_t run_create(sc_read_callbackref_t callback, void *opaque);
+extern void run_interpret(sc_gameref_t game);
+extern void run_destroy(sc_gameref_t game);
+extern void run_restart(sc_gameref_t game);
+extern void run_save(sc_gameref_t game,
+ sc_write_callbackref_t callback, void *opaque);
+extern sc_bool run_save_prompted(sc_gameref_t game);
+extern sc_bool run_restore(sc_gameref_t game,
+ sc_read_callbackref_t callback, void *opaque);
+extern sc_bool run_restore_prompted(sc_gameref_t game);
+extern sc_bool run_undo(sc_gameref_t game);
+extern void run_quit(sc_gameref_t game);
+extern sc_bool run_is_running(sc_gameref_t game);
+extern sc_bool run_has_completed(sc_gameref_t game);
+extern sc_bool run_is_undo_available(sc_gameref_t game);
+extern void run_debug_trace(sc_bool flag);
+extern void run_get_attributes(sc_gameref_t game,
+ const sc_char **game_name,
+ const sc_char **game_author,
+ const sc_char **game_compile_date,
+ sc_int *turns, sc_int *score,
+ sc_int *max_score,
+ const sc_char **current_room_name,
+ const sc_char **status_line,
+ const sc_char **preferred_font,
+ sc_bool *bold_room_names, sc_bool *verbose,
+ sc_bool *notify_score_change);
+extern void run_set_attributes(sc_gameref_t game,
+ sc_bool bold_room_names, sc_bool verbose,
+ sc_bool notify_score_change);
+extern sc_hintref_t run_hint_iterate(sc_gameref_t game, sc_hintref_t hint);
+extern const sc_char *run_get_hint_question(sc_gameref_t game,
+ sc_hintref_t hint);
+extern const sc_char *run_get_subtle_hint(sc_gameref_t game,
+ sc_hintref_t hint);
+extern const sc_char *run_get_unsubtle_hint(sc_gameref_t game,
+ sc_hintref_t hint);
/* Event functions. */
-extern sc_bool evt_can_see_event (sc_gameref_t game, sc_int event);
-extern void evt_tick_events (sc_gameref_t game);
-extern void evt_debug_trace (sc_bool flag);
+extern sc_bool evt_can_see_event(sc_gameref_t game, sc_int event);
+extern void evt_tick_events(sc_gameref_t game);
+extern void evt_debug_trace(sc_bool flag);
/* Task functions. */
-extern sc_bool task_has_hints (sc_gameref_t game, sc_int task);
-extern const sc_char *task_get_hint_question (sc_gameref_t game, sc_int task);
-extern const sc_char *task_get_hint_subtle (sc_gameref_t game, sc_int task);
-extern const sc_char *task_get_hint_unsubtle (sc_gameref_t game, sc_int task);
-extern sc_bool task_can_run_task_directional (sc_gameref_t game,
- sc_int task, sc_bool forwards);
-extern sc_bool task_can_run_task (sc_gameref_t game, sc_int task);
-extern sc_bool task_run_task (sc_gameref_t game, sc_int task, sc_bool forwards);
-extern void task_debug_trace (sc_bool flag);
+extern sc_bool task_has_hints(sc_gameref_t game, sc_int task);
+extern const sc_char *task_get_hint_question(sc_gameref_t game, sc_int task);
+extern const sc_char *task_get_hint_subtle(sc_gameref_t game, sc_int task);
+extern const sc_char *task_get_hint_unsubtle(sc_gameref_t game, sc_int task);
+extern sc_bool task_can_run_task_directional(sc_gameref_t game,
+ sc_int task, sc_bool forwards);
+extern sc_bool task_can_run_task(sc_gameref_t game, sc_int task);
+extern sc_bool task_run_task(sc_gameref_t game, sc_int task, sc_bool forwards);
+extern void task_debug_trace(sc_bool flag);
/* Task restriction functions. */
-extern sc_bool restr_pass_task_object_state (sc_gameref_t game,
- sc_int var1, sc_int var2);
-extern sc_bool restr_eval_task_restrictions (sc_gameref_t game,
- sc_int task, sc_bool *pass,
- const sc_char **fail_message);
-extern void restr_debug_trace (sc_bool flag);
+extern sc_bool restr_pass_task_object_state(sc_gameref_t game,
+ sc_int var1, sc_int var2);
+extern sc_bool restr_eval_task_restrictions(sc_gameref_t game,
+ sc_int task, sc_bool *pass,
+ const sc_char **fail_message);
+extern void restr_debug_trace(sc_bool flag);
/* NPC gender enumeration and functions. */
-enum
-{ NPC_MALE = 0,
- NPC_FEMALE = 1,
- NPC_NEUTER = 2
+enum {
+ NPC_MALE = 0,
+ NPC_FEMALE = 1,
+ NPC_NEUTER = 2
};
-extern sc_bool npc_in_room (sc_gameref_t game, sc_int npc, sc_int room);
-extern sc_int npc_count_in_room (sc_gameref_t game, sc_int room);
-extern void npc_setup_initial (sc_gameref_t game);
-extern void npc_start_npc_walk (sc_gameref_t game, sc_int npc, sc_int walk);
-extern void npc_tick_npcs (sc_gameref_t game);
-extern void npc_turn_update (sc_gameref_t game);
-extern void npc_debug_trace (sc_bool flag);
+extern sc_bool npc_in_room(sc_gameref_t game, sc_int npc, sc_int room);
+extern sc_int npc_count_in_room(sc_gameref_t game, sc_int room);
+extern void npc_setup_initial(sc_gameref_t game);
+extern void npc_start_npc_walk(sc_gameref_t game, sc_int npc, sc_int walk);
+extern void npc_tick_npcs(sc_gameref_t game);
+extern void npc_turn_update(sc_gameref_t game);
+extern void npc_debug_trace(sc_bool flag);
/* Object open/closed state enumeration and functions. */
-enum
-{ OBJ_WONTCLOSE = 0,
- OBJ_OPEN = 5,
- OBJ_CLOSED = 6,
- OBJ_LOCKED = 7
+enum {
+ OBJ_WONTCLOSE = 0,
+ OBJ_OPEN = 5,
+ OBJ_CLOSED = 6,
+ OBJ_LOCKED = 7
};
-extern sc_bool obj_is_static (sc_gameref_t game, sc_int object);
-extern sc_bool obj_is_container (sc_gameref_t game, sc_int object);
-extern sc_bool obj_is_surface (sc_gameref_t game, sc_int object);
-extern sc_int obj_container_object (sc_gameref_t game, sc_int n);
-extern sc_int obj_surface_object (sc_gameref_t game, sc_int n);
-extern sc_bool obj_indirectly_in_room (sc_gameref_t game,
- sc_int object, sc_int room);
-extern sc_bool obj_indirectly_held_by_player (sc_gameref_t game, sc_int object);
-extern sc_bool obj_directly_in_room (sc_gameref_t game,
- sc_int object, sc_int room);
-extern sc_int obj_stateful_object (sc_gameref_t game, sc_int n);
-extern sc_int obj_dynamic_object (sc_gameref_t game, sc_int n);
-extern sc_int obj_wearable_object (sc_gameref_t game, sc_int n);
-extern sc_int obj_standable_object (sc_gameref_t game, sc_int n);
-extern sc_int obj_get_size (sc_gameref_t game, sc_int object);
-extern sc_int obj_get_weight (sc_gameref_t game, sc_int object);
-extern sc_int obj_get_player_size_limit (sc_gameref_t game);
-extern sc_int obj_get_player_weight_limit (sc_gameref_t game);
-extern sc_int obj_get_container_maxsize (sc_gameref_t game, sc_int object);
-extern sc_int obj_get_container_capacity (sc_gameref_t game, sc_int object);
-extern sc_int obj_lieable_object (sc_gameref_t game, sc_int n);
-extern sc_bool obj_appears_plural (sc_gameref_t game, sc_int object);
-extern void obj_setup_initial (sc_gameref_t game);
-extern sc_int obj_container_index (sc_gameref_t game, sc_int object);
-extern sc_int obj_surface_index (sc_gameref_t game, sc_int object);
-extern sc_int obj_stateful_index (sc_gameref_t game, sc_int object);
-extern sc_char *obj_state_name (sc_gameref_t game, sc_int object);
-extern sc_bool obj_shows_initial_description (sc_gameref_t game, sc_int object);
-extern void obj_turn_update (sc_gameref_t game);
-extern void obj_debug_trace (sc_bool flag);
+extern sc_bool obj_is_static(sc_gameref_t game, sc_int object);
+extern sc_bool obj_is_container(sc_gameref_t game, sc_int object);
+extern sc_bool obj_is_surface(sc_gameref_t game, sc_int object);
+extern sc_int obj_container_object(sc_gameref_t game, sc_int n);
+extern sc_int obj_surface_object(sc_gameref_t game, sc_int n);
+extern sc_bool obj_indirectly_in_room(sc_gameref_t game,
+ sc_int object, sc_int room);
+extern sc_bool obj_indirectly_held_by_player(sc_gameref_t game, sc_int object);
+extern sc_bool obj_directly_in_room(sc_gameref_t game,
+ sc_int object, sc_int room);
+extern sc_int obj_stateful_object(sc_gameref_t game, sc_int n);
+extern sc_int obj_dynamic_object(sc_gameref_t game, sc_int n);
+extern sc_int obj_wearable_object(sc_gameref_t game, sc_int n);
+extern sc_int obj_standable_object(sc_gameref_t game, sc_int n);
+extern sc_int obj_get_size(sc_gameref_t game, sc_int object);
+extern sc_int obj_get_weight(sc_gameref_t game, sc_int object);
+extern sc_int obj_get_player_size_limit(sc_gameref_t game);
+extern sc_int obj_get_player_weight_limit(sc_gameref_t game);
+extern sc_int obj_get_container_maxsize(sc_gameref_t game, sc_int object);
+extern sc_int obj_get_container_capacity(sc_gameref_t game, sc_int object);
+extern sc_int obj_lieable_object(sc_gameref_t game, sc_int n);
+extern sc_bool obj_appears_plural(sc_gameref_t game, sc_int object);
+extern void obj_setup_initial(sc_gameref_t game);
+extern sc_int obj_container_index(sc_gameref_t game, sc_int object);
+extern sc_int obj_surface_index(sc_gameref_t game, sc_int object);
+extern sc_int obj_stateful_index(sc_gameref_t game, sc_int object);
+extern sc_char *obj_state_name(sc_gameref_t game, sc_int object);
+extern sc_bool obj_shows_initial_description(sc_gameref_t game, sc_int object);
+extern void obj_turn_update(sc_gameref_t game);
+extern void obj_debug_trace(sc_bool flag);
/* Game serialization functions. */
-extern void ser_save_game (sc_gameref_t game,
- sc_write_callbackref_t callback, void *opaque);
-extern sc_bool ser_save_game_prompted (sc_gameref_t game);
-extern sc_bool ser_load_game (sc_gameref_t game,
- sc_read_callbackref_t callback, void *opaque);
-extern sc_bool ser_load_game_prompted (sc_gameref_t game);
+extern void ser_save_game(sc_gameref_t game,
+ sc_write_callbackref_t callback, void *opaque);
+extern sc_bool ser_save_game_prompted(sc_gameref_t game);
+extern sc_bool ser_load_game(sc_gameref_t game,
+ sc_read_callbackref_t callback, void *opaque);
+extern sc_bool ser_load_game_prompted(sc_gameref_t game);
/* Locale support, and locale-sensitive functions. */
-extern void loc_detect_game_locale (sc_prop_setref_t bundle);
-extern sc_bool loc_set_locale (const sc_char *name);
-extern const sc_char *loc_get_locale (void);
-extern sc_bool sc_isspace (sc_char character);
-extern sc_bool sc_isdigit (sc_char character);
-extern sc_bool sc_isalpha (sc_char character);
-extern sc_char sc_toupper (sc_char character);
-extern sc_char sc_tolower (sc_char character);
-extern void loc_debug_dump (void);
+extern void loc_detect_game_locale(sc_prop_setref_t bundle);
+extern sc_bool loc_set_locale(const sc_char *name);
+extern const sc_char *loc_get_locale(void);
+extern sc_bool sc_isspace(sc_char character);
+extern sc_bool sc_isdigit(sc_char character);
+extern sc_bool sc_isalpha(sc_char character);
+extern sc_char sc_toupper(sc_char character);
+extern sc_char sc_tolower(sc_char character);
+extern void loc_debug_dump(void);
/* Debugger interface. */
typedef struct sc_debugger_s *sc_debuggerref_t;
-extern sc_bool debug_run_command (sc_gameref_t game,
- const sc_char *debug_command);
-extern sc_bool debug_cmd_debugger (sc_gameref_t game);
-extern void debug_set_enabled (sc_gameref_t game, sc_bool enable);
-extern sc_bool debug_get_enabled (sc_gameref_t game);
-extern void debug_game_started (sc_gameref_t game);
-extern void debug_game_ended (sc_gameref_t game);
-extern void debug_turn_update (sc_gameref_t game);
+extern sc_bool debug_run_command(sc_gameref_t game,
+ const sc_char *debug_command);
+extern sc_bool debug_cmd_debugger(sc_gameref_t game);
+extern void debug_set_enabled(sc_gameref_t game, sc_bool enable);
+extern sc_bool debug_get_enabled(sc_gameref_t game);
+extern void debug_game_started(sc_gameref_t game);
+extern void debug_game_ended(sc_gameref_t game);
+extern void debug_turn_update(sc_gameref_t game);
/* OS interface functions. */
-extern sc_bool if_get_trace_flag (sc_uint bitmask);
-extern void if_print_string (const sc_char *string);
-extern void if_print_debug (const sc_char *string);
-extern void if_print_character (sc_char character);
-extern void if_print_debug_character (sc_char character);
-extern void if_print_tag (sc_int tag, const sc_char *arg);
-extern void if_read_line (sc_char *buffer, sc_int length);
-extern void if_read_debug (sc_char *buffer, sc_int length);
-extern sc_bool if_confirm (sc_int type);
-extern void *if_open_saved_game (sc_bool is_save);
-extern void if_write_saved_game (void *opaque,
- const sc_byte *buffer, sc_int length);
-extern sc_int if_read_saved_game (void *opaque,
- sc_byte *buffer, sc_int length);
-extern void if_close_saved_game (void *opaque);
-extern void if_display_hints (sc_gameref_t game);
-extern void if_update_sound (const sc_char *filepath,
- sc_int sound_offset,
- sc_int sound_length, sc_bool is_looping);
-extern void if_update_graphic (const sc_char *filepath,
- sc_int graphic_offset,
- sc_int graphic_length);
+extern sc_bool if_get_trace_flag(sc_uint bitmask);
+extern void if_print_string(const sc_char *string);
+extern void if_print_debug(const sc_char *string);
+extern void if_print_character(sc_char character);
+extern void if_print_debug_character(sc_char character);
+extern void if_print_tag(sc_int tag, const sc_char *arg);
+extern void if_read_line(sc_char *buffer, sc_int length);
+extern void if_read_debug(sc_char *buffer, sc_int length);
+extern sc_bool if_confirm(sc_int type);
+extern void *if_open_saved_game(sc_bool is_save);
+extern void if_write_saved_game(void *opaque,
+ const sc_byte *buffer, sc_int length);
+extern sc_int if_read_saved_game(void *opaque,
+ sc_byte *buffer, sc_int length);
+extern void if_close_saved_game(void *opaque);
+extern void if_display_hints(sc_gameref_t game);
+extern void if_update_sound(const sc_char *filepath,
+ sc_int sound_offset,
+ sc_int sound_length, sc_bool is_looping);
+extern void if_update_graphic(const sc_char *filepath,
+ sc_int graphic_offset,
+ sc_int graphic_length);
#endif
diff --git a/engines/glk/adrift/scresour.cpp b/engines/glk/adrift/scresour.cpp
index bc78bf3dea..739c3d73f6 100644
--- a/engines/glk/adrift/scresour.cpp
+++ b/engines/glk/adrift/scresour.cpp
@@ -38,31 +38,29 @@ static const sc_char NUL = '\0';
* Return TRUE if the game uses sound or graphics.
*/
sc_bool
-res_has_sound (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_bool has_sound;
- assert (gs_is_game_valid (game));
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "Sound";
- has_sound = prop_get_boolean (bundle, "B<-ss", vt_key);
- return has_sound;
+res_has_sound(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_bool has_sound;
+ assert(gs_is_game_valid(game));
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Sound";
+ has_sound = prop_get_boolean(bundle, "B<-ss", vt_key);
+ return has_sound;
}
sc_bool
-res_has_graphics (sc_gameref_t game)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_bool has_graphics;
- assert (gs_is_game_valid (game));
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "Graphics";
- has_graphics = prop_get_boolean (bundle, "B<-ss", vt_key);
- return has_graphics;
+res_has_graphics(sc_gameref_t game) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_bool has_graphics;
+ assert(gs_is_game_valid(game));
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Graphics";
+ has_graphics = prop_get_boolean(bundle, "B<-ss", vt_key);
+ return has_graphics;
}
@@ -74,25 +72,22 @@ res_has_graphics (sc_gameref_t game)
* Convenience functions to set, clear, and compare resource fields.
*/
static void
-res_set_resource (sc_resourceref_t resource, const sc_char *name,
- sc_int offset, sc_int length)
-{
- resource->name = name;
- resource->offset = offset;
- resource->length = length;
+res_set_resource(sc_resourceref_t resource, const sc_char *name,
+ sc_int offset, sc_int length) {
+ resource->name = name;
+ resource->offset = offset;
+ resource->length = length;
}
void
-res_clear_resource (sc_resourceref_t resource)
-{
- res_set_resource (resource, "", 0, 0);
+res_clear_resource(sc_resourceref_t resource) {
+ res_set_resource(resource, "", 0, 0);
}
sc_bool
-res_compare_resource (sc_resourceref_t from, sc_resourceref_t with)
-{
- return strcmp (from->name, with->name) == 0
- && from->offset == with->offset && from->length == with->length;
+res_compare_resource(sc_resourceref_t from, sc_resourceref_t with) {
+ return strcmp(from->name, with->name) == 0
+ && from->offset == with->offset && from->length == with->length;
}
@@ -109,157 +104,143 @@ res_compare_resource (sc_resourceref_t from, sc_resourceref_t with)
* strlen(partial_format) elements.
*/
void
-res_handle_resource (sc_gameref_t game,
- const sc_char *partial_format,
- const sc_vartype_t vt_partial[])
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2], *vt_full;
- sc_int partial_length, resource_start_offset;
- sc_bool embedded;
- sc_char *format;
- assert (gs_is_game_valid (game));
- assert (partial_format && vt_partial);
-
- /*
- * Check for resources. If this game doesn't use any, exit now to avoid the
- * overhead of pointless lookups and allocations.
- */
- if (!(res_has_sound (game) || res_has_graphics (game)))
- return;
-
- /*
- * Get the global offset for all resources. For version 3.9 games this
- * should be zero. For version 4.0 games, it's the start of resource data
- * in the TAF file where resources are embedded.
- */
- vt_key[0].string = "ResourceOffset";
- resource_start_offset = prop_get_integer (bundle, "I<-s", vt_key);
-
- /*
- * Get the flag that indicated embedded resources. For version 3.9 games
- * this should be false. If not set, offset and length are forced to zero
- * for interface functions.
- */
- vt_key[0].string = "Globals";
- vt_key[1].string = "Embedded";
- embedded = prop_get_boolean (bundle, "B<-ss", vt_key);
-
- /*
- * Allocate a format for use with properties calls, five characters longer
- * than the partial passed in. Build a key one element larger than the
- * partial supplied, and copy over all supplied elements.
- */
- partial_length = strlen (partial_format);
- format = (sc_char *)sc_malloc (partial_length + 5);
-
- vt_full = (sc_vartype_t *)sc_malloc ((partial_length + 1) * sizeof (vt_partial[0]));
- memcpy (vt_full, vt_partial, partial_length * sizeof (vt_partial[0]));
-
- /* Search for sound resources, and offer if found. */
- if (res_has_sound (game))
- {
- const sc_char *soundfile;
- sc_int soundoffset, soundlen;
-
- /* Get soundfile property from the node supplied. */
- vt_full[partial_length].string = "SoundFile";
- strcpy (format, "S<-");
- strcat (format, partial_format);
- strcat (format, "s");
- soundfile = prop_get_string (bundle, format, vt_full);
-
- /* If a sound is defined, handle it. */
- if (!sc_strempty (soundfile))
- {
- if (embedded)
- {
- /* Retrieve offset and length. */
- vt_full[partial_length].string = "SoundOffset";
- strcpy (format, "I<-");
- strcat (format, partial_format);
- strcat (format, "s");
- soundoffset = prop_get_integer (bundle, format, vt_full)
- + resource_start_offset;
-
- vt_full[partial_length].string = "SoundLen";
- strcpy (format, "I<-");
- strcat (format, partial_format);
- strcat (format, "s");
- soundlen = prop_get_integer (bundle, format, vt_full);
- }
- else
- {
- /* Coerce offset and length to zero. */
- soundoffset = 0;
- soundlen = 0;
- }
-
- /*
- * If the sound is the special "##", latch stop, otherwise note
- * details to play on sync.
- */
- if (!strcmp (soundfile, "##"))
- {
- game->stop_sound = TRUE;
- res_clear_resource (&game->requested_sound);
- }
- else
- {
- res_set_resource (&game->requested_sound,
- soundfile, soundoffset, soundlen);
- }
- }
- }
-
- /* Now do the same thing for graphics resources. */
- if (res_has_graphics (game))
- {
- const sc_char *graphicfile;
- sc_int graphicoffset, graphiclen;
-
- /* Get graphicfile property from the node supplied. */
- vt_full[partial_length].string = "GraphicFile";
- strcpy (format, "S<-");
- strcat (format, partial_format);
- strcat (format, "s");
- graphicfile = prop_get_string (bundle, format, vt_full);
-
- /* If a graphic is defined, handle it. */
- if (!sc_strempty (graphicfile))
- {
- if (embedded)
- {
- /* Retrieve offset and length. */
- vt_full[partial_length].string = "GraphicOffset";
- strcpy (format, "I<-");
- strcat (format, partial_format);
- strcat (format, "s");
- graphicoffset = prop_get_integer (bundle, format, vt_full)
- + resource_start_offset;
-
- vt_full[partial_length].string = "GraphicLen";
- strcpy (format, "I<-");
- strcat (format, partial_format);
- strcat (format, "s");
- graphiclen = prop_get_integer (bundle, format, vt_full);
- }
- else
- {
- /* Coerce offset and length to zero. */
- graphicoffset = 0;
- graphiclen = 0;
- }
-
- /* Graphics resource retrieved, note to show on sync. */
- res_set_resource (&game->requested_graphic,
- graphicfile, graphicoffset, graphiclen);
- }
- }
-
- /* Free allocated memory. */
- sc_free (format);
- sc_free (vt_full);
+res_handle_resource(sc_gameref_t game,
+ const sc_char *partial_format,
+ const sc_vartype_t vt_partial[]) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2], *vt_full;
+ sc_int partial_length, resource_start_offset;
+ sc_bool embedded;
+ sc_char *format;
+ assert(gs_is_game_valid(game));
+ assert(partial_format && vt_partial);
+
+ /*
+ * Check for resources. If this game doesn't use any, exit now to avoid the
+ * overhead of pointless lookups and allocations.
+ */
+ if (!(res_has_sound(game) || res_has_graphics(game)))
+ return;
+
+ /*
+ * Get the global offset for all resources. For version 3.9 games this
+ * should be zero. For version 4.0 games, it's the start of resource data
+ * in the TAF file where resources are embedded.
+ */
+ vt_key[0].string = "ResourceOffset";
+ resource_start_offset = prop_get_integer(bundle, "I<-s", vt_key);
+
+ /*
+ * Get the flag that indicated embedded resources. For version 3.9 games
+ * this should be false. If not set, offset and length are forced to zero
+ * for interface functions.
+ */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Embedded";
+ embedded = prop_get_boolean(bundle, "B<-ss", vt_key);
+
+ /*
+ * Allocate a format for use with properties calls, five characters longer
+ * than the partial passed in. Build a key one element larger than the
+ * partial supplied, and copy over all supplied elements.
+ */
+ partial_length = strlen(partial_format);
+ format = (sc_char *)sc_malloc(partial_length + 5);
+
+ vt_full = (sc_vartype_t *)sc_malloc((partial_length + 1) * sizeof(vt_partial[0]));
+ memcpy(vt_full, vt_partial, partial_length * sizeof(vt_partial[0]));
+
+ /* Search for sound resources, and offer if found. */
+ if (res_has_sound(game)) {
+ const sc_char *soundfile;
+ sc_int soundoffset, soundlen;
+
+ /* Get soundfile property from the node supplied. */
+ vt_full[partial_length].string = "SoundFile";
+ strcpy(format, "S<-");
+ strcat(format, partial_format);
+ strcat(format, "s");
+ soundfile = prop_get_string(bundle, format, vt_full);
+
+ /* If a sound is defined, handle it. */
+ if (!sc_strempty(soundfile)) {
+ if (embedded) {
+ /* Retrieve offset and length. */
+ vt_full[partial_length].string = "SoundOffset";
+ strcpy(format, "I<-");
+ strcat(format, partial_format);
+ strcat(format, "s");
+ soundoffset = prop_get_integer(bundle, format, vt_full)
+ + resource_start_offset;
+
+ vt_full[partial_length].string = "SoundLen";
+ strcpy(format, "I<-");
+ strcat(format, partial_format);
+ strcat(format, "s");
+ soundlen = prop_get_integer(bundle, format, vt_full);
+ } else {
+ /* Coerce offset and length to zero. */
+ soundoffset = 0;
+ soundlen = 0;
+ }
+
+ /*
+ * If the sound is the special "##", latch stop, otherwise note
+ * details to play on sync.
+ */
+ if (!strcmp(soundfile, "##")) {
+ game->stop_sound = TRUE;
+ res_clear_resource(&game->requested_sound);
+ } else {
+ res_set_resource(&game->requested_sound,
+ soundfile, soundoffset, soundlen);
+ }
+ }
+ }
+
+ /* Now do the same thing for graphics resources. */
+ if (res_has_graphics(game)) {
+ const sc_char *graphicfile;
+ sc_int graphicoffset, graphiclen;
+
+ /* Get graphicfile property from the node supplied. */
+ vt_full[partial_length].string = "GraphicFile";
+ strcpy(format, "S<-");
+ strcat(format, partial_format);
+ strcat(format, "s");
+ graphicfile = prop_get_string(bundle, format, vt_full);
+
+ /* If a graphic is defined, handle it. */
+ if (!sc_strempty(graphicfile)) {
+ if (embedded) {
+ /* Retrieve offset and length. */
+ vt_full[partial_length].string = "GraphicOffset";
+ strcpy(format, "I<-");
+ strcat(format, partial_format);
+ strcat(format, "s");
+ graphicoffset = prop_get_integer(bundle, format, vt_full)
+ + resource_start_offset;
+
+ vt_full[partial_length].string = "GraphicLen";
+ strcpy(format, "I<-");
+ strcat(format, partial_format);
+ strcat(format, "s");
+ graphiclen = prop_get_integer(bundle, format, vt_full);
+ } else {
+ /* Coerce offset and length to zero. */
+ graphicoffset = 0;
+ graphiclen = 0;
+ }
+
+ /* Graphics resource retrieved, note to show on sync. */
+ res_set_resource(&game->requested_graphic,
+ graphicfile, graphicoffset, graphiclen);
+ }
+ }
+
+ /* Free allocated memory. */
+ sc_free(format);
+ sc_free(vt_full);
}
@@ -270,58 +251,53 @@ res_handle_resource (sc_gameref_t game,
* restore, and so on.
*/
void
-res_sync_resources (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
-
- /* Deal with any latched sound stop first. */
- if (game->stop_sound)
- {
- if (game->sound_active)
- {
- if_update_sound ("", 0, 0, FALSE);
- game->sound_active = FALSE;
-
- res_clear_resource (&game->playing_sound);
- }
- game->stop_sound = FALSE;
- }
-
- /* Look for a change of sound, and pass to interface on change. */
- if (!res_compare_resource (&game->playing_sound,
- &game->requested_sound))
- {
- const sc_char *name;
- sc_char *clean_name;
- sc_bool is_looping;
-
- /* If the sound name ends '##', this is a looping sound. */
- name = game->requested_sound.name;
- is_looping = !strcmp (name + strlen (name) - 2, "##");
-
- clean_name = (sc_char *)sc_malloc (strlen (name) + 1);
- strcpy (clean_name, name);
- if (is_looping)
- clean_name[strlen (clean_name) - 2] = NUL;
-
- if_update_sound (clean_name,
- game->requested_sound.offset,
- game->requested_sound.length, is_looping);
- game->playing_sound = game->requested_sound;
- game->sound_active = TRUE;
-
- sc_free (clean_name);
- }
-
- /* Look for a change of graphic, and pass to interface on change. */
- if (!res_compare_resource (&game->displayed_graphic,
- &game->requested_graphic))
- {
- if_update_graphic (game->requested_graphic.name,
- game->requested_graphic.offset,
- game->requested_graphic.length);
- game->displayed_graphic = game->requested_graphic;
- }
+res_sync_resources(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
+
+ /* Deal with any latched sound stop first. */
+ if (game->stop_sound) {
+ if (game->sound_active) {
+ if_update_sound("", 0, 0, FALSE);
+ game->sound_active = FALSE;
+
+ res_clear_resource(&game->playing_sound);
+ }
+ game->stop_sound = FALSE;
+ }
+
+ /* Look for a change of sound, and pass to interface on change. */
+ if (!res_compare_resource(&game->playing_sound,
+ &game->requested_sound)) {
+ const sc_char *name;
+ sc_char *clean_name;
+ sc_bool is_looping;
+
+ /* If the sound name ends '##', this is a looping sound. */
+ name = game->requested_sound.name;
+ is_looping = !strcmp(name + strlen(name) - 2, "##");
+
+ clean_name = (sc_char *)sc_malloc(strlen(name) + 1);
+ strcpy(clean_name, name);
+ if (is_looping)
+ clean_name[strlen(clean_name) - 2] = NUL;
+
+ if_update_sound(clean_name,
+ game->requested_sound.offset,
+ game->requested_sound.length, is_looping);
+ game->playing_sound = game->requested_sound;
+ game->sound_active = TRUE;
+
+ sc_free(clean_name);
+ }
+
+ /* Look for a change of graphic, and pass to interface on change. */
+ if (!res_compare_resource(&game->displayed_graphic,
+ &game->requested_graphic)) {
+ if_update_graphic(game->requested_graphic.name,
+ game->requested_graphic.offset,
+ game->requested_graphic.length);
+ game->displayed_graphic = game->requested_graphic;
+ }
}
@@ -332,17 +308,16 @@ res_sync_resources (sc_gameref_t game)
* use to match. Called on game restart or restore.
*/
void
-res_cancel_resources (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
+res_cancel_resources(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
- /* Request that everything stops and clears. */
- game->stop_sound = FALSE;
- res_clear_resource (&game->requested_sound);
- res_clear_resource (&game->requested_graphic);
+ /* Request that everything stops and clears. */
+ game->stop_sound = FALSE;
+ res_clear_resource(&game->requested_sound);
+ res_clear_resource(&game->requested_graphic);
- /* Synchronize to have the above take effect. */
- res_sync_resources (game);
+ /* Synchronize to have the above take effect. */
+ res_sync_resources(game);
}
} // End of namespace Adrift
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
diff --git a/engines/glk/adrift/scrunner.cpp b/engines/glk/adrift/scrunner.cpp
index ab6bfd8305..9e979d1193 100644
--- a/engines/glk/adrift/scrunner.cpp
+++ b/engines/glk/adrift/scrunner.cpp
@@ -45,396 +45,427 @@ static const sc_char *const SEPARATORS = ".,";
* and handled.
*/
static sc_bool
-run_is_task_function (const sc_char *pattern, sc_gameref_t game)
-{
- 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 room, object;
- sc_char *argument;
-
- /* Simple comparison against the one known task expression. */
- argument = (sc_char *)sc_malloc (strlen (pattern) + 1);
- if (sscanf (pattern, " # %%object%% = getdynfromroom (%[^)])", argument) == 0)
- {
- sc_free (argument);
- return FALSE;
- }
-
- /*
- * Compare the argument read in against known room names.
- *
- * TODO Is this simple room name comparison good enough?
- */
- vt_key[0].string = "Rooms";
- for (room = 0; room < gs_room_count (game); room++)
- {
- const sc_char *name;
-
- vt_key[1].integer = room;
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- if (sc_strcasecmp (name, argument) == 0)
- break;
- }
- sc_free (argument);
- if (room == gs_room_count (game))
- return FALSE;
-
- /*
- * Select a dynamic object from the room.
- *
- * TODO What are the selection criteria supposed to be? Here we use "on
- * the floor".
- */
- vt_key[0].string = "Objects";
- for (object = 0; object < gs_object_count (game); object++)
- {
- sc_bool bstatic;
-
- vt_key[1].integer = object;
- vt_key[2].string = "Static";
- bstatic = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (!bstatic && obj_directly_in_room (game, object, room))
- break;
- }
- if (object == gs_object_count (game))
- return FALSE;
-
- /* Set this object reference, unambiguously, as if %object% match. */
- gs_clear_object_references (game);
- game->object_references[object] = TRUE;
- var_set_ref_object (vars, object);
-
- return TRUE;
+run_is_task_function(const sc_char *pattern, sc_gameref_t game) {
+ 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 room, object;
+ sc_char *argument;
+
+ /* Simple comparison against the one known task expression. */
+ argument = (sc_char *)sc_malloc(strlen(pattern) + 1);
+ if (sscanf(pattern, " # %%object%% = getdynfromroom (%[^)])", argument) == 0) {
+ sc_free(argument);
+ return FALSE;
+ }
+
+ /*
+ * Compare the argument read in against known room names.
+ *
+ * TODO Is this simple room name comparison good enough?
+ */
+ vt_key[0].string = "Rooms";
+ for (room = 0; room < gs_room_count(game); room++) {
+ const sc_char *name;
+
+ vt_key[1].integer = room;
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ if (sc_strcasecmp(name, argument) == 0)
+ break;
+ }
+ sc_free(argument);
+ if (room == gs_room_count(game))
+ return FALSE;
+
+ /*
+ * Select a dynamic object from the room.
+ *
+ * TODO What are the selection criteria supposed to be? Here we use "on
+ * the floor".
+ */
+ vt_key[0].string = "Objects";
+ for (object = 0; object < gs_object_count(game); object++) {
+ sc_bool bstatic;
+
+ vt_key[1].integer = object;
+ vt_key[2].string = "Static";
+ bstatic = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (!bstatic && obj_directly_in_room(game, object, room))
+ break;
+ }
+ if (object == gs_object_count(game))
+ return FALSE;
+
+ /* Set this object reference, unambiguously, as if %object% match. */
+ gs_clear_object_references(game);
+ game->object_references[object] = TRUE;
+ var_set_ref_object(vars, object);
+
+ return TRUE;
}
/* Structure used to associate a pattern with a handler function. */
-typedef struct sc_commands_s
-{
- const sc_char *const command;
- sc_bool (*const handler) (sc_gameref_t game);
+typedef struct sc_commands_s {
+ const sc_char *const command;
+ sc_bool(*const handler)(sc_gameref_t game);
} sc_commands_t;
typedef sc_commands_t *sc_commandsref_t;
/* Movement commands for the four point compass. */
static sc_commands_t MOVE_COMMANDS_4[] = {
- {"{go {to {the}}} [north/n]", lib_cmd_go_north},
- {"{go {to {the}}} [east/e]", lib_cmd_go_east},
- {"{go {to {the}}} [south/s]", lib_cmd_go_south},
- {"{go {to {the}}} [west/w]", lib_cmd_go_west},
- {"{go {to {the}}} [up/u]", lib_cmd_go_up},
- {"{go {to {the}}} [down/d]", lib_cmd_go_down},
- {"{go {to {the}}} [in]", lib_cmd_go_in},
- {"{go {to {the}}} [out/o]", lib_cmd_go_out},
- {NULL, NULL}
+ {"{go {to {the}}} [north/n]", lib_cmd_go_north},
+ {"{go {to {the}}} [east/e]", lib_cmd_go_east},
+ {"{go {to {the}}} [south/s]", lib_cmd_go_south},
+ {"{go {to {the}}} [west/w]", lib_cmd_go_west},
+ {"{go {to {the}}} [up/u]", lib_cmd_go_up},
+ {"{go {to {the}}} [down/d]", lib_cmd_go_down},
+ {"{go {to {the}}} [in]", lib_cmd_go_in},
+ {"{go {to {the}}} [out/o]", lib_cmd_go_out},
+ {NULL, NULL}
};
/* Movement commands for the eight point compass. */
static sc_commands_t MOVE_COMMANDS_8[] = {
- {"{go {to {the}}} [north/n]", lib_cmd_go_north},
- {"{go {to {the}}} [east/e]", lib_cmd_go_east},
- {"{go {to {the}}} [south/s]", lib_cmd_go_south},
- {"{go {to {the}}} [west/w]", lib_cmd_go_west},
- {"{go {to {the}}} [up/u]", lib_cmd_go_up},
- {"{go {to {the}}} [down/d]", lib_cmd_go_down},
- {"{go {to {the}}} [in]", lib_cmd_go_in},
- {"{go {to {the}}} [out/o]", lib_cmd_go_out},
- {"{go {to {the}}} [northeast/north-east/ne]", lib_cmd_go_northeast},
- {"{go {to {the}}} [southeast/south-east/se]", lib_cmd_go_southeast},
- {"{go {to {the}}} [northwest/north-west/nw]", lib_cmd_go_northwest},
- {"{go {to {the}}} [southwest/south-west/sw]", lib_cmd_go_southwest},
- {NULL, NULL}
+ {"{go {to {the}}} [north/n]", lib_cmd_go_north},
+ {"{go {to {the}}} [east/e]", lib_cmd_go_east},
+ {"{go {to {the}}} [south/s]", lib_cmd_go_south},
+ {"{go {to {the}}} [west/w]", lib_cmd_go_west},
+ {"{go {to {the}}} [up/u]", lib_cmd_go_up},
+ {"{go {to {the}}} [down/d]", lib_cmd_go_down},
+ {"{go {to {the}}} [in]", lib_cmd_go_in},
+ {"{go {to {the}}} [out/o]", lib_cmd_go_out},
+ {"{go {to {the}}} [northeast/north-east/ne]", lib_cmd_go_northeast},
+ {"{go {to {the}}} [southeast/south-east/se]", lib_cmd_go_southeast},
+ {"{go {to {the}}} [northwest/north-west/nw]", lib_cmd_go_northwest},
+ {"{go {to {the}}} [southwest/south-west/sw]", lib_cmd_go_southwest},
+ {NULL, NULL}
};
/* "Priority" library commands, may take precedence over the game. */
static sc_commands_t PRIORITY_COMMANDS[] = {
- /* Acquisition of and disposal of inventory. */
- {"[[get/take/remove/extract] [all/everything] from/empty] %object%",
- lib_cmd_take_all_from},
- {"[[get/take/remove/extract] [all/everything] from/empty] %object%"
- " [[except/but] {for}/apart from] %text%",
- lib_cmd_take_from_except_multiple},
- {"[get/take/remove/extract] [all/everything]"
- " [[except/but] {for}/apart from] %text% from %object%",
- lib_cmd_take_from_except_multiple},
- {"[get/take/remove/extract] %text% from %object%",
- lib_cmd_take_from_multiple},
- {"[get/take] [all/everything] from %character%", lib_cmd_take_all_from_npc},
- {"[get/take] [all/everything] from %character%"
- " [[except/but] {for}/apart from] %text%",
- lib_cmd_take_from_npc_except_multiple},
- {"[get/take] [all/everything]"
- " [[except/but] {for}/apart from] %text% from %character%",
- lib_cmd_take_from_npc_except_multiple},
- {"[get/take] %text% from %character%", lib_cmd_take_from_npc_multiple},
- {"[[get/take/pick up] [all/everything]/pick [all/everything] up]",
- lib_cmd_take_all},
- {"[get/take/pick up] [all/everything] [[except/but] {for}/apart from] %text%",
- lib_cmd_take_except_multiple},
- {"[get/take/pick up] %text%", lib_cmd_take_multiple},
- {"pick %text% up", lib_cmd_take_multiple},
- {"[[drop/put down] [all/everything]/put [all/everything] down]",
- lib_cmd_drop_all},
- {"[drop/put down] [all/everything] [[except/but] {for}/apart from] %text%",
- lib_cmd_drop_except_multiple},
- {"[drop/put down] %text%", lib_cmd_drop_multiple},
- {"put %text% down", lib_cmd_drop_multiple},
- {NULL, NULL}
+ /* Acquisition of and disposal of inventory. */
+ {
+ "[[get/take/remove/extract] [all/everything] from/empty] %object%",
+ lib_cmd_take_all_from
+ },
+ {
+ "[[get/take/remove/extract] [all/everything] from/empty] %object%"
+ " [[except/but] {for}/apart from] %text%",
+ lib_cmd_take_from_except_multiple
+ },
+ {
+ "[get/take/remove/extract] [all/everything]"
+ " [[except/but] {for}/apart from] %text% from %object%",
+ lib_cmd_take_from_except_multiple
+ },
+ {
+ "[get/take/remove/extract] %text% from %object%",
+ lib_cmd_take_from_multiple
+ },
+ {"[get/take] [all/everything] from %character%", lib_cmd_take_all_from_npc},
+ {
+ "[get/take] [all/everything] from %character%"
+ " [[except/but] {for}/apart from] %text%",
+ lib_cmd_take_from_npc_except_multiple
+ },
+ {
+ "[get/take] [all/everything]"
+ " [[except/but] {for}/apart from] %text% from %character%",
+ lib_cmd_take_from_npc_except_multiple
+ },
+ {"[get/take] %text% from %character%", lib_cmd_take_from_npc_multiple},
+ {
+ "[[get/take/pick up] [all/everything]/pick [all/everything] up]",
+ lib_cmd_take_all
+ },
+ {
+ "[get/take/pick up] [all/everything] [[except/but] {for}/apart from] %text%",
+ lib_cmd_take_except_multiple
+ },
+ {"[get/take/pick up] %text%", lib_cmd_take_multiple},
+ {"pick %text% up", lib_cmd_take_multiple},
+ {
+ "[[drop/put down] [all/everything]/put [all/everything] down]",
+ lib_cmd_drop_all
+ },
+ {
+ "[drop/put down] [all/everything] [[except/but] {for}/apart from] %text%",
+ lib_cmd_drop_except_multiple
+ },
+ {"[drop/put down] %text%", lib_cmd_drop_multiple},
+ {"put %text% down", lib_cmd_drop_multiple},
+ {NULL, NULL}
};
/* Standard library commands, other than movement and priority above. */
static sc_commands_t STANDARD_COMMANDS[] = {
- /* Inventory, and general investigation of surroundings. */
- {"[inventory/inv/i]", lib_cmd_inventory},
- {"[x/ex/exam/examine/l/look {at}] {{the} [room/location]}", lib_cmd_look},
- {"[x/ex/exam/examine/look {at/in}] %object%", lib_cmd_examine_object},
- {"[x/ex/exam/examine/look {at}] %character%", lib_cmd_examine_npc},
- {"[x/ex/exam/examine/look {at}] [me/self/myself]", lib_cmd_examine_self},
- {"[x/ex/exam/examine/look {at}] all", lib_cmd_examine_all},
-
- /* Attempted acquisition of and disposal of NPCs. */
- {"[get/take/pick up] %character%", lib_cmd_take_npc},
- {"pick %character% up", lib_cmd_take_npc},
-
- /* Manipulating selected objects. */
- {"put [all/everything] [in/into/inside {of}] %object%", lib_cmd_put_all_in},
- {"put [all/everything] [[except/but] {for}/apart from] %text%"
- " [in/into/inside {of}] %object%", lib_cmd_put_in_except_multiple},
- {"put %text% [in/into/inside {of}] %object%", lib_cmd_put_in_multiple},
- {"put [all/everything] [on/onto/on top of] %object%", lib_cmd_put_all_on},
- {"put [all/everything] [[except/but] {for}/apart from] %text%"
- " [on/onto/on top of] %object%", lib_cmd_put_on_except_multiple},
- {"put %text% [on/onto/on top of] %object%", lib_cmd_put_on_multiple},
- {"open %object%", lib_cmd_open_object},
- {"close %object%", lib_cmd_close_object},
- {"unlock %object% with %text%", lib_cmd_unlock_object_with},
- {"lock %object% with %text%", lib_cmd_lock_object_with},
- {"unlock %object%", lib_cmd_unlock_object},
- {"lock %object%", lib_cmd_lock_object},
- {"read %object%", lib_cmd_read_object},
- {"read *", lib_cmd_read_other},
- {"give %object% to %character%", lib_cmd_give_object_npc},
- {"sit {down/up} [on/in] %object%", lib_cmd_sit_on_object},
- {"stand {up/down} [on/in] %object%", lib_cmd_stand_on_object},
- {"[lie/lay] on %object%", lib_cmd_lie_on_object},
- {"get {down/up} off %object%", lib_cmd_get_off_object},
- {"get off", lib_cmd_get_off},
- {"sit {down/up} {[on/in] {the} [ground/floor]}", lib_cmd_sit_on_floor},
- {"stand {up/down} {[on/in] {the} [ground/floor]}", lib_cmd_stand_on_floor},
- {"[lie/lay] {down/up} {[on/in] {the} [ground/floor]}", lib_cmd_lie_on_floor},
- {"eat %object%", lib_cmd_eat_object},
-
- /* Dressing up, and dressing down. */
- {"[[wear/put on/don] [all/everything]/put [all/everything] on]",
- lib_cmd_wear_all},
- {"[wear/put on/don] [all/everything] [[except/but] {for}/apart from] %text%",
- lib_cmd_wear_except_multiple},
- {"[wear/put on/don] %text%", lib_cmd_wear_multiple},
- {"put %text% on", lib_cmd_wear_multiple},
- {"[[remove/take off/doff] [all/everything]/take [all/everything] off/strip]",
- lib_cmd_remove_all},
- {"[remove/take off/doff] [all/everything]"
- " [[except/but] {for}/apart from] %text%",
- lib_cmd_remove_except_multiple},
- {"[remove/take off/doff] %text%", lib_cmd_remove_multiple},
- {"take %text% off", lib_cmd_remove_multiple},
-
- /* Selected NPC interactions and conversation. */
- {"ask %character% about %text%", lib_cmd_ask_npc_about},
- {"[attack/hit/kick/slap/shoot/stab] %character% with %object%",
- lib_cmd_attack_npc_with},
- {"[attack/shoot] %character%", lib_cmd_attack_npc},
-
- /* More movement, waiting, and miscellaneous administrative commands. */
- {"[goto/go {to}] %text%", lib_cmd_go_room},
- {"[goto/go {to}] *", lib_cmd_print_room_exits},
- {"[exit/exits/directions/where]", lib_cmd_print_room_exits},
- {"[wait/z] %number%", lib_cmd_wait_number},
- {"[wait/z]", lib_cmd_wait},
- {"save", lib_cmd_save},
- {"[restore/load]", lib_cmd_restore},
- {"restart", lib_cmd_restart},
- {"[again/g]", lib_cmd_again},
- {"[redo /!]%number%", lib_cmd_redo_number},
- {"[redo /!]%text%", lib_cmd_redo_text},
- {"[redo/!]", lib_cmd_redo_last},
- {"[quit/q]", lib_cmd_quit},
- {"turns", lib_cmd_turns},
- {"score", lib_cmd_score},
- {"undo", lib_cmd_undo},
- {"[hist/history] %number%", lib_cmd_history_number},
- {"[hist/history]", lib_cmd_history},
- {"[hint/hints]", lib_cmd_hints},
- {"verbose", lib_cmd_verbose},
- {"brief", lib_cmd_brief},
- {"[notify/notification] %text%", lib_cmd_notify_on_off},
- {"[notify/notification]", lib_cmd_notify},
- {"time", lib_cmd_time},
- {"date", lib_cmd_date},
- {"[help/commands]", lib_cmd_help},
- {"[gpl/license]", lib_cmd_license},
- {"[about/info/information/author]", lib_cmd_information},
- {"[clear/cls/clr]", lib_cmd_clear},
- {"status{line}", lib_cmd_statusline},
- {"version", lib_cmd_version},
-
- {"[locate/where {is/are}/find] %object%", lib_cmd_locate_object},
- {"[locate/where {is}/find] %character%", lib_cmd_locate_npc},
-
- {"[count/num]", lib_cmd_count},
-
- /* Standard response commands; no real action, just output. */
- {"[get/take/pick up] *", lib_cmd_get_what},
- {"open *", lib_cmd_open_what},
- {"close *", lib_cmd_close_other},
- {"give %object% *", lib_cmd_give_object},
- {"give *", lib_cmd_give_what},
- {"lock %text%", lib_cmd_lock_other},
- {"lock", lib_cmd_lock_what},
- {"unlock %text%", lib_cmd_unlock_other},
- {"unlock", lib_cmd_unlock_what},
- {"sit {down/up} [on/in] *", lib_cmd_sit_other},
- {"stand {up/down} [on/in] *", lib_cmd_stand_other},
- {"[lie/lay] {down/up} [on/in] *", lib_cmd_lie_other},
- {"[remove/take off/doff] *", lib_cmd_remove_what},
- {"[drop/put down] *", lib_cmd_drop_what},
- {"[wear/put on/don] *", lib_cmd_wear_what},
- {"[shit/fuck/bastard/cunt/crap/hell/shag/bollocks/bollox/bugger] *",
- lib_cmd_profanity},
- {"[x/examine/look {at}] *", lib_cmd_examine_other},
- {"[locate/where {is/are}/find] *", lib_cmd_locate_other},
- {"[cp/mv/ln/ls] *", lib_cmd_unix_like},
- {"dir *", lib_cmd_dos_like},
- {"ask %character% *", lib_cmd_ask_npc},
- {"ask %object% *", lib_cmd_ask_object},
- {"ask *", lib_cmd_ask_other},
- {"block %object% *", lib_cmd_block_object},
- {"block %text%", lib_cmd_block_other},
- {"block", lib_cmd_block_what},
- {"[break/destroy/smash] %object% *", lib_cmd_break_object},
- {"[break/destroy/smash] %text%", lib_cmd_break_other},
- {"break", lib_cmd_break_what},
- {"destroy", lib_cmd_destroy_what},
- {"smash", lib_cmd_smash_what},
- {"buy %object% *", lib_cmd_buy_object},
- {"buy %text%", lib_cmd_buy_other},
- {"buy", lib_cmd_buy_what},
- {"clean %object% *", lib_cmd_clean_object},
- {"clean %text%", lib_cmd_clean_other},
- {"clean", lib_cmd_clean_what},
- {"climb %object% *", lib_cmd_climb_object},
- {"climb %text%", lib_cmd_climb_other},
- {"climb", lib_cmd_climb_what},
- {"cry *", lib_cmd_cry},
- {"cut %object% *", lib_cmd_cut_object},
- {"cut %text%", lib_cmd_cut_other},
- {"cut", lib_cmd_cut_what},
- {"dance *", lib_cmd_dance},
- {"drink %object% *", lib_cmd_drink_object},
- {"drink %text%", lib_cmd_drink_other},
- {"drink", lib_cmd_drink_what},
- {"eat *", lib_cmd_eat_other},
- {"feed *", lib_cmd_feed},
- {"feel *", lib_cmd_feel},
- {"fight *", lib_cmd_fight},
- {"fix %object% *", lib_cmd_fix_object},
- {"fix %text%", lib_cmd_fix_other},
- {"fix", lib_cmd_fix_what},
- {"fly *", lib_cmd_fly},
- {"hint *", lib_cmd_hint},
- {"hit %character%", lib_cmd_attack_npc},
- {"hit %object% *", lib_cmd_hit_object},
- {"hit %text%", lib_cmd_hit_other},
- {"hit", lib_cmd_hit_what},
- {"hum *", lib_cmd_hum},
- {"jump *", lib_cmd_jump},
- {"kick %character%", lib_cmd_attack_npc},
- {"kick %object% *", lib_cmd_kick_object},
- {"kick %text%", lib_cmd_kick_other},
- {"kick", lib_cmd_kick_what},
- {"kiss %character% *", lib_cmd_kiss_npc},
- {"kiss %object% *", lib_cmd_kiss_object},
- {"kiss *", lib_cmd_kiss_other},
- {"kill *", lib_cmd_kill_other},
- {"lift %object% *", lib_cmd_lift_object},
- {"lift %text%", lib_cmd_lift_other},
- {"lift", lib_cmd_lift_what},
- {"light %object% *", lib_cmd_light_object},
- {"light %text%", lib_cmd_light_other},
- {"light", lib_cmd_light_what},
- {"listen *", lib_cmd_listen},
- {"mend %object% *", lib_cmd_mend_object},
- {"mend %text%", lib_cmd_mend_other},
- {"mend", lib_cmd_mend_what},
- {"move %object% *", lib_cmd_move_object},
- {"move %text%", lib_cmd_move_other},
- {"move", lib_cmd_move_what},
- {"please *", lib_cmd_please},
- {"press %object% *", lib_cmd_press_object},
- {"press %text%", lib_cmd_press_other},
- {"press", lib_cmd_press_what},
- {"pull %object% *", lib_cmd_pull_object},
- {"pull %text%", lib_cmd_pull_other},
- {"pull", lib_cmd_pull_what},
- {"punch *", lib_cmd_punch},
- {"push %object% *", lib_cmd_push_object},
- {"push %text%", lib_cmd_push_other},
- {"push", lib_cmd_push_what},
- {"repair %object% *", lib_cmd_repair_object},
- {"repair %text%", lib_cmd_repair_other},
- {"repair", lib_cmd_repair_what},
- {"rub %object% *", lib_cmd_rub_object},
- {"rub %text%", lib_cmd_rub_other},
- {"rub", lib_cmd_rub_what},
- {"run *", lib_cmd_run},
- {"say *", lib_cmd_say},
- {"sell %object% *", lib_cmd_sell_object},
- {"sell %text%", lib_cmd_sell_other},
- {"sell", lib_cmd_sell_what},
- {"shake %object% *", lib_cmd_shake_object},
- {"shake %text%", lib_cmd_shake_other},
- {"shake", lib_cmd_shake_what},
- {"shout *", lib_cmd_shout},
- {"sing *", lib_cmd_sing},
- {"sleep *", lib_cmd_sleep},
- {"smell %object% *", lib_cmd_smell_object},
- {"smell *", lib_cmd_smell_other},
- {"stop %object% *", lib_cmd_stop_object},
- {"stop %text%", lib_cmd_stop_other},
- {"stop", lib_cmd_stop_what},
- {"suck %object% *", lib_cmd_suck_object},
- {"suck %text%", lib_cmd_suck_other},
- {"suck", lib_cmd_suck_what},
- {"talk *", lib_cmd_talk},
- {"thank *", lib_cmd_thank},
- {"turn %object% *", lib_cmd_turn_object},
- {"turn %text%", lib_cmd_turn_other},
- {"turn", lib_cmd_turn_what},
- {"touch %object% *", lib_cmd_touch_object},
- {"touch %text%", lib_cmd_touch_other},
- {"touch", lib_cmd_touch_what},
- {"unblock %object% *", lib_cmd_unblock_object},
- {"unblock %text%", lib_cmd_unblock_other},
- {"unblock", lib_cmd_unblock_what},
- {"wash %object% *", lib_cmd_wash_object},
- {"wash %text%", lib_cmd_wash_other},
- {"wash", lib_cmd_wash_what},
- {"whistle *", lib_cmd_whistle},
- {"[why/when/what/can/how] *", lib_cmd_interrogation},
- {"xyzzy *", lib_cmd_xyzzy},
- {"campbell", lib_cmd_egotistic},
- {"[yes/no] *", lib_cmd_yes_or_no},
- {"* %object% *", lib_cmd_verb_object},
- {"* %character% *", lib_cmd_verb_npc},
-
- /* SCARE debugger hook command, placed last just in case... */
- {"{#}debug{ger}", debug_cmd_debugger},
-
- {NULL, NULL}
+ /* Inventory, and general investigation of surroundings. */
+ {"[inventory/inv/i]", lib_cmd_inventory},
+ {"[x/ex/exam/examine/l/look {at}] {{the} [room/location]}", lib_cmd_look},
+ {"[x/ex/exam/examine/look {at/in}] %object%", lib_cmd_examine_object},
+ {"[x/ex/exam/examine/look {at}] %character%", lib_cmd_examine_npc},
+ {"[x/ex/exam/examine/look {at}] [me/self/myself]", lib_cmd_examine_self},
+ {"[x/ex/exam/examine/look {at}] all", lib_cmd_examine_all},
+
+ /* Attempted acquisition of and disposal of NPCs. */
+ {"[get/take/pick up] %character%", lib_cmd_take_npc},
+ {"pick %character% up", lib_cmd_take_npc},
+
+ /* Manipulating selected objects. */
+ {"put [all/everything] [in/into/inside {of}] %object%", lib_cmd_put_all_in},
+ {
+ "put [all/everything] [[except/but] {for}/apart from] %text%"
+ " [in/into/inside {of}] %object%", lib_cmd_put_in_except_multiple
+ },
+ {"put %text% [in/into/inside {of}] %object%", lib_cmd_put_in_multiple},
+ {"put [all/everything] [on/onto/on top of] %object%", lib_cmd_put_all_on},
+ {
+ "put [all/everything] [[except/but] {for}/apart from] %text%"
+ " [on/onto/on top of] %object%", lib_cmd_put_on_except_multiple
+ },
+ {"put %text% [on/onto/on top of] %object%", lib_cmd_put_on_multiple},
+ {"open %object%", lib_cmd_open_object},
+ {"close %object%", lib_cmd_close_object},
+ {"unlock %object% with %text%", lib_cmd_unlock_object_with},
+ {"lock %object% with %text%", lib_cmd_lock_object_with},
+ {"unlock %object%", lib_cmd_unlock_object},
+ {"lock %object%", lib_cmd_lock_object},
+ {"read %object%", lib_cmd_read_object},
+ {"read *", lib_cmd_read_other},
+ {"give %object% to %character%", lib_cmd_give_object_npc},
+ {"sit {down/up} [on/in] %object%", lib_cmd_sit_on_object},
+ {"stand {up/down} [on/in] %object%", lib_cmd_stand_on_object},
+ {"[lie/lay] on %object%", lib_cmd_lie_on_object},
+ {"get {down/up} off %object%", lib_cmd_get_off_object},
+ {"get off", lib_cmd_get_off},
+ {"sit {down/up} {[on/in] {the} [ground/floor]}", lib_cmd_sit_on_floor},
+ {"stand {up/down} {[on/in] {the} [ground/floor]}", lib_cmd_stand_on_floor},
+ {"[lie/lay] {down/up} {[on/in] {the} [ground/floor]}", lib_cmd_lie_on_floor},
+ {"eat %object%", lib_cmd_eat_object},
+
+ /* Dressing up, and dressing down. */
+ {
+ "[[wear/put on/don] [all/everything]/put [all/everything] on]",
+ lib_cmd_wear_all
+ },
+ {
+ "[wear/put on/don] [all/everything] [[except/but] {for}/apart from] %text%",
+ lib_cmd_wear_except_multiple
+ },
+ {"[wear/put on/don] %text%", lib_cmd_wear_multiple},
+ {"put %text% on", lib_cmd_wear_multiple},
+ {
+ "[[remove/take off/doff] [all/everything]/take [all/everything] off/strip]",
+ lib_cmd_remove_all
+ },
+ {
+ "[remove/take off/doff] [all/everything]"
+ " [[except/but] {for}/apart from] %text%",
+ lib_cmd_remove_except_multiple
+ },
+ {"[remove/take off/doff] %text%", lib_cmd_remove_multiple},
+ {"take %text% off", lib_cmd_remove_multiple},
+
+ /* Selected NPC interactions and conversation. */
+ {"ask %character% about %text%", lib_cmd_ask_npc_about},
+ {
+ "[attack/hit/kick/slap/shoot/stab] %character% with %object%",
+ lib_cmd_attack_npc_with
+ },
+ {"[attack/shoot] %character%", lib_cmd_attack_npc},
+
+ /* More movement, waiting, and miscellaneous administrative commands. */
+ {"[goto/go {to}] %text%", lib_cmd_go_room},
+ {"[goto/go {to}] *", lib_cmd_print_room_exits},
+ {"[exit/exits/directions/where]", lib_cmd_print_room_exits},
+ {"[wait/z] %number%", lib_cmd_wait_number},
+ {"[wait/z]", lib_cmd_wait},
+ {"save", lib_cmd_save},
+ {"[restore/load]", lib_cmd_restore},
+ {"restart", lib_cmd_restart},
+ {"[again/g]", lib_cmd_again},
+ {"[redo /!]%number%", lib_cmd_redo_number},
+ {"[redo /!]%text%", lib_cmd_redo_text},
+ {"[redo/!]", lib_cmd_redo_last},
+ {"[quit/q]", lib_cmd_quit},
+ {"turns", lib_cmd_turns},
+ {"score", lib_cmd_score},
+ {"undo", lib_cmd_undo},
+ {"[hist/history] %number%", lib_cmd_history_number},
+ {"[hist/history]", lib_cmd_history},
+ {"[hint/hints]", lib_cmd_hints},
+ {"verbose", lib_cmd_verbose},
+ {"brief", lib_cmd_brief},
+ {"[notify/notification] %text%", lib_cmd_notify_on_off},
+ {"[notify/notification]", lib_cmd_notify},
+ {"time", lib_cmd_time},
+ {"date", lib_cmd_date},
+ {"[help/commands]", lib_cmd_help},
+ {"[gpl/license]", lib_cmd_license},
+ {"[about/info/information/author]", lib_cmd_information},
+ {"[clear/cls/clr]", lib_cmd_clear},
+ {"status{line}", lib_cmd_statusline},
+ {"version", lib_cmd_version},
+
+ {"[locate/where {is/are}/find] %object%", lib_cmd_locate_object},
+ {"[locate/where {is}/find] %character%", lib_cmd_locate_npc},
+
+ {"[count/num]", lib_cmd_count},
+
+ /* Standard response commands; no real action, just output. */
+ {"[get/take/pick up] *", lib_cmd_get_what},
+ {"open *", lib_cmd_open_what},
+ {"close *", lib_cmd_close_other},
+ {"give %object% *", lib_cmd_give_object},
+ {"give *", lib_cmd_give_what},
+ {"lock %text%", lib_cmd_lock_other},
+ {"lock", lib_cmd_lock_what},
+ {"unlock %text%", lib_cmd_unlock_other},
+ {"unlock", lib_cmd_unlock_what},
+ {"sit {down/up} [on/in] *", lib_cmd_sit_other},
+ {"stand {up/down} [on/in] *", lib_cmd_stand_other},
+ {"[lie/lay] {down/up} [on/in] *", lib_cmd_lie_other},
+ {"[remove/take off/doff] *", lib_cmd_remove_what},
+ {"[drop/put down] *", lib_cmd_drop_what},
+ {"[wear/put on/don] *", lib_cmd_wear_what},
+ {
+ "[shit/fuck/bastard/cunt/crap/hell/shag/bollocks/bollox/bugger] *",
+ lib_cmd_profanity
+ },
+ {"[x/examine/look {at}] *", lib_cmd_examine_other},
+ {"[locate/where {is/are}/find] *", lib_cmd_locate_other},
+ {"[cp/mv/ln/ls] *", lib_cmd_unix_like},
+ {"dir *", lib_cmd_dos_like},
+ {"ask %character% *", lib_cmd_ask_npc},
+ {"ask %object% *", lib_cmd_ask_object},
+ {"ask *", lib_cmd_ask_other},
+ {"block %object% *", lib_cmd_block_object},
+ {"block %text%", lib_cmd_block_other},
+ {"block", lib_cmd_block_what},
+ {"[break/destroy/smash] %object% *", lib_cmd_break_object},
+ {"[break/destroy/smash] %text%", lib_cmd_break_other},
+ {"break", lib_cmd_break_what},
+ {"destroy", lib_cmd_destroy_what},
+ {"smash", lib_cmd_smash_what},
+ {"buy %object% *", lib_cmd_buy_object},
+ {"buy %text%", lib_cmd_buy_other},
+ {"buy", lib_cmd_buy_what},
+ {"clean %object% *", lib_cmd_clean_object},
+ {"clean %text%", lib_cmd_clean_other},
+ {"clean", lib_cmd_clean_what},
+ {"climb %object% *", lib_cmd_climb_object},
+ {"climb %text%", lib_cmd_climb_other},
+ {"climb", lib_cmd_climb_what},
+ {"cry *", lib_cmd_cry},
+ {"cut %object% *", lib_cmd_cut_object},
+ {"cut %text%", lib_cmd_cut_other},
+ {"cut", lib_cmd_cut_what},
+ {"dance *", lib_cmd_dance},
+ {"drink %object% *", lib_cmd_drink_object},
+ {"drink %text%", lib_cmd_drink_other},
+ {"drink", lib_cmd_drink_what},
+ {"eat *", lib_cmd_eat_other},
+ {"feed *", lib_cmd_feed},
+ {"feel *", lib_cmd_feel},
+ {"fight *", lib_cmd_fight},
+ {"fix %object% *", lib_cmd_fix_object},
+ {"fix %text%", lib_cmd_fix_other},
+ {"fix", lib_cmd_fix_what},
+ {"fly *", lib_cmd_fly},
+ {"hint *", lib_cmd_hint},
+ {"hit %character%", lib_cmd_attack_npc},
+ {"hit %object% *", lib_cmd_hit_object},
+ {"hit %text%", lib_cmd_hit_other},
+ {"hit", lib_cmd_hit_what},
+ {"hum *", lib_cmd_hum},
+ {"jump *", lib_cmd_jump},
+ {"kick %character%", lib_cmd_attack_npc},
+ {"kick %object% *", lib_cmd_kick_object},
+ {"kick %text%", lib_cmd_kick_other},
+ {"kick", lib_cmd_kick_what},
+ {"kiss %character% *", lib_cmd_kiss_npc},
+ {"kiss %object% *", lib_cmd_kiss_object},
+ {"kiss *", lib_cmd_kiss_other},
+ {"kill *", lib_cmd_kill_other},
+ {"lift %object% *", lib_cmd_lift_object},
+ {"lift %text%", lib_cmd_lift_other},
+ {"lift", lib_cmd_lift_what},
+ {"light %object% *", lib_cmd_light_object},
+ {"light %text%", lib_cmd_light_other},
+ {"light", lib_cmd_light_what},
+ {"listen *", lib_cmd_listen},
+ {"mend %object% *", lib_cmd_mend_object},
+ {"mend %text%", lib_cmd_mend_other},
+ {"mend", lib_cmd_mend_what},
+ {"move %object% *", lib_cmd_move_object},
+ {"move %text%", lib_cmd_move_other},
+ {"move", lib_cmd_move_what},
+ {"please *", lib_cmd_please},
+ {"press %object% *", lib_cmd_press_object},
+ {"press %text%", lib_cmd_press_other},
+ {"press", lib_cmd_press_what},
+ {"pull %object% *", lib_cmd_pull_object},
+ {"pull %text%", lib_cmd_pull_other},
+ {"pull", lib_cmd_pull_what},
+ {"punch *", lib_cmd_punch},
+ {"push %object% *", lib_cmd_push_object},
+ {"push %text%", lib_cmd_push_other},
+ {"push", lib_cmd_push_what},
+ {"repair %object% *", lib_cmd_repair_object},
+ {"repair %text%", lib_cmd_repair_other},
+ {"repair", lib_cmd_repair_what},
+ {"rub %object% *", lib_cmd_rub_object},
+ {"rub %text%", lib_cmd_rub_other},
+ {"rub", lib_cmd_rub_what},
+ {"run *", lib_cmd_run},
+ {"say *", lib_cmd_say},
+ {"sell %object% *", lib_cmd_sell_object},
+ {"sell %text%", lib_cmd_sell_other},
+ {"sell", lib_cmd_sell_what},
+ {"shake %object% *", lib_cmd_shake_object},
+ {"shake %text%", lib_cmd_shake_other},
+ {"shake", lib_cmd_shake_what},
+ {"shout *", lib_cmd_shout},
+ {"sing *", lib_cmd_sing},
+ {"sleep *", lib_cmd_sleep},
+ {"smell %object% *", lib_cmd_smell_object},
+ {"smell *", lib_cmd_smell_other},
+ {"stop %object% *", lib_cmd_stop_object},
+ {"stop %text%", lib_cmd_stop_other},
+ {"stop", lib_cmd_stop_what},
+ {"suck %object% *", lib_cmd_suck_object},
+ {"suck %text%", lib_cmd_suck_other},
+ {"suck", lib_cmd_suck_what},
+ {"talk *", lib_cmd_talk},
+ {"thank *", lib_cmd_thank},
+ {"turn %object% *", lib_cmd_turn_object},
+ {"turn %text%", lib_cmd_turn_other},
+ {"turn", lib_cmd_turn_what},
+ {"touch %object% *", lib_cmd_touch_object},
+ {"touch %text%", lib_cmd_touch_other},
+ {"touch", lib_cmd_touch_what},
+ {"unblock %object% *", lib_cmd_unblock_object},
+ {"unblock %text%", lib_cmd_unblock_other},
+ {"unblock", lib_cmd_unblock_what},
+ {"wash %object% *", lib_cmd_wash_object},
+ {"wash %text%", lib_cmd_wash_other},
+ {"wash", lib_cmd_wash_what},
+ {"whistle *", lib_cmd_whistle},
+ {"[why/when/what/can/how] *", lib_cmd_interrogation},
+ {"xyzzy *", lib_cmd_xyzzy},
+ {"campbell", lib_cmd_egotistic},
+ {"[yes/no] *", lib_cmd_yes_or_no},
+ {"* %object% *", lib_cmd_verb_object},
+ {"* %character% *", lib_cmd_verb_npc},
+
+ /* SCARE debugger hook command, placed last just in case... */
+ {"{#}debug{ger}", debug_cmd_debugger},
+
+ {NULL, NULL}
};
@@ -457,61 +488,53 @@ static sc_commands_t STANDARD_COMMANDS[] = {
* object acquisition take precedence over game commands.
*/
static sc_bool
-run_priority_commands (sc_gameref_t game, const sc_char *string)
-{
- sc_commandsref_t command;
-
- for (command = PRIORITY_COMMANDS; command->command; command++)
- {
- if (uip_match (command->command, string, game))
- {
- if (command->handler (game))
- return TRUE;
- }
- }
-
- /* Nothing matched match the string. Or if it did, its handler failed. */
- return FALSE;
+run_priority_commands(sc_gameref_t game, const sc_char *string) {
+ sc_commandsref_t command;
+
+ for (command = PRIORITY_COMMANDS; command->command; command++) {
+ if (uip_match(command->command, string, game)) {
+ if (command->handler(game))
+ return TRUE;
+ }
+ }
+
+ /* Nothing matched match the string. Or if it did, its handler failed. */
+ return FALSE;
}
static sc_bool
-run_standard_commands (sc_gameref_t game, const sc_char *string)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[2];
- sc_bool eightpointcompass;
- sc_commandsref_t command;
-
- /* Select the appropriate movement commands. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "EightPointCompass";
- eightpointcompass = prop_get_boolean (bundle, "B<-ss", vt_key);
- command = eightpointcompass ? MOVE_COMMANDS_8 : MOVE_COMMANDS_4;
-
- /*
- * Search movement commands first, returning TRUE if any matching command
- * handler succeeded. Then repeat for standard library commands.
- */
- for (; command->command; command++)
- {
- if (uip_match (command->command, string, game))
- {
- if (command->handler (game))
- return TRUE;
- }
- }
-
- for (command = STANDARD_COMMANDS; command->command; command++)
- {
- if (uip_match (command->command, string, game))
- {
- if (command->handler (game))
- return TRUE;
- }
- }
-
- /* Nothing matched match the string. Or if it did, its handler failed. */
- return FALSE;
+run_standard_commands(sc_gameref_t game, const sc_char *string) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[2];
+ sc_bool eightpointcompass;
+ sc_commandsref_t command;
+
+ /* Select the appropriate movement commands. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "EightPointCompass";
+ eightpointcompass = prop_get_boolean(bundle, "B<-ss", vt_key);
+ command = eightpointcompass ? MOVE_COMMANDS_8 : MOVE_COMMANDS_4;
+
+ /*
+ * Search movement commands first, returning TRUE if any matching command
+ * handler succeeded. Then repeat for standard library commands.
+ */
+ for (; command->command; command++) {
+ if (uip_match(command->command, string, game)) {
+ if (command->handler(game))
+ return TRUE;
+ }
+ }
+
+ for (command = STANDARD_COMMANDS; command->command; command++) {
+ if (uip_match(command->command, string, game)) {
+ if (command->handler(game))
+ return TRUE;
+ }
+ }
+
+ /* Nothing matched match the string. Or if it did, its handler failed. */
+ return FALSE;
}
@@ -521,43 +544,40 @@ run_standard_commands (sc_gameref_t game, const sc_char *string)
* Update the game's current room and status line strings.
*/
static void
-run_update_status (sc_gameref_t game)
-{
- 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[2];
- const sc_char *name, *status;
- sc_char *filtered;
- sc_bool statusbox;
-
- /* Get the current room name, and filter and untag it. */
- name = lib_get_room_name (game, gs_playerroom (game));
- filtered = pf_filter (name, vars, bundle);
- pf_strip_tags (filtered);
-
- /* Free any existing room name, then save this room name. */
- sc_free (game->current_room_name);
- game->current_room_name = filtered;
-
- /* See if the game does a status box. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "StatusBox";
- statusbox = prop_get_boolean (bundle, "B<-ss", vt_key);
- if (statusbox)
- {
- /* Get the status line, and filter and untag it. */
- vt_key[1].string = "StatusBoxText";
- status = prop_get_string (bundle, "S<-ss", vt_key);
- filtered = pf_filter (status, vars, bundle);
- pf_strip_tags (filtered);
- }
- else
- /* No status line, so use NULL. */
- filtered = NULL;
-
- /* Free any existing status line, then save this status text. */
- sc_free (game->status_line);
- game->status_line = filtered;
+run_update_status(sc_gameref_t game) {
+ 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[2];
+ const sc_char *name, *status;
+ sc_char *filtered;
+ sc_bool statusbox;
+
+ /* Get the current room name, and filter and untag it. */
+ name = lib_get_room_name(game, gs_playerroom(game));
+ filtered = pf_filter(name, vars, bundle);
+ pf_strip_tags(filtered);
+
+ /* Free any existing room name, then save this room name. */
+ sc_free(game->current_room_name);
+ game->current_room_name = filtered;
+
+ /* See if the game does a status box. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "StatusBox";
+ statusbox = prop_get_boolean(bundle, "B<-ss", vt_key);
+ if (statusbox) {
+ /* Get the status line, and filter and untag it. */
+ vt_key[1].string = "StatusBoxText";
+ status = prop_get_string(bundle, "S<-ss", vt_key);
+ filtered = pf_filter(status, vars, bundle);
+ pf_strip_tags(filtered);
+ } else
+ /* No status line, so use NULL. */
+ filtered = NULL;
+
+ /* Free any existing status line, then save this status text. */
+ sc_free(game->status_line);
+ game->status_line = filtered;
}
@@ -570,36 +590,32 @@ run_update_status (sc_gameref_t game)
* output ahead of buffered printfilter text.
*/
static void
-run_notify_score_change (sc_gameref_t game)
-{
- const sc_gameref_t undo = game->undo;
- sc_char buffer[32];
- assert (gs_is_game_valid (undo));
-
- /*
- * Do nothing if no undo available, or if notification is off, or if we've
- * already done this once this turn.
- */
- if (!game->undo_available
- || !game->notify_score_change || game->has_notified)
- return;
-
- /* Note any change in the score. */
- if (game->score > undo->score)
- {
- if_print_string ("(Your score has increased by ");
- sprintf (buffer, "%ld", game->score - undo->score);
- if_print_string (buffer);
- if_print_string (")\n");
- }
- else if (game->score < undo->score)
- {
- if_print_string ("(Your score has decreased by ");
- sprintf (buffer, "%ld", undo->score - game->score);
- if_print_string (buffer);
- if_print_string (")\n");
- }
- game->has_notified = TRUE;
+run_notify_score_change(sc_gameref_t game) {
+ const sc_gameref_t undo = game->undo;
+ sc_char buffer[32];
+ assert(gs_is_game_valid(undo));
+
+ /*
+ * Do nothing if no undo available, or if notification is off, or if we've
+ * already done this once this turn.
+ */
+ if (!game->undo_available
+ || !game->notify_score_change || game->has_notified)
+ return;
+
+ /* Note any change in the score. */
+ if (game->score > undo->score) {
+ if_print_string("(Your score has increased by ");
+ sprintf(buffer, "%ld", game->score - undo->score);
+ if_print_string(buffer);
+ if_print_string(")\n");
+ } else if (game->score < undo->score) {
+ if_print_string("(Your score has decreased by ");
+ sprintf(buffer, "%ld", undo->score - game->score);
+ if_print_string(buffer);
+ if_print_string(")\n");
+ }
+ game->has_notified = TRUE;
}
@@ -615,81 +631,73 @@ run_notify_score_change (sc_gameref_t game)
* are selected by 'forwards'.
*/
static sc_bool
-run_match_task_common (sc_gameref_t game,
- sc_int task, const sc_char *string, sc_bool forwards,
- sc_bool is_library, sc_bool is_normal)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[4];
- sc_int command_count, command;
- sc_bool is_matched;
-
- /* Get the count of task commands. */
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = forwards ? "Command" : "ReverseCommand";
- command_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- /* Iterate over commands, looking for patterns that match string. */
- is_matched = FALSE;
- for (command = 0; command < command_count; command++)
- {
- const sc_char *pattern;
- sc_int first;
-
- /* Retrieve the pattern for this command, find its first character. */
- vt_key[3].integer = command;
- pattern = prop_get_string (bundle, "S<-sisi", vt_key);
- first = strspn (pattern, WHITESPACE);
-
- /* Match using either the parser, or the special function matcher. */
- if (is_normal)
- {
- if (pattern[first] != SPECIAL_PATTERN)
- {
- /*
- * Make a special case of library calls and commands that begin
- * with a wildcard; these we ignore for this match attempt.
- */
- if (is_library && pattern[first] == WILDCARD_PATTERN)
- is_matched = FALSE;
- else
- is_matched = uip_match (pattern, string, game);
- }
- }
- else
- {
- if (pattern[first] == SPECIAL_PATTERN)
- is_matched = run_is_task_function (pattern, game);
- }
-
- /* Stop searching if we find a match. */
- if (is_matched)
- break;
- }
-
- /* Return TRUE if we found a pattern match. */
- return is_matched;
+run_match_task_common(sc_gameref_t game,
+ sc_int task, const sc_char *string, sc_bool forwards,
+ sc_bool is_library, sc_bool is_normal) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[4];
+ sc_int command_count, command;
+ sc_bool is_matched;
+
+ /* Get the count of task commands. */
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = forwards ? "Command" : "ReverseCommand";
+ command_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ /* Iterate over commands, looking for patterns that match string. */
+ is_matched = FALSE;
+ for (command = 0; command < command_count; command++) {
+ const sc_char *pattern;
+ sc_int first;
+
+ /* Retrieve the pattern for this command, find its first character. */
+ vt_key[3].integer = command;
+ pattern = prop_get_string(bundle, "S<-sisi", vt_key);
+ first = strspn(pattern, WHITESPACE);
+
+ /* Match using either the parser, or the special function matcher. */
+ if (is_normal) {
+ if (pattern[first] != SPECIAL_PATTERN) {
+ /*
+ * Make a special case of library calls and commands that begin
+ * with a wildcard; these we ignore for this match attempt.
+ */
+ if (is_library && pattern[first] == WILDCARD_PATTERN)
+ is_matched = FALSE;
+ else
+ is_matched = uip_match(pattern, string, game);
+ }
+ } else {
+ if (pattern[first] == SPECIAL_PATTERN)
+ is_matched = run_is_task_function(pattern, game);
+ }
+
+ /* Stop searching if we find a match. */
+ if (is_matched)
+ break;
+ }
+
+ /* Return TRUE if we found a pattern match. */
+ return is_matched;
}
static sc_bool
-run_match_task_commands (sc_gameref_t game,
- sc_int task, const sc_char *string,
- sc_bool forwards, sc_bool is_library)
-{
- /*
- * Match tasks using the normal pattern matcher, with or without any note
- * about whether the call is from the library.
- */
- return run_match_task_common (game, task, string, forwards, is_library, TRUE);
+run_match_task_commands(sc_gameref_t game,
+ sc_int task, const sc_char *string,
+ sc_bool forwards, sc_bool is_library) {
+ /*
+ * Match tasks using the normal pattern matcher, with or without any note
+ * about whether the call is from the library.
+ */
+ return run_match_task_common(game, task, string, forwards, is_library, TRUE);
}
static sc_bool
-run_match_task_functions (sc_gameref_t game,
- sc_int task, const sc_char *string, sc_bool forwards)
-{
- /* Match tasks against "task command functions". */
- return run_match_task_common (game, task, string, forwards, FALSE, FALSE);
+run_match_task_functions(sc_gameref_t game,
+ sc_int task, const sc_char *string, sc_bool forwards) {
+ /* Match tasks against "task command functions". */
+ return run_match_task_common(game, task, string, forwards, FALSE, FALSE);
}
@@ -706,46 +714,42 @@ run_match_task_functions (sc_gameref_t game,
* and don't change state.
*/
static sc_bool
-run_task_is_unrestricted (sc_gameref_t game, sc_int task)
-{
- sc_bool restrictions_passed;
- const sc_char *fail_message;
-
- /*
- * Evaluate task restrictions, and if they fail to parse for some reason,
- * return as if restrictions did not pass.
- */
- if (!restr_eval_task_restrictions (game, task,
- &restrictions_passed, &fail_message))
- {
- sc_error ("run_task_is_unrestricted: restrictions error, %ld\n", task);
- return FALSE;
- }
-
- /* Return TRUE if the task is unrestricted. */
- return restrictions_passed;
+run_task_is_unrestricted(sc_gameref_t game, sc_int task) {
+ sc_bool restrictions_passed;
+ const sc_char *fail_message;
+
+ /*
+ * Evaluate task restrictions, and if they fail to parse for some reason,
+ * return as if restrictions did not pass.
+ */
+ if (!restr_eval_task_restrictions(game, task,
+ &restrictions_passed, &fail_message)) {
+ sc_error("run_task_is_unrestricted: restrictions error, %ld\n", task);
+ return FALSE;
+ }
+
+ /* Return TRUE if the task is unrestricted. */
+ return restrictions_passed;
}
static sc_bool
-run_task_is_loudly_restricted (sc_gameref_t game, sc_int task)
-{
- sc_bool restrictions_passed;
- const sc_char *fail_message;
-
- /*
- * Evaluate task restrictions, and if they fail to parse for some reason,
- * return as if restrictions did not pass.
- */
- if (!restr_eval_task_restrictions (game, task,
- &restrictions_passed, &fail_message))
- {
- sc_error ("run_task_is_loudly_restricted:"
- " restrictions error, %ld\n", task);
- return TRUE;
- }
-
- /* Return TRUE if the task is restricted and indicates why. */
- return !restrictions_passed && (fail_message != NULL);
+run_task_is_loudly_restricted(sc_gameref_t game, sc_int task) {
+ sc_bool restrictions_passed;
+ const sc_char *fail_message;
+
+ /*
+ * Evaluate task restrictions, and if they fail to parse for some reason,
+ * return as if restrictions did not pass.
+ */
+ if (!restr_eval_task_restrictions(game, task,
+ &restrictions_passed, &fail_message)) {
+ sc_error("run_task_is_loudly_restricted:"
+ " restrictions error, %ld\n", task);
+ return TRUE;
+ }
+
+ /* Return TRUE if the task is restricted and indicates why. */
+ return !restrictions_passed && (fail_message != NULL);
}
@@ -785,134 +789,119 @@ run_task_is_loudly_restricted (sc_gameref_t game, sc_int task)
* handlers and get_all/drop_all handlers. No pressure, then.
*/
static sc_bool
-run_game_commands_common (sc_gameref_t game, const sc_char *string,
- sc_bool include_restrictions, sc_bool is_library)
-{
- sc_bool is_matched = FALSE, is_handled = FALSE;
- sc_bool *is_matching;
- sc_int task_count, task, direction;
-
- /*
- * Matching is expensive, so it helps to use a cache of results from the
- * first loop in the second. If we're using the second, that is.
- */
- task_count = gs_task_count (game);
- if (include_restrictions)
- {
- is_matching = (sc_bool *)sc_malloc (task_count * sizeof (*is_matching));
- memset (is_matching, FALSE, task_count * sizeof (*is_matching));
- }
- else
- is_matching = NULL;
-
- /*
- * Iterate over every task, ignoring those not runnable. For each runnable
- * task, try matching task commands, and on matches, check restrictions and
- * if they pass, try running the task.
- */
- for (task = 0; task < task_count; task++)
- {
- if (!task_can_run_task (game, task))
- continue;
-
- /*
- * Try matching forwards and reverse commands. If there's a match for
- * unrestricted tasks, run the task, and if it runs (defined as printing
- * some game output), we're done; otherwise, note the command match but
- * keep searching for other possible matches.
- */
- for (direction = 0; direction < 2; direction++)
- {
- const sc_bool is_forwards = !direction;
-
- if (task_can_run_task_directional (game, task, is_forwards)
- && run_match_task_commands (game, task, string,
- is_forwards, is_library))
- {
- if (run_task_is_unrestricted (game, task))
- {
- if (task_run_task (game, task, is_forwards))
- is_handled = TRUE;
- is_matched = TRUE;
- break;
- }
-
- if (is_matching)
- is_matching[task] = TRUE;
- }
- }
- if (is_matched)
- break;
- }
-
- /*
- * If no match, and we've been asked to consider failing restrictions, look
- * through all of the runnable tasks again, this time searching for
- * restricted ones with a fail message. Use the cache built above to weed
- * out matches that are certain to fail.
- */
- if (!is_handled && !is_matched && include_restrictions)
- {
- for (task = 0; task < task_count; task++)
- {
- if (!is_matching[task] || !task_can_run_task (game, task))
- continue;
-
- /*
- * Check matches of forwards and reverse commands. If there's a
- * match for restricted tasks (ones that have and will print a fail
- * message if we try to run them), run the task to get the print of
- * the fail message, and we're done.
- */
- for (direction = 0; direction < 2; direction++)
- {
- const sc_bool is_forwards = !direction;
-
- if (task_can_run_task_directional (game, task, is_forwards)
- && run_match_task_commands (game, task, string,
- is_forwards, is_library))
- {
- if (run_task_is_loudly_restricted (game, task))
- {
- if (task_run_task (game, task, is_forwards))
- {
- is_handled = TRUE;
- break;
- }
- }
- }
- }
- if (is_handled)
- break;
- }
- }
-
- /* Return TRUE if any game task handled the command in some way. */
- sc_free (is_matching);
- return is_handled;
+run_game_commands_common(sc_gameref_t game, const sc_char *string,
+ sc_bool include_restrictions, sc_bool is_library) {
+ sc_bool is_matched = FALSE, is_handled = FALSE;
+ sc_bool *is_matching;
+ sc_int task_count, task, direction;
+
+ /*
+ * Matching is expensive, so it helps to use a cache of results from the
+ * first loop in the second. If we're using the second, that is.
+ */
+ task_count = gs_task_count(game);
+ if (include_restrictions) {
+ is_matching = (sc_bool *)sc_malloc(task_count * sizeof(*is_matching));
+ memset(is_matching, FALSE, task_count * sizeof(*is_matching));
+ } else
+ is_matching = NULL;
+
+ /*
+ * Iterate over every task, ignoring those not runnable. For each runnable
+ * task, try matching task commands, and on matches, check restrictions and
+ * if they pass, try running the task.
+ */
+ for (task = 0; task < task_count; task++) {
+ if (!task_can_run_task(game, task))
+ continue;
+
+ /*
+ * Try matching forwards and reverse commands. If there's a match for
+ * unrestricted tasks, run the task, and if it runs (defined as printing
+ * some game output), we're done; otherwise, note the command match but
+ * keep searching for other possible matches.
+ */
+ for (direction = 0; direction < 2; direction++) {
+ const sc_bool is_forwards = !direction;
+
+ if (task_can_run_task_directional(game, task, is_forwards)
+ && run_match_task_commands(game, task, string,
+ is_forwards, is_library)) {
+ if (run_task_is_unrestricted(game, task)) {
+ if (task_run_task(game, task, is_forwards))
+ is_handled = TRUE;
+ is_matched = TRUE;
+ break;
+ }
+
+ if (is_matching)
+ is_matching[task] = TRUE;
+ }
+ }
+ if (is_matched)
+ break;
+ }
+
+ /*
+ * If no match, and we've been asked to consider failing restrictions, look
+ * through all of the runnable tasks again, this time searching for
+ * restricted ones with a fail message. Use the cache built above to weed
+ * out matches that are certain to fail.
+ */
+ if (!is_handled && !is_matched && include_restrictions) {
+ for (task = 0; task < task_count; task++) {
+ if (!is_matching[task] || !task_can_run_task(game, task))
+ continue;
+
+ /*
+ * Check matches of forwards and reverse commands. If there's a
+ * match for restricted tasks (ones that have and will print a fail
+ * message if we try to run them), run the task to get the print of
+ * the fail message, and we're done.
+ */
+ for (direction = 0; direction < 2; direction++) {
+ const sc_bool is_forwards = !direction;
+
+ if (task_can_run_task_directional(game, task, is_forwards)
+ && run_match_task_commands(game, task, string,
+ is_forwards, is_library)) {
+ if (run_task_is_loudly_restricted(game, task)) {
+ if (task_run_task(game, task, is_forwards)) {
+ is_handled = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ if (is_handled)
+ break;
+ }
+ }
+
+ /* Return TRUE if any game task handled the command in some way. */
+ sc_free(is_matching);
+ return is_handled;
}
static sc_bool
-run_game_commands_in_parser_context (sc_gameref_t game, const sc_char *string,
- sc_bool include_restrictions)
-{
- /*
- * Try game commands, either with or without restrictions, and all full and
- * complete parse matching (no special case for game commands that begin
- * with a '*' wildcard).
- */
- return run_game_commands_common (game, string, include_restrictions, FALSE);
+run_game_commands_in_parser_context(sc_gameref_t game, const sc_char *string,
+ sc_bool include_restrictions) {
+ /*
+ * Try game commands, either with or without restrictions, and all full and
+ * complete parse matching (no special case for game commands that begin
+ * with a '*' wildcard).
+ */
+ return run_game_commands_common(game, string, include_restrictions, FALSE);
}
static sc_bool
-run_game_commands_in_library_context (sc_gameref_t game, const sc_char *string)
-{
- /*
- * Try game commands, including restrictions, and noting that this is a
- * library call so that the parse matcher can exclude game commands that
- * begin with a '*' wildcard.
- */
- return run_game_commands_common (game, string, TRUE, TRUE);
+run_game_commands_in_library_context(sc_gameref_t game, const sc_char *string) {
+ /*
+ * Try game commands, including restrictions, and noting that this is a
+ * library call so that the parse matcher can exclude game commands that
+ * begin with a '*' wildcard.
+ */
+ return run_game_commands_common(game, string, TRUE, TRUE);
}
@@ -924,33 +913,29 @@ run_game_commands_in_library_context (sc_gameref_t game, const sc_char *string)
* command matches, so we try them as a separate action.
*/
static void
-run_game_functions (sc_gameref_t game, const sc_char *string)
-{
- sc_int task_count, task, direction;
-
- /* Iterate over every task, ignoring those not runnable. */
- task_count = gs_task_count (game);
- for (task = 0; task < task_count; task++)
- {
- if (!task_can_run_task (game, task))
- continue;
-
- /*
- * Try matching forwards and reverse commands. I don't know if it's
- * valid to put a function in a reverse command, but nevertheless...
- */
- for (direction = 0; direction < 2; direction++)
- {
- const sc_bool is_forwards = !direction;
-
- if (task_can_run_task_directional (game, task, is_forwards)
- && run_match_task_functions (game, task, string, is_forwards))
- {
- if (run_task_is_unrestricted (game, task))
- task_run_task (game, task, is_forwards);
- }
- }
- }
+run_game_functions(sc_gameref_t game, const sc_char *string) {
+ sc_int task_count, task, direction;
+
+ /* Iterate over every task, ignoring those not runnable. */
+ task_count = gs_task_count(game);
+ for (task = 0; task < task_count; task++) {
+ if (!task_can_run_task(game, task))
+ continue;
+
+ /*
+ * Try matching forwards and reverse commands. I don't know if it's
+ * valid to put a function in a reverse command, but nevertheless...
+ */
+ for (direction = 0; direction < 2; direction++) {
+ const sc_bool is_forwards = !direction;
+
+ if (task_can_run_task_directional(game, task, is_forwards)
+ && run_match_task_functions(game, task, string, is_forwards)) {
+ if (run_task_is_unrestricted(game, task))
+ task_run_task(game, task, is_forwards);
+ }
+ }
+ }
}
@@ -963,73 +948,70 @@ run_game_functions (sc_gameref_t game, const sc_char *string)
* game commands that override standard actions.
*/
static sc_bool
-run_all_commands (sc_gameref_t game, const sc_char *string)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_bool status;
-
- /*
- * Adrift command matching is just weird, perhaps broken. In theory, a
- * game can override system commands with a properly constructed task and
- * set of command matchers. However, the Runner isn't terribly consistent
- * in when this will work and when not, and some games rely on that in-
- * consistency. In particular, a game with a "* object" task that has
- * failing restrictions will not be able to override the system's "take
- * object", whereas a game's "take object", under the same circumstances,
- * will. Yet if the restrictions pass, a game's "* object" overrides the
- * system's "take object" with no apparent difficulty.
- *
- * For example, "The Woods Are Dark" has a "* ball *" task with the
- * restriction "must be holding ball". Without special casing it, there's
- * no way to get the ball in the first place.
- *
- * Trying to find the right way to do things here, then, has been tricky.
- * Here's the current process: First, run game commands, ignoring any
- * cases where restrictions fail to let the task run. Next, try "priority"
- * system commands; ones that move objects to inventory. These system
- * commands will call back into trying game commands for objects taken or
- * dropped, and in those tries, allow overrides only if the game task is
- * explicit about what it's doing (that is, doesn't start with "*"), and
- * handle restrictions in those tries. After that, retry all game commands
- * again with restrictions enabled. And finally, try all other standard
- * library commands.
- *
- * TODO This is the fourth or fifth attempt at getting this to match the
- * Runner, which is surprisingly inconsistent in this area. What on earth
- * is the real behavior supposed to be?
- */
- status = run_game_commands_in_parser_context (game, string, FALSE);
- if (!status)
- status = run_priority_commands (game, string);
- if (!status)
- status = run_game_commands_in_parser_context (game, string, TRUE);
- if (!status)
- status = run_standard_commands (game, string);
-
- /*
- * For version 4.0 games, it seems that if any command succeeded, we need
- * need to scan for and run any matching "task command functions", in
- * addition to anything done above.
- */
- if (status && !game->is_admin)
- {
- sc_vartype_t vt_key;
- sc_int version;
-
- /* Check "task command functions" for version 4.0 only. */
- vt_key.string = "Version";
- version = prop_get_integer (bundle, "I<-s", &vt_key);
- if (version == TAF_VERSION_400)
- run_game_functions (game, string);
- }
-
- return status;
+run_all_commands(sc_gameref_t game, const sc_char *string) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_bool status;
+
+ /*
+ * Adrift command matching is just weird, perhaps broken. In theory, a
+ * game can override system commands with a properly constructed task and
+ * set of command matchers. However, the Runner isn't terribly consistent
+ * in when this will work and when not, and some games rely on that in-
+ * consistency. In particular, a game with a "* object" task that has
+ * failing restrictions will not be able to override the system's "take
+ * object", whereas a game's "take object", under the same circumstances,
+ * will. Yet if the restrictions pass, a game's "* object" overrides the
+ * system's "take object" with no apparent difficulty.
+ *
+ * For example, "The Woods Are Dark" has a "* ball *" task with the
+ * restriction "must be holding ball". Without special casing it, there's
+ * no way to get the ball in the first place.
+ *
+ * Trying to find the right way to do things here, then, has been tricky.
+ * Here's the current process: First, run game commands, ignoring any
+ * cases where restrictions fail to let the task run. Next, try "priority"
+ * system commands; ones that move objects to inventory. These system
+ * commands will call back into trying game commands for objects taken or
+ * dropped, and in those tries, allow overrides only if the game task is
+ * explicit about what it's doing (that is, doesn't start with "*"), and
+ * handle restrictions in those tries. After that, retry all game commands
+ * again with restrictions enabled. And finally, try all other standard
+ * library commands.
+ *
+ * TODO This is the fourth or fifth attempt at getting this to match the
+ * Runner, which is surprisingly inconsistent in this area. What on earth
+ * is the real behavior supposed to be?
+ */
+ status = run_game_commands_in_parser_context(game, string, FALSE);
+ if (!status)
+ status = run_priority_commands(game, string);
+ if (!status)
+ status = run_game_commands_in_parser_context(game, string, TRUE);
+ if (!status)
+ status = run_standard_commands(game, string);
+
+ /*
+ * For version 4.0 games, it seems that if any command succeeded, we need
+ * need to scan for and run any matching "task command functions", in
+ * addition to anything done above.
+ */
+ if (status && !game->is_admin) {
+ sc_vartype_t vt_key;
+ sc_int version;
+
+ /* Check "task command functions" for version 4.0 only. */
+ vt_key.string = "Version";
+ version = prop_get_integer(bundle, "I<-s", &vt_key);
+ if (version == TAF_VERSION_400)
+ run_game_functions(game, string);
+ }
+
+ return status;
}
sc_bool
-run_game_task_commands (sc_gameref_t game, const sc_char *string)
-{
- return run_game_commands_in_library_context (game, string);
+run_game_task_commands(sc_gameref_t game, const sc_char *string) {
+ return run_game_commands_in_library_context(game, string);
}
@@ -1051,238 +1033,219 @@ run_game_task_commands (sc_gameref_t game, const sc_char *string)
* just return. Sorry about the ugliness.
*/
static sc_bool
-run_player_input (sc_gameref_t game)
-{
- static sc_char line_buffer[LINE_BUFFER_SIZE];
- static sc_char prior_element[LINE_BUFFER_SIZE];
- static sc_char line_element[LINE_BUFFER_SIZE];
-
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_memo_setref_t memento = gs_get_memento (game);
- sc_bool is_rerunning, was_undo_available, status;
- sc_char *filtered, *replaced;
- const sc_char *command;
-
- /* Special case; reset statics if the game isn't running. */
- if (!game->is_running)
- {
- memset (line_buffer, NUL, sizeof (line_buffer));
- memset (prior_element, NUL, sizeof (prior_element));
- memset (line_element, NUL, sizeof (line_element));
- return TRUE;
- }
-
- /*
- * Save the settings of the game's do_again and undo_available flags for
- * later checks.
- */
- is_rerunning = game->do_again;
- was_undo_available = game->undo_available;
-
- /* See if the player asked to rerun a command element. */
- if (game->do_again)
- {
- game->do_again = FALSE;
-
- /* Check there is a last element to repeat. */
- if (prior_element[0] == NUL)
- {
- pf_buffer_string (filter, "You can hardly repeat that.\n");
- return FALSE;
- }
-
- /* Make the last element the current input element. */
- strcpy (line_element, prior_element);
- }
- else
- {
- sc_int length, extent;
-
- /*
- * If there's none buffered, read a new line of player input. Other-
- * wise, separate output so far with a newline.
- */
- if (line_buffer[0] == NUL)
- if_read_line (line_buffer, sizeof (line_buffer));
- else
- if_print_character ('\n');
-
- /*
- * Find the length of the next input line element. Unless the line
- * buffer is empty, we always take the first character, even if it's a
- * separator. This catches odd input like "." and turns it into a
- * parser complaint, rather than treating it as two empty commands with
- * a separator between them; this makes it close to what Inform does
- * with similar inputs.
- */
- length = (line_buffer[0] == NUL) ? 0 : 1;
- while (line_buffer[length] != NUL
- && strchr (SEPARATORS, line_buffer[length]) == NULL)
- length++;
-
- /*
- * Make this the current input element, and remove it, the separator,
- * and any trailing whitespace, from the front of the line buffer.
- * Removing whitespace prevents "i. ." looking like "i" and ""; it
- * instead looks like "i" and ".", and results in a parser complaint.
- */
- memcpy (line_element, line_buffer, length);
- line_element[length] = NUL;
-
- extent = length;
- extent += (line_buffer[length] == NUL
- || strchr (SEPARATORS, line_buffer[length]) == NULL) ? 0 : 1;
- extent += strspn (line_buffer + extent, WHITESPACE);
- memmove (line_buffer,
- line_buffer + extent, strlen (line_buffer) - extent + 1);
- }
-
- /* Copy the current game to the temporary undo buffer. */
- gs_copy (game->temporary, game);
-
- /* Filter the input element for synonyms, then for pronouns. */
- filtered = pf_filter_input (line_element, bundle);
- replaced = uip_replace_pronouns (game, filtered ? filtered : line_element);
-
- /*
- * If filtering didn't replace synonyms, or no pronouns were replaced, use
- * the original line element.
- */
- command = replaced ? sc_normalize_string (replaced)
- : (filtered ? sc_normalize_string (filtered) : line_element);
- if (command != line_element)
- {
- if_print_tag (SC_TAG_ITALICS, "");
- if_print_character ('[');
- if_print_string (command);
- if_print_character (']');
- if_print_tag (SC_TAG_ENDITALICS, "");
- if_print_character ('\n');
- }
-
- /* Try the command line element against command matchers. */
- status = run_all_commands (game, command);
- if (!status)
- {
- /* Only complain on non-empty command input line elements. */
- if (!sc_strempty (command))
- {
- sc_vartype_t vt_key[2];
- sc_char *escaped;
- const sc_char *message;
-
- /* Command line element not understood. */
- escaped = pf_escape (sc_normalize_string (line_element));
- var_set_ref_text (vars, escaped);
- sc_free (escaped);
- vt_key[0].string = "Globals";
- vt_key[1].string = "DontUnderstand";
- message = prop_get_string (bundle, "S<-ss", vt_key);
- pf_buffer_string (filter, message);
- pf_buffer_character (filter, '\n');
-
- /*
- * On a line element that's not understood, throw out any remaining
- * input line elements.
- */
- line_buffer[0] = NUL;
- sc_free (filtered);
- sc_free (replaced);
- return status;
- }
- }
- else
- {
- /*
- * Unless administrative, back up any valid undo, copy the temporary
- * game into the undo buffer, flag the undo buffer as available, and
- * assign any pronouns used in the command ready for the next iteration.
- */
- if (!game->is_admin)
- {
- if (game->undo_available)
- memo_save_game (memento, game->undo);
-
- gs_copy (game->undo, game->temporary);
- game->undo_available = TRUE;
-
- uip_assign_pronouns (game, command);
- }
- }
- sc_free (filtered);
- sc_free (replaced);
-
- /*
- * If do_again is set, we'll come round with the prior command in line
- * element in a moment, so save nothing for that case. Otherwise save the
- * command in the history.
- */
- if (!sc_strempty (line_element) && !game->do_again)
- {
- /*
- * If this is a failed redo, redo_sequence will be set but do_again will
- * be clear. Suppress the save for this special case; otherwise, failed
- * redo commands get into the history, where they can cause problems
- * later on.
- */
- if (game->redo_sequence == 0)
- {
- sc_int timestamp;
-
- timestamp = var_get_elapsed_seconds (vars);
- memo_save_command (memento, line_element, timestamp, game->turns);
- }
- else
- game->redo_sequence = 0;
- }
-
- /*
- * Special case restart and restore commands; throw out any remaining input
- * and return straight away. Do the same if this was an undo, detected by
- * noting that undo is no longer available, where it was on entry.
- */
- if (game->do_restart || game->do_restore
- || (was_undo_available && !game->undo_available))
- {
- line_buffer[0] = NUL;
- return status;
- }
-
- /* If not empty, consider as saving for "again" calls and in the history. */
- if (!sc_strempty (line_element))
- {
- /*
- * Unless "again", note this line element as prior input. "Again" shows
- * up as do_again set in the game, where it wasn't when we entered here.
- */
- if (!game->do_again && !is_rerunning)
- strcpy (prior_element, line_element);
-
- /*
- * If this was a request to run a command from the history, copy that
- * command into the prior_element for the next iteration. The library
- * should have verified the value in redo_sequence, so fetching the
- * command string should not fail.
- */
- if (game->do_again && game->redo_sequence != 0)
- {
- const sc_char *redo_command;
-
- redo_command = memo_find_command (memento, game->redo_sequence);
- if (redo_command)
- strcpy (prior_element, redo_command);
- else
- {
- sc_error ("run_player_input: invalid redo sequence request\n");
- game->do_again = FALSE;
- }
- game->redo_sequence = 0;
- }
- }
-
- return status;
+run_player_input(sc_gameref_t game) {
+ static sc_char line_buffer[LINE_BUFFER_SIZE];
+ static sc_char prior_element[LINE_BUFFER_SIZE];
+ static sc_char line_element[LINE_BUFFER_SIZE];
+
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_memo_setref_t memento = gs_get_memento(game);
+ sc_bool is_rerunning, was_undo_available, status;
+ sc_char *filtered, *replaced;
+ const sc_char *command;
+
+ /* Special case; reset statics if the game isn't running. */
+ if (!game->is_running) {
+ memset(line_buffer, NUL, sizeof(line_buffer));
+ memset(prior_element, NUL, sizeof(prior_element));
+ memset(line_element, NUL, sizeof(line_element));
+ return TRUE;
+ }
+
+ /*
+ * Save the settings of the game's do_again and undo_available flags for
+ * later checks.
+ */
+ is_rerunning = game->do_again;
+ was_undo_available = game->undo_available;
+
+ /* See if the player asked to rerun a command element. */
+ if (game->do_again) {
+ game->do_again = FALSE;
+
+ /* Check there is a last element to repeat. */
+ if (prior_element[0] == NUL) {
+ pf_buffer_string(filter, "You can hardly repeat that.\n");
+ return FALSE;
+ }
+
+ /* Make the last element the current input element. */
+ strcpy(line_element, prior_element);
+ } else {
+ sc_int length, extent;
+
+ /*
+ * If there's none buffered, read a new line of player input. Other-
+ * wise, separate output so far with a newline.
+ */
+ if (line_buffer[0] == NUL)
+ if_read_line(line_buffer, sizeof(line_buffer));
+ else
+ if_print_character('\n');
+
+ /*
+ * Find the length of the next input line element. Unless the line
+ * buffer is empty, we always take the first character, even if it's a
+ * separator. This catches odd input like "." and turns it into a
+ * parser complaint, rather than treating it as two empty commands with
+ * a separator between them; this makes it close to what Inform does
+ * with similar inputs.
+ */
+ length = (line_buffer[0] == NUL) ? 0 : 1;
+ while (line_buffer[length] != NUL
+ && strchr(SEPARATORS, line_buffer[length]) == NULL)
+ length++;
+
+ /*
+ * Make this the current input element, and remove it, the separator,
+ * and any trailing whitespace, from the front of the line buffer.
+ * Removing whitespace prevents "i. ." looking like "i" and ""; it
+ * instead looks like "i" and ".", and results in a parser complaint.
+ */
+ memcpy(line_element, line_buffer, length);
+ line_element[length] = NUL;
+
+ extent = length;
+ extent += (line_buffer[length] == NUL
+ || strchr(SEPARATORS, line_buffer[length]) == NULL) ? 0 : 1;
+ extent += strspn(line_buffer + extent, WHITESPACE);
+ memmove(line_buffer,
+ line_buffer + extent, strlen(line_buffer) - extent + 1);
+ }
+
+ /* Copy the current game to the temporary undo buffer. */
+ gs_copy(game->temporary, game);
+
+ /* Filter the input element for synonyms, then for pronouns. */
+ filtered = pf_filter_input(line_element, bundle);
+ replaced = uip_replace_pronouns(game, filtered ? filtered : line_element);
+
+ /*
+ * If filtering didn't replace synonyms, or no pronouns were replaced, use
+ * the original line element.
+ */
+ command = replaced ? sc_normalize_string(replaced)
+ : (filtered ? sc_normalize_string(filtered) : line_element);
+ if (command != line_element) {
+ if_print_tag(SC_TAG_ITALICS, "");
+ if_print_character('[');
+ if_print_string(command);
+ if_print_character(']');
+ if_print_tag(SC_TAG_ENDITALICS, "");
+ if_print_character('\n');
+ }
+
+ /* Try the command line element against command matchers. */
+ status = run_all_commands(game, command);
+ if (!status) {
+ /* Only complain on non-empty command input line elements. */
+ if (!sc_strempty(command)) {
+ sc_vartype_t vt_key[2];
+ sc_char *escaped;
+ const sc_char *message;
+
+ /* Command line element not understood. */
+ escaped = pf_escape(sc_normalize_string(line_element));
+ var_set_ref_text(vars, escaped);
+ sc_free(escaped);
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "DontUnderstand";
+ message = prop_get_string(bundle, "S<-ss", vt_key);
+ pf_buffer_string(filter, message);
+ pf_buffer_character(filter, '\n');
+
+ /*
+ * On a line element that's not understood, throw out any remaining
+ * input line elements.
+ */
+ line_buffer[0] = NUL;
+ sc_free(filtered);
+ sc_free(replaced);
+ return status;
+ }
+ } else {
+ /*
+ * Unless administrative, back up any valid undo, copy the temporary
+ * game into the undo buffer, flag the undo buffer as available, and
+ * assign any pronouns used in the command ready for the next iteration.
+ */
+ if (!game->is_admin) {
+ if (game->undo_available)
+ memo_save_game(memento, game->undo);
+
+ gs_copy(game->undo, game->temporary);
+ game->undo_available = TRUE;
+
+ uip_assign_pronouns(game, command);
+ }
+ }
+ sc_free(filtered);
+ sc_free(replaced);
+
+ /*
+ * If do_again is set, we'll come round with the prior command in line
+ * element in a moment, so save nothing for that case. Otherwise save the
+ * command in the history.
+ */
+ if (!sc_strempty(line_element) && !game->do_again) {
+ /*
+ * If this is a failed redo, redo_sequence will be set but do_again will
+ * be clear. Suppress the save for this special case; otherwise, failed
+ * redo commands get into the history, where they can cause problems
+ * later on.
+ */
+ if (game->redo_sequence == 0) {
+ sc_int timestamp;
+
+ timestamp = var_get_elapsed_seconds(vars);
+ memo_save_command(memento, line_element, timestamp, game->turns);
+ } else
+ game->redo_sequence = 0;
+ }
+
+ /*
+ * Special case restart and restore commands; throw out any remaining input
+ * and return straight away. Do the same if this was an undo, detected by
+ * noting that undo is no longer available, where it was on entry.
+ */
+ if (game->do_restart || game->do_restore
+ || (was_undo_available && !game->undo_available)) {
+ line_buffer[0] = NUL;
+ return status;
+ }
+
+ /* If not empty, consider as saving for "again" calls and in the history. */
+ if (!sc_strempty(line_element)) {
+ /*
+ * Unless "again", note this line element as prior input. "Again" shows
+ * up as do_again set in the game, where it wasn't when we entered here.
+ */
+ if (!game->do_again && !is_rerunning)
+ strcpy(prior_element, line_element);
+
+ /*
+ * If this was a request to run a command from the history, copy that
+ * command into the prior_element for the next iteration. The library
+ * should have verified the value in redo_sequence, so fetching the
+ * command string should not fail.
+ */
+ if (game->do_again && game->redo_sequence != 0) {
+ const sc_char *redo_command;
+
+ redo_command = memo_find_command(memento, game->redo_sequence);
+ if (redo_command)
+ strcpy(prior_element, redo_command);
+ else {
+ sc_error("run_player_input: invalid redo sequence request\n");
+ game->do_again = FALSE;
+ }
+ game->redo_sequence = 0;
+ }
+ }
+
+ return status;
}
@@ -1292,190 +1255,179 @@ run_player_input (sc_gameref_t game)
* Main interpreter loop.
*/
static void
-run_main_loop (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
-
- /*
- * This may not be the very first time this game has been used, for example
- * saving a game right at the start, or undo-ing back to the start through
- * memos. Caught by looking to see if the player room is marked as seen.
- */
- if (!gs_room_seen (game, gs_playerroom (game)))
- {
- sc_vartype_t vt_key[2];
- const sc_char *gamename, *startuptext;
- sc_bool disp_first_room, battle_system;
-
- /* If battle system and no debugger display a warning. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "BattleSystem";
- battle_system = prop_get_boolean (bundle, "B<-ss", vt_key);
- if (battle_system && !debug_get_enabled (game))
- {
- if_print_tag (SC_TAG_CLS, "");
- lib_warn_battle_system ();
- }
-
- /* Initial clear screen. */
- pf_buffer_tag (filter, SC_TAG_CLS);
-
- /* Print the game name. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- gamename = prop_get_string (bundle, "S<-ss", vt_key);
- pf_buffer_string (filter, gamename);
- pf_buffer_character (filter, '\n');
-
- /* Print the game header. */
- vt_key[0].string = "Header";
- vt_key[1].string = "StartupText";
- startuptext = prop_get_string (bundle, "S<-ss", vt_key);
- pf_buffer_string (filter, startuptext);
- pf_buffer_character (filter, '\n');
-
- /* If flagged, describe the initial room. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "DispFirstRoom";
- disp_first_room = prop_get_boolean (bundle, "B<-ss", vt_key);
- if (disp_first_room)
- lib_cmd_look (game);
-
- /* Handle any introductory resources. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "IntroRes";
- res_handle_resource (game, "ss", vt_key);
-
- /* Set initial values for NPC and object states. */
- npc_setup_initial (game);
- obj_setup_initial (game);
-
- /* Nudge events and NPCs. */
- evt_tick_events (game);
- npc_tick_npcs (game);
-
- /*
- * Notify the debugger that the game has started. This is a chance to
- * set watchpoints to catch game startup actions. Done before setting
- * the initial room visited as this is how the debugger differentiates
- * restarts from restore or undo back to game start.
- */
- debug_game_started (game);
-
- /* Note the initial room as visited. */
- gs_set_room_seen (game, gs_playerroom (game), TRUE);
- }
- else
- {
- /* Notify the debugger that the game has restarted. */
- debug_game_started (game);
- }
-
- /*
- * Game loop, exits either when a command parser handler sets the game
- * running flag to FALSE, or by call to run_quit().
- */
- game->is_running &= !g_vm->shouldQuit();
- while (game->is_running)
- {
- sc_bool status;
-
- /*
- * Synchronize any resources in use; do this before flushing so that any
- * appropriate graphics/sound appear before waits or waitkey tag delays
- * invoked by flushing the printfilter. Also, print any score change
- * notifications.
- */
- res_sync_resources (game);
- run_notify_score_change (game);
-
- /*
- * Flush printfilter of any accumulated output, and clear any prior
- * notion of administrative commands from input.
- */
- pf_flush (filter, vars, bundle);
- game->is_admin = FALSE;
-
- /* If waitcounter is zero, accept and try a command. */
- if (game->waitcounter == 0)
- {
- /* Not waiting, so handle a player input line. */
- run_update_status (game);
- status = run_player_input (game);
-
- /*
- * If waitcounter is now set, decrement it, as this turn counts as
- * one of them.
- */
- if (game->waitcounter > 0)
- game->waitcounter--;
- }
- else
- {
- /*
- * Currently "waiting"; decrement wait turns, then run a turn having
- * taken no input.
- */
- game->waitcounter--;
- status = TRUE;
- }
-
- /*
- * Do usual turn stuff unless either something stopped the game, or the
- * last command didn't match, or the last command did match but was
- * administrative.
- */
- if (status && !game->is_admin)
- {
- /* Increment turn counter, and clear notifications done flag. */
- game->turns++;
- game->has_notified = FALSE;
-
- if (game->is_running)
- {
- /* Nudge events and NPCs. */
- evt_tick_events (game);
- npc_tick_npcs (game);
-
- /* Update NPC and object states. */
- npc_turn_update (game);
- obj_turn_update (game);
-
- /* Note the current room as visited. */
- gs_set_room_seen (game, gs_playerroom (game), TRUE);
-
- /* Give the debugger a chance to catch watchpoints. */
- debug_turn_update (game);
- }
- }
-
- game->is_running &= !g_vm->shouldQuit();
- }
-
- /*
- * Final status update, for games that vary it on completion, then notify
- * the debugger that the game has ended, to let it make a last watchpoint
- * scan and offer the dialog if appropriate.
- */
- run_update_status (game);
- debug_game_ended (game);
-
- /*
- * Final resource sync, score change notification and printfilter flush
- * on game-instigated loop exit.
- */
- res_sync_resources (game);
- run_notify_score_change (game);
- pf_flush (filter, vars, bundle);
-
- /*
- * Reset static variables inside run_player_input() with a call to it with
- * is_running false; this is a special case.
- */
- assert (!game->is_running);
- run_player_input (game);
+run_main_loop(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+
+ /*
+ * This may not be the very first time this game has been used, for example
+ * saving a game right at the start, or undo-ing back to the start through
+ * memos. Caught by looking to see if the player room is marked as seen.
+ */
+ if (!gs_room_seen(game, gs_playerroom(game))) {
+ sc_vartype_t vt_key[2];
+ const sc_char *gamename, *startuptext;
+ sc_bool disp_first_room, battle_system;
+
+ /* If battle system and no debugger display a warning. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "BattleSystem";
+ battle_system = prop_get_boolean(bundle, "B<-ss", vt_key);
+ if (battle_system && !debug_get_enabled(game)) {
+ if_print_tag(SC_TAG_CLS, "");
+ lib_warn_battle_system();
+ }
+
+ /* Initial clear screen. */
+ pf_buffer_tag(filter, SC_TAG_CLS);
+
+ /* Print the game name. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ gamename = prop_get_string(bundle, "S<-ss", vt_key);
+ pf_buffer_string(filter, gamename);
+ pf_buffer_character(filter, '\n');
+
+ /* Print the game header. */
+ vt_key[0].string = "Header";
+ vt_key[1].string = "StartupText";
+ startuptext = prop_get_string(bundle, "S<-ss", vt_key);
+ pf_buffer_string(filter, startuptext);
+ pf_buffer_character(filter, '\n');
+
+ /* If flagged, describe the initial room. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "DispFirstRoom";
+ disp_first_room = prop_get_boolean(bundle, "B<-ss", vt_key);
+ if (disp_first_room)
+ lib_cmd_look(game);
+
+ /* Handle any introductory resources. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "IntroRes";
+ res_handle_resource(game, "ss", vt_key);
+
+ /* Set initial values for NPC and object states. */
+ npc_setup_initial(game);
+ obj_setup_initial(game);
+
+ /* Nudge events and NPCs. */
+ evt_tick_events(game);
+ npc_tick_npcs(game);
+
+ /*
+ * Notify the debugger that the game has started. This is a chance to
+ * set watchpoints to catch game startup actions. Done before setting
+ * the initial room visited as this is how the debugger differentiates
+ * restarts from restore or undo back to game start.
+ */
+ debug_game_started(game);
+
+ /* Note the initial room as visited. */
+ gs_set_room_seen(game, gs_playerroom(game), TRUE);
+ } else {
+ /* Notify the debugger that the game has restarted. */
+ debug_game_started(game);
+ }
+
+ /*
+ * Game loop, exits either when a command parser handler sets the game
+ * running flag to FALSE, or by call to run_quit().
+ */
+ game->is_running &= !g_vm->shouldQuit();
+ while (game->is_running) {
+ sc_bool status;
+
+ /*
+ * Synchronize any resources in use; do this before flushing so that any
+ * appropriate graphics/sound appear before waits or waitkey tag delays
+ * invoked by flushing the printfilter. Also, print any score change
+ * notifications.
+ */
+ res_sync_resources(game);
+ run_notify_score_change(game);
+
+ /*
+ * Flush printfilter of any accumulated output, and clear any prior
+ * notion of administrative commands from input.
+ */
+ pf_flush(filter, vars, bundle);
+ game->is_admin = FALSE;
+
+ /* If waitcounter is zero, accept and try a command. */
+ if (game->waitcounter == 0) {
+ /* Not waiting, so handle a player input line. */
+ run_update_status(game);
+ status = run_player_input(game);
+
+ /*
+ * If waitcounter is now set, decrement it, as this turn counts as
+ * one of them.
+ */
+ if (game->waitcounter > 0)
+ game->waitcounter--;
+ } else {
+ /*
+ * Currently "waiting"; decrement wait turns, then run a turn having
+ * taken no input.
+ */
+ game->waitcounter--;
+ status = TRUE;
+ }
+
+ /*
+ * Do usual turn stuff unless either something stopped the game, or the
+ * last command didn't match, or the last command did match but was
+ * administrative.
+ */
+ if (status && !game->is_admin) {
+ /* Increment turn counter, and clear notifications done flag. */
+ game->turns++;
+ game->has_notified = FALSE;
+
+ if (game->is_running) {
+ /* Nudge events and NPCs. */
+ evt_tick_events(game);
+ npc_tick_npcs(game);
+
+ /* Update NPC and object states. */
+ npc_turn_update(game);
+ obj_turn_update(game);
+
+ /* Note the current room as visited. */
+ gs_set_room_seen(game, gs_playerroom(game), TRUE);
+
+ /* Give the debugger a chance to catch watchpoints. */
+ debug_turn_update(game);
+ }
+ }
+
+ game->is_running &= !g_vm->shouldQuit();
+ }
+
+ /*
+ * Final status update, for games that vary it on completion, then notify
+ * the debugger that the game has ended, to let it make a last watchpoint
+ * scan and offer the dialog if appropriate.
+ */
+ run_update_status(game);
+ debug_game_ended(game);
+
+ /*
+ * Final resource sync, score change notification and printfilter flush
+ * on game-instigated loop exit.
+ */
+ res_sync_resources(game);
+ run_notify_score_change(game);
+ pf_flush(filter, vars, bundle);
+
+ /*
+ * Reset static variables inside run_player_input() with a call to it with
+ * is_running false; this is a special case.
+ */
+ assert(!game->is_running);
+ run_player_input(game);
}
@@ -1485,66 +1437,63 @@ run_main_loop (sc_gameref_t game)
* Create a game context from a callback.
*/
sc_gameref_t
-run_create (sc_read_callbackref_t callback, void *opaque)
-{
- sc_tafref_t taf;
- sc_prop_setref_t bundle;
- sc_var_setref_t vars, temporary_vars, undo_vars;
- sc_filterref_t filter;
- sc_gameref_t game, temporary_game, undo_game;
- assert (callback);
-
- /* Create a new TAF using the callback; return NULL if this fails. */
- taf = taf_create (callback, opaque);
- if (!taf)
- return NULL;
- else if (if_get_trace_flag (SC_DUMP_TAF))
- taf_debug_dump (taf);
-
- /* Create a properties bundle, and parse the TAF data into it. */
- bundle = prop_create (taf);
- if (!bundle)
- {
- sc_error ("run_create: error parsing game data\n");
- taf_destroy (taf);
- return NULL;
- }
- else if (if_get_trace_flag (SC_DUMP_PROPERTIES))
- prop_debug_dump (bundle);
-
- /* Try to set an interpreter locale from the properties bundle. */
- loc_detect_game_locale (bundle);
- if (if_get_trace_flag (SC_DUMP_LOCALE_TABLES))
- loc_debug_dump ();
-
- /* Create a set of variables from the bundle. */
- vars = var_create (bundle);
- if (if_get_trace_flag (SC_DUMP_VARIABLES))
- var_debug_dump (vars);
-
- /* Create a printfilter for the game. */
- filter = pf_create ();
-
- /*
- * Create an initial game state, and register it with variables. Also,
- * create undo buffers, and initialize them in the same way.
- */
- game = gs_create (vars, bundle, filter);
- var_register_game (vars, game);
-
- temporary_vars = var_create (bundle);
- temporary_game = gs_create (temporary_vars, bundle, filter);
- var_register_game (temporary_vars, temporary_game);
-
- undo_vars = var_create (bundle);
- undo_game = gs_create (undo_vars, bundle, filter);
- var_register_game (undo_vars, undo_game);
-
- /* Add the undo buffers and memos to the game, and return it. */
- game->temporary = temporary_game;
- game->undo = undo_game;
- game->memento = memo_create ();
- return game;
+run_create(sc_read_callbackref_t callback, void *opaque) {
+ sc_tafref_t taf;
+ sc_prop_setref_t bundle;
+ sc_var_setref_t vars, temporary_vars, undo_vars;
+ sc_filterref_t filter;
+ sc_gameref_t game, temporary_game, undo_game;
+ assert(callback);
+
+ /* Create a new TAF using the callback; return NULL if this fails. */
+ taf = taf_create(callback, opaque);
+ if (!taf)
+ return NULL;
+ else if (if_get_trace_flag(SC_DUMP_TAF))
+ taf_debug_dump(taf);
+
+ /* Create a properties bundle, and parse the TAF data into it. */
+ bundle = prop_create(taf);
+ if (!bundle) {
+ sc_error("run_create: error parsing game data\n");
+ taf_destroy(taf);
+ return NULL;
+ } else if (if_get_trace_flag(SC_DUMP_PROPERTIES))
+ prop_debug_dump(bundle);
+
+ /* Try to set an interpreter locale from the properties bundle. */
+ loc_detect_game_locale(bundle);
+ if (if_get_trace_flag(SC_DUMP_LOCALE_TABLES))
+ loc_debug_dump();
+
+ /* Create a set of variables from the bundle. */
+ vars = var_create(bundle);
+ if (if_get_trace_flag(SC_DUMP_VARIABLES))
+ var_debug_dump(vars);
+
+ /* Create a printfilter for the game. */
+ filter = pf_create();
+
+ /*
+ * Create an initial game state, and register it with variables. Also,
+ * create undo buffers, and initialize them in the same way.
+ */
+ game = gs_create(vars, bundle, filter);
+ var_register_game(vars, game);
+
+ temporary_vars = var_create(bundle);
+ temporary_game = gs_create(temporary_vars, bundle, filter);
+ var_register_game(temporary_vars, temporary_game);
+
+ undo_vars = var_create(bundle);
+ undo_game = gs_create(undo_vars, bundle, filter);
+ var_register_game(undo_vars, undo_game);
+
+ /* Add the undo buffers and memos to the game, and return it. */
+ game->temporary = temporary_game;
+ game->undo = undo_game;
+ game->memento = memo_create();
+ return game;
}
@@ -1554,44 +1503,43 @@ run_create (sc_read_callbackref_t callback, void *opaque)
* Return a game context to initial states to restart a game.
*/
static void
-run_restart_handler (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_gameref_t new_game;
- sc_var_setref_t new_vars;
-
- /*
- * Create a fresh set of variables from the current game properties,
- * then a new game using these variables and existing properties and
- * printfilter.
- */
- new_vars = var_create (bundle);
- new_game = gs_create (new_vars, bundle, filter);
- var_register_game (new_vars, new_game);
-
- /*
- * Overwrite the dynamic parts of the current game with the new one.
- */
- new_game->temporary = game->temporary;
- new_game->undo = game->undo;
- gs_copy (game, new_game);
-
- /* Destroy invalid game status strings. */
- sc_free (game->current_room_name);
- game->current_room_name = NULL;
- sc_free (game->status_line);
- game->status_line = NULL;
-
- /*
- * Now it's safely copied, destroy the temporary new game, and its
- * associated variable set.
- */
- gs_destroy (new_game);
- var_destroy (new_vars);
-
- /* Reset resources handling. */
- res_cancel_resources (game);
+run_restart_handler(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_gameref_t new_game;
+ sc_var_setref_t new_vars;
+
+ /*
+ * Create a fresh set of variables from the current game properties,
+ * then a new game using these variables and existing properties and
+ * printfilter.
+ */
+ new_vars = var_create(bundle);
+ new_game = gs_create(new_vars, bundle, filter);
+ var_register_game(new_vars, new_game);
+
+ /*
+ * Overwrite the dynamic parts of the current game with the new one.
+ */
+ new_game->temporary = game->temporary;
+ new_game->undo = game->undo;
+ gs_copy(game, new_game);
+
+ /* Destroy invalid game status strings. */
+ sc_free(game->current_room_name);
+ game->current_room_name = NULL;
+ sc_free(game->status_line);
+ game->status_line = NULL;
+
+ /*
+ * Now it's safely copied, destroy the temporary new game, and its
+ * associated variable set.
+ */
+ gs_destroy(new_game);
+ var_destroy(new_vars);
+
+ /* Reset resources handling. */
+ res_cancel_resources(game);
}
@@ -1601,20 +1549,19 @@ run_restart_handler (sc_gameref_t game)
* Adjust a game context for continuation after restoring a game.
*/
static void
-run_restore_handler (sc_gameref_t game)
-{
- /* Invalidate the undo buffer. */
- game->undo_available = FALSE;
-
- /*
- * Resources handling? Arguably we should re-offer resources active when
- * the game was saved, but I can't see how this can be achieved with Adrift
- * the way it is. Canceling is too broad, so I'll go here with just
- * stopping sounds (in case looping).
- *
- * TODO Rationalize what happens here.
- */
- game->stop_sound = TRUE;
+run_restore_handler(sc_gameref_t game) {
+ /* Invalidate the undo buffer. */
+ game->undo_available = FALSE;
+
+ /*
+ * Resources handling? Arguably we should re-offer resources active when
+ * the game was saved, but I can't see how this can be achieved with Adrift
+ * the way it is. Canceling is too broad, so I'll go here with just
+ * stopping sounds (in case looping).
+ *
+ * TODO Rationalize what happens here.
+ */
+ game->stop_sound = TRUE;
}
@@ -1624,25 +1571,24 @@ run_restore_handler (sc_gameref_t game)
* Tidy up printfilter and input statics on game quit.
*/
static void
-run_quit_handler (sc_gameref_t game)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
-
- /* Flush printfilter and notifications of any dangling output. */
- run_notify_score_change (game);
- pf_flush (filter, vars, bundle);
-
- /* Cancel any active resources. */
- res_cancel_resources (game);
-
- /*
- * Make the special call to reset all of the static variables inside
- * run_player_input().
- */
- assert (!game->is_running);
- run_player_input (game);
+run_quit_handler(sc_gameref_t game) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+
+ /* Flush printfilter and notifications of any dangling output. */
+ run_notify_score_change(game);
+ pf_flush(filter, vars, bundle);
+
+ /* Cancel any active resources. */
+ res_cancel_resources(game);
+
+ /*
+ * Make the special call to reset all of the static variables inside
+ * run_player_input().
+ */
+ assert(!game->is_running);
+ run_player_input(game);
}
@@ -1652,60 +1598,52 @@ run_quit_handler (sc_gameref_t game)
* Intepret the game in a game context.
*/
void
-run_interpret (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
-
- /* Verify the game is not already running, and is runnable. */
- if (game->is_running)
- {
- sc_error ("run_interpret: game is already running\n");
- return;
- }
- if (game->has_completed)
- {
- sc_error ("run_interpret: game has already completed\n");
- return;
- }
-
- /* Refuse to run a game with no rooms. */
- if (gs_room_count (game) == 0)
- {
- sc_error ("run_interpret: game contains no rooms\n");
- return;
- }
-
- /* Run the main interpreter loop until no more restarts. */
- game->is_running = TRUE;
- do
- {
- /* Run the game until some form of halt is requested. */
- if (setjmp (game->quitter) == 0)
- run_main_loop (game);
-
- /*
- * If the halt was a restart or restore, cancel the request, handle
- * restart or restore game adjustments, and set the game running
- * again.
- */
- if (game->do_restart)
- {
- game->do_restart = FALSE;
- run_restart_handler (game);
- game->is_running = TRUE;
- }
-
- if (game->do_restore)
- {
- game->do_restore = FALSE;
- run_restore_handler (game);
- game->is_running = TRUE;
- }
- }
- while (game->is_running);
-
- /* Tidy up the printfilter and input statics. */
- run_quit_handler (game);
+run_interpret(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
+
+ /* Verify the game is not already running, and is runnable. */
+ if (game->is_running) {
+ sc_error("run_interpret: game is already running\n");
+ return;
+ }
+ if (game->has_completed) {
+ sc_error("run_interpret: game has already completed\n");
+ return;
+ }
+
+ /* Refuse to run a game with no rooms. */
+ if (gs_room_count(game) == 0) {
+ sc_error("run_interpret: game contains no rooms\n");
+ return;
+ }
+
+ /* Run the main interpreter loop until no more restarts. */
+ game->is_running = TRUE;
+ do {
+ /* Run the game until some form of halt is requested. */
+ if (setjmp(game->quitter) == 0)
+ run_main_loop(game);
+
+ /*
+ * If the halt was a restart or restore, cancel the request, handle
+ * restart or restore game adjustments, and set the game running
+ * again.
+ */
+ if (game->do_restart) {
+ game->do_restart = FALSE;
+ run_restart_handler(game);
+ game->is_running = TRUE;
+ }
+
+ if (game->do_restore) {
+ game->do_restore = FALSE;
+ run_restore_handler(game);
+ game->is_running = TRUE;
+ }
+ } while (game->is_running);
+
+ /* Tidy up the printfilter and input statics. */
+ run_quit_handler(game);
}
@@ -1715,52 +1653,50 @@ run_interpret (sc_gameref_t game)
* Destroy a game context, and free all resources.
*/
void
-run_destroy (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
-
- /* Can't destroy the context of a running game. */
- if (game->is_running)
- {
- sc_error ("run_destroy: game is running, stop it first\n");
- return;
- }
-
- /*
- * Cancel any game state debugger -- this frees its resources. Only the
- * primary game may have acquired a debugger.
- */
- debug_set_enabled (game, FALSE);
- assert (!debug_get_enabled (game->temporary));
- assert (!debug_get_enabled (game->undo));
-
- /*
- * Destroy the game state, variables, properties bundle, memos, undo
- * buffers and their variables, and filter. The bundle and printfilter
- * are shared by the main game, the undo game, and the temporary game, so
- * destroy these only once! The main game has a memento, but it is not
- * visible to these other two games, neither of which have one.
- */
- assert (gs_get_bundle (game->temporary) == gs_get_bundle (game));
- assert (gs_get_filter (game->temporary) == gs_get_filter (game));
- assert (gs_get_vars (game->temporary) != gs_get_vars (game));
- assert (!gs_get_memento (game->temporary));
- var_destroy (gs_get_vars (game->temporary));
- gs_destroy (game->temporary);
-
- assert (gs_get_bundle (game->undo) == gs_get_bundle (game));
- assert (gs_get_filter (game->undo) == gs_get_filter (game));
- assert (gs_get_vars (game->undo) != gs_get_vars (game));
- assert (!gs_get_memento (game->undo));
- var_destroy (gs_get_vars (game->undo));
- gs_destroy (game->undo);
-
- prop_destroy (gs_get_bundle (game));
- pf_destroy (gs_get_filter (game));
- var_destroy (gs_get_vars (game));
- memo_destroy (gs_get_memento (game));
-
- gs_destroy (game);
+run_destroy(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
+
+ /* Can't destroy the context of a running game. */
+ if (game->is_running) {
+ sc_error("run_destroy: game is running, stop it first\n");
+ return;
+ }
+
+ /*
+ * Cancel any game state debugger -- this frees its resources. Only the
+ * primary game may have acquired a debugger.
+ */
+ debug_set_enabled(game, FALSE);
+ assert(!debug_get_enabled(game->temporary));
+ assert(!debug_get_enabled(game->undo));
+
+ /*
+ * Destroy the game state, variables, properties bundle, memos, undo
+ * buffers and their variables, and filter. The bundle and printfilter
+ * are shared by the main game, the undo game, and the temporary game, so
+ * destroy these only once! The main game has a memento, but it is not
+ * visible to these other two games, neither of which have one.
+ */
+ assert(gs_get_bundle(game->temporary) == gs_get_bundle(game));
+ assert(gs_get_filter(game->temporary) == gs_get_filter(game));
+ assert(gs_get_vars(game->temporary) != gs_get_vars(game));
+ assert(!gs_get_memento(game->temporary));
+ var_destroy(gs_get_vars(game->temporary));
+ gs_destroy(game->temporary);
+
+ assert(gs_get_bundle(game->undo) == gs_get_bundle(game));
+ assert(gs_get_filter(game->undo) == gs_get_filter(game));
+ assert(gs_get_vars(game->undo) != gs_get_vars(game));
+ assert(!gs_get_memento(game->undo));
+ var_destroy(gs_get_vars(game->undo));
+ gs_destroy(game->undo);
+
+ prop_destroy(gs_get_bundle(game));
+ pf_destroy(gs_get_filter(game));
+ var_destroy(gs_get_vars(game));
+ memo_destroy(gs_get_memento(game));
+
+ gs_destroy(game);
}
@@ -1771,21 +1707,19 @@ run_destroy (sc_gameref_t game)
* run_main_loop() returned, and so never returns to its caller.
*/
void
-run_quit (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
-
- /* Disallow quitting a non-running game. */
- if (!game->is_running)
- {
- sc_error ("run_quit: game is not running\n");
- return;
- }
-
- /* Exit the main loop with a longjump. */
- game->is_running = FALSE;
- longjmp (game->quitter, 1);
- sc_fatal ("run_quit: unable to quit cleanly\n");
+run_quit(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
+
+ /* Disallow quitting a non-running game. */
+ if (!game->is_running) {
+ sc_error("run_quit: game is not running\n");
+ return;
+ }
+
+ /* Exit the main loop with a longjump. */
+ game->is_running = FALSE;
+ longjmp(game->quitter, 1);
+ sc_fatal("run_quit: unable to quit cleanly\n");
}
@@ -1797,25 +1731,23 @@ run_quit (sc_gameref_t game)
* never returns to its caller. For stopped games, it returns.
*/
void
-run_restart (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
-
- /*
- * If the game is running, stop it, request a restart, and exit the main
- * loop with a longjump.
- */
- if (game->is_running)
- {
- game->is_running = FALSE;
- game->do_restart = TRUE;
- longjmp (game->quitter, 1);
- sc_fatal ("run_restart: unable to restart cleanly\n");
- }
-
- /* Restart locally, and ensure that the game remains stopped. */
- run_restart_handler (game);
- game->is_running = FALSE;
+run_restart(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
+
+ /*
+ * If the game is running, stop it, request a restart, and exit the main
+ * loop with a longjump.
+ */
+ if (game->is_running) {
+ game->is_running = FALSE;
+ game->do_restart = TRUE;
+ longjmp(game->quitter, 1);
+ sc_fatal("run_restart: unable to restart cleanly\n");
+ }
+
+ /* Restart locally, and ensure that the game remains stopped. */
+ run_restart_handler(game);
+ game->is_running = FALSE;
}
@@ -1826,20 +1758,18 @@ run_restart (sc_gameref_t game)
* Saves either a running or a stopped game.
*/
void
-run_save (sc_gameref_t game, sc_write_callbackref_t callback, void *opaque)
-{
- assert (gs_is_game_valid (game));
- assert (callback);
+run_save(sc_gameref_t game, sc_write_callbackref_t callback, void *opaque) {
+ assert(gs_is_game_valid(game));
+ assert(callback);
- ser_save_game (game, callback, opaque);
+ ser_save_game(game, callback, opaque);
}
sc_bool
-run_save_prompted (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
+run_save_prompted(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
- return ser_save_game_prompted (game);
+ return ser_save_game_prompted(game);
}
@@ -1855,56 +1785,51 @@ run_save_prompted (sc_gameref_t game)
* FALSE if restore failed.
*/
static sc_bool
-run_restore_common (sc_gameref_t game,
- sc_read_callbackref_t callback, void *opaque)
-{
- sc_bool is_running, status;
-
- /*
- * Save the game running flag, and call the restore appropriate for the
- * caller. The indication of a call from run_restore_prompted() is a
- * callback of NULL; callback cannot be NULL for run_restore() calls.
- */
- is_running = game->is_running;
- status = callback ? ser_load_game (game, callback, opaque)
- : ser_load_game_prompted (game);
- if (status)
- {
- /* Loading a game clears is_running -- restore it here. */
- game->is_running = is_running;
-
- /*
- * If the game is (was) running, set flags so that the interpreter
- * loop cycles, and exit the main loop with a longjump.
- */
- if (game->is_running)
- {
- game->is_running = FALSE;
- game->do_restore = TRUE;
- longjmp (game->quitter, 1);
- sc_fatal ("run_restore_common: unable to restart cleanly\n");
- }
- }
-
- /* Return TRUE on successful restore of a stopped game, FALSE on error. */
- return status;
+run_restore_common(sc_gameref_t game,
+ sc_read_callbackref_t callback, void *opaque) {
+ sc_bool is_running, status;
+
+ /*
+ * Save the game running flag, and call the restore appropriate for the
+ * caller. The indication of a call from run_restore_prompted() is a
+ * callback of NULL; callback cannot be NULL for run_restore() calls.
+ */
+ is_running = game->is_running;
+ status = callback ? ser_load_game(game, callback, opaque)
+ : ser_load_game_prompted(game);
+ if (status) {
+ /* Loading a game clears is_running -- restore it here. */
+ game->is_running = is_running;
+
+ /*
+ * If the game is (was) running, set flags so that the interpreter
+ * loop cycles, and exit the main loop with a longjump.
+ */
+ if (game->is_running) {
+ game->is_running = FALSE;
+ game->do_restore = TRUE;
+ longjmp(game->quitter, 1);
+ sc_fatal("run_restore_common: unable to restart cleanly\n");
+ }
+ }
+
+ /* Return TRUE on successful restore of a stopped game, FALSE on error. */
+ return status;
}
sc_bool
-run_restore (sc_gameref_t game, sc_read_callbackref_t callback, void *opaque)
-{
- assert (gs_is_game_valid (game));
- assert (callback);
+run_restore(sc_gameref_t game, sc_read_callbackref_t callback, void *opaque) {
+ assert(gs_is_game_valid(game));
+ assert(callback);
- return run_restore_common (game, callback, opaque);
+ return run_restore_common(game, callback, opaque);
}
sc_bool
-run_restore_prompted (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
+run_restore_prompted(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
- return run_restore_common (game, NULL, NULL);
+ return run_restore_common(game, NULL, NULL);
}
@@ -1915,58 +1840,54 @@ run_restore_prompted (sc_gameref_t game)
* successful undo, FALSE if no undo buffer is available.
*/
sc_bool
-run_undo (sc_gameref_t game)
-{
- const sc_memo_setref_t memento = gs_get_memento (game);
- sc_bool is_running;
- assert (gs_is_game_valid (game));
-
- /* Save the game's running state, so we can restore it later. */
- is_running = game->is_running;
-
- /* If there's an undo buffer available, restore it. */
- if (game->undo_available)
- {
- /* Restore the undo buffer, and then restore running flag. */
- gs_copy (game, game->undo);
- game->undo_available = FALSE;
- game->is_running = is_running;
-
- /* Location may have changed; update status. */
- run_update_status (game);
-
- /* Bring resources into line with the revised game. */
- res_sync_resources (game);
- return TRUE;
- }
-
- /*
- * If there is no undo buffer, try to restore one saved previously in a
- * memo. Handle as if restoring from a file.
- */
- if (memo_load_game (memento, game))
- {
- /* Loading a game clears is_running -- restore it here. */
- game->is_running = is_running;
-
- /*
- * If the game is (was) running, set flags so that the interpreter
- * loop cycles, and exit the main loop with a longjump.
- */
- if (game->is_running)
- {
- game->is_running = FALSE;
- game->do_restore = TRUE;
- longjmp (game->quitter, 1);
- sc_fatal ("run_undo: unable to restart cleanly\n");
- }
-
- /* Game undo on non-running game accomplished with memos. */
- return TRUE;
- }
-
- /* No undo buffer and no memos available. */
- return FALSE;
+run_undo(sc_gameref_t game) {
+ const sc_memo_setref_t memento = gs_get_memento(game);
+ sc_bool is_running;
+ assert(gs_is_game_valid(game));
+
+ /* Save the game's running state, so we can restore it later. */
+ is_running = game->is_running;
+
+ /* If there's an undo buffer available, restore it. */
+ if (game->undo_available) {
+ /* Restore the undo buffer, and then restore running flag. */
+ gs_copy(game, game->undo);
+ game->undo_available = FALSE;
+ game->is_running = is_running;
+
+ /* Location may have changed; update status. */
+ run_update_status(game);
+
+ /* Bring resources into line with the revised game. */
+ res_sync_resources(game);
+ return TRUE;
+ }
+
+ /*
+ * If there is no undo buffer, try to restore one saved previously in a
+ * memo. Handle as if restoring from a file.
+ */
+ if (memo_load_game(memento, game)) {
+ /* Loading a game clears is_running -- restore it here. */
+ game->is_running = is_running;
+
+ /*
+ * If the game is (was) running, set flags so that the interpreter
+ * loop cycles, and exit the main loop with a longjump.
+ */
+ if (game->is_running) {
+ game->is_running = FALSE;
+ game->do_restore = TRUE;
+ longjmp(game->quitter, 1);
+ sc_fatal("run_undo: unable to restart cleanly\n");
+ }
+
+ /* Game undo on non-running game accomplished with memos. */
+ return TRUE;
+ }
+
+ /* No undo buffer and no memos available. */
+ return FALSE;
}
@@ -1976,11 +1897,10 @@ run_undo (sc_gameref_t game)
* Query the game running state.
*/
sc_bool
-run_is_running (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
+run_is_running(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
- return game->is_running;
+ return game->is_running;
}
@@ -1991,11 +1911,10 @@ run_is_running (sc_gameref_t game)
* since they've run the exit task and thus have nowhere to go.
*/
sc_bool
-run_has_completed (sc_gameref_t game)
-{
- assert (gs_is_game_valid (game));
+run_has_completed(sc_gameref_t game) {
+ assert(gs_is_game_valid(game));
- return game->has_completed;
+ return game->has_completed;
}
@@ -2005,12 +1924,11 @@ run_has_completed (sc_gameref_t game)
* Query the game turn undo buffer and memo availability.
*/
sc_bool
-run_is_undo_available (sc_gameref_t game)
-{
- const sc_memo_setref_t memento = gs_get_memento (game);
- assert (gs_is_game_valid (game));
+run_is_undo_available(sc_gameref_t game) {
+ const sc_memo_setref_t memento = gs_get_memento(game);
+ assert(gs_is_game_valid(game));
- return game->undo_available || memo_is_load_available (memento);
+ return game->undo_available || memo_is_load_available(memento);
}
@@ -2021,110 +1939,99 @@ run_is_undo_available (sc_gameref_t game)
* Get and set selected game attributes.
*/
void
-run_get_attributes (sc_gameref_t game,
- const sc_char **game_name, const sc_char **game_author,
- const sc_char **game_compile_date,
- sc_int *turns, sc_int *score, sc_int *max_score,
- const sc_char **current_room_name,
- const sc_char **status_line, const sc_char **preferred_font,
- sc_bool *bold_room_names, sc_bool *verbose,
- sc_bool *notify_score_change)
-{
- 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[2];
- assert (gs_is_game_valid (game));
-
- /* Return the game name, author, and compile date if requested. */
- if (game_name)
- {
- if (!game->title)
- {
- const sc_char *gamename;
- sc_char *filtered;
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- gamename = prop_get_string (bundle, "S<-ss", vt_key);
-
- filtered = pf_filter_for_info (gamename, vars);
- pf_strip_tags (filtered);
- game->title = filtered;
- }
- *game_name = game->title;
- }
- if (game_author)
- {
- if (!game->author)
- {
- const sc_char *gameauthor;
- sc_char *filtered;
-
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameAuthor";
- gameauthor = prop_get_string (bundle, "S<-ss", vt_key);
-
- filtered = pf_filter_for_info (gameauthor, vars);
- pf_strip_tags (filtered);
- game->author = filtered;
- }
- *game_author = game->author;
- }
- if (game_compile_date)
- {
- vt_key[0].string = "CompileDate";
- *game_compile_date = prop_get_string (bundle, "S<-s", vt_key);
- }
-
- /* Return the current room name and status line if requested. */
- if (current_room_name)
- *current_room_name = game->current_room_name;
- if (status_line)
- *status_line = game->status_line;
-
- /* Return any game preferred font, or NULL if none. */
- if (preferred_font)
- {
- vt_key[0].string = "CustomFont";
- if (prop_get_boolean (bundle, "B<-s", vt_key))
- {
- vt_key[0].string = "FontNameSize";
- *preferred_font = prop_get_string (bundle, "S<-s", vt_key);
- }
- else
- *preferred_font = NULL;
- }
-
- /* Return any other selected game attributes. */
- if (turns)
- *turns = game->turns;
- if (score)
- *score = game->score;
- if (max_score)
- {
- vt_key[0].string = "Globals";
- vt_key[1].string = "MaxScore";
- *max_score = prop_get_integer (bundle, "I<-ss", vt_key);
- }
- if (bold_room_names)
- *bold_room_names = game->bold_room_names;
- if (verbose)
- *verbose = game->verbose;
- if (notify_score_change)
- *notify_score_change = game->notify_score_change;
+run_get_attributes(sc_gameref_t game,
+ const sc_char **game_name, const sc_char **game_author,
+ const sc_char **game_compile_date,
+ sc_int *turns, sc_int *score, sc_int *max_score,
+ const sc_char **current_room_name,
+ const sc_char **status_line, const sc_char **preferred_font,
+ sc_bool *bold_room_names, sc_bool *verbose,
+ sc_bool *notify_score_change) {
+ 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[2];
+ assert(gs_is_game_valid(game));
+
+ /* Return the game name, author, and compile date if requested. */
+ if (game_name) {
+ if (!game->title) {
+ const sc_char *gamename;
+ sc_char *filtered;
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ gamename = prop_get_string(bundle, "S<-ss", vt_key);
+
+ filtered = pf_filter_for_info(gamename, vars);
+ pf_strip_tags(filtered);
+ game->title = filtered;
+ }
+ *game_name = game->title;
+ }
+ if (game_author) {
+ if (!game->author) {
+ const sc_char *gameauthor;
+ sc_char *filtered;
+
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameAuthor";
+ gameauthor = prop_get_string(bundle, "S<-ss", vt_key);
+
+ filtered = pf_filter_for_info(gameauthor, vars);
+ pf_strip_tags(filtered);
+ game->author = filtered;
+ }
+ *game_author = game->author;
+ }
+ if (game_compile_date) {
+ vt_key[0].string = "CompileDate";
+ *game_compile_date = prop_get_string(bundle, "S<-s", vt_key);
+ }
+
+ /* Return the current room name and status line if requested. */
+ if (current_room_name)
+ *current_room_name = game->current_room_name;
+ if (status_line)
+ *status_line = game->status_line;
+
+ /* Return any game preferred font, or NULL if none. */
+ if (preferred_font) {
+ vt_key[0].string = "CustomFont";
+ if (prop_get_boolean(bundle, "B<-s", vt_key)) {
+ vt_key[0].string = "FontNameSize";
+ *preferred_font = prop_get_string(bundle, "S<-s", vt_key);
+ } else
+ *preferred_font = NULL;
+ }
+
+ /* Return any other selected game attributes. */
+ if (turns)
+ *turns = game->turns;
+ if (score)
+ *score = game->score;
+ if (max_score) {
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "MaxScore";
+ *max_score = prop_get_integer(bundle, "I<-ss", vt_key);
+ }
+ if (bold_room_names)
+ *bold_room_names = game->bold_room_names;
+ if (verbose)
+ *verbose = game->verbose;
+ if (notify_score_change)
+ *notify_score_change = game->notify_score_change;
}
void
-run_set_attributes (sc_gameref_t game,
- sc_bool bold_room_names, sc_bool verbose,
- sc_bool notify_score_change)
-{
- assert (gs_is_game_valid (game));
-
- /* Set game options. */
- game->bold_room_names = bold_room_names;
- game->verbose = verbose;
- game->notify_score_change = notify_score_change;
+run_set_attributes(sc_gameref_t game,
+ sc_bool bold_room_names, sc_bool verbose,
+ sc_bool notify_score_change) {
+ assert(gs_is_game_valid(game));
+
+ /* Set game options. */
+ game->bold_room_names = bold_room_names;
+ game->verbose = verbose;
+ game->notify_score_change = notify_score_change;
}
@@ -2138,40 +2045,36 @@ run_set_attributes (sc_gameref_t game,
* the client as a void*.
*/
sc_hintref_t
-run_hint_iterate (sc_gameref_t game, sc_hintref_t hint)
-{
- sc_int task;
- assert (gs_is_game_valid (game));
-
- /*
- * Hint is a pointer to a task state; convert to a task index, adding one
- * to move on to the next task, or start at the first task if null.
- */
- if (!hint)
- task = 0;
- else
- {
- /* Convert into pointer, and range check. */
- task = hint - game->tasks;
- if (task < 0 || task >= gs_task_count (game))
- {
- sc_error ("run_hint_iterate: invalid iteration hint\n");
- return NULL;
- }
-
- /* Advance beyond current task. */
- task++;
- }
-
- /* Scan for the next runnable task that offers a hint. */
- for (; task < gs_task_count (game); task++)
- {
- if (task_can_run_task (game, task) && task_has_hints (game, task))
- break;
- }
-
- /* Return a pointer to the state of the task identified, or NULL. */
- return task < gs_task_count (game) ? game->tasks + task : NULL;
+run_hint_iterate(sc_gameref_t game, sc_hintref_t hint) {
+ sc_int task;
+ assert(gs_is_game_valid(game));
+
+ /*
+ * Hint is a pointer to a task state; convert to a task index, adding one
+ * to move on to the next task, or start at the first task if null.
+ */
+ if (!hint)
+ task = 0;
+ else {
+ /* Convert into pointer, and range check. */
+ task = hint - game->tasks;
+ if (task < 0 || task >= gs_task_count(game)) {
+ sc_error("run_hint_iterate: invalid iteration hint\n");
+ return NULL;
+ }
+
+ /* Advance beyond current task. */
+ task++;
+ }
+
+ /* Scan for the next runnable task that offers a hint. */
+ for (; task < gs_task_count(game); task++) {
+ if (task_can_run_task(game, task) && task_has_hints(game, task))
+ break;
+ }
+
+ /* Return a pointer to the state of the task identified, or NULL. */
+ return task < gs_task_count(game) ? game->tasks + task : NULL;
}
@@ -2189,66 +2092,56 @@ run_hint_iterate (sc_gameref_t game, sc_hintref_t hint)
* Hint strings are NULL if empty (not defined by the game).
*/
static const sc_char *
-run_get_hint_common (sc_gameref_t game, sc_hintref_t hint,
- const sc_char *(*handler) (sc_gameref_t, sc_int))
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int task;
- const sc_char *string;
- assert (gs_is_game_valid (game));
-
- /* Verify the caller passed in a valid hint. */
- task = hint - game->tasks;
- if (task < 0 || task >= gs_task_count (game))
- {
- sc_error ("run_get_hint_common: invalid iteration hint\n");
- return NULL;
- }
- else if (!task_has_hints (game, task))
- {
- sc_error ("run_get_hint_common: task has no hint\n");
- return NULL;
- }
-
- /* Get the required game text by calling the given handler function. */
- string = handler (game, task);
- if (!sc_strempty (string))
- {
- sc_char *filtered;
-
- /* Filter and strip tags, note in game. */
- filtered = pf_filter (string, vars, bundle);
- pf_strip_tags_for_hints (filtered);
- sc_free (game->hint_text);
- game->hint_text = filtered;
- }
- else
- {
- /* Hint text is empty; drop any text noted in game. */
- sc_free (game->hint_text);
- game->hint_text = NULL;
- }
-
- return game->hint_text;
+run_get_hint_common(sc_gameref_t game, sc_hintref_t hint,
+ const sc_char * (*handler)(sc_gameref_t, sc_int)) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int task;
+ const sc_char *string;
+ assert(gs_is_game_valid(game));
+
+ /* Verify the caller passed in a valid hint. */
+ task = hint - game->tasks;
+ if (task < 0 || task >= gs_task_count(game)) {
+ sc_error("run_get_hint_common: invalid iteration hint\n");
+ return NULL;
+ } else if (!task_has_hints(game, task)) {
+ sc_error("run_get_hint_common: task has no hint\n");
+ return NULL;
+ }
+
+ /* Get the required game text by calling the given handler function. */
+ string = handler(game, task);
+ if (!sc_strempty(string)) {
+ sc_char *filtered;
+
+ /* Filter and strip tags, note in game. */
+ filtered = pf_filter(string, vars, bundle);
+ pf_strip_tags_for_hints(filtered);
+ sc_free(game->hint_text);
+ game->hint_text = filtered;
+ } else {
+ /* Hint text is empty; drop any text noted in game. */
+ sc_free(game->hint_text);
+ game->hint_text = NULL;
+ }
+
+ return game->hint_text;
}
const sc_char *
-run_get_hint_question (sc_gameref_t game, sc_hintref_t hint)
-{
- return run_get_hint_common (game, hint, task_get_hint_question);
+run_get_hint_question(sc_gameref_t game, sc_hintref_t hint) {
+ return run_get_hint_common(game, hint, task_get_hint_question);
}
const sc_char *
-run_get_subtle_hint (sc_gameref_t game, sc_hintref_t hint)
-{
- return run_get_hint_common (game, hint, task_get_hint_subtle);
+run_get_subtle_hint(sc_gameref_t game, sc_hintref_t hint) {
+ return run_get_hint_common(game, hint, task_get_hint_subtle);
}
const sc_char *
-run_get_unsubtle_hint (sc_gameref_t game, sc_hintref_t hint)
-{
- return run_get_hint_common (game, hint, task_get_hint_unsubtle);
+run_get_unsubtle_hint(sc_gameref_t game, sc_hintref_t hint) {
+ return run_get_hint_common(game, hint, task_get_hint_unsubtle);
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scserial.cpp b/engines/glk/adrift/scserial.cpp
index 3ade8ac124..9c41db25b4 100644
--- a/engines/glk/adrift/scserial.cpp
+++ b/engines/glk/adrift/scserial.cpp
@@ -50,156 +50,145 @@ static void *ser_opaque = NULL;
*
* Flush pending buffer contents; add a character to the buffer.
*/
-static void ser_flush (sc_bool is_final)
-{
+static void ser_flush(sc_bool is_final) {
error("TODO");
#ifdef TODO
- static sc_bool initialized = FALSE;
- static sc_byte *out_buffer = NULL;
- static sc_int out_buffer_size = 0;
- static z_stream stream;
-
- sc_int status;
-
- /* If this is an initial call, initialize deflation. */
- if (!initialized)
- {
- /* Allocate an initial output buffer. */
- out_buffer_size = BUFFER_SIZE;
- out_buffer = sc_malloc (out_buffer_size);
-
- /* Initialize Zlib deflation functions. */
- stream.next_out = out_buffer;
- stream.avail_out = out_buffer_size;
- stream.next_in = ser_buffer;
- stream.avail_in = 0;
-
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
-
- status = deflateInit (&stream, Z_DEFAULT_COMPRESSION);
- if (status != Z_OK)
- {
- sc_error ("ser_flush: deflateInit: error %ld\n", status);
- ser_buffer_length = 0;
-
- sc_free (out_buffer);
- out_buffer = NULL;
- out_buffer_size = 0;
- return;
- }
-
- initialized = TRUE;
- }
-
- /* Deflate data from the current output buffer. */
- stream.next_in = ser_buffer;
- stream.avail_in = ser_buffer_length;
-
- /* Loop while deflate output is pending and buffer not emptied. */
- while (TRUE)
- {
- sc_int in_bytes, out_bytes;
-
- /* Compress stream data, with finish if this is the final flush. */
- if (is_final)
- status = deflate (&stream, Z_FINISH);
- else
- status = deflate (&stream, Z_NO_FLUSH);
- if (status != Z_STREAM_END && status != Z_OK)
- {
- sc_error ("ser_flush: deflate: error %ld\n", status);
- ser_buffer_length = 0;
-
- sc_free (out_buffer);
- out_buffer = NULL;
- out_buffer_size = 0;
- initialized = FALSE;
- return;
- }
-
- /* Calculate bytes used, and output. */
- in_bytes = ser_buffer_length - stream.avail_in;
- out_bytes = out_buffer_size - stream.avail_out;
-
- /* See if compressed data is available. */
- if (out_bytes > 0)
- {
- /* Write it to save file output through the callback. */
- ser_callback (ser_opaque, out_buffer, out_bytes);
-
- /* Reset deflation stream for available space. */
- stream.next_out = out_buffer;
- stream.avail_out = out_buffer_size;
- }
-
- /* Remove consumed data from the input buffer. */
- if (in_bytes > 0)
- {
- /* Move any unused data, and reduce length. */
- memmove (ser_buffer,
- ser_buffer + in_bytes, ser_buffer_length - in_bytes);
- ser_buffer_length -= in_bytes;
-
- /* Reset deflation stream for consumed data. */
- stream.next_in = ser_buffer;
- stream.avail_in = ser_buffer_length;
- }
-
- /* If final flush, wait until deflate indicates finished. */
- if (is_final && status == Z_OK)
- continue;
-
- /* If data was consumed or produced, break. */
- if (out_bytes > 0 || in_bytes > 0)
- break;
- }
-
- /* If this was a final call, clean up. */
- if (is_final)
- {
- /* Compression completed. */
- status = deflateEnd (&stream);
- if (status != Z_OK)
- sc_error ("ser_flush: warning: deflateEnd: error %ld\n", status);
-
- if (ser_buffer_length != 0)
- {
- sc_error ("ser_flush: warning: deflate missed data\n");
- ser_buffer_length = 0;
- }
-
- /* Free the allocated compression buffer. */
- sc_free (ser_buffer);
- ser_buffer = NULL;
-
- /*
- * Free output buffer, and reset flag for reinitialization on the next
- * call.
- */
- sc_free (out_buffer);
- out_buffer = NULL;
- out_buffer_size = 0;
- initialized = FALSE;
- }
+ static sc_bool initialized = FALSE;
+ static sc_byte *out_buffer = NULL;
+ static sc_int out_buffer_size = 0;
+ static z_stream stream;
+
+ sc_int status;
+
+ /* If this is an initial call, initialize deflation. */
+ if (!initialized) {
+ /* Allocate an initial output buffer. */
+ out_buffer_size = BUFFER_SIZE;
+ out_buffer = sc_malloc(out_buffer_size);
+
+ /* Initialize Zlib deflation functions. */
+ stream.next_out = out_buffer;
+ stream.avail_out = out_buffer_size;
+ stream.next_in = ser_buffer;
+ stream.avail_in = 0;
+
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ status = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
+ if (status != Z_OK) {
+ sc_error("ser_flush: deflateInit: error %ld\n", status);
+ ser_buffer_length = 0;
+
+ sc_free(out_buffer);
+ out_buffer = NULL;
+ out_buffer_size = 0;
+ return;
+ }
+
+ initialized = TRUE;
+ }
+
+ /* Deflate data from the current output buffer. */
+ stream.next_in = ser_buffer;
+ stream.avail_in = ser_buffer_length;
+
+ /* Loop while deflate output is pending and buffer not emptied. */
+ while (TRUE) {
+ sc_int in_bytes, out_bytes;
+
+ /* Compress stream data, with finish if this is the final flush. */
+ if (is_final)
+ status = deflate(&stream, Z_FINISH);
+ else
+ status = deflate(&stream, Z_NO_FLUSH);
+ if (status != Z_STREAM_END && status != Z_OK) {
+ sc_error("ser_flush: deflate: error %ld\n", status);
+ ser_buffer_length = 0;
+
+ sc_free(out_buffer);
+ out_buffer = NULL;
+ out_buffer_size = 0;
+ initialized = FALSE;
+ return;
+ }
+
+ /* Calculate bytes used, and output. */
+ in_bytes = ser_buffer_length - stream.avail_in;
+ out_bytes = out_buffer_size - stream.avail_out;
+
+ /* See if compressed data is available. */
+ if (out_bytes > 0) {
+ /* Write it to save file output through the callback. */
+ ser_callback(ser_opaque, out_buffer, out_bytes);
+
+ /* Reset deflation stream for available space. */
+ stream.next_out = out_buffer;
+ stream.avail_out = out_buffer_size;
+ }
+
+ /* Remove consumed data from the input buffer. */
+ if (in_bytes > 0) {
+ /* Move any unused data, and reduce length. */
+ memmove(ser_buffer,
+ ser_buffer + in_bytes, ser_buffer_length - in_bytes);
+ ser_buffer_length -= in_bytes;
+
+ /* Reset deflation stream for consumed data. */
+ stream.next_in = ser_buffer;
+ stream.avail_in = ser_buffer_length;
+ }
+
+ /* If final flush, wait until deflate indicates finished. */
+ if (is_final && status == Z_OK)
+ continue;
+
+ /* If data was consumed or produced, break. */
+ if (out_bytes > 0 || in_bytes > 0)
+ break;
+ }
+
+ /* If this was a final call, clean up. */
+ if (is_final) {
+ /* Compression completed. */
+ status = deflateEnd(&stream);
+ if (status != Z_OK)
+ sc_error("ser_flush: warning: deflateEnd: error %ld\n", status);
+
+ if (ser_buffer_length != 0) {
+ sc_error("ser_flush: warning: deflate missed data\n");
+ ser_buffer_length = 0;
+ }
+
+ /* Free the allocated compression buffer. */
+ sc_free(ser_buffer);
+ ser_buffer = NULL;
+
+ /*
+ * Free output buffer, and reset flag for reinitialization on the next
+ * call.
+ */
+ sc_free(out_buffer);
+ out_buffer = NULL;
+ out_buffer_size = 0;
+ initialized = FALSE;
+ }
#endif
}
static void
-ser_buffer_character (sc_char character)
-{
- /* Allocate the buffer if not yet done. */
- if (!ser_buffer)
- {
- assert (ser_buffer_length == 0);
- ser_buffer = (sc_byte *)sc_malloc (BUFFER_SIZE);
- }
-
- /* Add to the buffer, with intermediate flush if filled. */
- ser_buffer[ser_buffer_length++] = character;
- if (ser_buffer_length == BUFFER_SIZE)
- ser_flush (FALSE);
+ser_buffer_character(sc_char character) {
+ /* Allocate the buffer if not yet done. */
+ if (!ser_buffer) {
+ assert(ser_buffer_length == 0);
+ ser_buffer = (sc_byte *)sc_malloc(BUFFER_SIZE);
+ }
+
+ /* Add to the buffer, with intermediate flush if filled. */
+ ser_buffer[ser_buffer_length++] = character;
+ if (ser_buffer_length == BUFFER_SIZE)
+ ser_flush(FALSE);
}
@@ -214,59 +203,53 @@ ser_buffer_character (sc_char character)
* Buffer a buffer, a string, an unsigned and signed integer, and a boolean.
*/
static void
-ser_buffer_buffer (const sc_char *buffer, sc_int length)
-{
- sc_int index_;
+ser_buffer_buffer(const sc_char *buffer, sc_int length) {
+ sc_int index_;
- /* Add each character to the buffer. */
- for (index_ = 0; index_ < length; index_++)
- ser_buffer_character (buffer[index_]);
+ /* Add each character to the buffer. */
+ for (index_ = 0; index_ < length; index_++)
+ ser_buffer_character(buffer[index_]);
}
static void
-ser_buffer_string (const sc_char *string)
-{
- /* Buffer string, followed by DOS style end-of-line. */
- ser_buffer_buffer (string, strlen (string));
- ser_buffer_character (CARRIAGE_RETURN);
- ser_buffer_character (NEWLINE);
+ser_buffer_string(const sc_char *string) {
+ /* Buffer string, followed by DOS style end-of-line. */
+ ser_buffer_buffer(string, strlen(string));
+ ser_buffer_character(CARRIAGE_RETURN);
+ ser_buffer_character(NEWLINE);
}
static void
-ser_buffer_int (sc_int value)
-{
- sc_char buffer[32];
+ser_buffer_int(sc_int value) {
+ sc_char buffer[32];
- /* Convert to a string and buffer that. */
- sprintf (buffer, "%ld", value);
- ser_buffer_string (buffer);
+ /* Convert to a string and buffer that. */
+ sprintf(buffer, "%ld", value);
+ ser_buffer_string(buffer);
}
static void
-ser_buffer_int_special (sc_int value)
-{
- sc_char buffer[32];
+ser_buffer_int_special(sc_int value) {
+ sc_char buffer[32];
- /* Weirdo formatting for compatibility. */
- sprintf (buffer, "% ld ", value);
- ser_buffer_string (buffer);
+ /* Weirdo formatting for compatibility. */
+ sprintf(buffer, "% ld ", value);
+ ser_buffer_string(buffer);
}
static void
-ser_buffer_uint (sc_uint value)
-{
- sc_char buffer[32];
+ser_buffer_uint(sc_uint value) {
+ sc_char buffer[32];
- /* Convert to a string and buffer that. */
- sprintf (buffer, "%lu", value);
- ser_buffer_string (buffer);
+ /* Convert to a string and buffer that. */
+ sprintf(buffer, "%lu", value);
+ ser_buffer_string(buffer);
}
static void
-ser_buffer_boolean (sc_bool boolean)
-{
- /* Write a 1 for TRUE, 0 for FALSE. */
- ser_buffer_string (boolean ? "1" : "0");
+ser_buffer_boolean(sc_bool boolean) {
+ /* Write a 1 for TRUE, 0 for FALSE. */
+ ser_buffer_string(boolean ? "1" : "0");
}
@@ -276,165 +259,156 @@ ser_buffer_boolean (sc_bool boolean)
* Serialize a game and save its state using the given callback and opaque.
*/
void
-ser_save_game (sc_gameref_t game,
- sc_write_callbackref_t callback, void *opaque)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int index_, var_count;
- assert (callback);
-
- /* Store the callback and opaque references, for writer functions. */
- ser_callback = callback;
- ser_opaque = opaque;
-
- /* Write the game name. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- ser_buffer_string (prop_get_string (bundle, "S<-ss", vt_key));
-
- /* Write the counts of rooms, objects, etc. */
- ser_buffer_int (gs_room_count (game));
- ser_buffer_int (gs_object_count (game));
- ser_buffer_int (gs_task_count (game));
- ser_buffer_int (gs_event_count (game));
- ser_buffer_int (gs_npc_count (game));
-
- /* Write the score and player information. */
- ser_buffer_int (game->score);
- ser_buffer_int (gs_playerroom (game) + 1);
- ser_buffer_int (gs_playerparent (game));
- ser_buffer_int (gs_playerposition (game));
-
- /* Write player gender. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "PlayerGender";
- ser_buffer_int (prop_get_integer (bundle, "I<-ss", vt_key));
-
- /*
- * Write encumbrance details. The player limits are constant for a given
- * game, and can be extracted from properties. The current sizes and
- * weights can also be recalculated from held objects, so we don't maintain
- * them in the game. We can write constants here, then, and ignore
- * the values on restoring. Note however that if the Adrift Runner is
- * relying on these values, this may give it problems with one of our saved
- * games.
- */
- ser_buffer_int (90);
- ser_buffer_int (0);
- ser_buffer_int (90);
- ser_buffer_int (0);
-
- /* Save rooms information. */
- for (index_ = 0; index_ < gs_room_count (game); index_++)
- ser_buffer_boolean (gs_room_seen (game, index_));
-
- /* Save objects information. */
- for (index_ = 0; index_ < gs_object_count (game); index_++)
- {
- ser_buffer_int (gs_object_position (game, index_));
- ser_buffer_boolean (gs_object_seen (game, index_));
- ser_buffer_int (gs_object_parent (game, index_));
- if (gs_object_openness (game, index_) != 0)
- ser_buffer_int (gs_object_openness (game, index_));
-
- if (gs_object_state (game, index_) != 0)
- ser_buffer_int (gs_object_state (game, index_));
-
- ser_buffer_boolean (gs_object_unmoved (game, index_));
- }
-
- /* Save tasks information. */
- for (index_ = 0; index_ < gs_task_count (game); index_++)
- {
- ser_buffer_boolean (gs_task_done (game, index_));
- ser_buffer_boolean (gs_task_scored (game, index_));
- }
-
- /* Save events information. */
- for (index_ = 0; index_ < gs_event_count (game); index_++)
- {
- sc_int startertype, task;
-
- /* Get starter task, if any. */
- vt_key[0].string = "Events";
- vt_key[1].integer = index_;
- vt_key[2].string = "StarterType";
- startertype = prop_get_integer (bundle, "I<-sis", vt_key);
- if (startertype == 3)
- {
- vt_key[2].string = "TaskNum";
- task = prop_get_integer (bundle, "I<-sis", vt_key);
- }
- else
- task = 0;
-
- /* Save event details. */
- ser_buffer_int (gs_event_time (game, index_));
- ser_buffer_int (task);
- ser_buffer_int (gs_event_state (game, index_) - 1);
- if (task > 0)
- ser_buffer_boolean (gs_task_done (game, task - 1));
- else
- ser_buffer_boolean (FALSE);
- }
-
- /* Save NPCs information. */
- for (index_ = 0; index_ < gs_npc_count (game); index_++)
- {
- sc_int walk;
-
- ser_buffer_int (gs_npc_location (game, index_));
- ser_buffer_boolean (gs_npc_seen (game, index_));
- for (walk = 0; walk < gs_npc_walkstep_count (game, index_); walk++)
- ser_buffer_int_special (gs_npc_walkstep (game, index_, walk));
- }
-
- /* Save each variable. */
- vt_key[0].string = "Variables";
- var_count = prop_get_child_count (bundle, "I<-s", vt_key);
-
- for (index_ = 0; index_ < var_count; index_++)
- {
- const sc_char *name;
- sc_int var_type;
-
- vt_key[1].integer = index_;
-
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Type";
- var_type = prop_get_integer (bundle, "I<-sis", vt_key);
-
- switch (var_type)
- {
- case TAFVAR_NUMERIC:
- ser_buffer_int (var_get_integer (vars, name));
- break;
-
- case TAFVAR_STRING:
- ser_buffer_string (var_get_string (vars, name));
- break;
-
- default:
- sc_fatal ("ser_save_game: unknown variable type, %ld\n", var_type);
- }
- }
-
- /* Save timing information. */
- ser_buffer_uint (var_get_elapsed_seconds (vars));
-
- /* Save turns count. */
- ser_buffer_uint ((sc_uint) game->turns);
-
- /*
- * Flush the last buffer contents, and drop the callback and opaque
- * references.
- */
- ser_flush (TRUE);
- ser_callback = NULL;
- ser_opaque = NULL;
+ser_save_game(sc_gameref_t game,
+ sc_write_callbackref_t callback, void *opaque) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int index_, var_count;
+ assert(callback);
+
+ /* Store the callback and opaque references, for writer functions. */
+ ser_callback = callback;
+ ser_opaque = opaque;
+
+ /* Write the game name. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ ser_buffer_string(prop_get_string(bundle, "S<-ss", vt_key));
+
+ /* Write the counts of rooms, objects, etc. */
+ ser_buffer_int(gs_room_count(game));
+ ser_buffer_int(gs_object_count(game));
+ ser_buffer_int(gs_task_count(game));
+ ser_buffer_int(gs_event_count(game));
+ ser_buffer_int(gs_npc_count(game));
+
+ /* Write the score and player information. */
+ ser_buffer_int(game->score);
+ ser_buffer_int(gs_playerroom(game) + 1);
+ ser_buffer_int(gs_playerparent(game));
+ ser_buffer_int(gs_playerposition(game));
+
+ /* Write player gender. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "PlayerGender";
+ ser_buffer_int(prop_get_integer(bundle, "I<-ss", vt_key));
+
+ /*
+ * Write encumbrance details. The player limits are constant for a given
+ * game, and can be extracted from properties. The current sizes and
+ * weights can also be recalculated from held objects, so we don't maintain
+ * them in the game. We can write constants here, then, and ignore
+ * the values on restoring. Note however that if the Adrift Runner is
+ * relying on these values, this may give it problems with one of our saved
+ * games.
+ */
+ ser_buffer_int(90);
+ ser_buffer_int(0);
+ ser_buffer_int(90);
+ ser_buffer_int(0);
+
+ /* Save rooms information. */
+ for (index_ = 0; index_ < gs_room_count(game); index_++)
+ ser_buffer_boolean(gs_room_seen(game, index_));
+
+ /* Save objects information. */
+ for (index_ = 0; index_ < gs_object_count(game); index_++) {
+ ser_buffer_int(gs_object_position(game, index_));
+ ser_buffer_boolean(gs_object_seen(game, index_));
+ ser_buffer_int(gs_object_parent(game, index_));
+ if (gs_object_openness(game, index_) != 0)
+ ser_buffer_int(gs_object_openness(game, index_));
+
+ if (gs_object_state(game, index_) != 0)
+ ser_buffer_int(gs_object_state(game, index_));
+
+ ser_buffer_boolean(gs_object_unmoved(game, index_));
+ }
+
+ /* Save tasks information. */
+ for (index_ = 0; index_ < gs_task_count(game); index_++) {
+ ser_buffer_boolean(gs_task_done(game, index_));
+ ser_buffer_boolean(gs_task_scored(game, index_));
+ }
+
+ /* Save events information. */
+ for (index_ = 0; index_ < gs_event_count(game); index_++) {
+ sc_int startertype, task;
+
+ /* Get starter task, if any. */
+ vt_key[0].string = "Events";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "StarterType";
+ startertype = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (startertype == 3) {
+ vt_key[2].string = "TaskNum";
+ task = prop_get_integer(bundle, "I<-sis", vt_key);
+ } else
+ task = 0;
+
+ /* Save event details. */
+ ser_buffer_int(gs_event_time(game, index_));
+ ser_buffer_int(task);
+ ser_buffer_int(gs_event_state(game, index_) - 1);
+ if (task > 0)
+ ser_buffer_boolean(gs_task_done(game, task - 1));
+ else
+ ser_buffer_boolean(FALSE);
+ }
+
+ /* Save NPCs information. */
+ for (index_ = 0; index_ < gs_npc_count(game); index_++) {
+ sc_int walk;
+
+ ser_buffer_int(gs_npc_location(game, index_));
+ ser_buffer_boolean(gs_npc_seen(game, index_));
+ for (walk = 0; walk < gs_npc_walkstep_count(game, index_); walk++)
+ ser_buffer_int_special(gs_npc_walkstep(game, index_, walk));
+ }
+
+ /* Save each variable. */
+ vt_key[0].string = "Variables";
+ var_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ for (index_ = 0; index_ < var_count; index_++) {
+ const sc_char *name;
+ sc_int var_type;
+
+ vt_key[1].integer = index_;
+
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Type";
+ var_type = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ switch (var_type) {
+ case TAFVAR_NUMERIC:
+ ser_buffer_int(var_get_integer(vars, name));
+ break;
+
+ case TAFVAR_STRING:
+ ser_buffer_string(var_get_string(vars, name));
+ break;
+
+ default:
+ sc_fatal("ser_save_game: unknown variable type, %ld\n", var_type);
+ }
+ }
+
+ /* Save timing information. */
+ ser_buffer_uint(var_get_elapsed_seconds(vars));
+
+ /* Save turns count. */
+ ser_buffer_uint((sc_uint) game->turns);
+
+ /*
+ * Flush the last buffer contents, and drop the callback and opaque
+ * references.
+ */
+ ser_flush(TRUE);
+ ser_callback = NULL;
+ ser_opaque = NULL;
}
@@ -445,23 +419,21 @@ ser_save_game (sc_gameref_t game,
* the user.
*/
sc_bool
-ser_save_game_prompted (sc_gameref_t game)
-{
- void *opaque;
-
- /*
- * Open an output stream, and if successful, save a game using the opaque
- * value returned.
- */
- opaque = if_open_saved_game (TRUE);
- if (opaque)
- {
- ser_save_game (game, if_write_saved_game, opaque);
- if_close_saved_game (opaque);
- return TRUE;
- }
-
- return FALSE;
+ser_save_game_prompted(sc_gameref_t game) {
+ void *opaque;
+
+ /*
+ * Open an output stream, and if successful, save a game using the opaque
+ * value returned.
+ */
+ opaque = if_open_saved_game(TRUE);
+ if (opaque) {
+ ser_save_game(game, if_write_saved_game, opaque);
+ if_close_saved_game(opaque);
+ return TRUE;
+ }
+
+ return FALSE;
}
@@ -482,82 +454,73 @@ static jmp_buf ser_tas_error;
* the line content into an appropriate type.
*/
static const sc_char *
-ser_get_string (void)
-{
- const sc_char *string;
-
- /* Get the next line, and complain if absent. */
- string = taf_next_line (ser_tas);
- if (!string)
- {
- sc_error ("ser_get_string: out of TAS data at line %ld\n", ser_tasline);
- longjmp (ser_tas_error, 1);
- }
-
- ser_tasline++;
- return string;
+ser_get_string(void) {
+ const sc_char *string;
+
+ /* Get the next line, and complain if absent. */
+ string = taf_next_line(ser_tas);
+ if (!string) {
+ sc_error("ser_get_string: out of TAS data at line %ld\n", ser_tasline);
+ longjmp(ser_tas_error, 1);
+ }
+
+ ser_tasline++;
+ return string;
}
static sc_int
-ser_get_int (void)
-{
- const sc_char *string;
- sc_int value;
-
- /* Get line, and scan for a single integer; return it. */
- string = ser_get_string ();
- if (sscanf (string, "%ld", &value) != 1)
- {
- sc_error ("ser_get_int:"
- " invalid integer at line %ld\n", ser_tasline - 1);
- longjmp (ser_tas_error, 1);
- }
-
- return value;
+ser_get_int(void) {
+ const sc_char *string;
+ sc_int value;
+
+ /* Get line, and scan for a single integer; return it. */
+ string = ser_get_string();
+ if (sscanf(string, "%ld", &value) != 1) {
+ sc_error("ser_get_int:"
+ " invalid integer at line %ld\n", ser_tasline - 1);
+ longjmp(ser_tas_error, 1);
+ }
+
+ return value;
}
static sc_uint
-ser_get_uint (void)
-{
- const sc_char *string;
- sc_uint value;
-
- /* Get line, and scan for a single integer; return it. */
- string = ser_get_string ();
- if (sscanf (string, "%lu", &value) != 1)
- {
- sc_error ("ser_get_uint:"
- " invalid integer at line %ld\n", ser_tasline - 1);
- longjmp (ser_tas_error, 1);
- }
-
- return value;
+ser_get_uint(void) {
+ const sc_char *string;
+ sc_uint value;
+
+ /* Get line, and scan for a single integer; return it. */
+ string = ser_get_string();
+ if (sscanf(string, "%lu", &value) != 1) {
+ sc_error("ser_get_uint:"
+ " invalid integer at line %ld\n", ser_tasline - 1);
+ longjmp(ser_tas_error, 1);
+ }
+
+ return value;
}
static sc_bool
-ser_get_boolean (void)
-{
- const sc_char *string;
- sc_uint value;
-
- /*
- * Get line, and scan for a single integer; check it's a valid-looking flag,
- * and return it.
- */
- string = ser_get_string ();
- if (sscanf (string, "%lu", &value) != 1)
- {
- sc_error ("ser_get_boolean:"
- " invalid boolean at line %ld\n", ser_tasline - 1);
- longjmp (ser_tas_error, 1);
- }
- if (value != 0 && value != 1)
- {
- sc_error ("ser_get_boolean:"
- " warning: suspect boolean at line %ld\n", ser_tasline - 1);
- }
-
- return value != 0;
+ser_get_boolean(void) {
+ const sc_char *string;
+ sc_uint value;
+
+ /*
+ * Get line, and scan for a single integer; check it's a valid-looking flag,
+ * and return it.
+ */
+ string = ser_get_string();
+ if (sscanf(string, "%lu", &value) != 1) {
+ sc_error("ser_get_boolean:"
+ " invalid boolean at line %ld\n", ser_tasline - 1);
+ longjmp(ser_tas_error, 1);
+ }
+ if (value != 0 && value != 1) {
+ sc_error("ser_get_boolean:"
+ " warning: suspect boolean at line %ld\n", ser_tasline - 1);
+ }
+
+ return value != 0;
}
@@ -568,229 +531,219 @@ ser_get_boolean (void)
* callback() function.
*/
sc_bool
-ser_load_game (sc_gameref_t game,
- sc_read_callbackref_t callback, void *opaque)
-{
- static sc_var_setref_t new_vars; /* For setjmp safety */
- static sc_gameref_t new_game; /* For setjmp safety */
-
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int index_, var_count;
- const sc_char *gamename;
-
- /* Create a TAF (TAS) reference from callbacks, for reader functions. */
- ser_tas = taf_create_tas (callback, opaque);
- if (!ser_tas)
- return FALSE;
-
- /* Reset line counter for error messages. */
- ser_tasline = 1;
-
- new_game = NULL;
- new_vars = NULL;
-
- /* Set up error handling jump buffer, and handle errors. */
- if (setjmp (ser_tas_error) != 0)
- {
- /* Destroy any temporary game and variables. */
- if (new_game)
- gs_destroy (new_game);
- if (new_vars)
- var_destroy (new_vars);
-
- /* Destroy the TAF (TAS) file and return fail status. */
- taf_destroy (ser_tas);
- ser_tas = NULL;
- return FALSE;
- }
-
- /*
- * Read the game name, and compare with the one in the game. Fail if
- * they don't match exactly. A tighter check than this would perhaps be
- * preferable, say, something based on the TAF file header, but this isn't
- * in the save file format.
- */
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- gamename = prop_get_string (bundle, "S<-ss", vt_key);
- if (strcmp (ser_get_string (), gamename) != 0)
- longjmp (ser_tas_error, 1);
-
- /* Read and verify the counts in the saved game. */
- if (ser_get_int () != gs_room_count (game)
- || ser_get_int () != gs_object_count (game)
- || ser_get_int () != gs_task_count (game)
- || ser_get_int () != gs_event_count (game)
- || ser_get_int () != gs_npc_count (game))
- longjmp (ser_tas_error, 1);
-
- /* Create a variables set and game to restore into. */
- new_vars = var_create (bundle);
- new_game = gs_create (new_vars, bundle, filter);
- var_register_game (new_vars, new_game);
-
- /* All set to load TAF (TAS) data into the new game. */
-
- /* Restore the score and player information. */
- new_game->score = ser_get_int ();
- gs_set_playerroom (new_game, ser_get_int () - 1);
- gs_set_playerparent (new_game, ser_get_int ());
- gs_set_playerposition (new_game, ser_get_int ());
-
- /* Skip player gender. */
- (void) ser_get_int ();
-
- /* Skip encumbrance details, not currently maintained by the game. */
- (void) ser_get_int ();
- (void) ser_get_int ();
- (void) ser_get_int ();
- (void) ser_get_int ();
-
- /* Restore rooms information. */
- for (index_ = 0; index_ < gs_room_count (new_game); index_++)
- gs_set_room_seen (new_game, index_, ser_get_boolean ());
-
- /* Restore objects information. */
- for (index_ = 0; index_ < gs_object_count (new_game); index_++)
- {
- sc_int openable, currentstate;
-
- /* Bypass mutators for position and parent. Fix later? */
- new_game->objects[index_].position = ser_get_int ();
- gs_set_object_seen (new_game, index_, ser_get_boolean ());
- new_game->objects[index_].parent = ser_get_int ();
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = index_;
- vt_key[2].string = "Openable";
- openable = prop_get_integer (bundle, "I<-sis", vt_key);
- gs_set_object_openness (new_game, index_,
- openable != 0 ? ser_get_int () : 0);
-
- vt_key[2].string = "CurrentState";
- currentstate = prop_get_integer (bundle, "I<-sis", vt_key);
- gs_set_object_state (new_game, index_,
- currentstate != 0 ? ser_get_int () : 0);
-
- gs_set_object_unmoved (new_game, index_, ser_get_boolean ());
- }
-
- /* Restore tasks information. */
- for (index_ = 0; index_ < gs_task_count (new_game); index_++)
- {
- gs_set_task_done (new_game, index_, ser_get_boolean ());
- gs_set_task_scored (new_game, index_, ser_get_boolean ());
- }
-
- /* Restore events information. */
- for (index_ = 0; index_ < gs_event_count (new_game); index_++)
- {
- sc_int startertype, task;
-
- /* Restore first event details. */
- gs_set_event_time (new_game, index_, ser_get_int ());
- task = ser_get_int ();
- gs_set_event_state (new_game, index_, ser_get_int () + 1);
-
- /* Verify and restore the starter task, if any. */
- if (task > 0)
- {
- vt_key[0].string = "Events";
- vt_key[1].integer = index_;
- vt_key[2].string = "StarterType";
- startertype = prop_get_integer (bundle, "I<-sis", vt_key);
- if (startertype != 3)
- longjmp (ser_tas_error, 1);
-
- /* Restore task state. */
- gs_set_task_done (new_game, task - 1, ser_get_boolean ());
- }
- else
- (void) ser_get_boolean ();
- }
-
- /* Restore NPCs information. */
- for (index_ = 0; index_ < gs_npc_count (new_game); index_++)
- {
- sc_int walk;
-
- gs_set_npc_location (new_game, index_, ser_get_int ());
- gs_set_npc_seen (new_game, index_, ser_get_boolean ());
- for (walk = 0; walk < gs_npc_walkstep_count (new_game, index_); walk++)
- gs_set_npc_walkstep (new_game, index_, walk, ser_get_int ());
- }
-
- /* Restore each variable. */
- vt_key[0].string = "Variables";
- var_count = prop_get_child_count (bundle, "I<-s", vt_key);
-
- for (index_ = 0; index_ < var_count; index_++)
- {
- const sc_char *name;
- sc_int var_type;
-
- vt_key[1].integer = index_;
-
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- vt_key[2].string = "Type";
- var_type = prop_get_integer (bundle, "I<-sis", vt_key);
-
- switch (var_type)
- {
- case TAFVAR_NUMERIC:
- var_put_integer (new_vars, name, ser_get_int ());
- break;
-
- case TAFVAR_STRING:
- var_put_string (new_vars, name, ser_get_string ());
- break;
-
- default:
- sc_fatal ("ser_load_game: unknown variable type, %ld\n", var_type);
- }
- }
-
- /* Restore timing information. */
- var_set_elapsed_seconds (new_vars, ser_get_uint ());
-
- /* Restore turns count. */
- new_game->turns = (sc_int) ser_get_uint ();
-
- /*
- * Resources tweak -- set requested to match those in the current game
- * so that they remain unchanged by the gs_copy() of new_game onto
- * game. This way, both the requested and the active resources in the
- * game are unchanged by restore.
- */
- new_game->requested_sound = game->requested_sound;
- new_game->requested_graphic = game->requested_graphic;
-
- /*
- * Quitter tweak -- set the quit jump buffer in the new game to be the
- * same as the current one, so that it remains unchanged by gs_copy(). The
- * one in the new game is still the unset one from gs_create().
- */
- memcpy (&new_game->quitter, &game->quitter, sizeof (game->quitter));
-
- /*
- * If we got this far, we successfully restored the game from the file.
- * As our final act, copy the new game onto the old one.
- */
- new_game->temporary = game->temporary;
- new_game->undo = game->undo;
- gs_copy (game, new_game);
-
- /* Done with the temporary game and variables. */
- gs_destroy (new_game);
- var_destroy (new_vars);
-
- /* Done with TAF (TAS) file; destroy it and return successfully. */
- taf_destroy (ser_tas);
- ser_tas = NULL;
- return TRUE;
+ser_load_game(sc_gameref_t game,
+ sc_read_callbackref_t callback, void *opaque) {
+ static sc_var_setref_t new_vars; /* For setjmp safety */
+ static sc_gameref_t new_game; /* For setjmp safety */
+
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int index_, var_count;
+ const sc_char *gamename;
+
+ /* Create a TAF (TAS) reference from callbacks, for reader functions. */
+ ser_tas = taf_create_tas(callback, opaque);
+ if (!ser_tas)
+ return FALSE;
+
+ /* Reset line counter for error messages. */
+ ser_tasline = 1;
+
+ new_game = NULL;
+ new_vars = NULL;
+
+ /* Set up error handling jump buffer, and handle errors. */
+ if (setjmp(ser_tas_error) != 0) {
+ /* Destroy any temporary game and variables. */
+ if (new_game)
+ gs_destroy(new_game);
+ if (new_vars)
+ var_destroy(new_vars);
+
+ /* Destroy the TAF (TAS) file and return fail status. */
+ taf_destroy(ser_tas);
+ ser_tas = NULL;
+ return FALSE;
+ }
+
+ /*
+ * Read the game name, and compare with the one in the game. Fail if
+ * they don't match exactly. A tighter check than this would perhaps be
+ * preferable, say, something based on the TAF file header, but this isn't
+ * in the save file format.
+ */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ gamename = prop_get_string(bundle, "S<-ss", vt_key);
+ if (strcmp(ser_get_string(), gamename) != 0)
+ longjmp(ser_tas_error, 1);
+
+ /* Read and verify the counts in the saved game. */
+ if (ser_get_int() != gs_room_count(game)
+ || ser_get_int() != gs_object_count(game)
+ || ser_get_int() != gs_task_count(game)
+ || ser_get_int() != gs_event_count(game)
+ || ser_get_int() != gs_npc_count(game))
+ longjmp(ser_tas_error, 1);
+
+ /* Create a variables set and game to restore into. */
+ new_vars = var_create(bundle);
+ new_game = gs_create(new_vars, bundle, filter);
+ var_register_game(new_vars, new_game);
+
+ /* All set to load TAF (TAS) data into the new game. */
+
+ /* Restore the score and player information. */
+ new_game->score = ser_get_int();
+ gs_set_playerroom(new_game, ser_get_int() - 1);
+ gs_set_playerparent(new_game, ser_get_int());
+ gs_set_playerposition(new_game, ser_get_int());
+
+ /* Skip player gender. */
+ (void) ser_get_int();
+
+ /* Skip encumbrance details, not currently maintained by the game. */
+ (void) ser_get_int();
+ (void) ser_get_int();
+ (void) ser_get_int();
+ (void) ser_get_int();
+
+ /* Restore rooms information. */
+ for (index_ = 0; index_ < gs_room_count(new_game); index_++)
+ gs_set_room_seen(new_game, index_, ser_get_boolean());
+
+ /* Restore objects information. */
+ for (index_ = 0; index_ < gs_object_count(new_game); index_++) {
+ sc_int openable, currentstate;
+
+ /* Bypass mutators for position and parent. Fix later? */
+ new_game->objects[index_].position = ser_get_int();
+ gs_set_object_seen(new_game, index_, ser_get_boolean());
+ new_game->objects[index_].parent = ser_get_int();
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "Openable";
+ openable = prop_get_integer(bundle, "I<-sis", vt_key);
+ gs_set_object_openness(new_game, index_,
+ openable != 0 ? ser_get_int() : 0);
+
+ vt_key[2].string = "CurrentState";
+ currentstate = prop_get_integer(bundle, "I<-sis", vt_key);
+ gs_set_object_state(new_game, index_,
+ currentstate != 0 ? ser_get_int() : 0);
+
+ gs_set_object_unmoved(new_game, index_, ser_get_boolean());
+ }
+
+ /* Restore tasks information. */
+ for (index_ = 0; index_ < gs_task_count(new_game); index_++) {
+ gs_set_task_done(new_game, index_, ser_get_boolean());
+ gs_set_task_scored(new_game, index_, ser_get_boolean());
+ }
+
+ /* Restore events information. */
+ for (index_ = 0; index_ < gs_event_count(new_game); index_++) {
+ sc_int startertype, task;
+
+ /* Restore first event details. */
+ gs_set_event_time(new_game, index_, ser_get_int());
+ task = ser_get_int();
+ gs_set_event_state(new_game, index_, ser_get_int() + 1);
+
+ /* Verify and restore the starter task, if any. */
+ if (task > 0) {
+ vt_key[0].string = "Events";
+ vt_key[1].integer = index_;
+ vt_key[2].string = "StarterType";
+ startertype = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (startertype != 3)
+ longjmp(ser_tas_error, 1);
+
+ /* Restore task state. */
+ gs_set_task_done(new_game, task - 1, ser_get_boolean());
+ } else
+ (void) ser_get_boolean();
+ }
+
+ /* Restore NPCs information. */
+ for (index_ = 0; index_ < gs_npc_count(new_game); index_++) {
+ sc_int walk;
+
+ gs_set_npc_location(new_game, index_, ser_get_int());
+ gs_set_npc_seen(new_game, index_, ser_get_boolean());
+ for (walk = 0; walk < gs_npc_walkstep_count(new_game, index_); walk++)
+ gs_set_npc_walkstep(new_game, index_, walk, ser_get_int());
+ }
+
+ /* Restore each variable. */
+ vt_key[0].string = "Variables";
+ var_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ for (index_ = 0; index_ < var_count; index_++) {
+ const sc_char *name;
+ sc_int var_type;
+
+ vt_key[1].integer = index_;
+
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ vt_key[2].string = "Type";
+ var_type = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ switch (var_type) {
+ case TAFVAR_NUMERIC:
+ var_put_integer(new_vars, name, ser_get_int());
+ break;
+
+ case TAFVAR_STRING:
+ var_put_string(new_vars, name, ser_get_string());
+ break;
+
+ default:
+ sc_fatal("ser_load_game: unknown variable type, %ld\n", var_type);
+ }
+ }
+
+ /* Restore timing information. */
+ var_set_elapsed_seconds(new_vars, ser_get_uint());
+
+ /* Restore turns count. */
+ new_game->turns = (sc_int) ser_get_uint();
+
+ /*
+ * Resources tweak -- set requested to match those in the current game
+ * so that they remain unchanged by the gs_copy() of new_game onto
+ * game. This way, both the requested and the active resources in the
+ * game are unchanged by restore.
+ */
+ new_game->requested_sound = game->requested_sound;
+ new_game->requested_graphic = game->requested_graphic;
+
+ /*
+ * Quitter tweak -- set the quit jump buffer in the new game to be the
+ * same as the current one, so that it remains unchanged by gs_copy(). The
+ * one in the new game is still the unset one from gs_create().
+ */
+ memcpy(&new_game->quitter, &game->quitter, sizeof(game->quitter));
+
+ /*
+ * If we got this far, we successfully restored the game from the file.
+ * As our final act, copy the new game onto the old one.
+ */
+ new_game->temporary = game->temporary;
+ new_game->undo = game->undo;
+ gs_copy(game, new_game);
+
+ /* Done with the temporary game and variables. */
+ gs_destroy(new_game);
+ var_destroy(new_vars);
+
+ /* Done with TAF (TAS) file; destroy it and return successfully. */
+ taf_destroy(ser_tas);
+ ser_tas = NULL;
+ return TRUE;
}
@@ -801,25 +754,23 @@ ser_load_game (sc_gameref_t game,
* stream from the user.
*/
sc_bool
-ser_load_game_prompted (sc_gameref_t game)
-{
- void *opaque;
-
- /*
- * Open an input stream, and if successful, try to load a game using
- * the opaque value returned and the saved game callback.
- */
- opaque = if_open_saved_game (FALSE);
- if (opaque)
- {
- sc_bool status;
-
- status = ser_load_game (game, if_read_saved_game, opaque);
- if_close_saved_game (opaque);
- return status;
- }
-
- return FALSE;
+ser_load_game_prompted(sc_gameref_t game) {
+ void *opaque;
+
+ /*
+ * Open an input stream, and if successful, try to load a game using
+ * the opaque value returned and the saved game callback.
+ */
+ opaque = if_open_saved_game(FALSE);
+ if (opaque) {
+ sc_bool status;
+
+ status = ser_load_game(game, if_read_saved_game, opaque);
+ if_close_saved_game(opaque);
+ return status;
+ }
+
+ return FALSE;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sctaffil.cpp b/engines/glk/adrift/sctaffil.cpp
index c8a25edaeb..f365a7fa46 100644
--- a/engines/glk/adrift/sctaffil.cpp
+++ b/engines/glk/adrift/sctaffil.cpp
@@ -27,15 +27,15 @@
#include "common/memstream.h"
#if defined(USE_ZLIB)
- #ifdef __SYMBIAN32__
- #include <zlib\zlib.h>
- #else
- #include <zlib.h>
- #endif
-
- #if ZLIB_VERNUM < 0x1204
- #error Version 1.2.0.4 or newer of zlib is required for this code
- #endif
+#ifdef __SYMBIAN32__
+#include <zlib\zlib.h>
+#else
+#include <zlib.h>
+#endif
+
+#if ZLIB_VERNUM < 0x1204
+#error Version 1.2.0.4 or newer of zlib is required for this code
+#endif
#endif
namespace Glk {
@@ -49,14 +49,14 @@ namespace Adrift {
/* Assorted definitions and constants. */
static const sc_uint TAF_MAGIC = 0x5bdcfa41;
-enum
-{ VERSION_HEADER_SIZE = 14,
- V400_HEADER_EXTRA = 8
+enum {
+ VERSION_HEADER_SIZE = 14,
+ V400_HEADER_EXTRA = 8
};
-enum
-{ OUT_BUFFER_SIZE = 31744,
- IN_BUFFER_SIZE = 16384,
- GROW_INCREMENT = 8
+enum {
+ OUT_BUFFER_SIZE = 31744,
+ IN_BUFFER_SIZE = 16384,
+ GROW_INCREMENT = 8
};
static const sc_char NEWLINE = '\n';
static const sc_char CARRIAGE_RETURN = '\r';
@@ -64,17 +64,20 @@ static const sc_char NUL = '\0';
/* Version 4.0, version 3.9, and version 3.8 TAF file signatures. */
static const sc_byte
- V400_SIGNATURE[VERSION_HEADER_SIZE] = {0x3c, 0x42, 0x3f, 0xc9, 0x6a, 0x87,
- 0xc2, 0xcf, 0x93, 0x45, 0x3e, 0x61,
- 0x39, 0xfa};
+V400_SIGNATURE[VERSION_HEADER_SIZE] = {0x3c, 0x42, 0x3f, 0xc9, 0x6a, 0x87,
+ 0xc2, 0xcf, 0x93, 0x45, 0x3e, 0x61,
+ 0x39, 0xfa
+ };
static const sc_byte
- V390_SIGNATURE[VERSION_HEADER_SIZE] = {0x3c, 0x42, 0x3f, 0xc9, 0x6a, 0x87,
- 0xc2, 0xcf, 0x94, 0x45, 0x37, 0x61,
- 0x39, 0xfa};
+V390_SIGNATURE[VERSION_HEADER_SIZE] = {0x3c, 0x42, 0x3f, 0xc9, 0x6a, 0x87,
+ 0xc2, 0xcf, 0x94, 0x45, 0x37, 0x61,
+ 0x39, 0xfa
+ };
static const sc_byte
- V380_SIGNATURE[VERSION_HEADER_SIZE] = {0x3c, 0x42, 0x3f, 0xc9, 0x6a, 0x87,
- 0xc2, 0xcf, 0x94, 0x45, 0x36, 0x61,
- 0x39, 0xfa};
+V380_SIGNATURE[VERSION_HEADER_SIZE] = {0x3c, 0x42, 0x3f, 0xc9, 0x6a, 0x87,
+ 0xc2, 0xcf, 0x94, 0x45, 0x36, 0x61,
+ 0x39, 0xfa
+ };
/*
* Game TAF data structure. The game structure contains the original TAF
@@ -87,22 +90,21 @@ static const sc_byte
* header. So for files of this type, the header is all zeroes.
*/
struct sc_slabdesc_t {
- sc_byte *data;
- sc_int size;
+ sc_byte *data;
+ sc_int size;
};
typedef sc_slabdesc_t *sc_slabdescref_t;
-typedef struct sc_taf_s
-{
- sc_uint magic;
- sc_byte header[VERSION_HEADER_SIZE + V400_HEADER_EXTRA];
- sc_int version;
- sc_int total_in_bytes;
- sc_slabdescref_t slabs;
- sc_int slab_count;
- sc_int slabs_allocated;
- sc_bool is_unterminated;
- sc_int current_slab;
- sc_int current_offset;
+typedef struct sc_taf_s {
+ sc_uint magic;
+ sc_byte header[VERSION_HEADER_SIZE + V400_HEADER_EXTRA];
+ sc_int version;
+ sc_int total_in_bytes;
+ sc_slabdescref_t slabs;
+ sc_int slab_count;
+ sc_int slabs_allocated;
+ sc_bool is_unterminated;
+ sc_int current_slab;
+ sc_int current_offset;
} sc_taf_t;
@@ -124,18 +126,16 @@ static sc_int taf_random_state = 0x00a09e86;
* range 0..254. Thanks to Rik Snel for uncovering this obfuscation.
*/
static sc_byte
-taf_random (void)
-{
- /* Generate and return the next pseudo-random number. */
- taf_random_state = (taf_random_state * PRNG_CST1 + PRNG_CST2) & PRNG_CST3;
- return (UCHAR_MAX * (sc_uint) taf_random_state) / (sc_uint) (PRNG_CST3 + 1);
+taf_random(void) {
+ /* Generate and return the next pseudo-random number. */
+ taf_random_state = (taf_random_state * PRNG_CST1 + PRNG_CST2) & PRNG_CST3;
+ return (UCHAR_MAX * (sc_uint) taf_random_state) / (sc_uint)(PRNG_CST3 + 1);
}
static void
-taf_random_reset (void)
-{
- /* Reset PRNG to initial conditions. */
- taf_random_state = PRNG_INITIAL_STATE;
+taf_random_reset(void) {
+ /* Reset PRNG to initial conditions. */
+ taf_random_state = PRNG_INITIAL_STATE;
}
@@ -145,9 +145,8 @@ taf_random_reset (void)
* Return TRUE if pointer is a valid TAF structure, FALSE otherwise.
*/
static sc_bool
-taf_is_valid (sc_tafref_t taf)
-{
- return taf && taf->magic == TAF_MAGIC;
+taf_is_valid(sc_tafref_t taf) {
+ return taf && taf->magic == TAF_MAGIC;
}
@@ -157,25 +156,24 @@ taf_is_valid (sc_tafref_t taf)
* Allocate and return a new, empty TAF structure.
*/
static sc_tafref_t
-taf_create_empty (void)
-{
- sc_tafref_t taf;
-
- /* Create an empty TAF structure. */
- taf = (sc_tafref_t)sc_malloc(sizeof (*taf));
- taf->magic = TAF_MAGIC;
- memset (taf->header, 0, sizeof (taf->header));
- taf->version = TAF_VERSION_NONE;
- taf->total_in_bytes = 0;
- taf->slabs = NULL;
- taf->slab_count = 0;
- taf->slabs_allocated = 0;
- taf->is_unterminated = FALSE;
- taf->current_slab = 0;
- taf->current_offset = 0;
-
- /* Return the new TAF structure. */
- return taf;
+taf_create_empty(void) {
+ sc_tafref_t taf;
+
+ /* Create an empty TAF structure. */
+ taf = (sc_tafref_t)sc_malloc(sizeof(*taf));
+ taf->magic = TAF_MAGIC;
+ memset(taf->header, 0, sizeof(taf->header));
+ taf->version = TAF_VERSION_NONE;
+ taf->total_in_bytes = 0;
+ taf->slabs = NULL;
+ taf->slab_count = 0;
+ taf->slabs_allocated = 0;
+ taf->is_unterminated = FALSE;
+ taf->current_slab = 0;
+ taf->current_offset = 0;
+
+ /* Return the new TAF structure. */
+ return taf;
}
@@ -185,22 +183,21 @@ taf_create_empty (void)
* Free TAF memory, and destroy a TAF structure.
*/
void
-taf_destroy (sc_tafref_t taf)
-{
- sc_int index_;
- assert (taf_is_valid (taf));
-
- /* First free each slab in the slabs array,... */
- for (index_ = 0; index_ < taf->slab_count; index_++)
- sc_free (taf->slabs[index_].data);
-
- /*
- * ...then free slabs growable array, and poison and free the TAF structure
- * itself.
- */
- sc_free (taf->slabs);
- memset (taf, 0xaa, sizeof (*taf));
- sc_free (taf);
+taf_destroy(sc_tafref_t taf) {
+ sc_int index_;
+ assert(taf_is_valid(taf));
+
+ /* First free each slab in the slabs array,... */
+ for (index_ = 0; index_ < taf->slab_count; index_++)
+ sc_free(taf->slabs[index_].data);
+
+ /*
+ * ...then free slabs growable array, and poison and free the TAF structure
+ * itself.
+ */
+ sc_free(taf->slabs);
+ memset(taf, 0xaa, sizeof(*taf));
+ sc_free(taf);
}
@@ -211,37 +208,32 @@ taf_destroy (sc_tafref_t taf)
* strings. Nul's are used to replace carriage return and newline pairs.
*/
static void
-taf_finalize_last_slab (sc_tafref_t taf)
-{
- sc_slabdescref_t slab;
- sc_int index_;
-
- /* Locate the final slab in the slab descriptors array. */
- assert (taf->slab_count > 0);
- slab = taf->slabs + taf->slab_count - 1;
-
- /*
- * Replace carriage return and newline pairs with nuls, and individual
- * carriage returns with a single newline.
- */
- for (index_ = 0; index_ < slab->size; index_++)
- {
- if (slab->data[index_] == CARRIAGE_RETURN)
- {
- if (index_ < slab->size - 1 && slab->data[index_ + 1] == NEWLINE)
- {
- slab->data[index_] = NUL;
- slab->data[index_ + 1] = NUL;
- index_++;
- }
- else
- slab->data[index_] = NEWLINE;
- }
-
- /* Also protect against unlikely incoming nul characters. */
- else if (slab->data[index_] == NUL)
- slab->data[index_] = NEWLINE;
- }
+taf_finalize_last_slab(sc_tafref_t taf) {
+ sc_slabdescref_t slab;
+ sc_int index_;
+
+ /* Locate the final slab in the slab descriptors array. */
+ assert(taf->slab_count > 0);
+ slab = taf->slabs + taf->slab_count - 1;
+
+ /*
+ * Replace carriage return and newline pairs with nuls, and individual
+ * carriage returns with a single newline.
+ */
+ for (index_ = 0; index_ < slab->size; index_++) {
+ if (slab->data[index_] == CARRIAGE_RETURN) {
+ if (index_ < slab->size - 1 && slab->data[index_ + 1] == NEWLINE) {
+ slab->data[index_] = NUL;
+ slab->data[index_ + 1] = NUL;
+ index_++;
+ } else
+ slab->data[index_] = NEWLINE;
+ }
+
+ /* Also protect against unlikely incoming nul characters. */
+ else if (slab->data[index_] == NUL)
+ slab->data[index_] = NEWLINE;
+ }
}
@@ -253,26 +245,23 @@ taf_finalize_last_slab (sc_tafref_t taf)
* Otherwise, return the count of usable bytes found in the buffer.
*/
static sc_int
-taf_find_buffer_extent (const sc_byte *buffer,
- sc_int length, sc_bool *is_unterminated)
-{
- sc_int bytes;
-
- /* Search backwards from the buffer end for the final line feed. */
- for (bytes = length; bytes > 1; bytes--)
- {
- if (buffer[bytes - 2] == CARRIAGE_RETURN && buffer[bytes - 1] == NEWLINE)
- break;
- }
- if (bytes < 2)
- {
- /* No carriage return and newline termination found. */
- *is_unterminated = TRUE;
- return length;
- }
-
- *is_unterminated = FALSE;
- return bytes;
+taf_find_buffer_extent(const sc_byte *buffer,
+ sc_int length, sc_bool *is_unterminated) {
+ sc_int bytes;
+
+ /* Search backwards from the buffer end for the final line feed. */
+ for (bytes = length; bytes > 1; bytes--) {
+ if (buffer[bytes - 2] == CARRIAGE_RETURN && buffer[bytes - 1] == NEWLINE)
+ break;
+ }
+ if (bytes < 2) {
+ /* No carriage return and newline termination found. */
+ *is_unterminated = TRUE;
+ return length;
+ }
+
+ *is_unterminated = FALSE;
+ return bytes;
}
@@ -283,75 +272,70 @@ taf_find_buffer_extent (const sc_byte *buffer,
* number of characters consumed from the buffer.
*/
static sc_int
-taf_append_buffer (sc_tafref_t taf, const sc_byte *buffer, sc_int length)
-{
- sc_int bytes;
- sc_bool is_unterminated;
-
- /* Locate the extent of appendable data in the buffer. */
- bytes = taf_find_buffer_extent (buffer, length, &is_unterminated);
-
- /* See if the last buffer handled contained at least one data line. */
- if (!taf->is_unterminated)
- {
- sc_slabdescref_t slab;
-
- /* Extend the slabs array if we've reached the current allocation. */
- if (taf->slab_count == taf->slabs_allocated)
- {
- taf->slabs_allocated += GROW_INCREMENT;
- taf->slabs = (sc_slabdescref_t)sc_realloc (taf->slabs,
- taf->slabs_allocated * sizeof (*taf->slabs));
- }
-
- /* Advance to the next unused slab in the slab descriptors array. */
- slab = taf->slabs + taf->slab_count;
- taf->slab_count++;
-
- /* Copy the input buffer into the new slab. */
- slab->data = (sc_byte *)sc_malloc (bytes);
- memcpy (slab->data, buffer, bytes);
- slab->size = bytes;
- }
- else
- {
- sc_slabdescref_t slab;
-
- /* Locate the final slab in the slab descriptors array. */
- assert (taf->slab_count > 0);
- slab = taf->slabs + taf->slab_count - 1;
-
- /*
- * The last buffer we saw had no line endings in it. In this case,
- * append the input buffer to the end of the last slab's data, rather
- * than creating a new slab. This may cause allocation to overflow
- * the system limits on single allocated areas on some platforms.
- */
- slab->data = (sc_byte *)sc_realloc(slab->data, slab->size + bytes);
- memcpy (slab->data + slab->size, buffer, bytes);
- slab->size += bytes;
-
- /*
- * Use a special case for the final carriage return and newline pairing
- * that are split over two buffers; force correct termination of this
- * slab.
- */
- if (slab->size > 1
- && slab->data[slab->size - 2] == CARRIAGE_RETURN
- && slab->data[slab->size - 1] == NEWLINE)
- is_unterminated = FALSE;
- }
-
- /*
- * Note if this buffer requires that the next be coalesced with it. If it
- * doesn't, finalize the last slab by breaking it into separate lines.
- */
- taf->is_unterminated = is_unterminated;
- if (!is_unterminated)
- taf_finalize_last_slab (taf);
-
- /* Return count of buffer bytes consumed. */
- return bytes;
+taf_append_buffer(sc_tafref_t taf, const sc_byte *buffer, sc_int length) {
+ sc_int bytes;
+ sc_bool is_unterminated;
+
+ /* Locate the extent of appendable data in the buffer. */
+ bytes = taf_find_buffer_extent(buffer, length, &is_unterminated);
+
+ /* See if the last buffer handled contained at least one data line. */
+ if (!taf->is_unterminated) {
+ sc_slabdescref_t slab;
+
+ /* Extend the slabs array if we've reached the current allocation. */
+ if (taf->slab_count == taf->slabs_allocated) {
+ taf->slabs_allocated += GROW_INCREMENT;
+ taf->slabs = (sc_slabdescref_t)sc_realloc(taf->slabs,
+ taf->slabs_allocated * sizeof(*taf->slabs));
+ }
+
+ /* Advance to the next unused slab in the slab descriptors array. */
+ slab = taf->slabs + taf->slab_count;
+ taf->slab_count++;
+
+ /* Copy the input buffer into the new slab. */
+ slab->data = (sc_byte *)sc_malloc(bytes);
+ memcpy(slab->data, buffer, bytes);
+ slab->size = bytes;
+ } else {
+ sc_slabdescref_t slab;
+
+ /* Locate the final slab in the slab descriptors array. */
+ assert(taf->slab_count > 0);
+ slab = taf->slabs + taf->slab_count - 1;
+
+ /*
+ * The last buffer we saw had no line endings in it. In this case,
+ * append the input buffer to the end of the last slab's data, rather
+ * than creating a new slab. This may cause allocation to overflow
+ * the system limits on single allocated areas on some platforms.
+ */
+ slab->data = (sc_byte *)sc_realloc(slab->data, slab->size + bytes);
+ memcpy(slab->data + slab->size, buffer, bytes);
+ slab->size += bytes;
+
+ /*
+ * Use a special case for the final carriage return and newline pairing
+ * that are split over two buffers; force correct termination of this
+ * slab.
+ */
+ if (slab->size > 1
+ && slab->data[slab->size - 2] == CARRIAGE_RETURN
+ && slab->data[slab->size - 1] == NEWLINE)
+ is_unterminated = FALSE;
+ }
+
+ /*
+ * Note if this buffer requires that the next be coalesced with it. If it
+ * doesn't, finalize the last slab by breaking it into separate lines.
+ */
+ taf->is_unterminated = is_unterminated;
+ if (!is_unterminated)
+ taf_finalize_last_slab(taf);
+
+ /* Return count of buffer bytes consumed. */
+ return bytes;
}
@@ -364,80 +348,75 @@ taf_append_buffer (sc_tafref_t taf, const sc_byte *buffer, sc_int length)
* Assumes that the file has been read past the header.
*/
static sc_bool
-taf_unobfuscate (sc_tafref_t taf, sc_read_callbackref_t callback,
- void *opaque, sc_bool is_gamefile)
-{
- sc_byte *buffer;
- sc_int bytes, used_bytes, total_bytes, index_;
-
- /* Reset the PRNG, and synchronize with the header already read. */
- taf_random_reset ();
- for (index_ = 0; index_ < VERSION_HEADER_SIZE; index_++)
- taf_random ();
-
- /*
- * Malloc buffer, done to help systems with limited stacks, and initialize
- * count of bytes read and used in the buffer to zero.
- */
- buffer = (sc_byte *)sc_malloc (IN_BUFFER_SIZE);
- used_bytes = 0;
- total_bytes = 0;
-
- /* Unobfuscate in buffer sized chunks. */
- do
- {
- /* Try to obtain more data. */
- bytes = callback (opaque,
- buffer + used_bytes, IN_BUFFER_SIZE - used_bytes);
-
- /* Unobfuscate data read in. */
- for (index_ = 0; index_ < bytes; index_++)
- buffer[used_bytes + index_] ^= taf_random ();
-
- /*
- * Add data read in and unobfuscated to buffer used data, and if
- * unobfuscated data is available, add it to the TAF.
- */
- used_bytes += bytes;
- if (used_bytes > 0)
- {
- sc_int consumed;
-
- /* Add lines from this buffer to the TAF. */
- consumed = taf_append_buffer (taf, buffer, used_bytes);
-
- /* Move unused buffer data to buffer start. */
- memmove (buffer, buffer + consumed, IN_BUFFER_SIZE - consumed);
-
- /* Note counts of bytes consumed and remaining in the buffer. */
- used_bytes -= consumed;
- total_bytes += consumed;
- }
- }
- while (bytes > 0);
-
- /*
- * Unobfuscation completed, note the total bytes read. This value is
- * actually not used for version 3.9 and version 3.8 games, but we maintain
- * it just in case.
- */
- taf->total_in_bytes = total_bytes;
- if (is_gamefile)
- taf->total_in_bytes += VERSION_HEADER_SIZE;
-
- /* Check that we found the end of the input file as expected. */
- if (used_bytes > 0)
- {
- sc_error ("taf_unobfuscate:"
- " warning: %ld unhandled bytes in the buffer\n", used_bytes);
- }
-
- if (taf->is_unterminated)
- sc_fatal ("taf_unobfuscate: unterminated final data slab\n");
-
- /* Return successfully. */
- sc_free (buffer);
- return TRUE;
+taf_unobfuscate(sc_tafref_t taf, sc_read_callbackref_t callback,
+ void *opaque, sc_bool is_gamefile) {
+ sc_byte *buffer;
+ sc_int bytes, used_bytes, total_bytes, index_;
+
+ /* Reset the PRNG, and synchronize with the header already read. */
+ taf_random_reset();
+ for (index_ = 0; index_ < VERSION_HEADER_SIZE; index_++)
+ taf_random();
+
+ /*
+ * Malloc buffer, done to help systems with limited stacks, and initialize
+ * count of bytes read and used in the buffer to zero.
+ */
+ buffer = (sc_byte *)sc_malloc(IN_BUFFER_SIZE);
+ used_bytes = 0;
+ total_bytes = 0;
+
+ /* Unobfuscate in buffer sized chunks. */
+ do {
+ /* Try to obtain more data. */
+ bytes = callback(opaque,
+ buffer + used_bytes, IN_BUFFER_SIZE - used_bytes);
+
+ /* Unobfuscate data read in. */
+ for (index_ = 0; index_ < bytes; index_++)
+ buffer[used_bytes + index_] ^= taf_random();
+
+ /*
+ * Add data read in and unobfuscated to buffer used data, and if
+ * unobfuscated data is available, add it to the TAF.
+ */
+ used_bytes += bytes;
+ if (used_bytes > 0) {
+ sc_int consumed;
+
+ /* Add lines from this buffer to the TAF. */
+ consumed = taf_append_buffer(taf, buffer, used_bytes);
+
+ /* Move unused buffer data to buffer start. */
+ memmove(buffer, buffer + consumed, IN_BUFFER_SIZE - consumed);
+
+ /* Note counts of bytes consumed and remaining in the buffer. */
+ used_bytes -= consumed;
+ total_bytes += consumed;
+ }
+ } while (bytes > 0);
+
+ /*
+ * Unobfuscation completed, note the total bytes read. This value is
+ * actually not used for version 3.9 and version 3.8 games, but we maintain
+ * it just in case.
+ */
+ taf->total_in_bytes = total_bytes;
+ if (is_gamefile)
+ taf->total_in_bytes += VERSION_HEADER_SIZE;
+
+ /* Check that we found the end of the input file as expected. */
+ if (used_bytes > 0) {
+ sc_error("taf_unobfuscate:"
+ " warning: %ld unhandled bytes in the buffer\n", used_bytes);
+ }
+
+ if (taf->is_unterminated)
+ sc_fatal("taf_unobfuscate: unterminated final data slab\n");
+
+ /* Return successfully. */
+ sc_free(buffer);
+ return TRUE;
}
#define BUFFER_SIZE 16384
@@ -448,7 +427,7 @@ taf_unobfuscate (sc_tafref_t taf, sc_read_callbackref_t callback,
* Decompress a version 4.0 TAF
*/
static sc_bool taf_decompress(sc_tafref_t taf, sc_read_callbackref_t callback,
- void *opaque, sc_bool is_gamefile) {
+ void *opaque, sc_bool is_gamefile) {
#if USE_ZLIB
Common::SeekableReadStream *src = (Common::SeekableReadStream *)opaque;
assert(src);
@@ -484,99 +463,88 @@ static sc_bool taf_decompress(sc_tafref_t taf, sc_read_callbackref_t callback,
* in the buffer, or 0 if no more (end of file).
*/
static sc_tafref_t
-taf_create_from_callback (sc_read_callbackref_t callback,
- void *opaque, sc_bool is_gamefile)
-{
- sc_tafref_t taf;
- sc_bool status = FALSE;
- assert (callback);
-
- /* Create an empty TAF structure. */
- taf = taf_create_empty ();
-
- /*
- * Determine the TAF file version in use. For saved games, we always use
- * version 4.0 format. For others, it's determined from the header.
- */
- if (is_gamefile)
- {
- sc_int in_bytes;
-
- /*
- * Read in the ADRIFT header for game files. Start by reading in the
- * shorter header common to all.
- */
- in_bytes = callback (opaque, taf->header, VERSION_HEADER_SIZE);
- if (in_bytes != VERSION_HEADER_SIZE)
- {
- sc_error ("taf_create: not enough data for standard TAF header\n");
- taf_destroy (taf);
- return NULL;
- }
-
- /*
- * Compare the header with the known TAF signatures, and set TAF version
- * appropriately.
- */
- if (memcmp (taf->header, V400_SIGNATURE, VERSION_HEADER_SIZE) == 0)
- {
- /* Read in the version 4.0 header extension. */
- in_bytes = callback (opaque,
- taf->header + VERSION_HEADER_SIZE,
- V400_HEADER_EXTRA);
- if (in_bytes != V400_HEADER_EXTRA)
- {
- sc_error ("taf_create:"
- " not enough data for extended TAF header\n");
- taf_destroy (taf);
- return NULL;
- }
-
- taf->version = TAF_VERSION_400;
- }
- else if (memcmp (taf->header, V390_SIGNATURE, VERSION_HEADER_SIZE) == 0)
- taf->version = TAF_VERSION_390;
- else if (memcmp (taf->header, V380_SIGNATURE, VERSION_HEADER_SIZE) == 0)
- taf->version = TAF_VERSION_380;
- else
- {
- taf_destroy (taf);
- return NULL;
- }
- }
- else
- {
- /* Saved games are always considered to be version 4.0. */
- taf->version = TAF_VERSION_400;
- }
-
- /*
- * Call the appropriate game file reader function. For version 4.0 games,
- * data is compressed with Zlib. For version 3.9 and version 3.8 games,
- * it's obfuscated with the Visual Basic PRNG.
- */
- switch (taf->version)
- {
- case TAF_VERSION_400:
- status = taf_decompress (taf, callback, opaque, is_gamefile);
- break;
-
- case TAF_VERSION_390:
- case TAF_VERSION_380:
- status = taf_unobfuscate (taf, callback, opaque, is_gamefile);
- break;
-
- default:
- sc_fatal ("taf_create: invalid version\n");
- }
- if (!status)
- {
- taf_destroy (taf);
- return NULL;
- }
-
- /* Return successfully. */
- return taf;
+taf_create_from_callback(sc_read_callbackref_t callback,
+ void *opaque, sc_bool is_gamefile) {
+ sc_tafref_t taf;
+ sc_bool status = FALSE;
+ assert(callback);
+
+ /* Create an empty TAF structure. */
+ taf = taf_create_empty();
+
+ /*
+ * Determine the TAF file version in use. For saved games, we always use
+ * version 4.0 format. For others, it's determined from the header.
+ */
+ if (is_gamefile) {
+ sc_int in_bytes;
+
+ /*
+ * Read in the ADRIFT header for game files. Start by reading in the
+ * shorter header common to all.
+ */
+ in_bytes = callback(opaque, taf->header, VERSION_HEADER_SIZE);
+ if (in_bytes != VERSION_HEADER_SIZE) {
+ sc_error("taf_create: not enough data for standard TAF header\n");
+ taf_destroy(taf);
+ return NULL;
+ }
+
+ /*
+ * Compare the header with the known TAF signatures, and set TAF version
+ * appropriately.
+ */
+ if (memcmp(taf->header, V400_SIGNATURE, VERSION_HEADER_SIZE) == 0) {
+ /* Read in the version 4.0 header extension. */
+ in_bytes = callback(opaque,
+ taf->header + VERSION_HEADER_SIZE,
+ V400_HEADER_EXTRA);
+ if (in_bytes != V400_HEADER_EXTRA) {
+ sc_error("taf_create:"
+ " not enough data for extended TAF header\n");
+ taf_destroy(taf);
+ return NULL;
+ }
+
+ taf->version = TAF_VERSION_400;
+ } else if (memcmp(taf->header, V390_SIGNATURE, VERSION_HEADER_SIZE) == 0)
+ taf->version = TAF_VERSION_390;
+ else if (memcmp(taf->header, V380_SIGNATURE, VERSION_HEADER_SIZE) == 0)
+ taf->version = TAF_VERSION_380;
+ else {
+ taf_destroy(taf);
+ return NULL;
+ }
+ } else {
+ /* Saved games are always considered to be version 4.0. */
+ taf->version = TAF_VERSION_400;
+ }
+
+ /*
+ * Call the appropriate game file reader function. For version 4.0 games,
+ * data is compressed with Zlib. For version 3.9 and version 3.8 games,
+ * it's obfuscated with the Visual Basic PRNG.
+ */
+ switch (taf->version) {
+ case TAF_VERSION_400:
+ status = taf_decompress(taf, callback, opaque, is_gamefile);
+ break;
+
+ case TAF_VERSION_390:
+ case TAF_VERSION_380:
+ status = taf_unobfuscate(taf, callback, opaque, is_gamefile);
+ break;
+
+ default:
+ sc_fatal("taf_create: invalid version\n");
+ }
+ if (!status) {
+ taf_destroy(taf);
+ return NULL;
+ }
+
+ /* Return successfully. */
+ return taf;
}
@@ -588,31 +556,28 @@ taf_create_from_callback (sc_read_callbackref_t callback,
* constructed from either *.TAF (game) or *.TAS (saved game state) file data.
*/
sc_tafref_t
-taf_create (sc_read_callbackref_t callback, void *opaque)
-{
- return taf_create_from_callback (callback, opaque, TRUE);
+taf_create(sc_read_callbackref_t callback, void *opaque) {
+ return taf_create_from_callback(callback, opaque, TRUE);
}
sc_tafref_t
-taf_create_tas (sc_read_callbackref_t callback, void *opaque)
-{
- return taf_create_from_callback (callback, opaque, FALSE);
+taf_create_tas(sc_read_callbackref_t callback, void *opaque) {
+ return taf_create_from_callback(callback, opaque, FALSE);
}
-
+
/*
* taf_first_line()
*
* Iterator rewind function, reset current slab location to TAF data start.
*/
void
-taf_first_line (sc_tafref_t taf)
-{
- assert (taf_is_valid (taf));
+taf_first_line(sc_tafref_t taf) {
+ assert(taf_is_valid(taf));
- /* Set current locations to TAF start. */
- taf->current_slab = 0;
- taf->current_offset = 0;
+ /* Set current locations to TAF start. */
+ taf->current_slab = 0;
+ taf->current_offset = 0;
}
@@ -623,35 +588,32 @@ taf_first_line (sc_tafref_t taf)
* if no more lines.
*/
const sc_char *
-taf_next_line (sc_tafref_t taf)
-{
- assert (taf_is_valid (taf));
-
- /* If there is a next line, return it and advance current. */
- if (taf->current_slab < taf->slab_count)
- {
- sc_char *line;
-
- /* Get the effective address of the current line. */
- line = (sc_char *) taf->slabs[taf->current_slab].data;
- line += taf->current_offset;
-
- /*
- * Advance to the next line. The + 2 skips the NULs used to replace the
- * carriage return and line feed.
- */
- taf->current_offset += strlen (line) + 2;
- if (taf->current_offset >= taf->slabs[taf->current_slab].size)
- {
- taf->current_slab++;
- taf->current_offset = 0;
- }
-
- return line;
- }
-
- /* No more lines, so return NULL. */
- return NULL;
+taf_next_line(sc_tafref_t taf) {
+ assert(taf_is_valid(taf));
+
+ /* If there is a next line, return it and advance current. */
+ if (taf->current_slab < taf->slab_count) {
+ sc_char *line;
+
+ /* Get the effective address of the current line. */
+ line = (sc_char *) taf->slabs[taf->current_slab].data;
+ line += taf->current_offset;
+
+ /*
+ * Advance to the next line. The + 2 skips the NULs used to replace the
+ * carriage return and line feed.
+ */
+ taf->current_offset += strlen(line) + 2;
+ if (taf->current_offset >= taf->slabs[taf->current_slab].size) {
+ taf->current_slab++;
+ taf->current_offset = 0;
+ }
+
+ return line;
+ }
+
+ /* No more lines, so return NULL. */
+ return NULL;
}
@@ -661,12 +623,11 @@ taf_next_line (sc_tafref_t taf)
* Iterator end function, returns TRUE if more TAF lines are readable.
*/
sc_bool
-taf_more_lines (sc_tafref_t taf)
-{
- assert (taf_is_valid (taf));
+taf_more_lines(sc_tafref_t taf) {
+ assert(taf_is_valid(taf));
- /* Return TRUE if not at TAF data end. */
- return taf->current_slab < taf->slab_count;
+ /* Return TRUE if not at TAF data end. */
+ return taf->current_slab < taf->slab_count;
}
@@ -678,16 +639,15 @@ taf_more_lines (sc_tafref_t taf)
* be located.
*/
sc_int
-taf_get_game_data_length (sc_tafref_t taf)
-{
- assert (taf_is_valid (taf));
-
- /*
- * Return the count of bytes inflated; this includes the TAF header length
- * for TAF, rather than TAS, files. For TAS files, the count of file bytes
- * read is irrelevant, and is never used.
- */
- return taf->total_in_bytes;
+taf_get_game_data_length(sc_tafref_t taf) {
+ assert(taf_is_valid(taf));
+
+ /*
+ * Return the count of bytes inflated; this includes the TAF header length
+ * for TAF, rather than TAS, files. For TAS files, the count of file bytes
+ * read is irrelevant, and is never used.
+ */
+ return taf->total_in_bytes;
}
@@ -697,12 +657,11 @@ taf_get_game_data_length (sc_tafref_t taf)
* Return the version number of the TAF file, 400, 390, or 380.
*/
sc_int
-taf_get_version (sc_tafref_t taf)
-{
- assert (taf_is_valid (taf));
+taf_get_version(sc_tafref_t taf) {
+ assert(taf_is_valid(taf));
- assert (taf->version != TAF_VERSION_NONE);
- return taf->version;
+ assert(taf->version != TAF_VERSION_NONE);
+ return taf->version;
}
@@ -715,67 +674,64 @@ taf_get_version (sc_tafref_t taf)
* slab, and therefore safe to print.
*/
sc_bool
-taf_debug_is_taf_string (sc_tafref_t taf, const void *addr) {
- const sc_byte *const addr_ = (const sc_byte *const)addr;
- sc_int index_;
-
- /*
- * Compare pointer, by address directly, against all memory contained in
- * the TAF slabs. Return TRUE if in range.
- */
- for (index_ = 0; index_ < taf->slab_count; index_++)
- {
- if (addr_ >= taf->slabs[index_].data
- && addr_ < taf->slabs[index_].data + taf->slabs[index_].size)
- return TRUE;
- }
-
- return FALSE;
+taf_debug_is_taf_string(sc_tafref_t taf, const void *addr) {
+ const sc_byte *const addr_ = (const sc_byte * const)addr;
+ sc_int index_;
+
+ /*
+ * Compare pointer, by address directly, against all memory contained in
+ * the TAF slabs. Return TRUE if in range.
+ */
+ for (index_ = 0; index_ < taf->slab_count; index_++) {
+ if (addr_ >= taf->slabs[index_].data
+ && addr_ < taf->slabs[index_].data + taf->slabs[index_].size)
+ return TRUE;
+ }
+
+ return FALSE;
}
void
-taf_debug_dump (sc_tafref_t taf)
-{
- sc_int index_, current_slab, current_offset;
- assert (taf_is_valid (taf));
-
- /* Dump complete structure. */
- sc_trace ("TAFfile: debug dump follows...\n");
- sc_trace ("taf->header =");
- for (index_ = 0; index_ < (sc_int) sizeof (taf->header); index_++)
- sc_trace (" %02x", taf->header[index_]);
- sc_trace ("\n");
-
- sc_trace ("taf->version = %s\n",
- taf->version == TAF_VERSION_400 ? "4.00" :
- taf->version == TAF_VERSION_390 ? "3.90" :
- taf->version == TAF_VERSION_380 ? "3.80" : "[Unknown]");
-
- sc_trace ("taf->slabs = \n");
- for (index_ = 0; index_ < taf->slab_count; index_++)
- {
- sc_trace ("%3ld : %p, %ld bytes\n", index_,
- taf->slabs[index_].data, taf->slabs[index_].size);
- }
-
- sc_trace ("taf->slab_count = %ld\n", taf->slab_count);
- sc_trace ("taf->slabs_allocated = %ld\n", taf->slabs_allocated);
- sc_trace ("taf->current_slab = %ld\n", taf->current_slab);
- sc_trace ("taf->current_offset = %ld\n", taf->current_offset);
-
- /* Save current location. */
- current_slab = taf->current_slab;
- current_offset = taf->current_offset;
-
- /* Print out taf lines using taf iterators. */
- sc_trace ("\ntaf iterators:\n");
- taf_first_line (taf);
- for (index_ = 0; taf_more_lines (taf); index_++)
- sc_trace ("%5ld %s\n", index_, taf_next_line (taf));
-
- /* Restore current location. */
- taf->current_slab = current_slab;
- taf->current_offset = current_offset;
+taf_debug_dump(sc_tafref_t taf) {
+ sc_int index_, current_slab, current_offset;
+ assert(taf_is_valid(taf));
+
+ /* Dump complete structure. */
+ sc_trace("TAFfile: debug dump follows...\n");
+ sc_trace("taf->header =");
+ for (index_ = 0; index_ < (sc_int) sizeof(taf->header); index_++)
+ sc_trace(" %02x", taf->header[index_]);
+ sc_trace("\n");
+
+ sc_trace("taf->version = %s\n",
+ taf->version == TAF_VERSION_400 ? "4.00" :
+ taf->version == TAF_VERSION_390 ? "3.90" :
+ taf->version == TAF_VERSION_380 ? "3.80" : "[Unknown]");
+
+ sc_trace("taf->slabs = \n");
+ for (index_ = 0; index_ < taf->slab_count; index_++) {
+ sc_trace("%3ld : %p, %ld bytes\n", index_,
+ taf->slabs[index_].data, taf->slabs[index_].size);
+ }
+
+ sc_trace("taf->slab_count = %ld\n", taf->slab_count);
+ sc_trace("taf->slabs_allocated = %ld\n", taf->slabs_allocated);
+ sc_trace("taf->current_slab = %ld\n", taf->current_slab);
+ sc_trace("taf->current_offset = %ld\n", taf->current_offset);
+
+ /* Save current location. */
+ current_slab = taf->current_slab;
+ current_offset = taf->current_offset;
+
+ /* Print out taf lines using taf iterators. */
+ sc_trace("\ntaf iterators:\n");
+ taf_first_line(taf);
+ for (index_ = 0; taf_more_lines(taf); index_++)
+ sc_trace("%5ld %s\n", index_, taf_next_line(taf));
+
+ /* Restore current location. */
+ taf->current_slab = current_slab;
+ taf->current_offset = current_offset;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sctafpar.cpp b/engines/glk/adrift/sctafpar.cpp
index 269308a953..9880603faf 100644
--- a/engines/glk/adrift/sctafpar.cpp
+++ b/engines/glk/adrift/sctafpar.cpp
@@ -42,9 +42,9 @@ namespace Adrift {
/* Assorted definitions and constants. */
static const sc_char NUL = '\0';
-enum
-{ PARSE_TEMP_LENGTH = 256,
- PARSE_MAX_DEPTH = 32
+enum {
+ PARSE_TEMP_LENGTH = 256,
+ PARSE_MAX_DEPTH = 32
};
/* Multiline separator sequences for the various versions supported. */
@@ -71,257 +71,382 @@ static const sc_byte V380_SEPARATOR[SEPARATOR_SIZE] = {0x2a, 0x2a, 0x00};
* |...| - fixup specials for versions < 4
* {special} - because some things just defy description
*/
-typedef struct
-{
- const sc_char *const class_name;
- const sc_char *const descriptor;
+typedef struct {
+ const sc_char *const class_name;
+ const sc_char *const descriptor;
} sc_parse_schema_t;
/* Version 4.0 TAF file properties descriptor table. */
static const sc_parse_schema_t V400_PARSE_SCHEMA[] = {
- {"_GAME_",
- "<HEADER>Header <GLOBAL>Globals V<ROOM>Rooms V<OBJECT>Objects V<TASK>Tasks"
- " V<EVENT>Events V<NPC>NPCs V<ROOM_GROUP>RoomGroups V<SYNONYM>Synonyms"
- " V<VARIABLE>Variables V<ALR>ALRs BCustomFont ?BCustomFont:$FontNameSize"
- " $CompileDate"},
- {"HEADER",
- "MStartupText #StartRoom MWinText"},
- {"GLOBAL",
- "$GameName $GameAuthor $DontUnderstand #Perspective BShowExits #WaitTurns"
- " BDispFirstRoom BBattleSystem #MaxScore $PlayerName BPromptName $PlayerDesc"
- " #Task ?!#Task=0:$AltDesc #Position #ParentObject #PlayerGender"
- " #MaxSize #MaxWt ?GBattleSystem:<BATTLE>Battle BEightPointCompass bNoDebug"
- " BNoScoreNotify BNoMap bNoAutoComplete bNoControlPanel bNoMouse BSound"
- " BGraphics <RESOURCE>IntroRes <RESOURCE>WinRes BStatusBox $StatusBoxText"
- " iUnk1 iUnk2 BEmbedded"},
- {"BATTLE",
- "iStaminaLo iStaminaHi iStrengthLo iStrengthHi iAccuracyLo iAccuracyHi"
- " iDefenseLo iDefenseHi iAgilityLo iAgilityHi iRecovery"},
- {"ROOM",
- "$Short $Long ?GEightPointCompass:[12]<ROOM_EXIT>Exits"
- " ?!GEightPointCompass:[8]<ROOM_EXIT>Exits <RESOURCE>Res V<ROOM_ALT>Alts"
- " ?!GNoMap:bHideOnMap"},
- {"ROOM_EXIT",
- "{V400_ROOM_EXIT:#Dest_#Var1_#Var2_#Var3}"},
- {"ROOM_ALT",
- "$M1 #Type <RESOURCE>Res1 $M2 #Var2 <RESOURCE>Res2 #HideObjects $Changed"
- " #Var3 #DisplayRoom"},
- {"RESOURCE",
- "?GSound:$SoundFile,#SoundLen,ZSoundOffset"
- " ?GGraphics:$GraphicFile,#GraphicLen,ZGraphicOffset {V400_RESOURCE}"},
- {"OBJECT",
- "$Prefix $Short V$Alias BStatic $Description #InitialPosition #Task"
- " BTaskNotDone $AltDesc ?BStatic:<ROOM_LIST1>Where BContainer BSurface"
- " #Capacity ?!BStatic:BWearable,#SizeWeight,#Parent"
- " ?BStatic:{OBJECT:#Parent} #Openable ?#Openable=5:#Key ?#Openable=6:#Key"
- " ?#Openable=7:#Key #SitLie ?!BStatic:BEdible BReadable ?BReadable:$ReadText"
- " ?!BStatic:BWeapon #CurrentState ?!#CurrentState=0:$States,BStateListed"
- " BListFlag <RESOURCE>Res1 <RESOURCE>Res2 ?GBattleSystem:<OBJ_BATTLE>Battle"
- " $InRoomDesc #OnlyWhenNotMoved"},
- {"OBJ_BATTLE",
- "iProtectionValue iHitValue iMethod iAccuracy"},
- {"ROOM_LIST1",
- "#Type {ROOM_LIST1}"},
- {"TASK",
- "V$Command $CompleteText $ReverseMessage $RepeatText $AdditionalMessage"
- " #ShowRoomDesc BRepeatable BReversible V$ReverseCommand <ROOM_LIST0>Where"
- " $Question ?$Question:$Hint1,$Hint2 V<TASK_RESTR>Restrictions"
- " V<TASK_ACTION>Actions $RestrMask <RESOURCE>Res"},
- {"TASK_RESTR",
- "#Type ?#Type=0:#Var1,#Var2,#Var3 ?#Type=1:#Var1,#Var2 ?#Type=2:#Var1,#Var2"
- " ?#Type=3:#Var1,#Var2,#Var3 ?#Type=4:#Var1,#Var2,#Var3,$Var4 $FailMessage"},
- {"TASK_ACTION",
- "#Type ?#Type=0:#Var1,#Var2,#Var3 ?#Type=1:#Var1,#Var2,#Var3"
- " ?#Type=2:#Var1,#Var2 ?#Type=3:#Var1,#Var2,#Var3,$Expr,#Var5"
- " ?#Type=4:#Var1 ?#Type=5:#Var1,#Var2 ?#Type=6:#Var1,#Var2,#Var3"
- " ?#Type=7:iVar1,iVar2,iVar3"},
- {"ROOM_LIST0",
- "#Type {ROOM_LIST0}"},
- {"EVENT",
- "$Short #StarterType ?#StarterType=2:#StartTime,#EndTime"
- " ?#StarterType=3:#TaskNum #RestartType BTaskFinished #Time1 #Time2"
- " $StartText $LookText $FinishText <ROOM_LIST0>Where #PauseTask"
- " BPauserCompleted #PrefTime1 $PrefText1 #ResumeTask BResumerCompleted"
- " #PrefTime2 $PrefText2 #Obj2 #Obj2Dest #Obj3 #Obj3Dest #Obj1 #Obj1Dest"
- " #TaskAffected [5]<RESOURCE>Res"},
- {"NPC",
- "$Name $Prefix V$Alias $Descr #StartRoom $AltText #Task V<TOPIC>Topics"
- " V<WALK>Walks BShowEnterExit ?BShowEnterExit:$EnterText,$ExitText"
- " $InRoomText #Gender [4]<RESOURCE>Res ?GBattleSystem:<NPC_BATTLE>Battle"},
- {"NPC_BATTLE",
- "iAttitude iStaminaLo iStaminaHi iStrengthLo iStrengthHi iAccuracyLo"
- " iAccuracyHi iDefenseLo iDefenseHi iAgilityLo iAgilityHi iSpeed"
- " iKilledTask iRecovery iStaminaTask"},
- {"TOPIC",
- "$Subject $Reply #Task $AltReply"},
- {"WALK",
- "#NumStops BLoop #StartTask #CharTask #MeetObject #ObjectTask #StoppingTask"
- " #MeetChar $ChangedDesc {WALK:#Rooms_#Times}"},
- {"ROOM_GROUP",
- "$Name {ROOM_GROUP:[]BList}"},
- {"SYNONYM",
- "$Replacement $Original"},
- {"VARIABLE",
- "$Name #Type $Value"},
- {"ALR",
- "$Original $Replacement"},
- {NULL, NULL}
+ {
+ "_GAME_",
+ "<HEADER>Header <GLOBAL>Globals V<ROOM>Rooms V<OBJECT>Objects V<TASK>Tasks"
+ " V<EVENT>Events V<NPC>NPCs V<ROOM_GROUP>RoomGroups V<SYNONYM>Synonyms"
+ " V<VARIABLE>Variables V<ALR>ALRs BCustomFont ?BCustomFont:$FontNameSize"
+ " $CompileDate"
+ },
+ {
+ "HEADER",
+ "MStartupText #StartRoom MWinText"
+ },
+ {
+ "GLOBAL",
+ "$GameName $GameAuthor $DontUnderstand #Perspective BShowExits #WaitTurns"
+ " BDispFirstRoom BBattleSystem #MaxScore $PlayerName BPromptName $PlayerDesc"
+ " #Task ?!#Task=0:$AltDesc #Position #ParentObject #PlayerGender"
+ " #MaxSize #MaxWt ?GBattleSystem:<BATTLE>Battle BEightPointCompass bNoDebug"
+ " BNoScoreNotify BNoMap bNoAutoComplete bNoControlPanel bNoMouse BSound"
+ " BGraphics <RESOURCE>IntroRes <RESOURCE>WinRes BStatusBox $StatusBoxText"
+ " iUnk1 iUnk2 BEmbedded"
+ },
+ {
+ "BATTLE",
+ "iStaminaLo iStaminaHi iStrengthLo iStrengthHi iAccuracyLo iAccuracyHi"
+ " iDefenseLo iDefenseHi iAgilityLo iAgilityHi iRecovery"
+ },
+ {
+ "ROOM",
+ "$Short $Long ?GEightPointCompass:[12]<ROOM_EXIT>Exits"
+ " ?!GEightPointCompass:[8]<ROOM_EXIT>Exits <RESOURCE>Res V<ROOM_ALT>Alts"
+ " ?!GNoMap:bHideOnMap"
+ },
+ {
+ "ROOM_EXIT",
+ "{V400_ROOM_EXIT:#Dest_#Var1_#Var2_#Var3}"
+ },
+ {
+ "ROOM_ALT",
+ "$M1 #Type <RESOURCE>Res1 $M2 #Var2 <RESOURCE>Res2 #HideObjects $Changed"
+ " #Var3 #DisplayRoom"
+ },
+ {
+ "RESOURCE",
+ "?GSound:$SoundFile,#SoundLen,ZSoundOffset"
+ " ?GGraphics:$GraphicFile,#GraphicLen,ZGraphicOffset {V400_RESOURCE}"
+ },
+ {
+ "OBJECT",
+ "$Prefix $Short V$Alias BStatic $Description #InitialPosition #Task"
+ " BTaskNotDone $AltDesc ?BStatic:<ROOM_LIST1>Where BContainer BSurface"
+ " #Capacity ?!BStatic:BWearable,#SizeWeight,#Parent"
+ " ?BStatic:{OBJECT:#Parent} #Openable ?#Openable=5:#Key ?#Openable=6:#Key"
+ " ?#Openable=7:#Key #SitLie ?!BStatic:BEdible BReadable ?BReadable:$ReadText"
+ " ?!BStatic:BWeapon #CurrentState ?!#CurrentState=0:$States,BStateListed"
+ " BListFlag <RESOURCE>Res1 <RESOURCE>Res2 ?GBattleSystem:<OBJ_BATTLE>Battle"
+ " $InRoomDesc #OnlyWhenNotMoved"
+ },
+ {
+ "OBJ_BATTLE",
+ "iProtectionValue iHitValue iMethod iAccuracy"
+ },
+ {
+ "ROOM_LIST1",
+ "#Type {ROOM_LIST1}"
+ },
+ {
+ "TASK",
+ "V$Command $CompleteText $ReverseMessage $RepeatText $AdditionalMessage"
+ " #ShowRoomDesc BRepeatable BReversible V$ReverseCommand <ROOM_LIST0>Where"
+ " $Question ?$Question:$Hint1,$Hint2 V<TASK_RESTR>Restrictions"
+ " V<TASK_ACTION>Actions $RestrMask <RESOURCE>Res"
+ },
+ {
+ "TASK_RESTR",
+ "#Type ?#Type=0:#Var1,#Var2,#Var3 ?#Type=1:#Var1,#Var2 ?#Type=2:#Var1,#Var2"
+ " ?#Type=3:#Var1,#Var2,#Var3 ?#Type=4:#Var1,#Var2,#Var3,$Var4 $FailMessage"
+ },
+ {
+ "TASK_ACTION",
+ "#Type ?#Type=0:#Var1,#Var2,#Var3 ?#Type=1:#Var1,#Var2,#Var3"
+ " ?#Type=2:#Var1,#Var2 ?#Type=3:#Var1,#Var2,#Var3,$Expr,#Var5"
+ " ?#Type=4:#Var1 ?#Type=5:#Var1,#Var2 ?#Type=6:#Var1,#Var2,#Var3"
+ " ?#Type=7:iVar1,iVar2,iVar3"
+ },
+ {
+ "ROOM_LIST0",
+ "#Type {ROOM_LIST0}"
+ },
+ {
+ "EVENT",
+ "$Short #StarterType ?#StarterType=2:#StartTime,#EndTime"
+ " ?#StarterType=3:#TaskNum #RestartType BTaskFinished #Time1 #Time2"
+ " $StartText $LookText $FinishText <ROOM_LIST0>Where #PauseTask"
+ " BPauserCompleted #PrefTime1 $PrefText1 #ResumeTask BResumerCompleted"
+ " #PrefTime2 $PrefText2 #Obj2 #Obj2Dest #Obj3 #Obj3Dest #Obj1 #Obj1Dest"
+ " #TaskAffected [5]<RESOURCE>Res"
+ },
+ {
+ "NPC",
+ "$Name $Prefix V$Alias $Descr #StartRoom $AltText #Task V<TOPIC>Topics"
+ " V<WALK>Walks BShowEnterExit ?BShowEnterExit:$EnterText,$ExitText"
+ " $InRoomText #Gender [4]<RESOURCE>Res ?GBattleSystem:<NPC_BATTLE>Battle"
+ },
+ {
+ "NPC_BATTLE",
+ "iAttitude iStaminaLo iStaminaHi iStrengthLo iStrengthHi iAccuracyLo"
+ " iAccuracyHi iDefenseLo iDefenseHi iAgilityLo iAgilityHi iSpeed"
+ " iKilledTask iRecovery iStaminaTask"
+ },
+ {
+ "TOPIC",
+ "$Subject $Reply #Task $AltReply"
+ },
+ {
+ "WALK",
+ "#NumStops BLoop #StartTask #CharTask #MeetObject #ObjectTask #StoppingTask"
+ " #MeetChar $ChangedDesc {WALK:#Rooms_#Times}"
+ },
+ {
+ "ROOM_GROUP",
+ "$Name {ROOM_GROUP:[]BList}"
+ },
+ {
+ "SYNONYM",
+ "$Replacement $Original"
+ },
+ {
+ "VARIABLE",
+ "$Name #Type $Value"
+ },
+ {
+ "ALR",
+ "$Original $Replacement"
+ },
+ {NULL, NULL}
};
/* Version 3.9 TAF file properties descriptor table. */
static const sc_parse_schema_t V390_PARSE_SCHEMA[] = {
- {"_GAME_",
- "<HEADER>Header <GLOBAL>Globals V<ROOM>Rooms V<OBJECT>Objects V<TASK>Tasks"
- " V<EVENT>Events V<NPC>NPCs V<ROOM_GROUP>RoomGroups V<SYNONYM>Synonyms"
- " V<VARIABLE>Variables V<ALR>ALRs BCustomFont ?BCustomFont:$FontNameSize"
- " $CompileDate sPassword"},
- {"HEADER",
- "MStartupText #StartRoom MWinText"},
- {"GLOBAL",
- "$GameName $GameAuthor $DontUnderstand #Perspective BShowExits #WaitTurns"
- " BDispFirstRoom BBattleSystem #MaxScore $PlayerName BPromptName $PlayerDesc"
- " #Task ?!#Task=0:$AltDesc #Position #ParentObject #PlayerGender"
- " #MaxSize #MaxWt ?GBattleSystem:<BATTLE>Battle BEightPointCompass bNoDebug"
- " BNoScoreNotify BNoMap bNoAutoComplete bNoControlPanel bNoMouse"
- " BSound BGraphics <RESOURCE>IntroRes <RESOURCE>WinRes FStatusBox"
- " EStatusBoxText iUnk1 iUnk2 FEmbedded"},
- {"BATTLE",
- "iStamina iStrength iDefense"},
- {"ROOM",
- "$Short $Long $LastDesc ?GEightPointCompass:[12]<ROOM_EXIT>Exits"
- " ?!GEightPointCompass:[8]<ROOM_EXIT>Exits $AddDesc1 #Task1 $AddDesc2 #Task2"
- " #Obj $AltDesc #TypeHideObjects <RESOURCE>Res <RESOURCE>LastRes"
- " <RESOURCE>Task1Res <RESOURCE>Task2Res <RESOURCE>AltRes"
- " ?!GNoMap:bHideOnMap |V390_ROOM:_Alts_|"},
- {"ROOM_EXIT",
- "{V390_V380_ROOM_EXIT:#Dest_#Var1_#Var2_ZVar3}"},
- {"RESOURCE",
- "?GSound:$SoundFile,ZSoundLen,ZSoundOffset"
- " ?GGraphics:$GraphicFile,ZGraphicLen,ZGraphicOffset"},
- {"OBJECT",
- "$Prefix $Short"
- " [1]$Alias BStatic $Description #InitialPosition #Task BTaskNotDone"
- " $AltDesc ?BStatic:<ROOM_LIST1>Where BContainer BSurface #Capacity"
- " ?!BStatic:BWearable,#SizeWeight,#Parent ?BStatic:{OBJECT:#Parent}"
- " #Openable |V390_OBJECT:_Openable_,Key| #SitLie ?!BStatic:BEdible BReadable"
- " ?BReadable:$ReadText ?!BStatic:BWeapon ZCurrentState FListFlag"
- " <RESOURCE>Res1 <RESOURCE>Res2 ?GBattleSystem:<OBJ_BATTLE>Battle"
- " EInRoomDesc ZOnlyWhenNotMoved"},
- {"OBJ_BATTLE",
- "iProtectionValue iHitValue iMethod"},
- {"ROOM_LIST1",
- "#Type {ROOM_LIST1}"},
- {"TASK",
- "W$Command $CompleteText $ReverseMessage $RepeatText $AdditionalMessage"
- " #ShowRoomDesc BRepeatable BReversible W$ReverseCommand <ROOM_LIST0>Where"
- " $Question ?$Question:$Hint1,$Hint2 V<TASK_RESTR>Restrictions"
- " V<TASK_ACTION>Actions |V390_TASK:$RestrMask| <RESOURCE>Res"},
- {"TASK_RESTR",
- "#Type ?#Type=0:#Var1,#Var2,#Var3 ?#Type=1:#Var1,#Var2 ?#Type=2:#Var1,#Var2"
- " ?#Type=3:#Var1,#Var2,#Var3 ?#Type=4:#Var1,#Var2,#Var3,EVar4"
- ",|V390_TASK_RESTR:Var1>0?#Var1++| $FailMessage"},
- {"TASK_ACTION",
- "#Type |V390_TASK_ACTION:Type>4?#Type++| ?#Type=0:#Var1,#Var2,#Var3"
- " ?#Type=1:#Var1,#Var2,#Var3 ?#Type=2:#Var1,#Var2"
- " ?#Type=3:#Var1,#Var2,#Var3,|V390_TASK_ACTION:$Expr_#Var5|"
- " ?#Type=4:#Var1 ?#Type=6:#Var1,ZVar2,ZVar3 ?#Type=7:iVar1,iVar2,iVar3"},
- {"ROOM_LIST0",
- "#Type {ROOM_LIST0}"},
- {"EVENT",
- "$Short #StarterType ?#StarterType=2:#StartTime,#EndTime"
- " ?#StarterType=3:#TaskNum #RestartType BTaskFinished #Time1 #Time2"
- " $StartText $LookText $FinishText <ROOM_LIST0>Where #PauseTask"
- " BPauserCompleted #PrefTime1 $PrefText1 #ResumeTask BResumerCompleted"
- " #PrefTime2 $PrefText2 #Obj2 #Obj2Dest #Obj3 #Obj3Dest #Obj1 #Obj1Dest"
- " #TaskAffected [5]<RESOURCE>Res"},
- {"NPC",
- "$Name $Prefix [1]$Alias $Descr #StartRoom $AltText #Task V<TOPIC>Topics"
- " V<WALK>Walks BShowEnterExit ?BShowEnterExit:$EnterText,$ExitText"
- " $InRoomText #Gender [4]<RESOURCE>Res ?GBattleSystem:<NPC_BATTLE>Battle"},
- {"NPC_BATTLE",
- "iAttitude iStamina iStrength iDefense iSpeed iKilledTask"},
- {"TOPIC",
- "$Subject $Reply #Task $AltReply"},
- {"WALK",
- "#NumStops BLoop #StartTask #CharTask #MeetObject #ObjectTask #StoppingTask"
- " ZMeetChar $ChangedDesc {WALK:#Rooms_#Times}"},
- {"ROOM_GROUP",
- "$Name {ROOM_GROUP:[]BList}"},
- {"SYNONYM",
- "$Replacement $Original"},
- {"VARIABLE",
- "$Name ZType $Value"},
- {"ALR",
- "$Original $Replacement"},
- {NULL, NULL}
+ {
+ "_GAME_",
+ "<HEADER>Header <GLOBAL>Globals V<ROOM>Rooms V<OBJECT>Objects V<TASK>Tasks"
+ " V<EVENT>Events V<NPC>NPCs V<ROOM_GROUP>RoomGroups V<SYNONYM>Synonyms"
+ " V<VARIABLE>Variables V<ALR>ALRs BCustomFont ?BCustomFont:$FontNameSize"
+ " $CompileDate sPassword"
+ },
+ {
+ "HEADER",
+ "MStartupText #StartRoom MWinText"
+ },
+ {
+ "GLOBAL",
+ "$GameName $GameAuthor $DontUnderstand #Perspective BShowExits #WaitTurns"
+ " BDispFirstRoom BBattleSystem #MaxScore $PlayerName BPromptName $PlayerDesc"
+ " #Task ?!#Task=0:$AltDesc #Position #ParentObject #PlayerGender"
+ " #MaxSize #MaxWt ?GBattleSystem:<BATTLE>Battle BEightPointCompass bNoDebug"
+ " BNoScoreNotify BNoMap bNoAutoComplete bNoControlPanel bNoMouse"
+ " BSound BGraphics <RESOURCE>IntroRes <RESOURCE>WinRes FStatusBox"
+ " EStatusBoxText iUnk1 iUnk2 FEmbedded"
+ },
+ {
+ "BATTLE",
+ "iStamina iStrength iDefense"
+ },
+ {
+ "ROOM",
+ "$Short $Long $LastDesc ?GEightPointCompass:[12]<ROOM_EXIT>Exits"
+ " ?!GEightPointCompass:[8]<ROOM_EXIT>Exits $AddDesc1 #Task1 $AddDesc2 #Task2"
+ " #Obj $AltDesc #TypeHideObjects <RESOURCE>Res <RESOURCE>LastRes"
+ " <RESOURCE>Task1Res <RESOURCE>Task2Res <RESOURCE>AltRes"
+ " ?!GNoMap:bHideOnMap |V390_ROOM:_Alts_|"
+ },
+ {
+ "ROOM_EXIT",
+ "{V390_V380_ROOM_EXIT:#Dest_#Var1_#Var2_ZVar3}"
+ },
+ {
+ "RESOURCE",
+ "?GSound:$SoundFile,ZSoundLen,ZSoundOffset"
+ " ?GGraphics:$GraphicFile,ZGraphicLen,ZGraphicOffset"
+ },
+ {
+ "OBJECT",
+ "$Prefix $Short"
+ " [1]$Alias BStatic $Description #InitialPosition #Task BTaskNotDone"
+ " $AltDesc ?BStatic:<ROOM_LIST1>Where BContainer BSurface #Capacity"
+ " ?!BStatic:BWearable,#SizeWeight,#Parent ?BStatic:{OBJECT:#Parent}"
+ " #Openable |V390_OBJECT:_Openable_,Key| #SitLie ?!BStatic:BEdible BReadable"
+ " ?BReadable:$ReadText ?!BStatic:BWeapon ZCurrentState FListFlag"
+ " <RESOURCE>Res1 <RESOURCE>Res2 ?GBattleSystem:<OBJ_BATTLE>Battle"
+ " EInRoomDesc ZOnlyWhenNotMoved"
+ },
+ {
+ "OBJ_BATTLE",
+ "iProtectionValue iHitValue iMethod"
+ },
+ {
+ "ROOM_LIST1",
+ "#Type {ROOM_LIST1}"
+ },
+ {
+ "TASK",
+ "W$Command $CompleteText $ReverseMessage $RepeatText $AdditionalMessage"
+ " #ShowRoomDesc BRepeatable BReversible W$ReverseCommand <ROOM_LIST0>Where"
+ " $Question ?$Question:$Hint1,$Hint2 V<TASK_RESTR>Restrictions"
+ " V<TASK_ACTION>Actions |V390_TASK:$RestrMask| <RESOURCE>Res"
+ },
+ {
+ "TASK_RESTR",
+ "#Type ?#Type=0:#Var1,#Var2,#Var3 ?#Type=1:#Var1,#Var2 ?#Type=2:#Var1,#Var2"
+ " ?#Type=3:#Var1,#Var2,#Var3 ?#Type=4:#Var1,#Var2,#Var3,EVar4"
+ ",|V390_TASK_RESTR:Var1>0?#Var1++| $FailMessage"
+ },
+ {
+ "TASK_ACTION",
+ "#Type |V390_TASK_ACTION:Type>4?#Type++| ?#Type=0:#Var1,#Var2,#Var3"
+ " ?#Type=1:#Var1,#Var2,#Var3 ?#Type=2:#Var1,#Var2"
+ " ?#Type=3:#Var1,#Var2,#Var3,|V390_TASK_ACTION:$Expr_#Var5|"
+ " ?#Type=4:#Var1 ?#Type=6:#Var1,ZVar2,ZVar3 ?#Type=7:iVar1,iVar2,iVar3"
+ },
+ {
+ "ROOM_LIST0",
+ "#Type {ROOM_LIST0}"
+ },
+ {
+ "EVENT",
+ "$Short #StarterType ?#StarterType=2:#StartTime,#EndTime"
+ " ?#StarterType=3:#TaskNum #RestartType BTaskFinished #Time1 #Time2"
+ " $StartText $LookText $FinishText <ROOM_LIST0>Where #PauseTask"
+ " BPauserCompleted #PrefTime1 $PrefText1 #ResumeTask BResumerCompleted"
+ " #PrefTime2 $PrefText2 #Obj2 #Obj2Dest #Obj3 #Obj3Dest #Obj1 #Obj1Dest"
+ " #TaskAffected [5]<RESOURCE>Res"
+ },
+ {
+ "NPC",
+ "$Name $Prefix [1]$Alias $Descr #StartRoom $AltText #Task V<TOPIC>Topics"
+ " V<WALK>Walks BShowEnterExit ?BShowEnterExit:$EnterText,$ExitText"
+ " $InRoomText #Gender [4]<RESOURCE>Res ?GBattleSystem:<NPC_BATTLE>Battle"
+ },
+ {
+ "NPC_BATTLE",
+ "iAttitude iStamina iStrength iDefense iSpeed iKilledTask"
+ },
+ {
+ "TOPIC",
+ "$Subject $Reply #Task $AltReply"
+ },
+ {
+ "WALK",
+ "#NumStops BLoop #StartTask #CharTask #MeetObject #ObjectTask #StoppingTask"
+ " ZMeetChar $ChangedDesc {WALK:#Rooms_#Times}"
+ },
+ {
+ "ROOM_GROUP",
+ "$Name {ROOM_GROUP:[]BList}"
+ },
+ {
+ "SYNONYM",
+ "$Replacement $Original"
+ },
+ {
+ "VARIABLE",
+ "$Name ZType $Value"
+ },
+ {
+ "ALR",
+ "$Original $Replacement"
+ },
+ {NULL, NULL}
};
/* Version 3.8 TAF file properties descriptor table. */
static const sc_parse_schema_t V380_PARSE_SCHEMA[] = {
- {"_GAME_",
- "<HEADER>Header <GLOBAL>Globals V<ROOM>Rooms V<OBJECT>Objects V<TASK>Tasks"
- " V<EVENT>Events V<NPC>NPCs V<ROOM_GROUP>RoomGroups V<SYNONYM>Synonyms"
- " FCustomFont $CompileDate sPassword |V380_GLOBAL:_MaxScore_|"
- " |V380_OBJECT:_InitialPositions_|"},
- {"HEADER",
- "MStartupText #StartRoom MWinText"},
- {"GLOBAL",
- "$GameName $GameAuthor #MaxCarried |V380_MaxSize_MaxWt_| $DontUnderstand"
- " #Perspective BShowExits #WaitTurns FDispFirstRoom FBattleSystem"
- " EPlayerName FPromptName EPlayerDesc ZTask ZPosition ZParentObject"
- " ZPlayerGender FEightPointCompass TNoScoreNotify FSound FGraphics"
- " FStatusBox EStatusBoxText FEmbedded"},
- {"ROOM",
- "$Short $Long $LastDesc [8]<ROOM_EXIT>Exits $AddDesc1 #Task1 $AddDesc2"
- " #Task2 #Obj $AltDesc #TypeHideObjects |V380_ROOM:_Alts_|"},
- {"ROOM_EXIT",
- "{V390_V380_ROOM_EXIT:#Dest_#Var1_#Var2_ZVar3}"},
- {"OBJECT",
- "$Prefix $Short [1]$Alias BStatic $Description #InitialPosition #Task"
- " BTaskNotDone $AltDesc ?BStatic:<ROOM_LIST1>Where #SurfaceContainer"
- " FSurface ?#SurfaceContainer=2:TSurface FContainer"
- " ?#SurfaceContainer=1:TContainer #Capacity |V380_OBJECT:#Capacity*10+2|"
- " ?!BStatic:BWearable,#SizeWeight,#Parent ?BStatic:{OBJECT:#Parent}"
- " #Openable |V380_OBJECT:_Openable_,Key| #SitLie ?!BStatic:BEdible BReadable"
- " ?BReadable:$ReadText ?!BStatic:BWeapon ZCurrentState FListFlag"
- " EInRoomDesc ZOnlyWhenNotMoved"},
- {"ROOM_LIST1",
- "#Type {ROOM_LIST1}"},
- {"TASK",
- "W$Command $CompleteText $ReverseMessage $RepeatText $AdditionalMessage"
- " #ShowRoomDesc BRepeatable #Score BSingleScore [6]<TASK_MOVE>Movements"
- " BReversible W$ReverseCommand #WearObj1 #WearObj2 #HoldObj1 #HoldObj2"
- " #HoldObj3 #Obj1 #Task BTaskNotDone $TaskMsg $HoldMsg $WearMsg $CompanyMsg"
- " BNotInSameRoom #NPC $Obj1Msg #Obj1Room <ROOM_LIST0>Where BKillsPlayer"
- " BHoldingSameRoom $Question ?$Question:$Hint1,$Hint2 #Obj2"
- " ?!#Obj2=0:#Obj2Var1,#Obj2Var2,$Obj2Msg BWinGame |V380_TASK:_Actions_|"
- " |V380_TASK:_Restrictions_|"},
- {"TASK_MOVE",
- "#Var1 #Var2 #Var3"},
- {"ROOM_LIST0",
- "#Type {ROOM_LIST0}"},
- {"EVENT",
- "$Short #StarterType ?#StarterType=2:#StartTime,#EndTime"
- " ?#StarterType=3:#TaskNum #RestartType BTaskFinished #Time1 #Time2"
- " $StartText $LookText $FinishText <ROOM_LIST0>Where #PauseTask"
- " BPauserCompleted #PrefTime1 $PrefText1 #ResumeTask BResumerCompleted"
- " #PrefTime2 $PrefText2 #Obj2 #Obj2Dest #Obj3 #Obj3Dest #Obj1 #Obj1Dest"
- " #TaskAffected"},
- {"NPC",
- "$Name $Prefix [1]$Alias $Descr #StartRoom $AltText #Task V<TOPIC>Topics"
- " V<WALK>Walks BShowEnterExit ?BShowEnterExit:$EnterText,$ExitText"
- " $InRoomText ZGender"},
- {"TOPIC",
- "$Subject $Reply #Task $AltReply"},
- {"WALK",
- "#NumStops BLoop #StartTask #CharTask #MeetObject"
- " ?!#MeetObject=0:|V380_WALK:_MeetObject_| #ObjectTask ZMeetChar"
- " {WALK:#Rooms_#Times} ZStoppingTask EChangedDesc"},
- {"ROOM_GROUP",
- "$Name {ROOM_GROUP:[]BList}"},
- {"SYNONYM",
- "$Replacement $Original"},
- {NULL, NULL}
+ {
+ "_GAME_",
+ "<HEADER>Header <GLOBAL>Globals V<ROOM>Rooms V<OBJECT>Objects V<TASK>Tasks"
+ " V<EVENT>Events V<NPC>NPCs V<ROOM_GROUP>RoomGroups V<SYNONYM>Synonyms"
+ " FCustomFont $CompileDate sPassword |V380_GLOBAL:_MaxScore_|"
+ " |V380_OBJECT:_InitialPositions_|"
+ },
+ {
+ "HEADER",
+ "MStartupText #StartRoom MWinText"
+ },
+ {
+ "GLOBAL",
+ "$GameName $GameAuthor #MaxCarried |V380_MaxSize_MaxWt_| $DontUnderstand"
+ " #Perspective BShowExits #WaitTurns FDispFirstRoom FBattleSystem"
+ " EPlayerName FPromptName EPlayerDesc ZTask ZPosition ZParentObject"
+ " ZPlayerGender FEightPointCompass TNoScoreNotify FSound FGraphics"
+ " FStatusBox EStatusBoxText FEmbedded"
+ },
+ {
+ "ROOM",
+ "$Short $Long $LastDesc [8]<ROOM_EXIT>Exits $AddDesc1 #Task1 $AddDesc2"
+ " #Task2 #Obj $AltDesc #TypeHideObjects |V380_ROOM:_Alts_|"
+ },
+ {
+ "ROOM_EXIT",
+ "{V390_V380_ROOM_EXIT:#Dest_#Var1_#Var2_ZVar3}"
+ },
+ {
+ "OBJECT",
+ "$Prefix $Short [1]$Alias BStatic $Description #InitialPosition #Task"
+ " BTaskNotDone $AltDesc ?BStatic:<ROOM_LIST1>Where #SurfaceContainer"
+ " FSurface ?#SurfaceContainer=2:TSurface FContainer"
+ " ?#SurfaceContainer=1:TContainer #Capacity |V380_OBJECT:#Capacity*10+2|"
+ " ?!BStatic:BWearable,#SizeWeight,#Parent ?BStatic:{OBJECT:#Parent}"
+ " #Openable |V380_OBJECT:_Openable_,Key| #SitLie ?!BStatic:BEdible BReadable"
+ " ?BReadable:$ReadText ?!BStatic:BWeapon ZCurrentState FListFlag"
+ " EInRoomDesc ZOnlyWhenNotMoved"
+ },
+ {
+ "ROOM_LIST1",
+ "#Type {ROOM_LIST1}"
+ },
+ {
+ "TASK",
+ "W$Command $CompleteText $ReverseMessage $RepeatText $AdditionalMessage"
+ " #ShowRoomDesc BRepeatable #Score BSingleScore [6]<TASK_MOVE>Movements"
+ " BReversible W$ReverseCommand #WearObj1 #WearObj2 #HoldObj1 #HoldObj2"
+ " #HoldObj3 #Obj1 #Task BTaskNotDone $TaskMsg $HoldMsg $WearMsg $CompanyMsg"
+ " BNotInSameRoom #NPC $Obj1Msg #Obj1Room <ROOM_LIST0>Where BKillsPlayer"
+ " BHoldingSameRoom $Question ?$Question:$Hint1,$Hint2 #Obj2"
+ " ?!#Obj2=0:#Obj2Var1,#Obj2Var2,$Obj2Msg BWinGame |V380_TASK:_Actions_|"
+ " |V380_TASK:_Restrictions_|"
+ },
+ {
+ "TASK_MOVE",
+ "#Var1 #Var2 #Var3"
+ },
+ {
+ "ROOM_LIST0",
+ "#Type {ROOM_LIST0}"
+ },
+ {
+ "EVENT",
+ "$Short #StarterType ?#StarterType=2:#StartTime,#EndTime"
+ " ?#StarterType=3:#TaskNum #RestartType BTaskFinished #Time1 #Time2"
+ " $StartText $LookText $FinishText <ROOM_LIST0>Where #PauseTask"
+ " BPauserCompleted #PrefTime1 $PrefText1 #ResumeTask BResumerCompleted"
+ " #PrefTime2 $PrefText2 #Obj2 #Obj2Dest #Obj3 #Obj3Dest #Obj1 #Obj1Dest"
+ " #TaskAffected"
+ },
+ {
+ "NPC",
+ "$Name $Prefix [1]$Alias $Descr #StartRoom $AltText #Task V<TOPIC>Topics"
+ " V<WALK>Walks BShowEnterExit ?BShowEnterExit:$EnterText,$ExitText"
+ " $InRoomText ZGender"
+ },
+ {
+ "TOPIC",
+ "$Subject $Reply #Task $AltReply"
+ },
+ {
+ "WALK",
+ "#NumStops BLoop #StartTask #CharTask #MeetObject"
+ " ?!#MeetObject=0:|V380_WALK:_MeetObject_| #ObjectTask ZMeetChar"
+ " {WALK:#Rooms_#Times} ZStoppingTask EChangedDesc"
+ },
+ {
+ "ROOM_GROUP",
+ "$Name {ROOM_GROUP:[]BList}"
+ },
+ {
+ "SYNONYM",
+ "$Replacement $Original"
+ },
+ {NULL, NULL}
};
@@ -331,21 +456,19 @@ static const sc_parse_schema_t V380_PARSE_SCHEMA[] = {
* Select one of the parse schemata based on a TAF file.
*/
static const sc_parse_schema_t *
-parse_select_schema (sc_tafref_t taf)
-{
- /* Switch based on the TAF file version. */
- switch (taf_get_version (taf))
- {
- case TAF_VERSION_400:
- return V400_PARSE_SCHEMA;
- case TAF_VERSION_390:
- return V390_PARSE_SCHEMA;
- case TAF_VERSION_380:
- return V380_PARSE_SCHEMA;
- default:
- sc_fatal ("parse_select_schema: invalid TAF file version\n");
- return NULL;
- }
+parse_select_schema(sc_tafref_t taf) {
+ /* Switch based on the TAF file version. */
+ switch (taf_get_version(taf)) {
+ case TAF_VERSION_400:
+ return V400_PARSE_SCHEMA;
+ case TAF_VERSION_390:
+ return V390_PARSE_SCHEMA;
+ case TAF_VERSION_380:
+ return V380_PARSE_SCHEMA;
+ default:
+ sc_fatal("parse_select_schema: invalid TAF file version\n");
+ return NULL;
+ }
}
@@ -377,24 +500,22 @@ static sc_int parse_depth = 0;
* off on unwind.
*/
static void
-parse_push_key (sc_vartype_t vt_key, sc_char type)
-{
- if (parse_depth == PARSE_MAX_DEPTH)
- sc_fatal ("parse_push_key: stack overrun\n");
-
- /* Push the key, and its associated type. */
- parse_vt_key[parse_depth] = vt_key;
- parse_format[parse_depth] = type;
- parse_depth++;
+parse_push_key(sc_vartype_t vt_key, sc_char type) {
+ if (parse_depth == PARSE_MAX_DEPTH)
+ sc_fatal("parse_push_key: stack overrun\n");
+
+ /* Push the key, and its associated type. */
+ parse_vt_key[parse_depth] = vt_key;
+ parse_format[parse_depth] = type;
+ parse_depth++;
}
static void
-parse_pop_key (void)
-{
- /* Check the stack has something to pop, then pop it. */
- if (parse_depth == 0)
- sc_fatal ("parse_pop_key: stack underrun\n");
- parse_depth--;
+parse_pop_key(void) {
+ /* Check the stack has something to pop, then pop it. */
+ if (parse_depth == 0)
+ sc_fatal("parse_pop_key: stack underrun\n");
+ parse_depth--;
}
@@ -406,35 +527,30 @@ parse_pop_key (void)
* value
*/
static void
-parse_retrieve_stack (sc_char format[], sc_vartype_t vt_key[], sc_int *depth)
-{
- sc_int index_;
-
- /* Switch index-string key pairs. */
- for (index_ = 0; index_ < parse_depth; index_++)
- {
- if (index_ < parse_depth - 1
- && parse_format[index_] == PROP_KEY_INTEGER
- && parse_format[index_ + 1] == PROP_KEY_STRING)
- {
- /* Swap format and key elements. */
- format[index_] = parse_format[index_ + 1];
- format[index_ + 1] = parse_format[index_];
- vt_key[index_] = parse_vt_key[index_ + 1];
- vt_key[index_ + 1] = parse_vt_key[index_];
-
- index_++;
- }
- else
- {
- /* Simple copy of format and key elements. */
- format[index_] = parse_format[index_];
- vt_key[index_] = parse_vt_key[index_];
- }
- }
-
- /* Return the parse depth. */
- *depth = parse_depth;
+parse_retrieve_stack(sc_char format[], sc_vartype_t vt_key[], sc_int *depth) {
+ sc_int index_;
+
+ /* Switch index-string key pairs. */
+ for (index_ = 0; index_ < parse_depth; index_++) {
+ if (index_ < parse_depth - 1
+ && parse_format[index_] == PROP_KEY_INTEGER
+ && parse_format[index_ + 1] == PROP_KEY_STRING) {
+ /* Swap format and key elements. */
+ format[index_] = parse_format[index_ + 1];
+ format[index_ + 1] = parse_format[index_];
+ vt_key[index_] = parse_vt_key[index_ + 1];
+ vt_key[index_ + 1] = parse_vt_key[index_];
+
+ index_++;
+ } else {
+ /* Simple copy of format and key elements. */
+ format[index_] = parse_format[index_];
+ vt_key[index_] = parse_vt_key[index_];
+ }
+ }
+
+ /* Return the parse depth. */
+ *depth = parse_depth;
}
@@ -445,33 +561,31 @@ parse_retrieve_stack (sc_char format[], sc_vartype_t vt_key[], sc_int *depth)
* be a bad game.
*/
static void
-parse_stack_backtrace (void)
-{
- sc_vartype_t vt_key[PARSE_MAX_DEPTH];
- sc_char format[PARSE_MAX_DEPTH];
- sc_int depth, index_;
-
- parse_retrieve_stack (format, vt_key, &depth);
-
- sc_error ("parse_stack_backtrace: version %s schema parsed to depth %ld\n",
- (parse_schema == V400_PARSE_SCHEMA) ? "4.00" :
- (parse_schema == V390_PARSE_SCHEMA) ? "3.90" :
- (parse_schema == V380_PARSE_SCHEMA) ? "3.80" : "[Invalid]",
- depth);
-
- sc_error ("parse_stack_backtrace: parse stack backtrace follows...\n");
- for (index_ = 0; index_ < depth; index_++)
- {
- sc_char type;
-
- type = format[index_];
- if (type == PROP_KEY_INTEGER)
- sc_error ("%2ld - [%c] %ld\n", index_, type, vt_key[index_].integer);
- else if (type == PROP_KEY_STRING)
- sc_error ("%2ld - [%c] \"%s\"\n", index_, type, vt_key[index_].string);
- else
- sc_error ("%2ld - [%c] %p\n", index_, type, vt_key[index_].voidp);
- }
+parse_stack_backtrace(void) {
+ sc_vartype_t vt_key[PARSE_MAX_DEPTH];
+ sc_char format[PARSE_MAX_DEPTH];
+ sc_int depth, index_;
+
+ parse_retrieve_stack(format, vt_key, &depth);
+
+ sc_error("parse_stack_backtrace: version %s schema parsed to depth %ld\n",
+ (parse_schema == V400_PARSE_SCHEMA) ? "4.00" :
+ (parse_schema == V390_PARSE_SCHEMA) ? "3.90" :
+ (parse_schema == V380_PARSE_SCHEMA) ? "3.80" : "[Invalid]",
+ depth);
+
+ sc_error("parse_stack_backtrace: parse stack backtrace follows...\n");
+ for (index_ = 0; index_ < depth; index_++) {
+ sc_char type;
+
+ type = format[index_];
+ if (type == PROP_KEY_INTEGER)
+ sc_error("%2ld - [%c] %ld\n", index_, type, vt_key[index_].integer);
+ else if (type == PROP_KEY_STRING)
+ sc_error("%2ld - [%c] \"%s\"\n", index_, type, vt_key[index_].string);
+ else
+ sc_error("%2ld - [%c] %p\n", index_, type, vt_key[index_].voidp);
+ }
}
@@ -482,48 +596,46 @@ parse_stack_backtrace (void)
* Write or read a property based on the keys amassed so far.
*/
static void
-parse_put_property (sc_vartype_t vt_value, sc_char type)
-{
- sc_vartype_t vt_key[PARSE_MAX_DEPTH];
- sc_char format[PARSE_MAX_DEPTH + 4];
- sc_int depth;
-
- /* Retrieve the adjusted stack. */
- parse_retrieve_stack (format + 3, vt_key, &depth);
-
- /* Complete the format for the property put. */
- format[0] = type;
- format[1] = '-';
- format[2] = '>';
- format[depth + 3] = NUL;
-
- /* Store the property under the stacked keys. */
- assert (parse_bundle);
- prop_put (parse_bundle, format, vt_value, vt_key);
+parse_put_property(sc_vartype_t vt_value, sc_char type) {
+ sc_vartype_t vt_key[PARSE_MAX_DEPTH];
+ sc_char format[PARSE_MAX_DEPTH + 4];
+ sc_int depth;
+
+ /* Retrieve the adjusted stack. */
+ parse_retrieve_stack(format + 3, vt_key, &depth);
+
+ /* Complete the format for the property put. */
+ format[0] = type;
+ format[1] = '-';
+ format[2] = '>';
+ format[depth + 3] = NUL;
+
+ /* Store the property under the stacked keys. */
+ assert(parse_bundle);
+ prop_put(parse_bundle, format, vt_value, vt_key);
}
static sc_bool
-parse_get_property (sc_vartype_t *vt_rvalue, sc_char type)
-{
- sc_vartype_t vt_key[PARSE_MAX_DEPTH];
- sc_char format[PARSE_MAX_DEPTH + 4];
- sc_int depth;
- sc_bool status;
-
- /* Retrieve the adjusted stack. */
- parse_retrieve_stack (format + 3, vt_key, &depth);
-
- /* Complete the format for the property put. */
- format[0] = type;
- format[1] = '<';
- format[2] = '-';
- format[depth + 3] = NUL;
-
- /* Retrieve the property using the stacked keys. */
- assert (parse_bundle);
- status = prop_get (parse_bundle, format, vt_rvalue, vt_key);
-
- return status;
+parse_get_property(sc_vartype_t *vt_rvalue, sc_char type) {
+ sc_vartype_t vt_key[PARSE_MAX_DEPTH];
+ sc_char format[PARSE_MAX_DEPTH + 4];
+ sc_int depth;
+ sc_bool status;
+
+ /* Retrieve the adjusted stack. */
+ parse_retrieve_stack(format + 3, vt_key, &depth);
+
+ /* Complete the format for the property put. */
+ format[0] = type;
+ format[1] = '<';
+ format[2] = '-';
+ format[depth + 3] = NUL;
+
+ /* Retrieve the property using the stacked keys. */
+ assert(parse_bundle);
+ status = prop_get(parse_bundle, format, vt_rvalue, vt_key);
+
+ return status;
}
@@ -535,14 +647,13 @@ parse_get_property (sc_vartype_t *vt_rvalue, sc_char type)
* no such node exists.
*/
static sc_int
-parse_get_child_count (void)
-{
- sc_vartype_t vt_rvalue;
+parse_get_child_count(void) {
+ sc_vartype_t vt_rvalue;
- if (!parse_get_property (&vt_rvalue, PROP_INTEGER))
- vt_rvalue.integer = 0;
+ if (!parse_get_property(&vt_rvalue, PROP_INTEGER))
+ vt_rvalue.integer = 0;
- return vt_rvalue.integer;
+ return vt_rvalue.integer;
}
@@ -555,36 +666,33 @@ parse_get_child_count (void)
* a fatal error if the property does not exist.
*/
static sc_int
-parse_get_integer_property (void)
-{
- sc_vartype_t vt_rvalue;
+parse_get_integer_property(void) {
+ sc_vartype_t vt_rvalue;
- if (!parse_get_property (&vt_rvalue, PROP_INTEGER))
- sc_fatal ("parse_get_integer_property: missing property\n");
+ if (!parse_get_property(&vt_rvalue, PROP_INTEGER))
+ sc_fatal("parse_get_integer_property: missing property\n");
- return vt_rvalue.integer;
+ return vt_rvalue.integer;
}
static sc_bool
-parse_get_boolean_property (void)
-{
- sc_vartype_t vt_rvalue;
+parse_get_boolean_property(void) {
+ sc_vartype_t vt_rvalue;
- if (!parse_get_property (&vt_rvalue, PROP_BOOLEAN))
- sc_fatal ("parse_get_boolean_property: missing property\n");
+ if (!parse_get_property(&vt_rvalue, PROP_BOOLEAN))
+ sc_fatal("parse_get_boolean_property: missing property\n");
- return vt_rvalue.boolean;
+ return vt_rvalue.boolean;
}
static const sc_char *
-parse_get_string_property (void)
-{
- sc_vartype_t vt_rvalue;
+parse_get_string_property(void) {
+ sc_vartype_t vt_rvalue;
- if (!parse_get_property (&vt_rvalue, PROP_STRING))
- sc_fatal ("parse_get_string_property: missing property\n");
+ if (!parse_get_property(&vt_rvalue, PROP_STRING))
+ sc_fatal("parse_get_string_property: missing property\n");
- return vt_rvalue.string;
+ return vt_rvalue.string;
}
@@ -606,132 +714,121 @@ static sc_bool parse_use_pushback = FALSE;
* TAF line pushback.
*/
static const sc_char *
-parse_get_taf_string (void)
-{
- const sc_char *line;
-
- /* If pushback requested, use that instead of reading. */
- if (parse_use_pushback)
- {
- /* Use the pushback line, and clear the request. */
- assert (parse_pushback_line);
- line = parse_pushback_line;
- parse_use_pushback = FALSE;
- }
- else
- {
- /* Get the next line, and complain if absent. */
- line = taf_next_line (parse_taf);
- if (!line)
- {
- sc_error ("parse_get_taf_string:"
- " out of TAF data at line %ld\n", parse_tafline);
- parse_stack_backtrace ();
- longjmp (parse_taf_error, 1);
- }
-
- /* Note this line for possible pushback. */
- parse_pushback_line = line;
- }
-
- /* Print out the line we're parsing if tracing. */
- if (parse_trace)
- sc_trace ("Parse: read in line %ld : %s\n", parse_tafline, line);
-
- parse_tafline++;
- return line;
+parse_get_taf_string(void) {
+ const sc_char *line;
+
+ /* If pushback requested, use that instead of reading. */
+ if (parse_use_pushback) {
+ /* Use the pushback line, and clear the request. */
+ assert(parse_pushback_line);
+ line = parse_pushback_line;
+ parse_use_pushback = FALSE;
+ } else {
+ /* Get the next line, and complain if absent. */
+ line = taf_next_line(parse_taf);
+ if (!line) {
+ sc_error("parse_get_taf_string:"
+ " out of TAF data at line %ld\n", parse_tafline);
+ parse_stack_backtrace();
+ longjmp(parse_taf_error, 1);
+ }
+
+ /* Note this line for possible pushback. */
+ parse_pushback_line = line;
+ }
+
+ /* Print out the line we're parsing if tracing. */
+ if (parse_trace)
+ sc_trace("Parse: read in line %ld : %s\n", parse_tafline, line);
+
+ parse_tafline++;
+ return line;
}
static sc_int
-parse_get_taf_integer (void)
-{
- const sc_char *line;
- sc_int integer;
-
- /* Get line, and scan for a single integer; return it. */
- line = parse_get_taf_string ();
- if (sscanf (line, "%ld", &integer) != 1)
- {
- sc_error ("parse_get_taf_integer:"
- " invalid integer at line %ld\n", parse_tafline - 1);
- parse_stack_backtrace ();
- longjmp (parse_taf_error, 1);
- }
-
- return integer;
+parse_get_taf_integer(void) {
+ const sc_char *line;
+ sc_int integer;
+
+ /* Get line, and scan for a single integer; return it. */
+ line = parse_get_taf_string();
+ if (sscanf(line, "%ld", &integer) != 1) {
+ sc_error("parse_get_taf_integer:"
+ " invalid integer at line %ld\n", parse_tafline - 1);
+ parse_stack_backtrace();
+ longjmp(parse_taf_error, 1);
+ }
+
+ return integer;
}
static sc_bool
-parse_get_taf_boolean (void)
-{
- const sc_char *line;
- sc_uint boolean;
-
- /*
- * Get line, and scan for a single integer; check it's a valid-looking flag,
- * and return it.
- */
- line = parse_get_taf_string ();
- if (sscanf (line, "%lu", &boolean) != 1)
- {
- sc_error ("parse_get_taf_boolean:"
- " invalid boolean at line %ld\n", parse_tafline - 1);
- parse_stack_backtrace ();
- longjmp (parse_taf_error, 1);
- }
- if (boolean != 0 && boolean != 1)
- {
- sc_error ("parse_get_taf_boolean:"
- " warning: suspect boolean at line %ld\n", parse_tafline - 1);
- }
-
- return boolean != 0;
+parse_get_taf_boolean(void) {
+ const sc_char *line;
+ sc_uint boolean;
+
+ /*
+ * Get line, and scan for a single integer; check it's a valid-looking flag,
+ * and return it.
+ */
+ line = parse_get_taf_string();
+ if (sscanf(line, "%lu", &boolean) != 1) {
+ sc_error("parse_get_taf_boolean:"
+ " invalid boolean at line %ld\n", parse_tafline - 1);
+ parse_stack_backtrace();
+ longjmp(parse_taf_error, 1);
+ }
+ if (boolean != 0 && boolean != 1) {
+ sc_error("parse_get_taf_boolean:"
+ " warning: suspect boolean at line %ld\n", parse_tafline - 1);
+ }
+
+ return boolean != 0;
}
static void
-parse_taf_pushback (void)
-{
- if (parse_use_pushback || !parse_pushback_line)
- sc_fatal ("parse_taf_pushback: too much pushback requested\n");
-
- /* Set pushback request, and decrement line counter. */
- parse_use_pushback = TRUE;
- parse_tafline--;
-
- /* Note pushback for tracing purposes. */
- if (parse_trace)
- sc_trace ("Parse: push back at line %ld\n", parse_tafline);
+parse_taf_pushback(void) {
+ if (parse_use_pushback || !parse_pushback_line)
+ sc_fatal("parse_taf_pushback: too much pushback requested\n");
+
+ /* Set pushback request, and decrement line counter. */
+ parse_use_pushback = TRUE;
+ parse_tafline--;
+
+ /* Note pushback for tracing purposes. */
+ if (parse_trace)
+ sc_trace("Parse: push back at line %ld\n", parse_tafline);
}
/* Enumerations of parse types found in the parse schema. */
-enum
-{ PARSE_INTEGER = '#',
- PARSE_DEFAULT_ZERO = 'Z',
- PARSE_BOOLEAN = 'B',
- PARSE_DEFAULT_FALSE = 'F',
- PARSE_DEFAULT_TRUE = 'T',
- PARSE_STRING = '$',
- PARSE_DEFAULT_EMPTY = 'E',
- PARSE_MULTILINE = 'M',
- PARSE_VECTOR = 'V',
- PARSE_VECTOR_ALTERNATE = 'W',
- PARSE_ARRAY = '[',
- PARSE_EXPRESSION = '?',
- PARSE_EXPRESSION_NOT = '!',
- PARSE_GLOBAL_EXPRESSION = 'G',
- PARSE_CLASS = '<',
- PARSE_FIXUP = '|',
- PARSE_SPECIAL = '{',
- PARSE_IGNORE_INTEGER = 'i',
- PARSE_IGNORE_BOOLEAN = 'b',
- PARSE_IGNORE_STRING = 's'
+enum {
+ PARSE_INTEGER = '#',
+ PARSE_DEFAULT_ZERO = 'Z',
+ PARSE_BOOLEAN = 'B',
+ PARSE_DEFAULT_FALSE = 'F',
+ PARSE_DEFAULT_TRUE = 'T',
+ PARSE_STRING = '$',
+ PARSE_DEFAULT_EMPTY = 'E',
+ PARSE_MULTILINE = 'M',
+ PARSE_VECTOR = 'V',
+ PARSE_VECTOR_ALTERNATE = 'W',
+ PARSE_ARRAY = '[',
+ PARSE_EXPRESSION = '?',
+ PARSE_EXPRESSION_NOT = '!',
+ PARSE_GLOBAL_EXPRESSION = 'G',
+ PARSE_CLASS = '<',
+ PARSE_FIXUP = '|',
+ PARSE_SPECIAL = '{',
+ PARSE_IGNORE_INTEGER = 'i',
+ PARSE_IGNORE_BOOLEAN = 'b',
+ PARSE_IGNORE_STRING = 's'
};
/* Forward declarations of parse functions for recursion. */
-static void parse_element (const sc_char *element);
-static void parse_class (const sc_char *class_);
-static void parse_descriptor (const sc_char *descriptor);
+static void parse_element(const sc_char *element);
+static void parse_class(const sc_char *class_);
+static void parse_descriptor(const sc_char *descriptor);
/*
* parse_array()
@@ -739,33 +836,31 @@ static void parse_descriptor (const sc_char *descriptor);
* Parse a descriptor [] array.
*/
static void
-parse_array (const sc_char *array)
-{
- sc_int count, index_;
- sc_char element[PARSE_TEMP_LENGTH];
+parse_array(const sc_char *array) {
+ sc_int count, index_;
+ sc_char element[PARSE_TEMP_LENGTH];
- if (parse_trace)
- sc_trace ("Parse: entering array %s\n", array);
+ if (parse_trace)
+ sc_trace("Parse: entering array %s\n", array);
- /* Find the count of elements in the array, and the element itself. */
- if (sscanf (array, "[%ld]%[^ ]", &count, element) != 2)
- sc_fatal ("parse_array: bad array, %s\n", array);
+ /* Find the count of elements in the array, and the element itself. */
+ if (sscanf(array, "[%ld]%[^ ]", &count, element) != 2)
+ sc_fatal("parse_array: bad array, %s\n", array);
- /* Parse the element for array count iterations, each a key. */
- for (index_ = 0; index_ < count; index_++)
- {
- sc_vartype_t vt_key;
+ /* Parse the element for array count iterations, each a key. */
+ for (index_ = 0; index_ < count; index_++) {
+ sc_vartype_t vt_key;
- vt_key.integer = index_;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
+ vt_key.integer = index_;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
- parse_element (element);
+ parse_element(element);
- parse_pop_key ();
- }
+ parse_pop_key();
+ }
- if (parse_trace)
- sc_trace ("Parse: leaving array %s\n", array);
+ if (parse_trace)
+ sc_trace("Parse: leaving array %s\n", array);
}
@@ -777,54 +872,50 @@ parse_array (const sc_char *array)
* Parse a variable-length vector of properties.
*/
static void
-parse_vector_common (const sc_char *vector, sc_int count)
-{
- sc_int index_;
+parse_vector_common(const sc_char *vector, sc_int count) {
+ sc_int index_;
- /* Parse the vector property count times, pushing a key on each. */
- for (index_ = 0; index_ < count; index_++)
- {
- sc_vartype_t vt_key;
+ /* Parse the vector property count times, pushing a key on each. */
+ for (index_ = 0; index_ < count; index_++) {
+ sc_vartype_t vt_key;
- vt_key.integer = index_;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
+ vt_key.integer = index_;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
- parse_element (vector + 1);
+ parse_element(vector + 1);
- parse_pop_key ();
- }
+ parse_pop_key();
+ }
}
static void
-parse_vector (const sc_char *vector)
-{
- sc_int count;
+parse_vector(const sc_char *vector) {
+ sc_int count;
- if (parse_trace)
- sc_trace ("Parse: entering vector %s\n", vector);
+ if (parse_trace)
+ sc_trace("Parse: entering vector %s\n", vector);
- /* Find the count of elements in the vector, and parse. */
- count = parse_get_taf_integer ();
- parse_vector_common (vector, count);
+ /* Find the count of elements in the vector, and parse. */
+ count = parse_get_taf_integer();
+ parse_vector_common(vector, count);
- if (parse_trace)
- sc_trace ("Parse: leaving vector %s\n", vector);
+ if (parse_trace)
+ sc_trace("Parse: leaving vector %s\n", vector);
}
static void
-parse_vector_alternate (const sc_char *vector)
-{
- sc_int count;
+parse_vector_alternate(const sc_char *vector) {
+ sc_int count;
- if (parse_trace)
- sc_trace ("Parse: entering alternate vector %s\n", vector);
+ if (parse_trace)
+ sc_trace("Parse: entering alternate vector %s\n", vector);
- /* Element count, this is a vector described by size - 1. */
- count = parse_get_taf_integer () + 1;
- parse_vector_common (vector, count);
+ /* Element count, this is a vector described by size - 1. */
+ count = parse_get_taf_integer() + 1;
+ parse_vector_common(vector, count);
- if (parse_trace)
- sc_trace ("Parse: leaving alternate vector %s\n", vector);
+ if (parse_trace)
+ sc_trace("Parse: leaving alternate vector %s\n", vector);
}
@@ -835,112 +926,105 @@ parse_vector_alternate (const sc_char *vector)
* Parse a conditional field definition, with runtime test.
*/
static sc_bool
-parse_test_expression (const sc_char *test_expression)
-{
- sc_vartype_t vt_key;
- sc_char plhs[PARSE_TEMP_LENGTH];
- sc_int rhs;
- sc_bool retval = FALSE;
-
- /* Identify the type of expression to evaluate. */
- switch (test_expression[0])
- {
- case PARSE_BOOLEAN:
- /* Read boolean property and return its value. */
- vt_key.string = test_expression + 1;
- parse_push_key (vt_key, PROP_KEY_STRING);
- retval = parse_get_boolean_property ();
- parse_pop_key ();
- break;
-
- case PARSE_INTEGER:
- /* Get the left and right sides of = comparison. */
- if (sscanf (test_expression, "#%[^=]=%ld", plhs, &rhs) != 2)
- {
- sc_fatal ("parse_test_expression: bad = compare, %s\n",
- test_expression + 1);
- }
-
- /* Read integer property and return comparison. */
- vt_key.string = plhs;
- parse_push_key (vt_key, PROP_KEY_STRING);
- retval = (parse_get_integer_property () == rhs);
- parse_pop_key ();
- break;
-
- case PARSE_STRING:
- /* Read property and return TRUE if not an empty string. */
- vt_key.string = test_expression + 1;
- parse_push_key (vt_key, PROP_KEY_STRING);
- retval = !sc_strempty (parse_get_string_property ());
- parse_pop_key ();
- break;
-
- case PARSE_GLOBAL_EXPRESSION:
- {
- sc_vartype_t vt_gkey[2];
-
- /* Read the given Global boolean property and return it. */
- vt_gkey[0].string = "Globals";
- vt_gkey[1].string = test_expression + 1;
- retval = prop_get_boolean (parse_bundle, "B<-ss", vt_gkey);
- break;
- }
-
- default:
- sc_fatal ("parse_test_expression:"
- " bad expression, %s\n", test_expression + 1);
- }
-
- if (parse_trace)
- sc_trace ("Parse: expression is %s\n", retval ? "true" : "false");
-
- return retval;
+parse_test_expression(const sc_char *test_expression) {
+ sc_vartype_t vt_key;
+ sc_char plhs[PARSE_TEMP_LENGTH];
+ sc_int rhs;
+ sc_bool retval = FALSE;
+
+ /* Identify the type of expression to evaluate. */
+ switch (test_expression[0]) {
+ case PARSE_BOOLEAN:
+ /* Read boolean property and return its value. */
+ vt_key.string = test_expression + 1;
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ retval = parse_get_boolean_property();
+ parse_pop_key();
+ break;
+
+ case PARSE_INTEGER:
+ /* Get the left and right sides of = comparison. */
+ if (sscanf(test_expression, "#%[^=]=%ld", plhs, &rhs) != 2) {
+ sc_fatal("parse_test_expression: bad = compare, %s\n",
+ test_expression + 1);
+ }
+
+ /* Read integer property and return comparison. */
+ vt_key.string = plhs;
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ retval = (parse_get_integer_property() == rhs);
+ parse_pop_key();
+ break;
+
+ case PARSE_STRING:
+ /* Read property and return TRUE if not an empty string. */
+ vt_key.string = test_expression + 1;
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ retval = !sc_strempty(parse_get_string_property());
+ parse_pop_key();
+ break;
+
+ case PARSE_GLOBAL_EXPRESSION: {
+ sc_vartype_t vt_gkey[2];
+
+ /* Read the given Global boolean property and return it. */
+ vt_gkey[0].string = "Globals";
+ vt_gkey[1].string = test_expression + 1;
+ retval = prop_get_boolean(parse_bundle, "B<-ss", vt_gkey);
+ break;
+ }
+
+ default:
+ sc_fatal("parse_test_expression:"
+ " bad expression, %s\n", test_expression + 1);
+ }
+
+ if (parse_trace)
+ sc_trace("Parse: expression is %s\n", retval ? "true" : "false");
+
+ return retval;
}
static void
-parse_expression (const sc_char *expression)
-{
- sc_char test_expression[PARSE_TEMP_LENGTH];
- sc_bool is_present;
-
- if (parse_trace)
- sc_trace ("Parse: entering expression %s\n", expression);
-
- /* Isolate the test part of the expression. */
- if (sscanf (expression, "?%[^:]", test_expression) != 1)
- sc_fatal ("parse_expression: bad expression, %s\n", expression);
-
- /* Handle the remainder of the expression only if test passes. */
- is_present = (test_expression[0] == PARSE_EXPRESSION_NOT)
- ? !parse_test_expression (test_expression + 1)
- : parse_test_expression (test_expression);
- if (is_present)
- {
- sc_int next;
-
- /*
- * Following the ':' may be a single element, or a comma-separated list.
- */
- for (next = strlen (test_expression) + 2; expression[next] != NUL; )
- {
- sc_char element[PARSE_TEMP_LENGTH];
-
- /* Get the next individual element to parse. */
- if (sscanf (expression + next, "%[^,]", element) != 1)
- sc_fatal ("parse_expression: bad list, %s\n", expression + next);
-
- /* Parse this isolated element. */
- parse_element (element);
-
- /* Advance to the start of the next element. */
- next += strlen (element);
- next += strspn (expression + next, ",");
- }
- }
-
- if (parse_trace)
- sc_trace ("Parse: leaving expression %s\n", expression);
+parse_expression(const sc_char *expression) {
+ sc_char test_expression[PARSE_TEMP_LENGTH];
+ sc_bool is_present;
+
+ if (parse_trace)
+ sc_trace("Parse: entering expression %s\n", expression);
+
+ /* Isolate the test part of the expression. */
+ if (sscanf(expression, "?%[^:]", test_expression) != 1)
+ sc_fatal("parse_expression: bad expression, %s\n", expression);
+
+ /* Handle the remainder of the expression only if test passes. */
+ is_present = (test_expression[0] == PARSE_EXPRESSION_NOT)
+ ? !parse_test_expression(test_expression + 1)
+ : parse_test_expression(test_expression);
+ if (is_present) {
+ sc_int next;
+
+ /*
+ * Following the ':' may be a single element, or a comma-separated list.
+ */
+ for (next = strlen(test_expression) + 2; expression[next] != NUL;) {
+ sc_char element[PARSE_TEMP_LENGTH];
+
+ /* Get the next individual element to parse. */
+ if (sscanf(expression + next, "%[^,]", element) != 1)
+ sc_fatal("parse_expression: bad list, %s\n", expression + next);
+
+ /* Parse this isolated element. */
+ parse_element(element);
+
+ /* Advance to the start of the next element. */
+ next += strlen(element);
+ next += strspn(expression + next, ",");
+ }
+ }
+
+ if (parse_trace)
+ sc_trace("Parse: leaving expression %s\n", expression);
}
@@ -951,46 +1035,43 @@ parse_expression (const sc_char *expression)
* string is malloc'ed, and the caller needs to handle that.
*/
static sc_char *
-parse_read_multiline (void)
-{
- const sc_byte *separator = NULL;
- const sc_char *line;
- sc_char *multiline;
-
- /* Select the appropriate multiline separator. */
- switch (taf_get_version (parse_taf))
- {
- case TAF_VERSION_400:
- separator = V400_SEPARATOR;
- break;
- case TAF_VERSION_390:
- separator = V390_SEPARATOR;
- break;
- case TAF_VERSION_380:
- separator = V380_SEPARATOR;
- break;
- default:
- sc_fatal ("parse_read_multiline: invalid TAF file version\n");
- break;
- }
-
- /* Take a simple copy of the first line. */
- line = parse_get_taf_string ();
- multiline = (sc_char *)sc_malloc (strlen (line) + 1);
- strcpy (multiline, line);
-
- /* Now concatenate until separator found. */
- line = parse_get_taf_string ();
- while (memcmp (line, separator, SEPARATOR_SIZE) != 0)
- {
- multiline = (sc_char *)sc_realloc (multiline,
- strlen (multiline) + strlen (line) + 2);
- strcat (multiline, "\n");
- strcat (multiline, line);
- line = parse_get_taf_string ();
- }
-
- return multiline;
+parse_read_multiline(void) {
+ const sc_byte *separator = NULL;
+ const sc_char *line;
+ sc_char *multiline;
+
+ /* Select the appropriate multiline separator. */
+ switch (taf_get_version(parse_taf)) {
+ case TAF_VERSION_400:
+ separator = V400_SEPARATOR;
+ break;
+ case TAF_VERSION_390:
+ separator = V390_SEPARATOR;
+ break;
+ case TAF_VERSION_380:
+ separator = V380_SEPARATOR;
+ break;
+ default:
+ sc_fatal("parse_read_multiline: invalid TAF file version\n");
+ break;
+ }
+
+ /* Take a simple copy of the first line. */
+ line = parse_get_taf_string();
+ multiline = (sc_char *)sc_malloc(strlen(line) + 1);
+ strcpy(multiline, line);
+
+ /* Now concatenate until separator found. */
+ line = parse_get_taf_string();
+ while (memcmp(line, separator, SEPARATOR_SIZE) != 0) {
+ multiline = (sc_char *)sc_realloc(multiline,
+ strlen(multiline) + strlen(line) + 2);
+ strcat(multiline, "\n");
+ strcat(multiline, line);
+ line = parse_get_taf_string();
+ }
+
+ return multiline;
}
@@ -1000,76 +1081,74 @@ parse_read_multiline (void)
* Common handler for string, integer, boolean, and multiline parse terminals.
*/
static void
-parse_terminal (const sc_char *terminal)
-{
- sc_vartype_t vt_key, vt_value;
-
- if (parse_trace)
- sc_trace ("Parse: entering terminal %s\n", terminal);
-
- /* Push the key string. */
- vt_key.string = terminal + 1;
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- /* Retrieve, or invent, then store the value. */
- switch (terminal[0])
- {
- case PARSE_INTEGER:
- vt_value.integer = parse_get_taf_integer ();
- parse_put_property (vt_value, PROP_INTEGER);
- break;
- case PARSE_DEFAULT_ZERO:
- vt_value.integer = 0;
- parse_put_property (vt_value, PROP_INTEGER);
- break;
-
- case PARSE_BOOLEAN:
- vt_value.boolean = parse_get_taf_boolean ();
- parse_put_property (vt_value, PROP_BOOLEAN);
- break;
- case PARSE_DEFAULT_FALSE:
- case PARSE_DEFAULT_TRUE:
- vt_value.boolean = (terminal[0] == PARSE_DEFAULT_TRUE);
- parse_put_property (vt_value, PROP_BOOLEAN);
- break;
-
- case PARSE_STRING:
- vt_value.string = parse_get_taf_string ();
- parse_put_property (vt_value, PROP_STRING);
- break;
- case PARSE_DEFAULT_EMPTY:
- vt_value.string = "";
- parse_put_property (vt_value, PROP_STRING);
- break;
-
- case PARSE_MULTILINE:
- /* Assign to and adopt mutable string rather than const string. */
- vt_value.mutable_string = parse_read_multiline ();
- parse_put_property (vt_value, PROP_STRING);
-
- assert (parse_bundle);
- prop_adopt (parse_bundle, vt_value.mutable_string);
- break;
-
- case PARSE_IGNORE_INTEGER:
- (void) parse_get_taf_integer ();
- break;
- case PARSE_IGNORE_BOOLEAN:
- (void) parse_get_taf_boolean ();
- break;
- case PARSE_IGNORE_STRING:
- (void) parse_get_taf_string ();
- break;
-
- default:
- sc_fatal ("parse_terminal: bad type, %c\n", terminal[0]);
- }
-
- /* Pop terminal key. */
- parse_pop_key ();
-
- if (parse_trace)
- sc_trace ("Parse: leaving terminal %s\n", terminal);
+parse_terminal(const sc_char *terminal) {
+ sc_vartype_t vt_key, vt_value;
+
+ if (parse_trace)
+ sc_trace("Parse: entering terminal %s\n", terminal);
+
+ /* Push the key string. */
+ vt_key.string = terminal + 1;
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ /* Retrieve, or invent, then store the value. */
+ switch (terminal[0]) {
+ case PARSE_INTEGER:
+ vt_value.integer = parse_get_taf_integer();
+ parse_put_property(vt_value, PROP_INTEGER);
+ break;
+ case PARSE_DEFAULT_ZERO:
+ vt_value.integer = 0;
+ parse_put_property(vt_value, PROP_INTEGER);
+ break;
+
+ case PARSE_BOOLEAN:
+ vt_value.boolean = parse_get_taf_boolean();
+ parse_put_property(vt_value, PROP_BOOLEAN);
+ break;
+ case PARSE_DEFAULT_FALSE:
+ case PARSE_DEFAULT_TRUE:
+ vt_value.boolean = (terminal[0] == PARSE_DEFAULT_TRUE);
+ parse_put_property(vt_value, PROP_BOOLEAN);
+ break;
+
+ case PARSE_STRING:
+ vt_value.string = parse_get_taf_string();
+ parse_put_property(vt_value, PROP_STRING);
+ break;
+ case PARSE_DEFAULT_EMPTY:
+ vt_value.string = "";
+ parse_put_property(vt_value, PROP_STRING);
+ break;
+
+ case PARSE_MULTILINE:
+ /* Assign to and adopt mutable string rather than const string. */
+ vt_value.mutable_string = parse_read_multiline();
+ parse_put_property(vt_value, PROP_STRING);
+
+ assert(parse_bundle);
+ prop_adopt(parse_bundle, vt_value.mutable_string);
+ break;
+
+ case PARSE_IGNORE_INTEGER:
+ (void) parse_get_taf_integer();
+ break;
+ case PARSE_IGNORE_BOOLEAN:
+ (void) parse_get_taf_boolean();
+ break;
+ case PARSE_IGNORE_STRING:
+ (void) parse_get_taf_string();
+ break;
+
+ default:
+ sc_fatal("parse_terminal: bad type, %c\n", terminal[0]);
+ }
+
+ /* Pop terminal key. */
+ parse_pop_key();
+
+ if (parse_trace)
+ sc_trace("Parse: leaving terminal %s\n", terminal);
}
@@ -1078,12 +1157,11 @@ parse_terminal (const sc_char *terminal)
* for the various sound and graphic resources encountered on parsing
* version 4.0 games. It's unused if the version is not 4.0.
*/
-typedef struct
-{
- sc_char *name;
- sc_uint hash;
- sc_int length;
- sc_int offset;
+typedef struct {
+ sc_char *name;
+ sc_uint hash;
+ sc_int length;
+ sc_int offset;
} sc_parse_resource_t;
enum { RESOURCE_GROW_INCREMENT = 32 };
@@ -1098,21 +1176,19 @@ static sc_parse_resource_t *parse_resources = NULL;
* Free and clear down the version 4.0 resources table.
*/
static void
-parse_clear_v400_resources_table (void)
-{
- /* Free allocated memory and return to initial values. */
- if (parse_resources)
- {
- sc_int index_;
-
- for (index_ = 0; index_ < parse_resources_length; index_++)
- sc_free (parse_resources[index_].name);
-
- sc_free (parse_resources);
- parse_resources = NULL;
- }
- parse_resources_length = 0;
- parse_resources_size = 0;
+parse_clear_v400_resources_table(void) {
+ /* Free allocated memory and return to initial values. */
+ if (parse_resources) {
+ sc_int index_;
+
+ for (index_ = 0; index_ < parse_resources_length; index_++)
+ sc_free(parse_resources[index_].name);
+
+ sc_free(parse_resources);
+ parse_resources = NULL;
+ }
+ parse_resources_length = 0;
+ parse_resources_size = 0;
}
@@ -1130,77 +1206,71 @@ parse_clear_v400_resources_table (void)
* length with real_length to see if that happened.
*/
static sc_int
-parse_get_v400_resource_offset (const sc_char *name,
- sc_int length, sc_int *real_length)
-{
- sc_char *clean_name;
- sc_uint hash;
- sc_int index_, offset;
-
- /*
- * Take a copy of the name, and remove any trailing "##" looping sound
- * indicator flag. Who thinks this junk up?
- */
- clean_name = (sc_char *)sc_malloc (strlen (name) + 1);
- strcpy (clean_name, name);
- if (strcmp (clean_name + strlen (clean_name) - 2, "##") == 0)
- clean_name[strlen (clean_name) - 2] = NUL;
-
- /*
- * Scan the current resources list for a matching name, and if the resource
- * is already known, return its offset. The hash check is an attempt to
- * improve the search times, relative to using only string comparisons --
- * the table's not fully hashed. If found, we need to also pass back the
- * corrected length.
- */
- offset = -1;
- hash = sc_hash (clean_name);
- for (index_ = 0; index_ < parse_resources_length; index_++)
- {
- if (parse_resources[index_].hash == hash
- && strcmp (parse_resources[index_].name, clean_name) == 0)
- {
- offset = parse_resources[index_].offset;
- break;
- }
- }
- if (offset != -1)
- {
- *real_length = parse_resources[index_].length;
- sc_free (clean_name);
- return offset;
- }
-
- /* Resize the resources table if required. */
- if (parse_resources_length == parse_resources_size)
- {
- parse_resources_size += RESOURCE_GROW_INCREMENT;
- parse_resources = (sc_parse_resource_t *)sc_realloc (parse_resources,
- parse_resources_size *
- sizeof (parse_resources[0]));
- }
-
- /*
- * Calculate the offset. For the first resource, it's zero; for others,
- * it's one after the prior entry's offset and length.
- */
- if (parse_resources_length == 0)
- offset = 0;
- else
- {
- offset = parse_resources[parse_resources_length - 1].offset
- + parse_resources[parse_resources_length - 1].length + 1;
- }
-
- /* Add details to the table. */
- parse_resources[parse_resources_length].name = clean_name;
- parse_resources[parse_resources_length].hash = hash;
- parse_resources[parse_resources_length].offset = offset;
- parse_resources[parse_resources_length].length = length;
- parse_resources_length++;
-
- *real_length = length;
- return offset;
+parse_get_v400_resource_offset(const sc_char *name,
+ sc_int length, sc_int *real_length) {
+ sc_char *clean_name;
+ sc_uint hash;
+ sc_int index_, offset;
+
+ /*
+ * Take a copy of the name, and remove any trailing "##" looping sound
+ * indicator flag. Who thinks this junk up?
+ */
+ clean_name = (sc_char *)sc_malloc(strlen(name) + 1);
+ strcpy(clean_name, name);
+ if (strcmp(clean_name + strlen(clean_name) - 2, "##") == 0)
+ clean_name[strlen(clean_name) - 2] = NUL;
+
+ /*
+ * Scan the current resources list for a matching name, and if the resource
+ * is already known, return its offset. The hash check is an attempt to
+ * improve the search times, relative to using only string comparisons --
+ * the table's not fully hashed. If found, we need to also pass back the
+ * corrected length.
+ */
+ offset = -1;
+ hash = sc_hash(clean_name);
+ for (index_ = 0; index_ < parse_resources_length; index_++) {
+ if (parse_resources[index_].hash == hash
+ && strcmp(parse_resources[index_].name, clean_name) == 0) {
+ offset = parse_resources[index_].offset;
+ break;
+ }
+ }
+ if (offset != -1) {
+ *real_length = parse_resources[index_].length;
+ sc_free(clean_name);
+ return offset;
+ }
+
+ /* Resize the resources table if required. */
+ if (parse_resources_length == parse_resources_size) {
+ parse_resources_size += RESOURCE_GROW_INCREMENT;
+ parse_resources = (sc_parse_resource_t *)sc_realloc(parse_resources,
+ parse_resources_size *
+ sizeof(parse_resources[0]));
+ }
+
+ /*
+ * Calculate the offset. For the first resource, it's zero; for others,
+ * it's one after the prior entry's offset and length.
+ */
+ if (parse_resources_length == 0)
+ offset = 0;
+ else {
+ offset = parse_resources[parse_resources_length - 1].offset
+ + parse_resources[parse_resources_length - 1].length + 1;
+ }
+
+ /* Add details to the table. */
+ parse_resources[parse_resources_length].name = clean_name;
+ parse_resources[parse_resources_length].hash = hash;
+ parse_resources[parse_resources_length].offset = offset;
+ parse_resources[parse_resources_length].length = length;
+ parse_resources_length++;
+
+ *real_length = length;
+ return offset;
}
@@ -1221,104 +1291,97 @@ parse_get_v400_resource_offset (const sc_char *name,
* our parse_resources table, but not always...
*/
static void
-parse_handle_v400_resources (sc_bool has_sound, sc_bool has_graphics)
-{
- sc_vartype_t vt_key, vt_value;
- const sc_char *file;
- sc_int length, offset;
-
- /*
- * Retrieve the file and length for the sound just parsed. If there's a
- * file of non-zero length, rewrite its offset.
- */
- if (has_sound)
- {
- /* Retrieve the file and length information. */
- vt_key.string = "SoundFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- file = parse_get_string_property ();
- parse_pop_key ();
-
- vt_key.string = "SoundLen";
- parse_push_key (vt_key, PROP_KEY_STRING);
- length = parse_get_integer_property ();
- parse_pop_key ();
-
- /*
- * If defined and has a length, rewrite the offset, and also the length
- * in case changed.
- */
- if (!sc_strempty (file) && length != 0)
- {
- sc_int real_length;
-
- offset = parse_get_v400_resource_offset (file, length, &real_length);
- vt_key.string = "SoundOffset";
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- vt_value.integer = offset;
- parse_put_property (vt_value, PROP_INTEGER);
-
- parse_pop_key ();
-
- /* Rewrite length if changed. */
- if (real_length != length)
- {
- vt_key.string = "SoundLen";
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- vt_value.integer = real_length;
- parse_put_property (vt_value, PROP_INTEGER);
-
- parse_pop_key ();
- }
- }
- }
-
- /* Now do the same thing for graphics. */
- if (has_graphics)
- {
- /* Retrieve the file and length information. */
- vt_key.string = "GraphicFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- file = parse_get_string_property ();
- parse_pop_key ();
-
- vt_key.string = "GraphicLen";
- parse_push_key (vt_key, PROP_KEY_STRING);
- length = parse_get_integer_property ();
- parse_pop_key ();
-
- /*
- * If defined and has a length, rewrite the offset, and also the length
- * in case changed.
- */
- if (!sc_strempty (file) && length != 0)
- {
- sc_int real_length;
-
- offset = parse_get_v400_resource_offset (file, length, &real_length);
- vt_key.string = "GraphicOffset";
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- vt_value.integer = offset;
- parse_put_property (vt_value, PROP_INTEGER);
-
- parse_pop_key ();
-
- /* Rewrite length if changed. */
- if (real_length != length)
- {
- vt_key.string = "GraphicLen";
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- vt_value.integer = real_length;
- parse_put_property (vt_value, PROP_INTEGER);
-
- parse_pop_key ();
- }
- }
- }
+parse_handle_v400_resources(sc_bool has_sound, sc_bool has_graphics) {
+ sc_vartype_t vt_key, vt_value;
+ const sc_char *file;
+ sc_int length, offset;
+
+ /*
+ * Retrieve the file and length for the sound just parsed. If there's a
+ * file of non-zero length, rewrite its offset.
+ */
+ if (has_sound) {
+ /* Retrieve the file and length information. */
+ vt_key.string = "SoundFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ file = parse_get_string_property();
+ parse_pop_key();
+
+ vt_key.string = "SoundLen";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ length = parse_get_integer_property();
+ parse_pop_key();
+
+ /*
+ * If defined and has a length, rewrite the offset, and also the length
+ * in case changed.
+ */
+ if (!sc_strempty(file) && length != 0) {
+ sc_int real_length;
+
+ offset = parse_get_v400_resource_offset(file, length, &real_length);
+ vt_key.string = "SoundOffset";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ vt_value.integer = offset;
+ parse_put_property(vt_value, PROP_INTEGER);
+
+ parse_pop_key();
+
+ /* Rewrite length if changed. */
+ if (real_length != length) {
+ vt_key.string = "SoundLen";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ vt_value.integer = real_length;
+ parse_put_property(vt_value, PROP_INTEGER);
+
+ parse_pop_key();
+ }
+ }
+ }
+
+ /* Now do the same thing for graphics. */
+ if (has_graphics) {
+ /* Retrieve the file and length information. */
+ vt_key.string = "GraphicFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ file = parse_get_string_property();
+ parse_pop_key();
+
+ vt_key.string = "GraphicLen";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ length = parse_get_integer_property();
+ parse_pop_key();
+
+ /*
+ * If defined and has a length, rewrite the offset, and also the length
+ * in case changed.
+ */
+ if (!sc_strempty(file) && length != 0) {
+ sc_int real_length;
+
+ offset = parse_get_v400_resource_offset(file, length, &real_length);
+ vt_key.string = "GraphicOffset";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ vt_value.integer = offset;
+ parse_put_property(vt_value, PROP_INTEGER);
+
+ parse_pop_key();
+
+ /* Rewrite length if changed. */
+ if (real_length != length) {
+ vt_key.string = "GraphicLen";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ vt_value.integer = real_length;
+ parse_put_property(vt_value, PROP_INTEGER);
+
+ parse_pop_key();
+ }
+ }
+ }
}
@@ -1329,238 +1392,222 @@ parse_handle_v400_resources (sc_bool has_sound, sc_bool has_graphics)
* therefore need careful treatment.
*/
static void
-parse_special (const sc_char *special)
-{
- if (parse_trace)
- sc_trace ("Parse: entering special %s\n", special);
-
- /* Special handling for version 4.0 resources. */
- if (strcmp (special, "{V400_RESOURCE}") == 0)
- {
- sc_vartype_t vt_key[2];
- sc_bool has_sound, has_graphics;
-
- /* Get sound and graphics global flags. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "Sound";
- has_sound = prop_get_boolean (parse_bundle, "B<-ss", vt_key);
-
- vt_key[1].string = "Graphics";
- has_graphics = prop_get_boolean (parse_bundle, "B<-ss", vt_key);
-
- /* Apply special handling to the resources. */
- parse_handle_v400_resources (has_sound, has_graphics);
- }
-
- /* Parse a version 4.0 optional set of room exit information. */
- else if (strcmp (special, "{V400_ROOM_EXIT:#Dest_#Var1_#Var2_#Var3}") == 0)
- {
- sc_int flag;
-
- /* Get next flag, and if true, pushback and parse. */
- flag = parse_get_taf_integer ();
- if (flag != 0)
- {
- parse_taf_pushback ();
- parse_descriptor ("#Dest #Var1 #Var2 #Var3");
- }
- }
-
- /* Parse version 3.9 and version 3.8 optional room exit information. */
- else if (strcmp (special,
- "{V390_V380_ROOM_EXIT:#Dest_#Var1_#Var2_ZVar3}") == 0)
- {
- sc_int flag;
-
- /* Get next flag, and if true, pushback and parse. */
- flag = parse_get_taf_integer ();
- if (flag != 0)
- {
- parse_taf_pushback ();
- parse_descriptor ("#Dest #Var1 #Var2 ZVar3");
- }
- }
-
- /* Parse room lists, with optional extra room. */
- else if (strcmp (special, "{ROOM_LIST0}") == 0
- || strcmp (special, "{ROOM_LIST1}") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int room_count, num_rooms, type, index_;
-
- /* Retrieve the room list type. */
- vt_key.string = "Type";
- parse_push_key (vt_key, PROP_KEY_STRING);
- type = parse_get_integer_property ();
- parse_pop_key ();
-
- /* Write remaining room list depending on the type. */
- switch (type)
- {
- case ROOMLIST_NO_ROOMS:
- case ROOMLIST_ALL_ROOMS:
- case ROOMLIST_NPC_PART:
- break;
-
- case ROOMLIST_ONE_ROOM:
- /* Store this room as the single list entry. */
- parse_element ("#Room");
- break;
-
- case ROOMLIST_SOME_ROOMS:
- /* Get count of rooms defined, add one if necessary. */
- vt_key.string = "Rooms";
- room_count = prop_get_child_count (parse_bundle, "I<-s", &vt_key);
-
- if (strcmp (special, "{ROOM_LIST1}") == 0)
- num_rooms = room_count + 1;
- else
- num_rooms = room_count;
-
- /* Store an array of rooms flags for each room. */
- vt_key.string = "Rooms";
- parse_push_key (vt_key, PROP_KEY_STRING);
- for (index_ = 0; index_ < num_rooms; index_++)
- {
- sc_bool this_room;
-
- /* Get flag for this room. */
- this_room = parse_get_taf_boolean ();
-
- /* Store flag directly. */
- vt_key.integer = index_;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
- vt_value.boolean = this_room;
- parse_put_property (vt_value, PROP_BOOLEAN);
- parse_pop_key ();
- }
- parse_pop_key ();
- break;
-
- default:
- sc_fatal ("parse_special: bad type, %ld\n", type);
- }
- }
-
- /* Parse Parent number iff this object is an NPC part. */
- else if (strcmp (special, "{OBJECT:#Parent}") == 0)
- {
- sc_vartype_t vt_key;
- sc_int type;
-
- /* Check object's Where room list Type for NPC part. */
- vt_key.string = "Where";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_key.string = "Type";
- parse_push_key (vt_key, PROP_KEY_STRING);
- type = parse_get_integer_property ();
- parse_pop_key ();
- parse_pop_key ();
-
- /* Get Parent if the object is part of an NPC. */
- if (type == ROOMLIST_NPC_PART)
- parse_element ("#Parent");
- }
-
- /* Parse a list of rooms and times for a walk. */
- else if (strcmp (special, "{WALK:#Rooms_#Times}") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int num_stops, index_;
-
- /* Obtain the count of stops in this walk. */
- vt_key.string = "NumStops";
- parse_push_key (vt_key, PROP_KEY_STRING);
- num_stops = parse_get_integer_property ();
- parse_pop_key ();
-
- /* Look for a room and time for each stop. */
- for (index_ = 0; index_ < num_stops; index_++)
- {
- sc_int room, time;
-
- /* Parse and store Rooms[index_]. */
- vt_key.string = "Rooms";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_key.integer = index_;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
-
- room = parse_get_taf_integer ();
-
- vt_value.integer = room;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- parse_pop_key ();
-
- /* Parse and store Times[index_]. */
- vt_key.string = "Times";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_key.integer = index_;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
-
- time = parse_get_taf_integer ();
-
- vt_value.integer = time;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- parse_pop_key ();
- }
- }
-
- /* Parse a room group variable size boolean list. */
- else if (strcmp (special, "{ROOM_GROUP:[]BList}") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int num_rooms, index_, l2index_;
- sc_bool in_group;
-
- /* Get the count of rooms defined. */
- vt_key.string = "Rooms";
- num_rooms = prop_get_integer (parse_bundle, "I<-s", &vt_key);
-
- /* Read a boolean for each room. */
- l2index_ = 0;
- for (index_ = 0; index_ < num_rooms; index_++)
- {
- in_group = parse_get_taf_boolean ();
-
- /* Store raw flag as List[index_]. */
- vt_key.string = "List";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_key.integer = index_;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
- vt_value.boolean = in_group;
- parse_put_property (vt_value, PROP_BOOLEAN);
-
- parse_pop_key ();
- parse_pop_key ();
-
- /* Store in-group index'es as List2[0..n]. */
- if (in_group)
- {
- vt_key.string = "List2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_key.integer = l2index_;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
- vt_value.integer = index_;
- parse_put_property (vt_value, PROP_INTEGER);
-
- parse_pop_key ();
- parse_pop_key ();
-
- l2index_++;
- }
- }
- }
-
- /* Error if no special handler available. */
- else
- {
- sc_fatal ("parse_special: no handler for \"%s\"\n", special);
- }
-
- if (parse_trace)
- sc_trace ("Parse: leaving special %s\n", special);
+parse_special(const sc_char *special) {
+ if (parse_trace)
+ sc_trace("Parse: entering special %s\n", special);
+
+ /* Special handling for version 4.0 resources. */
+ if (strcmp(special, "{V400_RESOURCE}") == 0) {
+ sc_vartype_t vt_key[2];
+ sc_bool has_sound, has_graphics;
+
+ /* Get sound and graphics global flags. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Sound";
+ has_sound = prop_get_boolean(parse_bundle, "B<-ss", vt_key);
+
+ vt_key[1].string = "Graphics";
+ has_graphics = prop_get_boolean(parse_bundle, "B<-ss", vt_key);
+
+ /* Apply special handling to the resources. */
+ parse_handle_v400_resources(has_sound, has_graphics);
+ }
+
+ /* Parse a version 4.0 optional set of room exit information. */
+ else if (strcmp(special, "{V400_ROOM_EXIT:#Dest_#Var1_#Var2_#Var3}") == 0) {
+ sc_int flag;
+
+ /* Get next flag, and if true, pushback and parse. */
+ flag = parse_get_taf_integer();
+ if (flag != 0) {
+ parse_taf_pushback();
+ parse_descriptor("#Dest #Var1 #Var2 #Var3");
+ }
+ }
+
+ /* Parse version 3.9 and version 3.8 optional room exit information. */
+ else if (strcmp(special,
+ "{V390_V380_ROOM_EXIT:#Dest_#Var1_#Var2_ZVar3}") == 0) {
+ sc_int flag;
+
+ /* Get next flag, and if true, pushback and parse. */
+ flag = parse_get_taf_integer();
+ if (flag != 0) {
+ parse_taf_pushback();
+ parse_descriptor("#Dest #Var1 #Var2 ZVar3");
+ }
+ }
+
+ /* Parse room lists, with optional extra room. */
+ else if (strcmp(special, "{ROOM_LIST0}") == 0
+ || strcmp(special, "{ROOM_LIST1}") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int room_count, num_rooms, type, index_;
+
+ /* Retrieve the room list type. */
+ vt_key.string = "Type";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ type = parse_get_integer_property();
+ parse_pop_key();
+
+ /* Write remaining room list depending on the type. */
+ switch (type) {
+ case ROOMLIST_NO_ROOMS:
+ case ROOMLIST_ALL_ROOMS:
+ case ROOMLIST_NPC_PART:
+ break;
+
+ case ROOMLIST_ONE_ROOM:
+ /* Store this room as the single list entry. */
+ parse_element("#Room");
+ break;
+
+ case ROOMLIST_SOME_ROOMS:
+ /* Get count of rooms defined, add one if necessary. */
+ vt_key.string = "Rooms";
+ room_count = prop_get_child_count(parse_bundle, "I<-s", &vt_key);
+
+ if (strcmp(special, "{ROOM_LIST1}") == 0)
+ num_rooms = room_count + 1;
+ else
+ num_rooms = room_count;
+
+ /* Store an array of rooms flags for each room. */
+ vt_key.string = "Rooms";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ for (index_ = 0; index_ < num_rooms; index_++) {
+ sc_bool this_room;
+
+ /* Get flag for this room. */
+ this_room = parse_get_taf_boolean();
+
+ /* Store flag directly. */
+ vt_key.integer = index_;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+ vt_value.boolean = this_room;
+ parse_put_property(vt_value, PROP_BOOLEAN);
+ parse_pop_key();
+ }
+ parse_pop_key();
+ break;
+
+ default:
+ sc_fatal("parse_special: bad type, %ld\n", type);
+ }
+ }
+
+ /* Parse Parent number iff this object is an NPC part. */
+ else if (strcmp(special, "{OBJECT:#Parent}") == 0) {
+ sc_vartype_t vt_key;
+ sc_int type;
+
+ /* Check object's Where room list Type for NPC part. */
+ vt_key.string = "Where";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_key.string = "Type";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ type = parse_get_integer_property();
+ parse_pop_key();
+ parse_pop_key();
+
+ /* Get Parent if the object is part of an NPC. */
+ if (type == ROOMLIST_NPC_PART)
+ parse_element("#Parent");
+ }
+
+ /* Parse a list of rooms and times for a walk. */
+ else if (strcmp(special, "{WALK:#Rooms_#Times}") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int num_stops, index_;
+
+ /* Obtain the count of stops in this walk. */
+ vt_key.string = "NumStops";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ num_stops = parse_get_integer_property();
+ parse_pop_key();
+
+ /* Look for a room and time for each stop. */
+ for (index_ = 0; index_ < num_stops; index_++) {
+ sc_int room, time;
+
+ /* Parse and store Rooms[index_]. */
+ vt_key.string = "Rooms";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_key.integer = index_;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+
+ room = parse_get_taf_integer();
+
+ vt_value.integer = room;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ parse_pop_key();
+
+ /* Parse and store Times[index_]. */
+ vt_key.string = "Times";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_key.integer = index_;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+
+ time = parse_get_taf_integer();
+
+ vt_value.integer = time;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ parse_pop_key();
+ }
+ }
+
+ /* Parse a room group variable size boolean list. */
+ else if (strcmp(special, "{ROOM_GROUP:[]BList}") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int num_rooms, index_, l2index_;
+ sc_bool in_group;
+
+ /* Get the count of rooms defined. */
+ vt_key.string = "Rooms";
+ num_rooms = prop_get_integer(parse_bundle, "I<-s", &vt_key);
+
+ /* Read a boolean for each room. */
+ l2index_ = 0;
+ for (index_ = 0; index_ < num_rooms; index_++) {
+ in_group = parse_get_taf_boolean();
+
+ /* Store raw flag as List[index_]. */
+ vt_key.string = "List";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_key.integer = index_;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+ vt_value.boolean = in_group;
+ parse_put_property(vt_value, PROP_BOOLEAN);
+
+ parse_pop_key();
+ parse_pop_key();
+
+ /* Store in-group index'es as List2[0..n]. */
+ if (in_group) {
+ vt_key.string = "List2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_key.integer = l2index_;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+ vt_value.integer = index_;
+ parse_put_property(vt_value, PROP_INTEGER);
+
+ parse_pop_key();
+ parse_pop_key();
+
+ l2index_++;
+ }
+ }
+ }
+
+ /* Error if no special handler available. */
+ else {
+ sc_fatal("parse_special: no handler for \"%s\"\n", special);
+ }
+
+ if (parse_trace)
+ sc_trace("Parse: leaving special %s\n", special);
}
@@ -1571,219 +1618,205 @@ parse_special (const sc_char *special)
* version 4.0 room alts for version 3.9 and version 3.8 games.
*/
static void
-parse_fixup_v390_v380_room_alt (const sc_char *m1, sc_int type,
- const sc_char *resource1,
- const sc_char *m2, sc_int var2,
- const sc_char *resource2,
- sc_int hide_objects,
- const sc_char *changed,
- sc_int var3, sc_int display_room)
-{
- sc_vartype_t vt_key, vt_value, vt_gkey[2];
- sc_bool has_sound, has_graphics;
- sc_int alt_count;
- const sc_char *soundfile1, *graphicfile1;
- const sc_char *soundfile2, *graphicfile2;
-
- /*
- * Initialize resource files to empty, for cases where no resource is copied
- * over from the main room (NULL resource1/2).
- */
- soundfile1 = "";
- graphicfile1 = "";
- soundfile2 = "";
- graphicfile2 = "";
-
- /* Get sound and graphics flags, always FALSE for version 3.8. */
- vt_gkey[0].string = "Globals";
- vt_gkey[1].string = "Sound";
- has_sound = prop_get_boolean (parse_bundle, "B<-ss", vt_gkey);
-
- vt_gkey[1].string = "Graphics";
- has_graphics = prop_get_boolean (parse_bundle, "B<-ss", vt_gkey);
-
- /* Get a count of alts so far defined for the room. */
- vt_key.string = "Alts";
- parse_push_key (vt_key, PROP_KEY_STRING);
- alt_count = parse_get_child_count ();
- parse_pop_key ();
-
- /*
- * Lookup any resource details now, and save them. Because this is not
- * version 4.0, we can ignore lengths, and set them to zero when needed.
- */
- if (has_sound || has_graphics)
- {
- if (resource1)
- {
- vt_key.string = resource1;
- parse_push_key (vt_key, PROP_KEY_STRING);
- if (has_sound)
- {
- vt_key.string = "SoundFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- soundfile1 = parse_get_string_property ();
- parse_pop_key ();
- }
- if (has_graphics)
- {
- vt_key.string = "GraphicFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- graphicfile1 = parse_get_string_property ();
- parse_pop_key ();
- }
- parse_pop_key ();
- }
-
- if (resource2)
- {
- vt_key.string = resource2;
- parse_push_key (vt_key, PROP_KEY_STRING);
- if (has_sound)
- {
- vt_key.string = "SoundFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- soundfile2 = parse_get_string_property ();
- parse_pop_key ();
- }
- if (has_graphics)
- {
- vt_key.string = "GraphicFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- graphicfile2 = parse_get_string_property ();
- parse_pop_key ();
- }
- parse_pop_key ();
- }
- }
-
- /*
- * Create a room alt to match data passed in. Start with the Alts string
- * and the index to the alt being written. To correctly emulate the parse,
- * we also have to reverse the "Alts" and the index, as parse_put_property()
- * will swap them. Madness.
- */
- vt_key.integer = alt_count;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
- vt_key.string = "Alts";
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- /* Write M1 and Type. */
- vt_key.string = "M1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = m1;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
- vt_key.string = "Type";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = type;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
-
- /* If resources, add these as retrieved above. */
- if (has_sound || has_graphics)
- {
- vt_key.string = "Res1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- if (has_sound)
- {
- vt_key.string = "SoundFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = soundfile1;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
- vt_key.string = "SoundLen";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = 0;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
- if (has_graphics)
- {
- vt_key.string = "GraphicFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = graphicfile1;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
- vt_key.string = "GraphicLen";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = 0;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
- parse_pop_key ();
- }
-
- /* Write M2 and Var2. */
- vt_key.string = "M2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = m2;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
- vt_key.string = "Var2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = var2;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
-
- /* If resources, again add these as retrieved above. */
- if (has_sound || has_graphics)
- {
- vt_key.string = "Res2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- if (has_sound)
- {
- vt_key.string = "SoundFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = soundfile2;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
- vt_key.string = "SoundLen";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = 0;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
- if (has_graphics)
- {
- vt_key.string = "GraphicFile";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = graphicfile2;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
- vt_key.string = "GraphicLen";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = 0;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
- parse_pop_key ();
- }
-
- /* Finish off with the last four alt properties. */
- vt_key.string = "HideObjects";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = hide_objects;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- vt_key.string = "Changed";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = changed;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
- vt_key.string = "Var3";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = var3;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- vt_key.string = "DisplayRoom";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = display_room;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
-
- parse_pop_key ();
- parse_pop_key ();
+parse_fixup_v390_v380_room_alt(const sc_char *m1, sc_int type,
+ const sc_char *resource1,
+ const sc_char *m2, sc_int var2,
+ const sc_char *resource2,
+ sc_int hide_objects,
+ const sc_char *changed,
+ sc_int var3, sc_int display_room) {
+ sc_vartype_t vt_key, vt_value, vt_gkey[2];
+ sc_bool has_sound, has_graphics;
+ sc_int alt_count;
+ const sc_char *soundfile1, *graphicfile1;
+ const sc_char *soundfile2, *graphicfile2;
+
+ /*
+ * Initialize resource files to empty, for cases where no resource is copied
+ * over from the main room (NULL resource1/2).
+ */
+ soundfile1 = "";
+ graphicfile1 = "";
+ soundfile2 = "";
+ graphicfile2 = "";
+
+ /* Get sound and graphics flags, always FALSE for version 3.8. */
+ vt_gkey[0].string = "Globals";
+ vt_gkey[1].string = "Sound";
+ has_sound = prop_get_boolean(parse_bundle, "B<-ss", vt_gkey);
+
+ vt_gkey[1].string = "Graphics";
+ has_graphics = prop_get_boolean(parse_bundle, "B<-ss", vt_gkey);
+
+ /* Get a count of alts so far defined for the room. */
+ vt_key.string = "Alts";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ alt_count = parse_get_child_count();
+ parse_pop_key();
+
+ /*
+ * Lookup any resource details now, and save them. Because this is not
+ * version 4.0, we can ignore lengths, and set them to zero when needed.
+ */
+ if (has_sound || has_graphics) {
+ if (resource1) {
+ vt_key.string = resource1;
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ if (has_sound) {
+ vt_key.string = "SoundFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ soundfile1 = parse_get_string_property();
+ parse_pop_key();
+ }
+ if (has_graphics) {
+ vt_key.string = "GraphicFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ graphicfile1 = parse_get_string_property();
+ parse_pop_key();
+ }
+ parse_pop_key();
+ }
+
+ if (resource2) {
+ vt_key.string = resource2;
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ if (has_sound) {
+ vt_key.string = "SoundFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ soundfile2 = parse_get_string_property();
+ parse_pop_key();
+ }
+ if (has_graphics) {
+ vt_key.string = "GraphicFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ graphicfile2 = parse_get_string_property();
+ parse_pop_key();
+ }
+ parse_pop_key();
+ }
+ }
+
+ /*
+ * Create a room alt to match data passed in. Start with the Alts string
+ * and the index to the alt being written. To correctly emulate the parse,
+ * we also have to reverse the "Alts" and the index, as parse_put_property()
+ * will swap them. Madness.
+ */
+ vt_key.integer = alt_count;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+ vt_key.string = "Alts";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ /* Write M1 and Type. */
+ vt_key.string = "M1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = m1;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+ vt_key.string = "Type";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = type;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+
+ /* If resources, add these as retrieved above. */
+ if (has_sound || has_graphics) {
+ vt_key.string = "Res1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ if (has_sound) {
+ vt_key.string = "SoundFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = soundfile1;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+ vt_key.string = "SoundLen";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = 0;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+ if (has_graphics) {
+ vt_key.string = "GraphicFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = graphicfile1;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+ vt_key.string = "GraphicLen";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = 0;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+ parse_pop_key();
+ }
+
+ /* Write M2 and Var2. */
+ vt_key.string = "M2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = m2;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+ vt_key.string = "Var2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = var2;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+
+ /* If resources, again add these as retrieved above. */
+ if (has_sound || has_graphics) {
+ vt_key.string = "Res2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ if (has_sound) {
+ vt_key.string = "SoundFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = soundfile2;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+ vt_key.string = "SoundLen";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = 0;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+ if (has_graphics) {
+ vt_key.string = "GraphicFile";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = graphicfile2;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+ vt_key.string = "GraphicLen";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = 0;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+ parse_pop_key();
+ }
+
+ /* Finish off with the last four alt properties. */
+ vt_key.string = "HideObjects";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = hide_objects;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ vt_key.string = "Changed";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = changed;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+ vt_key.string = "Var3";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = var3;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ vt_key.string = "DisplayRoom";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = display_room;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+
+ parse_pop_key();
+ parse_pop_key();
}
@@ -1798,127 +1831,122 @@ enum { V390_V380_ALT_TYPEHIDE_MULT = 10 };
* an equivalent array of version 4.0 style room alts.
*/
static void
-parse_fixup_v390_v380_room_alts (void)
-{
- sc_vartype_t vt_key;
- const sc_char *m1, *m2, *changed;
- sc_int type, var2, hide_objects, var3, display_room;
-
- /* Room alt invariants. */
- m2 = ""; /* No else text */
- changed = ""; /* No changed room name */
-
- /*
- * Create a room alt to override all others, controlled by an object
- * condition and with optional object hiding.
- */
- type = 2; /* Object condition */
- display_room = 0; /* Override all others */
-
- vt_key.string = "Obj";
- parse_push_key (vt_key, PROP_KEY_STRING);
- var3 = parse_get_integer_property ();
- parse_pop_key ();
-
- if (var3 > 0)
- {
- sc_int typehideobjects;
-
- vt_key.string = "AltDesc";
- parse_push_key (vt_key, PROP_KEY_STRING);
- m1 = parse_get_string_property ();
- parse_pop_key ();
-
- vt_key.string = "TypeHideObjects";
- parse_push_key (vt_key, PROP_KEY_STRING);
- typehideobjects = parse_get_integer_property ();
- parse_pop_key ();
-
- var2 = typehideobjects / V390_V380_ALT_TYPEHIDE_MULT;
- hide_objects = typehideobjects % V390_V380_ALT_TYPEHIDE_MULT;
-
- parse_fixup_v390_v380_room_alt (m1, type, "AltRes",
- m2, var2, NULL,
- hide_objects, changed, var3,
- display_room);
- }
-
- /*
- * If a second task alternate description is defined, create a room alt to
- * add after the main description, one that stops printing once done.
- */
- type = 0; /* Task condition */
- display_room = 1; /* Print after main and stop */
-
- vt_key.string = "Task2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- var2 = parse_get_integer_property ();
- parse_pop_key ();
-
- if (var2 > 0)
- {
- vt_key.string = "AddDesc2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- m1 = parse_get_string_property ();
- parse_pop_key ();
-
- var3 = 0;
- hide_objects = 0;
-
- parse_fixup_v390_v380_room_alt (m1, type, "Task2Res",
- m2, var2, NULL,
- hide_objects, changed, var3,
- display_room);
- }
-
- /* Do the same for any first task additional description. */
- type = 0; /* Task condition */
- display_room = 1; /* Print after main and stop */
-
- vt_key.string = "Task1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- var2 = parse_get_integer_property ();
- parse_pop_key ();
-
- if (var2 > 0)
- {
- vt_key.string = "AddDesc1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- m1 = parse_get_string_property ();
- parse_pop_key ();
-
- var3 = 0;
- hide_objects = 0;
-
- parse_fixup_v390_v380_room_alt (m1, type, "Task1Res",
- m2, var2, NULL,
- hide_objects, changed, var3,
- display_room);
- }
-
- /*
- * If still printing at this point, we need a catch-all room alt that will
- * print. So create one with an always true condition.
- */
- type = 0; /* Task condition */
- display_room = 2; /* Lowest priority output */
-
- vt_key.string = "LastDesc";
- parse_push_key (vt_key, PROP_KEY_STRING);
- m1 = parse_get_string_property ();
- parse_pop_key ();
-
- if (!sc_strempty (m1))
- {
- var2 = 0; /* No task - always TRUE */
- var3 = 0;
- hide_objects = 0;
-
- parse_fixup_v390_v380_room_alt (m1, type, "LastRes",
- m2, var2, NULL,
- hide_objects, changed, var3,
- display_room);
- }
+parse_fixup_v390_v380_room_alts(void) {
+ sc_vartype_t vt_key;
+ const sc_char *m1, *m2, *changed;
+ sc_int type, var2, hide_objects, var3, display_room;
+
+ /* Room alt invariants. */
+ m2 = ""; /* No else text */
+ changed = ""; /* No changed room name */
+
+ /*
+ * Create a room alt to override all others, controlled by an object
+ * condition and with optional object hiding.
+ */
+ type = 2; /* Object condition */
+ display_room = 0; /* Override all others */
+
+ vt_key.string = "Obj";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ var3 = parse_get_integer_property();
+ parse_pop_key();
+
+ if (var3 > 0) {
+ sc_int typehideobjects;
+
+ vt_key.string = "AltDesc";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ m1 = parse_get_string_property();
+ parse_pop_key();
+
+ vt_key.string = "TypeHideObjects";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ typehideobjects = parse_get_integer_property();
+ parse_pop_key();
+
+ var2 = typehideobjects / V390_V380_ALT_TYPEHIDE_MULT;
+ hide_objects = typehideobjects % V390_V380_ALT_TYPEHIDE_MULT;
+
+ parse_fixup_v390_v380_room_alt(m1, type, "AltRes",
+ m2, var2, NULL,
+ hide_objects, changed, var3,
+ display_room);
+ }
+
+ /*
+ * If a second task alternate description is defined, create a room alt to
+ * add after the main description, one that stops printing once done.
+ */
+ type = 0; /* Task condition */
+ display_room = 1; /* Print after main and stop */
+
+ vt_key.string = "Task2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ var2 = parse_get_integer_property();
+ parse_pop_key();
+
+ if (var2 > 0) {
+ vt_key.string = "AddDesc2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ m1 = parse_get_string_property();
+ parse_pop_key();
+
+ var3 = 0;
+ hide_objects = 0;
+
+ parse_fixup_v390_v380_room_alt(m1, type, "Task2Res",
+ m2, var2, NULL,
+ hide_objects, changed, var3,
+ display_room);
+ }
+
+ /* Do the same for any first task additional description. */
+ type = 0; /* Task condition */
+ display_room = 1; /* Print after main and stop */
+
+ vt_key.string = "Task1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ var2 = parse_get_integer_property();
+ parse_pop_key();
+
+ if (var2 > 0) {
+ vt_key.string = "AddDesc1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ m1 = parse_get_string_property();
+ parse_pop_key();
+
+ var3 = 0;
+ hide_objects = 0;
+
+ parse_fixup_v390_v380_room_alt(m1, type, "Task1Res",
+ m2, var2, NULL,
+ hide_objects, changed, var3,
+ display_room);
+ }
+
+ /*
+ * If still printing at this point, we need a catch-all room alt that will
+ * print. So create one with an always true condition.
+ */
+ type = 0; /* Task condition */
+ display_room = 2; /* Lowest priority output */
+
+ vt_key.string = "LastDesc";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ m1 = parse_get_string_property();
+ parse_pop_key();
+
+ if (!sc_strempty(m1)) {
+ var2 = 0; /* No task - always TRUE */
+ var3 = 0;
+ hide_objects = 0;
+
+ parse_fixup_v390_v380_room_alt(m1, type, "LastRes",
+ m2, var2, NULL,
+ hide_objects, changed, var3,
+ display_room);
+ }
}
@@ -1929,151 +1957,138 @@ parse_fixup_v390_v380_room_alts (void)
* 3.9 format into version 4.0.
*/
static void
-parse_fixup_v390 (const sc_char *fixup)
-{
- if (parse_trace)
- sc_trace ("Parse: entering version 3.9 fixup %s\n", fixup);
-
- /* Fixup a version 3.9 task action by incrementing Type > 4. */
- if (strcmp (fixup, "|V390_TASK_ACTION:Type>4?#Type++|") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int type;
-
- /* Retrieve Type, and if > 4, increment. */
- vt_key.string = "Type";
- parse_push_key (vt_key, PROP_KEY_STRING);
- type = parse_get_integer_property ();
-
- if (type > 4)
- {
- vt_value.integer = type + 1;
- parse_put_property (vt_value, PROP_INTEGER);
- }
-
- parse_pop_key ();
- }
-
- /* Handle either Expr or Var5 for version 3.9 task actions. */
- else if (strcmp (fixup, "|V390_TASK_ACTION:$Expr_#Var5|") == 0)
- {
- sc_vartype_t vt_key;
- sc_int var2;
-
- /* Either Expr or Var5, depending on Var2. */
- vt_key.string = "Var2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- var2 = parse_get_integer_property ();
- parse_pop_key ();
-
- if (var2 == 5)
- parse_descriptor ("$Expr ZVar5");
- else
- parse_descriptor ("EExpr #Var5");
- }
-
- /*
- * Exchange openable values 5 and 6, and write -1 key for openable objects.
- */
- else if (strcmp (fixup, "|V390_OBJECT:_Openable_,Key|") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int openable;
-
- /* Retrieve Openable, and if 5 or 6, exchange. */
- vt_key.string = "Openable";
- parse_push_key (vt_key, PROP_KEY_STRING);
- openable = parse_get_integer_property ();
-
- if (openable == 5 || openable == 6)
- {
- vt_value.integer = (openable == 5) ? 6 : 5;
- parse_put_property (vt_value, PROP_INTEGER);
- }
-
- parse_pop_key ();
-
- /* For openable objects, store a Key of -1. */
- if (openable == 5 || openable == 6)
- {
- vt_key.string = "Key";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = -1;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
- }
-
- /* Create a RestrMask that 'and's all the restrictions together. */
- else if (strcmp (fixup, "|V390_TASK:$RestrMask|") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int restriction_count;
-
- /* Get a count of restrictions. */
- vt_key.string = "Restrictions";
- parse_push_key (vt_key, PROP_KEY_STRING);
- restriction_count = parse_get_child_count ();
- parse_pop_key ();
-
- /* Allocate and fill a new mask for these restrictions. */
- if (restriction_count > 0)
- {
- sc_char *restrmask;
- sc_int index_;
-
- restrmask = (sc_char *)sc_malloc (2 * restriction_count);
- strcpy (restrmask, "#");
- for (index_ = 1; index_ < restriction_count; index_++)
- strcat (restrmask, "A#");
-
- vt_key.string = "RestrMask";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = restrmask;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
-
- prop_adopt (parse_bundle, restrmask);
- }
- }
-
- /*
- * Increment var1 for variable restrictions to compensate for there being no
- * referenced text comparison (no string variables).
- */
- else if (strcmp (fixup, "|V390_TASK_RESTR:Var1>0?#Var1++|") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int var1;
-
- /* Retrieve Var1, and if greater than zero, increment. */
- vt_key.string = "Var1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- var1 = parse_get_integer_property ();
-
- if (var1 > 0)
- {
- vt_value.integer = var1 + 1;
- parse_put_property (vt_value, PROP_INTEGER);
- }
-
- parse_pop_key ();
- }
-
- /* Convert version 3.9 fixed alts into a version 4.0 array. */
- else if (strcmp (fixup, "|V390_ROOM:_Alts_|") == 0)
- {
- parse_fixup_v390_v380_room_alts ();
- }
-
- /* Error if no fixup special handler available. */
- else
- {
- sc_fatal ("parse_fixup_v390: no handler for \"%s\"\n", fixup);
- }
-
- if (parse_trace)
- sc_trace ("Parse: leaving version 3.9 fixup %s\n", fixup);
+parse_fixup_v390(const sc_char *fixup) {
+ if (parse_trace)
+ sc_trace("Parse: entering version 3.9 fixup %s\n", fixup);
+
+ /* Fixup a version 3.9 task action by incrementing Type > 4. */
+ if (strcmp(fixup, "|V390_TASK_ACTION:Type>4?#Type++|") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int type;
+
+ /* Retrieve Type, and if > 4, increment. */
+ vt_key.string = "Type";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ type = parse_get_integer_property();
+
+ if (type > 4) {
+ vt_value.integer = type + 1;
+ parse_put_property(vt_value, PROP_INTEGER);
+ }
+
+ parse_pop_key();
+ }
+
+ /* Handle either Expr or Var5 for version 3.9 task actions. */
+ else if (strcmp(fixup, "|V390_TASK_ACTION:$Expr_#Var5|") == 0) {
+ sc_vartype_t vt_key;
+ sc_int var2;
+
+ /* Either Expr or Var5, depending on Var2. */
+ vt_key.string = "Var2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ var2 = parse_get_integer_property();
+ parse_pop_key();
+
+ if (var2 == 5)
+ parse_descriptor("$Expr ZVar5");
+ else
+ parse_descriptor("EExpr #Var5");
+ }
+
+ /*
+ * Exchange openable values 5 and 6, and write -1 key for openable objects.
+ */
+ else if (strcmp(fixup, "|V390_OBJECT:_Openable_,Key|") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int openable;
+
+ /* Retrieve Openable, and if 5 or 6, exchange. */
+ vt_key.string = "Openable";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ openable = parse_get_integer_property();
+
+ if (openable == 5 || openable == 6) {
+ vt_value.integer = (openable == 5) ? 6 : 5;
+ parse_put_property(vt_value, PROP_INTEGER);
+ }
+
+ parse_pop_key();
+
+ /* For openable objects, store a Key of -1. */
+ if (openable == 5 || openable == 6) {
+ vt_key.string = "Key";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = -1;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+ }
+
+ /* Create a RestrMask that 'and's all the restrictions together. */
+ else if (strcmp(fixup, "|V390_TASK:$RestrMask|") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int restriction_count;
+
+ /* Get a count of restrictions. */
+ vt_key.string = "Restrictions";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ restriction_count = parse_get_child_count();
+ parse_pop_key();
+
+ /* Allocate and fill a new mask for these restrictions. */
+ if (restriction_count > 0) {
+ sc_char *restrmask;
+ sc_int index_;
+
+ restrmask = (sc_char *)sc_malloc(2 * restriction_count);
+ strcpy(restrmask, "#");
+ for (index_ = 1; index_ < restriction_count; index_++)
+ strcat(restrmask, "A#");
+
+ vt_key.string = "RestrMask";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = restrmask;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+
+ prop_adopt(parse_bundle, restrmask);
+ }
+ }
+
+ /*
+ * Increment var1 for variable restrictions to compensate for there being no
+ * referenced text comparison (no string variables).
+ */
+ else if (strcmp(fixup, "|V390_TASK_RESTR:Var1>0?#Var1++|") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int var1;
+
+ /* Retrieve Var1, and if greater than zero, increment. */
+ vt_key.string = "Var1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ var1 = parse_get_integer_property();
+
+ if (var1 > 0) {
+ vt_value.integer = var1 + 1;
+ parse_put_property(vt_value, PROP_INTEGER);
+ }
+
+ parse_pop_key();
+ }
+
+ /* Convert version 3.9 fixed alts into a version 4.0 array. */
+ else if (strcmp(fixup, "|V390_ROOM:_Alts_|") == 0) {
+ parse_fixup_v390_v380_room_alts();
+ }
+
+ /* Error if no fixup special handler available. */
+ else {
+ sc_fatal("parse_fixup_v390: no handler for \"%s\"\n", fixup);
+ }
+
+ if (parse_trace)
+ sc_trace("Parse: leaving version 3.9 fixup %s\n", fixup);
}
@@ -2092,57 +2107,54 @@ enum { V380_TASK_MOVEMENTS = 6 };
* Helper for parse_fixup_v380(), adds a task action.
*/
static void
-parse_fixup_v380_action (sc_int type, sc_int var_count,
- sc_int var1, sc_int var2, sc_int var3)
-{
- sc_vartype_t vt_key, vt_value;
- sc_int action_count;
-
- /* Get a count of actions so far defined for the task. */
- vt_key.string = "Actions";
- parse_push_key (vt_key, PROP_KEY_STRING);
- action_count = parse_get_child_count ();
- parse_pop_key ();
-
- /* Write actions key, reversed to emulate parse actions. */
- vt_key.integer = action_count;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
- vt_key.string = "Actions";
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- /* Write new action according to the given arguments. */
- vt_key.string = "Type";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = type;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
-
- vt_key.string = "Var1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = var1;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
-
- if (var_count > 1)
- {
- vt_key.string = "Var2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = var2;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
-
- if (var_count > 2)
- {
- vt_key.string = "Var3";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = var3;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
-
- parse_pop_key ();
- parse_pop_key ();
+parse_fixup_v380_action(sc_int type, sc_int var_count,
+ sc_int var1, sc_int var2, sc_int var3) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int action_count;
+
+ /* Get a count of actions so far defined for the task. */
+ vt_key.string = "Actions";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ action_count = parse_get_child_count();
+ parse_pop_key();
+
+ /* Write actions key, reversed to emulate parse actions. */
+ vt_key.integer = action_count;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+ vt_key.string = "Actions";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ /* Write new action according to the given arguments. */
+ vt_key.string = "Type";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = type;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+
+ vt_key.string = "Var1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = var1;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+
+ if (var_count > 1) {
+ vt_key.string = "Var2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = var2;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+
+ if (var_count > 2) {
+ vt_key.string = "Var3";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = var3;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+
+ parse_pop_key();
+ parse_pop_key();
}
@@ -2152,83 +2164,79 @@ parse_fixup_v380_action (sc_int type, sc_int var_count,
* Helper for parse_fixup_v380(), converts a task movement into an action.
*/
static void
-parse_fixup_v380_movement (sc_int mvar1, sc_int mvar2, sc_int mvar3)
-{
- sc_int var1;
-
- /* If nothing was selected to move, ignore the call. */
- if (mvar1 == 0)
- return;
-
- /*
- * Accept only player moves into rooms. Other combinations, such as move
- * player to worn by player, are unlikely. And move player to same room as
- * player isn't useful.
- */
- if (mvar1 == 1)
- {
- if (mvar3 == 0 && mvar2 >= 2)
- parse_fixup_v380_action (1, 3, 0, 0, mvar2 - 2);
- return;
- }
-
- /*
- * Convert movement var1 into action var1. Var1 is the dynamic object + 3,
- * or 2 for referenced object, or 0 for all held.
- */
- switch (mvar1)
- {
- case 2:
- var1 = 2;
- break; /* Referenced obj */
- case 3:
- var1 = 0;
- break; /* All held */
- default:
- var1 = mvar1 - 1;
- break; /* Dynamic obj */
- }
-
- /* Dissect the rest of the movement. */
- switch (mvar3)
- {
- case 0: /* To room */
- /*
- * Convert movement var2 into action var2 and var3. Var2 is 0 for move
- * to room, 6 for move to player room. Var3 is 0 for hidden, otherwise
- * the room number plus one.
- */
- if (mvar2 == 0) /* Hidden */
- parse_fixup_v380_action (0, 3, var1, 0, 0);
- else if (mvar2 == 1) /* Player room */
- parse_fixup_v380_action (0, 3, var1, 6, 0);
- else /* Specified room */
- parse_fixup_v380_action (0, 3, var1, 0, mvar2 - 1);
- break;
-
- case 1: /* To inside */
- case 2: /* To onto */
- /*
- * Convert movement var2 and var3 into action var3 and var2, a simple
- * conversion, but check that var2 is not 'not selected' first.
- */
- if (mvar2 > 0)
- parse_fixup_v380_action (0, 3, var1, mvar3 + 1, mvar2 - 1);
- break;
-
- case 3: /* To held by */
- case 4: /* To worn by */
- /*
- * Convert movement var2 and var3 into action var3 and var2, in this
- * case a simple conversion, since version 4.0 task actions are close
- * here.
- */
- parse_fixup_v380_action (0, 3, var1, mvar3 + 1, mvar2);
- break;
-
- default:
- sc_fatal ("parse_fixup_v380_movement: invalid mvar3, %ld\n", mvar3);
- }
+parse_fixup_v380_movement(sc_int mvar1, sc_int mvar2, sc_int mvar3) {
+ sc_int var1;
+
+ /* If nothing was selected to move, ignore the call. */
+ if (mvar1 == 0)
+ return;
+
+ /*
+ * Accept only player moves into rooms. Other combinations, such as move
+ * player to worn by player, are unlikely. And move player to same room as
+ * player isn't useful.
+ */
+ if (mvar1 == 1) {
+ if (mvar3 == 0 && mvar2 >= 2)
+ parse_fixup_v380_action(1, 3, 0, 0, mvar2 - 2);
+ return;
+ }
+
+ /*
+ * Convert movement var1 into action var1. Var1 is the dynamic object + 3,
+ * or 2 for referenced object, or 0 for all held.
+ */
+ switch (mvar1) {
+ case 2:
+ var1 = 2;
+ break; /* Referenced obj */
+ case 3:
+ var1 = 0;
+ break; /* All held */
+ default:
+ var1 = mvar1 - 1;
+ break; /* Dynamic obj */
+ }
+
+ /* Dissect the rest of the movement. */
+ switch (mvar3) {
+ case 0: /* To room */
+ /*
+ * Convert movement var2 into action var2 and var3. Var2 is 0 for move
+ * to room, 6 for move to player room. Var3 is 0 for hidden, otherwise
+ * the room number plus one.
+ */
+ if (mvar2 == 0) /* Hidden */
+ parse_fixup_v380_action(0, 3, var1, 0, 0);
+ else if (mvar2 == 1) /* Player room */
+ parse_fixup_v380_action(0, 3, var1, 6, 0);
+ else /* Specified room */
+ parse_fixup_v380_action(0, 3, var1, 0, mvar2 - 1);
+ break;
+
+ case 1: /* To inside */
+ case 2: /* To onto */
+ /*
+ * Convert movement var2 and var3 into action var3 and var2, a simple
+ * conversion, but check that var2 is not 'not selected' first.
+ */
+ if (mvar2 > 0)
+ parse_fixup_v380_action(0, 3, var1, mvar3 + 1, mvar2 - 1);
+ break;
+
+ case 3: /* To held by */
+ case 4: /* To worn by */
+ /*
+ * Convert movement var2 and var3 into action var3 and var2, in this
+ * case a simple conversion, since version 4.0 task actions are close
+ * here.
+ */
+ parse_fixup_v380_action(0, 3, var1, mvar3 + 1, mvar2);
+ break;
+
+ default:
+ sc_fatal("parse_fixup_v380_movement: invalid mvar3, %ld\n", mvar3);
+ }
}
@@ -2238,64 +2246,61 @@ parse_fixup_v380_movement (sc_int mvar1, sc_int mvar2, sc_int mvar3)
* Helper for parse_fixup_v380(), adds a task restriction.
*/
static void
-parse_fixup_v380_restr (sc_int type, sc_int var_count,
- sc_int var1, sc_int var2, sc_int var3,
- const sc_char *failmessage)
-{
- sc_vartype_t vt_key, vt_value;
- sc_int restriction_count;
-
- /* Get a count of restrictions so far defined for the task. */
- vt_key.string = "Restrictions";
- parse_push_key (vt_key, PROP_KEY_STRING);
- restriction_count = parse_get_child_count ();
- parse_pop_key ();
-
- /* Write restrictions key, reversed to emulate parse actions. */
- vt_key.integer = restriction_count;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
- vt_key.string = "Restrictions";
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- /* Write new restriction according to the given arguments. */
- vt_key.string = "Type";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = type;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
-
- vt_key.string = "Var1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = var1;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
-
- if (var_count > 1)
- {
- vt_key.string = "Var2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = var2;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
-
- if (var_count > 2)
- {
- vt_key.string = "Var3";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = var3;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
-
- vt_key.string = "FailMessage";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = failmessage;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
-
- parse_pop_key ();
- parse_pop_key ();
+parse_fixup_v380_restr(sc_int type, sc_int var_count,
+ sc_int var1, sc_int var2, sc_int var3,
+ const sc_char *failmessage) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int restriction_count;
+
+ /* Get a count of restrictions so far defined for the task. */
+ vt_key.string = "Restrictions";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ restriction_count = parse_get_child_count();
+ parse_pop_key();
+
+ /* Write restrictions key, reversed to emulate parse actions. */
+ vt_key.integer = restriction_count;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+ vt_key.string = "Restrictions";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ /* Write new restriction according to the given arguments. */
+ vt_key.string = "Type";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = type;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+
+ vt_key.string = "Var1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = var1;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+
+ if (var_count > 1) {
+ vt_key.string = "Var2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = var2;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+
+ if (var_count > 2) {
+ vt_key.string = "Var3";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = var3;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+
+ vt_key.string = "FailMessage";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = failmessage;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+
+ parse_pop_key();
+ parse_pop_key();
}
@@ -2310,223 +2315,201 @@ parse_fixup_v380_restr (sc_int type, sc_int var_count,
* Helper handlers for parse_fixup_v380(); create task restrictions.
*/
static void
-parse_fixup_v380_obj_restr (sc_bool holding,
- sc_int holdobj, const sc_char *failmessage)
-{
- /* Ignore if no object selected. */
- if (holdobj > 0)
- {
- sc_int var1, var2;
-
- /*
- * Create version 4.0 task restriction to check for either the
- * referenced object or a dynamic object being either held or in the
- * same room (visible to player).
- */
- var1 = (holdobj == 1) ? 2 : holdobj + 1;
- var2 = holding ? 1 : 3;
- parse_fixup_v380_restr (0, 3, var1, var2, 0, failmessage);
- }
+parse_fixup_v380_obj_restr(sc_bool holding,
+ sc_int holdobj, const sc_char *failmessage) {
+ /* Ignore if no object selected. */
+ if (holdobj > 0) {
+ sc_int var1, var2;
+
+ /*
+ * Create version 4.0 task restriction to check for either the
+ * referenced object or a dynamic object being either held or in the
+ * same room (visible to player).
+ */
+ var1 = (holdobj == 1) ? 2 : holdobj + 1;
+ var2 = holding ? 1 : 3;
+ parse_fixup_v380_restr(0, 3, var1, var2, 0, failmessage);
+ }
}
static void
-parse_fixup_v380_task_restr (sc_bool tasknotdone, sc_int task,
- const sc_char *failmessage)
-{
- /* Ignore if no task selected. */
- if (task > 0)
- {
- sc_int var2;
-
- /* Create version 4.0 restriction to check task state. */
- var2 = tasknotdone ? 1 : 0;
- parse_fixup_v380_restr (2, 2, task, var2, 0, failmessage);
- }
+parse_fixup_v380_task_restr(sc_bool tasknotdone, sc_int task,
+ const sc_char *failmessage) {
+ /* Ignore if no task selected. */
+ if (task > 0) {
+ sc_int var2;
+
+ /* Create version 4.0 restriction to check task state. */
+ var2 = tasknotdone ? 1 : 0;
+ parse_fixup_v380_restr(2, 2, task, var2, 0, failmessage);
+ }
}
static void
-parse_fixup_v380_wear_restr (sc_int wearobj, const sc_char *failmessage)
-{
- /* Ignore if no object selected. */
- if (wearobj > 0)
- {
- sc_vartype_t vt_key[3];
- sc_int object_count, object, dynamic, obj_index;
-
- /*
- * Create version 4.0 restrictions for something or nothing worn by
- * player.
- */
- if (wearobj == 1)
- {
- parse_fixup_v380_restr (0, 3, 1, 2, 0, failmessage);
- return;
- }
- else if (wearobj == 2)
- {
- parse_fixup_v380_restr (0, 3, 0, 2, 0, failmessage);
- return;
- }
-
- /* Get the count of objects defined. */
- vt_key[0].string = "Objects";
- object_count = prop_get_child_count (parse_bundle, "I<-s", vt_key);
-
- /* Convert wearobj from worn index to object index. */
- wearobj -= 2;
- for (object = 0; object < object_count && wearobj > 0; object++)
- {
- sc_bool bstatic, wearable;
-
- vt_key[1].integer = object;
- vt_key[2].string = "Static";
- bstatic = prop_get_boolean (parse_bundle, "B<-sis", vt_key);
- if (!bstatic)
- {
- vt_key[2].string = "Wearable";
- wearable = prop_get_boolean (parse_bundle, "B<-sis", vt_key);
- if (wearable)
- wearobj--;
- }
- }
- obj_index = object - 1;
-
- /* Now convert wearobj from object index to dynamic index. */
- dynamic = 0;
- for (object = 0; object <= obj_index; object++)
- {
- sc_bool bstatic;
-
- vt_key[1].integer = object;
- vt_key[2].string = "Static";
- bstatic = prop_get_boolean (parse_bundle, "B<-sis", vt_key);
- if (!bstatic)
- dynamic++;
- }
- dynamic--;
-
- /* Create version 4.0 restriction for object worn by player. */
- parse_fixup_v380_restr (0, 3, dynamic + 3, 2, 0, failmessage);
- }
+parse_fixup_v380_wear_restr(sc_int wearobj, const sc_char *failmessage) {
+ /* Ignore if no object selected. */
+ if (wearobj > 0) {
+ sc_vartype_t vt_key[3];
+ sc_int object_count, object, dynamic, obj_index;
+
+ /*
+ * Create version 4.0 restrictions for something or nothing worn by
+ * player.
+ */
+ if (wearobj == 1) {
+ parse_fixup_v380_restr(0, 3, 1, 2, 0, failmessage);
+ return;
+ } else if (wearobj == 2) {
+ parse_fixup_v380_restr(0, 3, 0, 2, 0, failmessage);
+ return;
+ }
+
+ /* Get the count of objects defined. */
+ vt_key[0].string = "Objects";
+ object_count = prop_get_child_count(parse_bundle, "I<-s", vt_key);
+
+ /* Convert wearobj from worn index to object index. */
+ wearobj -= 2;
+ for (object = 0; object < object_count && wearobj > 0; object++) {
+ sc_bool bstatic, wearable;
+
+ vt_key[1].integer = object;
+ vt_key[2].string = "Static";
+ bstatic = prop_get_boolean(parse_bundle, "B<-sis", vt_key);
+ if (!bstatic) {
+ vt_key[2].string = "Wearable";
+ wearable = prop_get_boolean(parse_bundle, "B<-sis", vt_key);
+ if (wearable)
+ wearobj--;
+ }
+ }
+ obj_index = object - 1;
+
+ /* Now convert wearobj from object index to dynamic index. */
+ dynamic = 0;
+ for (object = 0; object <= obj_index; object++) {
+ sc_bool bstatic;
+
+ vt_key[1].integer = object;
+ vt_key[2].string = "Static";
+ bstatic = prop_get_boolean(parse_bundle, "B<-sis", vt_key);
+ if (!bstatic)
+ dynamic++;
+ }
+ dynamic--;
+
+ /* Create version 4.0 restriction for object worn by player. */
+ parse_fixup_v380_restr(0, 3, dynamic + 3, 2, 0, failmessage);
+ }
}
static void
-parse_fixup_v380_npc_restr (sc_bool notinsameroom, sc_int npc,
- const sc_char *failmessage)
-{
- /* Ignore if no NPC selected. */
- if (npc > 0)
- {
- sc_int var2;
-
- if (npc == 1)
- {
- /* Create restriction to look for alone, or not. */
- var2 = notinsameroom ? 3 : 2;
- parse_fixup_v380_restr (3, 3, 0, var2, 0, failmessage);
- return;
- }
-
- /* Create restriction to look for company. */
- var2 = notinsameroom ? 1 : 0;
- parse_fixup_v380_restr (3, 3, 0, var2, npc, failmessage);
- }
+parse_fixup_v380_npc_restr(sc_bool notinsameroom, sc_int npc,
+ const sc_char *failmessage) {
+ /* Ignore if no NPC selected. */
+ if (npc > 0) {
+ sc_int var2;
+
+ if (npc == 1) {
+ /* Create restriction to look for alone, or not. */
+ var2 = notinsameroom ? 3 : 2;
+ parse_fixup_v380_restr(3, 3, 0, var2, 0, failmessage);
+ return;
+ }
+
+ /* Create restriction to look for company. */
+ var2 = notinsameroom ? 1 : 0;
+ parse_fixup_v380_restr(3, 3, 0, var2, npc, failmessage);
+ }
}
static void
-parse_fixup_v380_objroom_restr (sc_int obj, sc_int objroom,
- const sc_char *failmessage)
-{
- /* Ignore if no object selected. */
- if (obj > 0)
- {
- /* Create version 4.0 restriction to check object in room. */
- parse_fixup_v380_restr (0, 3, obj + 1, 0, objroom, failmessage);
- }
+parse_fixup_v380_objroom_restr(sc_int obj, sc_int objroom,
+ const sc_char *failmessage) {
+ /* Ignore if no object selected. */
+ if (obj > 0) {
+ /* Create version 4.0 restriction to check object in room. */
+ parse_fixup_v380_restr(0, 3, obj + 1, 0, objroom, failmessage);
+ }
}
static void
-parse_fixup_v380_objstate_restr (sc_int obj, sc_int ivar1, sc_int ivar2,
- const sc_char *failmessage)
-{
- sc_vartype_t vt_key[3];
- sc_int object, dynamic, var2, var3;
-
- /* Initialize variables to avoid gcc warnings. */
- var2 = -1;
- var3 = -1;
-
- /* Ignore restrictions with no "type". */
- if (ivar1 == 0)
- return;
-
- /* Look for opened/closed restrictions, convert and return. */
- if (ivar1 == 3 || ivar1 == 4)
- {
- sc_int stateful;
-
- /* Convert obj from object to openable (stateful) index. */
- stateful = 0;
- for (object = 0; object <= obj - 1; object++)
- {
- sc_int openable;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Openable";
- openable = prop_get_integer (parse_bundle, "I<-sis", vt_key);
- if (openable > 0)
- stateful++;
- }
- stateful--;
-
- /*
- * Create a version 4.0 restriction that checks that an object's state
- * is open (var2 = 0) or closed (var2 = 1).
- */
- var2 = (ivar1 == 3) ? 0 : 1;
- parse_fixup_v380_restr (1, 2, stateful + 1, var2, 0, failmessage);
- return;
- }
-
- /* Convert obj from object to dynamic index. */
- dynamic = 0;
- for (object = 0; object <= obj - 1; object++)
- {
- sc_bool bstatic;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Static";
- bstatic = prop_get_boolean (parse_bundle, "B<-sis", vt_key);
- if (!bstatic)
- dynamic++;
- }
- dynamic--;
-
- /* Create version 4.0 object location restrictions for the rest. */
- switch (ivar1)
- {
- case 1:
- var2 = 4;
- var3 = ivar2;
- break; /* Inside */
- case 2:
- var2 = 5;
- var3 = ivar2;
- break; /* On */
- case 5:
- var2 = 1;
- var3 = ivar2 + 1;
- break; /* Held by */
- case 6:
- var2 = 2;
- var3 = ivar2 + 1;
- break; /* Worn by */
- default:
- sc_fatal ("parse_fixup_v380_objstate_restr: invalid ivar1, %ld\n", ivar1);
- }
- parse_fixup_v380_restr (0, 3, dynamic + 3, var2, var3, failmessage);
+parse_fixup_v380_objstate_restr(sc_int obj, sc_int ivar1, sc_int ivar2,
+ const sc_char *failmessage) {
+ sc_vartype_t vt_key[3];
+ sc_int object, dynamic, var2, var3;
+
+ /* Initialize variables to avoid gcc warnings. */
+ var2 = -1;
+ var3 = -1;
+
+ /* Ignore restrictions with no "type". */
+ if (ivar1 == 0)
+ return;
+
+ /* Look for opened/closed restrictions, convert and return. */
+ if (ivar1 == 3 || ivar1 == 4) {
+ sc_int stateful;
+
+ /* Convert obj from object to openable (stateful) index. */
+ stateful = 0;
+ for (object = 0; object <= obj - 1; object++) {
+ sc_int openable;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Openable";
+ openable = prop_get_integer(parse_bundle, "I<-sis", vt_key);
+ if (openable > 0)
+ stateful++;
+ }
+ stateful--;
+
+ /*
+ * Create a version 4.0 restriction that checks that an object's state
+ * is open (var2 = 0) or closed (var2 = 1).
+ */
+ var2 = (ivar1 == 3) ? 0 : 1;
+ parse_fixup_v380_restr(1, 2, stateful + 1, var2, 0, failmessage);
+ return;
+ }
+
+ /* Convert obj from object to dynamic index. */
+ dynamic = 0;
+ for (object = 0; object <= obj - 1; object++) {
+ sc_bool bstatic;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Static";
+ bstatic = prop_get_boolean(parse_bundle, "B<-sis", vt_key);
+ if (!bstatic)
+ dynamic++;
+ }
+ dynamic--;
+
+ /* Create version 4.0 object location restrictions for the rest. */
+ switch (ivar1) {
+ case 1:
+ var2 = 4;
+ var3 = ivar2;
+ break; /* Inside */
+ case 2:
+ var2 = 5;
+ var3 = ivar2;
+ break; /* On */
+ case 5:
+ var2 = 1;
+ var3 = ivar2 + 1;
+ break; /* Held by */
+ case 6:
+ var2 = 2;
+ var3 = ivar2 + 1;
+ break; /* Worn by */
+ default:
+ sc_fatal("parse_fixup_v380_objstate_restr: invalid ivar1, %ld\n", ivar1);
+ }
+ parse_fixup_v380_restr(0, 3, dynamic + 3, var2, var3, failmessage);
}
@@ -2537,516 +2520,489 @@ parse_fixup_v380_objstate_restr (sc_int obj, sc_int ivar1, sc_int ivar2,
* 3.8 format into version 4.0.
*/
static void
-parse_fixup_v380 (const sc_char *fixup)
-{
- if (parse_trace)
- sc_trace ("Parse: entering version 3.8 fixup %s\n", fixup);
-
- /* Convert container capacity attributes to version 4.0 values. */
- if (strcmp (fixup, "|V380_OBJECT:#Capacity*10+2|") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int surfacecontainer;
-
- /* Get the object surface and container attributes. */
- vt_key.string = "SurfaceContainer";
- parse_push_key (vt_key, PROP_KEY_STRING);
- surfacecontainer = parse_get_integer_property ();
- parse_pop_key ();
-
- /* Convert capacity from version 3.8 format to version 4.0. */
- if (surfacecontainer == V380_OBJ_IS_CONTAINER)
- {
- sc_int capacity;
-
- vt_key.string = "Capacity";
- parse_push_key (vt_key, PROP_KEY_STRING);
- capacity = parse_get_integer_property ();
-
- capacity = capacity * V380_OBJ_CAPACITY_MULT + V380_OBJ_DEFAULT_SIZE;
-
- vt_value.integer = capacity;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
- }
-
- /*
- * Exchange openable values 5 and 6, watch for a possible 1 from a 3.8 game
- * (interpret as 0), and write -1 key for openable objects.
- */
- else if (strcmp (fixup, "|V380_OBJECT:_Openable_,Key|") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int openable;
-
- /* Retrieve Openable, and if 5 or 6, exchange. */
- vt_key.string = "Openable";
- parse_push_key (vt_key, PROP_KEY_STRING);
- openable = parse_get_integer_property ();
-
- if (openable == 5 || openable == 6)
- {
- vt_value.integer = (openable == 5) ? 6 : 5;
- parse_put_property (vt_value, PROP_INTEGER);
- }
-
- /* If the odd value of 1, rewrite as zero. */
- else if (openable == 1)
- {
- vt_value.integer = 0;
- parse_put_property (vt_value, PROP_INTEGER);
- }
-
- parse_pop_key ();
-
- /* For openable objects, store a Key of -1. */
- if (openable == 5 || openable == 6)
- {
- vt_key.string = "Key";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.integer = -1;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
- }
-
- /* Create version 4.0 task actions from a version 3.8 task. */
- else if (strcmp (fixup, "|V380_TASK:_Actions_|") == 0)
- {
- sc_vartype_t vt_key;
- sc_int score;
- sc_bool killsplayer, wingame;
- sc_int movement;
-
- /* Retrieve the score change for the task. */
- vt_key.string = "Score";
- parse_push_key (vt_key, PROP_KEY_STRING);
- score = parse_get_integer_property ();
- parse_pop_key ();
-
- /* Create any appropriate score change action. */
- if (score != 0)
- parse_fixup_v380_action (4, 1, score, 0, 0);
-
- /* Get player death and game winning flags. */
- vt_key.string = "KillsPlayer";
- parse_push_key (vt_key, PROP_KEY_STRING);
- killsplayer = parse_get_boolean_property ();
- parse_pop_key ();
- vt_key.string = "WinGame";
- parse_push_key (vt_key, PROP_KEY_STRING);
- wingame = parse_get_boolean_property ();
- parse_pop_key ();
-
- /* Create any appropriate game ending actions. */
- if (killsplayer)
- parse_fixup_v380_action (6, 1, 2, 0, 0);
- if (wingame)
- parse_fixup_v380_action (6, 1, 0, 0, 0);
-
- /* Handle each defined movement for the task. */
- for (movement = 0; movement < V380_TASK_MOVEMENTS; movement++)
- {
- sc_int mvar1, mvar2, mvar3;
-
- vt_key.integer = movement;
- parse_push_key (vt_key, PROP_KEY_INTEGER);
- vt_key.string = "Movements";
- parse_push_key (vt_key, PROP_KEY_STRING);
-
- /* Retrieve the movement parameters. */
- vt_key.string = "Var1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- mvar1 = parse_get_integer_property ();
- parse_pop_key ();
- vt_key.string = "Var2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- mvar2 = parse_get_integer_property ();
- parse_pop_key ();
- vt_key.string = "Var3";
- parse_push_key (vt_key, PROP_KEY_STRING);
- mvar3 = parse_get_integer_property ();
- parse_pop_key ();
-
- parse_pop_key ();
- parse_pop_key ();
-
- /* Create the corresponding task action. */
- parse_fixup_v380_movement (mvar1, mvar2, mvar3);
- }
- }
-
- /* Create version 4.0 task restrictions from a version 3.8 task. */
- else if (strcmp (fixup, "|V380_TASK:_Restrictions_|") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_bool holding, tasknotdone, notinsameroom;
- sc_int holdobj1, holdobj2, holdobj3, task;
- sc_int wearobj1, wearobj2, npc, obj1, obj1room, obj2;
- const sc_char *holdmsg, *taskmsg, *wearmsg, *companymsg;
- const sc_char *obj1msg;
- sc_int restriction_count;
-
- /* Create restrictions for objects not held or absent. */
- vt_key.string = "HoldingSameRoom";
- parse_push_key (vt_key, PROP_KEY_STRING);
- holding = parse_get_boolean_property ();
- parse_pop_key ();
-
- vt_key.string = "HoldObj1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- holdobj1 = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "HoldObj2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- holdobj2 = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "HoldObj3";
- parse_push_key (vt_key, PROP_KEY_STRING);
- holdobj3 = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "HoldMsg";
- parse_push_key (vt_key, PROP_KEY_STRING);
- holdmsg = parse_get_string_property ();
- parse_pop_key ();
-
- parse_fixup_v380_obj_restr (holding, holdobj1, holdmsg);
- parse_fixup_v380_obj_restr (holding, holdobj2, holdmsg);
- parse_fixup_v380_obj_restr (holding, holdobj3, holdmsg);
-
- /* Create any task state restriction. */
- vt_key.string = "TaskNotDone";
- parse_push_key (vt_key, PROP_KEY_STRING);
- tasknotdone = parse_get_boolean_property ();
- parse_pop_key ();
-
- vt_key.string = "Task";
- parse_push_key (vt_key, PROP_KEY_STRING);
- task = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "TaskMsg";
- parse_push_key (vt_key, PROP_KEY_STRING);
- taskmsg = parse_get_string_property ();
- parse_pop_key ();
-
- parse_fixup_v380_task_restr (tasknotdone, task, taskmsg);
-
- /* Create any object not worn restrictions. */
- vt_key.string = "WearObj1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- wearobj1 = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "WearObj2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- wearobj2 = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "WearMsg";
- parse_push_key (vt_key, PROP_KEY_STRING);
- wearmsg = parse_get_string_property ();
- parse_pop_key ();
-
- parse_fixup_v380_wear_restr (wearobj1, wearmsg);
- parse_fixup_v380_wear_restr (wearobj2, wearmsg);
-
- /* Check for presence/absence of NPCs restriction. */
- vt_key.string = "NotInSameRoom";
- parse_push_key (vt_key, PROP_KEY_STRING);
- notinsameroom = parse_get_boolean_property ();
- parse_pop_key ();
-
- vt_key.string = "NPC";
- parse_push_key (vt_key, PROP_KEY_STRING);
- npc = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "CompanyMsg";
- parse_push_key (vt_key, PROP_KEY_STRING);
- companymsg = parse_get_string_property ();
- parse_pop_key ();
-
- parse_fixup_v380_npc_restr (notinsameroom, npc, companymsg);
-
- /* Create any object location restriction. */
- vt_key.string = "Obj1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- obj1 = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "Obj1Room";
- parse_push_key (vt_key, PROP_KEY_STRING);
- obj1room = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "Obj1Msg";
- parse_push_key (vt_key, PROP_KEY_STRING);
- obj1msg = parse_get_string_property ();
- parse_pop_key ();
-
- parse_fixup_v380_objroom_restr (obj1, obj1room, obj1msg);
-
- /* And finally, any object state restriction. */
- vt_key.string = "Obj2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- obj2 = parse_get_integer_property ();
- parse_pop_key ();
-
- if (obj2 > 0)
- {
- sc_int var1, var2;
- const sc_char *obj2msg;
-
- vt_key.string = "Obj2Var1";
- parse_push_key (vt_key, PROP_KEY_STRING);
- var1 = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "Obj2Var2";
- parse_push_key (vt_key, PROP_KEY_STRING);
- var2 = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_key.string = "Obj2Msg";
- parse_push_key (vt_key, PROP_KEY_STRING);
- obj2msg = parse_get_string_property ();
- parse_pop_key ();
-
- parse_fixup_v380_objstate_restr (obj2, var1, var2, obj2msg);
- }
-
- /* Get a count of restrictions created. */
- vt_key.string = "Restrictions";
- parse_push_key (vt_key, PROP_KEY_STRING);
- restriction_count = parse_get_child_count ();
- parse_pop_key ();
-
- /* Allocate and fill a new mask for these restrictions. */
- if (restriction_count > 0)
- {
- sc_char *restrmask;
- sc_int index_;
-
- restrmask = (sc_char *)sc_malloc (2 * restriction_count);
- strcpy (restrmask, "#");
- for (index_ = 1; index_ < restriction_count; index_++)
- strcat (restrmask, "A#");
-
- vt_key.string = "RestrMask";
- parse_push_key (vt_key, PROP_KEY_STRING);
- vt_value.string = restrmask;
- parse_put_property (vt_value, PROP_STRING);
- parse_pop_key ();
-
- prop_adopt (parse_bundle, restrmask);
- }
- }
-
- /*
- * Adjust dynamic object initial positions and parents (where contained
- * or on surfaces) into version 4.0 range.
- */
- else if (strcmp (fixup, "|V380_OBJECT:_InitialPositions_|") == 0)
- {
- sc_vartype_t vt_key[3];
- sc_int object_count, object, *object_type;
-
- /* Get a count of objects. */
- vt_key[0].string = "Objects";
- object_count = prop_get_child_count (parse_bundle, "I<-s", vt_key);
-
- /* Build an array of object container/surface types. */
- object_type = (sc_int *)sc_malloc (object_count * sizeof (*object_type));
- for (object = 0; object < object_count; object++)
- {
- vt_key[1].integer = object;
- vt_key[2].string = "SurfaceContainer";
- object_type[object] = prop_get_integer (parse_bundle,
- "I<-sis", vt_key);
- }
-
- /* Adjust each object's initial position if necessary. */
- for (object = 0; object < object_count; object++)
- {
- sc_vartype_t vt_value;
- sc_bool is_static;
- sc_int initialposition;
-
- /* Ignore static objects; we only want dynamic ones. */
- vt_key[1].integer = object;
- vt_key[2].string = "Static";
- is_static = prop_get_boolean (parse_bundle, "B<-sis", vt_key);
- if (is_static)
- continue;
-
- /* If initial position is above on/in, increment. */
- vt_key[1].integer = object;
- vt_key[2].string = "InitialPosition";
- initialposition = prop_get_integer (parse_bundle, "I<-sis", vt_key);
- if (initialposition > 2)
- {
- vt_value.integer = initialposition + 1;
- prop_put (parse_bundle, "I->sis", vt_value, vt_key);
- }
-
- /*
- * If initial position is on or in, decide which, depending on the
- * type of the parent. From this, expand initial position into a
- * version 4.0 value.
- */
- if (initialposition == 2)
- {
- sc_int count, parent, index_;
-
- /* Get parent container/surface index. */
- vt_key[1].integer = object;
- vt_key[2].string = "Parent";
- count = prop_get_integer (parse_bundle, "I<-sis", vt_key);
-
- /* Convert container/surface index. */
- for (parent = 0; parent < object_count && count >= 0; parent++)
- {
- if (object_type[parent] == V380_OBJ_IS_CONTAINER
- || object_type[parent] == V380_OBJ_IS_SURFACE)
- count--;
- }
- parent--;
-
- /* If parent is a surface, adjust position. */
- if (object_type[parent] == V380_OBJ_IS_SURFACE)
- {
- vt_key[2].string = "InitialPosition";
- vt_value.integer = initialposition + 1;
- prop_put (parse_bundle, "I->sis", vt_value, vt_key);
- }
-
- /*
- * For both, adjust parent to be an object index for that type
- * of object only.
- */
- count = 0;
- for (index_ = 0; index_ < parent; index_++)
- {
- if (object_type[index_] == object_type[parent])
- count++;
- }
- vt_key[2].string = "Parent";
- vt_value.integer = count;
- prop_put (parse_bundle, "I->sis", vt_value, vt_key);
- }
- }
-
- /* Done with temporary array. */
- sc_free (object_type);
- }
-
- /* Convert carry limit into version 4.0-like size and weight limits. */
- else if (strcmp (fixup, "|V380_MaxSize_MaxWt_|") == 0)
- {
- sc_vartype_t vt_key, vt_value;
- sc_int maxcarried;
-
- vt_key.string = "MaxCarried";
- parse_push_key (vt_key, PROP_KEY_STRING);
- maxcarried = parse_get_integer_property ();
- parse_pop_key ();
-
- vt_value.integer = maxcarried * V380_OBJ_CAPACITY_MULT
- + V380_OBJ_DEFAULT_SIZE;
-
- vt_key.string = "MaxSize";
- parse_push_key (vt_key, PROP_KEY_STRING);
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
-
- vt_key.string = "MaxWt";
- parse_push_key (vt_key, PROP_KEY_STRING);
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
-
- /* Add up positive scoring tasks to arrive at max score. */
- else if (strcmp (fixup, "|V380_GLOBAL:_MaxScore_|") == 0)
- {
- sc_vartype_t vt_key[3], vt_value;
- sc_int task_count, maxscore, task;
-
- /* Get a count of tasks. */
- vt_key[0].string = "Tasks";
- task_count = prop_get_child_count (parse_bundle, "I<-s", vt_key);
-
- /* Sum positive scoring tasks. */
- maxscore = 0;
- for (task = 0; task < task_count; task++)
- {
- sc_int score;
-
- vt_key[1].integer = task;
- vt_key[2].string = "Score";
- score = prop_get_integer (parse_bundle, "I<-sis", vt_key);
- if (score > 0)
- maxscore += score;
- }
-
- /* Write MaxScore global property. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "MaxScore";
- vt_value.integer = maxscore;
- prop_put (parse_bundle, "I->ss", vt_value, vt_key);
- }
-
- /* Convert walk meetobject from dynamic index to object. */
- else if (strcmp (fixup, "|V380_WALK:_MeetObject_|") == 0)
- {
- sc_vartype_t vt_key, vt_value, vt_gkey[3];
- sc_int meetobject, count, object_count, object;
-
- vt_key.string = "MeetObject";
- parse_push_key (vt_key, PROP_KEY_STRING);
- meetobject = parse_get_integer_property ();
-
- /* Get a count of objects. */
- vt_gkey[0].string = "Objects";
- object_count = prop_get_child_count (parse_bundle, "I<-s", vt_gkey);
-
- /* Convert dynamic index to object, and rewrite. */
- count = meetobject - 1;
- for (object = 0; object < object_count && count >= 0; object++)
- {
- sc_bool bstatic;
-
- vt_gkey[1].integer = object;
- vt_gkey[2].string = "Static";
- bstatic = prop_get_boolean (parse_bundle, "B<-sis", vt_gkey);
- if (!bstatic)
- count--;
- }
- object--;
-
- vt_value.integer = object;
- parse_put_property (vt_value, PROP_INTEGER);
- parse_pop_key ();
- }
-
- /* Convert version 3.8 room data into a version 4.0 alts array. */
- else if (strcmp (fixup, "|V380_ROOM:_Alts_|") == 0)
- {
- parse_fixup_v390_v380_room_alts ();
- }
-
- /* Error if no fixup special handler available. */
- else
- {
- sc_fatal ("parse_fixup_v380: no handler for \"%s\"\n", fixup);
- }
-
- if (parse_trace)
- sc_trace ("Parse: leaving version 3.8 fixup %s\n", fixup);
+parse_fixup_v380(const sc_char *fixup) {
+ if (parse_trace)
+ sc_trace("Parse: entering version 3.8 fixup %s\n", fixup);
+
+ /* Convert container capacity attributes to version 4.0 values. */
+ if (strcmp(fixup, "|V380_OBJECT:#Capacity*10+2|") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int surfacecontainer;
+
+ /* Get the object surface and container attributes. */
+ vt_key.string = "SurfaceContainer";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ surfacecontainer = parse_get_integer_property();
+ parse_pop_key();
+
+ /* Convert capacity from version 3.8 format to version 4.0. */
+ if (surfacecontainer == V380_OBJ_IS_CONTAINER) {
+ sc_int capacity;
+
+ vt_key.string = "Capacity";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ capacity = parse_get_integer_property();
+
+ capacity = capacity * V380_OBJ_CAPACITY_MULT + V380_OBJ_DEFAULT_SIZE;
+
+ vt_value.integer = capacity;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+ }
+
+ /*
+ * Exchange openable values 5 and 6, watch for a possible 1 from a 3.8 game
+ * (interpret as 0), and write -1 key for openable objects.
+ */
+ else if (strcmp(fixup, "|V380_OBJECT:_Openable_,Key|") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int openable;
+
+ /* Retrieve Openable, and if 5 or 6, exchange. */
+ vt_key.string = "Openable";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ openable = parse_get_integer_property();
+
+ if (openable == 5 || openable == 6) {
+ vt_value.integer = (openable == 5) ? 6 : 5;
+ parse_put_property(vt_value, PROP_INTEGER);
+ }
+
+ /* If the odd value of 1, rewrite as zero. */
+ else if (openable == 1) {
+ vt_value.integer = 0;
+ parse_put_property(vt_value, PROP_INTEGER);
+ }
+
+ parse_pop_key();
+
+ /* For openable objects, store a Key of -1. */
+ if (openable == 5 || openable == 6) {
+ vt_key.string = "Key";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.integer = -1;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+ }
+
+ /* Create version 4.0 task actions from a version 3.8 task. */
+ else if (strcmp(fixup, "|V380_TASK:_Actions_|") == 0) {
+ sc_vartype_t vt_key;
+ sc_int score;
+ sc_bool killsplayer, wingame;
+ sc_int movement;
+
+ /* Retrieve the score change for the task. */
+ vt_key.string = "Score";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ score = parse_get_integer_property();
+ parse_pop_key();
+
+ /* Create any appropriate score change action. */
+ if (score != 0)
+ parse_fixup_v380_action(4, 1, score, 0, 0);
+
+ /* Get player death and game winning flags. */
+ vt_key.string = "KillsPlayer";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ killsplayer = parse_get_boolean_property();
+ parse_pop_key();
+ vt_key.string = "WinGame";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ wingame = parse_get_boolean_property();
+ parse_pop_key();
+
+ /* Create any appropriate game ending actions. */
+ if (killsplayer)
+ parse_fixup_v380_action(6, 1, 2, 0, 0);
+ if (wingame)
+ parse_fixup_v380_action(6, 1, 0, 0, 0);
+
+ /* Handle each defined movement for the task. */
+ for (movement = 0; movement < V380_TASK_MOVEMENTS; movement++) {
+ sc_int mvar1, mvar2, mvar3;
+
+ vt_key.integer = movement;
+ parse_push_key(vt_key, PROP_KEY_INTEGER);
+ vt_key.string = "Movements";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+
+ /* Retrieve the movement parameters. */
+ vt_key.string = "Var1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ mvar1 = parse_get_integer_property();
+ parse_pop_key();
+ vt_key.string = "Var2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ mvar2 = parse_get_integer_property();
+ parse_pop_key();
+ vt_key.string = "Var3";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ mvar3 = parse_get_integer_property();
+ parse_pop_key();
+
+ parse_pop_key();
+ parse_pop_key();
+
+ /* Create the corresponding task action. */
+ parse_fixup_v380_movement(mvar1, mvar2, mvar3);
+ }
+ }
+
+ /* Create version 4.0 task restrictions from a version 3.8 task. */
+ else if (strcmp(fixup, "|V380_TASK:_Restrictions_|") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_bool holding, tasknotdone, notinsameroom;
+ sc_int holdobj1, holdobj2, holdobj3, task;
+ sc_int wearobj1, wearobj2, npc, obj1, obj1room, obj2;
+ const sc_char *holdmsg, *taskmsg, *wearmsg, *companymsg;
+ const sc_char *obj1msg;
+ sc_int restriction_count;
+
+ /* Create restrictions for objects not held or absent. */
+ vt_key.string = "HoldingSameRoom";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ holding = parse_get_boolean_property();
+ parse_pop_key();
+
+ vt_key.string = "HoldObj1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ holdobj1 = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "HoldObj2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ holdobj2 = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "HoldObj3";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ holdobj3 = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "HoldMsg";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ holdmsg = parse_get_string_property();
+ parse_pop_key();
+
+ parse_fixup_v380_obj_restr(holding, holdobj1, holdmsg);
+ parse_fixup_v380_obj_restr(holding, holdobj2, holdmsg);
+ parse_fixup_v380_obj_restr(holding, holdobj3, holdmsg);
+
+ /* Create any task state restriction. */
+ vt_key.string = "TaskNotDone";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ tasknotdone = parse_get_boolean_property();
+ parse_pop_key();
+
+ vt_key.string = "Task";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ task = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "TaskMsg";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ taskmsg = parse_get_string_property();
+ parse_pop_key();
+
+ parse_fixup_v380_task_restr(tasknotdone, task, taskmsg);
+
+ /* Create any object not worn restrictions. */
+ vt_key.string = "WearObj1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ wearobj1 = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "WearObj2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ wearobj2 = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "WearMsg";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ wearmsg = parse_get_string_property();
+ parse_pop_key();
+
+ parse_fixup_v380_wear_restr(wearobj1, wearmsg);
+ parse_fixup_v380_wear_restr(wearobj2, wearmsg);
+
+ /* Check for presence/absence of NPCs restriction. */
+ vt_key.string = "NotInSameRoom";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ notinsameroom = parse_get_boolean_property();
+ parse_pop_key();
+
+ vt_key.string = "NPC";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ npc = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "CompanyMsg";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ companymsg = parse_get_string_property();
+ parse_pop_key();
+
+ parse_fixup_v380_npc_restr(notinsameroom, npc, companymsg);
+
+ /* Create any object location restriction. */
+ vt_key.string = "Obj1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ obj1 = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "Obj1Room";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ obj1room = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "Obj1Msg";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ obj1msg = parse_get_string_property();
+ parse_pop_key();
+
+ parse_fixup_v380_objroom_restr(obj1, obj1room, obj1msg);
+
+ /* And finally, any object state restriction. */
+ vt_key.string = "Obj2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ obj2 = parse_get_integer_property();
+ parse_pop_key();
+
+ if (obj2 > 0) {
+ sc_int var1, var2;
+ const sc_char *obj2msg;
+
+ vt_key.string = "Obj2Var1";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ var1 = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "Obj2Var2";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ var2 = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_key.string = "Obj2Msg";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ obj2msg = parse_get_string_property();
+ parse_pop_key();
+
+ parse_fixup_v380_objstate_restr(obj2, var1, var2, obj2msg);
+ }
+
+ /* Get a count of restrictions created. */
+ vt_key.string = "Restrictions";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ restriction_count = parse_get_child_count();
+ parse_pop_key();
+
+ /* Allocate and fill a new mask for these restrictions. */
+ if (restriction_count > 0) {
+ sc_char *restrmask;
+ sc_int index_;
+
+ restrmask = (sc_char *)sc_malloc(2 * restriction_count);
+ strcpy(restrmask, "#");
+ for (index_ = 1; index_ < restriction_count; index_++)
+ strcat(restrmask, "A#");
+
+ vt_key.string = "RestrMask";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ vt_value.string = restrmask;
+ parse_put_property(vt_value, PROP_STRING);
+ parse_pop_key();
+
+ prop_adopt(parse_bundle, restrmask);
+ }
+ }
+
+ /*
+ * Adjust dynamic object initial positions and parents (where contained
+ * or on surfaces) into version 4.0 range.
+ */
+ else if (strcmp(fixup, "|V380_OBJECT:_InitialPositions_|") == 0) {
+ sc_vartype_t vt_key[3];
+ sc_int object_count, object, *object_type;
+
+ /* Get a count of objects. */
+ vt_key[0].string = "Objects";
+ object_count = prop_get_child_count(parse_bundle, "I<-s", vt_key);
+
+ /* Build an array of object container/surface types. */
+ object_type = (sc_int *)sc_malloc(object_count * sizeof(*object_type));
+ for (object = 0; object < object_count; object++) {
+ vt_key[1].integer = object;
+ vt_key[2].string = "SurfaceContainer";
+ object_type[object] = prop_get_integer(parse_bundle,
+ "I<-sis", vt_key);
+ }
+
+ /* Adjust each object's initial position if necessary. */
+ for (object = 0; object < object_count; object++) {
+ sc_vartype_t vt_value;
+ sc_bool is_static;
+ sc_int initialposition;
+
+ /* Ignore static objects; we only want dynamic ones. */
+ vt_key[1].integer = object;
+ vt_key[2].string = "Static";
+ is_static = prop_get_boolean(parse_bundle, "B<-sis", vt_key);
+ if (is_static)
+ continue;
+
+ /* If initial position is above on/in, increment. */
+ vt_key[1].integer = object;
+ vt_key[2].string = "InitialPosition";
+ initialposition = prop_get_integer(parse_bundle, "I<-sis", vt_key);
+ if (initialposition > 2) {
+ vt_value.integer = initialposition + 1;
+ prop_put(parse_bundle, "I->sis", vt_value, vt_key);
+ }
+
+ /*
+ * If initial position is on or in, decide which, depending on the
+ * type of the parent. From this, expand initial position into a
+ * version 4.0 value.
+ */
+ if (initialposition == 2) {
+ sc_int count, parent, index_;
+
+ /* Get parent container/surface index. */
+ vt_key[1].integer = object;
+ vt_key[2].string = "Parent";
+ count = prop_get_integer(parse_bundle, "I<-sis", vt_key);
+
+ /* Convert container/surface index. */
+ for (parent = 0; parent < object_count && count >= 0; parent++) {
+ if (object_type[parent] == V380_OBJ_IS_CONTAINER
+ || object_type[parent] == V380_OBJ_IS_SURFACE)
+ count--;
+ }
+ parent--;
+
+ /* If parent is a surface, adjust position. */
+ if (object_type[parent] == V380_OBJ_IS_SURFACE) {
+ vt_key[2].string = "InitialPosition";
+ vt_value.integer = initialposition + 1;
+ prop_put(parse_bundle, "I->sis", vt_value, vt_key);
+ }
+
+ /*
+ * For both, adjust parent to be an object index for that type
+ * of object only.
+ */
+ count = 0;
+ for (index_ = 0; index_ < parent; index_++) {
+ if (object_type[index_] == object_type[parent])
+ count++;
+ }
+ vt_key[2].string = "Parent";
+ vt_value.integer = count;
+ prop_put(parse_bundle, "I->sis", vt_value, vt_key);
+ }
+ }
+
+ /* Done with temporary array. */
+ sc_free(object_type);
+ }
+
+ /* Convert carry limit into version 4.0-like size and weight limits. */
+ else if (strcmp(fixup, "|V380_MaxSize_MaxWt_|") == 0) {
+ sc_vartype_t vt_key, vt_value;
+ sc_int maxcarried;
+
+ vt_key.string = "MaxCarried";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ maxcarried = parse_get_integer_property();
+ parse_pop_key();
+
+ vt_value.integer = maxcarried * V380_OBJ_CAPACITY_MULT
+ + V380_OBJ_DEFAULT_SIZE;
+
+ vt_key.string = "MaxSize";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+
+ vt_key.string = "MaxWt";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+
+ /* Add up positive scoring tasks to arrive at max score. */
+ else if (strcmp(fixup, "|V380_GLOBAL:_MaxScore_|") == 0) {
+ sc_vartype_t vt_key[3], vt_value;
+ sc_int task_count, maxscore, task;
+
+ /* Get a count of tasks. */
+ vt_key[0].string = "Tasks";
+ task_count = prop_get_child_count(parse_bundle, "I<-s", vt_key);
+
+ /* Sum positive scoring tasks. */
+ maxscore = 0;
+ for (task = 0; task < task_count; task++) {
+ sc_int score;
+
+ vt_key[1].integer = task;
+ vt_key[2].string = "Score";
+ score = prop_get_integer(parse_bundle, "I<-sis", vt_key);
+ if (score > 0)
+ maxscore += score;
+ }
+
+ /* Write MaxScore global property. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "MaxScore";
+ vt_value.integer = maxscore;
+ prop_put(parse_bundle, "I->ss", vt_value, vt_key);
+ }
+
+ /* Convert walk meetobject from dynamic index to object. */
+ else if (strcmp(fixup, "|V380_WALK:_MeetObject_|") == 0) {
+ sc_vartype_t vt_key, vt_value, vt_gkey[3];
+ sc_int meetobject, count, object_count, object;
+
+ vt_key.string = "MeetObject";
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ meetobject = parse_get_integer_property();
+
+ /* Get a count of objects. */
+ vt_gkey[0].string = "Objects";
+ object_count = prop_get_child_count(parse_bundle, "I<-s", vt_gkey);
+
+ /* Convert dynamic index to object, and rewrite. */
+ count = meetobject - 1;
+ for (object = 0; object < object_count && count >= 0; object++) {
+ sc_bool bstatic;
+
+ vt_gkey[1].integer = object;
+ vt_gkey[2].string = "Static";
+ bstatic = prop_get_boolean(parse_bundle, "B<-sis", vt_gkey);
+ if (!bstatic)
+ count--;
+ }
+ object--;
+
+ vt_value.integer = object;
+ parse_put_property(vt_value, PROP_INTEGER);
+ parse_pop_key();
+ }
+
+ /* Convert version 3.8 room data into a version 4.0 alts array. */
+ else if (strcmp(fixup, "|V380_ROOM:_Alts_|") == 0) {
+ parse_fixup_v390_v380_room_alts();
+ }
+
+ /* Error if no fixup special handler available. */
+ else {
+ sc_fatal("parse_fixup_v380: no handler for \"%s\"\n", fixup);
+ }
+
+ if (parse_trace)
+ sc_trace("Parse: leaving version 3.8 fixup %s\n", fixup);
}
@@ -3057,27 +3013,25 @@ parse_fixup_v380 (const sc_char *fixup)
* 3.9 and version 3.8 formats into version 4.0.
*/
static void
-parse_fixup (const sc_char *fixup)
-{
- /*
- * Pick a fixup handler specific to the TAF version. This helps keep
- * fixup code separate, rather than glommed into one large function.
- */
- switch (taf_get_version (parse_taf))
- {
- case TAF_VERSION_400:
- sc_fatal ("parse_fixup: unexpected call\n");
- break;
- case TAF_VERSION_390:
- parse_fixup_v390 (fixup);
- break;
- case TAF_VERSION_380:
- parse_fixup_v380 (fixup);
- break;
- default:
- sc_fatal ("parse_fixup: invalid TAF file version\n");
- break;
- }
+parse_fixup(const sc_char *fixup) {
+ /*
+ * Pick a fixup handler specific to the TAF version. This helps keep
+ * fixup code separate, rather than glommed into one large function.
+ */
+ switch (taf_get_version(parse_taf)) {
+ case TAF_VERSION_400:
+ sc_fatal("parse_fixup: unexpected call\n");
+ break;
+ case TAF_VERSION_390:
+ parse_fixup_v390(fixup);
+ break;
+ case TAF_VERSION_380:
+ parse_fixup_v380(fixup);
+ break;
+ default:
+ sc_fatal("parse_fixup: invalid TAF file version\n");
+ break;
+ }
}
@@ -3087,55 +3041,53 @@ parse_fixup (const sc_char *fixup)
* Parse a class descriptor element.
*/
static void
-parse_element (const sc_char *element)
-{
- if (parse_trace)
- sc_trace ("Parse: entering element %s\n", element);
-
- /* Determine the element type from the first character. */
- switch (element[0])
- {
- case PARSE_ARRAY:
- parse_array (element);
- break;
- case PARSE_VECTOR:
- parse_vector (element);
- break;
- case PARSE_VECTOR_ALTERNATE:
- parse_vector_alternate (element);
- break;
- case PARSE_CLASS:
- parse_class (element);
- break;
- case PARSE_EXPRESSION:
- parse_expression (element);
- break;
- case PARSE_SPECIAL:
- parse_special (element);
- break;
- case PARSE_FIXUP:
- parse_fixup (element);
- break;
-
- case PARSE_INTEGER:
- case PARSE_DEFAULT_ZERO:
- case PARSE_BOOLEAN:
- case PARSE_DEFAULT_TRUE:
- case PARSE_DEFAULT_FALSE:
- case PARSE_STRING:
- case PARSE_DEFAULT_EMPTY:
- case PARSE_IGNORE_INTEGER:
- case PARSE_IGNORE_BOOLEAN:
- case PARSE_IGNORE_STRING:
- case PARSE_MULTILINE:
- parse_terminal (element);
- break;
- default:
- sc_fatal ("parse_element: bad type, %c\n", element[0]);
- }
-
- if (parse_trace)
- sc_trace ("Parse: leaving element %s\n", element);
+parse_element(const sc_char *element) {
+ if (parse_trace)
+ sc_trace("Parse: entering element %s\n", element);
+
+ /* Determine the element type from the first character. */
+ switch (element[0]) {
+ case PARSE_ARRAY:
+ parse_array(element);
+ break;
+ case PARSE_VECTOR:
+ parse_vector(element);
+ break;
+ case PARSE_VECTOR_ALTERNATE:
+ parse_vector_alternate(element);
+ break;
+ case PARSE_CLASS:
+ parse_class(element);
+ break;
+ case PARSE_EXPRESSION:
+ parse_expression(element);
+ break;
+ case PARSE_SPECIAL:
+ parse_special(element);
+ break;
+ case PARSE_FIXUP:
+ parse_fixup(element);
+ break;
+
+ case PARSE_INTEGER:
+ case PARSE_DEFAULT_ZERO:
+ case PARSE_BOOLEAN:
+ case PARSE_DEFAULT_TRUE:
+ case PARSE_DEFAULT_FALSE:
+ case PARSE_STRING:
+ case PARSE_DEFAULT_EMPTY:
+ case PARSE_IGNORE_INTEGER:
+ case PARSE_IGNORE_BOOLEAN:
+ case PARSE_IGNORE_STRING:
+ case PARSE_MULTILINE:
+ parse_terminal(element);
+ break;
+ default:
+ sc_fatal("parse_element: bad type, %c\n", element[0]);
+ }
+
+ if (parse_trace)
+ sc_trace("Parse: leaving element %s\n", element);
}
@@ -3145,26 +3097,24 @@ parse_element (const sc_char *element)
* Parse a class's properties descriptor list.
*/
static void
-parse_descriptor (const sc_char *descriptor)
-{
- sc_int next;
-
- /* Find and parse each element in the descriptor. */
- for (next = 0; descriptor[next] != NUL; )
- {
- sc_char element[PARSE_TEMP_LENGTH];
-
- /* Isolate the next descriptor element. */
- if (sscanf (descriptor + next, "%[^ ]", element) != 1)
- sc_fatal ("parse_element: no element, %s\n", descriptor + next);
-
- /* Parse this isolated element. */
- parse_element (element);
-
- /* Advance over the element and any trailing whitespace. */
- next += strlen (element);
- next += strspn (descriptor + next, " ");
- }
+parse_descriptor(const sc_char *descriptor) {
+ sc_int next;
+
+ /* Find and parse each element in the descriptor. */
+ for (next = 0; descriptor[next] != NUL;) {
+ sc_char element[PARSE_TEMP_LENGTH];
+
+ /* Isolate the next descriptor element. */
+ if (sscanf(descriptor + next, "%[^ ]", element) != 1)
+ sc_fatal("parse_element: no element, %s\n", descriptor + next);
+
+ /* Parse this isolated element. */
+ parse_element(element);
+
+ /* Advance over the element and any trailing whitespace. */
+ next += strlen(element);
+ next += strspn(descriptor + next, " ");
+ }
}
@@ -3174,47 +3124,44 @@ parse_descriptor (const sc_char *descriptor)
* Parse a class of properties.
*/
static void
-parse_class (const sc_char *class_)
-{
- sc_char class_name[PARSE_TEMP_LENGTH];
- sc_int index_;
- sc_vartype_t vt_key;
-
- /* Isolate the class name. */
- if (sscanf (class_, "<%[^>]", class_name) != 1)
- sc_fatal ("parse_class: error in class, %s\n", class_);
- if (parse_trace)
- sc_trace ("Parse: entering class %s\n", class_name);
-
- /* Find the class in the parse schema, and fail if not found. */
- for (index_ = 0; parse_schema[index_].class_name; index_++)
- {
- if (strcmp (parse_schema[index_].class_name, class_name) == 0)
- break;
- }
- if (!parse_schema[index_].class_name)
- sc_fatal ("parse_class: class not described, %s\n", class_name);
-
- /*
- * Unless we are at the top level of the parse schema, push the class tag
- * as a key. The top level is "_GAME_", index_ 0, and isn't part of key
- * formation.
- */
- if (index_ > 0)
- {
- vt_key.string = class_ + strlen (class_name) + 2;
- parse_push_key (vt_key, PROP_KEY_STRING);
- }
-
- /* Parse each element in the descriptor. */
- parse_descriptor (parse_schema[index_].descriptor);
-
- /* Pop a key if the class tag was pushed above. */
- if (index_ > 0)
- parse_pop_key ();
-
- if (parse_trace)
- sc_trace ("Parse: leaving class %s\n", class_name);
+parse_class(const sc_char *class_) {
+ sc_char class_name[PARSE_TEMP_LENGTH];
+ sc_int index_;
+ sc_vartype_t vt_key;
+
+ /* Isolate the class name. */
+ if (sscanf(class_, "<%[^>]", class_name) != 1)
+ sc_fatal("parse_class: error in class, %s\n", class_);
+ if (parse_trace)
+ sc_trace("Parse: entering class %s\n", class_name);
+
+ /* Find the class in the parse schema, and fail if not found. */
+ for (index_ = 0; parse_schema[index_].class_name; index_++) {
+ if (strcmp(parse_schema[index_].class_name, class_name) == 0)
+ break;
+ }
+ if (!parse_schema[index_].class_name)
+ sc_fatal("parse_class: class not described, %s\n", class_name);
+
+ /*
+ * Unless we are at the top level of the parse schema, push the class tag
+ * as a key. The top level is "_GAME_", index_ 0, and isn't part of key
+ * formation.
+ */
+ if (index_ > 0) {
+ vt_key.string = class_ + strlen(class_name) + 2;
+ parse_push_key(vt_key, PROP_KEY_STRING);
+ }
+
+ /* Parse each element in the descriptor. */
+ parse_descriptor(parse_schema[index_].descriptor);
+
+ /* Pop a key if the class tag was pushed above. */
+ if (index_ > 0)
+ parse_pop_key();
+
+ if (parse_trace)
+ sc_trace("Parse: leaving class %s\n", class_name);
}
@@ -3225,54 +3172,50 @@ parse_class (const sc_char *class_)
* that occurs after the TAF file has been successfully parsed.
*/
static void
-parse_add_walkalerts (sc_prop_setref_t bundle)
-{
- sc_vartype_t vt_key[5];
- sc_int npcs_count, npc;
-
- /* Get the count of NPCs. */
- vt_key[0].string = "NPCs";
- npcs_count = prop_get_child_count (bundle, "I<-s", vt_key);
-
- /* Set up each NPC. */
- for (npc = 0; npc < npcs_count; npc++)
- {
- sc_int walk_count, walk;
-
- /* Get NPC walk details. */
- vt_key[1].integer = npc;
- vt_key[2].string = "Walks";
- walk_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- for (walk = 0; walk < walk_count; walk++)
- {
- sc_int starttask;
-
- /* Get start task of walk. */
- vt_key[3].integer = walk;
- vt_key[4].string = "StartTask";
- starttask = prop_get_integer (bundle, "I<-sisis", vt_key) - 1;
- if (starttask >= 0)
- {
- sc_vartype_t vt_key2[4], vt_value;
- sc_int count;
-
- /* Count existing walkalerts for the task. */
- vt_key2[0].string = "Tasks";
- vt_key2[1].integer = starttask;
- vt_key2[2].string = "NPCWalkAlert";
- count = prop_get_child_count (bundle, "I<-sis", vt_key2);
-
- /* Add two more -- NPC and walk. */
- vt_key2[3].integer = count;
- vt_value.integer = npc;
- prop_put (bundle, "I->sisi", vt_value, vt_key2);
- vt_key2[3].integer = count + 1;
- vt_value.integer = walk;
- prop_put (bundle, "I->sisi", vt_value, vt_key2);
- }
- }
- }
+parse_add_walkalerts(sc_prop_setref_t bundle) {
+ sc_vartype_t vt_key[5];
+ sc_int npcs_count, npc;
+
+ /* Get the count of NPCs. */
+ vt_key[0].string = "NPCs";
+ npcs_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ /* Set up each NPC. */
+ for (npc = 0; npc < npcs_count; npc++) {
+ sc_int walk_count, walk;
+
+ /* Get NPC walk details. */
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Walks";
+ walk_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ for (walk = 0; walk < walk_count; walk++) {
+ sc_int starttask;
+
+ /* Get start task of walk. */
+ vt_key[3].integer = walk;
+ vt_key[4].string = "StartTask";
+ starttask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
+ if (starttask >= 0) {
+ sc_vartype_t vt_key2[4], vt_value;
+ sc_int count;
+
+ /* Count existing walkalerts for the task. */
+ vt_key2[0].string = "Tasks";
+ vt_key2[1].integer = starttask;
+ vt_key2[2].string = "NPCWalkAlert";
+ count = prop_get_child_count(bundle, "I<-sis", vt_key2);
+
+ /* Add two more -- NPC and walk. */
+ vt_key2[3].integer = count;
+ vt_value.integer = npc;
+ prop_put(bundle, "I->sisi", vt_value, vt_key2);
+ vt_key2[3].integer = count + 1;
+ vt_value.integer = walk;
+ prop_put(bundle, "I->sisi", vt_value, vt_key2);
+ }
+ }
+ }
}
@@ -3283,56 +3226,51 @@ parse_add_walkalerts (sc_prop_setref_t bundle)
* occurs after the TAF file has been successfully parsed.
*/
static void
-parse_add_movetimes (sc_prop_setref_t bundle)
-{
- sc_vartype_t vt_key[6];
- sc_int npcs_count, npc;
-
- /* Get the count of NPCs. */
- vt_key[0].string = "NPCs";
- npcs_count = prop_get_child_count (bundle, "I<-s", vt_key);
-
- /* Set up each NPC. */
- for (npc = 0; npc < npcs_count; npc++)
- {
- sc_int walk_count, walk;
-
- /* Get NPC walk details. */
- vt_key[1].integer = npc;
- vt_key[2].string = "Walks";
- walk_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- for (walk = 0; walk < walk_count; walk++)
- {
- sc_int waittimes;
- sc_int *movetimes, index_;
- sc_vartype_t vt_value;
-
- vt_key[3].integer = walk;
- vt_key[4].string = "Times";
- waittimes = prop_get_child_count (bundle, "I<-sisis", vt_key);
-
- movetimes = (sc_int *)sc_malloc ((waittimes + 1) * sizeof (*movetimes));
- memset (movetimes, 0, (waittimes + 1) * sizeof (*movetimes));
- for (index_ = waittimes - 1; index_ >= 0; index_--)
- {
- vt_key[4].string = "Times";
- vt_key[5].integer = index_;
- movetimes[index_] = prop_get_integer (bundle, "I<-sisisi", vt_key)
- + movetimes[index_ + 1];
- }
- movetimes[waittimes] = -2;
-
- for (index_ = 0; index_ <= waittimes; index_++)
- {
- vt_key[4].string = "MoveTimes";
- vt_key[5].integer = index_;
- vt_value.integer = movetimes[index_];
- prop_put (bundle, "I->sisisi", vt_value, vt_key);
- }
- sc_free (movetimes);
- }
- }
+parse_add_movetimes(sc_prop_setref_t bundle) {
+ sc_vartype_t vt_key[6];
+ sc_int npcs_count, npc;
+
+ /* Get the count of NPCs. */
+ vt_key[0].string = "NPCs";
+ npcs_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ /* Set up each NPC. */
+ for (npc = 0; npc < npcs_count; npc++) {
+ sc_int walk_count, walk;
+
+ /* Get NPC walk details. */
+ vt_key[1].integer = npc;
+ vt_key[2].string = "Walks";
+ walk_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ for (walk = 0; walk < walk_count; walk++) {
+ sc_int waittimes;
+ sc_int *movetimes, index_;
+ sc_vartype_t vt_value;
+
+ vt_key[3].integer = walk;
+ vt_key[4].string = "Times";
+ waittimes = prop_get_child_count(bundle, "I<-sisis", vt_key);
+
+ movetimes = (sc_int *)sc_malloc((waittimes + 1) * sizeof(*movetimes));
+ memset(movetimes, 0, (waittimes + 1) * sizeof(*movetimes));
+ for (index_ = waittimes - 1; index_ >= 0; index_--) {
+ vt_key[4].string = "Times";
+ vt_key[5].integer = index_;
+ movetimes[index_] = prop_get_integer(bundle, "I<-sisisi", vt_key)
+ + movetimes[index_ + 1];
+ }
+ movetimes[waittimes] = -2;
+
+ for (index_ = 0; index_ <= waittimes; index_++) {
+ vt_key[4].string = "MoveTimes";
+ vt_key[5].integer = index_;
+ vt_value.integer = movetimes[index_];
+ prop_put(bundle, "I->sisisi", vt_value, vt_key);
+ }
+ sc_free(movetimes);
+ }
+ }
}
@@ -3343,65 +3281,60 @@ parse_add_movetimes (sc_prop_setref_t bundle)
* that ALR replacements look at longer strings before shorter ones.
*/
static void
-parse_add_alrs_index (sc_prop_setref_t bundle)
-{
- sc_vartype_t vt_key[3];
- sc_int alr_count, index_, alr;
- sc_int *alr_lengths, longest, shortest, length;
-
- /* Count ALRs, and set invariant part of properties key. */
- vt_key[0].string = "ALRs";
- alr_count = prop_get_child_count (bundle, "I<-s", vt_key);
-
- /*
- * Set up an array of the lengths of ALR original strings, and while at it,
- * get the shortest and longest defined.
- */
- alr_lengths = (sc_int *)sc_malloc(alr_count * sizeof (*alr_lengths));
- shortest = INT_MAX;
- longest = 0;
- for (index_ = 0; index_ < alr_count; index_++)
- {
- const sc_char *original;
-
- vt_key[1].integer = index_;
- vt_key[2].string = "Original";
- original = prop_get_string (bundle, "S<-sis", vt_key);
- length = strlen (original);
-
- alr_lengths[index_] = length;
- shortest = (length < shortest) ? length : shortest;
- longest = (length > longest) ? length : longest;
- }
-
- /*
- * Now write a set of secondary properties that define the order of handling
- * for ALRs. Our friend qsort() can't help here as it doesn't define the
- * final ordering of equal members, and we need here to retain file ordering
- * for ALR originals of the same length.
- */
- vt_key[0].string = "ALRs2";
- alr = 0;
- for (length = longest; length >= shortest; length--)
- {
- /* Find and add each ALR of this length. */
- for (index_ = 0; index_ < alr_count; index_++)
- {
- if (alr_lengths[index_] == length)
- {
- sc_vartype_t vt_value;
-
- vt_key[1].integer = alr++;
- vt_key[2].string = "ALRIndex";
- vt_value.integer = index_;
- prop_put (bundle, "I->sis", vt_value, vt_key);
- }
- }
- }
- assert (alr == alr_count);
-
- /* Done with ALR lengths array. */
- sc_free (alr_lengths);
+parse_add_alrs_index(sc_prop_setref_t bundle) {
+ sc_vartype_t vt_key[3];
+ sc_int alr_count, index_, alr;
+ sc_int *alr_lengths, longest, shortest, length;
+
+ /* Count ALRs, and set invariant part of properties key. */
+ vt_key[0].string = "ALRs";
+ alr_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ /*
+ * Set up an array of the lengths of ALR original strings, and while at it,
+ * get the shortest and longest defined.
+ */
+ alr_lengths = (sc_int *)sc_malloc(alr_count * sizeof(*alr_lengths));
+ shortest = INT_MAX;
+ longest = 0;
+ for (index_ = 0; index_ < alr_count; index_++) {
+ const sc_char *original;
+
+ vt_key[1].integer = index_;
+ vt_key[2].string = "Original";
+ original = prop_get_string(bundle, "S<-sis", vt_key);
+ length = strlen(original);
+
+ alr_lengths[index_] = length;
+ shortest = (length < shortest) ? length : shortest;
+ longest = (length > longest) ? length : longest;
+ }
+
+ /*
+ * Now write a set of secondary properties that define the order of handling
+ * for ALRs. Our friend qsort() can't help here as it doesn't define the
+ * final ordering of equal members, and we need here to retain file ordering
+ * for ALR originals of the same length.
+ */
+ vt_key[0].string = "ALRs2";
+ alr = 0;
+ for (length = longest; length >= shortest; length--) {
+ /* Find and add each ALR of this length. */
+ for (index_ = 0; index_ < alr_count; index_++) {
+ if (alr_lengths[index_] == length) {
+ sc_vartype_t vt_value;
+
+ vt_key[1].integer = alr++;
+ vt_key[2].string = "ALRIndex";
+ vt_value.integer = index_;
+ prop_put(bundle, "I->sis", vt_value, vt_key);
+ }
+ }
+ }
+ assert(alr == alr_count);
+
+ /* Done with ALR lengths array. */
+ sc_free(alr_lengths);
}
@@ -3413,25 +3346,24 @@ parse_add_alrs_index (sc_prop_setref_t bundle)
* zero; only version 4.0 games can embed their resources into the TAF file.
*/
static void
-parse_add_resources_offset (sc_prop_setref_t bundle, sc_tafref_t taf)
-{
- sc_vartype_t vt_key[2], vt_value;
- sc_bool embedded;
- sc_int offset;
-
- /*
- * Get the resources offset from the TAF, or default to zero. The resources
- * offset is one byte after the end of game data.
- */
- vt_key[0].string = "Globals";
- vt_key[1].string = "Embedded";
- embedded = prop_get_boolean (bundle, "B<-ss", vt_key);
- offset = embedded ? taf_get_game_data_length (taf) + 1 : 0;
-
- /* Add this offset to the properties. */
- vt_key[0].string = "ResourceOffset";
- vt_value.integer = offset;
- prop_put (bundle, "I->s", vt_value, vt_key);
+parse_add_resources_offset(sc_prop_setref_t bundle, sc_tafref_t taf) {
+ sc_vartype_t vt_key[2], vt_value;
+ sc_bool embedded;
+ sc_int offset;
+
+ /*
+ * Get the resources offset from the TAF, or default to zero. The resources
+ * offset is one byte after the end of game data.
+ */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "Embedded";
+ embedded = prop_get_boolean(bundle, "B<-ss", vt_key);
+ offset = embedded ? taf_get_game_data_length(taf) + 1 : 0;
+
+ /* Add this offset to the properties. */
+ vt_key[0].string = "ResourceOffset";
+ vt_value.integer = offset;
+ prop_put(bundle, "I->s", vt_value, vt_key);
}
@@ -3442,34 +3374,32 @@ parse_add_resources_offset (sc_prop_setref_t bundle, sc_tafref_t taf)
* for convenience.
*/
static void
-parse_add_version (sc_prop_setref_t bundle, sc_tafref_t taf)
-{
- sc_vartype_t vt_key, vt_value;
-
- /* Add the version integer to the properties. */
- vt_key.string = "Version";
- vt_value.integer = taf_get_version (taf);
- prop_put (bundle, "I->s", vt_value, &vt_key);
-
- /* Add the version string to the properties. */
- switch (taf_get_version (taf))
- {
- case TAF_VERSION_400:
- vt_value.string = "4.00";
- break;
- case TAF_VERSION_390:
- vt_value.string = "3.90";
- break;
- case TAF_VERSION_380:
- vt_value.string = "3.80";
- break;
- default:
- sc_error ("parse_add_version_string: invalid TAF file version\n");
- vt_value.string = "[Unknown version]";
- break;
- }
- vt_key.string = "VersionString";
- prop_put (bundle, "S->s", vt_value, &vt_key);
+parse_add_version(sc_prop_setref_t bundle, sc_tafref_t taf) {
+ sc_vartype_t vt_key, vt_value;
+
+ /* Add the version integer to the properties. */
+ vt_key.string = "Version";
+ vt_value.integer = taf_get_version(taf);
+ prop_put(bundle, "I->s", vt_value, &vt_key);
+
+ /* Add the version string to the properties. */
+ switch (taf_get_version(taf)) {
+ case TAF_VERSION_400:
+ vt_value.string = "4.00";
+ break;
+ case TAF_VERSION_390:
+ vt_value.string = "3.90";
+ break;
+ case TAF_VERSION_380:
+ vt_value.string = "3.80";
+ break;
+ default:
+ sc_error("parse_add_version_string: invalid TAF file version\n");
+ vt_value.string = "[Unknown version]";
+ break;
+ }
+ vt_key.string = "VersionString";
+ prop_put(bundle, "S->s", vt_value, &vt_key);
}
@@ -3480,60 +3410,57 @@ parse_add_version (sc_prop_setref_t bundle, sc_tafref_t taf)
* it encountered an error reading the TAF file.
*/
sc_bool parse_game(sc_tafref_t taf, sc_prop_setref_t bundle) {
- assert (taf && bundle);
-
- /* Store the TAF to read from, and the bundle to store into. */
- parse_taf = taf;
- parse_bundle = bundle;
- parse_schema = parse_select_schema (parse_taf);
- parse_depth = 0;
-
- /* Try parsing, and catch errors from longjmp. */
- if (setjmp (parse_taf_error) == 0)
- {
- /* Parse a complete game. */
- taf_first_line (parse_taf);
- parse_tafline = 0;
- parse_class ("<_GAME_>");
- }
- else
- {
- /* Error with one of the TAF file lines. */
- parse_clear_v400_resources_table ();
- parse_taf = NULL;
- parse_bundle = NULL;
- parse_schema = NULL;
- parse_depth = 0;
- return FALSE;
- }
-
- /* Free the accumulated version 4.0 resources details. */
- parse_clear_v400_resources_table ();
-
- /* See if we reached the end of the TAF. */
- if (taf_more_lines (parse_taf))
- sc_error ("parse_game: unexpected trailing data\n");
-
- /* Append post-processing walkalerts and move times. */
- parse_add_walkalerts (parse_bundle);
- parse_add_movetimes (parse_bundle);
-
- /* Append sorted ALR list and resources offset. */
- parse_add_alrs_index (parse_bundle);
- parse_add_resources_offset (parse_bundle, parse_taf);
-
- /* Add a note of the TAF file version. */
- parse_add_version (parse_bundle, parse_taf);
-
- /* Trim excess allocations from properties. */
- prop_solidify (parse_bundle);
-
- /* Return successfully. */
- parse_taf = NULL;
- parse_bundle = NULL;
- parse_schema = NULL;
- parse_depth = 0;
- return TRUE;
+ assert(taf && bundle);
+
+ /* Store the TAF to read from, and the bundle to store into. */
+ parse_taf = taf;
+ parse_bundle = bundle;
+ parse_schema = parse_select_schema(parse_taf);
+ parse_depth = 0;
+
+ /* Try parsing, and catch errors from longjmp. */
+ if (setjmp(parse_taf_error) == 0) {
+ /* Parse a complete game. */
+ taf_first_line(parse_taf);
+ parse_tafline = 0;
+ parse_class("<_GAME_>");
+ } else {
+ /* Error with one of the TAF file lines. */
+ parse_clear_v400_resources_table();
+ parse_taf = NULL;
+ parse_bundle = NULL;
+ parse_schema = NULL;
+ parse_depth = 0;
+ return FALSE;
+ }
+
+ /* Free the accumulated version 4.0 resources details. */
+ parse_clear_v400_resources_table();
+
+ /* See if we reached the end of the TAF. */
+ if (taf_more_lines(parse_taf))
+ sc_error("parse_game: unexpected trailing data\n");
+
+ /* Append post-processing walkalerts and move times. */
+ parse_add_walkalerts(parse_bundle);
+ parse_add_movetimes(parse_bundle);
+
+ /* Append sorted ALR list and resources offset. */
+ parse_add_alrs_index(parse_bundle);
+ parse_add_resources_offset(parse_bundle, parse_taf);
+
+ /* Add a note of the TAF file version. */
+ parse_add_version(parse_bundle, parse_taf);
+
+ /* Trim excess allocations from properties. */
+ prop_solidify(parse_bundle);
+
+ /* Return successfully. */
+ parse_taf = NULL;
+ parse_bundle = NULL;
+ parse_schema = NULL;
+ parse_depth = 0;
+ return TRUE;
}
@@ -3543,9 +3470,8 @@ sc_bool parse_game(sc_tafref_t taf, sc_prop_setref_t bundle) {
* Set parse tracing on/off.
*/
void
-parse_debug_trace (sc_bool flag)
-{
- parse_trace = flag;
+parse_debug_trace(sc_bool flag) {
+ parse_trace = flag;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sctasks.cpp b/engines/glk/adrift/sctasks.cpp
index 4ced0c5099..8273affef6 100644
--- a/engines/glk/adrift/sctasks.cpp
+++ b/engines/glk/adrift/sctasks.cpp
@@ -57,43 +57,38 @@ static sc_bool task_trace = FALSE;
* hints.
*/
static const sc_char *
-task_get_hint_common (sc_gameref_t game, sc_int task, const sc_char *hint)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *retval;
-
- /* Look up and return the requested hint string. */
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = hint;
- retval = prop_get_string (bundle, "S<-sis", vt_key);
- return retval;
+task_get_hint_common(sc_gameref_t game, sc_int task, const sc_char *hint) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *retval;
+
+ /* Look up and return the requested hint string. */
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = hint;
+ retval = prop_get_string(bundle, "S<-sis", vt_key);
+ return retval;
}
const sc_char *
-task_get_hint_question (sc_gameref_t game, sc_int task)
-{
- return task_get_hint_common (game, task, "Question");
+task_get_hint_question(sc_gameref_t game, sc_int task) {
+ return task_get_hint_common(game, task, "Question");
}
const sc_char *
-task_get_hint_subtle (sc_gameref_t game, sc_int task)
-{
- return task_get_hint_common (game, task, "Hint1");
+task_get_hint_subtle(sc_gameref_t game, sc_int task) {
+ return task_get_hint_common(game, task, "Hint1");
}
const sc_char *
-task_get_hint_unsubtle (sc_gameref_t game, sc_int task)
-{
- return task_get_hint_common (game, task, "Hint2");
+task_get_hint_unsubtle(sc_gameref_t game, sc_int task) {
+ return task_get_hint_common(game, task, "Hint2");
}
sc_bool
-task_has_hints (sc_gameref_t game, sc_int task)
-{
- /* A non-empty question implies hints available. */
- return !sc_strempty (task_get_hint_question (game, task));
+task_has_hints(sc_gameref_t game, sc_int task) {
+ /* A non-empty question implies hints available. */
+ return !sc_strempty(task_get_hint_question(game, task));
}
@@ -104,72 +99,68 @@ task_has_hints (sc_gameref_t game, sc_int task)
* is runnable in the given direction.
*/
sc_bool
-task_can_run_task_directional (sc_gameref_t game,
- sc_int task, sc_bool forwards)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int type;
-
- /* If already run, non-repeatable tasks are not re-runnable forwards. */
- if (forwards && gs_task_done (game, task))
- {
- sc_bool repeatable;
- const sc_char *repeattext;
-
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "Repeatable";
- repeatable = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (!repeatable)
- return FALSE;
-
- vt_key[2].string = "RepeatText";
- repeattext = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (repeattext))
- return FALSE;
- }
-
- /* If checking for reverse, test the reversibility flag. */
- if (!forwards)
- {
- sc_bool reversible;
-
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "Reversible";
- reversible = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (!reversible)
- return FALSE;
- }
-
- /* Check room list for the task and return it. */
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- 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 ("task_can_run_task_directional: invalid type, %ld\n", type);
- return FALSE;
- }
+task_can_run_task_directional(sc_gameref_t game,
+ sc_int task, sc_bool forwards) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int type;
+
+ /* If already run, non-repeatable tasks are not re-runnable forwards. */
+ if (forwards && gs_task_done(game, task)) {
+ sc_bool repeatable;
+ const sc_char *repeattext;
+
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "Repeatable";
+ repeatable = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (!repeatable)
+ return FALSE;
+
+ vt_key[2].string = "RepeatText";
+ repeattext = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(repeattext))
+ return FALSE;
+ }
+
+ /* If checking for reverse, test the reversibility flag. */
+ if (!forwards) {
+ sc_bool reversible;
+
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "Reversible";
+ reversible = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (!reversible)
+ return FALSE;
+ }
+
+ /* Check room list for the task and return it. */
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ 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("task_can_run_task_directional: invalid type, %ld\n", type);
+ return FALSE;
+ }
}
@@ -179,15 +170,14 @@ task_can_run_task_directional (sc_gameref_t game,
* Returns TRUE if the task can be run in either direction.
*/
sc_bool
-task_can_run_task (sc_gameref_t game, sc_int task)
-{
- /*
- * Testing reversible tasks first may be a little more efficient if they
- * aren't common in games. There is, though, probably a little bit of
- * redundant work going on here.
- */
- return task_can_run_task_directional (game, task, FALSE)
- || task_can_run_task_directional (game, task, TRUE);
+task_can_run_task(sc_gameref_t game, sc_int task) {
+ /*
+ * Testing reversible tasks first may be a little more efficient if they
+ * aren't common in games. There is, though, probably a little bit of
+ * redundant work going on here.
+ */
+ return task_can_run_task_directional(game, task, FALSE)
+ || task_can_run_task_directional(game, task, TRUE);
}
@@ -197,114 +187,102 @@ task_can_run_task (sc_gameref_t game, sc_int task)
* Move an object to a place.
*/
static void
-task_move_object (sc_gameref_t game, sc_int object, sc_int var2, sc_int var3)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
-
- /* Select action depending on var2. */
- switch (var2)
- {
- case 0: /* To room */
- if (var3 == 0)
- {
- if (task_trace)
- sc_trace ("Task: moving object %ld to hidden\n", object);
-
- gs_object_make_hidden (game, object);
- }
- else
- {
- if (task_trace)
- {
- sc_trace ("Task: moving object %ld to room %ld\n",
- object, var3 - 1);
- }
-
- if (var3 == 0)
- gs_object_player_get (game, object);
- else
- gs_object_to_room (game, object, var3 - 1);
- }
- break;
-
- case 1: /* To roomgroup part */
- if (task_trace)
- {
- sc_trace ("Task: moving object %ld to random room in group %ld\n",
- object, var3);
- }
-
- gs_object_to_room (game, object,
- lib_random_roomgroup_member (game, var3));
- break;
-
- case 2: /* Into object */
- if (task_trace)
- sc_trace ("Task: moving object %ld into %ld\n", object, var3);
-
- gs_object_move_into (game, object, obj_container_object (game, var3));
- break;
-
- case 3: /* Onto object */
- if (task_trace)
- sc_trace ("Task: moving object %ld onto %ld\n", object, var3);
-
- gs_object_move_onto (game, object, obj_surface_object (game, var3));
- break;
-
- case 4: /* Held by */
- if (task_trace)
- sc_trace ("Task: moving object %ld to held by %ld\n", object, var3);
-
- if (var3 == 0) /* Player */
- gs_object_player_get (game, object);
- else if (var3 == 1) /* Ref character */
- gs_object_npc_get (game, object, var_get_ref_character (vars));
- else /* NPC id */
- gs_object_npc_get (game, object, var3 - 2);
- break;
-
- case 5: /* Worn by */
- if (task_trace)
- sc_trace ("Task: moving object %ld to worn by %ld\n", object, var3);
-
- if (var3 == 0) /* Player */
- gs_object_player_wear (game, object);
- else if (var3 == 1) /* Ref character */
- gs_object_npc_wear (game, object, var_get_ref_character (vars));
- else /* NPC id */
- gs_object_npc_wear (game, object, var3 - 2);
- break;
-
- case 6: /* Same room as */
- {
- sc_int room, npc;
-
- if (task_trace)
- {
- sc_trace ("Task: moving object %ld to same room as %ld\n",
- object, var3);
- }
-
- if (var3 == 0) /* Player */
- room = gs_playerroom (game);
- else if (var3 == 1) /* Ref character */
- {
- npc = var_get_ref_character (vars);
- room = gs_npc_location (game, npc) - 1;
- }
- else /* NPC id */
- {
- npc = var3 - 2;
- room = gs_npc_location (game, npc) - 1;
- }
- gs_object_to_room (game, object, room);
- break;
- }
-
- default:
- sc_fatal ("task_move_object: unknown move type, %ld\n", var2);
- }
+task_move_object(sc_gameref_t game, sc_int object, sc_int var2, sc_int var3) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+
+ /* Select action depending on var2. */
+ switch (var2) {
+ case 0: /* To room */
+ if (var3 == 0) {
+ if (task_trace)
+ sc_trace("Task: moving object %ld to hidden\n", object);
+
+ gs_object_make_hidden(game, object);
+ } else {
+ if (task_trace) {
+ sc_trace("Task: moving object %ld to room %ld\n",
+ object, var3 - 1);
+ }
+
+ if (var3 == 0)
+ gs_object_player_get(game, object);
+ else
+ gs_object_to_room(game, object, var3 - 1);
+ }
+ break;
+
+ case 1: /* To roomgroup part */
+ if (task_trace) {
+ sc_trace("Task: moving object %ld to random room in group %ld\n",
+ object, var3);
+ }
+
+ gs_object_to_room(game, object,
+ lib_random_roomgroup_member(game, var3));
+ break;
+
+ case 2: /* Into object */
+ if (task_trace)
+ sc_trace("Task: moving object %ld into %ld\n", object, var3);
+
+ gs_object_move_into(game, object, obj_container_object(game, var3));
+ break;
+
+ case 3: /* Onto object */
+ if (task_trace)
+ sc_trace("Task: moving object %ld onto %ld\n", object, var3);
+
+ gs_object_move_onto(game, object, obj_surface_object(game, var3));
+ break;
+
+ case 4: /* Held by */
+ if (task_trace)
+ sc_trace("Task: moving object %ld to held by %ld\n", object, var3);
+
+ if (var3 == 0) /* Player */
+ gs_object_player_get(game, object);
+ else if (var3 == 1) /* Ref character */
+ gs_object_npc_get(game, object, var_get_ref_character(vars));
+ else /* NPC id */
+ gs_object_npc_get(game, object, var3 - 2);
+ break;
+
+ case 5: /* Worn by */
+ if (task_trace)
+ sc_trace("Task: moving object %ld to worn by %ld\n", object, var3);
+
+ if (var3 == 0) /* Player */
+ gs_object_player_wear(game, object);
+ else if (var3 == 1) /* Ref character */
+ gs_object_npc_wear(game, object, var_get_ref_character(vars));
+ else /* NPC id */
+ gs_object_npc_wear(game, object, var3 - 2);
+ break;
+
+ case 6: { /* Same room as */
+ sc_int room, npc;
+
+ if (task_trace) {
+ sc_trace("Task: moving object %ld to same room as %ld\n",
+ object, var3);
+ }
+
+ if (var3 == 0) /* Player */
+ room = gs_playerroom(game);
+ else if (var3 == 1) { /* Ref character */
+ npc = var_get_ref_character(vars);
+ room = gs_npc_location(game, npc) - 1;
+ } else { /* NPC id */
+ npc = var3 - 2;
+ room = gs_npc_location(game, npc) - 1;
+ }
+ gs_object_to_room(game, object, room);
+ break;
+ }
+
+ default:
+ sc_fatal("task_move_object: unknown move type, %ld\n", var2);
+ }
}
@@ -314,41 +292,37 @@ task_move_object (sc_gameref_t game, sc_int object, sc_int var2, sc_int var3)
* Demultiplex an object move action and execute it.
*/
static void
-task_run_move_object_action (sc_gameref_t game,
- sc_int var1, sc_int var2, sc_int var3)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int object;
-
- /* Select depending on value in var1. */
- switch (var1)
- {
- case 0: /* All held */
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_HELD_PLAYER)
- task_move_object (game, object, var2, var3);
- }
- break;
-
- case 1: /* All worn */
- for (object = 0; object < gs_object_count (game); object++)
- {
- if (gs_object_position (game, object) == OBJ_WORN_PLAYER)
- task_move_object (game, object, var2, var3);
- }
- break;
-
- case 2: /* Ref object */
- object = var_get_ref_object (vars);
- task_move_object (game, object, var2, var3);
- break;
-
- default: /* Dynamic object */
- object = obj_dynamic_object (game, var1 - 3);
- task_move_object (game, object, var2, var3);
- break;
- }
+task_run_move_object_action(sc_gameref_t game,
+ sc_int var1, sc_int var2, sc_int var3) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int object;
+
+ /* Select depending on value in var1. */
+ switch (var1) {
+ case 0: /* All held */
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_HELD_PLAYER)
+ task_move_object(game, object, var2, var3);
+ }
+ break;
+
+ case 1: /* All worn */
+ for (object = 0; object < gs_object_count(game); object++) {
+ if (gs_object_position(game, object) == OBJ_WORN_PLAYER)
+ task_move_object(game, object, var2, var3);
+ }
+ break;
+
+ case 2: /* Ref object */
+ object = var_get_ref_object(vars);
+ task_move_object(game, object, var2, var3);
+ break;
+
+ default: /* Dynamic object */
+ object = obj_dynamic_object(game, var1 - 3);
+ task_move_object(game, object, var2, var3);
+ break;
+ }
}
@@ -358,21 +332,20 @@ task_run_move_object_action (sc_gameref_t game,
* Move an NPC to a given room.
*/
static void
-task_move_npc_to_room (sc_gameref_t game, sc_int npc, sc_int room)
-{
- if (task_trace)
- sc_trace ("Task: moving NPC %ld to room %ld\n", npc, room);
-
- /* Update the NPC's state. */
- if (room < gs_room_count (game))
- gs_set_npc_location (game, npc, room + 1);
- else
- gs_set_npc_location (game, npc,
- lib_random_roomgroup_member (game,
- room - gs_room_count (game)) + 1);
-
- gs_set_npc_parent (game, npc, -1);
- gs_set_npc_position (game, npc, 0);
+task_move_npc_to_room(sc_gameref_t game, sc_int npc, sc_int room) {
+ if (task_trace)
+ sc_trace("Task: moving NPC %ld to room %ld\n", npc, room);
+
+ /* Update the NPC's state. */
+ if (room < gs_room_count(game))
+ gs_set_npc_location(game, npc, room + 1);
+ else
+ gs_set_npc_location(game, npc,
+ lib_random_roomgroup_member(game,
+ room - gs_room_count(game)) + 1);
+
+ gs_set_npc_parent(game, npc, -1);
+ gs_set_npc_position(game, npc, 0);
}
@@ -382,164 +355,149 @@ task_move_npc_to_room (sc_gameref_t game, sc_int npc, sc_int room)
* Move player or NPC.
*/
static void
-task_run_move_npc_action (sc_gameref_t game,
- sc_int var1, sc_int var2, sc_int var3)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int npc, room, ref_npc = -1;
-
- /* Player or NPC? */
- if (var1 == 0)
- {
- /* Player -- decide where to move player to. */
- switch (var2)
- {
- case 0: /* To room */
- gs_move_player_to_room (game, var3);
- return;
-
- case 1: /* To roomgroup part */
- if (task_trace)
- {
- sc_trace ("Task: moving player to random room in group %ld\n",
- var3);
- }
-
- gs_move_player_to_room (game,
- lib_random_roomgroup_member (game, var3));
- return;
-
- case 2: /* To same room as... */
- switch (var3)
- {
- case 0: /* ...player! */
- return;
- case 1: /* ...referenced NPC */
- npc = var_get_ref_character (vars);
- break;
- default: /* ...specified NPC */
- npc = var3 - 2;
- break;
- }
-
- if (task_trace)
- sc_trace ("Task: moving player to same room as NPC %ld\n", npc);
-
- room = gs_npc_location (game, npc) - 1;
- if (room < 0)
- {
- if (task_trace)
- sc_trace ("Task: silently suppressed player move to hidden\n");
- }
- else
- gs_move_player_to_room (game, room);
- return;
-
- case 3: /* To standing on */
- gs_set_playerposition (game, 0);
- gs_set_playerparent (game, obj_standable_object (game, var3 - 1));
- return;
-
- case 4: /* To sitting on */
- gs_set_playerposition (game, 1);
- gs_set_playerparent (game, obj_standable_object (game, var3 - 1));
- return;
-
- case 5: /* To lying on */
- gs_set_playerposition (game, 2);
- gs_set_playerparent (game, obj_lieable_object (game, var3 - 1));
- return;
-
- default:
- sc_fatal ("task_run_move_npc_action:"
- " unknown player move type, %ld\n", var2);
- return;
- }
- }
- else
- {
- /* NPC -- first find which NPC to move about. */
- if (var1 == 1)
- npc = var_get_ref_character (vars);
- else
- npc = var1 - 2;
-
- /* Decide where to move the NPC to. */
- switch (var2)
- {
- case 0: /* To room */
- task_move_npc_to_room (game, npc, var3 - 1);
- return;
-
- case 1: /* To roomgroup part */
- if (task_trace)
- {
- sc_trace ("Task: moving NPC %ld to random room in group %ld\n",
- npc, var3);
- }
-
- task_move_npc_to_room (game, npc,
- lib_random_roomgroup_member (game, var3));
- return;
-
- case 2: /* To same room as... */
- switch (var3)
- {
- case 0: /* ...player */
- if (task_trace)
- {
- sc_trace ("Task: moving NPC %ld to same room as player\n",
- npc);
- }
-
- task_move_npc_to_room (game, npc, gs_playerroom (game));
- break;
- case 1: /* ...referenced NPC */
- ref_npc = var_get_ref_character (vars);
- if (task_trace)
- {
- sc_trace ("Task: moving NPC %ld to"
- " same room as referenced NPC %ld\n", npc, ref_npc);
- }
-
- room = gs_npc_location (game, ref_npc) - 1;
- task_move_npc_to_room (game, npc, room);
- break;
- default: /* ...specified NPC */
- ref_npc = var3 - 2;
- if (task_trace)
- {
- sc_trace ("Task: moving NPC %ld to"
- " same room as NPC %ld\n", npc, ref_npc);
- }
-
- room = gs_npc_location (game, ref_npc) - 1;
- task_move_npc_to_room (game, npc, room);
- break;
- }
- return;
-
- case 3: /* To standing on */
- gs_set_npc_position (game, npc, 0);
- gs_set_npc_parent (game, npc, obj_standable_object (game, var3));
- return;
-
- case 4: /* To sitting on */
- gs_set_npc_position (game, npc, 1);
- gs_set_npc_parent (game, npc, obj_standable_object (game, var3));
- return;
-
- case 5: /* To lying on */
- gs_set_npc_position (game, npc, 2);
- gs_set_npc_parent (game, npc, obj_lieable_object (game, var3));
- return;
-
- default:
- sc_fatal ("task_run_move_npc_action:"
- " unknown NPC move type, %ld\n", var2);
- return;
- }
- }
+task_run_move_npc_action(sc_gameref_t game,
+ sc_int var1, sc_int var2, sc_int var3) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int npc, room, ref_npc = -1;
+
+ /* Player or NPC? */
+ if (var1 == 0) {
+ /* Player -- decide where to move player to. */
+ switch (var2) {
+ case 0: /* To room */
+ gs_move_player_to_room(game, var3);
+ return;
+
+ case 1: /* To roomgroup part */
+ if (task_trace) {
+ sc_trace("Task: moving player to random room in group %ld\n",
+ var3);
+ }
+
+ gs_move_player_to_room(game,
+ lib_random_roomgroup_member(game, var3));
+ return;
+
+ case 2: /* To same room as... */
+ switch (var3) {
+ case 0: /* ...player! */
+ return;
+ case 1: /* ...referenced NPC */
+ npc = var_get_ref_character(vars);
+ break;
+ default: /* ...specified NPC */
+ npc = var3 - 2;
+ break;
+ }
+
+ if (task_trace)
+ sc_trace("Task: moving player to same room as NPC %ld\n", npc);
+
+ room = gs_npc_location(game, npc) - 1;
+ if (room < 0) {
+ if (task_trace)
+ sc_trace("Task: silently suppressed player move to hidden\n");
+ } else
+ gs_move_player_to_room(game, room);
+ return;
+
+ case 3: /* To standing on */
+ gs_set_playerposition(game, 0);
+ gs_set_playerparent(game, obj_standable_object(game, var3 - 1));
+ return;
+
+ case 4: /* To sitting on */
+ gs_set_playerposition(game, 1);
+ gs_set_playerparent(game, obj_standable_object(game, var3 - 1));
+ return;
+
+ case 5: /* To lying on */
+ gs_set_playerposition(game, 2);
+ gs_set_playerparent(game, obj_lieable_object(game, var3 - 1));
+ return;
+
+ default:
+ sc_fatal("task_run_move_npc_action:"
+ " unknown player move type, %ld\n", var2);
+ return;
+ }
+ } else {
+ /* NPC -- first find which NPC to move about. */
+ if (var1 == 1)
+ npc = var_get_ref_character(vars);
+ else
+ npc = var1 - 2;
+
+ /* Decide where to move the NPC to. */
+ switch (var2) {
+ case 0: /* To room */
+ task_move_npc_to_room(game, npc, var3 - 1);
+ return;
+
+ case 1: /* To roomgroup part */
+ if (task_trace) {
+ sc_trace("Task: moving NPC %ld to random room in group %ld\n",
+ npc, var3);
+ }
+
+ task_move_npc_to_room(game, npc,
+ lib_random_roomgroup_member(game, var3));
+ return;
+
+ case 2: /* To same room as... */
+ switch (var3) {
+ case 0: /* ...player */
+ if (task_trace) {
+ sc_trace("Task: moving NPC %ld to same room as player\n",
+ npc);
+ }
+
+ task_move_npc_to_room(game, npc, gs_playerroom(game));
+ break;
+ case 1: /* ...referenced NPC */
+ ref_npc = var_get_ref_character(vars);
+ if (task_trace) {
+ sc_trace("Task: moving NPC %ld to"
+ " same room as referenced NPC %ld\n", npc, ref_npc);
+ }
+
+ room = gs_npc_location(game, ref_npc) - 1;
+ task_move_npc_to_room(game, npc, room);
+ break;
+ default: /* ...specified NPC */
+ ref_npc = var3 - 2;
+ if (task_trace) {
+ sc_trace("Task: moving NPC %ld to"
+ " same room as NPC %ld\n", npc, ref_npc);
+ }
+
+ room = gs_npc_location(game, ref_npc) - 1;
+ task_move_npc_to_room(game, npc, room);
+ break;
+ }
+ return;
+
+ case 3: /* To standing on */
+ gs_set_npc_position(game, npc, 0);
+ gs_set_npc_parent(game, npc, obj_standable_object(game, var3));
+ return;
+
+ case 4: /* To sitting on */
+ gs_set_npc_position(game, npc, 1);
+ gs_set_npc_parent(game, npc, obj_standable_object(game, var3));
+ return;
+
+ case 5: /* To lying on */
+ gs_set_npc_position(game, npc, 2);
+ gs_set_npc_parent(game, npc, obj_lieable_object(game, var3));
+ return;
+
+ default:
+ sc_fatal("task_run_move_npc_action:"
+ " unknown NPC move type, %ld\n", var2);
+ return;
+ }
+ }
}
@@ -549,59 +507,51 @@ task_run_move_npc_action (sc_gameref_t game,
* Change the status of an object.
*/
static void
-task_run_change_object_status (sc_gameref_t game, sc_int var1, sc_int var2)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int object, openable, lockable;
-
- if (task_trace)
- {
- sc_trace ("Task: setting status of stateful object %ld to %ld\n",
- var1, var2);
- }
-
- /* Identify the target object. */
- object = obj_stateful_object (game, var1);
-
- /* See if openable. */
- 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)
- {
- /* See if lockable. */
- vt_key[2].string = "Key";
- lockable = prop_get_integer (bundle, "I<-sis", vt_key);
- if (lockable >= 0)
- {
- /* Lockable. */
- if (var2 <= 2)
- gs_set_object_openness (game, object, var2 + 5);
- else
- gs_set_object_state (game, object, var2 - 2);
- }
- else
- {
- /* Not lockable, though openable. */
- if (var2 <= 1)
- gs_set_object_openness (game, object, var2 + 5);
- else
- gs_set_object_state (game, object, var2 - 1);
- }
- }
- else
- /* Not openable. */
- gs_set_object_state (game, object, var2 + 1);
-
- if (task_trace)
- {
- sc_trace ("Task: openness of object %ld is now %ld\n",
- object, gs_object_openness (game, object));
- sc_trace ("Task: state of object %ld is now %ld\n",
- object, gs_object_state (game, object));
- }
+task_run_change_object_status(sc_gameref_t game, sc_int var1, sc_int var2) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int object, openable, lockable;
+
+ if (task_trace) {
+ sc_trace("Task: setting status of stateful object %ld to %ld\n",
+ var1, var2);
+ }
+
+ /* Identify the target object. */
+ object = obj_stateful_object(game, var1);
+
+ /* See if openable. */
+ 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) {
+ /* See if lockable. */
+ vt_key[2].string = "Key";
+ lockable = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (lockable >= 0) {
+ /* Lockable. */
+ if (var2 <= 2)
+ gs_set_object_openness(game, object, var2 + 5);
+ else
+ gs_set_object_state(game, object, var2 - 2);
+ } else {
+ /* Not lockable, though openable. */
+ if (var2 <= 1)
+ gs_set_object_openness(game, object, var2 + 5);
+ else
+ gs_set_object_state(game, object, var2 - 1);
+ }
+ } else
+ /* Not openable. */
+ gs_set_object_state(game, object, var2 + 1);
+
+ if (task_trace) {
+ sc_trace("Task: openness of object %ld is now %ld\n",
+ object, gs_object_openness(game, object));
+ sc_trace("Task: state of object %ld is now %ld\n",
+ object, gs_object_state(game, object));
+ }
}
@@ -611,164 +561,151 @@ task_run_change_object_status (sc_gameref_t game, sc_int var1, sc_int var2)
* Change a variable's value in inscrutable ways.
*/
static void
-task_run_change_variable_action (sc_gameref_t game,
- sc_int var1, sc_int var2, sc_int var3,
- const sc_char *expr, sc_int var5)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- 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];
- const sc_char *name, *string;
- sc_char *mutable_string;
- sc_int type, value;
-
- /*
- * At this point, we need to checkpoint the filter. We're about to change
- * a variable value, so interpolating here before doing that ensures that
- * any currently buffered text gets the values that were set when the text
- * was buffered.
- */
- pf_checkpoint (filter, vars, bundle);
-
- /* Get the name and type of the variable being addressed. */
- vt_key[0].string = "Variables";
- vt_key[1].integer = var1;
- 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: /* Integer */
-
- /* Select again based on action type. */
- switch (var2)
- {
- case 0: /* Var = */
- if (task_trace)
- sc_trace ("Task: variable %ld (%s) = %ld\n", var1, name, var3);
-
- var_put_integer (vars, name, var3);
- return;
-
- case 1: /* Var += */
- if (task_trace)
- sc_trace ("Task: variable %ld (%s) += %ld\n", var1, name, var3);
-
- value = var_get_integer (vars, name) + var3;
- var_put_integer (vars, name, value);
- return;
-
- case 2: /* Var = rnd(range) */
- if (task_trace)
- {
- sc_trace ("Task: variable %ld (%s) = random(%ld,%ld)\n",
- var1, name, var3, var5);
- }
-
- value = sc_randomint (var3, var5);
- var_put_integer (vars, name, value);
- return;
-
- case 3: /* Var += rnd(range) */
- if (task_trace)
- {
- sc_trace ("Task: variable %ld (%s) += random(%ld,%ld)\n",
- var1, name, var3, var5);
- }
-
- value = var_get_integer (vars, name) + sc_randomint (var3, var5);
- var_put_integer (vars, name, value);
- return;
-
- case 4: /* Var = ref */
- value = var_get_ref_number (vars);
- if (task_trace)
- {
- sc_trace ("Task: variable %ld (%s) = ref, %ld\n",
- var1, name, value);
- }
-
- var_put_integer (vars, name, value);
- return;
-
- case 5: /* Var = expr */
- if (!expr_eval_numeric_expression (expr, vars, &value))
- {
- sc_error ("task_run_change_variable_action:"
- " invalid expression, %s\n", expr);
- value = 0;
- }
- if (task_trace)
- {
- sc_trace ("Task: variable %ld (%s) = %s, %ld\n",
- var1, name, expr, value);
- }
-
- var_put_integer (vars, name, value);
- return;
-
- default:
- sc_fatal ("task_run_change_variable_action:"
- " unknown integer change type, %ld\n", var2);
- }
-
- case TAFVAR_STRING: /* String */
-
- /* Select again based on action type. */
- switch (var2)
- {
- case 0: /* Var = text literal */
- if (task_trace)
- {
- sc_trace ("Task: variable %ld (%s) = \"%s\"\n",
- var1, name, expr);
- }
-
- var_put_string (vars, name, expr);
- return;
-
- case 1: /* Var = ref */
- string = var_get_ref_text (vars);
- if (task_trace)
- {
- sc_trace ("Task: variable %ld (%s) = ref, \"%s\"\n",
- var1, name, string);
- }
-
- var_put_string (vars, name, string);
- return;
-
- case 2: /* Var = expr */
- if (!expr_eval_string_expression (expr, vars, &mutable_string))
- {
- sc_error ("task_run_change_variable_action:"
- " invalid string expression, %s\n", expr);
- mutable_string = (sc_char *)sc_malloc (strlen ("[expr error]") + 1);
- strcpy (mutable_string, "[expr error]");
- }
- if (task_trace)
- {
- sc_trace ("Task: variable %ld (%s) = %s, %s\n",
- var1, name, expr, mutable_string);
- }
-
- var_put_string (vars, name, mutable_string);
- sc_free (mutable_string);
- return;
-
- default:
- sc_fatal ("task_run_change_variable_action:"
- " unknown string change type, %ld\n", var2);
- }
-
- default:
- sc_fatal ("task_run_change_variable_action:"
- " invalid variable type, %ld\n", type);
- }
+task_run_change_variable_action(sc_gameref_t game,
+ sc_int var1, sc_int var2, sc_int var3,
+ const sc_char *expr, sc_int var5) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ 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];
+ const sc_char *name, *string;
+ sc_char *mutable_string;
+ sc_int type, value;
+
+ /*
+ * At this point, we need to checkpoint the filter. We're about to change
+ * a variable value, so interpolating here before doing that ensures that
+ * any currently buffered text gets the values that were set when the text
+ * was buffered.
+ */
+ pf_checkpoint(filter, vars, bundle);
+
+ /* Get the name and type of the variable being addressed. */
+ vt_key[0].string = "Variables";
+ vt_key[1].integer = var1;
+ 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: /* Integer */
+
+ /* Select again based on action type. */
+ switch (var2) {
+ case 0: /* Var = */
+ if (task_trace)
+ sc_trace("Task: variable %ld (%s) = %ld\n", var1, name, var3);
+
+ var_put_integer(vars, name, var3);
+ return;
+
+ case 1: /* Var += */
+ if (task_trace)
+ sc_trace("Task: variable %ld (%s) += %ld\n", var1, name, var3);
+
+ value = var_get_integer(vars, name) + var3;
+ var_put_integer(vars, name, value);
+ return;
+
+ case 2: /* Var = rnd(range) */
+ if (task_trace) {
+ sc_trace("Task: variable %ld (%s) = random(%ld,%ld)\n",
+ var1, name, var3, var5);
+ }
+
+ value = sc_randomint(var3, var5);
+ var_put_integer(vars, name, value);
+ return;
+
+ case 3: /* Var += rnd(range) */
+ if (task_trace) {
+ sc_trace("Task: variable %ld (%s) += random(%ld,%ld)\n",
+ var1, name, var3, var5);
+ }
+
+ value = var_get_integer(vars, name) + sc_randomint(var3, var5);
+ var_put_integer(vars, name, value);
+ return;
+
+ case 4: /* Var = ref */
+ value = var_get_ref_number(vars);
+ if (task_trace) {
+ sc_trace("Task: variable %ld (%s) = ref, %ld\n",
+ var1, name, value);
+ }
+
+ var_put_integer(vars, name, value);
+ return;
+
+ case 5: /* Var = expr */
+ if (!expr_eval_numeric_expression(expr, vars, &value)) {
+ sc_error("task_run_change_variable_action:"
+ " invalid expression, %s\n", expr);
+ value = 0;
+ }
+ if (task_trace) {
+ sc_trace("Task: variable %ld (%s) = %s, %ld\n",
+ var1, name, expr, value);
+ }
+
+ var_put_integer(vars, name, value);
+ return;
+
+ default:
+ sc_fatal("task_run_change_variable_action:"
+ " unknown integer change type, %ld\n", var2);
+ }
+
+ case TAFVAR_STRING: /* String */
+
+ /* Select again based on action type. */
+ switch (var2) {
+ case 0: /* Var = text literal */
+ if (task_trace) {
+ sc_trace("Task: variable %ld (%s) = \"%s\"\n",
+ var1, name, expr);
+ }
+
+ var_put_string(vars, name, expr);
+ return;
+
+ case 1: /* Var = ref */
+ string = var_get_ref_text(vars);
+ if (task_trace) {
+ sc_trace("Task: variable %ld (%s) = ref, \"%s\"\n",
+ var1, name, string);
+ }
+
+ var_put_string(vars, name, string);
+ return;
+
+ case 2: /* Var = expr */
+ if (!expr_eval_string_expression(expr, vars, &mutable_string)) {
+ sc_error("task_run_change_variable_action:"
+ " invalid string expression, %s\n", expr);
+ mutable_string = (sc_char *)sc_malloc(strlen("[expr error]") + 1);
+ strcpy(mutable_string, "[expr error]");
+ }
+ if (task_trace) {
+ sc_trace("Task: variable %ld (%s) = %s, %s\n",
+ var1, name, expr, mutable_string);
+ }
+
+ var_put_string(vars, name, mutable_string);
+ sc_free(mutable_string);
+ return;
+
+ default:
+ sc_fatal("task_run_change_variable_action:"
+ " unknown string change type, %ld\n", var2);
+ }
+
+ default:
+ sc_fatal("task_run_change_variable_action:"
+ " invalid variable type, %ld\n", type);
+ }
}
@@ -778,64 +715,56 @@ task_run_change_variable_action (sc_gameref_t game,
* Change game score.
*/
static void
-task_run_change_score_action (sc_gameref_t game, sc_int task, sc_int var1)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
-
- /* Increasing or decreasing the score? */
- if (var1 > 0)
- {
- sc_bool increase_score;
-
- /* See if this task is already scored. */
- increase_score = !gs_task_scored (game, task);
- if (!increase_score)
- {
- sc_vartype_t vt_key[3];
- sc_int version;
-
- if (task_trace)
- sc_trace ("Task: already scored task %ld\n", var1);
-
- /* Version 3.8 games permit tasks to rescore. */
- vt_key[0].string = "Version";
- version = prop_get_integer (bundle, "I<-s", vt_key);
- if (version == TAF_VERSION_380)
- {
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "SingleScore";
- increase_score = !prop_get_boolean (bundle, "B<-sis", vt_key);
-
- if (increase_score)
- {
- if (task_trace)
- sc_trace ("Task: rescoring version 3.8 task anyway\n");
- }
- }
- }
-
- /*
- * Increase the score if not yet scored or a version 3.8 multiple
- * scoring task, and note as a scored task.
- */
- if (increase_score)
- {
- if (task_trace)
- sc_trace ("Task: increased score by %ld\n", var1);
-
- game->score += var1;
- gs_set_task_scored (game, task, TRUE);
- }
- }
- else if (var1 < 0)
- {
- /* Decrease the score. */
- if (task_trace)
- sc_trace ("Task: decreased score by %ld\n", -(var1));
-
- game->score += var1;
- }
+task_run_change_score_action(sc_gameref_t game, sc_int task, sc_int var1) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+
+ /* Increasing or decreasing the score? */
+ if (var1 > 0) {
+ sc_bool increase_score;
+
+ /* See if this task is already scored. */
+ increase_score = !gs_task_scored(game, task);
+ if (!increase_score) {
+ sc_vartype_t vt_key[3];
+ sc_int version;
+
+ if (task_trace)
+ sc_trace("Task: already scored task %ld\n", var1);
+
+ /* Version 3.8 games permit tasks to rescore. */
+ vt_key[0].string = "Version";
+ version = prop_get_integer(bundle, "I<-s", vt_key);
+ if (version == TAF_VERSION_380) {
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "SingleScore";
+ increase_score = !prop_get_boolean(bundle, "B<-sis", vt_key);
+
+ if (increase_score) {
+ if (task_trace)
+ sc_trace("Task: rescoring version 3.8 task anyway\n");
+ }
+ }
+ }
+
+ /*
+ * Increase the score if not yet scored or a version 3.8 multiple
+ * scoring task, and note as a scored task.
+ */
+ if (increase_score) {
+ if (task_trace)
+ sc_trace("Task: increased score by %ld\n", var1);
+
+ game->score += var1;
+ gs_set_task_scored(game, task, TRUE);
+ }
+ } else if (var1 < 0) {
+ /* Decrease the score. */
+ if (task_trace)
+ sc_trace("Task: decreased score by %ld\n", -(var1));
+
+ game->score += var1;
+ }
}
@@ -845,36 +774,29 @@ task_run_change_score_action (sc_gameref_t game, sc_int task, sc_int var1)
* Redirect to another task.
*/
static sc_bool
-task_run_set_task_action (sc_gameref_t game, sc_int var1, sc_int var2)
-{
- sc_bool status = FALSE;
-
- /* Select based on var1. */
- if (var1 == 0)
- {
- /* Redirect forwards. */
- if (task_can_run_task_directional (game, var2, TRUE))
- {
- if (task_trace)
- sc_trace ("Task: redirecting to task %ld\n", var2);
-
- status = task_run_task (game, var2, TRUE);
- }
- else
- {
- if (task_trace)
- sc_trace ("Task: can't redirect to task %ld\n", var2);
- }
- }
- else
- {
- /* Undo task. */
- gs_set_task_done (game, var2, FALSE);
- if (task_trace)
- sc_trace ("Task: reversing task %ld\n", var2);
- }
-
- return status;
+task_run_set_task_action(sc_gameref_t game, sc_int var1, sc_int var2) {
+ sc_bool status = FALSE;
+
+ /* Select based on var1. */
+ if (var1 == 0) {
+ /* Redirect forwards. */
+ if (task_can_run_task_directional(game, var2, TRUE)) {
+ if (task_trace)
+ sc_trace("Task: redirecting to task %ld\n", var2);
+
+ status = task_run_task(game, var2, TRUE);
+ } else {
+ if (task_trace)
+ sc_trace("Task: can't redirect to task %ld\n", var2);
+ }
+ } else {
+ /* Undo task. */
+ gs_set_task_done(game, var2, FALSE);
+ if (task_trace)
+ sc_trace("Task: reversing task %ld\n", var2);
+ }
+
+ return status;
}
@@ -884,65 +806,60 @@ task_run_set_task_action (sc_gameref_t game, sc_int var1, sc_int var2)
* End of game task action.
*/
static sc_bool
-task_run_end_game_action (sc_gameref_t game, sc_int var1)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_bool status = FALSE;
-
- /* Print a message based on var1. */
- switch (var1)
- {
- case 0:
- {
- sc_vartype_t vt_key[2];
- const sc_char *wintext;
-
- /* Get game WinText. */
- vt_key[0].string = "Header";
- vt_key[1].string = "WinText";
- wintext = prop_get_string (bundle, "S<-ss", vt_key);
-
- /* Print WinText, if any defined, otherwise a default. */
- if (!sc_strempty (wintext))
- {
- pf_buffer_string (filter, wintext);
- pf_buffer_character (filter, '\n');
- }
- else
- pf_buffer_string (filter, "Congratulations!\n");
-
- /* Handle any associated WinRes resource. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "WinRes";
- res_handle_resource (game, "ss", vt_key);
-
- status = TRUE;
- break;
- }
-
- case 1:
- pf_buffer_string (filter, "Better luck next time.\n");
- status = TRUE;
- break;
-
- case 2:
- pf_buffer_string (filter, "I'm afraid you are dead!\n");
- status = TRUE;
- break;
-
- case 3:
- break;
-
- default:
- sc_fatal ("task_run_end_game_action: invalid type, %ld\n", var1);
- }
-
- /* Stop the game, and note that it's not resumeable. */
- game->is_running = FALSE;
- game->has_completed = TRUE;
-
- return status;
+task_run_end_game_action(sc_gameref_t game, sc_int var1) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_bool status = FALSE;
+
+ /* Print a message based on var1. */
+ switch (var1) {
+ case 0: {
+ sc_vartype_t vt_key[2];
+ const sc_char *wintext;
+
+ /* Get game WinText. */
+ vt_key[0].string = "Header";
+ vt_key[1].string = "WinText";
+ wintext = prop_get_string(bundle, "S<-ss", vt_key);
+
+ /* Print WinText, if any defined, otherwise a default. */
+ if (!sc_strempty(wintext)) {
+ pf_buffer_string(filter, wintext);
+ pf_buffer_character(filter, '\n');
+ } else
+ pf_buffer_string(filter, "Congratulations!\n");
+
+ /* Handle any associated WinRes resource. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "WinRes";
+ res_handle_resource(game, "ss", vt_key);
+
+ status = TRUE;
+ break;
+ }
+
+ case 1:
+ pf_buffer_string(filter, "Better luck next time.\n");
+ status = TRUE;
+ break;
+
+ case 2:
+ pf_buffer_string(filter, "I'm afraid you are dead!\n");
+ status = TRUE;
+ break;
+
+ case 3:
+ break;
+
+ default:
+ sc_fatal("task_run_end_game_action: invalid type, %ld\n", var1);
+ }
+
+ /* Stop the game, and note that it's not resumeable. */
+ game->is_running = FALSE;
+ game->has_completed = TRUE;
+
+ return status;
}
@@ -952,95 +869,93 @@ task_run_end_game_action (sc_gameref_t game, sc_int var1)
* Demultiplexer for task actions.
*/
static sc_bool
-task_run_task_action (sc_gameref_t game, sc_int task, sc_int action)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[5];
- sc_int type, var1, var2, var3, var5;
- const sc_char *expr;
- sc_bool status = FALSE;
-
- /* Get the task action type. */
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "Actions";
- vt_key[3].integer = action;
- vt_key[4].string = "Type";
- type = prop_get_integer (bundle, "I<-sisis", vt_key);
-
- /* Demultiplex depending on type. */
- switch (type)
- {
- case 0: /* Move object. */
- 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);
- task_run_move_object_action (game, var1, var2, var3);
- break;
-
- case 1: /* Move player/NPC. */
- 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);
- task_run_move_npc_action (game, var1, var2, var3);
- break;
-
- case 2: /* Change object status. */
- 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);
- task_run_change_object_status (game, var1, var2);
- break;
-
- case 3: /* Change 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 = "Expr";
- expr = prop_get_string (bundle, "S<-sisis", vt_key);
- vt_key[4].string = "Var5";
- var5 = prop_get_integer (bundle, "I<-sisis", vt_key);
- task_run_change_variable_action (game, var1, var2, var3, expr, var5);
- break;
-
- case 4: /* Change score. */
- vt_key[4].string = "Var1";
- var1 = prop_get_integer (bundle, "I<-sisis", vt_key);
- task_run_change_score_action (game, task, var1);
- break;
-
- case 5: /* Execute/unset task. */
- 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);
- status = task_run_set_task_action (game, var1, var2);
- break;
-
- case 6: /* End game. */
- vt_key[4].string = "Var1";
- var1 = prop_get_integer (bundle, "I<-sisis", vt_key);
- status = task_run_end_game_action (game, var1);
- break;
-
- case 7: /* Battle options, ignored for now... */
- break;
-
- default:
- sc_fatal ("task_run_task_action: unknown action type %ld\n", type);
- }
-
- return status;
+task_run_task_action(sc_gameref_t game, sc_int task, sc_int action) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[5];
+ sc_int type, var1, var2, var3, var5;
+ const sc_char *expr;
+ sc_bool status = FALSE;
+
+ /* Get the task action type. */
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "Actions";
+ vt_key[3].integer = action;
+ vt_key[4].string = "Type";
+ type = prop_get_integer(bundle, "I<-sisis", vt_key);
+
+ /* Demultiplex depending on type. */
+ switch (type) {
+ case 0: /* Move object. */
+ 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);
+ task_run_move_object_action(game, var1, var2, var3);
+ break;
+
+ case 1: /* Move player/NPC. */
+ 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);
+ task_run_move_npc_action(game, var1, var2, var3);
+ break;
+
+ case 2: /* Change object status. */
+ 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);
+ task_run_change_object_status(game, var1, var2);
+ break;
+
+ case 3: /* Change 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 = "Expr";
+ expr = prop_get_string(bundle, "S<-sisis", vt_key);
+ vt_key[4].string = "Var5";
+ var5 = prop_get_integer(bundle, "I<-sisis", vt_key);
+ task_run_change_variable_action(game, var1, var2, var3, expr, var5);
+ break;
+
+ case 4: /* Change score. */
+ vt_key[4].string = "Var1";
+ var1 = prop_get_integer(bundle, "I<-sisis", vt_key);
+ task_run_change_score_action(game, task, var1);
+ break;
+
+ case 5: /* Execute/unset task. */
+ 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);
+ status = task_run_set_task_action(game, var1, var2);
+ break;
+
+ case 6: /* End game. */
+ vt_key[4].string = "Var1";
+ var1 = prop_get_integer(bundle, "I<-sisis", vt_key);
+ status = task_run_end_game_action(game, var1);
+ break;
+
+ case 7: /* Battle options, ignored for now... */
+ break;
+
+ default:
+ sc_fatal("task_run_task_action: unknown action type %ld\n", type);
+ }
+
+ return status;
}
@@ -1052,68 +967,62 @@ task_run_task_action (sc_gameref_t game, sc_int task, sc_int action)
* returned TRUE.
*/
static sc_bool
-task_run_task_actions (sc_gameref_t game, sc_int task)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- sc_int action_count, action;
- sc_bool status, muted;
-
- /* Get the count of task actions. */
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "Actions";
- action_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- if (action_count > 0)
- {
- if (task_trace)
- {
- sc_trace ("Task: task %ld running %ld action%s\n",
- task, action_count, action_count == 1 ? "" : "s");
- }
- }
-
- /*
- * Run all task actions, capturing any TRUE status returned. If any task
- * ends the game, run the remaining tasks silently.
- *
- * This seems a little counterintuitive; a more conventional thing would be
- * to just exit the actions loop early. However, Adrift appears to plough
- * on, and there may be an action that changes the score in here somewhere,
- * so we'll do the same.
- */
- status = FALSE;
- muted = FALSE;
- for (action = 0; action < action_count; action++)
- {
- sc_bool was_running;
-
- was_running = game->is_running;
- status |= task_run_task_action (game, task, action);
-
- /* Did this action end the game? */
- if (was_running && !game->is_running)
- {
- if (task_trace)
- {
- sc_trace ("Task: task %ld action %ld ended game\n",
- task, action);
- }
-
- /* Mute the filter, and note that we did it, but continue. */
- pf_mute (filter);
- muted = TRUE;
- }
- }
-
- /* If this stack frame muted the filter, un-mute it now. */
- if (muted)
- pf_clear_mute (filter);
-
- /* Return TRUE if any task action returned TRUE. */
- return status;
+task_run_task_actions(sc_gameref_t game, sc_int task) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ sc_int action_count, action;
+ sc_bool status, muted;
+
+ /* Get the count of task actions. */
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "Actions";
+ action_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ if (action_count > 0) {
+ if (task_trace) {
+ sc_trace("Task: task %ld running %ld action%s\n",
+ task, action_count, action_count == 1 ? "" : "s");
+ }
+ }
+
+ /*
+ * Run all task actions, capturing any TRUE status returned. If any task
+ * ends the game, run the remaining tasks silently.
+ *
+ * This seems a little counterintuitive; a more conventional thing would be
+ * to just exit the actions loop early. However, Adrift appears to plough
+ * on, and there may be an action that changes the score in here somewhere,
+ * so we'll do the same.
+ */
+ status = FALSE;
+ muted = FALSE;
+ for (action = 0; action < action_count; action++) {
+ sc_bool was_running;
+
+ was_running = game->is_running;
+ status |= task_run_task_action(game, task, action);
+
+ /* Did this action end the game? */
+ if (was_running && !game->is_running) {
+ if (task_trace) {
+ sc_trace("Task: task %ld action %ld ended game\n",
+ task, action);
+ }
+
+ /* Mute the filter, and note that we did it, but continue. */
+ pf_mute(filter);
+ muted = TRUE;
+ }
+ }
+
+ /* If this stack frame muted the filter, un-mute it now. */
+ if (muted)
+ pf_clear_mute(filter);
+
+ /* Return TRUE if any task action returned TRUE. */
+ return status;
}
@@ -1123,29 +1032,27 @@ task_run_task_actions (sc_gameref_t game, sc_int task)
* Start NPC walks based on alerts.
*/
static void
-task_start_npc_walks (sc_gameref_t game, sc_int task)
-{
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[4];
- sc_int alert_count, alert;
-
- /* Get a count of NPC walk alerts. */
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "NPCWalkAlert";
- alert_count = prop_get_child_count (bundle, "I<-sis", vt_key);
-
- /* Check alerts, and start any walks that need starting. */
- for (alert = 0; alert < alert_count; alert += 2)
- {
- sc_int npc, walk;
-
- vt_key[3].integer = alert;
- npc = prop_get_integer (bundle, "I<-sisi", vt_key);
- vt_key[3].integer = alert + 1;
- walk = prop_get_integer (bundle, "I<-sisi", vt_key);
- npc_start_npc_walk (game, npc, walk);
- }
+task_start_npc_walks(sc_gameref_t game, sc_int task) {
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[4];
+ sc_int alert_count, alert;
+
+ /* Get a count of NPC walk alerts. */
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "NPCWalkAlert";
+ alert_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+
+ /* Check alerts, and start any walks that need starting. */
+ for (alert = 0; alert < alert_count; alert += 2) {
+ sc_int npc, walk;
+
+ vt_key[3].integer = alert;
+ npc = prop_get_integer(bundle, "I<-sisi", vt_key);
+ vt_key[3].integer = alert + 1;
+ walk = prop_get_integer(bundle, "I<-sisi", vt_key);
+ npc_start_npc_walk(game, npc, walk);
+ }
}
@@ -1158,166 +1065,151 @@ task_start_npc_walks (sc_gameref_t game, sc_int task)
* done.
*/
static sc_bool
-task_run_task_unrestricted (sc_gameref_t game, sc_int task, sc_bool forwards)
-{
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *completetext, *additionalmessage;
- sc_int action_count, showroomdesc;
- sc_bool status;
-
- /* Start considering task output tracking. */
- status = FALSE;
-
- /*
- * If reversing, print any reverse message for the task, and undo the task,
- * then return.
- */
- if (!forwards)
- {
- const sc_char *reversemessage;
-
- /* If not yet done, we can hardly reverse it. */
- if (gs_task_done (game, task))
- {
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "ReverseMessage";
- reversemessage = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (reversemessage))
- {
- pf_buffer_string (filter, reversemessage);
- pf_buffer_character (filter, '\n');
- status |= TRUE;
- }
-
- /* Undo the task. */
- gs_set_task_done (game, task, FALSE);
- }
-
- /* Return status of undo. */
- return status;
- }
-
- /* See if we are trying to repeat a task that's not repeatable. */
- if (gs_task_done (game, task))
- {
- sc_bool repeatable;
-
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "Repeatable";
- repeatable = prop_get_boolean (bundle, "B<-sis", vt_key);
- if (!repeatable)
- {
- const sc_char *repeattext;
-
- vt_key[2].string = "RepeatText";
- repeattext = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (repeattext))
- {
- if (task_trace)
- {
- sc_trace ("Task:"
- " trying to repeat completed action, aborting\n");
- }
-
- pf_buffer_string (filter, repeattext);
- pf_buffer_character (filter, '\n');
- status |= TRUE;
- return status;
- }
-
- /*
- * Task done, yet not repeatable, so don't consider this case
- * handled.
- */
- return status;
- }
- }
-
- /* Mark the task as done. */
- gs_set_task_done (game, task, TRUE);
-
- /* Print any task completion text. */
- vt_key[0].string = "Tasks";
- vt_key[1].integer = task;
- vt_key[2].string = "CompleteText";
- completetext = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (completetext))
- {
- pf_buffer_string (filter, completetext);
- pf_buffer_character (filter, '\n');
- status |= TRUE;
- }
-
- /* Handle any task completion resource. */
- vt_key[2].string = "Res";
- res_handle_resource (game, "sis", vt_key);
-
- /*
- * Things get slightly tricky here. We need to filter the completion text
- * for the task using any final variable values generated or modified by
- * task actions, but other task text, run by actions, according to the
- * variable value in effect when it runs.
- *
- * To do this, we take a local copy of the filter's current buffer at this
- * point, remove it from the filter, run task actions with checkpointing,
- * then prepend it back into the filter after all the actions are done.
- *
- * As an optimization, we can avoid doing this if there are no task actions.
- */
- vt_key[2].string = "Actions";
- action_count = prop_get_child_count (bundle, "I<-sis", vt_key);
- if (action_count > 0)
- {
- sc_char *buffer;
-
- /*
- * Take ownership of the current filter buffer text, then start NPC
- * walks based on alerts, and run any and all task actions. Note that
- * the buffer transferred out of the filter may be NULL if there is no
- * text currently in the filter.
- */
- buffer = pf_transfer_buffer (filter);
- task_start_npc_walks (game, task);
- status |= task_run_task_actions (game, task);
-
- /* Prepend the saved buffer data back onto the front of the filter. */
- if (buffer)
- {
- pf_prepend_string (filter, buffer);
- sc_free (buffer);
- }
- }
- else
- {
- /* Start NPC walks only; there are no task actions. */
- task_start_npc_walks (game, task);
- }
-
- /* Append any room description and additional message for the task. */
- vt_key[2].string = "ShowRoomDesc";
- showroomdesc = prop_get_integer (bundle, "I<-sis", vt_key);
- if (showroomdesc != 0)
- {
- lib_print_room_name (game, showroomdesc - 1);
- lib_print_room_description (game, showroomdesc - 1);
- status |= TRUE;
- }
-
- vt_key[2].string = "AdditionalMessage";
- additionalmessage = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (additionalmessage))
- {
- pf_buffer_string (filter, additionalmessage);
- pf_buffer_character (filter, '\n');
- status |= TRUE;
- }
-
- /* Return status -- TRUE if matched and we output something. */
- return status;
+task_run_task_unrestricted(sc_gameref_t game, sc_int task, sc_bool forwards) {
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *completetext, *additionalmessage;
+ sc_int action_count, showroomdesc;
+ sc_bool status;
+
+ /* Start considering task output tracking. */
+ status = FALSE;
+
+ /*
+ * If reversing, print any reverse message for the task, and undo the task,
+ * then return.
+ */
+ if (!forwards) {
+ const sc_char *reversemessage;
+
+ /* If not yet done, we can hardly reverse it. */
+ if (gs_task_done(game, task)) {
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "ReverseMessage";
+ reversemessage = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(reversemessage)) {
+ pf_buffer_string(filter, reversemessage);
+ pf_buffer_character(filter, '\n');
+ status |= TRUE;
+ }
+
+ /* Undo the task. */
+ gs_set_task_done(game, task, FALSE);
+ }
+
+ /* Return status of undo. */
+ return status;
+ }
+
+ /* See if we are trying to repeat a task that's not repeatable. */
+ if (gs_task_done(game, task)) {
+ sc_bool repeatable;
+
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "Repeatable";
+ repeatable = prop_get_boolean(bundle, "B<-sis", vt_key);
+ if (!repeatable) {
+ const sc_char *repeattext;
+
+ vt_key[2].string = "RepeatText";
+ repeattext = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(repeattext)) {
+ if (task_trace) {
+ sc_trace("Task:"
+ " trying to repeat completed action, aborting\n");
+ }
+
+ pf_buffer_string(filter, repeattext);
+ pf_buffer_character(filter, '\n');
+ status |= TRUE;
+ return status;
+ }
+
+ /*
+ * Task done, yet not repeatable, so don't consider this case
+ * handled.
+ */
+ return status;
+ }
+ }
+
+ /* Mark the task as done. */
+ gs_set_task_done(game, task, TRUE);
+
+ /* Print any task completion text. */
+ vt_key[0].string = "Tasks";
+ vt_key[1].integer = task;
+ vt_key[2].string = "CompleteText";
+ completetext = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(completetext)) {
+ pf_buffer_string(filter, completetext);
+ pf_buffer_character(filter, '\n');
+ status |= TRUE;
+ }
+
+ /* Handle any task completion resource. */
+ vt_key[2].string = "Res";
+ res_handle_resource(game, "sis", vt_key);
+
+ /*
+ * Things get slightly tricky here. We need to filter the completion text
+ * for the task using any final variable values generated or modified by
+ * task actions, but other task text, run by actions, according to the
+ * variable value in effect when it runs.
+ *
+ * To do this, we take a local copy of the filter's current buffer at this
+ * point, remove it from the filter, run task actions with checkpointing,
+ * then prepend it back into the filter after all the actions are done.
+ *
+ * As an optimization, we can avoid doing this if there are no task actions.
+ */
+ vt_key[2].string = "Actions";
+ action_count = prop_get_child_count(bundle, "I<-sis", vt_key);
+ if (action_count > 0) {
+ sc_char *buffer;
+
+ /*
+ * Take ownership of the current filter buffer text, then start NPC
+ * walks based on alerts, and run any and all task actions. Note that
+ * the buffer transferred out of the filter may be NULL if there is no
+ * text currently in the filter.
+ */
+ buffer = pf_transfer_buffer(filter);
+ task_start_npc_walks(game, task);
+ status |= task_run_task_actions(game, task);
+
+ /* Prepend the saved buffer data back onto the front of the filter. */
+ if (buffer) {
+ pf_prepend_string(filter, buffer);
+ sc_free(buffer);
+ }
+ } else {
+ /* Start NPC walks only; there are no task actions. */
+ task_start_npc_walks(game, task);
+ }
+
+ /* Append any room description and additional message for the task. */
+ vt_key[2].string = "ShowRoomDesc";
+ showroomdesc = prop_get_integer(bundle, "I<-sis", vt_key);
+ if (showroomdesc != 0) {
+ lib_print_room_name(game, showroomdesc - 1);
+ lib_print_room_description(game, showroomdesc - 1);
+ status |= TRUE;
+ }
+
+ vt_key[2].string = "AdditionalMessage";
+ additionalmessage = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(additionalmessage)) {
+ pf_buffer_string(filter, additionalmessage);
+ pf_buffer_character(filter, '\n');
+ status |= TRUE;
+ }
+
+ /* Return status -- TRUE if matched and we output something. */
+ return status;
}
@@ -1330,72 +1222,64 @@ task_run_task_unrestricted (sc_gameref_t game, sc_int task, sc_bool forwards)
* the call depth.
*/
sc_bool
-task_run_task (sc_gameref_t game, sc_int task, sc_bool forwards)
-{
- static sc_int recursion_depth = 0;
-
- const sc_filterref_t filter = gs_get_filter (game);
- const sc_char *fail_message;
- sc_bool restrictions_passed, status;
-
- if (task_trace)
- {
- sc_trace ("Task: running task %ld %s, depth %ld\n",
- task, forwards ? "forwards" : "backwards", recursion_depth);
- }
-
- /* Check restrictions. */
- if (!restr_eval_task_restrictions (game, task,
- &restrictions_passed, &fail_message))
- {
- sc_error ("task_run_task: restrictions error, %ld\n", task);
- return FALSE;
- }
- if (!restrictions_passed)
- {
- if (task_trace)
- {
- sc_trace ("Task: restrictions failed, task %s\n",
- fail_message ? "failed" : "aborted");
- }
-
- if (fail_message)
- {
- /*
- * Print a message, and return TRUE since we can consider this task
- * "done" (more accurately, we've output text, so the task command
- * searching in the main run loop can exit...).
- */
- pf_buffer_string (filter, fail_message);
- pf_buffer_character (filter, '\n');
- return TRUE;
- }
-
- /* Task not done; look for more possibilities. */
- return FALSE;
- }
-
- /* Check for infinite recursion. */
- if (recursion_depth > TASK_MAXIMUM_RECURSION)
- {
- sc_error ("task_run_task: maximum recursion depth exceeded --"
- " game task loop?\n");
- return FALSE;
- }
-
- /* Increment depth, run the task, then decrement depth. */
- recursion_depth++;
- status = task_run_task_unrestricted (game, task, forwards);
- recursion_depth--;
-
- if (task_trace)
- {
- sc_trace ("Task: task %ld finished, return %s, depth %ld\n",
- task, status ? "true" : "false", recursion_depth);
- }
-
- /* Return the task's status. */
- return status;
+task_run_task(sc_gameref_t game, sc_int task, sc_bool forwards) {
+ static sc_int recursion_depth = 0;
+
+ const sc_filterref_t filter = gs_get_filter(game);
+ const sc_char *fail_message;
+ sc_bool restrictions_passed, status;
+
+ if (task_trace) {
+ sc_trace("Task: running task %ld %s, depth %ld\n",
+ task, forwards ? "forwards" : "backwards", recursion_depth);
+ }
+
+ /* Check restrictions. */
+ if (!restr_eval_task_restrictions(game, task,
+ &restrictions_passed, &fail_message)) {
+ sc_error("task_run_task: restrictions error, %ld\n", task);
+ return FALSE;
+ }
+ if (!restrictions_passed) {
+ if (task_trace) {
+ sc_trace("Task: restrictions failed, task %s\n",
+ fail_message ? "failed" : "aborted");
+ }
+
+ if (fail_message) {
+ /*
+ * Print a message, and return TRUE since we can consider this task
+ * "done" (more accurately, we've output text, so the task command
+ * searching in the main run loop can exit...).
+ */
+ pf_buffer_string(filter, fail_message);
+ pf_buffer_character(filter, '\n');
+ return TRUE;
+ }
+
+ /* Task not done; look for more possibilities. */
+ return FALSE;
+ }
+
+ /* Check for infinite recursion. */
+ if (recursion_depth > TASK_MAXIMUM_RECURSION) {
+ sc_error("task_run_task: maximum recursion depth exceeded --"
+ " game task loop?\n");
+ return FALSE;
+ }
+
+ /* Increment depth, run the task, then decrement depth. */
+ recursion_depth++;
+ status = task_run_task_unrestricted(game, task, forwards);
+ recursion_depth--;
+
+ if (task_trace) {
+ sc_trace("Task: task %ld finished, return %s, depth %ld\n",
+ task, status ? "true" : "false", recursion_depth);
+ }
+
+ /* Return the task's status. */
+ return status;
}
@@ -1405,9 +1289,8 @@ task_run_task (sc_gameref_t game, sc_int task, sc_bool forwards)
* Set task tracing on/off.
*/
void
-task_debug_trace (sc_bool flag)
-{
- task_trace = flag;
+task_debug_trace(sc_bool flag) {
+ task_trace = flag;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scutils.cpp b/engines/glk/adrift/scutils.cpp
index 98e10651e7..97db91dbb8 100644
--- a/engines/glk/adrift/scutils.cpp
+++ b/engines/glk/adrift/scutils.cpp
@@ -42,14 +42,14 @@ namespace Adrift {
*
* Debugging trace function; printf wrapper that writes to stderr.
*/
-void sc_trace (const sc_char *format, ...) {
- va_list ap;
- assert(format);
-
- va_start (ap, format);
- Common::String s = Common::String::format(format, ap);
- va_end (ap);
- debug("%s", s.c_str());
+void sc_trace(const sc_char *format, ...) {
+ va_list ap;
+ assert(format);
+
+ va_start(ap, format);
+ Common::String s = Common::String::format(format, ap);
+ va_end(ap);
+ debug("%s", s.c_str());
}
@@ -60,7 +60,7 @@ void sc_trace (const sc_char *format, ...) {
* Error reporting functions. sc_error() prints a message and continues.
* sc_fatal() prints a message, then calls abort().
*/
-void sc_error (const sc_char *format, ...) {
+void sc_error(const sc_char *format, ...) {
va_list ap;
assert(format);
@@ -70,7 +70,7 @@ void sc_error (const sc_char *format, ...) {
warning("%s", s.c_str());
}
-void sc_fatal (const sc_char *format, ...) {
+void sc_fatal(const sc_char *format, ...) {
va_list ap;
assert(format);
@@ -83,7 +83,7 @@ void sc_fatal (const sc_char *format, ...) {
/* Unique non-heap address for zero size malloc() and realloc() requests. */
static void *sc_zero_allocation = &sc_zero_allocation;
-
+
/*
* sc_malloc()
* sc_realloc()
@@ -94,56 +94,52 @@ static void *sc_zero_allocation = &sc_zero_allocation;
* defined, so we have to take special care to get predictable behavior.
*/
void *
-sc_malloc (size_t size)
-{
- void *allocated;
+sc_malloc(size_t size) {
+ void *allocated;
- if (size == 0)
- return sc_zero_allocation;
+ if (size == 0)
+ return sc_zero_allocation;
- allocated = malloc (size);
- if (!allocated)
- sc_fatal ("sc_malloc: requested %lu bytes\n", (sc_uint) size);
- else if (allocated == sc_zero_allocation)
- sc_fatal ("sc_malloc: zero-byte allocation address returned\n");
+ allocated = malloc(size);
+ if (!allocated)
+ sc_fatal("sc_malloc: requested %lu bytes\n", (sc_uint) size);
+ else if (allocated == sc_zero_allocation)
+ sc_fatal("sc_malloc: zero-byte allocation address returned\n");
- memset (allocated, 0, size);
- return allocated;
+ memset(allocated, 0, size);
+ return allocated;
}
void *
-sc_realloc (void *pointer, size_t size)
-{
- void *allocated;
-
- if (size == 0)
- {
- sc_free (pointer);
- return sc_zero_allocation;
- }
-
- if (pointer == sc_zero_allocation)
- pointer = NULL;
-
- allocated = realloc (pointer, size);
- if (!allocated)
- sc_fatal ("sc_realloc: requested %lu bytes\n", (sc_uint) size);
- else if (allocated == sc_zero_allocation)
- sc_fatal ("sc_realloc: zero-byte allocation address returned\n");
-
- if (!pointer)
- memset (allocated, 0, size);
- return allocated;
+sc_realloc(void *pointer, size_t size) {
+ void *allocated;
+
+ if (size == 0) {
+ sc_free(pointer);
+ return sc_zero_allocation;
+ }
+
+ if (pointer == sc_zero_allocation)
+ pointer = NULL;
+
+ allocated = realloc(pointer, size);
+ if (!allocated)
+ sc_fatal("sc_realloc: requested %lu bytes\n", (sc_uint) size);
+ else if (allocated == sc_zero_allocation)
+ sc_fatal("sc_realloc: zero-byte allocation address returned\n");
+
+ if (!pointer)
+ memset(allocated, 0, size);
+ return allocated;
}
void
-sc_free (void *pointer)
-{
- if (sc_zero_allocation != &sc_zero_allocation)
- sc_fatal ("sc_free: write to zero-byte allocation address detected\n");
+sc_free(void *pointer) {
+ if (sc_zero_allocation != &sc_zero_allocation)
+ sc_fatal("sc_free: write to zero-byte allocation address detected\n");
- if (pointer && pointer != sc_zero_allocation)
- free (pointer);
+ if (pointer && pointer != sc_zero_allocation)
+ free(pointer);
}
@@ -155,37 +151,34 @@ sc_free (void *pointer)
* definitions to do the same jobs.
*/
sc_int
-sc_strncasecmp (const sc_char *s1, const sc_char *s2, sc_int n)
-{
- sc_int index_;
- assert (s1 && s2);
+sc_strncasecmp(const sc_char *s1, const sc_char *s2, sc_int n) {
+ sc_int index_;
+ assert(s1 && s2);
- for (index_ = 0; index_ < n; index_++)
- {
- sc_int diff;
+ for (index_ = 0; index_ < n; index_++) {
+ sc_int diff;
- diff = sc_tolower (s1[index_]) - sc_tolower (s2[index_]);
- if (diff < 0 || diff > 0)
- return diff < 0 ? -1 : 1;
- }
+ diff = sc_tolower(s1[index_]) - sc_tolower(s2[index_]);
+ if (diff < 0 || diff > 0)
+ return diff < 0 ? -1 : 1;
+ }
- return 0;
+ return 0;
}
sc_int
-sc_strcasecmp (const sc_char *s1, const sc_char *s2)
-{
- sc_int s1len, s2len, result;
- assert (s1 && s2);
-
- s1len = strlen (s1);
- s2len = strlen (s2);
-
- result = sc_strncasecmp (s1, s2, s1len < s2len ? s1len : s2len);
- if (result < 0 || result > 0)
- return result;
- else
- return s1len < s2len ? -1 : s1len > s2len ? 1 : 0;
+sc_strcasecmp(const sc_char *s1, const sc_char *s2) {
+ sc_int s1len, s2len, result;
+ assert(s1 && s2);
+
+ s1len = strlen(s1);
+ s2len = strlen(s2);
+
+ result = sc_strncasecmp(s1, s2, s1len < s2len ? s1len : s2len);
+ if (result < 0 || result > 0)
+ return result;
+ else
+ return s1len < s2len ? -1 : s1len > s2len ? 1 : 0;
}
@@ -202,70 +195,61 @@ sc_strcasecmp (const sc_char *s1, const sc_char *s2)
* with the latter intended for predictability of game actions.
*/
static sc_int
-sc_platform_rand (sc_uint new_seed)
-{
- static sc_bool is_seeded = FALSE;
-
- /* If reseeding, seed with the value supplied, note seeded, and return 0. */
- if (new_seed > 0) {
- g_vm->setRandomNumberSeed(new_seed);
- is_seeded = TRUE;
- return 0;
- }
- else
- {
- /* If not explicitly seeded yet, generate a seed from time(). */
- if (!is_seeded)
- {
- //srand ((sc_uint) time (NULL));
- is_seeded = TRUE;
- }
-
- /* Return the next rand() number in the sequence. */
- return g_vm->getRandomNumber(0xffffff);
- }
+sc_platform_rand(sc_uint new_seed) {
+ static sc_bool is_seeded = FALSE;
+
+ /* If reseeding, seed with the value supplied, note seeded, and return 0. */
+ if (new_seed > 0) {
+ g_vm->setRandomNumberSeed(new_seed);
+ is_seeded = TRUE;
+ return 0;
+ } else {
+ /* If not explicitly seeded yet, generate a seed from time(). */
+ if (!is_seeded) {
+ //srand ((sc_uint) time (NULL));
+ is_seeded = TRUE;
+ }
+
+ /* Return the next rand() number in the sequence. */
+ return g_vm->getRandomNumber(0xffffff);
+ }
}
static sc_int
-sc_congruential_rand (sc_uint new_seed)
-{
- static sc_bool is_seeded = FALSE;
- static sc_uint rand_state = 1;
-
- /* If reseeding, seed with the value supplied, and note seeded. */
- if (new_seed > 0)
- {
- rand_state = new_seed;
- is_seeded = TRUE;
- return 0;
- }
- else
- {
- /* If not explicitly seeded yet, generate a seed from time(). */
- if (!is_seeded)
- {
- rand_state = (sc_uint)g_vm->_events->getTotalPlayTicks();
- is_seeded = TRUE;
- }
-
- /*
- * Advance random state, using constants from Park & Miller (1988).
- * To keep the values the same for both 32 and 64 bit longs, mask out
- * any bits above the bottom 32.
- */
- rand_state = (rand_state * 16807 + 2147483647) & 0xffffffff;
-
- /*
- * Discard the lowest bit as a way to map 32-bits unsigned to a 32-bit
- * positive signed.
- */
- return rand_state >> 1;
- }
+sc_congruential_rand(sc_uint new_seed) {
+ static sc_bool is_seeded = FALSE;
+ static sc_uint rand_state = 1;
+
+ /* If reseeding, seed with the value supplied, and note seeded. */
+ if (new_seed > 0) {
+ rand_state = new_seed;
+ is_seeded = TRUE;
+ return 0;
+ } else {
+ /* If not explicitly seeded yet, generate a seed from time(). */
+ if (!is_seeded) {
+ rand_state = (sc_uint)g_vm->_events->getTotalPlayTicks();
+ is_seeded = TRUE;
+ }
+
+ /*
+ * Advance random state, using constants from Park & Miller (1988).
+ * To keep the values the same for both 32 and 64 bit longs, mask out
+ * any bits above the bottom 32.
+ */
+ rand_state = (rand_state * 16807 + 2147483647) & 0xffffffff;
+
+ /*
+ * Discard the lowest bit as a way to map 32-bits unsigned to a 32-bit
+ * positive signed.
+ */
+ return rand_state >> 1;
+ }
}
/* Function pointer for the actual random number generator in use. */
-static sc_int (*sc_rand_function) (sc_uint) = sc_platform_rand;
+static sc_int(*sc_rand_function)(sc_uint) = sc_platform_rand;
/*
* sc_set_congruential_random()
@@ -280,49 +264,43 @@ static sc_int (*sc_rand_function) (sc_uint) = sc_platform_rand;
* generate a random value within a given range.
*/
void
-sc_set_congruential_random (void)
-{
- sc_rand_function = sc_congruential_rand;
+sc_set_congruential_random(void) {
+ sc_rand_function = sc_congruential_rand;
}
void
-sc_set_platform_random (void)
-{
- sc_rand_function = sc_platform_rand;
+sc_set_platform_random(void) {
+ sc_rand_function = sc_platform_rand;
}
sc_bool
-sc_is_congruential_random (void)
-{
- return sc_rand_function == sc_congruential_rand;
+sc_is_congruential_random(void) {
+ return sc_rand_function == sc_congruential_rand;
}
void
-sc_seed_random (sc_uint new_seed)
-{
- /* Ignore zero values of new_seed by simply using 1 instead. */
- sc_rand_function (new_seed > 0 ? new_seed : 1);
+sc_seed_random(sc_uint new_seed) {
+ /* Ignore zero values of new_seed by simply using 1 instead. */
+ sc_rand_function(new_seed > 0 ? new_seed : 1);
}
sc_int
-sc_rand (void)
-{
- sc_int retval;
+sc_rand(void) {
+ sc_int retval;
- /* Passing zero indicates this is not a seed operation. */
- retval = sc_rand_function (0);
- return retval;
+ /* Passing zero indicates this is not a seed operation. */
+ retval = sc_rand_function(0);
+ return retval;
}
sc_int
-sc_randomint (sc_int low, sc_int high)
-{
- /*
- * If the range is invalid, just return the low value given. This mimics
- * Adrift under the same conditions, and also guards against division by
- * zero in the mod operation.
- */
- return (high < low) ? low : low + sc_rand () % (high - low + 1);
+sc_randomint(sc_int low, sc_int high) {
+ /*
+ * If the range is invalid, just return the low value given. This mimics
+ * Adrift under the same conditions, and also guards against division by
+ * zero in the mod operation.
+ */
+ return (high < low) ? low : low + sc_rand() % (high - low + 1);
}
@@ -336,20 +314,18 @@ static const sc_char SPACE = ' ';
* Return TRUE if a string is either zero-length or contains only whitespace.
*/
sc_bool
-sc_strempty (const sc_char *string)
-{
- sc_int index_;
- assert (string);
-
- /* Scan for any non-space character. */
- for (index_ = 0; string[index_] != NUL; index_++)
- {
- if (!sc_isspace (string[index_]))
- return FALSE;
- }
-
- /* None found, so string is empty. */
- return TRUE;
+sc_strempty(const sc_char *string) {
+ sc_int index_;
+ assert(string);
+
+ /* Scan for any non-space character. */
+ for (index_ = 0; string[index_] != NUL; index_++) {
+ if (!sc_isspace(string[index_]))
+ return FALSE;
+ }
+
+ /* None found, so string is empty. */
+ return TRUE;
}
@@ -360,20 +336,19 @@ sc_strempty (const sc_char *string)
* in place, and returns the string address for convenience.
*/
sc_char *
-sc_trim_string (sc_char *string)
-{
- sc_int index_;
- assert (string);
+sc_trim_string(sc_char *string) {
+ sc_int index_;
+ assert(string);
- for (index_ = strlen (string) - 1;
- index_ >= 0 && sc_isspace (string[index_]); index_--)
- string[index_] = NUL;
+ for (index_ = strlen(string) - 1;
+ index_ >= 0 && sc_isspace(string[index_]); index_--)
+ string[index_] = NUL;
- for (index_ = 0; sc_isspace (string[index_]);)
- index_++;
- memmove (string, string + index_, strlen (string) - index_ + 1);
+ for (index_ = 0; sc_isspace(string[index_]);)
+ index_++;
+ memmove(string, string + index_, strlen(string) - index_ + 1);
- return string;
+ return string;
}
@@ -385,30 +360,27 @@ sc_trim_string (sc_char *string)
* convenience.
*/
sc_char *
-sc_normalize_string (sc_char *string)
-{
- sc_int index_;
- assert (string);
-
- /* Trim all leading and trailing spaces. */
- string = sc_trim_string (string);
-
- /* Compress multiple whitespace runs into a single space character. */
- for (index_ = 0; string[index_] != NUL; index_++)
- {
- if (sc_isspace (string[index_]))
- {
- sc_int cursor;
-
- string[index_] = SPACE;
- for (cursor = index_ + 1; sc_isspace (string[cursor]);)
- cursor++;
- memmove (string + index_ + 1,
- string + cursor, strlen (string + cursor) + 1);
- }
- }
-
- return string;
+sc_normalize_string(sc_char *string) {
+ sc_int index_;
+ assert(string);
+
+ /* Trim all leading and trailing spaces. */
+ string = sc_trim_string(string);
+
+ /* Compress multiple whitespace runs into a single space character. */
+ for (index_ = 0; string[index_] != NUL; index_++) {
+ if (sc_isspace(string[index_])) {
+ sc_int cursor;
+
+ string[index_] = SPACE;
+ for (cursor = index_ + 1; sc_isspace(string[cursor]);)
+ cursor++;
+ memmove(string + index_ + 1,
+ string + cursor, strlen(string + cursor) + 1);
+ }
+ }
+
+ return string;
}
@@ -418,13 +390,12 @@ sc_normalize_string (sc_char *string)
* Return TRUE if the first word in the string is word, case insensitive.
*/
sc_bool
-sc_compare_word (const sc_char *string, const sc_char *word, sc_int length)
-{
- assert (string && word);
+sc_compare_word(const sc_char *string, const sc_char *word, sc_int length) {
+ assert(string && word);
- /* Return TRUE if string starts with word, then space or string end. */
- return sc_strncasecmp (string, word, length) == 0
- && (string[length] == NUL || sc_isspace (string[length]));
+ /* Return TRUE if string starts with word, then space or string end. */
+ return sc_strncasecmp(string, word, length) == 0
+ && (string[length] == NUL || sc_isspace(string[length]));
}
@@ -435,27 +406,24 @@ sc_compare_word (const sc_char *string, const sc_char *word, sc_int length)
* and tools', page 436, unmodulo'ed and somewhat restyled.
*/
sc_uint
-sc_hash (const sc_char *string)
-{
- sc_int index_;
- sc_uint hash;
- assert (string);
-
- hash = 0;
- for (index_ = 0; string[index_] != NUL; index_++)
- {
- sc_uint temp;
-
- hash = (hash << 4) + string[index_];
- temp = hash & 0xf0000000;
- if (temp != 0)
- {
- hash = hash ^ (temp >> 24);
- hash = hash ^ temp;
- }
- }
-
- return hash;
+sc_hash(const sc_char *string) {
+ sc_int index_;
+ sc_uint hash;
+ assert(string);
+
+ hash = 0;
+ for (index_ = 0; string[index_] != NUL; index_++) {
+ sc_uint temp;
+
+ hash = (hash << 4) + string[index_];
+ temp = hash & 0xf0000000;
+ if (temp != 0) {
+ hash = hash ^ (temp >> 24);
+ hash = hash ^ temp;
+ }
+ }
+
+ return hash;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/scvars.cpp b/engines/glk/adrift/scvars.cpp
index 0ed62446c1..65957e1c6e 100644
--- a/engines/glk/adrift/scvars.cpp
+++ b/engines/glk/adrift/scvars.cpp
@@ -51,19 +51,18 @@ static sc_bool var_trace = FALSE;
/* Table of numbers zero to twenty spelled out. */
enum { VAR_NUMBERS_SIZE = 21 };
static const sc_char *const VAR_NUMBERS[VAR_NUMBERS_SIZE] = {
- "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
- "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
- "sixteen", "seventeen", "eighteen", "nineteen", "twenty"
+ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
+ "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
+ "sixteen", "seventeen", "eighteen", "nineteen", "twenty"
};
/* Variable entry, held on a list hashed by variable name. */
-typedef struct sc_var_s
-{
- struct sc_var_s *next;
+typedef struct sc_var_s {
+ struct sc_var_s *next;
- const sc_char *name;
- sc_int type;
- sc_vartype_t value;
+ const sc_char *name;
+ sc_int type;
+ sc_vartype_t value;
} sc_var_t;
typedef sc_var_t *sc_varref_t;
@@ -74,20 +73,19 @@ typedef sc_var_t *sc_varref_t;
* exceed a fill factor of two (~422 variables).
*/
enum { VAR_HASH_TABLE_SIZE = 211 };
-typedef struct sc_var_set_s
-{
- sc_uint magic;
- sc_prop_setref_t bundle;
- sc_int referenced_character;
- sc_int referenced_object;
- sc_int referenced_number;
- sc_bool is_number_referenced;
- sc_char *referenced_text;
- sc_char *temporary;
- uint32 timestamp;
- sc_uint time_offset;
- sc_gameref_t game;
- sc_varref_t variable[VAR_HASH_TABLE_SIZE];
+typedef struct sc_var_set_s {
+ sc_uint magic;
+ sc_prop_setref_t bundle;
+ sc_int referenced_character;
+ sc_int referenced_object;
+ sc_int referenced_number;
+ sc_bool is_number_referenced;
+ sc_char *referenced_text;
+ sc_char *temporary;
+ uint32 timestamp;
+ sc_uint time_offset;
+ sc_gameref_t game;
+ sc_varref_t variable[VAR_HASH_TABLE_SIZE];
} sc_var_set_t;
@@ -97,9 +95,8 @@ typedef struct sc_var_set_s
* Return TRUE if pointer is a valid variables set, FALSE otherwise.
*/
static sc_bool
-var_is_valid (sc_var_setref_t vars)
-{
- return vars && vars->magic == VARS_MAGIC;
+var_is_valid(sc_var_setref_t vars) {
+ return vars && vars->magic == VARS_MAGIC;
}
@@ -109,9 +106,8 @@ var_is_valid (sc_var_setref_t vars)
* Hash a variable name, modulo'ed to the number of buckets.
*/
static sc_uint
-var_hash_name (const sc_char *name)
-{
- return sc_hash (name) % VAR_HASH_TABLE_SIZE;
+var_hash_name(const sc_char *name) {
+ return sc_hash(name) % VAR_HASH_TABLE_SIZE;
}
@@ -121,30 +117,29 @@ var_hash_name (const sc_char *name)
* Create and return a new empty set of variables.
*/
static sc_var_setref_t
-var_create_empty (void)
-{
- sc_var_setref_t vars;
- sc_int index_;
-
- /* Create a clean set of variables. */
- vars = (sc_var_setref_t)sc_malloc(sizeof (*vars));
- vars->magic = VARS_MAGIC;
- vars->bundle = nullptr;
- vars->referenced_character = -1;
- vars->referenced_object = -1;
- vars->referenced_number = 0;
- vars->is_number_referenced = FALSE;
- vars->referenced_text = nullptr;
- vars->temporary = nullptr;
- vars->timestamp = g_vm->_events->getTotalPlayTicks() / 1000;
- vars->time_offset = 0;
- vars->game = nullptr;
-
- /* Clear all variable hash lists. */
- for (index_ = 0; index_ < VAR_HASH_TABLE_SIZE; index_++)
- vars->variable[index_] = nullptr;
-
- return vars;
+var_create_empty(void) {
+ sc_var_setref_t vars;
+ sc_int index_;
+
+ /* Create a clean set of variables. */
+ vars = (sc_var_setref_t)sc_malloc(sizeof(*vars));
+ vars->magic = VARS_MAGIC;
+ vars->bundle = nullptr;
+ vars->referenced_character = -1;
+ vars->referenced_object = -1;
+ vars->referenced_number = 0;
+ vars->is_number_referenced = FALSE;
+ vars->referenced_text = nullptr;
+ vars->temporary = nullptr;
+ vars->timestamp = g_vm->_events->getTotalPlayTicks() / 1000;
+ vars->time_offset = 0;
+ vars->game = nullptr;
+
+ /* Clear all variable hash lists. */
+ for (index_ = 0; index_ < VAR_HASH_TABLE_SIZE; index_++)
+ vars->variable[index_] = nullptr;
+
+ return vars;
}
@@ -154,35 +149,32 @@ var_create_empty (void)
* Destroy a variable set, and free its heap memory.
*/
void
-var_destroy (sc_var_setref_t vars)
-{
- sc_int index_;
- assert (var_is_valid (vars));
-
- /*
- * Free the content of each string variable, and variable entry. String
- * variable content needs to use mutable string instead of const string.
- */
- for (index_ = 0; index_ < VAR_HASH_TABLE_SIZE; index_++)
- {
- sc_varref_t var, next;
-
- for (var = vars->variable[index_]; var; var = next)
- {
- next = var->next;
- if (var->type == VAR_STRING)
- sc_free (var->value.mutable_string);
- sc_free (var);
- }
- }
-
- /* Free any temporary and reference text storage area. */
- sc_free (vars->temporary);
- sc_free (vars->referenced_text);
-
- /* Poison and free the variable set itself. */
- memset (vars, 0xaa, sizeof (*vars));
- sc_free (vars);
+var_destroy(sc_var_setref_t vars) {
+ sc_int index_;
+ assert(var_is_valid(vars));
+
+ /*
+ * Free the content of each string variable, and variable entry. String
+ * variable content needs to use mutable string instead of const string.
+ */
+ for (index_ = 0; index_ < VAR_HASH_TABLE_SIZE; index_++) {
+ sc_varref_t var, next;
+
+ for (var = vars->variable[index_]; var; var = next) {
+ next = var->next;
+ if (var->type == VAR_STRING)
+ sc_free(var->value.mutable_string);
+ sc_free(var);
+ }
+ }
+
+ /* Free any temporary and reference text storage area. */
+ sc_free(vars->temporary);
+ sc_free(vars->referenced_text);
+
+ /* Poison and free the variable set itself. */
+ memset(vars, 0xaa, sizeof(*vars));
+ sc_free(vars);
}
@@ -194,41 +186,38 @@ var_destroy (sc_var_setref_t vars)
* variable exists, and add a new variable structure to the lists.
*/
static sc_varref_t
-var_find (sc_var_setref_t vars, const sc_char *name)
-{
- sc_uint hash;
- sc_varref_t var;
-
- /* Hash name, search list and return if name match found. */
- hash = var_hash_name (name);
- for (var = vars->variable[hash]; var; var = var->next)
- {
- if (strcmp (name, var->name) == 0)
- break;
- }
-
- /* Return variable, or nullptr if no such variable. */
- return var;
+var_find(sc_var_setref_t vars, const sc_char *name) {
+ sc_uint hash;
+ sc_varref_t var;
+
+ /* Hash name, search list and return if name match found. */
+ hash = var_hash_name(name);
+ for (var = vars->variable[hash]; var; var = var->next) {
+ if (strcmp(name, var->name) == 0)
+ break;
+ }
+
+ /* Return variable, or nullptr if no such variable. */
+ return var;
}
static sc_varref_t
-var_add (sc_var_setref_t vars, const sc_char *name, sc_int type)
-{
- sc_varref_t var;
- sc_uint hash;
-
- /* Create a new variable entry. */
- var = (sc_varref_t)sc_malloc (sizeof (*var));
- var->name = name;
- var->type = type;
- var->value.voidp = nullptr;
-
- /* Hash its name, and insert it at start of the relevant list. */
- hash = var_hash_name (name);
- var->next = vars->variable[hash];
- vars->variable[hash] = var;
-
- return var;
+var_add(sc_var_setref_t vars, const sc_char *name, sc_int type) {
+ sc_varref_t var;
+ sc_uint hash;
+
+ /* Create a new variable entry. */
+ var = (sc_varref_t)sc_malloc(sizeof(*var));
+ var->name = name;
+ var->type = type;
+ var->value.voidp = nullptr;
+
+ /* Hash its name, and insert it at start of the relevant list. */
+ hash = var_hash_name(name);
+ var->next = vars->variable[hash];
+ vars->variable[hash] = var;
+
+ return var;
}
@@ -239,18 +228,16 @@ var_add (sc_var_setref_t vars, const sc_char *name, sc_int type)
* of this variable, and to re-initialize user versions initialized to zero.
*/
static sc_int
-var_get_scare_version (void)
-{
- sc_int major, minor, point, version;
-
- if (sscanf (SCARE_VERSION, "%ld.%ld.%ld", &major, &minor, &point) != 3)
- {
- sc_error ("var_get_scare_version: unable to generate scare_version\n");
- return 0;
- }
-
- version = major * 10000 + minor * 100 + point;
- return version;
+var_get_scare_version(void) {
+ sc_int major, minor, point, version;
+
+ if (sscanf(SCARE_VERSION, "%ld.%ld.%ld", &major, &minor, &point) != 3) {
+ sc_error("var_get_scare_version: unable to generate scare_version\n");
+ return 0;
+ }
+
+ version = major * 10000 + minor * 100 + point;
+ return version;
}
@@ -261,109 +248,99 @@ var_get_scare_version (void)
* is created. Type is one of 'I' or 'S' for integer or string.
*/
void
-var_put (sc_var_setref_t vars,
- const sc_char *name, sc_int type, sc_vartype_t vt_value)
-{
- sc_varref_t var;
- sc_bool is_modification;
- assert (var_is_valid (vars));
- assert (name);
-
- /* Check type is either integer or string. */
- switch (type)
- {
- case VAR_INTEGER:
- case VAR_STRING:
- break;
-
- default:
- sc_fatal ("var_put: invalid variable type, %ld\n", type);
- }
-
- /* See if the user variable already exists. */
- var = var_find (vars, name);
- if (var)
- {
- /* Verify that nothing is trying to change the variable's type. */
- if (var->type != type)
- sc_fatal ("var_put: variable type changed, %s\n", name);
-
- /*
- * Special case %scare_version%. If a game changes its value, it may
- * compromise version checking, so warn here, but continue.
- */
- if (strcmp (name, "scare_version") == 0)
- {
- if (var->value.integer != vt_value.integer)
- sc_error ("var_put: warning: %%%s%% value changed\n", name);
- }
-
- is_modification = TRUE;
- }
- else
- {
- /*
- * Special case %scare_version%. If a game defines this and initializes
- * it to zero, re-initialize it to SCARE's version number. Games that
- * define %scare_version%, initially zero, can use this to test if
- * running under SCARE or Runner.
- */
- if (strcmp (name, "scare_version") == 0 && vt_value.integer == 0)
- {
- vt_value.integer = var_get_scare_version ();
-
- if (var_trace)
- sc_trace ("Variable: %%%s%% [new] caught and mapped\n", name);
- }
-
- /*
- * Create a new and empty variable entry. The mutable string needs to
- * be set to nullptr here so that realloc works correctly on assigning
- * the value below.
- */
- var = var_add (vars, name, type);
- var->value.mutable_string = nullptr;
-
- is_modification = FALSE;
- }
-
- /* Update the existing variable, or populate the new one fully. */
- switch (var->type)
- {
- case VAR_INTEGER:
- var->value.integer = vt_value.integer;
- break;
-
- case VAR_STRING:
- /* Use mutable string instead of const string. */
- var->value.mutable_string = (sc_char *)sc_realloc(var->value.mutable_string,
- strlen (vt_value.string) + 1);
- strcpy (var->value.mutable_string, vt_value.string);
- break;
-
- default:
- sc_fatal ("var_put: invalid variable type, %ld\n", var->type);
- }
-
- if (var_trace)
- {
- sc_trace ("Variable: %%%s%%%s = ",
- name, is_modification ? "" : " [new]");
- switch (var->type)
- {
- case VAR_INTEGER:
- sc_trace ("%ld", var->value.integer);
- break;
- case VAR_STRING:
- sc_trace ("\"%s\"", var->value.string);
- break;
-
- default:
- sc_trace ("[invalid variable type, %ld]", var->type);
- break;
- }
- sc_trace ("\n");
- }
+var_put(sc_var_setref_t vars,
+ const sc_char *name, sc_int type, sc_vartype_t vt_value) {
+ sc_varref_t var;
+ sc_bool is_modification;
+ assert(var_is_valid(vars));
+ assert(name);
+
+ /* Check type is either integer or string. */
+ switch (type) {
+ case VAR_INTEGER:
+ case VAR_STRING:
+ break;
+
+ default:
+ sc_fatal("var_put: invalid variable type, %ld\n", type);
+ }
+
+ /* See if the user variable already exists. */
+ var = var_find(vars, name);
+ if (var) {
+ /* Verify that nothing is trying to change the variable's type. */
+ if (var->type != type)
+ sc_fatal("var_put: variable type changed, %s\n", name);
+
+ /*
+ * Special case %scare_version%. If a game changes its value, it may
+ * compromise version checking, so warn here, but continue.
+ */
+ if (strcmp(name, "scare_version") == 0) {
+ if (var->value.integer != vt_value.integer)
+ sc_error("var_put: warning: %%%s%% value changed\n", name);
+ }
+
+ is_modification = TRUE;
+ } else {
+ /*
+ * Special case %scare_version%. If a game defines this and initializes
+ * it to zero, re-initialize it to SCARE's version number. Games that
+ * define %scare_version%, initially zero, can use this to test if
+ * running under SCARE or Runner.
+ */
+ if (strcmp(name, "scare_version") == 0 && vt_value.integer == 0) {
+ vt_value.integer = var_get_scare_version();
+
+ if (var_trace)
+ sc_trace("Variable: %%%s%% [new] caught and mapped\n", name);
+ }
+
+ /*
+ * Create a new and empty variable entry. The mutable string needs to
+ * be set to nullptr here so that realloc works correctly on assigning
+ * the value below.
+ */
+ var = var_add(vars, name, type);
+ var->value.mutable_string = nullptr;
+
+ is_modification = FALSE;
+ }
+
+ /* Update the existing variable, or populate the new one fully. */
+ switch (var->type) {
+ case VAR_INTEGER:
+ var->value.integer = vt_value.integer;
+ break;
+
+ case VAR_STRING:
+ /* Use mutable string instead of const string. */
+ var->value.mutable_string = (sc_char *)sc_realloc(var->value.mutable_string,
+ strlen(vt_value.string) + 1);
+ strcpy(var->value.mutable_string, vt_value.string);
+ break;
+
+ default:
+ sc_fatal("var_put: invalid variable type, %ld\n", var->type);
+ }
+
+ if (var_trace) {
+ sc_trace("Variable: %%%s%%%s = ",
+ name, is_modification ? "" : " [new]");
+ switch (var->type) {
+ case VAR_INTEGER:
+ sc_trace("%ld", var->value.integer);
+ break;
+ case VAR_STRING:
+ sc_trace("\"%s\"", var->value.string);
+ break;
+
+ default:
+ sc_trace("[invalid variable type, %ld]", var->type);
+ break;
+ }
+ sc_trace("\n");
+ }
}
@@ -374,32 +351,28 @@ var_put (sc_var_setref_t vars,
* to the string.
*/
static void
-var_append_temp (sc_var_setref_t vars, const sc_char *string)
-{
- sc_bool new_sentence;
- sc_int noted;
-
- if (!vars->temporary)
- {
- /* Create a new temporary area and copy string. */
- new_sentence = TRUE;
- noted = 0;
- vars->temporary = (sc_char *)sc_malloc (strlen (string) + 1);
- strcpy (vars->temporary, string);
- }
- else
- {
- /* Append string to existing temporary. */
- new_sentence = (vars->temporary[0] == NUL);
- noted = strlen (vars->temporary);
- vars->temporary = (sc_char *)sc_realloc (vars->temporary,
- strlen (vars->temporary) +
- strlen (string) + 1);
- strcat (vars->temporary, string);
- }
-
- if (new_sentence)
- vars->temporary[noted] = sc_toupper (vars->temporary[noted]);
+var_append_temp(sc_var_setref_t vars, const sc_char *string) {
+ sc_bool new_sentence;
+ sc_int noted;
+
+ if (!vars->temporary) {
+ /* Create a new temporary area and copy string. */
+ new_sentence = TRUE;
+ noted = 0;
+ vars->temporary = (sc_char *)sc_malloc(strlen(string) + 1);
+ strcpy(vars->temporary, string);
+ } else {
+ /* Append string to existing temporary. */
+ new_sentence = (vars->temporary[0] == NUL);
+ noted = strlen(vars->temporary);
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary,
+ strlen(vars->temporary) +
+ strlen(string) + 1);
+ strcat(vars->temporary, string);
+ }
+
+ if (new_sentence)
+ vars->temporary[noted] = sc_toupper(vars->temporary[noted]);
}
@@ -411,101 +384,87 @@ var_append_temp (sc_var_setref_t vars, const sc_char *string)
* prefix, to variables temporary.
*/
static void
-var_print_object_np (sc_gameref_t game, sc_int object)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *prefix, *normalized, *name;
-
- /* Get the object's prefix. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
-
- /*
- * Try the same shenanigans as done by the equivalent function in the
- * library.
- */
- normalized = prefix;
- if (sc_compare_word (prefix, "a", 1))
- {
- normalized = prefix + 1;
- var_append_temp (vars, "the");
- }
- else if (sc_compare_word (prefix, "an", 2))
- {
- normalized = prefix + 2;
- var_append_temp (vars, "the");
- }
- else if (sc_compare_word (prefix, "the", 3))
- {
- normalized = prefix + 3;
- var_append_temp (vars, "the");
- }
- else if (sc_compare_word (prefix, "some", 4))
- {
- normalized = prefix + 4;
- var_append_temp (vars, "the");
- }
- else if (sc_strempty (prefix))
- var_append_temp (vars, "the ");
-
- /* As with the library, handle the remaining prefix. */
- if (!sc_strempty (normalized))
- {
- var_append_temp (vars, normalized);
- var_append_temp (vars, " ");
- }
- else if (normalized > prefix)
- var_append_temp (vars, " ");
-
- /*
- * Print the object's name, again, as with the library, stripping any
- * leading article
- */
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- if (sc_compare_word (name, "a", 1))
- name += 1;
- else if (sc_compare_word (name, "an", 2))
- name += 2;
- else if (sc_compare_word (name, "the", 3))
- name += 3;
- else if (sc_compare_word (name, "some", 4))
- name += 4;
- var_append_temp (vars, name);
+var_print_object_np(sc_gameref_t game, sc_int object) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *prefix, *normalized, *name;
+
+ /* Get the object's prefix. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+
+ /*
+ * Try the same shenanigans as done by the equivalent function in the
+ * library.
+ */
+ normalized = prefix;
+ if (sc_compare_word(prefix, "a", 1)) {
+ normalized = prefix + 1;
+ var_append_temp(vars, "the");
+ } else if (sc_compare_word(prefix, "an", 2)) {
+ normalized = prefix + 2;
+ var_append_temp(vars, "the");
+ } else if (sc_compare_word(prefix, "the", 3)) {
+ normalized = prefix + 3;
+ var_append_temp(vars, "the");
+ } else if (sc_compare_word(prefix, "some", 4)) {
+ normalized = prefix + 4;
+ var_append_temp(vars, "the");
+ } else if (sc_strempty(prefix))
+ var_append_temp(vars, "the ");
+
+ /* As with the library, handle the remaining prefix. */
+ if (!sc_strempty(normalized)) {
+ var_append_temp(vars, normalized);
+ var_append_temp(vars, " ");
+ } else if (normalized > prefix)
+ var_append_temp(vars, " ");
+
+ /*
+ * Print the object's name, again, as with the library, stripping any
+ * leading article
+ */
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ if (sc_compare_word(name, "a", 1))
+ name += 1;
+ else if (sc_compare_word(name, "an", 2))
+ name += 2;
+ else if (sc_compare_word(name, "the", 3))
+ name += 3;
+ else if (sc_compare_word(name, "some", 4))
+ name += 4;
+ var_append_temp(vars, name);
}
static void
-var_print_object (sc_gameref_t game, sc_int object)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- const sc_prop_setref_t bundle = gs_get_bundle (game);
- sc_vartype_t vt_key[3];
- const sc_char *prefix, *name;
-
- /*
- * Get the object's prefix. As with the library, if the prefix is empty,
- * put in an "a ".
- */
- vt_key[0].string = "Objects";
- vt_key[1].integer = object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
- if (!sc_strempty (prefix))
- {
- var_append_temp (vars, prefix);
- var_append_temp (vars, " ");
- }
- else
- var_append_temp (vars, "a ");
-
- /* Print the object's name. */
- vt_key[2].string = "Short";
- name = prop_get_string (bundle, "S<-sis", vt_key);
- var_append_temp (vars, name);
+var_print_object(sc_gameref_t game, sc_int object) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ const sc_prop_setref_t bundle = gs_get_bundle(game);
+ sc_vartype_t vt_key[3];
+ const sc_char *prefix, *name;
+
+ /*
+ * Get the object's prefix. As with the library, if the prefix is empty,
+ * put in an "a ".
+ */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+ if (!sc_strempty(prefix)) {
+ var_append_temp(vars, prefix);
+ var_append_temp(vars, " ");
+ } else
+ var_append_temp(vars, "a ");
+
+ /* Print the object's name. */
+ vt_key[2].string = "Short";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+ var_append_temp(vars, name);
}
@@ -516,10 +475,9 @@ var_print_object (sc_gameref_t game, sc_int object)
* on whether an object appears singular or plural.
*/
static const sc_char *
-var_select_plurality (sc_gameref_t game, sc_int object,
- const sc_char *singular, const sc_char *plural)
-{
- return obj_appears_plural (game, object) ? plural : singular;
+var_select_plurality(sc_gameref_t game, sc_int object,
+ const sc_char *singular, const sc_char *plural) {
+ return obj_appears_plural(game, object) ? plural : singular;
}
@@ -529,54 +487,46 @@ var_select_plurality (sc_gameref_t game, sc_int object,
* List the objects in a given container object.
*/
static void
-var_list_in_object (sc_gameref_t game, sc_int container)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int object, count, trail;
-
- /* List out the objects contained in this object. */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- /* Contained? */
- if (gs_object_position (game, object) == OBJ_IN_OBJECT
- && gs_object_parent (game, object) == container)
- {
- if (count > 0)
- {
- if (count > 1)
- var_append_temp (vars, ", ");
-
- /* Print out the current list object. */
- var_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- var_print_object (game, trail);
- var_append_temp (vars,
- var_select_plurality (game, trail,
- " is inside ",
- " are inside "));
- }
- else
- {
- var_append_temp (vars, " and ");
- var_print_object (game, trail);
- var_append_temp (vars, " are inside ");
- }
-
- /* Print out the container. */
- var_print_object_np (game, container);
- var_append_temp (vars, ".");
- }
+var_list_in_object(sc_gameref_t game, sc_int container) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int object, count, trail;
+
+ /* List out the objects contained in this object. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ /* Contained? */
+ if (gs_object_position(game, object) == OBJ_IN_OBJECT
+ && gs_object_parent(game, object) == container) {
+ if (count > 0) {
+ if (count > 1)
+ var_append_temp(vars, ", ");
+
+ /* Print out the current list object. */
+ var_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ var_print_object(game, trail);
+ var_append_temp(vars,
+ var_select_plurality(game, trail,
+ " is inside ",
+ " are inside "));
+ } else {
+ var_append_temp(vars, " and ");
+ var_print_object(game, trail);
+ var_append_temp(vars, " are inside ");
+ }
+
+ /* Print out the container. */
+ var_print_object_np(game, container);
+ var_append_temp(vars, ".");
+ }
}
@@ -586,53 +536,45 @@ var_list_in_object (sc_gameref_t game, sc_int container)
* List the objects on a given surface object.
*/
static void
-var_list_on_object (sc_gameref_t game, sc_int supporter)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int object, count, trail;
-
- /* List out the objects standing on this object. */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- /* Standing on? */
- if (gs_object_position (game, object) == OBJ_ON_OBJECT
- && gs_object_parent (game, object) == supporter)
- {
- if (count > 0)
- {
- if (count > 1)
- var_append_temp (vars, ", ");
-
- /* Print out the current list object. */
- var_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- var_print_object (game, trail);
- var_append_temp (vars,
- var_select_plurality (game, trail,
- " is on ", " are on "));
- }
- else
- {
- var_append_temp (vars, " and ");
- var_print_object (game, trail);
- var_append_temp (vars, " are on ");
- }
-
- /* Print out the surface. */
- var_print_object_np (game, supporter);
- var_append_temp (vars, ".");
- }
+var_list_on_object(sc_gameref_t game, sc_int supporter) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int object, count, trail;
+
+ /* List out the objects standing on this object. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ /* Standing on? */
+ if (gs_object_position(game, object) == OBJ_ON_OBJECT
+ && gs_object_parent(game, object) == supporter) {
+ if (count > 0) {
+ if (count > 1)
+ var_append_temp(vars, ", ");
+
+ /* Print out the current list object. */
+ var_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ var_print_object(game, trail);
+ var_append_temp(vars,
+ var_select_plurality(game, trail,
+ " is on ", " are on "));
+ } else {
+ var_append_temp(vars, " and ");
+ var_print_object(game, trail);
+ var_append_temp(vars, " are on ");
+ }
+
+ /* Print out the surface. */
+ var_print_object_np(game, supporter);
+ var_append_temp(vars, ".");
+ }
}
@@ -642,115 +584,95 @@ var_list_on_object (sc_gameref_t game, sc_int supporter)
* List the objects on and in a given associate object.
*/
static void
-var_list_onin_object (sc_gameref_t game, sc_int associate)
-{
- const sc_var_setref_t vars = gs_get_vars (game);
- sc_int object, count, trail;
- sc_bool supporting;
-
- /* List out the objects standing on this object. */
- count = 0;
- trail = -1;
- supporting = FALSE;
- for (object = 0; object < gs_object_count (game); object++)
- {
- /* Standing on? */
- if (gs_object_position (game, object) == OBJ_ON_OBJECT
- && gs_object_parent (game, object) == associate)
- {
- if (count > 0)
- {
- if (count > 1)
- var_append_temp (vars, ", ");
-
- /* Print out the current list object. */
- var_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- var_print_object (game, trail);
- var_append_temp (vars,
- var_select_plurality (game, trail,
- " is on ", " are on "));
- }
- else
- {
- var_append_temp (vars, " and ");
- var_print_object (game, trail);
- var_append_temp (vars, " are on ");
- }
-
- /* Print out the surface. */
- var_print_object_np (game, associate);
- supporting = TRUE;
- }
-
- /* List out the objects contained in this object. */
- count = 0;
- trail = -1;
- for (object = 0; object < gs_object_count (game); object++)
- {
- /* Contained? */
- if (gs_object_position (game, object) == OBJ_IN_OBJECT
- && gs_object_parent (game, object) == associate)
- {
- if (count > 0)
- {
- if (count == 1)
- {
- if (supporting)
- var_append_temp (vars, ", and ");
- }
- else
- var_append_temp (vars, ", ");
-
- /* Print out the current list object. */
- var_print_object (game, trail);
- }
- trail = object;
- count++;
- }
- }
- if (count >= 1)
- {
- /* Print out final listed object. */
- if (count == 1)
- {
- if (supporting)
- var_append_temp (vars, ", and ");
- var_print_object (game, trail);
- var_append_temp (vars,
- var_select_plurality (game, trail,
- " is inside ",
- " are inside "));
- }
- else
- {
- var_append_temp (vars, " and ");
- var_print_object (game, trail);
- var_append_temp (vars, " are inside");
- }
-
- /* Print out the container. */
- if (!supporting)
- {
- var_append_temp (vars, " ");
- var_print_object_np (game, associate);
- }
- var_append_temp (vars, ".");
- }
- else
- {
- if (supporting)
- var_append_temp (vars, ".");
- }
+var_list_onin_object(sc_gameref_t game, sc_int associate) {
+ const sc_var_setref_t vars = gs_get_vars(game);
+ sc_int object, count, trail;
+ sc_bool supporting;
+
+ /* List out the objects standing on this object. */
+ count = 0;
+ trail = -1;
+ supporting = FALSE;
+ for (object = 0; object < gs_object_count(game); object++) {
+ /* Standing on? */
+ if (gs_object_position(game, object) == OBJ_ON_OBJECT
+ && gs_object_parent(game, object) == associate) {
+ if (count > 0) {
+ if (count > 1)
+ var_append_temp(vars, ", ");
+
+ /* Print out the current list object. */
+ var_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ var_print_object(game, trail);
+ var_append_temp(vars,
+ var_select_plurality(game, trail,
+ " is on ", " are on "));
+ } else {
+ var_append_temp(vars, " and ");
+ var_print_object(game, trail);
+ var_append_temp(vars, " are on ");
+ }
+
+ /* Print out the surface. */
+ var_print_object_np(game, associate);
+ supporting = TRUE;
+ }
+
+ /* List out the objects contained in this object. */
+ count = 0;
+ trail = -1;
+ for (object = 0; object < gs_object_count(game); object++) {
+ /* Contained? */
+ if (gs_object_position(game, object) == OBJ_IN_OBJECT
+ && gs_object_parent(game, object) == associate) {
+ if (count > 0) {
+ if (count == 1) {
+ if (supporting)
+ var_append_temp(vars, ", and ");
+ } else
+ var_append_temp(vars, ", ");
+
+ /* Print out the current list object. */
+ var_print_object(game, trail);
+ }
+ trail = object;
+ count++;
+ }
+ }
+ if (count >= 1) {
+ /* Print out final listed object. */
+ if (count == 1) {
+ if (supporting)
+ var_append_temp(vars, ", and ");
+ var_print_object(game, trail);
+ var_append_temp(vars,
+ var_select_plurality(game, trail,
+ " is inside ",
+ " are inside "));
+ } else {
+ var_append_temp(vars, " and ");
+ var_print_object(game, trail);
+ var_append_temp(vars, " are inside");
+ }
+
+ /* Print out the container. */
+ if (!supporting) {
+ var_append_temp(vars, " ");
+ var_print_object_np(game, associate);
+ }
+ var_append_temp(vars, ".");
+ } else {
+ if (supporting)
+ var_append_temp(vars, ".");
+ }
}
@@ -764,19 +686,17 @@ var_list_onin_object (sc_gameref_t game, sc_int associate)
* return value field, and always return TRUE. A macro was tempting here...
*/
static sc_bool
-var_return_integer (sc_int value, sc_int *type, sc_vartype_t *vt_rvalue)
-{
- *type = VAR_INTEGER;
- vt_rvalue->integer = value;
- return TRUE;
+var_return_integer(sc_int value, sc_int *type, sc_vartype_t *vt_rvalue) {
+ *type = VAR_INTEGER;
+ vt_rvalue->integer = value;
+ return TRUE;
}
static sc_bool
-var_return_string (const sc_char *value, sc_int *type, sc_vartype_t *vt_rvalue)
-{
- *type = VAR_STRING;
- vt_rvalue->string = value;
- return TRUE;
+var_return_string(const sc_char *value, sc_int *type, sc_vartype_t *vt_rvalue) {
+ *type = VAR_STRING;
+ vt_rvalue->string = value;
+ return TRUE;
}
@@ -787,698 +707,614 @@ var_return_string (const sc_char *value, sc_int *type, sc_vartype_t *vt_rvalue)
* if invalid name passed in. Uses var_return_*() to reduce code untidiness.
*/
static sc_bool
-var_get_system (sc_var_setref_t vars,
- const sc_char *name, sc_int *type, sc_vartype_t *vt_rvalue)
-{
- const sc_prop_setref_t bundle = vars->bundle;
- const sc_gameref_t game = vars->game;
-
- /* Check name for known system variables. */
- if (strcmp (name, "author") == 0)
- {
- sc_vartype_t vt_key[2];
- const sc_char *author;
-
- /* Get and return the global gameauthor string. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameAuthor";
- author = prop_get_string (bundle, "S<-ss", vt_key);
- if (sc_strempty (author))
- author = "[Author unknown]";
-
- return var_return_string (author, type, vt_rvalue);
- }
-
- else if (strcmp (name, "character") == 0)
- {
- /* See if there is a referenced character. */
- if (vars->referenced_character != -1)
- {
- sc_vartype_t vt_key[3];
- const sc_char *npc_name;
-
- /* Return the character name string. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = vars->referenced_character;
- vt_key[2].string = "Name";
- npc_name = prop_get_string (bundle, "S<-sis", vt_key);
- if (sc_strempty (npc_name))
- npc_name = "[Character unknown]";
-
- return var_return_string (npc_name, type, vt_rvalue);
- }
- else
- {
- sc_error ("var_get_system: no referenced character yet\n");
- return var_return_string ("[Character unknown]", type, vt_rvalue);
- }
- }
-
- else if (strcmp (name, "heshe") == 0 || strcmp (name, "himher") == 0)
- {
- /* See if there is a referenced character. */
- if (vars->referenced_character != -1)
- {
- sc_vartype_t vt_key[3];
- sc_int gender;
- const sc_char *retval;
-
- /* Return the appropriate character gender string. */
- vt_key[0].string = "NPCs";
- vt_key[1].integer = vars->referenced_character;
- vt_key[2].string = "Gender";
- gender = prop_get_integer (bundle, "I<-sis", vt_key);
- switch (gender)
- {
- case NPC_MALE:
- retval = (strcmp (name, "heshe") == 0) ? "he" : "him";
- break;
- case NPC_FEMALE:
- retval = (strcmp (name, "heshe") == 0) ? "she" : "her";
- break;
- case NPC_NEUTER:
- retval = "it";
- break;
-
- default:
- sc_error ("var_get_system: unknown gender, %ld\n", gender);
- retval = "[Gender unknown]";
- break;
- }
- return var_return_string (retval, type, vt_rvalue);
- }
- else
- {
- sc_error ("var_get_system: no referenced character yet\n");
- return var_return_string ("[Gender unknown]", type, vt_rvalue);
- }
- }
-
- else if (strncmp (name, "in_", 3) == 0)
- {
- sc_int saved_ref_object = vars->referenced_object;
-
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for in_\n");
- return var_return_string ("[In_ unavailable]", type, vt_rvalue);
- }
- if (!uip_match ("%object%", name + 3, game))
- {
- sc_error ("var_get_system: invalid object for in_\n");
- return var_return_string ("[In_ unavailable]", type, vt_rvalue);
- }
-
- /* Clear any current temporary for appends. */
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, 1);
- strcpy (vars->temporary, "");
-
- /* Write what's in the object into temporary. */
- var_list_in_object (game, vars->referenced_object);
-
- /* Restore saved referenced object and return. */
- vars->referenced_object = saved_ref_object;
- return var_return_string (vars->temporary, type, vt_rvalue);
- }
-
- else if (strcmp (name, "maxscore") == 0)
- {
- sc_vartype_t vt_key[2];
- sc_int maxscore;
-
- /* Return the maximum score. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "MaxScore";
- maxscore = prop_get_integer (bundle, "I<-ss", vt_key);
-
- return var_return_integer (maxscore, type, vt_rvalue);
- }
-
- else if (strcmp (name, "modified") == 0)
- {
- sc_vartype_t vt_key;
- const sc_char *compiledate;
-
- /* Return the game compilation date. */
- vt_key.string = "CompileDate";
- compiledate = prop_get_string (bundle, "S<-s", &vt_key);
- if (sc_strempty (compiledate))
- compiledate = "[Modified unknown]";
-
- return var_return_string (compiledate, type, vt_rvalue);
- }
-
- else if (strcmp (name, "number") == 0)
- {
- /* Return the referenced number, or 0 if none yet. */
- if (!vars->is_number_referenced)
- sc_error ("var_get_system: no referenced number yet\n");
-
- return var_return_integer (vars->referenced_number, type, vt_rvalue);
- }
-
- else if (strcmp (name, "object") == 0)
- {
- /* See if we have a referenced object yet. */
- if (vars->referenced_object != -1)
- {
- /* Return object name with its prefix. */
- sc_vartype_t vt_key[3];
- const sc_char *prefix, *objname;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = vars->referenced_object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
-
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, strlen (prefix) + 1);
- strcpy (vars->temporary, prefix);
-
- vt_key[2].string = "Short";
- objname = prop_get_string (bundle, "S<-sis", vt_key);
-
- vars->temporary = (sc_char *)sc_realloc (vars->temporary,
- strlen (vars->temporary)
- + strlen (objname) + 2);
- strcat (vars->temporary, " ");
- strcat (vars->temporary, objname);
-
- return var_return_string (vars->temporary, type, vt_rvalue);
- }
- else
- {
- sc_error ("var_get_system: no referenced object yet\n");
- return var_return_string ("[Object unknown]", type, vt_rvalue);
- }
- }
-
- else if (strcmp (name, "obstate") == 0)
- {
- sc_vartype_t vt_key[3];
- sc_bool is_statussed;
- sc_char *state;
-
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for obstate\n");
- return var_return_string ("[Obstate unavailable]", type, vt_rvalue);
- }
- if (vars->referenced_object == -1)
- {
- sc_error ("var_get_system: no object for obstate\n");
- return var_return_string ("[Obstate unavailable]", type, vt_rvalue);
- }
-
- /*
- * If not a stateful object, Runner 4.0.45 crashes; we'll do something
- * different here.
- */
- vt_key[0].string = "Objects";
- vt_key[1].integer = vars->referenced_object;
- vt_key[2].string = "CurrentState";
- is_statussed = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- if (!is_statussed)
- return var_return_string ("stateless", type, vt_rvalue);
-
- /* Get state, and copy to temporary. */
- state = obj_state_name (game, vars->referenced_object);
- if (!state)
- {
- sc_error ("var_get_system: invalid state for obstate\n");
- return var_return_string ("[Obstate unknown]", type, vt_rvalue);
- }
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, strlen (state) + 1);
- strcpy (vars->temporary, state);
- sc_free (state);
-
- /* Return temporary. */
- return var_return_string (vars->temporary, type, vt_rvalue);
- }
-
- else if (strcmp (name, "obstatus") == 0)
- {
- sc_vartype_t vt_key[3];
- sc_bool is_openable;
- sc_int openness;
- const sc_char *retval;
-
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for obstatus\n");
- return var_return_string ("[Obstatus unavailable]", type, vt_rvalue);
- }
- if (vars->referenced_object == -1)
- {
- sc_error ("var_get_system: no object for obstatus\n");
- return var_return_string ("[Obstatus unavailable]", type, vt_rvalue);
- }
-
- /* If not an openable object, return unopenable to match Adrift. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = vars->referenced_object;
- vt_key[2].string = "Openable";
- is_openable = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- if (!is_openable)
- return var_return_string ("unopenable", type, vt_rvalue);
-
- /* Return one of open, closed, or locked. */
- openness = gs_object_openness (game, vars->referenced_object);
- switch (openness)
- {
- case OBJ_OPEN:
- retval = "open";
- break;
- case OBJ_CLOSED:
- retval = "closed";
- break;
- case OBJ_LOCKED:
- retval = "locked";
- break;
- default:
- retval = "[Obstatus unknown]";
- break;
- }
- return var_return_string (retval, type, vt_rvalue);
- }
-
- else if (strncmp (name, "on_", 3) == 0)
- {
- sc_int saved_ref_object = vars->referenced_object;
-
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for on_\n");
- return var_return_string ("[On_ unavailable]", type, vt_rvalue);
- }
- if (!uip_match ("%object%", name + 3, game))
- {
- sc_error ("var_get_system: invalid object for on_\n");
- return var_return_string ("[On_ unavailable]", type, vt_rvalue);
- }
-
- /* Clear any current temporary for appends. */
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, 1);
- strcpy (vars->temporary, "");
-
- /* Write what's on the object into temporary. */
- var_list_on_object (game, vars->referenced_object);
-
- /* Restore saved referenced object and return. */
- vars->referenced_object = saved_ref_object;
- return var_return_string (vars->temporary, type, vt_rvalue);
- }
-
- else if (strncmp (name, "onin_", 5) == 0)
- {
- sc_int saved_ref_object = vars->referenced_object;
-
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for onin_\n");
- return var_return_string ("[Onin_ unavailable]", type, vt_rvalue);
- }
- if (!uip_match ("%object%", name + 5, game))
- {
- sc_error ("var_get_system: invalid object for onin_\n");
- return var_return_string ("[Onin_ unavailable]", type, vt_rvalue);
- }
-
- /* Clear any current temporary for appends. */
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, 1);
- strcpy (vars->temporary, "");
-
- /* Write what's on/in the object into temporary. */
- var_list_onin_object (game, vars->referenced_object);
-
- /* Restore saved referenced object and return. */
- vars->referenced_object = saved_ref_object;
- return var_return_string (vars->temporary, type, vt_rvalue);
- }
-
- else if (strcmp (name, "player") == 0)
- {
- sc_vartype_t vt_key[2];
- const sc_char *playername;
-
- /*
- * Return player's name from properties, or just "Player" if not set
- * in the properties.
- */
- vt_key[0].string = "Globals";
- vt_key[1].string = "PlayerName";
- playername = prop_get_string (bundle, "S<-ss", vt_key);
- if (sc_strempty (playername))
- playername = "Player";
-
- return var_return_string (playername, type, vt_rvalue);
- }
-
- else if (strcmp (name, "room") == 0)
- {
- const sc_char *roomname;
-
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for room\n");
- return var_return_string ("[Room unavailable]", type, vt_rvalue);
- }
-
- /* Return the current player room. */
- roomname = lib_get_room_name (game, gs_playerroom (game));
- return var_return_string (roomname, type, vt_rvalue);
- }
-
- else if (strcmp (name, "score") == 0)
- {
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for score\n");
- return var_return_integer (0, type, vt_rvalue);
- }
-
- /* Return the current game score. */
- return var_return_integer (game->score, type, vt_rvalue);
- }
-
- else if (strncmp (name, "state_", 6) == 0)
- {
- sc_int saved_ref_object = vars->referenced_object;
- sc_vartype_t vt_key[3];
- sc_bool is_statussed;
- sc_char *state;
-
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for state_\n");
- return var_return_string ("[State_ unavailable]", type, vt_rvalue);
- }
- if (!uip_match ("%object%", name + 6, game))
- {
- sc_error ("var_get_system: invalid object for state_\n");
- return var_return_string ("[State_ unavailable]", type, vt_rvalue);
- }
-
- /* Verify this is a stateful object. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = vars->referenced_object;
- vt_key[2].string = "CurrentState";
- is_statussed = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- if (!is_statussed)
- {
- vars->referenced_object = saved_ref_object;
- sc_error ("var_get_system: stateless object for state_\n");
- return var_return_string ("[State_ unavailable]", type, vt_rvalue);
- }
-
- /* Get state, and copy to temporary. */
- state = obj_state_name (game, vars->referenced_object);
- if (!state)
- {
- vars->referenced_object = saved_ref_object;
- sc_error ("var_get_system: invalid state for state_\n");
- return var_return_string ("[State_ unknown]", type, vt_rvalue);
- }
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, strlen (state) + 1);
- strcpy (vars->temporary, state);
- sc_free (state);
-
- /* Restore saved referenced object and return. */
- vars->referenced_object = saved_ref_object;
- return var_return_string (vars->temporary, type, vt_rvalue);
- }
-
- else if (strncmp (name, "status_", 7) == 0)
- {
- sc_int saved_ref_object = vars->referenced_object;
- sc_vartype_t vt_key[3];
- sc_bool is_openable;
- sc_int openness;
- const sc_char *retval;
-
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for status_\n");
- return var_return_string ("[Status_ unavailable]", type, vt_rvalue);
- }
- if (!uip_match ("%object%", name + 7, game))
- {
- sc_error ("var_get_system: invalid object for status_\n");
- return var_return_string ("[Status_ unavailable]", type, vt_rvalue);
- }
-
- /* Verify this is an openable object. */
- vt_key[0].string = "Objects";
- vt_key[1].integer = vars->referenced_object;
- vt_key[2].string = "Openable";
- is_openable = prop_get_integer (bundle, "I<-sis", vt_key) != 0;
- if (!is_openable)
- {
- vars->referenced_object = saved_ref_object;
- sc_error ("var_get_system: stateless object for status_\n");
- return var_return_string ("[Status_ unavailable]", type, vt_rvalue);
- }
-
- /* Return one of open, closed, or locked. */
- openness = gs_object_openness (game, vars->referenced_object);
- switch (openness)
- {
- case OBJ_OPEN:
- retval = "open";
- break;
- case OBJ_CLOSED:
- retval = "closed";
- break;
- case OBJ_LOCKED:
- retval = "locked";
- break;
- default:
- retval = "[Status_ unknown]";
- break;
- }
-
- /* Restore saved referenced object and return. */
- vars->referenced_object = saved_ref_object;
- return var_return_string (retval, type, vt_rvalue);
- }
-
- else if (strcmp (name, "t_number") == 0)
- {
- /* See if we have a referenced number yet. */
- if (vars->is_number_referenced)
- {
- sc_int number;
- const sc_char *retval;
-
- /* Return the referenced number as a string. */
- number = vars->referenced_number;
- if (number >= 0 && number < VAR_NUMBERS_SIZE)
- retval = VAR_NUMBERS[number];
- else
- {
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, 32);
- sprintf (vars->temporary, "%ld", number);
- retval = vars->temporary;
- }
-
- return var_return_string (retval, type, vt_rvalue);
- }
- else
- {
- sc_error ("var_get_system: no referenced number yet\n");
- return var_return_string ("[Number unknown]", type, vt_rvalue);
- }
- }
-
- else if (strncmp (name, "t_", 2) == 0)
- {
- sc_varref_t var;
-
- /* Find the variable; must be a user, not a system, one. */
- var = var_find (vars, name + 2);
- if (!var)
- {
- sc_error ("var_get_system:"
- " no such variable, %s\n", name + 2);
- return var_return_string ("[Unknown variable]", type, vt_rvalue);
- }
- else if (var->type != VAR_INTEGER)
- {
- sc_error ("var_get_system:"
- " not an integer variable, %s\n", name + 2);
- return var_return_string (var->value.string, type, vt_rvalue);
- }
- else
- {
- sc_int number;
- const sc_char *retval;
-
- /* Return the variable value as a string. */
- number = var->value.integer;
- if (number >= 0 && number < VAR_NUMBERS_SIZE)
- retval = VAR_NUMBERS[number];
- else
- {
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, 32);
- sprintf (vars->temporary, "%ld", number);
- retval = vars->temporary;
- }
-
- return var_return_string (retval, type, vt_rvalue);
- }
- }
-
- else if (strcmp (name, "text") == 0)
- {
- const sc_char *retval;
-
- /* Return any referenced text, otherwise a neutral string. */
- if (vars->referenced_text)
- retval = vars->referenced_text;
- else
- {
- sc_error ("var_get_system: no text yet to reference\n");
- retval = "[Text unknown]";
- }
-
- return var_return_string (retval, type, vt_rvalue);
- }
-
- else if (strcmp (name, "theobject") == 0)
- {
- /* See if we have a referenced object yet. */
- if (vars->referenced_object != -1)
- {
- /* Return object name prefixed with "the"... */
- sc_vartype_t vt_key[3];
- const sc_char *prefix, *normalized, *objname;
-
- vt_key[0].string = "Objects";
- vt_key[1].integer = vars->referenced_object;
- vt_key[2].string = "Prefix";
- prefix = prop_get_string (bundle, "S<-sis", vt_key);
-
- vars->temporary = (sc_char *)sc_realloc (vars->temporary, strlen (prefix) + 5);
- strcpy (vars->temporary, "");
-
- normalized = prefix;
- if (sc_compare_word (prefix, "a", 1))
- {
- strcat (vars->temporary, "the");
- normalized = prefix + 1;
- }
- else if (sc_compare_word (prefix, "an", 2))
- {
- strcat (vars->temporary, "the");
- normalized = prefix + 2;
- }
- else if (sc_compare_word (prefix, "the", 3))
- {
- strcat (vars->temporary, "the");
- normalized = prefix + 3;
- }
- else if (sc_compare_word (prefix, "some", 4))
- {
- strcat (vars->temporary, "the");
- normalized = prefix + 4;
- }
- else if (sc_strempty (prefix))
- strcat (vars->temporary, "the ");
-
- if (!sc_strempty (normalized))
- {
- strcat (vars->temporary, normalized);
- strcat (vars->temporary, " ");
- }
- else if (normalized > prefix)
- strcat (vars->temporary, " ");
-
- vt_key[2].string = "Short";
- objname = prop_get_string (bundle, "S<-sis", vt_key);
- if (sc_compare_word (objname, "a", 1))
- objname += 1;
- else if (sc_compare_word (objname, "an", 2))
- objname += 2;
- else if (sc_compare_word (objname, "the", 3))
- objname += 3;
- else if (sc_compare_word (objname, "some", 4))
- objname += 4;
-
- vars->temporary = (sc_char *)sc_realloc (vars->temporary,
- strlen (vars->temporary)
- + strlen (objname) + 1);
- strcat (vars->temporary, objname);
-
- return var_return_string (vars->temporary, type, vt_rvalue);
- }
- else
- {
- sc_error ("var_get_system: no referenced object yet\n");
- return var_return_string ("[Object unknown]", type, vt_rvalue);
- }
- }
-
- else if (strcmp (name, "time") == 0)
- {
- double delta;
- sc_int retval;
-
- /* Return the elapsed game time in seconds. */
- delta = vars->timestamp - (g_vm->_events->getTotalPlayTicks() / 1000);
- retval = (sc_int) delta + vars->time_offset;
-
- return var_return_integer (retval, type, vt_rvalue);
- }
-
- else if (strcmp (name, "title") == 0)
- {
- sc_vartype_t vt_key[2];
- const sc_char *gamename;
-
- /* Return the game's title. */
- vt_key[0].string = "Globals";
- vt_key[1].string = "GameName";
- gamename = prop_get_string (bundle, "S<-ss", vt_key);
- if (sc_strempty (gamename))
- gamename = "[Title unknown]";
-
- return var_return_string (gamename, type, vt_rvalue);
- }
-
- else if (strcmp (name, "turns") == 0)
- {
- /* Check there's enough information to return a value. */
- if (!game)
- {
- sc_error ("var_get_system: no game for turns\n");
- return var_return_integer (0, type, vt_rvalue);
- }
-
- /* Return the count of game turns. */
- return var_return_integer (game->turns, type, vt_rvalue);
- }
-
- else if (strcmp (name, "version") == 0)
- {
- /* Return the Adrift emulation level of SCARE. */
- return var_return_integer (SCARE_EMULATION, type, vt_rvalue);
- }
-
- else if (strcmp (name, "scare_version") == 0)
- {
- /* Private system variable, return SCARE's version number. */
- return var_return_integer (var_get_scare_version (), type, vt_rvalue);
- }
-
- return FALSE;
+var_get_system(sc_var_setref_t vars,
+ const sc_char *name, sc_int *type, sc_vartype_t *vt_rvalue) {
+ const sc_prop_setref_t bundle = vars->bundle;
+ const sc_gameref_t game = vars->game;
+
+ /* Check name for known system variables. */
+ if (strcmp(name, "author") == 0) {
+ sc_vartype_t vt_key[2];
+ const sc_char *author;
+
+ /* Get and return the global gameauthor string. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameAuthor";
+ author = prop_get_string(bundle, "S<-ss", vt_key);
+ if (sc_strempty(author))
+ author = "[Author unknown]";
+
+ return var_return_string(author, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "character") == 0) {
+ /* See if there is a referenced character. */
+ if (vars->referenced_character != -1) {
+ sc_vartype_t vt_key[3];
+ const sc_char *npc_name;
+
+ /* Return the character name string. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = vars->referenced_character;
+ vt_key[2].string = "Name";
+ npc_name = prop_get_string(bundle, "S<-sis", vt_key);
+ if (sc_strempty(npc_name))
+ npc_name = "[Character unknown]";
+
+ return var_return_string(npc_name, type, vt_rvalue);
+ } else {
+ sc_error("var_get_system: no referenced character yet\n");
+ return var_return_string("[Character unknown]", type, vt_rvalue);
+ }
+ }
+
+ else if (strcmp(name, "heshe") == 0 || strcmp(name, "himher") == 0) {
+ /* See if there is a referenced character. */
+ if (vars->referenced_character != -1) {
+ sc_vartype_t vt_key[3];
+ sc_int gender;
+ const sc_char *retval;
+
+ /* Return the appropriate character gender string. */
+ vt_key[0].string = "NPCs";
+ vt_key[1].integer = vars->referenced_character;
+ vt_key[2].string = "Gender";
+ gender = prop_get_integer(bundle, "I<-sis", vt_key);
+ switch (gender) {
+ case NPC_MALE:
+ retval = (strcmp(name, "heshe") == 0) ? "he" : "him";
+ break;
+ case NPC_FEMALE:
+ retval = (strcmp(name, "heshe") == 0) ? "she" : "her";
+ break;
+ case NPC_NEUTER:
+ retval = "it";
+ break;
+
+ default:
+ sc_error("var_get_system: unknown gender, %ld\n", gender);
+ retval = "[Gender unknown]";
+ break;
+ }
+ return var_return_string(retval, type, vt_rvalue);
+ } else {
+ sc_error("var_get_system: no referenced character yet\n");
+ return var_return_string("[Gender unknown]", type, vt_rvalue);
+ }
+ }
+
+ else if (strncmp(name, "in_", 3) == 0) {
+ sc_int saved_ref_object = vars->referenced_object;
+
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for in_\n");
+ return var_return_string("[In_ unavailable]", type, vt_rvalue);
+ }
+ if (!uip_match("%object%", name + 3, game)) {
+ sc_error("var_get_system: invalid object for in_\n");
+ return var_return_string("[In_ unavailable]", type, vt_rvalue);
+ }
+
+ /* Clear any current temporary for appends. */
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, 1);
+ strcpy(vars->temporary, "");
+
+ /* Write what's in the object into temporary. */
+ var_list_in_object(game, vars->referenced_object);
+
+ /* Restore saved referenced object and return. */
+ vars->referenced_object = saved_ref_object;
+ return var_return_string(vars->temporary, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "maxscore") == 0) {
+ sc_vartype_t vt_key[2];
+ sc_int maxscore;
+
+ /* Return the maximum score. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "MaxScore";
+ maxscore = prop_get_integer(bundle, "I<-ss", vt_key);
+
+ return var_return_integer(maxscore, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "modified") == 0) {
+ sc_vartype_t vt_key;
+ const sc_char *compiledate;
+
+ /* Return the game compilation date. */
+ vt_key.string = "CompileDate";
+ compiledate = prop_get_string(bundle, "S<-s", &vt_key);
+ if (sc_strempty(compiledate))
+ compiledate = "[Modified unknown]";
+
+ return var_return_string(compiledate, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "number") == 0) {
+ /* Return the referenced number, or 0 if none yet. */
+ if (!vars->is_number_referenced)
+ sc_error("var_get_system: no referenced number yet\n");
+
+ return var_return_integer(vars->referenced_number, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "object") == 0) {
+ /* See if we have a referenced object yet. */
+ if (vars->referenced_object != -1) {
+ /* Return object name with its prefix. */
+ sc_vartype_t vt_key[3];
+ const sc_char *prefix, *objname;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = vars->referenced_object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, strlen(prefix) + 1);
+ strcpy(vars->temporary, prefix);
+
+ vt_key[2].string = "Short";
+ objname = prop_get_string(bundle, "S<-sis", vt_key);
+
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary,
+ strlen(vars->temporary)
+ + strlen(objname) + 2);
+ strcat(vars->temporary, " ");
+ strcat(vars->temporary, objname);
+
+ return var_return_string(vars->temporary, type, vt_rvalue);
+ } else {
+ sc_error("var_get_system: no referenced object yet\n");
+ return var_return_string("[Object unknown]", type, vt_rvalue);
+ }
+ }
+
+ else if (strcmp(name, "obstate") == 0) {
+ sc_vartype_t vt_key[3];
+ sc_bool is_statussed;
+ sc_char *state;
+
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for obstate\n");
+ return var_return_string("[Obstate unavailable]", type, vt_rvalue);
+ }
+ if (vars->referenced_object == -1) {
+ sc_error("var_get_system: no object for obstate\n");
+ return var_return_string("[Obstate unavailable]", type, vt_rvalue);
+ }
+
+ /*
+ * If not a stateful object, Runner 4.0.45 crashes; we'll do something
+ * different here.
+ */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = vars->referenced_object;
+ vt_key[2].string = "CurrentState";
+ is_statussed = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ if (!is_statussed)
+ return var_return_string("stateless", type, vt_rvalue);
+
+ /* Get state, and copy to temporary. */
+ state = obj_state_name(game, vars->referenced_object);
+ if (!state) {
+ sc_error("var_get_system: invalid state for obstate\n");
+ return var_return_string("[Obstate unknown]", type, vt_rvalue);
+ }
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, strlen(state) + 1);
+ strcpy(vars->temporary, state);
+ sc_free(state);
+
+ /* Return temporary. */
+ return var_return_string(vars->temporary, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "obstatus") == 0) {
+ sc_vartype_t vt_key[3];
+ sc_bool is_openable;
+ sc_int openness;
+ const sc_char *retval;
+
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for obstatus\n");
+ return var_return_string("[Obstatus unavailable]", type, vt_rvalue);
+ }
+ if (vars->referenced_object == -1) {
+ sc_error("var_get_system: no object for obstatus\n");
+ return var_return_string("[Obstatus unavailable]", type, vt_rvalue);
+ }
+
+ /* If not an openable object, return unopenable to match Adrift. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = vars->referenced_object;
+ vt_key[2].string = "Openable";
+ is_openable = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ if (!is_openable)
+ return var_return_string("unopenable", type, vt_rvalue);
+
+ /* Return one of open, closed, or locked. */
+ openness = gs_object_openness(game, vars->referenced_object);
+ switch (openness) {
+ case OBJ_OPEN:
+ retval = "open";
+ break;
+ case OBJ_CLOSED:
+ retval = "closed";
+ break;
+ case OBJ_LOCKED:
+ retval = "locked";
+ break;
+ default:
+ retval = "[Obstatus unknown]";
+ break;
+ }
+ return var_return_string(retval, type, vt_rvalue);
+ }
+
+ else if (strncmp(name, "on_", 3) == 0) {
+ sc_int saved_ref_object = vars->referenced_object;
+
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for on_\n");
+ return var_return_string("[On_ unavailable]", type, vt_rvalue);
+ }
+ if (!uip_match("%object%", name + 3, game)) {
+ sc_error("var_get_system: invalid object for on_\n");
+ return var_return_string("[On_ unavailable]", type, vt_rvalue);
+ }
+
+ /* Clear any current temporary for appends. */
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, 1);
+ strcpy(vars->temporary, "");
+
+ /* Write what's on the object into temporary. */
+ var_list_on_object(game, vars->referenced_object);
+
+ /* Restore saved referenced object and return. */
+ vars->referenced_object = saved_ref_object;
+ return var_return_string(vars->temporary, type, vt_rvalue);
+ }
+
+ else if (strncmp(name, "onin_", 5) == 0) {
+ sc_int saved_ref_object = vars->referenced_object;
+
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for onin_\n");
+ return var_return_string("[Onin_ unavailable]", type, vt_rvalue);
+ }
+ if (!uip_match("%object%", name + 5, game)) {
+ sc_error("var_get_system: invalid object for onin_\n");
+ return var_return_string("[Onin_ unavailable]", type, vt_rvalue);
+ }
+
+ /* Clear any current temporary for appends. */
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, 1);
+ strcpy(vars->temporary, "");
+
+ /* Write what's on/in the object into temporary. */
+ var_list_onin_object(game, vars->referenced_object);
+
+ /* Restore saved referenced object and return. */
+ vars->referenced_object = saved_ref_object;
+ return var_return_string(vars->temporary, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "player") == 0) {
+ sc_vartype_t vt_key[2];
+ const sc_char *playername;
+
+ /*
+ * Return player's name from properties, or just "Player" if not set
+ * in the properties.
+ */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "PlayerName";
+ playername = prop_get_string(bundle, "S<-ss", vt_key);
+ if (sc_strempty(playername))
+ playername = "Player";
+
+ return var_return_string(playername, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "room") == 0) {
+ const sc_char *roomname;
+
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for room\n");
+ return var_return_string("[Room unavailable]", type, vt_rvalue);
+ }
+
+ /* Return the current player room. */
+ roomname = lib_get_room_name(game, gs_playerroom(game));
+ return var_return_string(roomname, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "score") == 0) {
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for score\n");
+ return var_return_integer(0, type, vt_rvalue);
+ }
+
+ /* Return the current game score. */
+ return var_return_integer(game->score, type, vt_rvalue);
+ }
+
+ else if (strncmp(name, "state_", 6) == 0) {
+ sc_int saved_ref_object = vars->referenced_object;
+ sc_vartype_t vt_key[3];
+ sc_bool is_statussed;
+ sc_char *state;
+
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for state_\n");
+ return var_return_string("[State_ unavailable]", type, vt_rvalue);
+ }
+ if (!uip_match("%object%", name + 6, game)) {
+ sc_error("var_get_system: invalid object for state_\n");
+ return var_return_string("[State_ unavailable]", type, vt_rvalue);
+ }
+
+ /* Verify this is a stateful object. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = vars->referenced_object;
+ vt_key[2].string = "CurrentState";
+ is_statussed = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ if (!is_statussed) {
+ vars->referenced_object = saved_ref_object;
+ sc_error("var_get_system: stateless object for state_\n");
+ return var_return_string("[State_ unavailable]", type, vt_rvalue);
+ }
+
+ /* Get state, and copy to temporary. */
+ state = obj_state_name(game, vars->referenced_object);
+ if (!state) {
+ vars->referenced_object = saved_ref_object;
+ sc_error("var_get_system: invalid state for state_\n");
+ return var_return_string("[State_ unknown]", type, vt_rvalue);
+ }
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, strlen(state) + 1);
+ strcpy(vars->temporary, state);
+ sc_free(state);
+
+ /* Restore saved referenced object and return. */
+ vars->referenced_object = saved_ref_object;
+ return var_return_string(vars->temporary, type, vt_rvalue);
+ }
+
+ else if (strncmp(name, "status_", 7) == 0) {
+ sc_int saved_ref_object = vars->referenced_object;
+ sc_vartype_t vt_key[3];
+ sc_bool is_openable;
+ sc_int openness;
+ const sc_char *retval;
+
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for status_\n");
+ return var_return_string("[Status_ unavailable]", type, vt_rvalue);
+ }
+ if (!uip_match("%object%", name + 7, game)) {
+ sc_error("var_get_system: invalid object for status_\n");
+ return var_return_string("[Status_ unavailable]", type, vt_rvalue);
+ }
+
+ /* Verify this is an openable object. */
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = vars->referenced_object;
+ vt_key[2].string = "Openable";
+ is_openable = prop_get_integer(bundle, "I<-sis", vt_key) != 0;
+ if (!is_openable) {
+ vars->referenced_object = saved_ref_object;
+ sc_error("var_get_system: stateless object for status_\n");
+ return var_return_string("[Status_ unavailable]", type, vt_rvalue);
+ }
+
+ /* Return one of open, closed, or locked. */
+ openness = gs_object_openness(game, vars->referenced_object);
+ switch (openness) {
+ case OBJ_OPEN:
+ retval = "open";
+ break;
+ case OBJ_CLOSED:
+ retval = "closed";
+ break;
+ case OBJ_LOCKED:
+ retval = "locked";
+ break;
+ default:
+ retval = "[Status_ unknown]";
+ break;
+ }
+
+ /* Restore saved referenced object and return. */
+ vars->referenced_object = saved_ref_object;
+ return var_return_string(retval, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "t_number") == 0) {
+ /* See if we have a referenced number yet. */
+ if (vars->is_number_referenced) {
+ sc_int number;
+ const sc_char *retval;
+
+ /* Return the referenced number as a string. */
+ number = vars->referenced_number;
+ if (number >= 0 && number < VAR_NUMBERS_SIZE)
+ retval = VAR_NUMBERS[number];
+ else {
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, 32);
+ sprintf(vars->temporary, "%ld", number);
+ retval = vars->temporary;
+ }
+
+ return var_return_string(retval, type, vt_rvalue);
+ } else {
+ sc_error("var_get_system: no referenced number yet\n");
+ return var_return_string("[Number unknown]", type, vt_rvalue);
+ }
+ }
+
+ else if (strncmp(name, "t_", 2) == 0) {
+ sc_varref_t var;
+
+ /* Find the variable; must be a user, not a system, one. */
+ var = var_find(vars, name + 2);
+ if (!var) {
+ sc_error("var_get_system:"
+ " no such variable, %s\n", name + 2);
+ return var_return_string("[Unknown variable]", type, vt_rvalue);
+ } else if (var->type != VAR_INTEGER) {
+ sc_error("var_get_system:"
+ " not an integer variable, %s\n", name + 2);
+ return var_return_string(var->value.string, type, vt_rvalue);
+ } else {
+ sc_int number;
+ const sc_char *retval;
+
+ /* Return the variable value as a string. */
+ number = var->value.integer;
+ if (number >= 0 && number < VAR_NUMBERS_SIZE)
+ retval = VAR_NUMBERS[number];
+ else {
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, 32);
+ sprintf(vars->temporary, "%ld", number);
+ retval = vars->temporary;
+ }
+
+ return var_return_string(retval, type, vt_rvalue);
+ }
+ }
+
+ else if (strcmp(name, "text") == 0) {
+ const sc_char *retval;
+
+ /* Return any referenced text, otherwise a neutral string. */
+ if (vars->referenced_text)
+ retval = vars->referenced_text;
+ else {
+ sc_error("var_get_system: no text yet to reference\n");
+ retval = "[Text unknown]";
+ }
+
+ return var_return_string(retval, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "theobject") == 0) {
+ /* See if we have a referenced object yet. */
+ if (vars->referenced_object != -1) {
+ /* Return object name prefixed with "the"... */
+ sc_vartype_t vt_key[3];
+ const sc_char *prefix, *normalized, *objname;
+
+ vt_key[0].string = "Objects";
+ vt_key[1].integer = vars->referenced_object;
+ vt_key[2].string = "Prefix";
+ prefix = prop_get_string(bundle, "S<-sis", vt_key);
+
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary, strlen(prefix) + 5);
+ strcpy(vars->temporary, "");
+
+ normalized = prefix;
+ if (sc_compare_word(prefix, "a", 1)) {
+ strcat(vars->temporary, "the");
+ normalized = prefix + 1;
+ } else if (sc_compare_word(prefix, "an", 2)) {
+ strcat(vars->temporary, "the");
+ normalized = prefix + 2;
+ } else if (sc_compare_word(prefix, "the", 3)) {
+ strcat(vars->temporary, "the");
+ normalized = prefix + 3;
+ } else if (sc_compare_word(prefix, "some", 4)) {
+ strcat(vars->temporary, "the");
+ normalized = prefix + 4;
+ } else if (sc_strempty(prefix))
+ strcat(vars->temporary, "the ");
+
+ if (!sc_strempty(normalized)) {
+ strcat(vars->temporary, normalized);
+ strcat(vars->temporary, " ");
+ } else if (normalized > prefix)
+ strcat(vars->temporary, " ");
+
+ vt_key[2].string = "Short";
+ objname = prop_get_string(bundle, "S<-sis", vt_key);
+ if (sc_compare_word(objname, "a", 1))
+ objname += 1;
+ else if (sc_compare_word(objname, "an", 2))
+ objname += 2;
+ else if (sc_compare_word(objname, "the", 3))
+ objname += 3;
+ else if (sc_compare_word(objname, "some", 4))
+ objname += 4;
+
+ vars->temporary = (sc_char *)sc_realloc(vars->temporary,
+ strlen(vars->temporary)
+ + strlen(objname) + 1);
+ strcat(vars->temporary, objname);
+
+ return var_return_string(vars->temporary, type, vt_rvalue);
+ } else {
+ sc_error("var_get_system: no referenced object yet\n");
+ return var_return_string("[Object unknown]", type, vt_rvalue);
+ }
+ }
+
+ else if (strcmp(name, "time") == 0) {
+ double delta;
+ sc_int retval;
+
+ /* Return the elapsed game time in seconds. */
+ delta = vars->timestamp - (g_vm->_events->getTotalPlayTicks() / 1000);
+ retval = (sc_int) delta + vars->time_offset;
+
+ return var_return_integer(retval, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "title") == 0) {
+ sc_vartype_t vt_key[2];
+ const sc_char *gamename;
+
+ /* Return the game's title. */
+ vt_key[0].string = "Globals";
+ vt_key[1].string = "GameName";
+ gamename = prop_get_string(bundle, "S<-ss", vt_key);
+ if (sc_strempty(gamename))
+ gamename = "[Title unknown]";
+
+ return var_return_string(gamename, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "turns") == 0) {
+ /* Check there's enough information to return a value. */
+ if (!game) {
+ sc_error("var_get_system: no game for turns\n");
+ return var_return_integer(0, type, vt_rvalue);
+ }
+
+ /* Return the count of game turns. */
+ return var_return_integer(game->turns, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "version") == 0) {
+ /* Return the Adrift emulation level of SCARE. */
+ return var_return_integer(SCARE_EMULATION, type, vt_rvalue);
+ }
+
+ else if (strcmp(name, "scare_version") == 0) {
+ /* Private system variable, return SCARE's version number. */
+ return var_return_integer(var_get_scare_version(), type, vt_rvalue);
+ }
+
+ return FALSE;
}
@@ -1489,35 +1325,32 @@ var_get_system (sc_var_setref_t vars,
* name passed in is not a defined user variable.
*/
static sc_bool
-var_get_user (sc_var_setref_t vars,
- const sc_char *name, sc_int *type, sc_vartype_t *vt_rvalue)
-{
- sc_varref_t var;
-
- /* Check user variables for a reference to the named variable. */
- var = var_find (vars, name);
- if (var)
- {
- /* Copy out variable details. */
- *type = var->type;
- switch (var->type)
- {
- case VAR_INTEGER:
- vt_rvalue->integer = var->value.integer;
- break;
- case VAR_STRING:
- vt_rvalue->string = var->value.string;
- break;
-
- default:
- sc_fatal ("var_get_user: invalid variable type, %ld\n", var->type);
- }
-
- /* Return success. */
- return TRUE;
- }
-
- return FALSE;
+var_get_user(sc_var_setref_t vars,
+ const sc_char *name, sc_int *type, sc_vartype_t *vt_rvalue) {
+ sc_varref_t var;
+
+ /* Check user variables for a reference to the named variable. */
+ var = var_find(vars, name);
+ if (var) {
+ /* Copy out variable details. */
+ *type = var->type;
+ switch (var->type) {
+ case VAR_INTEGER:
+ vt_rvalue->integer = var->value.integer;
+ break;
+ case VAR_STRING:
+ vt_rvalue->string = var->value.string;
+ break;
+
+ default:
+ sc_fatal("var_get_user: invalid variable type, %ld\n", var->type);
+ }
+
+ /* Return success. */
+ return TRUE;
+ }
+
+ return FALSE;
}
@@ -1528,47 +1361,42 @@ var_get_user (sc_var_setref_t vars,
* named variable does not exist.
*/
sc_bool
-var_get (sc_var_setref_t vars,
- const sc_char *name, sc_int *type, sc_vartype_t *vt_rvalue)
-{
- sc_bool status;
- assert (var_is_valid (vars));
- assert (name && type && vt_rvalue);
-
- /*
- * Check user and system variables for a reference to the name. User
- * variables take precedence over system ones; that is, they may override
- * them in a game.
- */
- status = var_get_user (vars, name, type, vt_rvalue);
- if (!status)
- status = var_get_system (vars, name, type, vt_rvalue);
-
- if (var_trace)
- {
- if (status)
- {
- sc_trace ("Variable: %%%s%% retrieved, ", name);
- switch (*type)
- {
- case VAR_INTEGER:
- sc_trace ("%ld", vt_rvalue->integer);
- break;
- case VAR_STRING:
- sc_trace ("\"%s\"", vt_rvalue->string);
- break;
-
- default:
- sc_trace ("Variable: invalid variable type, %ld\n", *type);
- break;
- }
- sc_trace ("\n");
- }
- else
- sc_trace ("Variable: \"%s\", no such variable\n", name);
- }
-
- return status;
+var_get(sc_var_setref_t vars,
+ const sc_char *name, sc_int *type, sc_vartype_t *vt_rvalue) {
+ sc_bool status;
+ assert(var_is_valid(vars));
+ assert(name && type && vt_rvalue);
+
+ /*
+ * Check user and system variables for a reference to the name. User
+ * variables take precedence over system ones; that is, they may override
+ * them in a game.
+ */
+ status = var_get_user(vars, name, type, vt_rvalue);
+ if (!status)
+ status = var_get_system(vars, name, type, vt_rvalue);
+
+ if (var_trace) {
+ if (status) {
+ sc_trace("Variable: %%%s%% retrieved, ", name);
+ switch (*type) {
+ case VAR_INTEGER:
+ sc_trace("%ld", vt_rvalue->integer);
+ break;
+ case VAR_STRING:
+ sc_trace("\"%s\"", vt_rvalue->string);
+ break;
+
+ default:
+ sc_trace("Variable: invalid variable type, %ld\n", *type);
+ break;
+ }
+ sc_trace("\n");
+ } else
+ sc_trace("Variable: \"%s\", no such variable\n", name);
+ }
+
+ return status;
}
@@ -1580,28 +1408,26 @@ var_get (sc_var_setref_t vars,
* an error for the variable not to exist or to have the wrong type.
*/
void
-var_put_integer (sc_var_setref_t vars, const sc_char *name, sc_int value)
-{
- sc_vartype_t vt_value;
- assert (var_is_valid (vars));
+var_put_integer(sc_var_setref_t vars, const sc_char *name, sc_int value) {
+ sc_vartype_t vt_value;
+ assert(var_is_valid(vars));
- vt_value.integer = value;
- var_put (vars, name, VAR_INTEGER, vt_value);
+ vt_value.integer = value;
+ var_put(vars, name, VAR_INTEGER, vt_value);
}
sc_int
-var_get_integer (sc_var_setref_t vars, const sc_char *name)
-{
- sc_vartype_t vt_rvalue;
- sc_int type;
- assert (var_is_valid (vars));
-
- if (!var_get (vars, name, &type, &vt_rvalue))
- sc_fatal ("var_get_integer: no such variable, %s\n", name);
- else if (type != VAR_INTEGER)
- sc_fatal ("var_get_integer: not an integer, %s\n", name);
-
- return vt_rvalue.integer;
+var_get_integer(sc_var_setref_t vars, const sc_char *name) {
+ sc_vartype_t vt_rvalue;
+ sc_int type;
+ assert(var_is_valid(vars));
+
+ if (!var_get(vars, name, &type, &vt_rvalue))
+ sc_fatal("var_get_integer: no such variable, %s\n", name);
+ else if (type != VAR_INTEGER)
+ sc_fatal("var_get_integer: not an integer, %s\n", name);
+
+ return vt_rvalue.integer;
}
@@ -1613,29 +1439,27 @@ var_get_integer (sc_var_setref_t vars, const sc_char *name)
* an error for the variable not to exist or to have the wrong type.
*/
void
-var_put_string (sc_var_setref_t vars,
- const sc_char *name, const sc_char *string)
-{
- sc_vartype_t vt_value;
- assert (var_is_valid (vars));
-
- vt_value.string = string;
- var_put (vars, name, VAR_STRING, vt_value);
+var_put_string(sc_var_setref_t vars,
+ const sc_char *name, const sc_char *string) {
+ sc_vartype_t vt_value;
+ assert(var_is_valid(vars));
+
+ vt_value.string = string;
+ var_put(vars, name, VAR_STRING, vt_value);
}
const sc_char *
-var_get_string (sc_var_setref_t vars, const sc_char *name)
-{
- sc_vartype_t vt_rvalue;
- sc_int type;
- assert (var_is_valid (vars));
-
- if (!var_get (vars, name, &type, &vt_rvalue))
- sc_fatal ("var_get_string: no such variable, %s\n", name);
- else if (type != VAR_STRING)
- sc_fatal ("var_get_string: not a string, %s\n", name);
-
- return vt_rvalue.string;
+var_get_string(sc_var_setref_t vars, const sc_char *name) {
+ sc_vartype_t vt_rvalue;
+ sc_int type;
+ assert(var_is_valid(vars));
+
+ if (!var_get(vars, name, &type, &vt_rvalue))
+ sc_fatal("var_get_string: no such variable, %s\n", name);
+ else if (type != VAR_STRING)
+ sc_fatal("var_get_string: not a string, %s\n", name);
+
+ return vt_rvalue.string;
}
@@ -1646,65 +1470,60 @@ var_get_string (sc_var_setref_t vars, const sc_char *name)
* properties bundle passed in.
*/
sc_var_setref_t
-var_create (sc_prop_setref_t bundle)
-{
- sc_var_setref_t vars;
- sc_int var_count, index_;
- sc_vartype_t vt_key[3];
- assert (bundle);
-
- /* Create a clean set of variables to fill from the bundle. */
- vars = var_create_empty ();
- vars->bundle = bundle;
-
- /* Retrieve the count of variables. */
- vt_key[0].string = "Variables";
- var_count = prop_get_child_count (bundle, "I<-s", vt_key);
-
- /* Create a variable for each variable property held. */
- for (index_ = 0; index_ < var_count; index_++)
- {
- const sc_char *name;
- sc_int var_type;
- const sc_char *value;
-
- /* Retrieve variable name, type, and string initial value. */
- vt_key[1].integer = index_;
- vt_key[2].string = "Name";
- name = prop_get_string (bundle, "S<-sis", vt_key);
-
- vt_key[2].string = "Type";
- var_type = prop_get_integer (bundle, "I<-sis", vt_key);
-
- vt_key[2].string = "Value";
- value = prop_get_string (bundle, "S<-sis", vt_key);
-
- /* Handle numerics and strings differently. */
- switch (var_type)
- {
- case TAFVAR_NUMERIC:
- {
- sc_int integer_value;
- if (sscanf (value, "%ld", &integer_value) != 1)
- {
- sc_error ("var_create:"
- " invalid numeric variable %s, %s\n", name, value);
- integer_value = 0;
- }
- var_put_integer (vars, name, integer_value);
- break;
- }
-
- case TAFVAR_STRING:
- var_put_string (vars, name, value);
- break;
-
- default:
- sc_fatal ("var_create: invalid variable type, %ld\n", var_type);
- }
- }
-
- return vars;
+var_create(sc_prop_setref_t bundle) {
+ sc_var_setref_t vars;
+ sc_int var_count, index_;
+ sc_vartype_t vt_key[3];
+ assert(bundle);
+
+ /* Create a clean set of variables to fill from the bundle. */
+ vars = var_create_empty();
+ vars->bundle = bundle;
+
+ /* Retrieve the count of variables. */
+ vt_key[0].string = "Variables";
+ var_count = prop_get_child_count(bundle, "I<-s", vt_key);
+
+ /* Create a variable for each variable property held. */
+ for (index_ = 0; index_ < var_count; index_++) {
+ const sc_char *name;
+ sc_int var_type;
+ const sc_char *value;
+
+ /* Retrieve variable name, type, and string initial value. */
+ vt_key[1].integer = index_;
+ vt_key[2].string = "Name";
+ name = prop_get_string(bundle, "S<-sis", vt_key);
+
+ vt_key[2].string = "Type";
+ var_type = prop_get_integer(bundle, "I<-sis", vt_key);
+
+ vt_key[2].string = "Value";
+ value = prop_get_string(bundle, "S<-sis", vt_key);
+
+ /* Handle numerics and strings differently. */
+ switch (var_type) {
+ case TAFVAR_NUMERIC: {
+ sc_int integer_value;
+ if (sscanf(value, "%ld", &integer_value) != 1) {
+ sc_error("var_create:"
+ " invalid numeric variable %s, %s\n", name, value);
+ integer_value = 0;
+ }
+ var_put_integer(vars, name, integer_value);
+ break;
+ }
+
+ case TAFVAR_STRING:
+ var_put_string(vars, name, value);
+ break;
+
+ default:
+ sc_fatal("var_create: invalid variable type, %ld\n", var_type);
+ }
+ }
+
+ return vars;
}
@@ -1716,15 +1535,14 @@ var_create (sc_prop_setref_t bundle)
* reference this variable set.
*/
void
-var_register_game (sc_var_setref_t vars, sc_gameref_t game)
-{
- assert (var_is_valid (vars));
- assert (gs_is_game_valid (game));
+var_register_game(sc_var_setref_t vars, sc_gameref_t game) {
+ assert(var_is_valid(vars));
+ assert(gs_is_game_valid(game));
- if (vars != gs_get_vars (game))
- sc_fatal ("var_register_game: game binding error\n");
+ if (vars != gs_get_vars(game))
+ sc_fatal("var_register_game: game binding error\n");
- vars->game = game;
+ vars->game = game;
}
@@ -1737,35 +1555,31 @@ var_register_game (sc_var_setref_t vars, sc_gameref_t game)
* Set the "referenced" character, object, number, and text.
*/
void
-var_set_ref_character (sc_var_setref_t vars, sc_int character)
-{
- assert (var_is_valid (vars));
- vars->referenced_character = character;
+var_set_ref_character(sc_var_setref_t vars, sc_int character) {
+ assert(var_is_valid(vars));
+ vars->referenced_character = character;
}
void
-var_set_ref_object (sc_var_setref_t vars, sc_int object)
-{
- assert (var_is_valid (vars));
- vars->referenced_object = object;
+var_set_ref_object(sc_var_setref_t vars, sc_int object) {
+ assert(var_is_valid(vars));
+ vars->referenced_object = object;
}
void
-var_set_ref_number (sc_var_setref_t vars, sc_int number)
-{
- assert (var_is_valid (vars));
- vars->referenced_number = number;
- vars->is_number_referenced = TRUE;
+var_set_ref_number(sc_var_setref_t vars, sc_int number) {
+ assert(var_is_valid(vars));
+ vars->referenced_number = number;
+ vars->is_number_referenced = TRUE;
}
void
-var_set_ref_text (sc_var_setref_t vars, const sc_char *text)
-{
- assert (var_is_valid (vars));
+var_set_ref_text(sc_var_setref_t vars, const sc_char *text) {
+ assert(var_is_valid(vars));
- /* Take a copy of the string, and retain it. */
- vars->referenced_text = (sc_char *)sc_realloc (vars->referenced_text, strlen (text) + 1);
- strcpy (vars->referenced_text, text);
+ /* Take a copy of the string, and retain it. */
+ vars->referenced_text = (sc_char *)sc_realloc(vars->referenced_text, strlen(text) + 1);
+ strcpy(vars->referenced_text, text);
}
@@ -1778,37 +1592,33 @@ var_set_ref_text (sc_var_setref_t vars, const sc_char *text)
* Get the "referenced" character, object, number, and text.
*/
sc_int
-var_get_ref_character (sc_var_setref_t vars)
-{
- assert (var_is_valid (vars));
- return vars->referenced_character;
+var_get_ref_character(sc_var_setref_t vars) {
+ assert(var_is_valid(vars));
+ return vars->referenced_character;
}
sc_int
-var_get_ref_object (sc_var_setref_t vars)
-{
- assert (var_is_valid (vars));
- return vars->referenced_object;
+var_get_ref_object(sc_var_setref_t vars) {
+ assert(var_is_valid(vars));
+ return vars->referenced_object;
}
sc_int
-var_get_ref_number (sc_var_setref_t vars)
-{
- assert (var_is_valid (vars));
- return vars->referenced_number;
+var_get_ref_number(sc_var_setref_t vars) {
+ assert(var_is_valid(vars));
+ return vars->referenced_number;
}
const sc_char *
-var_get_ref_text (sc_var_setref_t vars)
-{
- assert (var_is_valid (vars));
-
- /*
- * If currently nullptr, return "". A game may check restrictions involving
- * referenced text before any value has been set; returning "" here for
- * this case prevents problems later (strcmp (nullptr, ...), for example).
- */
- return vars->referenced_text ? vars->referenced_text : "";
+var_get_ref_text(sc_var_setref_t vars) {
+ assert(var_is_valid(vars));
+
+ /*
+ * If currently nullptr, return "". A game may check restrictions involving
+ * referenced text before any value has been set; returning "" here for
+ * this case prevents problems later (strcmp (nullptr, ...), for example).
+ */
+ return vars->referenced_text ? vars->referenced_text : "";
}
@@ -1820,27 +1630,25 @@ var_get_ref_text (sc_var_setref_t vars)
* of game), and set the count to a given value (game restore).
*/
sc_uint
-var_get_elapsed_seconds (sc_var_setref_t vars)
-{
- double delta;
- assert (var_is_valid (vars));
+var_get_elapsed_seconds(sc_var_setref_t vars) {
+ double delta;
+ assert(var_is_valid(vars));
- delta = vars->timestamp - g_vm->_events->getTotalPlayTicks();
- return (sc_uint) delta + vars->time_offset;
+ delta = vars->timestamp - g_vm->_events->getTotalPlayTicks();
+ return (sc_uint) delta + vars->time_offset;
}
void
-var_set_elapsed_seconds (sc_var_setref_t vars, sc_uint seconds)
-{
- assert (var_is_valid (vars));
-
- /*
- * Reset the timestamp to now, and store seconds in offset. This is sort-of
- * forced by the fact that ANSI offers difftime but no 'settime' -- here,
- * we'd really want to set the timestamp to now less seconds.
- */
- vars->timestamp = g_vm->_events->getTotalPlayTicks() / 1000;
- vars->time_offset = seconds;
+var_set_elapsed_seconds(sc_var_setref_t vars, sc_uint seconds) {
+ assert(var_is_valid(vars));
+
+ /*
+ * Reset the timestamp to now, and store seconds in offset. This is sort-of
+ * forced by the fact that ANSI offers difftime but no 'settime' -- here,
+ * we'd really want to set the timestamp to now less seconds.
+ */
+ vars->timestamp = g_vm->_events->getTotalPlayTicks() / 1000;
+ vars->time_offset = seconds;
}
@@ -1850,9 +1658,8 @@ var_set_elapsed_seconds (sc_var_setref_t vars, sc_uint seconds)
* Set variable tracing on/off.
*/
void
-var_debug_trace (sc_bool flag)
-{
- var_trace = flag;
+var_debug_trace(sc_bool flag) {
+ var_trace = flag;
}
@@ -1862,56 +1669,52 @@ var_debug_trace (sc_bool flag)
* Print out a complete variables set.
*/
void
-var_debug_dump (sc_var_setref_t vars)
-{
- sc_int index_;
- sc_varref_t var;
- assert (var_is_valid (vars));
-
- /* Dump complete structure. */
- sc_trace ("Variable: debug dump follows...\n");
- sc_trace ("vars->bundle = %p\n", (void *) vars->bundle);
- sc_trace ("vars->referenced_character = %ld\n", vars->referenced_character);
- sc_trace ("vars->referenced_object = %ld\n", vars->referenced_object);
- sc_trace ("vars->referenced_number = %ld\n", vars->referenced_number);
- sc_trace ("vars->is_number_referenced = %s\n",
- vars->is_number_referenced ? "true" : "false");
-
- sc_trace ("vars->referenced_text = ");
- if (vars->referenced_text)
- sc_trace ("\"%s\"\n", vars->referenced_text);
- else
- sc_trace ("(nil)\n");
-
- sc_trace ("vars->temporary = %p\n", (void *) vars->temporary);
- sc_trace("vars->timestamp = %lu\n", (sc_uint) vars->timestamp);
- sc_trace ("vars->game = %p\n", (void *) vars->game);
-
- sc_trace ("vars->variables =\n");
- for (index_ = 0; index_ < VAR_HASH_TABLE_SIZE; index_++)
- {
- for (var = vars->variable[index_]; var; var = var->next)
- {
- if (var == vars->variable[index_])
- sc_trace ("%3ld : ", index_);
- else
- sc_trace (" : ");
- switch (var->type)
- {
- case VAR_STRING:
- sc_trace ("[String ] %s = \"%s\"", var->name, var->value.string);
- break;
- case VAR_INTEGER:
- sc_trace ("[Integer] %s = %ld", var->name, var->value.integer);
- break;
-
- default:
- sc_trace ("[Invalid] %s = %p", var->name, var->value.voidp);
- break;
- }
- sc_trace ("\n");
- }
- }
+var_debug_dump(sc_var_setref_t vars) {
+ sc_int index_;
+ sc_varref_t var;
+ assert(var_is_valid(vars));
+
+ /* Dump complete structure. */
+ sc_trace("Variable: debug dump follows...\n");
+ sc_trace("vars->bundle = %p\n", (void *) vars->bundle);
+ sc_trace("vars->referenced_character = %ld\n", vars->referenced_character);
+ sc_trace("vars->referenced_object = %ld\n", vars->referenced_object);
+ sc_trace("vars->referenced_number = %ld\n", vars->referenced_number);
+ sc_trace("vars->is_number_referenced = %s\n",
+ vars->is_number_referenced ? "true" : "false");
+
+ sc_trace("vars->referenced_text = ");
+ if (vars->referenced_text)
+ sc_trace("\"%s\"\n", vars->referenced_text);
+ else
+ sc_trace("(nil)\n");
+
+ sc_trace("vars->temporary = %p\n", (void *) vars->temporary);
+ sc_trace("vars->timestamp = %lu\n", (sc_uint) vars->timestamp);
+ sc_trace("vars->game = %p\n", (void *) vars->game);
+
+ sc_trace("vars->variables =\n");
+ for (index_ = 0; index_ < VAR_HASH_TABLE_SIZE; index_++) {
+ for (var = vars->variable[index_]; var; var = var->next) {
+ if (var == vars->variable[index_])
+ sc_trace("%3ld : ", index_);
+ else
+ sc_trace(" : ");
+ switch (var->type) {
+ case VAR_STRING:
+ sc_trace("[String ] %s = \"%s\"", var->name, var->value.string);
+ break;
+ case VAR_INTEGER:
+ sc_trace("[Integer] %s = %ld", var->name, var->value.integer);
+ break;
+
+ default:
+ sc_trace("[Invalid] %s = %p", var->name, var->value.voidp);
+ break;
+ }
+ sc_trace("\n");
+ }
+ }
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sxfile.cpp b/engines/glk/adrift/sxfile.cpp
index 41cfcc485e..4b91db9687 100644
--- a/engines/glk/adrift/sxfile.cpp
+++ b/engines/glk/adrift/sxfile.cpp
@@ -32,10 +32,10 @@ namespace Adrift {
* only one of these to exist.
*/
struct sx_scr_stream_t {
- sc_byte *data;
- sc_int length;
- sc_bool is_open;
- sc_bool is_writable;
+ sc_byte *data;
+ sc_int length;
+ sc_bool is_open;
+ sc_bool is_writable;
};
static sx_scr_stream_t scr_serialization_stream = {NULL, 0, FALSE, FALSE};
@@ -51,132 +51,109 @@ static sx_scr_stream_t scr_serialization_stream = {NULL, 0, FALSE, FALSE};
* exist, meaning that a script must restore a saved game before trying to
* save another.
*/
-void *file_open_file_callback (sc_bool is_save)
-{
- sx_scr_stream_t *const stream = &scr_serialization_stream;
-
- /* Detect any problems due to scripting limitations. */
- if (stream->is_open)
- {
- scr_test_failed ("File open error: %s",
- "stream is in use (script limitation)");
- return NULL;
- }
- else if (is_save && stream->data)
- {
- scr_test_failed ("File open error: %s",
- "stream has not been read (script limitation)");
- return NULL;
- }
-
- /*
- * Set up the stream for the requested mode. Act as if no such file if
- * no data available for a read-only open.
- */
- if (is_save)
- {
- stream->data = NULL;
- stream->length = 0;
- }
- else if (!stream->data)
- return NULL;
-
- stream->is_open = TRUE;
- stream->is_writable = is_save;
- return stream;
+void *file_open_file_callback(sc_bool is_save) {
+ sx_scr_stream_t *const stream = &scr_serialization_stream;
+
+ /* Detect any problems due to scripting limitations. */
+ if (stream->is_open) {
+ scr_test_failed("File open error: %s",
+ "stream is in use (script limitation)");
+ return NULL;
+ } else if (is_save && stream->data) {
+ scr_test_failed("File open error: %s",
+ "stream has not been read (script limitation)");
+ return NULL;
+ }
+
+ /*
+ * Set up the stream for the requested mode. Act as if no such file if
+ * no data available for a read-only open.
+ */
+ if (is_save) {
+ stream->data = NULL;
+ stream->length = 0;
+ } else if (!stream->data)
+ return NULL;
+
+ stream->is_open = TRUE;
+ stream->is_writable = is_save;
+ return stream;
}
sc_int
-file_read_file_callback (void *opaque, sc_byte *buffer, sc_int length)
-{
- sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
- sc_int bytes;
- assert (opaque && buffer && length > 0);
-
- /* Detect any problems with the callback parameters. */
- if (stream != &scr_serialization_stream)
- {
- scr_test_failed ("File read error: %s", "stream is invalid");
- return 0;
- }
- else if (!stream->is_open)
- {
- scr_test_failed ("File read error: %s", "stream is not open");
- return 0;
- }
- else if (stream->is_writable)
- {
- scr_test_failed ("File read error: %s", "stream is not open for read");
- return 0;
- }
-
- /* Read and remove the first block of data (or all if less than length). */
- bytes = (stream->length < length) ? stream->length : length;
- memcpy (buffer, stream->data, bytes);
- memmove (stream->data, stream->data + bytes, stream->length - bytes);
- stream->length -= bytes;
- return bytes;
+file_read_file_callback(void *opaque, sc_byte *buffer, sc_int length) {
+ sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
+ sc_int bytes;
+ assert(opaque && buffer && length > 0);
+
+ /* Detect any problems with the callback parameters. */
+ if (stream != &scr_serialization_stream) {
+ scr_test_failed("File read error: %s", "stream is invalid");
+ return 0;
+ } else if (!stream->is_open) {
+ scr_test_failed("File read error: %s", "stream is not open");
+ return 0;
+ } else if (stream->is_writable) {
+ scr_test_failed("File read error: %s", "stream is not open for read");
+ return 0;
+ }
+
+ /* Read and remove the first block of data (or all if less than length). */
+ bytes = (stream->length < length) ? stream->length : length;
+ memcpy(buffer, stream->data, bytes);
+ memmove(stream->data, stream->data + bytes, stream->length - bytes);
+ stream->length -= bytes;
+ return bytes;
}
void
-file_write_file_callback (void *opaque, const sc_byte *buffer, sc_int length)
-{
- sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
- assert (opaque && buffer && length > 0);
-
- /* Detect any problems with the callback parameters. */
- if (stream != &scr_serialization_stream)
- {
- scr_test_failed ("File write error: %s", "stream is invalid");
- return;
- }
- else if (!stream->is_open)
- {
- scr_test_failed ("File write error: %s", "stream is not open");
- return;
- }
- else if (!stream->is_writable)
- {
- scr_test_failed ("File write error: %s", "stream is not open for write");
- return;
- }
-
- /* Reallocate, then add this block of data to the buffer. */
- stream->data = (sc_byte *)sx_realloc(stream->data, stream->length + length);
- memcpy (stream->data + stream->length, buffer, length);
- stream->length += length;
+file_write_file_callback(void *opaque, const sc_byte *buffer, sc_int length) {
+ sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
+ assert(opaque && buffer && length > 0);
+
+ /* Detect any problems with the callback parameters. */
+ if (stream != &scr_serialization_stream) {
+ scr_test_failed("File write error: %s", "stream is invalid");
+ return;
+ } else if (!stream->is_open) {
+ scr_test_failed("File write error: %s", "stream is not open");
+ return;
+ } else if (!stream->is_writable) {
+ scr_test_failed("File write error: %s", "stream is not open for write");
+ return;
+ }
+
+ /* Reallocate, then add this block of data to the buffer. */
+ stream->data = (sc_byte *)sx_realloc(stream->data, stream->length + length);
+ memcpy(stream->data + stream->length, buffer, length);
+ stream->length += length;
}
void
-file_close_file_callback (void *opaque)
-{
- sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
- assert (opaque);
-
- /* Detect any problems with the callback parameters. */
- if (stream != &scr_serialization_stream)
- {
- scr_test_failed ("File close error: %s", "stream is invalid");
- return;
- }
- else if (!stream->is_open)
- {
- scr_test_failed ("File close error: %s", "stream is not open");
- return;
- }
-
- /*
- * If closing after a read, free allocations, and return the stream to
- * its empty state; if after write, leave the data for the later read.
- */
- if (!stream->is_writable)
- {
- sx_free (stream->data);
- stream->data = NULL;
- stream->length = 0;
- }
- stream->is_writable = FALSE;
- stream->is_open = FALSE;
+file_close_file_callback(void *opaque) {
+ sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
+ assert(opaque);
+
+ /* Detect any problems with the callback parameters. */
+ if (stream != &scr_serialization_stream) {
+ scr_test_failed("File close error: %s", "stream is invalid");
+ return;
+ } else if (!stream->is_open) {
+ scr_test_failed("File close error: %s", "stream is not open");
+ return;
+ }
+
+ /*
+ * If closing after a read, free allocations, and return the stream to
+ * its empty state; if after write, leave the data for the later read.
+ */
+ if (!stream->is_writable) {
+ sx_free(stream->data);
+ stream->data = NULL;
+ stream->length = 0;
+ }
+ stream->is_writable = FALSE;
+ stream->is_open = FALSE;
}
@@ -186,15 +163,14 @@ file_close_file_callback (void *opaque)
* Free any pending allocations and clean up on completion of a script.
*/
void
-file_cleanup (void)
-{
- sx_scr_stream_t *const stream = &scr_serialization_stream;
-
- sx_free (stream->data);
- stream->data = NULL;
- stream->length = 0;
- stream->is_writable = FALSE;
- stream->is_open = FALSE;
+file_cleanup(void) {
+ sx_scr_stream_t *const stream = &scr_serialization_stream;
+
+ sx_free(stream->data);
+ stream->data = NULL;
+ stream->length = 0;
+ stream->is_writable = FALSE;
+ stream->is_open = FALSE;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sxglob.cpp b/engines/glk/adrift/sxglob.cpp
index 3a4a0c6cc4..c6133aa458 100644
--- a/engines/glk/adrift/sxglob.cpp
+++ b/engines/glk/adrift/sxglob.cpp
@@ -67,170 +67,157 @@ namespace Adrift {
* above for notes on where these functions came from originally.
*/
static int
-glob_inrange_unsigned (const unsigned char **const pattern,
- unsigned char ch)
-{
- const unsigned char *const pattern_ = *pattern;
- int in_range = FALSE;
- unsigned int l = 256, r = 0, index_;
-
- /* Skip the leading '[' on entry to a range check. */
- index_ = 1;
-
- /* Special-case a range that has ']' as its first character. */
- if (pattern_[index_] == ']')
- {
- r = pattern_[index_++];
- if (ch == r)
- in_range = TRUE;
- }
-
- /*
- * Check at the loop top, rather than the bottom, to avoid problems with
- * invalid or uncompleted ranges.
- */
- while (pattern_[index_] && pattern_[index_] != ']')
- {
- r = pattern_[index_++];
- if (r == '-')
- {
- /* Special-case a range that has '-' as its last character. */
- if (pattern_[index_] == ']' || !pattern_[index_])
- {
- if (ch == r)
- in_range = TRUE;
- break;
- }
-
- /* Break the loop on unterminated range ending with '-'. */
- if (!pattern_[index_])
- break;
-
- r = pattern_[index_++];
- if (l <= ch && ch <= r)
- in_range = TRUE;
- }
- else
- {
- l = r;
- if (ch == r)
- in_range = TRUE;
- }
- }
-
- /* Update pattern with characters consumed, return result. */
- *pattern += index_;
- return in_range;
+glob_inrange_unsigned(const unsigned char **const pattern,
+ unsigned char ch) {
+ const unsigned char *const pattern_ = *pattern;
+ int in_range = FALSE;
+ unsigned int l = 256, r = 0, index_;
+
+ /* Skip the leading '[' on entry to a range check. */
+ index_ = 1;
+
+ /* Special-case a range that has ']' as its first character. */
+ if (pattern_[index_] == ']') {
+ r = pattern_[index_++];
+ if (ch == r)
+ in_range = TRUE;
+ }
+
+ /*
+ * Check at the loop top, rather than the bottom, to avoid problems with
+ * invalid or uncompleted ranges.
+ */
+ while (pattern_[index_] && pattern_[index_] != ']') {
+ r = pattern_[index_++];
+ if (r == '-') {
+ /* Special-case a range that has '-' as its last character. */
+ if (pattern_[index_] == ']' || !pattern_[index_]) {
+ if (ch == r)
+ in_range = TRUE;
+ break;
+ }
+
+ /* Break the loop on unterminated range ending with '-'. */
+ if (!pattern_[index_])
+ break;
+
+ r = pattern_[index_++];
+ if (l <= ch && ch <= r)
+ in_range = TRUE;
+ } else {
+ l = r;
+ if (ch == r)
+ in_range = TRUE;
+ }
+ }
+
+ /* Update pattern with characters consumed, return result. */
+ *pattern += index_;
+ return in_range;
}
static int
-glob_match_unsigned (const unsigned char *pattern,
- const unsigned char *string)
-{
- int is_match = FALSE;
-
- if (!*string)
- {
- if (*pattern == '*')
- is_match = glob_match_unsigned (pattern + 1, string);
- else
- is_match = !*pattern;
- }
- else
- {
- switch (*pattern)
- {
- case '\0':
- is_match = !*string;
- break;
- case '*':
- if (glob_match_unsigned (pattern + 1, string))
- is_match = TRUE;
- else
- is_match = glob_match_unsigned (pattern, string + 1);
- break;
- case '?':
- is_match = glob_match_unsigned (pattern + 1, string + 1);
- break;
- case '[':
- /*
- * After a range check, we need to see if we hit the end of the
- * pattern before recursively matching pattern + 1.
- */
- is_match = glob_inrange_unsigned (&pattern, *string)
- && (!*pattern
- || glob_match_unsigned (pattern + 1, string + 1));
- break;
- default:
- is_match = *pattern == *string
- && glob_match_unsigned (pattern + 1, string + 1);
- break;
- }
- }
-
- return is_match;
+glob_match_unsigned(const unsigned char *pattern,
+ const unsigned char *string) {
+ int is_match = FALSE;
+
+ if (!*string) {
+ if (*pattern == '*')
+ is_match = glob_match_unsigned(pattern + 1, string);
+ else
+ is_match = !*pattern;
+ } else {
+ switch (*pattern) {
+ case '\0':
+ is_match = !*string;
+ break;
+ case '*':
+ if (glob_match_unsigned(pattern + 1, string))
+ is_match = TRUE;
+ else
+ is_match = glob_match_unsigned(pattern, string + 1);
+ break;
+ case '?':
+ is_match = glob_match_unsigned(pattern + 1, string + 1);
+ break;
+ case '[':
+ /*
+ * After a range check, we need to see if we hit the end of the
+ * pattern before recursively matching pattern + 1.
+ */
+ is_match = glob_inrange_unsigned(&pattern, *string)
+ && (!*pattern
+ || glob_match_unsigned(pattern + 1, string + 1));
+ break;
+ default:
+ is_match = *pattern == *string
+ && glob_match_unsigned(pattern + 1, string + 1);
+ break;
+ }
+ }
+
+ return is_match;
}
/* Structures and data for the self test function. */
-typedef struct
-{
- const sc_char *const pattern;
- const sc_char *const string;
+typedef struct {
+ const sc_char *const pattern;
+ const sc_char *const string;
} sx_test_data_t;
static const sx_test_data_t SHOULD_MATCH[] = {
- {"a", "a"}, {"abc", "abc"}, {"", ""},
- {"*", ""}, {"*", "abc"}, {"*", "cba"},
- {"*c", "c"}, {"*c", "abc"}, {"*c", "cbac"},
- {"a*", "a"}, {"a*", "abc"}, {"a*", "abca"},
- {"a*c", "ac"}, {"a*c", "abc"}, {"a*c", "abcbcbc"},
- {"a**c", "ac"}, {"a**c", "abc"}, {"a**c", "abcbcbc"},
- {"*b*", "b"}, {"*b*", "abc"}, {"*b*", "ab"}, {"*b*", "bc"},
- {"?", "a"}, {"?", "z"}, {"?", "?"}, {"[?]", "?"},
- {"a?", "aa"}, {"a?", "az"}, {"a?", "a?"},
- {"?c", "ac"}, {"?c", "zc"}, {"?c", "?c"},
- {"[abz]", "a"}, {"[abz]", "b"}, {"[abz]", "z"},
- {"[a-c]", "a"}, {"[a-c]", "b"}, {"[a-c]", "c"},
- {"[ac]b[ac]", "abc"}, {"[ac]b[ac]", "cba"},
-
- {"[]]", "]"}, {"[]a-c]", "a"}, {"[]a-c]", "b"}, {"[]a-c]", "c"},
- {"[?]", "?" }, {"[-]", "-"}, {"[z-]", "z"}, {"[z-]", "-"},
- {"[][-]", "]"}, {"[][-]", "["}, {"[][-]", "-"},
- {"[a-c-]", "a"}, {"[a-c-]", "b"}, {"[a-c-]", "c"}, {"[a-c-]", "-"},
-
- {"*[a-z]*abc?xyz", "a<star>abcQxyz"}, {"*[a-z]*abc?xyz", "<star>aabcQxyz"},
- {"*[a-z]*abc?xyz", "aabcQxyz"}, {"*[a-z]*abc?xyz", "<star>a<star>abcQxyz"},
-
- {"???]", "abc]"}, {"[z-a]", "z"},
- {"[a-z", "a"}, {"[a-", "a"}, {"[a", "a"}, {"[[", "["},
- {NULL, NULL}
+ {"a", "a"}, {"abc", "abc"}, {"", ""},
+ {"*", ""}, {"*", "abc"}, {"*", "cba"},
+ {"*c", "c"}, {"*c", "abc"}, {"*c", "cbac"},
+ {"a*", "a"}, {"a*", "abc"}, {"a*", "abca"},
+ {"a*c", "ac"}, {"a*c", "abc"}, {"a*c", "abcbcbc"},
+ {"a**c", "ac"}, {"a**c", "abc"}, {"a**c", "abcbcbc"},
+ {"*b*", "b"}, {"*b*", "abc"}, {"*b*", "ab"}, {"*b*", "bc"},
+ {"?", "a"}, {"?", "z"}, {"?", "?"}, {"[?]", "?"},
+ {"a?", "aa"}, {"a?", "az"}, {"a?", "a?"},
+ {"?c", "ac"}, {"?c", "zc"}, {"?c", "?c"},
+ {"[abz]", "a"}, {"[abz]", "b"}, {"[abz]", "z"},
+ {"[a-c]", "a"}, {"[a-c]", "b"}, {"[a-c]", "c"},
+ {"[ac]b[ac]", "abc"}, {"[ac]b[ac]", "cba"},
+
+ {"[]]", "]"}, {"[]a-c]", "a"}, {"[]a-c]", "b"}, {"[]a-c]", "c"},
+ {"[?]", "?" }, {"[-]", "-"}, {"[z-]", "z"}, {"[z-]", "-"},
+ {"[][-]", "]"}, {"[][-]", "["}, {"[][-]", "-"},
+ {"[a-c-]", "a"}, {"[a-c-]", "b"}, {"[a-c-]", "c"}, {"[a-c-]", "-"},
+
+ {"*[a-z]*abc?xyz", "a<star>abcQxyz"}, {"*[a-z]*abc?xyz", "<star>aabcQxyz"},
+ {"*[a-z]*abc?xyz", "aabcQxyz"}, {"*[a-z]*abc?xyz", "<star>a<star>abcQxyz"},
+
+ {"???]", "abc]"}, {"[z-a]", "z"},
+ {"[a-z", "a"}, {"[a-", "a"}, {"[a", "a"}, {"[[", "["},
+ {NULL, NULL}
};
static const sx_test_data_t SHOULD_NOT_MATCH[] = {
- {"a", "b"}, {"abc", "abd"}, {"a", ""}, {"", "a"},
- {"*c", "a"}, {"*c", "ab"}, {"*c", "abca"},
- {"a*", "c"}, {"a*", "cba"}, {"a*", "cbac"},
- {"a*c", "ca"}, {"a*c", "cba"}, {"a*c", "cbababa"},
- {"a**c", "ca"}, {"a**c", "cba"}, {"a**c", "cbababa"},
- {"*b*", ""}, {"*b*", "z"}, {"*b*", "ac"}, {"*b*", "azc"},
- {"?", ""}, {"?", "ab"}, {"?", "abc"}, {"[?]", "a"},
- {"a?", "ca"}, {"a?", "cz"}, {"a?", "??"},
- {"?c", "ab"}, {"?c", "zb"}, {"?c", "??"},
- {"[bcy]", "a"}, {"[bcy]", "d"}, {"[bcy]", "z"},
- {"[b-d]", "a"}, {"[b-d]", "e"}, {"[b-d]", ""}, {"[b-d]", "bc"},
- {"[ac]b[ac]", "aaa"}, {"[ac]b[ac]", "bbb"}, {"[ac]b[ac]", "ccc"},
-
- {"[]]", "["}, {"[]]", "a"}, {"[]a-c]", "z"},
- {"[?]", "a" }, {"[-]", "a"}, {"[z-]", "a"},
- {"[][-]", "a"}, {"[][-]", "z"},
- {"[a-c-]", "z"},
-
- {"*[a-z]*abc?xyz", "A<STAR>abcQxyz"}, {"*[a-z]*abc?xyz", "<STAR>AabcQxyz"},
- {"*[a-z]*abc?xyz", "AabcQxyz"}, {"*[a-z]*abc?xyz", "aabcxyz"},
-
- {"[z-a]", "a"}, {"[z-a]", "b"}, {"[", "a"}, {"[[", "a"},
- {NULL, NULL}
+ {"a", "b"}, {"abc", "abd"}, {"a", ""}, {"", "a"},
+ {"*c", "a"}, {"*c", "ab"}, {"*c", "abca"},
+ {"a*", "c"}, {"a*", "cba"}, {"a*", "cbac"},
+ {"a*c", "ca"}, {"a*c", "cba"}, {"a*c", "cbababa"},
+ {"a**c", "ca"}, {"a**c", "cba"}, {"a**c", "cbababa"},
+ {"*b*", ""}, {"*b*", "z"}, {"*b*", "ac"}, {"*b*", "azc"},
+ {"?", ""}, {"?", "ab"}, {"?", "abc"}, {"[?]", "a"},
+ {"a?", "ca"}, {"a?", "cz"}, {"a?", "??"},
+ {"?c", "ab"}, {"?c", "zb"}, {"?c", "??"},
+ {"[bcy]", "a"}, {"[bcy]", "d"}, {"[bcy]", "z"},
+ {"[b-d]", "a"}, {"[b-d]", "e"}, {"[b-d]", ""}, {"[b-d]", "bc"},
+ {"[ac]b[ac]", "aaa"}, {"[ac]b[ac]", "bbb"}, {"[ac]b[ac]", "ccc"},
+
+ {"[]]", "["}, {"[]]", "a"}, {"[]a-c]", "z"},
+ {"[?]", "a" }, {"[-]", "a"}, {"[z-]", "a"},
+ {"[][-]", "a"}, {"[][-]", "z"},
+ {"[a-c-]", "z"},
+
+ {"*[a-z]*abc?xyz", "A<STAR>abcQxyz"}, {"*[a-z]*abc?xyz", "<STAR>AabcQxyz"},
+ {"*[a-z]*abc?xyz", "AabcQxyz"}, {"*[a-z]*abc?xyz", "aabcxyz"},
+
+ {"[z-a]", "a"}, {"[z-a]", "b"}, {"[", "a"}, {"[[", "a"},
+ {NULL, NULL}
};
@@ -240,47 +227,41 @@ static const sx_test_data_t SHOULD_NOT_MATCH[] = {
* Sed quis custodiet ipsos custodes?
*/
static void
-glob_self_test (void)
-{
- const sx_test_data_t *test;
- sc_int errors;
-
- /*
- * Run each test case and compare against expected result. To avoid a lot
- * of ugly casting, we use the main public glob_match() function.
- */
- errors = 0;
- for (test = SHOULD_MATCH; test->pattern; test++)
- {
- if (!glob_match (test->pattern, test->string))
- {
- sx_error ("glob_self_test: \"%s\", \"%s\""
- " did not match, and should have matched\n",
- test->pattern, test->string);
- errors++;
- }
- }
-
- for (test = SHOULD_NOT_MATCH; test->pattern; test++)
- {
- if (glob_match (test->pattern, test->string))
- {
- sx_error ("glob_self_test: \"%s\", \"%s\""
- " matched, and should not have matched\n",
- test->pattern, test->string);
- errors++;
- }
- }
-
- /*
- * Abort if any error. As befits our distrustful nature, we won't even
- * trust that sx_fatal() calls abort() (though it should).
- */
- if (errors > 0)
- {
- sx_fatal("glob_self_test: %ld self-test error%s found, aborting\n",
- errors, (errors == 1) ? "" : "s");
- }
+glob_self_test(void) {
+ const sx_test_data_t *test;
+ sc_int errors;
+
+ /*
+ * Run each test case and compare against expected result. To avoid a lot
+ * of ugly casting, we use the main public glob_match() function.
+ */
+ errors = 0;
+ for (test = SHOULD_MATCH; test->pattern; test++) {
+ if (!glob_match(test->pattern, test->string)) {
+ sx_error("glob_self_test: \"%s\", \"%s\""
+ " did not match, and should have matched\n",
+ test->pattern, test->string);
+ errors++;
+ }
+ }
+
+ for (test = SHOULD_NOT_MATCH; test->pattern; test++) {
+ if (glob_match(test->pattern, test->string)) {
+ sx_error("glob_self_test: \"%s\", \"%s\""
+ " matched, and should not have matched\n",
+ test->pattern, test->string);
+ errors++;
+ }
+ }
+
+ /*
+ * Abort if any error. As befits our distrustful nature, we won't even
+ * trust that sx_fatal() calls abort() (though it should).
+ */
+ if (errors > 0) {
+ sx_fatal("glob_self_test: %ld self-test error%s found, aborting\n",
+ errors, (errors == 1) ? "" : "s");
+ }
}
@@ -291,29 +272,27 @@ glob_self_test (void)
* based interface. Here is where all the evil casting lives.
*/
sc_bool
-glob_match (const sc_char *pattern, const sc_char *string)
-{
- static sc_bool initialized = FALSE;
-
- const unsigned char *pattern_ = (const unsigned char *) pattern;
- const unsigned char *string_ = (const unsigned char *) string;
- sc_bool retval;
- assert (pattern && string);
-
- /* On the first call, run a self-test to verify basic glob matching. */
- if (!initialized)
- {
- /*
- * To avoid lots of icky casting, the self-test uses the core public
- * glob_match() that we're in right here to run its tests. So set
- * initialized _before_ the test, to avoid infinite recursion.
- */
- initialized = TRUE;
- glob_self_test ();
- }
-
- retval = glob_match_unsigned (pattern_, string_) != 0;
- return retval;
+glob_match(const sc_char *pattern, const sc_char *string) {
+ static sc_bool initialized = FALSE;
+
+ const unsigned char *pattern_ = (const unsigned char *) pattern;
+ const unsigned char *string_ = (const unsigned char *) string;
+ sc_bool retval;
+ assert(pattern && string);
+
+ /* On the first call, run a self-test to verify basic glob matching. */
+ if (!initialized) {
+ /*
+ * To avoid lots of icky casting, the self-test uses the core public
+ * glob_match() that we're in right here to run its tests. So set
+ * initialized _before_ the test, to avoid infinite recursion.
+ */
+ initialized = TRUE;
+ glob_self_test();
+ }
+
+ retval = glob_match_unsigned(pattern_, string_) != 0;
+ return retval;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sxmain.cpp b/engines/glk/adrift/sxmain.cpp
index 2644a5d53e..d01e226716 100644
--- a/engines/glk/adrift/sxmain.cpp
+++ b/engines/glk/adrift/sxmain.cpp
@@ -51,124 +51,113 @@ namespace Adrift {
* Validate the command line, and each argument as a game to be run.
* Execute scripts for each, and return with an error code if any test fails.
*/
-int glk_main (int argc, const char *argv[])
-{
- const sc_char *const program = argv[0];
- sc_bool is_verbose = FALSE, is_tracing = FALSE;
- const sc_char *trace_flags;
- sx_test_descriptor_t *tests;
- sc_int count, index_, errors;
- assert (argc > 0 && argv);
-
- /* Get options and validate the command line. */
- if (argc > 1
- && (strcmp (argv[1], "-v") == 0 || strcmp (argv[1], "-vv") == 0))
- {
- is_verbose = TRUE;
- is_tracing = (strcmp (argv[1], "-vv") == 0);
- argc--;
- argv++;
- }
-
- if (is_verbose)
- {
- sx_trace ("--- %s Test Suite [Adrift %ld compatible]\n",
- sc_scare_version (), sc_scare_emulation ());
- if (argc < 2)
- return EXIT_SUCCESS;
- }
- else if (argc < 2)
- {
- error("Usage: %s [-v | -vv] test [test...]\n", program);
- return EXIT_FAILURE;
- }
-
- /* Ensure that the interpreter is in the Latin1 locale, and stays there. */
- if (!sc_set_locale ("Latin1"))
- {
- error("%s: failed to set locale\n", program);
- return EXIT_FAILURE;
- }
-
- /*
- * Force test reproducibility. Because game construction may use random
- * numbers, we also need to remember to reseed this before constructing
- * each game, and then again before running each.
- */
- sc_set_portable_random (TRUE);
-
- /* Set verbosity and tracing for other modules. */
- scr_set_verbose (is_verbose);
- stub_debug_trace (is_tracing);
- trace_flags = 0; // getenv("SC_TRACE_FLAGS");
- if (trace_flags)
- sc_set_trace_flags (strtoul (trace_flags, NULL, 0));
-
- /* Create an array of test descriptors large enough for all tests. */
- tests = (sx_test_descriptor_t *)sx_malloc ((argc - 1) * sizeof (*tests));
-
- /* Validate each test argument by opening a game and script for it. */
- count = 0;
- for (index_ = 1; index_ < argc; index_++)
- {
- const sc_char *name;
- Common::SeekableReadStream *stream;
- sx_script script;
- sc_game game;
-
- name = argv[index_];
-
- script = sx_fopen(name, "scr", "r");
- if (!script)
- {
- error("%s: %s.scr: %s\n", program, name, strerror (errno));
- continue;
- }
-
- stream = sx_fopen (name, "taf", "rb");
- if (!stream)
- {
- error("%s: %s.taf: %s\n", program, name, strerror (errno));
- delete script;
- continue;
- }
-
- sc_reseed_random_sequence (1);
- game = sc_game_from_stream(stream);
- delete stream;
- if (!game)
- {
- error("%s: %s.taf: Unable to decode Adrift game\n", program, name);
- delete script;
- continue;
- }
-
- tests[count].name = name;
- tests[count].script = script;
- tests[count].game = game;
- count++;
- }
-
- /* Run the available tests and report results. */
- if (count > 0)
- errors = test_run_game_tests (tests, count, is_verbose);
- else
- errors = 1;
-
- /* Clean up allocations and opened files. */
- for (index_ = 0; index_ < count; index_++)
- {
- delete tests[index_].script;
- sc_free_game (tests[index_].game);
- }
- sx_free (tests);
-
- /* Report results overall. */
- warning("%s [%ld test%s, %ld error%s]\n",
- errors > 0 ? "FAIL" : "PASS",
- count, count == 1 ? "" : "s", errors, errors == 1 ? "" : "s");
-
- return errors > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+int glk_main(int argc, const char *argv[]) {
+ const sc_char *const program = argv[0];
+ sc_bool is_verbose = FALSE, is_tracing = FALSE;
+ const sc_char *trace_flags;
+ sx_test_descriptor_t *tests;
+ sc_int count, index_, errors;
+ assert(argc > 0 && argv);
+
+ /* Get options and validate the command line. */
+ if (argc > 1
+ && (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "-vv") == 0)) {
+ is_verbose = TRUE;
+ is_tracing = (strcmp(argv[1], "-vv") == 0);
+ argc--;
+ argv++;
+ }
+
+ if (is_verbose) {
+ sx_trace("--- %s Test Suite [Adrift %ld compatible]\n",
+ sc_scare_version(), sc_scare_emulation());
+ if (argc < 2)
+ return EXIT_SUCCESS;
+ } else if (argc < 2) {
+ error("Usage: %s [-v | -vv] test [test...]\n", program);
+ return EXIT_FAILURE;
+ }
+
+ /* Ensure that the interpreter is in the Latin1 locale, and stays there. */
+ if (!sc_set_locale("Latin1")) {
+ error("%s: failed to set locale\n", program);
+ return EXIT_FAILURE;
+ }
+
+ /*
+ * Force test reproducibility. Because game construction may use random
+ * numbers, we also need to remember to reseed this before constructing
+ * each game, and then again before running each.
+ */
+ sc_set_portable_random(TRUE);
+
+ /* Set verbosity and tracing for other modules. */
+ scr_set_verbose(is_verbose);
+ stub_debug_trace(is_tracing);
+ trace_flags = 0; // getenv("SC_TRACE_FLAGS");
+ if (trace_flags)
+ sc_set_trace_flags(strtoul(trace_flags, NULL, 0));
+
+ /* Create an array of test descriptors large enough for all tests. */
+ tests = (sx_test_descriptor_t *)sx_malloc((argc - 1) * sizeof(*tests));
+
+ /* Validate each test argument by opening a game and script for it. */
+ count = 0;
+ for (index_ = 1; index_ < argc; index_++) {
+ const sc_char *name;
+ Common::SeekableReadStream *stream;
+ sx_script script;
+ sc_game game;
+
+ name = argv[index_];
+
+ script = sx_fopen(name, "scr", "r");
+ if (!script) {
+ error("%s: %s.scr: %s\n", program, name, strerror(errno));
+ continue;
+ }
+
+ stream = sx_fopen(name, "taf", "rb");
+ if (!stream) {
+ error("%s: %s.taf: %s\n", program, name, strerror(errno));
+ delete script;
+ continue;
+ }
+
+ sc_reseed_random_sequence(1);
+ game = sc_game_from_stream(stream);
+ delete stream;
+ if (!game) {
+ error("%s: %s.taf: Unable to decode Adrift game\n", program, name);
+ delete script;
+ continue;
+ }
+
+ tests[count].name = name;
+ tests[count].script = script;
+ tests[count].game = game;
+ count++;
+ }
+
+ /* Run the available tests and report results. */
+ if (count > 0)
+ errors = test_run_game_tests(tests, count, is_verbose);
+ else
+ errors = 1;
+
+ /* Clean up allocations and opened files. */
+ for (index_ = 0; index_ < count; index_++) {
+ delete tests[index_].script;
+ sc_free_game(tests[index_].game);
+ }
+ sx_free(tests);
+
+ /* Report results overall. */
+ warning("%s [%ld test%s, %ld error%s]\n",
+ errors > 0 ? "FAIL" : "PASS",
+ count, count == 1 ? "" : "s", errors, errors == 1 ? "" : "s");
+
+ return errors > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sxprotos.h b/engines/glk/adrift/sxprotos.h
index 6591b5d820..57ce5f392f 100644
--- a/engines/glk/adrift/sxprotos.h
+++ b/engines/glk/adrift/sxprotos.h
@@ -41,11 +41,10 @@ namespace Adrift {
typedef Common::SeekableReadStream *sx_script;
/* Typedef representing a test descriptor. */
-typedef struct sx_test_descriptor_s
-{
- const sc_char *name;
- sc_game game;
- sx_script script;
+typedef struct sx_test_descriptor_s {
+ const sc_char *name;
+ sc_game game;
+ sx_script script;
} sx_test_descriptor_t;
/*
@@ -54,58 +53,58 @@ typedef struct sx_test_descriptor_s
* checks.
*/
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
-extern void sx_trace (const sc_char *format, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
-extern void sx_error (const sc_char *format, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
-extern void sx_fatal (const sc_char *format, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
+extern void sx_trace(const sc_char *format, ...)
+__attribute__((__format__(__printf__, 1, 2)));
+extern void sx_error(const sc_char *format, ...)
+__attribute__((__format__(__printf__, 1, 2)));
+extern void sx_fatal(const sc_char *format, ...)
+__attribute__((__format__(__printf__, 1, 2)));
#else
-extern void sx_trace (const sc_char *format, ...);
-extern void sx_error (const sc_char *format, ...);
-extern void sx_fatal (const sc_char *format, ...);
+extern void sx_trace(const sc_char *format, ...);
+extern void sx_error(const sc_char *format, ...);
+extern void sx_fatal(const sc_char *format, ...);
#endif
-extern void *sx_malloc (size_t size);
-extern void *sx_realloc (void *pointer, size_t size);
-extern void sx_free (void *pointer);
+extern void *sx_malloc(size_t size);
+extern void *sx_realloc(void *pointer, size_t size);
+extern void sx_free(void *pointer);
extern Common::SeekableReadStream *sx_fopen(const sc_char *name,
- const sc_char *extension, const sc_char *mode);
-extern sc_char *sx_trim_string (sc_char *string);
-extern sc_char *sx_normalize_string (sc_char *string);
+ const sc_char *extension, const sc_char *mode);
+extern sc_char *sx_trim_string(sc_char *string);
+extern sc_char *sx_normalize_string(sc_char *string);
/* OS stub hooks controller functions. */
-extern void stub_attach_handlers (sc_bool (*read_line) (sc_char *, sc_int),
- void (*print_string) (const sc_char *),
- void *(*open_file) (sc_bool),
- sc_int (*read_file)
- (void*, sc_byte*, sc_int),
- void (*write_file)
- (void*, const sc_byte*, sc_int),
- void (*close_file) (void*));
-extern void stub_detach_handlers (void);
-extern void stub_debug_trace (sc_bool flag);
+extern void stub_attach_handlers(sc_bool(*read_line)(sc_char *, sc_int),
+ void (*print_string)(const sc_char *),
+ void *(*open_file)(sc_bool),
+ sc_int(*read_file)
+ (void *, sc_byte *, sc_int),
+ void (*write_file)
+ (void *, const sc_byte *, sc_int),
+ void (*close_file)(void *));
+extern void stub_detach_handlers(void);
+extern void stub_debug_trace(sc_bool flag);
/* Test controller function. */
-extern sc_int test_run_game_tests (const sx_test_descriptor_t tests[],
- sc_int count, sc_bool is_verbose);
+extern sc_int test_run_game_tests(const sx_test_descriptor_t tests[],
+ sc_int count, sc_bool is_verbose);
/* Globbing function. */
-extern sc_bool glob_match (const sc_char *pattern, const sc_char *string);
+extern sc_bool glob_match(const sc_char *pattern, const sc_char *string);
/* Script running and checking functions. */
-extern void scr_test_failed (const sc_char *format, const sc_char *string);
-extern void scr_set_verbose (sc_bool flag);
-extern void scr_start_script (sc_game game, Common::SeekableReadStream *script);
-extern sc_int scr_finalize_script (void);
+extern void scr_test_failed(const sc_char *format, const sc_char *string);
+extern void scr_set_verbose(sc_bool flag);
+extern void scr_start_script(sc_game game, Common::SeekableReadStream *script);
+extern sc_int scr_finalize_script(void);
/* Serialization helper for script running and checking. */
-extern void *file_open_file_callback (sc_bool is_save);
-extern sc_int file_read_file_callback (void *opaque,
- sc_byte *buffer, sc_int length);
-extern void file_write_file_callback (void *opaque,
- const sc_byte *buffer, sc_int length);
-extern void file_close_file_callback (void *opaque);
-extern void file_cleanup (void);
+extern void *file_open_file_callback(sc_bool is_save);
+extern sc_int file_read_file_callback(void *opaque,
+ sc_byte *buffer, sc_int length);
+extern void file_write_file_callback(void *opaque,
+ const sc_byte *buffer, sc_int length);
+extern void file_close_file_callback(void *opaque);
+extern void file_cleanup(void);
} // End of namespace Adrift
} // End of namespace Glk
diff --git a/engines/glk/adrift/sxscript.cpp b/engines/glk/adrift/sxscript.cpp
index 41be4c2b77..33c0501a3c 100644
--- a/engines/glk/adrift/sxscript.cpp
+++ b/engines/glk/adrift/sxscript.cpp
@@ -76,9 +76,8 @@ static sc_char *scr_game_output = NULL;
* Set error reporting for expectation errors detected in the script.
*/
void
-scr_set_verbose (sc_bool flag)
-{
- scr_is_verbose = flag;
+scr_set_verbose(sc_bool flag) {
+ scr_is_verbose = flag;
}
@@ -90,31 +89,27 @@ scr_set_verbose (sc_bool flag)
* is used by the serialization helper, so is not static.
*/
static void
-scr_test_message (const sc_char *format, const sc_char *string)
-{
- if (scr_is_verbose)
- {
- sx_trace ("--- ");
- sx_trace (format, string);
- sx_trace ("\n");
- }
+scr_test_message(const sc_char *format, const sc_char *string) {
+ if (scr_is_verbose) {
+ sx_trace("--- ");
+ sx_trace(format, string);
+ sx_trace("\n");
+ }
}
void
-scr_test_failed (const sc_char *format, const sc_char *string)
-{
- assert (format && string);
-
- if (scr_is_verbose)
- {
- if (scr_line_number > 0)
- sx_trace ("--- Near line %ld: ", scr_line_number);
- else
- sx_trace ("--- ");
- sx_trace (format, string);
- sx_trace ("\n");
- }
- scr_errors++;
+scr_test_failed(const sc_char *format, const sc_char *string) {
+ assert(format && string);
+
+ if (scr_is_verbose) {
+ if (scr_line_number > 0)
+ sx_trace("--- Near line %ld: ", scr_line_number);
+ else
+ sx_trace("--- ");
+ sx_trace(format, string);
+ sx_trace("\n");
+ }
+ scr_errors++;
}
@@ -129,47 +124,41 @@ scr_test_failed (const sc_char *format, const sc_char *string)
* Line classifiers, return TRUE if line has the given type.
*/
static sc_bool
-scr_is_line_type (const sc_char *line, sc_char type)
-{
- return line[0] == type;
+scr_is_line_type(const sc_char *line, sc_char type) {
+ return line[0] == type;
}
static sc_bool
-scr_is_line_comment_or_empty (const sc_char *line)
-{
- return scr_is_line_type (line, SCRIPT_COMMENT)
- || strspn (line, "\t\n\v\f\r ") == strlen (line);
+scr_is_line_comment_or_empty(const sc_char *line) {
+ return scr_is_line_type(line, SCRIPT_COMMENT)
+ || strspn(line, "\t\n\v\f\r ") == strlen(line);
}
static sc_bool
-scr_is_line_game_command (const sc_char *line)
-{
- return scr_is_line_type (line, GAME_COMMAND);
+scr_is_line_game_command(const sc_char *line) {
+ return scr_is_line_type(line, GAME_COMMAND);
}
static sc_bool
-scr_is_line_debug_command (const sc_char *line)
-{
- return scr_is_line_type (line, DEBUG_COMMAND);
+scr_is_line_debug_command(const sc_char *line) {
+ return scr_is_line_type(line, DEBUG_COMMAND);
}
static sc_bool
-scr_is_line_command (const sc_char *line)
-{
- return scr_is_line_game_command (line) || scr_is_line_debug_command (line);
+scr_is_line_command(const sc_char *line) {
+ return scr_is_line_game_command(line) || scr_is_line_debug_command(line);
}
static sc_bool
-scr_is_line_empty_debug_command (const sc_char *line)
-{
- return scr_is_line_type (line, DEBUG_COMMAND) && line[1] == NUL;
+scr_is_line_empty_debug_command(const sc_char *line) {
+ return scr_is_line_type(line, DEBUG_COMMAND) && line[1] == NUL;
}
/* Script location, a pair holding the file location and the line number. */
struct sx_scr_location_t {
- size_t position;
- sc_int line_number;
+ size_t position;
+ sc_int line_number;
};
typedef sx_scr_location_t *sx_scr_locationref_t;
@@ -180,12 +169,12 @@ typedef sx_scr_location_t *sx_scr_locationref_t;
* Save and restore the script location in the given structure.
*/
static void
-scr_save_location (sx_script script, sx_scr_locationref_t location) {
+scr_save_location(sx_script script, sx_scr_locationref_t location) {
location->position = script->pos();
location->line_number = scr_line_number;
}
-static void scr_restore_location (sx_script script, sx_scr_locationref_t location) {
+static void scr_restore_location(sx_script script, sx_scr_locationref_t location) {
script->seek(location->position);
scr_line_number = location->line_number;
}
@@ -198,28 +187,26 @@ static void scr_restore_location (sx_script script, sx_scr_locationref_t locatio
* line from the script. Returns NULL if no more lines, or on file error. The
* return string is allocated, and it's the caller's responsibility to free it.
*/
-static sc_char *scr_get_next_line (sx_script script) {
- sc_char *buffer, *line = NULL;
-
- /* Allocate a buffer for line reads. */
- buffer = (sc_char *)sx_malloc(LINE_BUFFER_SIZE);
-
- /* Read until a significant line is found, or end of file or error. */
- while (adrift_fgets(buffer, LINE_BUFFER_SIZE, script))
- {
- scr_line_number++;
- if (!scr_is_line_comment_or_empty (buffer))
- {
- line = buffer;
- break;
- }
- }
-
- /* If no significant line read, free the read buffer. */
- if (!line)
- sx_free (buffer);
-
- return line;
+static sc_char *scr_get_next_line(sx_script script) {
+ sc_char *buffer, *line = NULL;
+
+ /* Allocate a buffer for line reads. */
+ buffer = (sc_char *)sx_malloc(LINE_BUFFER_SIZE);
+
+ /* Read until a significant line is found, or end of file or error. */
+ while (adrift_fgets(buffer, LINE_BUFFER_SIZE, script)) {
+ scr_line_number++;
+ if (!scr_is_line_comment_or_empty(buffer)) {
+ line = buffer;
+ break;
+ }
+ }
+
+ /* If no significant line read, free the read buffer. */
+ if (!line)
+ sx_free(buffer);
+
+ return line;
}
@@ -231,23 +218,19 @@ static sc_char *scr_get_next_line (sx_script script) {
* instead.
*/
static sc_char *
-scr_concatenate (sc_char *string, const sc_char *buffer)
-{
- /* If string is not null, concatenate buffer, otherwise duplicate. */
- if (string)
- {
- string = (sc_char *)sx_realloc(string,
- strlen (string) + 1 + strlen (buffer) + 1);
- strcat (string, " ");
- strcat (string, buffer);
- }
- else
- {
- string = (sc_char *)sx_malloc(strlen (buffer) + 1);
- strcpy (string, buffer);
- }
-
- return string;
+scr_concatenate(sc_char *string, const sc_char *buffer) {
+ /* If string is not null, concatenate buffer, otherwise duplicate. */
+ if (string) {
+ string = (sc_char *)sx_realloc(string,
+ strlen(string) + 1 + strlen(buffer) + 1);
+ strcat(string, " ");
+ strcat(string, buffer);
+ } else {
+ string = (sc_char *)sx_malloc(strlen(buffer) + 1);
+ strcpy(string, buffer);
+ }
+
+ return string;
}
@@ -261,65 +244,57 @@ scr_concatenate (sc_char *string, const sc_char *buffer)
* free them.
*/
static sc_bool
-scr_get_next_section (sx_script script,
- sc_char **command, sc_char **expectation)
-{
- sc_char *line, *first_line, *other_lines;
- sx_scr_location_t location;
-
- /* Clear initial line accumulation. */
- first_line = other_lines = NULL;
-
- /* Read the next significant line from the script. */
- scr_save_location (script, &location);
- line = scr_get_next_line (script);
- while (line)
- {
- /* If already a first line, this is other lines or section end. */
- if (first_line)
- {
- /*
- * If we found the start of the next section, reset the script
- * location that saved on the line read, and we're done.
- */
- if (scr_is_line_command (line))
- {
- scr_restore_location (script, &location);
- sx_free (line);
- break;
- }
- else
- other_lines = scr_concatenate (other_lines, line);
- }
- else
- first_line = scr_concatenate (first_line, line);
-
- sx_free (line);
-
- /* Read the next significant line from the script. */
- scr_save_location (script, &location);
- line = scr_get_next_line (script);
- }
-
- /* Clean up and return nothing on file error. */
- if (script->err())
- {
- scr_test_failed ("Script error: Failed reading script input file", "");
- sx_free (first_line);
- sx_free (other_lines);
- return FALSE;
- }
-
- /* Return the command and the matching expectation string, if any. */
- if (first_line)
- {
- *command = sx_normalize_string (first_line);
- *expectation = other_lines ? sx_normalize_string (other_lines) : NULL;
- return TRUE;
- }
-
- /* End of file, no command section read. */
- return FALSE;
+scr_get_next_section(sx_script script,
+ sc_char **command, sc_char **expectation) {
+ sc_char *line, *first_line, *other_lines;
+ sx_scr_location_t location;
+
+ /* Clear initial line accumulation. */
+ first_line = other_lines = NULL;
+
+ /* Read the next significant line from the script. */
+ scr_save_location(script, &location);
+ line = scr_get_next_line(script);
+ while (line) {
+ /* If already a first line, this is other lines or section end. */
+ if (first_line) {
+ /*
+ * If we found the start of the next section, reset the script
+ * location that saved on the line read, and we're done.
+ */
+ if (scr_is_line_command(line)) {
+ scr_restore_location(script, &location);
+ sx_free(line);
+ break;
+ } else
+ other_lines = scr_concatenate(other_lines, line);
+ } else
+ first_line = scr_concatenate(first_line, line);
+
+ sx_free(line);
+
+ /* Read the next significant line from the script. */
+ scr_save_location(script, &location);
+ line = scr_get_next_line(script);
+ }
+
+ /* Clean up and return nothing on file error. */
+ if (script->err()) {
+ scr_test_failed("Script error: Failed reading script input file", "");
+ sx_free(first_line);
+ sx_free(other_lines);
+ return FALSE;
+ }
+
+ /* Return the command and the matching expectation string, if any. */
+ if (first_line) {
+ *command = sx_normalize_string(first_line);
+ *expectation = other_lines ? sx_normalize_string(other_lines) : NULL;
+ return TRUE;
+ }
+
+ /* End of file, no command section read. */
+ return FALSE;
}
@@ -334,48 +309,41 @@ scr_get_next_section (sx_script script,
* input.
*/
static void
-scr_expect (sc_char *expectation)
-{
- /*
- * Save the expectation, and set up collection of game output if needed.
- * And if not needed, ensure expectation and game output are cleared.
- */
- if (expectation)
- {
- scr_expectation = (sc_char *)sx_malloc(strlen (expectation) + 1);
- strcpy (scr_expectation, expectation);
- scr_game_output = (sc_char *)sx_malloc (1);
- strcpy (scr_game_output, "");
- }
- else
- {
- sx_free(scr_expectation);
- scr_expectation = NULL;
- sx_free(scr_game_output);
- scr_game_output = NULL;
- }
+scr_expect(sc_char *expectation) {
+ /*
+ * Save the expectation, and set up collection of game output if needed.
+ * And if not needed, ensure expectation and game output are cleared.
+ */
+ if (expectation) {
+ scr_expectation = (sc_char *)sx_malloc(strlen(expectation) + 1);
+ strcpy(scr_expectation, expectation);
+ scr_game_output = (sc_char *)sx_malloc(1);
+ strcpy(scr_game_output, "");
+ } else {
+ sx_free(scr_expectation);
+ scr_expectation = NULL;
+ sx_free(scr_game_output);
+ scr_game_output = NULL;
+ }
}
static void
-scr_verify_expectation (void)
-{
- /* Compare expected with actual, and handle any error detected. */
- if (scr_expectation && scr_game_output)
- {
- scr_game_output = sx_normalize_string (scr_game_output);
- if (!glob_match (scr_expectation, scr_game_output))
- {
- scr_test_failed ("Expectation error:", "");
- scr_test_message (" Expected: \"%s\"", scr_expectation);
- scr_test_message (" Received: \"%s\"", scr_game_output);
- }
- }
-
- /* Dispose of the expectation and accumulated game output. */
- sx_free (scr_expectation);
- scr_expectation = NULL;
- sx_free (scr_game_output);
- scr_game_output = NULL;
+scr_verify_expectation(void) {
+ /* Compare expected with actual, and handle any error detected. */
+ if (scr_expectation && scr_game_output) {
+ scr_game_output = sx_normalize_string(scr_game_output);
+ if (!glob_match(scr_expectation, scr_game_output)) {
+ scr_test_failed("Expectation error:", "");
+ scr_test_message(" Expected: \"%s\"", scr_expectation);
+ scr_test_message(" Received: \"%s\"", scr_game_output);
+ }
+ }
+
+ /* Dispose of the expectation and accumulated game output. */
+ sx_free(scr_expectation);
+ scr_expectation = NULL;
+ sx_free(scr_game_output);
+ scr_game_output = NULL;
}
@@ -390,28 +358,26 @@ scr_verify_expectation (void)
* to turn it off when it's no longer needed.
*/
static void
-scr_execute_debugger_command (const sc_char *command, sc_char *expectation)
-{
- sc_bool status;
-
- /* Set up the expectation. */
- scr_expect (expectation);
-
- /*
- * Execute the command via the debugger interface. The "+1" on command
- * skips the leading '~' read in from the game script.
- */
- sc_set_game_debugger_enabled (scr_game, TRUE);
- status = sc_run_game_debugger_command (scr_game, command + 1);
-
- if (!status)
- {
- scr_test_failed ("Script error:"
- " Debug command \"%s\" is not valid", command);
- }
-
- /* Check expectations immediately. */
- scr_verify_expectation ();
+scr_execute_debugger_command(const sc_char *command, sc_char *expectation) {
+ sc_bool status;
+
+ /* Set up the expectation. */
+ scr_expect(expectation);
+
+ /*
+ * Execute the command via the debugger interface. The "+1" on command
+ * skips the leading '~' read in from the game script.
+ */
+ sc_set_game_debugger_enabled(scr_game, TRUE);
+ status = sc_run_game_debugger_command(scr_game, command + 1);
+
+ if (!status) {
+ scr_test_failed("Script error:"
+ " Debug command \"%s\" is not valid", command);
+ }
+
+ /* Check expectations immediately. */
+ scr_verify_expectation();
}
@@ -425,65 +391,60 @@ scr_execute_debugger_command (const sc_char *command, sc_char *expectation)
* to the game.
*/
static sc_bool
-scr_read_line_callback (sc_char *buffer, sc_int length)
-{
- sc_char *command, *expectation;
- assert (buffer && length > 0);
-
- /* Check pending expectation, and clear settings for the next line. */
- scr_verify_expectation ();
-
- /* Get the next line-expectation pair from the script stream. */
- if (scr_get_next_section (scr_script, &command, &expectation))
- {
- if (scr_is_line_debug_command (command))
- {
- /* The debugger persists where debug commands are adjacent. */
- scr_execute_debugger_command (command, expectation);
- sx_free (command);
- sx_free (expectation);
-
- /*
- * Returning FALSE here causes the game to re-prompt. We could
- * loop (or tail recurse) ourselves, but returning is simpler.
- */
- return FALSE;
- }
- else
- sc_set_game_debugger_enabled (scr_game, FALSE);
-
- if (scr_is_line_game_command (command))
- {
- /* Set up the expectation. */
- scr_expect (expectation);
-
- /* Copy out the line to the return buffer, and free the line. */
- strncpy (buffer, command + 1, length);
- buffer[length - 1] = NUL;
- sx_free (command);
- sx_free (expectation);
- return TRUE;
- }
-
- /* Neither a '~' nor a '>' command. */
- scr_test_failed ("Script error:"
- " Command \"%s\" is not valid, ignored", command);
- sx_free (command);
- sx_free (expectation);
- return FALSE;
- }
-
- /* Ensure the game debugger is off after this section. */
- sc_set_game_debugger_enabled (scr_game, FALSE);
-
- /*
- * We reached the end of the script without finding a "quit" command.
- * Supply one here, then. In the unlikely even that this does not quit
- * the game, we'll iterate on this.
- */
- assert (length > 4);
- strcpy (buffer, "quit");
- return TRUE;
+scr_read_line_callback(sc_char *buffer, sc_int length) {
+ sc_char *command, *expectation;
+ assert(buffer && length > 0);
+
+ /* Check pending expectation, and clear settings for the next line. */
+ scr_verify_expectation();
+
+ /* Get the next line-expectation pair from the script stream. */
+ if (scr_get_next_section(scr_script, &command, &expectation)) {
+ if (scr_is_line_debug_command(command)) {
+ /* The debugger persists where debug commands are adjacent. */
+ scr_execute_debugger_command(command, expectation);
+ sx_free(command);
+ sx_free(expectation);
+
+ /*
+ * Returning FALSE here causes the game to re-prompt. We could
+ * loop (or tail recurse) ourselves, but returning is simpler.
+ */
+ return FALSE;
+ } else
+ sc_set_game_debugger_enabled(scr_game, FALSE);
+
+ if (scr_is_line_game_command(command)) {
+ /* Set up the expectation. */
+ scr_expect(expectation);
+
+ /* Copy out the line to the return buffer, and free the line. */
+ strncpy(buffer, command + 1, length);
+ buffer[length - 1] = NUL;
+ sx_free(command);
+ sx_free(expectation);
+ return TRUE;
+ }
+
+ /* Neither a '~' nor a '>' command. */
+ scr_test_failed("Script error:"
+ " Command \"%s\" is not valid, ignored", command);
+ sx_free(command);
+ sx_free(expectation);
+ return FALSE;
+ }
+
+ /* Ensure the game debugger is off after this section. */
+ sc_set_game_debugger_enabled(scr_game, FALSE);
+
+ /*
+ * We reached the end of the script without finding a "quit" command.
+ * Supply one here, then. In the unlikely even that this does not quit
+ * the game, we'll iterate on this.
+ */
+ assert(length > 4);
+ strcpy(buffer, "quit");
+ return TRUE;
}
@@ -495,17 +456,15 @@ scr_read_line_callback (sc_char *buffer, sc_int length)
* the current game output will be NULL, and we can simply save the effort.
*/
static void
-scr_print_string_callback (const sc_char *string)
-{
- assert (string);
-
- if (scr_game_output)
- {
- scr_game_output = (sc_char *)sx_realloc (scr_game_output,
- strlen (scr_game_output)
- + strlen (string) + 1);
- strcat (scr_game_output, string);
- }
+scr_print_string_callback(const sc_char *string) {
+ assert(string);
+
+ if (scr_game_output) {
+ scr_game_output = (sc_char *)sx_realloc(scr_game_output,
+ strlen(scr_game_output)
+ + strlen(string) + 1);
+ strcat(scr_game_output, string);
+ }
}
@@ -518,68 +477,60 @@ scr_print_string_callback (const sc_char *string)
* and match against the expectations on next request or on finalization.
*/
void
-scr_start_script (sc_game game, sx_script script)
-{
- sc_char *command, *expectation;
- sx_scr_location_t location;
- assert (game && script);
-
- /* Save the game and stream, and clear the line number and errors count. */
- assert (!scr_game && !scr_script);
- scr_game = game;
- scr_script = script;
- scr_line_number = 0;
- scr_errors = 0;
-
- /* Set up our callback functions to catch game i/o. */
- stub_attach_handlers (scr_read_line_callback, scr_print_string_callback,
- file_open_file_callback, file_read_file_callback,
- file_write_file_callback, file_close_file_callback);
-
- /*
- * Handle any initial debugging commands, terminating on either a non-
- * debugging one or an expectation for the game intro.
- */
- scr_script->seek(0);
- scr_save_location (scr_script, &location);
- while (scr_get_next_section (scr_script, &command, &expectation))
- {
- if (scr_is_line_debug_command (command))
- {
- if (scr_is_line_empty_debug_command (command))
- {
- /* It's an intro expectation - set and break loop. */
- scr_expect (expectation);
- sx_free (command);
- sx_free (expectation);
- break;
- }
- else
- {
- /* It's a full debug command - execute it as one. */
- scr_execute_debugger_command (command, expectation);
- sx_free (command);
- sx_free (expectation);
- }
- }
- else
- {
- /*
- * It's an ordinary section - rewind so that it's the first one
- * handled in the callback, and break loop.
- */
- scr_restore_location (scr_script, &location);
- sx_free (command);
- sx_free (expectation);
- break;
- }
-
- /* Note script position before reading the next section. */
- scr_save_location (scr_script, &location);
- }
-
- /* Ensure the game debugger is off after this section. */
- sc_set_game_debugger_enabled (scr_game, FALSE);
+scr_start_script(sc_game game, sx_script script) {
+ sc_char *command, *expectation;
+ sx_scr_location_t location;
+ assert(game && script);
+
+ /* Save the game and stream, and clear the line number and errors count. */
+ assert(!scr_game && !scr_script);
+ scr_game = game;
+ scr_script = script;
+ scr_line_number = 0;
+ scr_errors = 0;
+
+ /* Set up our callback functions to catch game i/o. */
+ stub_attach_handlers(scr_read_line_callback, scr_print_string_callback,
+ file_open_file_callback, file_read_file_callback,
+ file_write_file_callback, file_close_file_callback);
+
+ /*
+ * Handle any initial debugging commands, terminating on either a non-
+ * debugging one or an expectation for the game intro.
+ */
+ scr_script->seek(0);
+ scr_save_location(scr_script, &location);
+ while (scr_get_next_section(scr_script, &command, &expectation)) {
+ if (scr_is_line_debug_command(command)) {
+ if (scr_is_line_empty_debug_command(command)) {
+ /* It's an intro expectation - set and break loop. */
+ scr_expect(expectation);
+ sx_free(command);
+ sx_free(expectation);
+ break;
+ } else {
+ /* It's a full debug command - execute it as one. */
+ scr_execute_debugger_command(command, expectation);
+ sx_free(command);
+ sx_free(expectation);
+ }
+ } else {
+ /*
+ * It's an ordinary section - rewind so that it's the first one
+ * handled in the callback, and break loop.
+ */
+ scr_restore_location(scr_script, &location);
+ sx_free(command);
+ sx_free(expectation);
+ break;
+ }
+
+ /* Note script position before reading the next section. */
+ scr_save_location(scr_script, &location);
+ }
+
+ /* Ensure the game debugger is off after this section. */
+ sc_set_game_debugger_enabled(scr_game, FALSE);
}
@@ -591,51 +542,46 @@ scr_start_script (sc_game game, sx_script script)
* count of errors detected during the script.
*/
sc_int
-scr_finalize_script (void)
-{
- sc_char *command, *expectation;
- sc_int errors;
-
- /* Check pending expectation, and clear settings. */
- scr_verify_expectation ();
-
- /* Drain the remainder of the script, ignoring non-debugging commands. */
- while (scr_get_next_section (scr_script, &command, &expectation))
- {
- if (scr_is_line_debug_command (command))
- {
- scr_execute_debugger_command (command, expectation);
- sx_free (command);
- sx_free (expectation);
- }
- else
- {
- /* Complain about script entries ignored because the game ended. */
- scr_test_failed ("Script error:"
- " Game completed, command \"%s\" ignored", command);
- sx_free (command);
- sx_free (expectation);
- }
- }
-
- /* Ensure the game debugger is off after this section. */
- sc_set_game_debugger_enabled (scr_game, FALSE);
-
- /*
- * Remove our callback functions from the stubs, and "close" any retained
- * stream data from game save/load tests.
- */
- stub_detach_handlers ();
- file_cleanup ();
-
- /* Clear local records of game stream, line number, and errors count. */
- errors = scr_errors;
- scr_game = NULL;
- scr_script = NULL;
- scr_line_number = 0;
- scr_errors = 0;
-
- return errors;
+scr_finalize_script(void) {
+ sc_char *command, *expectation;
+ sc_int errors;
+
+ /* Check pending expectation, and clear settings. */
+ scr_verify_expectation();
+
+ /* Drain the remainder of the script, ignoring non-debugging commands. */
+ while (scr_get_next_section(scr_script, &command, &expectation)) {
+ if (scr_is_line_debug_command(command)) {
+ scr_execute_debugger_command(command, expectation);
+ sx_free(command);
+ sx_free(expectation);
+ } else {
+ /* Complain about script entries ignored because the game ended. */
+ scr_test_failed("Script error:"
+ " Game completed, command \"%s\" ignored", command);
+ sx_free(command);
+ sx_free(expectation);
+ }
+ }
+
+ /* Ensure the game debugger is off after this section. */
+ sc_set_game_debugger_enabled(scr_game, FALSE);
+
+ /*
+ * Remove our callback functions from the stubs, and "close" any retained
+ * stream data from game save/load tests.
+ */
+ stub_detach_handlers();
+ file_cleanup();
+
+ /* Clear local records of game stream, line number, and errors count. */
+ errors = scr_errors;
+ scr_game = NULL;
+ scr_script = NULL;
+ scr_line_number = 0;
+ scr_errors = 0;
+
+ return errors;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sxstubs.cpp b/engines/glk/adrift/sxstubs.cpp
index d55b4037a9..32d1fddd4e 100644
--- a/engines/glk/adrift/sxstubs.cpp
+++ b/engines/glk/adrift/sxstubs.cpp
@@ -41,12 +41,12 @@ static sc_bool stub_trace = FALSE;
* Input/output handler functions. If assigned, calls to os_* functions are
* routed here to allow the script runner to catch interpeter i/o.
*/
-static sc_bool (*stub_read_line) (sc_char*, sc_int) = NULL;
-static void (*stub_print_string) (const sc_char*) = NULL;
-static void *(*stub_open_file) (sc_bool) = NULL;
-static sc_int (*stub_read_file) (void*, sc_byte*, sc_int) = NULL;
-static void (*stub_write_file) (void*, const sc_byte*, sc_int) = NULL;
-static void (*stub_close_file) (void*) = NULL;
+static sc_bool(*stub_read_line)(sc_char *, sc_int) = NULL;
+static void (*stub_print_string)(const sc_char *) = NULL;
+static void *(*stub_open_file)(sc_bool) = NULL;
+static sc_int(*stub_read_file)(void *, sc_byte *, sc_int) = NULL;
+static void (*stub_write_file)(void *, const sc_byte *, sc_int) = NULL;
+static void (*stub_close_file)(void *) = NULL;
/* Flags for whether to report tags and resources via stub_print_string(). */
static sc_int stub_show_resources = 0;
@@ -60,36 +60,34 @@ static sc_int stub_show_tags = 0;
* Attach input/output handler functions, and reset to NULLs.
*/
void
-stub_attach_handlers (sc_bool (*read_line) (sc_char*, sc_int),
- void (*print_string) (const sc_char*),
- void *(*open_file) (sc_bool),
- sc_int (*read_file) (void*, sc_byte*, sc_int),
- void (*write_file) (void*, const sc_byte*, sc_int),
- void (*close_file) (void*))
-{
- stub_read_line = read_line;
- stub_print_string = print_string;
- stub_open_file = open_file;
- stub_read_file = read_file;
- stub_write_file = write_file;
- stub_close_file = close_file;
-
- stub_show_resources = 0;
- stub_show_tags = 0;
+stub_attach_handlers(sc_bool(*read_line)(sc_char *, sc_int),
+ void (*print_string)(const sc_char *),
+ void *(*open_file)(sc_bool),
+ sc_int(*read_file)(void *, sc_byte *, sc_int),
+ void (*write_file)(void *, const sc_byte *, sc_int),
+ void (*close_file)(void *)) {
+ stub_read_line = read_line;
+ stub_print_string = print_string;
+ stub_open_file = open_file;
+ stub_read_file = read_file;
+ stub_write_file = write_file;
+ stub_close_file = close_file;
+
+ stub_show_resources = 0;
+ stub_show_tags = 0;
}
void
-stub_detach_handlers (void)
-{
- stub_read_line = NULL;
- stub_print_string = NULL;
- stub_open_file = NULL;
- stub_read_file = NULL;
- stub_write_file = NULL;
- stub_close_file = NULL;
-
- stub_show_resources = 0;
- stub_show_tags = 0;
+stub_detach_handlers(void) {
+ stub_read_line = NULL;
+ stub_print_string = NULL;
+ stub_open_file = NULL;
+ stub_read_file = NULL;
+ stub_write_file = NULL;
+ stub_close_file = NULL;
+
+ stub_show_resources = 0;
+ stub_show_tags = 0;
}
@@ -102,35 +100,29 @@ stub_detach_handlers (void)
* Returns TRUE if the tag trapped was one of our testing ones.
*/
static void
-stub_adjust_test_control (sc_int *control, sc_bool is_begin)
-{
- *control += is_begin ? 1 : (*control > 0 ? -1 : 0);
+stub_adjust_test_control(sc_int *control, sc_bool is_begin) {
+ *control += is_begin ? 1 : (*control > 0 ? -1 : 0);
}
static sc_bool
-stub_catch_test_control (sc_int tag, const sc_char *argument)
-{
- if (tag == SC_TAG_UNKNOWN && argument)
- {
- sc_bool is_begin;
- const sc_char *name;
-
- is_begin = !(argument[0] == '/');
- name = is_begin ? argument : argument + 1;
-
- if (sc_strcasecmp (name, "sxshowresources") == 0)
- {
- stub_adjust_test_control (&stub_show_resources, is_begin);
- return TRUE;
- }
- else if (sc_strcasecmp (name, "sxshowtags") == 0)
- {
- stub_adjust_test_control (&stub_show_tags, is_begin);
- return TRUE;
- }
- }
-
- return FALSE;
+stub_catch_test_control(sc_int tag, const sc_char *argument) {
+ if (tag == SC_TAG_UNKNOWN && argument) {
+ sc_bool is_begin;
+ const sc_char *name;
+
+ is_begin = !(argument[0] == '/');
+ name = is_begin ? argument : argument + 1;
+
+ if (sc_strcasecmp(name, "sxshowresources") == 0) {
+ stub_adjust_test_control(&stub_show_resources, is_begin);
+ return TRUE;
+ } else if (sc_strcasecmp(name, "sxshowtags") == 0) {
+ stub_adjust_test_control(&stub_show_tags, is_begin);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}
@@ -141,9 +133,8 @@ stub_catch_test_control (sc_int tag, const sc_char *argument)
* safety. Most libc's handle this themselves, but it's not defined by ANSI.
*/
static const sc_char *
-stub_notnull (const sc_char *string)
-{
- return string ? string : "(nil)";
+stub_notnull(const sc_char *string) {
+ return string ? string : "(nil)";
}
@@ -153,245 +144,219 @@ stub_notnull (const sc_char *string)
* Stub functions called by the interpreter core.
*/
void
-os_print_tag (sc_int tag, const sc_char *argument)
-{
- if (stub_trace)
- sx_trace ("os_print_tag (%ld, \"%s\")\n", tag, stub_notnull (argument));
-
- if (!stub_catch_test_control (tag, argument))
- {
- if (stub_print_string)
- {
- if (stub_show_tags > 0) {
- stub_print_string ("<<Tag: id=");
- Common::String buffer = Common::String::format("%ld", tag);
- stub_print_string (buffer.c_str());
- stub_print_string (", argument=\"");
- stub_print_string (stub_notnull (argument));
- stub_print_string ("\">>");
- }
- else if (tag == SC_TAG_WAITKEY || tag == SC_TAG_CLS)
- stub_print_string (" ");
- }
- }
+os_print_tag(sc_int tag, const sc_char *argument) {
+ if (stub_trace)
+ sx_trace("os_print_tag (%ld, \"%s\")\n", tag, stub_notnull(argument));
+
+ if (!stub_catch_test_control(tag, argument)) {
+ if (stub_print_string) {
+ if (stub_show_tags > 0) {
+ stub_print_string("<<Tag: id=");
+ Common::String buffer = Common::String::format("%ld", tag);
+ stub_print_string(buffer.c_str());
+ stub_print_string(", argument=\"");
+ stub_print_string(stub_notnull(argument));
+ stub_print_string("\">>");
+ } else if (tag == SC_TAG_WAITKEY || tag == SC_TAG_CLS)
+ stub_print_string(" ");
+ }
+ }
}
void
-os_print_string (const sc_char *string)
-{
- if (stub_trace)
- sx_trace ("os_print_string (\"%s\")\n", stub_notnull (string));
+os_print_string(const sc_char *string) {
+ if (stub_trace)
+ sx_trace("os_print_string (\"%s\")\n", stub_notnull(string));
- if (stub_print_string)
- stub_print_string (string);
+ if (stub_print_string)
+ stub_print_string(string);
}
void
-os_print_string_debug (const sc_char *string)
-{
- if (stub_trace)
- sx_trace ("os_print_string_debug (\"%s\")\n", stub_notnull (string));
+os_print_string_debug(const sc_char *string) {
+ if (stub_trace)
+ sx_trace("os_print_string_debug (\"%s\")\n", stub_notnull(string));
- if (stub_print_string)
- stub_print_string (string);
+ if (stub_print_string)
+ stub_print_string(string);
}
void
-os_play_sound (const sc_char *filepath,
- sc_int offset, sc_int length, sc_bool is_looping)
-{
- if (stub_trace)
- sx_trace ("os_play_sound (\"%s\", %ld, %ld, %s)\n",
- stub_notnull (filepath), offset, length,
- is_looping ? "true" : "false");
-
- if (stub_print_string && stub_show_resources > 0)
- {
- sc_char buffer[32];
-
- stub_print_string ("<<Sound: id=\"");
- stub_print_string (stub_notnull (filepath));
- stub_print_string ("\", offset=");
- sprintf (buffer, "%ld", offset);
- stub_print_string (buffer);
- stub_print_string (", length=");
- sprintf (buffer, "%ld", length);
- stub_print_string (buffer);
- stub_print_string (", looping=");
- stub_print_string (is_looping ? "true" : "false");
- stub_print_string (">>");
- }
+os_play_sound(const sc_char *filepath,
+ sc_int offset, sc_int length, sc_bool is_looping) {
+ if (stub_trace)
+ sx_trace("os_play_sound (\"%s\", %ld, %ld, %s)\n",
+ stub_notnull(filepath), offset, length,
+ is_looping ? "true" : "false");
+
+ if (stub_print_string && stub_show_resources > 0) {
+ sc_char buffer[32];
+
+ stub_print_string("<<Sound: id=\"");
+ stub_print_string(stub_notnull(filepath));
+ stub_print_string("\", offset=");
+ sprintf(buffer, "%ld", offset);
+ stub_print_string(buffer);
+ stub_print_string(", length=");
+ sprintf(buffer, "%ld", length);
+ stub_print_string(buffer);
+ stub_print_string(", looping=");
+ stub_print_string(is_looping ? "true" : "false");
+ stub_print_string(">>");
+ }
}
void
-os_stop_sound (void)
-{
- if (stub_trace)
- sx_trace ("os_stop_sound ()\n");
+os_stop_sound(void) {
+ if (stub_trace)
+ sx_trace("os_stop_sound ()\n");
- if (stub_print_string && stub_show_resources > 0)
- stub_print_string ("<<Sound: stop>>");
+ if (stub_print_string && stub_show_resources > 0)
+ stub_print_string("<<Sound: stop>>");
}
void
-os_show_graphic (const sc_char *filepath, sc_int offset, sc_int length)
-{
- if (stub_trace)
- sx_trace ("os_show_graphic (\"%s\", %ld, %ld)\n",
- stub_notnull (filepath), offset, length);
-
- if (stub_print_string && stub_show_resources > 0)
- {
- sc_char buffer[32];
-
- stub_print_string ("<<Graphic: id=\"");
- stub_print_string (stub_notnull (filepath));
- stub_print_string ("\", offset=");
- sprintf (buffer, "%ld", offset);
- stub_print_string (buffer);
- stub_print_string (", length=");
- sprintf (buffer, "%ld", length);
- stub_print_string (buffer);
- stub_print_string (">>");
- }
+os_show_graphic(const sc_char *filepath, sc_int offset, sc_int length) {
+ if (stub_trace)
+ sx_trace("os_show_graphic (\"%s\", %ld, %ld)\n",
+ stub_notnull(filepath), offset, length);
+
+ if (stub_print_string && stub_show_resources > 0) {
+ sc_char buffer[32];
+
+ stub_print_string("<<Graphic: id=\"");
+ stub_print_string(stub_notnull(filepath));
+ stub_print_string("\", offset=");
+ sprintf(buffer, "%ld", offset);
+ stub_print_string(buffer);
+ stub_print_string(", length=");
+ sprintf(buffer, "%ld", length);
+ stub_print_string(buffer);
+ stub_print_string(">>");
+ }
}
sc_bool
-os_read_line (sc_char *buffer, sc_int length)
-{
- sc_bool status;
-
- if (stub_read_line)
- status = stub_read_line (buffer, length);
- else
- {
- assert (buffer && length > 4);
- sprintf (buffer, "%s", "quit");
- status = TRUE;
- }
-
- if (stub_trace)
- {
- if (status)
- sx_trace ("os_read_line (\"%s\", %ld) -> true\n",
- stub_notnull (buffer), length);
- else
- sx_trace ("os_read_line (\"...\", %ld) -> false\n", length);
- }
- return status;
+os_read_line(sc_char *buffer, sc_int length) {
+ sc_bool status;
+
+ if (stub_read_line)
+ status = stub_read_line(buffer, length);
+ else {
+ assert(buffer && length > 4);
+ sprintf(buffer, "%s", "quit");
+ status = TRUE;
+ }
+
+ if (stub_trace) {
+ if (status)
+ sx_trace("os_read_line (\"%s\", %ld) -> true\n",
+ stub_notnull(buffer), length);
+ else
+ sx_trace("os_read_line (\"...\", %ld) -> false\n", length);
+ }
+ return status;
}
sc_bool
-os_read_line_debug (sc_char *buffer, sc_int length)
-{
- assert (buffer && length > 8);
- sprintf (buffer, "%s", "continue");
-
- if (stub_trace)
- sx_trace ("os_read_line_debug (\"%s\", %ld) -> true\n", buffer, length);
- return TRUE;
+os_read_line_debug(sc_char *buffer, sc_int length) {
+ assert(buffer && length > 8);
+ sprintf(buffer, "%s", "continue");
+
+ if (stub_trace)
+ sx_trace("os_read_line_debug (\"%s\", %ld) -> true\n", buffer, length);
+ return TRUE;
}
sc_bool
-os_confirm (sc_int type)
-{
- if (stub_trace)
- sx_trace ("os_confirm (%ld) -> true\n", type);
- return TRUE;
+os_confirm(sc_int type) {
+ if (stub_trace)
+ sx_trace("os_confirm (%ld) -> true\n", type);
+ return TRUE;
}
void *
-os_open_file (sc_bool is_save)
-{
- void *opaque;
-
- if (stub_open_file)
- opaque = stub_open_file (is_save);
- else
- opaque = NULL;
-
- if (stub_trace)
- {
- if (opaque)
- sx_trace ("os_open_file (%s) -> %p\n",
- is_save ? "true" : "false", opaque);
- else
- sx_trace ("os_open_file (%s) -> null\n", is_save ? "true" : "false");
- }
- return opaque;
+os_open_file(sc_bool is_save) {
+ void *opaque;
+
+ if (stub_open_file)
+ opaque = stub_open_file(is_save);
+ else
+ opaque = NULL;
+
+ if (stub_trace) {
+ if (opaque)
+ sx_trace("os_open_file (%s) -> %p\n",
+ is_save ? "true" : "false", opaque);
+ else
+ sx_trace("os_open_file (%s) -> null\n", is_save ? "true" : "false");
+ }
+ return opaque;
}
sc_int
-os_read_file (void *opaque, sc_byte *buffer, sc_int length)
-{
- sc_int bytes;
-
- if (stub_read_file)
- bytes = stub_read_file (opaque, buffer, length);
- else
- bytes = 0;
-
- if (stub_trace)
- sx_trace ("os_read_file (%p, %p, %ld) -> %ld\n",
- opaque, buffer, length, bytes);
- return bytes;
+os_read_file(void *opaque, sc_byte *buffer, sc_int length) {
+ sc_int bytes;
+
+ if (stub_read_file)
+ bytes = stub_read_file(opaque, buffer, length);
+ else
+ bytes = 0;
+
+ if (stub_trace)
+ sx_trace("os_read_file (%p, %p, %ld) -> %ld\n",
+ opaque, buffer, length, bytes);
+ return bytes;
}
void
-os_write_file (void *opaque, const sc_byte *buffer, sc_int length)
-{
- if (stub_write_file)
- stub_write_file (opaque, buffer, length);
+os_write_file(void *opaque, const sc_byte *buffer, sc_int length) {
+ if (stub_write_file)
+ stub_write_file(opaque, buffer, length);
- if (stub_trace)
- sx_trace ("os_write_file (%p, %p, %ld)\n", opaque, buffer, length);
+ if (stub_trace)
+ sx_trace("os_write_file (%p, %p, %ld)\n", opaque, buffer, length);
}
void
-os_close_file (void *opaque)
-{
- if (stub_close_file)
- stub_close_file (opaque);
+os_close_file(void *opaque) {
+ if (stub_close_file)
+ stub_close_file(opaque);
- if (stub_trace)
- sx_trace ("os_close_file (%p)\n", opaque);
+ if (stub_trace)
+ sx_trace("os_close_file (%p)\n", opaque);
}
void
-os_display_hints (sc_game game)
-{
- if (stub_trace)
- sx_trace ("os_display_hints (%p)\n", game);
-
- if (stub_print_string)
- {
- sc_game_hint hint;
-
- for (hint = sc_get_first_game_hint (game);
- hint; hint = sc_get_next_game_hint (game, hint))
- {
- const sc_char *hint_text;
-
- stub_print_string (sc_get_game_hint_question (game, hint));
- stub_print_string ("\n");
-
- hint_text = sc_get_game_subtle_hint (game, hint);
- if (hint_text)
- {
- stub_print_string ("- ");
- stub_print_string (hint_text);
- stub_print_string ("\n");
- }
-
- hint_text = sc_get_game_unsubtle_hint (game, hint);
- if (hint_text)
- {
- stub_print_string ("- ");
- stub_print_string (hint_text);
- stub_print_string ("\n");
- }
- }
- }
+os_display_hints(sc_game game) {
+ if (stub_trace)
+ sx_trace("os_display_hints (%p)\n", game);
+
+ if (stub_print_string) {
+ sc_game_hint hint;
+
+ for (hint = sc_get_first_game_hint(game);
+ hint; hint = sc_get_next_game_hint(game, hint)) {
+ const sc_char *hint_text;
+
+ stub_print_string(sc_get_game_hint_question(game, hint));
+ stub_print_string("\n");
+
+ hint_text = sc_get_game_subtle_hint(game, hint);
+ if (hint_text) {
+ stub_print_string("- ");
+ stub_print_string(hint_text);
+ stub_print_string("\n");
+ }
+
+ hint_text = sc_get_game_unsubtle_hint(game, hint);
+ if (hint_text) {
+ stub_print_string("- ");
+ stub_print_string(hint_text);
+ stub_print_string("\n");
+ }
+ }
+ }
}
@@ -401,9 +366,8 @@ os_display_hints (sc_game game)
* Set stubs tracing on/off.
*/
void
-stub_debug_trace (sc_bool flag)
-{
- stub_trace = flag;
+stub_debug_trace(sc_bool flag) {
+ stub_trace = flag;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sxtester.cpp b/engines/glk/adrift/sxtester.cpp
index 483d8df202..f82ca275ad 100644
--- a/engines/glk/adrift/sxtester.cpp
+++ b/engines/glk/adrift/sxtester.cpp
@@ -33,18 +33,18 @@ namespace Adrift {
* the script's monitoring.
*/
static sc_int test_run_game_script(sc_game game, sx_script script) {
- sc_int errors;
+ sc_int errors;
- /* Ensure completely repeatable random number sequences. */
- sc_reseed_random_sequence (1);
+ /* Ensure completely repeatable random number sequences. */
+ sc_reseed_random_sequence(1);
- /* Start interpreting the script stream. */
- scr_start_script (game, script);
- sc_interpret_game (game);
+ /* Start interpreting the script stream. */
+ scr_start_script(game, script);
+ sc_interpret_game(game);
- /* Wrap up the script interpreter and capture error count. */
- errors = scr_finalize_script ();
- return errors;
+ /* Wrap up the script interpreter and capture error count. */
+ errors = scr_finalize_script();
+ return errors;
}
@@ -54,47 +54,43 @@ static sc_int test_run_game_script(sc_game game, sx_script script) {
* Run each test in the given descriptor array, reporting the results and
* accumulating an error count overall. Return the total error count.
*/
-sc_int test_run_game_tests (const sx_test_descriptor_t tests[],
- sc_int count, sc_bool is_verbose) {
- const sx_test_descriptor_t *test;
- sc_int errors;
- assert(tests);
+sc_int test_run_game_tests(const sx_test_descriptor_t tests[],
+ sc_int count, sc_bool is_verbose) {
+ const sx_test_descriptor_t *test;
+ sc_int errors;
+ assert(tests);
- errors = 0;
+ errors = 0;
- /* Execute each game in turn. */
- for (test = tests; test < tests + count; test++)
- {
- sc_int test_errors;
+ /* Execute each game in turn. */
+ for (test = tests; test < tests + count; test++) {
+ sc_int test_errors;
- if (is_verbose)
- {
- sx_trace ("--- Running Test \"%s\" [\"%s\", by %s]...\n",
- test->name,
- sc_get_game_name (test->game),
- sc_get_game_author (test->game));
- }
+ if (is_verbose) {
+ sx_trace("--- Running Test \"%s\" [\"%s\", by %s]...\n",
+ test->name,
+ sc_get_game_name(test->game),
+ sc_get_game_author(test->game));
+ }
- test_errors = test_run_game_script (test->game, test->script);
- errors += test_errors;
+ test_errors = test_run_game_script(test->game, test->script);
+ errors += test_errors;
- if (is_verbose)
- {
- sx_trace ("--- Test \"%s\": ", test->name);
- if (test_errors > 0)
- sx_trace ("%s [%ld error%s]\n",
- "FAIL", test_errors, test_errors == 1 ? "" : "s");
- else
- sx_trace ("%s\n", "PASS");
- }
- else
- sx_trace ("%s", test_errors > 0 ? "F" : ".");
- //fflush (stdout);
- //fflush (stderr);
- }
- sx_trace ("%s", is_verbose ? "" : "\n");
+ if (is_verbose) {
+ sx_trace("--- Test \"%s\": ", test->name);
+ if (test_errors > 0)
+ sx_trace("%s [%ld error%s]\n",
+ "FAIL", test_errors, test_errors == 1 ? "" : "s");
+ else
+ sx_trace("%s\n", "PASS");
+ } else
+ sx_trace("%s", test_errors > 0 ? "F" : ".");
+ //fflush (stdout);
+ //fflush (stderr);
+ }
+ sx_trace("%s", is_verbose ? "" : "\n");
- return errors;
+ return errors;
}
} // End of namespace Adrift
diff --git a/engines/glk/adrift/sxutils.cpp b/engines/glk/adrift/sxutils.cpp
index d52670db31..90c7385131 100644
--- a/engines/glk/adrift/sxutils.cpp
+++ b/engines/glk/adrift/sxutils.cpp
@@ -38,14 +38,14 @@ namespace Adrift {
* that trace output is synchronized to test expectation failure messages.
*/
void sx_trace(const sc_char *format, ...) {
- va_list ap;
- assert (format);
+ va_list ap;
+ assert(format);
- va_start(ap, format);
- Common::String line = Common::String::vformat(format, ap);
- va_end(ap);
+ va_start(ap, format);
+ Common::String line = Common::String::vformat(format, ap);
+ va_end(ap);
- debug("%s", line.c_str());
+ debug("%s", line.c_str());
}
/*
@@ -79,7 +79,7 @@ void sx_fatal(const sc_char *format, ...) {
/* Unique non-heap address for zero size malloc() and realloc() requests. */
static void *sx_zero_allocation = &sx_zero_allocation;
-
+
/*
* sx_malloc()
* sx_realloc()
@@ -90,54 +90,51 @@ static void *sx_zero_allocation = &sx_zero_allocation;
* defined, so we have to take special care to get predictable behavior.
*/
void *
-sx_malloc (size_t size)
-{
- void *allocated;
+sx_malloc(size_t size) {
+ void *allocated;
- if (size == 0)
- return sx_zero_allocation;
+ if (size == 0)
+ return sx_zero_allocation;
- allocated = malloc (size);
- if (!allocated)
- sx_fatal ("sx_malloc: requested %lu bytes\n", (sc_uint) size);
- else if (allocated == sx_zero_allocation)
- sx_fatal ("sx_malloc: zero-byte allocation address returned\n");
+ allocated = malloc(size);
+ if (!allocated)
+ sx_fatal("sx_malloc: requested %lu bytes\n", (sc_uint) size);
+ else if (allocated == sx_zero_allocation)
+ sx_fatal("sx_malloc: zero-byte allocation address returned\n");
- memset (allocated, 0, size);
- return allocated;
+ memset(allocated, 0, size);
+ return allocated;
}
void *
-sx_realloc (void *pointer, size_t size)
-{
- void *allocated;
-
- if (size == 0)
- {
- sx_free (pointer);
- return sx_zero_allocation;
- }
-
- if (pointer == sx_zero_allocation)
- pointer = NULL;
-
- allocated = realloc (pointer, size);
- if (!allocated)
- sx_fatal ("sx_realloc: requested %lu bytes\n", (sc_uint) size);
- else if (allocated == sx_zero_allocation)
- sx_fatal ("sx_realloc: zero-byte allocation address returned\n");
-
- if (!pointer)
- memset (allocated, 0, size);
- return allocated;
+sx_realloc(void *pointer, size_t size) {
+ void *allocated;
+
+ if (size == 0) {
+ sx_free(pointer);
+ return sx_zero_allocation;
+ }
+
+ if (pointer == sx_zero_allocation)
+ pointer = NULL;
+
+ allocated = realloc(pointer, size);
+ if (!allocated)
+ sx_fatal("sx_realloc: requested %lu bytes\n", (sc_uint) size);
+ else if (allocated == sx_zero_allocation)
+ sx_fatal("sx_realloc: zero-byte allocation address returned\n");
+
+ if (!pointer)
+ memset(allocated, 0, size);
+ return allocated;
}
-void sx_free (void *pointer) {
- if (sx_zero_allocation != &sx_zero_allocation)
- sx_fatal ("sx_free: write to zero-byte allocation address detected\n");
+void sx_free(void *pointer) {
+ if (sx_zero_allocation != &sx_zero_allocation)
+ sx_fatal("sx_free: write to zero-byte allocation address detected\n");
- if (pointer && pointer != sx_zero_allocation)
- free (pointer);
+ if (pointer && pointer != sx_zero_allocation)
+ free(pointer);
}
@@ -148,16 +145,16 @@ void sx_free (void *pointer) {
* Returns NULL if unsuccessful.
*/
Common::SeekableReadStream *sx_fopen(const sc_char *name, const sc_char *extension, const sc_char *mode) {
- assert (name && extension && mode);
+ assert(name && extension && mode);
- Common::String filename = Common::String::format("%s.%s", name, extension);
- Common::File *f = new Common::File();
+ Common::String filename = Common::String::format("%s.%s", name, extension);
+ Common::File *f = new Common::File();
- if (f->open(filename))
- return f;
+ if (f->open(filename))
+ return f;
- delete f;
- return nullptr;
+ delete f;
+ return nullptr;
}
@@ -171,19 +168,17 @@ static const sc_char NUL = '\0';
* Built in replacements for locale-sensitive libc ctype.h functions.
*/
static sc_bool
-sx_isspace (sc_char character)
-{
- static const sc_char *const WHITESPACE = "\t\n\v\f\r ";
+sx_isspace(sc_char character) {
+ static const sc_char *const WHITESPACE = "\t\n\v\f\r ";
- return character != NUL && strchr (WHITESPACE, character) != NULL;
+ return character != NUL && strchr(WHITESPACE, character) != NULL;
}
static sc_bool
-sx_isprint (sc_char character)
-{
- static const sc_int MIN_PRINTABLE = ' ', MAX_PRINTABLE = '~';
+sx_isprint(sc_char character) {
+ static const sc_int MIN_PRINTABLE = ' ', MAX_PRINTABLE = '~';
- return character >= MIN_PRINTABLE && character <= MAX_PRINTABLE;
+ return character >= MIN_PRINTABLE && character <= MAX_PRINTABLE;
}
@@ -194,20 +189,19 @@ sx_isprint (sc_char character)
* in place, and returns the string address for convenience.
*/
sc_char *
-sx_trim_string (sc_char *string)
-{
- sc_int index_;
- assert (string);
+sx_trim_string(sc_char *string) {
+ sc_int index_;
+ assert(string);
- for (index_ = strlen (string) - 1;
- index_ >= 0 && sx_isspace (string[index_]); index_--)
- string[index_] = NUL;
+ for (index_ = strlen(string) - 1;
+ index_ >= 0 && sx_isspace(string[index_]); index_--)
+ string[index_] = NUL;
- for (index_ = 0; sx_isspace (string[index_]);)
- index_++;
- memmove (string, string + index_, strlen (string) - index_ + 1);
+ for (index_ = 0; sx_isspace(string[index_]);)
+ index_++;
+ memmove(string, string + index_, strlen(string) - index_ + 1);
- return string;
+ return string;
}
@@ -219,30 +213,26 @@ sx_trim_string (sc_char *string)
* place, and returns the string address for convenience.
*/
sc_char *
-sx_normalize_string (sc_char *string)
-{
- sc_int index_;
- assert (string);
-
- string = sx_trim_string (string);
-
- for (index_ = 0; string[index_] != NUL; index_++)
- {
- if (sx_isspace (string[index_]))
- {
- sc_int cursor;
-
- string[index_] = ' ';
- for (cursor = index_ + 1; sx_isspace (string[cursor]);)
- cursor++;
- memmove (string + index_ + 1,
- string + cursor, strlen (string + cursor) + 1);
- }
- else if (!sx_isprint (string[index_]))
- string[index_] = '?';
- }
-
- return string;
+sx_normalize_string(sc_char *string) {
+ sc_int index_;
+ assert(string);
+
+ string = sx_trim_string(string);
+
+ for (index_ = 0; string[index_] != NUL; index_++) {
+ if (sx_isspace(string[index_])) {
+ sc_int cursor;
+
+ string[index_] = ' ';
+ for (cursor = index_ + 1; sx_isspace(string[cursor]);)
+ cursor++;
+ memmove(string + index_ + 1,
+ string + cursor, strlen(string + cursor) + 1);
+ } else if (!sx_isprint(string[index_]))
+ string[index_] = '?';
+ }
+
+ return string;
}
char *adrift_fgets(char *buf, int max, Common::SeekableReadStream *s) {