static void init_rumors(dlb * fp) { char line[BUFSZ]; dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment */ dlb_fgets(line, sizeof line, fp); if (sscanf(line, "%6x\n", &true_rumor_size) == 1 && true_rumor_size > 0L) { dlb_fseek(fp, 0L, SEEK_CUR); true_rumor_start = dlb_ftell(fp); true_rumor_end = true_rumor_start + true_rumor_size; dlb_fseek(fp, true_rumor_size, SEEK_CUR); dlb_fgets(line, sizeof line, fp); sscanf(line, "%6x\n", &false_rumor_size); dlb_fseek(fp, 0L, SEEK_CUR); false_rumor_start = dlb_ftell(fp); dlb_fseek(fp, false_rumor_size, SEEK_CUR); false_rumor_end = dlb_ftell(fp); potter_rumor_start = false_rumor_end; dlb_fseek(fp, 0L, SEEK_END); potter_rumor_end = dlb_ftell(fp); potter_rumor_size = potter_rumor_end - potter_rumor_start; } else true_rumor_size = -1L; /* init failed */ }
void display_file(const char *fname, boolean complain) { dlb *fp; char *buf; int fsize; fp = dlb_fopen(fname, "r"); if (!fp) { if (complain) { pline("Cannot open \"%s\".", fname); } else if (program_state.something_worth_saving) doredraw(); } else { dlb_fseek(fp, 0, SEEK_END); fsize = dlb_ftell(fp); dlb_fseek(fp, 0, SEEK_SET); buf = malloc(fsize); dlb_fread(buf, fsize, 1, fp); dlb_fclose(fp); display_buffer(buf, complain); free(buf); } }
void outoracle(boolean special, boolean delphi) { char line[COLNO]; char *endp; dlb *oracles; int oracle_idx; char xbuf[BUFSZ]; if (oracle_flg < 0 || /* couldn't open ORACLEFILE */ (oracle_flg > 0 && oracle_cnt == 0)) /* oracles already exhausted */ return; oracles = dlb_fopen(ORACLEFILE, "r"); if (oracles) { struct menulist menu; if (oracle_flg == 0) { /* if this is the first outoracle() */ init_oracles(oracles); oracle_flg = 1; if (oracle_cnt == 0) return; } /* oracle_loc[0] is the special oracle; */ /* oracle_loc[1..oracle_cnt-1] are normal ones */ if (oracle_cnt <= 1 && !special) return; /* (shouldn't happen) */ oracle_idx = special ? 0 : rnd((int)oracle_cnt - 1); dlb_fseek(oracles, oracle_loc[oracle_idx], SEEK_SET); if (!special) oracle_loc[oracle_idx] = oracle_loc[--oracle_cnt]; init_menulist(&menu); if (delphi) add_menutext(&menu, special ? "The Oracle scornfully takes all your money and says:" : "The Oracle meditates for a moment and then intones:"); else add_menutext(&menu, "The message reads:"); add_menutext(&menu, ""); while (dlb_fgets(line, COLNO, oracles) && strcmp(line, "---\n")) { if ((endp = strchr(line, '\n')) != 0) *endp = 0; add_menutext(&menu, xcrypt(line, xbuf)); } display_menu(menu.items, menu.icount, NULL, PICK_NONE, PLHINT_ANYWHERE, NULL); free(menu.items); dlb_fclose(oracles); } else { pline("Can't open oracles file!"); oracle_flg = -1; /* don't try to open it again */ } }
void outoracle(boolean special, boolean delphi) { char line[COLNO]; char *endp; dlb *oracles; int oracle_idx; if (oracle_flg < 0 || /* couldn't open ORACLEFILE */ (oracle_flg > 0 && oracle_cnt == 0)) /* oracles already exhausted */ return; oracles = dlb_fopen(ORACLEFILE, "r"); if (oracles) { struct nh_menulist menu; if (oracle_flg == 0) { /* if this is the first outoracle() */ init_oracles(oracles); oracle_flg = 1; if (oracle_cnt == 0) return; } /* oracle_loc[0] is the special oracle; */ /* oracle_loc[1..oracle_cnt-1] are normal ones */ if (oracle_cnt <= 1 && !special) return; /* (shouldn't happen) */ oracle_idx = special ? 0 : rnd((int)oracle_cnt - 1); dlb_fseek(oracles, oracle_loc[oracle_idx], SEEK_SET); if (!special) oracle_loc[oracle_idx] = oracle_loc[--oracle_cnt]; init_menulist(&menu); if (delphi) add_menutext( &menu, special ? "Potter protests, but then takes your money and says:" : "Potter thinks for a second, and then announces in a gravelly voice:"); else add_menutext(&menu, "The message reads:"); add_menutext(&menu, ""); while (dlb_fgets(line, COLNO, oracles) && strcmp(line, "---\n")) { if ((endp = strchr(line, '\n')) != 0) *endp = 0; char decrypted_line[strlen(line) + 1]; add_menutext(&menu, xcrypt(line, decrypted_line)); } display_menu(&menu, NULL, PICK_NONE, PLHINT_ANYWHERE, NULL); dlb_fclose(oracles); } else { pline("Can't open oracles file!"); oracle_flg = -1; /* don't try to open it again */ } }
static void init_rumors(dlb * fp) { char line[BUFSZ]; dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment */ dlb_fgets(line, sizeof line, fp); if (sscanf(line, "%6x\n", &true_rumor_size) == 1 && true_rumor_size > 0L) { dlb_fseek(fp, 0L, SEEK_CUR); true_rumor_start = dlb_ftell(fp); true_rumor_end = true_rumor_start + true_rumor_size; dlb_fseek(fp, 0L, SEEK_END); false_rumor_end = dlb_ftell(fp); false_rumor_start = true_rumor_end; /* ok, so it's redundant... */ false_rumor_size = false_rumor_end - false_rumor_start; } else true_rumor_size = -1L; /* init failed */ }
static void dump_qtlist() /* dump the character msg list to check appearance */ { struct qtmsg *msg; long size; for (msg = qt_list.chrole; msg->msgnum > 0; msg++) { pline("msgnum %d: delivery %c", msg->msgnum, msg->delivery); more(); (void) dlb_fseek(msg_file, msg->offset, SEEK_SET); deliver_by_window(msg, NHW_TEXT); } }
void com_pager (int msgnum) { struct qtmsg *qt_msg; if (!(qt_msg = msg_in(qt_list.common, msgnum))) { impossible("com_pager: message %d not found.", msgnum); return; } (void) dlb_fseek(msg_file, qt_msg->offset, SEEK_SET); if (qt_msg->delivery == 'p') deliver_by_pline(qt_msg); else if (msgnum == 1) deliver_by_window(qt_msg, NHW_MENU); else deliver_by_window(qt_msg, NHW_TEXT); return; }
void qt_pager(int msgnum) { struct qtmsg *qt_msg; if (!(qt_msg = msg_in(qt_list.chrole, msgnum))) { impossible("qt_pager: message %d not found.", msgnum); return; } dlb_fseek(msg_file, qt_msg->offset, SEEK_SET); if (qt_msg->delivery == 'p') deliver_by_pline(qt_msg); else deliver_by_window(qt_msg); return; }
static struct qtmsg * construct_qtlist(long hdr_offset) { struct qtmsg *msg_list; int n_msgs; dlb_fseek(msg_file, hdr_offset, SEEK_SET); Fread(&n_msgs, sizeof (int), 1, msg_file); msg_list = malloc((unsigned)(n_msgs + 1) * sizeof (struct qtmsg)); /* * Load up the list. */ Fread(msg_list, n_msgs * sizeof (struct qtmsg), 1, msg_file); msg_list[n_msgs].msgnum = -1; return msg_list; }
/* exclude_cookie is a hack used because we sometimes want to get rumors in a * context where messages such as "You swallowed the fortune!" that refer to * cookies should not appear. This has no effect for true rumors since none * of them contain such references anyway. */ char * getrumor(int truth, /* 1=true, -1=false, 0=either */ char *rumor_buf, boolean exclude_cookie, int *truth_out) { dlb *rumors; int tidbit, beginning; char *endp, line[BUFSZ], xbuf[BUFSZ]; int ltruth = 0; rumor_buf[0] = '\0'; if (true_rumor_size < 0L) /* we couldn't open RUMORFILE */ return rumor_buf; rumors = dlb_fopen(RUMORFILE, "r"); if (rumors) { int count = 0; int adjtruth; do { rumor_buf[0] = '\0'; if (true_rumor_size == 0L) { /* if this is 1st outrumor() */ init_rumors(rumors); if (true_rumor_size < 0L) { /* init failed */ sprintf(rumor_buf, "Error reading \"%.80s\".", RUMORFILE); return rumor_buf; } } /* * input: 1 0 -1 * rn2 \ +1 2=T 1=T 0=F * adj./ +0 1=T 0=F -1=F */ switch (adjtruth = truth + rn2(2)) { case 2: /* (might let a bogus input arg sneak thru) */ case 1: beginning = true_rumor_start; tidbit = mt_random() % true_rumor_size; break; case 0: /* once here, 0 => false rather than "either" */ case -1: beginning = false_rumor_start; tidbit = mt_random() % false_rumor_size; break; default: impossible("strange truth value for rumor"); return strcpy(rumor_buf, "Oops..."); } dlb_fseek(rumors, beginning + tidbit, SEEK_SET); dlb_fgets(line, sizeof line, rumors); if (!dlb_fgets(line, sizeof line, rumors) || (adjtruth > 0 && dlb_ftell(rumors) > true_rumor_end)) { /* reached end of rumors -- go back to beginning */ dlb_fseek(rumors, beginning, SEEK_SET); dlb_fgets(line, sizeof line, rumors); } if ((endp = strchr(line, '\n')) != 0) *endp = 0; strcat(rumor_buf, xcrypt(line, xbuf)); } while (count++ < 50 && exclude_cookie && (strstri(rumor_buf, "fortune") || strstri(rumor_buf, "pity"))); dlb_fclose(rumors); if (count >= 50) impossible("Can't find non-cookie rumor?"); else ltruth = (adjtruth > 0) ? 1 : -1; } else { pline("Can't open rumors file!"); true_rumor_size = -1; /* don't try to open it again */ if (truth_out) *truth_out = 0; } if (truth_out) *truth_out = ltruth; return rumor_buf; }
/* * Look in the "data" file for more info. Called if the user typed in the * whole name (user_typed_name == TRUE), or we've found a possible match * with a character/glyph. */ static void checkfile(const char *inp, struct permonst *pm, boolean user_typed_name, boolean without_asking) { dlb *fp; char buf[BUFSZ], newstr[BUFSZ]; char *ep, *dbase_str; long txt_offset = 0; int chk_skip; boolean found_in_file = FALSE, skipping_entry = FALSE; fp = dlb_fopen(DATAFILE, "r"); if (!fp) { pline("Cannot open data file!"); return; } /* To prevent the need for entries in data.base like *ngel to account for Angel and angel, make the lookup string the same for both user_typed_name and picked name. */ if (pm != NULL && !user_typed_name) dbase_str = strcpy(newstr, pm->mname); else dbase_str = strcpy(newstr, inp); for (ep = dbase_str; *ep; ep++) *ep = lowc(*ep); if (!strncmp(dbase_str, "interior of ", 12)) dbase_str += 12; if (!strncmp(dbase_str, "a ", 2)) dbase_str += 2; else if (!strncmp(dbase_str, "an ", 3)) dbase_str += 3; else if (!strncmp(dbase_str, "the ", 4)) dbase_str += 4; if (!strncmp(dbase_str, "tame ", 5)) dbase_str += 5; else if (!strncmp(dbase_str, "peaceful ", 9)) dbase_str += 9; if (!strncmp(dbase_str, "invisible ", 10)) dbase_str += 10; if (!strncmp(dbase_str, "statue of ", 10)) dbase_str[6] = '\0'; else if (!strncmp(dbase_str, "figurine of ", 12)) dbase_str[8] = '\0'; /* Make sure the name is non-empty. */ if (*dbase_str) { /* adjust the input to remove " [seen" and "named " and convert to lower case */ const char *alt = 0; /* alternate description */ if ((ep = strstri_mutable(dbase_str, " [seen")) != 0) *ep = '\0'; if ((ep = strstri_mutable(dbase_str, " named ")) != 0) alt = ep + 7; else ep = strstri_mutable(dbase_str, " called "); if (!ep) ep = strstri_mutable(dbase_str, ", "); if (ep && ep > dbase_str) *ep = '\0'; /* * If the object is named, then the name is the alternate description; * otherwise, the result of makesingular() applied to the name is. This * isn't strictly optimal, but named objects of interest to the user * will usually be found under their name, rather than under their * object type, so looking for a singular form is pointless. */ if (!alt) alt = makesingular(dbase_str); else if (user_typed_name) alt = msglowercase(alt); /* skip first record; read second */ txt_offset = 0L; if (!dlb_fgets(buf, BUFSZ, fp) || !dlb_fgets(buf, BUFSZ, fp)) { impossible("can't read 'data' file"); dlb_fclose(fp); return; } else if (sscanf(buf, "%8lx\n", &txt_offset) < 1 || txt_offset <= 0) goto bad_data_file; /* look for the appropriate entry */ while (dlb_fgets(buf, BUFSZ, fp)) { if (*buf == '.') break; /* we passed last entry without success */ if (digit(*buf)) { /* a number indicates the end of current entry */ skipping_entry = FALSE; } else if (!skipping_entry) { if (!(ep = strchr(buf, '\n'))) goto bad_data_file; *ep = 0; /* if we match a key that begins with "~", skip this entry */ chk_skip = (*buf == '~') ? 1 : 0; if (pmatch(&buf[chk_skip], dbase_str) || (alt && pmatch(&buf[chk_skip], alt))) { if (chk_skip) { skipping_entry = TRUE; continue; } else { found_in_file = TRUE; break; } } } } } if (found_in_file) { long entry_offset; int entry_count; int i; /* skip over other possible matches for the info */ do { if (!dlb_fgets(buf, BUFSZ, fp)) goto bad_data_file; } while (!digit(*buf)); if (sscanf(buf, "%ld,%d\n", &entry_offset, &entry_count) < 2) { bad_data_file:impossible("'data' file in wrong format"); dlb_fclose(fp); return; } if (user_typed_name || without_asking || yn("More info?") == 'y') { struct nh_menulist menu; if (dlb_fseek(fp, txt_offset + entry_offset, SEEK_SET) < 0) { pline("? Seek error on 'data' file!"); dlb_fclose(fp); return; } init_menulist(&menu); for (i = 0; i < entry_count; i++) { if (!dlb_fgets(buf, BUFSZ, fp)) goto bad_data_file; if ((ep = strchr(buf, '\n')) != 0) *ep = 0; if (strchr(buf + 1, '\t') != 0) tabexpand(buf + 1); add_menutext(&menu, buf + 1); } display_menu(&menu, NULL, FALSE, PLHINT_ANYWHERE, NULL); } } else if (user_typed_name) pline("I don't have any information on those things."); dlb_fclose(fp); }
/* exclude_cookie is a hack used because we sometimes want to get rumors in a * context where messages such as "You swallowed the fortune!" that refer to * cookies should not appear. This has no effect for true rumors since none * of them contain such references anyway. */ const char * getrumor(int truth, /* 1=true, -1=false, 0=either 3=potter (truier than true)*/ boolean exclude_cookie, int *truth_out, enum rng rng) { dlb *rumors; int tidbit, beginning; char *endp; int ltruth = 0; char line[BUFSZ]; /* for fgets */ const char *rv = ""; /* If this happens, we couldn't open the RUMORFILE. So synthesize a rumor just for the occasion :-) */ if (true_rumor_size < 0L) return ""; rumors = dlb_fopen(RUMORFILE, "r"); if (rumors) { int count = 0; int adjtruth; do { if (true_rumor_size == 0L) { /* if this is 1st outrumor() */ init_rumors(rumors); if (true_rumor_size < 0L) /* init failed */ return msgprintf("Error reading \"%.80s\".", RUMORFILE); } /* * input: 3 1 0 -1 * rn2 \ +1 4=P 2=T 1=T 0=F * adj./ +0 3=P 1=T 0=F -1=F */ switch (adjtruth = truth + rn2_on_rng(2, rng)) { case 4: /* (might let a bogus input arg sneak thru) */ case 3: beginning = potter_rumor_start; tidbit = rn2_on_rng(potter_rumor_size, rng); break; case 1: beginning = true_rumor_start; tidbit = rn2_on_rng(true_rumor_size, rng); break; case 0: /* once here, 0 => false rather than "either" */ case -1: beginning = false_rumor_start; tidbit = rn2_on_rng(false_rumor_size, rng); break; default: impossible("strange truth value for rumor"); if (truth_out) *truth_out = 0; return "Oops..."; } dlb_fseek(rumors, beginning + tidbit, SEEK_SET); dlb_fgets(line, sizeof line, rumors); if (!dlb_fgets(line, sizeof line, rumors) || ((adjtruth == 2 || adjtruth == 1) && dlb_ftell(rumors) > true_rumor_end)) { /* reached end of rumors -- go back to beginning */ dlb_fseek(rumors, beginning, SEEK_SET); dlb_fgets(line, sizeof line, rumors); } else if (!dlb_fgets(line, sizeof line, rumors) || (adjtruth < 1 && dlb_ftell(rumors) > false_rumor_end)){ dlb_fseek(rumors, beginning, SEEK_SET); dlb_fgets(line, sizeof line, rumors); } if ((endp = strchr(line, '\n')) != 0) *endp = 0; char decrypted_line[strlen(line) + 1]; xcrypt(line, decrypted_line); rv = msg_from_string(decrypted_line); } while (count++ < 50 && exclude_cookie && (strstri(rv, "fortune") || strstri(rv, "pity"))); dlb_fclose(rumors); if (count >= 50) impossible("Can't find non-cookie rumor?"); else ltruth = (adjtruth > 0) ? 1 : -1; } else { pline("Can't open rumors file!"); true_rumor_size = -1; /* don't try to open it again */ if (truth_out) *truth_out = 0; } if (truth_out) *truth_out = ltruth; return rv; }