Go to the documentation of this file.
76 #define MAX_TITLE_CHECK 20
81 #define MSGTYPE_MONSTER 1
83 #define MSGTYPE_ARTIFACT 2
85 #define MSGTYPE_SPELLPATH 3
87 #define MSGTYPE_ALCHEMY 4
89 #define MSGTYPE_GODS 5
91 #define MSGTYPE_MSGFILE 6
98 #define arraysize(arrayname) (sizeof(arrayname)/sizeof(*(arrayname)))
218 {
"Missile Weapon",
BOW },
219 {
"Missile",
ARROW },
220 {
"Hand Weapon",
WEAPON },
221 {
"Artifact",
SKILL },
362 "magical manufacture",
364 "philosophical items",
616 LOG(
llevInfo,
"Warning: invalid book index %d, using 0 instead\n", i);
620 for (tl =
booklist, number = i; tl && number; tl = tl->
next, number--) {
642 int nstrtok(
const char *buf1,
const char *buf2) {
650 for (tbuf = strtok(
buf, buf2); tbuf; tbuf = strtok(NULL, buf2)) {
662 while ((*
buf) ==
' ') {
684 char *
strtoktolin(
const char *buf1,
const char *buf2,
char *retbuf,
size_t size) {
685 int maxi, i =
nstrtok(buf1, buf2);
690 snprintf(retbuf, size,
" ");
691 for (tbuf = strtok(
buf, buf2); tbuf && i > 0; tbuf = strtok(NULL, buf2)) {
692 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf),
"%s",
trim(tbuf));
694 if (i == 1 && maxi > 1)
695 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf),
" and ");
696 else if (i > 0 && maxi > 1)
697 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf),
", ");
700 int end = strlen(retbuf);
701 if (retbuf[end-1] ==
'\n')
703 snprintf(retbuf+end, size-end,
".");
740 #ifdef BOOK_MSG_DEBUG
744 static int did_init_barch = 0;
754 LOG(
llevDebug,
" Reading bookarch from %s...\n", fname);
756 fp = fopen(fname,
"r");
768 for (lineno = 1; fgets(
buf,
MAX_BUF, fp) != NULL; lineno++) {
774 cp = strchr(
buf,
'\n');
776 while (cp >
buf && (cp[-1] ==
' ' || cp[-1] ==
'\t'))
781 if (strncmp(
buf,
"title ", 6) == 0) {
784 while (*cp ==
' ' || *cp ==
'\t')
787 LOG(
llevInfo,
"Warning: missing book title at %s, line %d\n", fname, lineno);
793 #ifdef BOOK_MSG_DEBUG
797 }
else if (book == NULL) {
800 LOG(
llevInfo,
"Warning: expecting 'title' at %s, line %d\n", fname, lineno);
802 }
else if (strncmp(
buf,
"authour ", 8) == 0) {
804 while (*cp ==
' ' || *cp ==
'\t')
807 LOG(
llevInfo,
"Warning: missing book authour at %s, line %d\n", fname, lineno);
811 }
else if (strncmp(
buf,
"arch ", 5) == 0) {
813 while (*cp ==
' ' || *cp ==
'\t')
816 LOG(
llevInfo,
"Warning: missing book arch at %s, line %d\n", fname, lineno);
820 }
else if (sscanf(
buf,
"level %d%n", &
value, &len) == 1 && len == (
int)strlen(
buf)) {
822 }
else if (sscanf(
buf,
"type %d%n", &
value, &len) == 1 && len == (
int)strlen(
buf)) {
824 }
else if (sscanf(
buf,
"size %d%n", &
value, &len) == 1 && len == (
int)strlen(
buf)) {
826 }
else if (sscanf(
buf,
"index %d%n", &
value, &len) == 1 && len == (
int)strlen(
buf)) {
828 }
else if (strcmp(
buf,
"end") == 0) {
833 LOG(
llevInfo,
"Warning: syntax error at %s, line %d\n", fname, lineno);
837 LOG(
llevInfo,
"Warning: missing 'end' at %s, line %d\n", fname, lineno);
847 #ifdef BOOK_MSG_DEBUG
848 LOG(
llevDebug,
"\n init_book_archive() got %d titles.\n", nroftitle);
864 LOG(
llevInfo,
"Warning: book with no type at %s, line %d; using type 0\n", fname, lineno);
887 static int did_init_mon_info = 0;
889 if (did_init_mon_info)
891 did_init_mon_info = 1;
905 static int did_this = 0;
942 return (
title *)NULL;
946 return (
title *)NULL;
948 length = strlen(book->
msg);
951 if (
t->size == length &&
t->msg_index ==
index) {
953 LOG(
llevDebug,
"Found title match (list %d): %s %s (%d)\n", msgtype,
t->name,
t->authour,
t->msg_index);
958 return (
title *)NULL;
1003 if (book->
weight > 2000) {
1027 if (msgtype < 0 || strlen(
op->msg) < 5)
1100 LOG(
llevError,
"add_book_to_list can't get booklist!\n");
1107 t->size = strlen(book->
msg);
1119 #ifdef ARCHIVE_DEBUG
1143 LOG(
llevError,
"change_book_name() called w/ illegal obj type.\n");
1176 const char *old_title;
1177 const char *old_name;
1187 LOG(
llevError,
"change_book_name(): can't find title list\n");
1192 if (numb == maxnames) {
1193 #ifdef ARCHIVE_DEBUG
1194 LOG(
llevDebug,
"titles for list %d full (%d possible).\n", msgtype, maxnames);
1201 else if (!book->
title)
1219 #ifdef ARCHIVE_DEBUG
1220 LOG(
llevDebug,
"Failed to obtain unique title for %s %s (names:%d/%d)\n", book->
name, book->
title, numb, maxnames);
1237 }
else if (book->
title && strlen(book->
msg) > 5) {
1241 if (old_title != NULL)
1273 return (
object *)NULL;
1279 std::vector<object *> select;
1280 std::copy_if(
monsters.cbegin(),
monsters.cend(), std::back_inserter(select), [&] (
auto ob) { return ob->level >= level; });
1282 if (select.empty()) {
1283 LOG(
llevError,
"get_random_mon() couldn't return monster for level %d\n",
level);
1286 return select[
RANDOM() % select.size()];
1348 const char *sep =
":";
1440 else if (chance >= 10)
1442 else if (chance >= 5)
1491 if (book_entries > 5)
1505 }
while (al == NULL && i < 10);
1514 auto iart = al->
items.cbegin();
1516 if (iart == al->
items.cend())
1517 iart = al->
items.cbegin();
1528 while (book_entries > 0) {
1530 if (iart == al->
items.cend())
1531 iart = al->
items.cbegin();
1645 int chance,
count = 0;
1646 const char *op_name;
1667 for (formula = fl->
items; formula != NULL; formula = formula->
next) {
1668 chance -= formula->
chance;
1669 if (chance <= 0 && formula->chance != 0 && !formula->
is_combination)
1687 LOG(
llevError,
"formula_msg() can't find arch %s for formula.\n", op_name);
1700 formula->
diff >= 10 && formula->
diff < 15 ?
"n" :
"",
1702 formula->
skill ? formula->
skill :
"an unknown skill");
1705 if (strcmp(formula->
title,
"NONE")) {
1731 if (formula->
ingred != NULL) {
1740 snprintf(
name,
sizeof(
name),
"an unknown place");
1749 LOG(
llevError,
"formula_msg() no ingredient list for object %s of %s\n", op_name, formula->
title);
1759 snprintf(km,
sizeof(km),
"alchemy:%d:%d:%s",
count, formula->
index, formula->
title);
1780 if (
msg->identifier != NULL) {
1784 snprintf(km,
sizeof(km),
"message:%s",
msg->identifier);
1787 if (
msg->quest_code) {
1797 #ifdef BOOK_MSG_DEBUG
1831 LOG(
llevError,
"common/readable.c:god_info_msg() - passed in booksize (%lu) is larger than book buffer (%d)\n", (
unsigned long)
booksize,
BOOK_BUF);
1865 snprintf(
buf,
sizeof(
buf),
"god:%s:%d", god->
name, what);
1894 size_t book_buf_size;
1906 book_buf_size -= strlen(
"\n");
1924 msg_type = msg_type > 0 ? msg_type : (
int)(
RANDOM()%6);
1976 title *title1, *titlenext;
1980 for (tlist =
booklist; tlist != NULL; tlist = tnext) {
1981 tnext = tlist->
next;
1982 for (title1 = tlist->
first_book; title1; title1 = titlenext) {
1983 titlenext = title1->
next;
2018 LOG(
llevDebug,
"Updating book archive: %s...\n", fname);
2027 fprintf(fp,
"title %s\n", book->
name);
2028 fprintf(fp,
"authour %s\n", book->
authour);
2029 fprintf(fp,
"arch %s\n", book->
archname);
2030 fprintf(fp,
"level %d\n", book->
level);
2031 fprintf(fp,
"type %d\n",
index);
2033 fprintf(fp,
"size %lu\n", (
unsigned long)book->
size);
2034 fprintf(fp,
"index %d\n", book->
msg_index);
2035 fprintf(fp,
"end\n");
2042 LOG(
llevError,
"Could not set permissions on '%s'\n", fname);
2056 uint8_t subtype = readable->
subtype;
void write_book_archive(void)
#define MSG_TYPE_MONUMENT_WALL_2
static const char *const formula_book_name[]
#define MSG_TYPE_BOOK_SPELL_PRAYER
static void change_book(object *book, int msgtype)
static const char *const path_book_name[]
size_t stringbuffer_length(StringBuffer *sb)
recipelist * get_formulalist(int i)
static titlelist * get_empty_booklist(void)
static void do_spellpath_msg(archetype *at)
static const char *const mon_author[]
static void init_mon_info(void)
static title * get_empty_book(void)
#define MSG_TYPE_PAPER_LETTER_OLD_2
void LOG(LogLevel logLevel, const char *format,...)
#define arraysize(arrayname)
#define MSG_TYPE_BOOK_SPELL_SUMMONER
static const char *const book_author[]
int of_close(OutputFile *of)
#define MONSTER_EXCLUDE_FROM_READABLE_KEY
void free_all_readable(void)
static std::vector< object * > monsters
FILE * of_open(OutputFile *of, const char *fname)
#define QUERY_FLAG(xyz, p)
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
void archetypes_for_each(arch_op op)
const char *const spellpathnames[NRSPELLPATHS]
static const char *const mon_book_name[]
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
static const char *const path_author[]
static StringBuffer * artifact_msg(unsigned int level, size_t booksize)
#define MSG_TYPE_PAPER_LETTER_NEW_2
StringBuffer * stringbuffer_new(void)
#define MSG_TYPE_BOOK_QUARTO_1
#define MSG_TYPE_SIGN_BASIC
std::vector< artifact * > items
static const char *const gods_book_name[]
#define MSG_TYPE_PAPER_SCROLL_NEW_2
#define MSG_TYPE_PAPER_SCROLL_OLD_2
#define MSG_TYPE_PAPER_NOTE_2
#define MSG_TYPE_CARD_MONEY_2
#define MSG_TYPE_MONUMENT_STATUE_3
static StringBuffer * god_info_msg(int level, size_t booksize, object *book)
void add_abilities(object *op, const object *change)
#define MSG_TYPE_PAPER_LETTER_OLD_1
char * strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size)
#define MSG_TYPE_SIGN_DIR_RIGHT
static const char *const gods_author[]
#define MSG_TYPE_CARD_SIMPLE_2
void object_copy(const object *src_ob, object *dest_ob)
std::vector< sstring > allowed
#define MSG_TYPE_BOOK_CLASP_2
#define MSG_TYPE_BOOK_ELEGANT_1
const char * object_get_value(const object *op, const char *const key)
AssetsManager * getManager()
object * object_insert_in_ob(object *op, object *where)
static const readable_message_type readable_message_types[]
static title * find_title(const object *book, int msgtype)
static object * get_next_mon(const object *tmp)
#define MSG_TYPE_PAPER_SCROLL_OLD_1
static int need_to_write_bookarchive
#define MSG_TYPE_CARD_STRANGE_1
GeneralMessage * random()
char * stringbuffer_finish(StringBuffer *sb)
void object_free_drop_inventory(object *ob)
static void add_author(object *op, int msgtype)
const object * get_rand_god(void)
#define MSG_TYPE_MONUMENT_GRAVESTONE_1
#define MSG_TYPE_MONUMENT
#define MSG_TYPE_CARD_STRANGE_2
void query_name(const object *op, char *buf, size_t size)
#define MSG_TYPE_SIGN_DIR_BOTH
#define MSG_TYPE_MONUMENT_GRAVESTONE_2
static titlelist * get_titlelist(int i)
sstring stringbuffer_finish_shared(StringBuffer *sb)
#define MSG_TYPE_SIGN_DIR_LEFT
sstring add_string(const char *str)
#define MSG_TYPE_BOOK_CLASP_1
static const char *const book_descrpt[]
static void init_book_archive(void)
void tailor_readable_ob(object *book, int msg_type)
static StringBuffer * spellpath_msg(int level, size_t booksize, StringBuffer *buf)
#define FREE_AND_COPY(sv, nv)
#define MSG_TYPE_MONUMENT_STATUE_2
static void add_book_to_list(const object *book, int msgtype)
#define MSG_TYPE_CARD_ELEGANT_1
object * object_create_arch(archetype *at)
#define FLAG_UNAGGRESSIVE
#define MSG_TYPE_CARD_ELEGANT_3
static StringBuffer * artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator)
#define MSG_TYPE_CARD_MONEY_3
#define MSG_TYPE_BOOK_SPELL_EVOKER
#define MSG_TYPE_MONUMENT_GRAVESTONE_3
sstring get_message_body(const GeneralMessage *message)
void stringbuffer_append_string(StringBuffer *sb, const char *str)
#define MSG_TYPE_MONUMENT_STONE_3
#define MSG_TYPE_MONUMENT_WALL_3
const char * trim(const char *buf)
#define MSG_TYPE_PAPER_ENVELOPE_2
#define MSG_TYPE_CARD_ELEGANT_2
#define MSG_TYPE_PAPER_NOTE_1
#define MSG_TYPE_BOOK_SPELL_SORCERER
#define MSG_TYPE_BOOK_SPELL_PYRO
#define MSG_TYPE_SIGN_MAGIC_MOUTH
void fatal(enum fatal_error err)
static StringBuffer * mon_desc(const object *mon)
size_t strlcpy(char *dst, const char *src, size_t size)
object * object_new(void)
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
object * create_archetype(const char *name)
void free_string(sstring str)
static const char *const art_book_name[]
#define MSG_TYPE_CARD_MONEY_1
archetype * find_archetype_by_object_name(const char *name)
#define MSG_TYPE_PAPER_ENVELOPE_1
sstring get_message_title(const GeneralMessage *message)
#define MSG_TYPE_CARD_SIMPLE_3
static const uint32_t spellpathdef[NRSPELLPATHS]
void stringbuffer_delete(StringBuffer *sb)
static StringBuffer * msgfile_msg(object *book, size_t booksize)
const typedef char * sstring
#define MSG_TYPE_PAPER_LETTER_NEW_1
archetype * find_archetype(const char *name)
#define MSG_TYPE_BOOK_ELEGANT_2
int strtoint(const char *buf)
void object_set_msg(object *op, const char *msg)
static void do_monster(archetype *at)
static const arttypename art_name_array[]
#define MSG_TYPE_MONUMENT_STONE_2
void stringbuffer_append_stringbuffer(StringBuffer *sb, const StringBuffer *sb2)
static void new_text_name(object *book, int msgtype)
static const char *const heavy_book_name[]
#define MSGTYPE_SPELLPATH
static const char *const formula_author[]
static titlelist * booklist
#define MSG_TYPE_MONUMENT_STATUE_1
#define MSG_TYPE_MONUMENT_WALL_1
const readable_message_type * get_readable_message_type(object *readable)
static const char *const art_author[]
static const int last_readable_subtype
object * get_random_mon(int level)
int book_overflow(const char *buf1, const char *buf2, size_t booksize)
#define MSG_TYPE_PAPER_NOTE_3
#define MSG_TYPE_BOOK_QUARTO_2
archetype * try_find_archetype(const char *name)
event
DIALOGCHECK MINARGS 1 MAXARGS 2
static StringBuffer * mon_info_msg(int level, size_t booksize, object *book)
static int unique_book(const object *book, int msgtype)
#define MSG_TYPE_CARD_SIMPLE_1
static const char *const light_book_name[]
#define MSG_TYPE_MONUMENT_STONE_1
int object_set_value(object *op, const char *key, const char *value, int add_key)
int buf_overflow(const char *buf1, const char *buf2, size_t bufsize)
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
static void add_book(title *book, int type, const char *fname, int lineno)
#define MSG_TYPE_PAPER_SCROLL_MAGIC
static void make_formula_book(object *book, int level)
#define MSG_TYPE_PAPER_SCROLL_NEW_1
static struct @0 sp_params
static const int max_titles[6]
int nstrtok(const char *buf1, const char *buf2)
artifactlist * find_artifactlist(int type)
#define MSG_TYPE_CARD_STRANGE_3
const Face * get_message_face(const GeneralMessage *message)
const char * recipe_get_difficulty_string(int difficulty)