return (ptr);
}
-void packed_to_token(long packed, char token[6])
+void packed_to_token(long packed, char token[TOKLEN+1])
{
// The advent->ascii mapping.
const char advent_to_ascii[] = {
// Replace trailing whitespace with \0.
for (int i = 4; i >= 0; --i) {
- if (token[i] == ' ' || token[i] == '\t')
+ if (token[i] == ' ' ||
+ token[i] == '\t')
token[i] = '\0';
else
break;
}
}
-long token_to_packed(const char token[6])
+long token_to_packed(const char token[TOKLEN+1])
{
const char ascii_to_advent[] = {
63, 63, 63, 63, 63, 63, 63, 63,
return (packed);
}
-void tokenize(char* raw, long tokens[4])
+void tokenize(char* raw, struct command_t *cmd)
{
- // set each token to 0
- for (int i = 0; i < 4; ++i)
- tokens[i] = 0;
+ memset(cmd, '\0', sizeof(struct command_t));
- // grab the first two words
- char* words[2];
- words[0] = (char*) xmalloc(strlen(raw) + 1);
- words[1] = (char*) xmalloc(strlen(raw) + 1);
- int word_count = sscanf(raw, "%s%s", words[0], words[1]);
+ /* FIXME: put a bound prefix on the %s to prevent buffer overflow */
+ int word_count = sscanf(raw, "%s%s", cmd->raw1, cmd->raw2);
// make space for substrings and zero it out
- char chunk_data[][6] = {
+ char chunk_data[][TOKLEN+1] = {
{"\0\0\0\0\0"},
{"\0\0\0\0\0"},
{"\0\0\0\0\0"},
};
// break the words into up to 4 5-char substrings
- sscanf(words[0], "%5s%5s", chunk_data[0], chunk_data[1]);
+ sscanf(cmd->raw1, "%5s%5s", chunk_data[0], chunk_data[1]);
if (word_count == 2)
- sscanf(words[1], "%5s%5s", chunk_data[2], chunk_data[3]);
- free(words[0]);
- free(words[1]);
+ sscanf(cmd->raw2, "%5s%5s", chunk_data[2], chunk_data[3]);
// uppercase all the substrings
for (int i = 0; i < 4; ++i)
chunk_data[i][j] = (char) toupper(chunk_data[i][j]);
// pack the substrings
- for (int i = 0; i < 4; ++i)
- tokens[i] = token_to_packed(chunk_data[i]);
+ cmd->wd1 = token_to_packed(chunk_data[0]);
+ cmd->wd2 = token_to_packed(chunk_data[2]);
}
/* Hide the fact that wods are corrently packed longs */
*v = 0;
}
-/* I/O routines (speak, pspeak, rspeak, get_input, yes) */
+/* I/O routines (speak, pspeak, rspeak, sspeak, get_input, yes) */
-void vspeak(const char* msg, va_list ap)
+void vspeak(const char* msg, bool blank, va_list ap)
{
// Do nothing if we got a null pointer.
if (msg == NULL)
if (strlen(msg) == 0)
return;
- // Print a newline if the global game.blklin says to.
- if (game.blklin == true)
+ if (blank == true)
printf("\n");
int msglen = strlen(msg);
}
// All-lowercase specifier.
- if (msg[i] == 'L' || msg[i] == 'C') {
+ if (msg[i] == 'L' ||
+ msg[i] == 'C') {
packed_to_token(arg, renderp); /* unpack directly to destination */
int len = strlen(renderp);
for (int j = 0; j < len; ++j) {
{
va_list ap;
va_start(ap, msg);
- vspeak(msg, ap);
+ vspeak(msg, true, ap);
+ va_end(ap);
+}
+
+void sspeak(const long msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ fputc('\n', stdout);
+ vprintf(arbitrary_messages[msg], ap);
+ fputc('\n', stdout);
va_end(ap);
}
-void pspeak(vocab_t msg, enum speaktype mode, int skip, ...)
+void pspeak(vocab_t msg, enum speaktype mode, int skip, bool blank, ...)
/* Find the skip+1st message from msg and print it. Modes are:
* feel = for inventory, what you can touch
* look = the long description for the state the object is in
* study = text on the object. */
{
va_list ap;
- va_start(ap, skip);
+ va_start(ap, blank);
switch (mode) {
case touch:
- vspeak(objects[msg].inventory, ap);
+ vspeak(objects[msg].inventory, blank, ap);
break;
case look:
- vspeak(objects[msg].descriptions[skip], ap);
+ vspeak(objects[msg].descriptions[skip], blank, ap);
break;
case hear:
- vspeak(objects[msg].sounds[skip], ap);
+ vspeak(objects[msg].sounds[skip], blank, ap);
break;
case study:
- vspeak(objects[msg].texts[skip], ap);
+ vspeak(objects[msg].texts[skip], blank, ap);
break;
case change:
- vspeak(objects[msg].changes[skip], ap);
+ vspeak(objects[msg].changes[skip], blank, ap);
break;
}
va_end(ap);
{
va_list ap;
va_start(ap, i);
- vspeak(arbitrary_messages[i], ap);
+ vspeak(arbitrary_messages[i], true, ap);
va_end(ap);
}
{
// Set up the prompt
char input_prompt[] = "> ";
- if (!prompt)
+ if (!settings.prompt)
input_prompt[0] = '\0';
- // Print a blank line if game.blklin tells us to.
- if (game.blklin == true)
- printf("\n");
+ // Print a blank line
+ printf("\n");
char* input;
while (true) {
if (!isatty(0))
echo_input(stdout, input_prompt, input);
- if (logfp)
- echo_input(logfp, "", input);
+ if (settings.logfp)
+ echo_input(settings.logfp, "", input);
return (input);
}
free(firstword);
- if (yes == 0 || y == 0) {
+ if (yes == 0 ||
+ y == 0) {
outcome = true;
break;
- } else if (no == 0 || n == 0) {
+ } else if (no == 0 ||
+ n == 0) {
outcome = false;
break;
} else
free(firstword);
- if (yes == 0 || y == 0) {
+ if (yes == 0 ||
+ y == 0) {
speak(yes_response);
outcome = true;
break;
- } else if (no == 0 || n == 0) {
+ } else if (no == 0 ||
+ n == 0) {
speak(no_response);
outcome = false;
break;
{
for (int i = 0; i < NMOTIONS; ++i) {
for (int j = 0; j < motions[i].words.n; ++j) {
- if (strcasecmp(word, motions[i].words.strs[j]) == 0 && (strlen(word) > 1 || strchr(ignore, word[0]) == NULL || !oldstyle))
+ if (strcasecmp(word, motions[i].words.strs[j]) == 0 && (strlen(word) > 1 ||
+ strchr(ignore, word[0]) == NULL ||
+ !settings.oldstyle))
return (i);
}
}
{
for (int i = 0; i < NACTIONS; ++i) {
for (int j = 0; j < actions[i].words.n; ++j) {
- if (strcasecmp(word, actions[i].words.strs[j]) == 0 && (strlen(word) > 1 || strchr(ignore, word[0]) == NULL || !oldstyle))
+ if (strcasecmp(word, actions[i].words.strs[j]) == 0 && (strlen(word) > 1 ||
+ strchr(ignore, word[0]) == NULL ||
+ !settings.oldstyle))
return (i);
}
}
/* Set the LCG seed */
{
game.lcg_x = (unsigned long) seedval % game.lcg_m;
-
+
// once seed is set, we need to generate the Z`ZZZ word
make_zzword(game.zzword);
}
return range * get_next_lcg_value() / game.lcg_m;
}
-void make_zzword(char zzword[6])
+void make_zzword(char zzword[TOKLEN+1])
{
for (int i = 0; i < 5; ++i) {
zzword[i] = 'A' + randrange(26);