Crossfire Server, Trunk
readable.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
23 /* laid down initial file - dec 1995. -b.t. thomas@astro.psu.edu */
24 
25 #include "global.h"
26 
27 #include <assert.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/stat.h>
32 
33 #include "book.h"
34 #include "living.h"
35 #include "output_file.h"
36 #include "spells.h"
37 #include "assets.h"
38 #include "AssetsManager.h"
39 
40 /* Define this if you want to archive book titles by contents.
41  * This option should enforce UNIQUE combinations of titles,authors and
42  * msg contents during and *between *game sessions.
43  * Note: a slight degeneracy exists since books are archived based on an integer
44  * index value calculated from the message text (similar to alchemy formulae).
45  * Sometimes two widely different messages have the same index value (rare). In
46  * this case, it is possible to occasionally generate 2 books with same title and
47  * different message content. Not really a bug, but rather a feature. This action
48  * should keeps player on their toes ;).
49  * Also, note that there is *finite *space available for archiving message and titles.
50  * Once this space is used, books will stop being archived. Not a serious problem
51  * under the current regime, since there are generally fewer possible (random)
52  * messages than space available on the titlelists.
53  * One exception (for sure) are the monster messages. But no worries, you should
54  * see all of the monster info in some order (but not all possble combinations)
55  * before the monster titlelist space is run out. You can increase titlelist
56  * space by increasing the array sizes for the monster book_authours and book_names
57  * (see max_titles[] array and include/read.h). Since the unique_book algorthm is
58  * kinda stupid, this program *may *slow down program execution if defined (but I don't
59  * think its a significant problem, at least, I have no problems running this option
60  * on a Sparc 10! Also, once archive title lists are filled and/or all possible msg
61  * combinations have been generated, unique_book isnt called anymore. It takes 5-10
62  * sessions for this to happen).
63  * Final note: the game remembers book/title/msg combinations from reading the
64  * file lib/bookarch. If you REMOVE this file, you will lose your archive. So
65  * be sure to copy it over to the new lib directory when you change versions.
66  * -b.t.
67  */
68 
69 /* This flag is useful to see what kind of output messages are created */
70 /* #define BOOK_MSG_DEBUG */
71 
72 /* This flag is useful for debugging archiving action */
73 /* #define ARCHIVE_DEBUG */
74 
76 #define MAX_TITLE_CHECK 20
77 
79 #define MSGTYPE_LIB 0
80 
81 #define MSGTYPE_MONSTER 1
82 
83 #define MSGTYPE_ARTIFACT 2
84 
85 #define MSGTYPE_SPELLPATH 3
86 
87 #define MSGTYPE_ALCHEMY 4
88 
89 #define MSGTYPE_GODS 5
90 
91 #define MSGTYPE_MSGFILE 6
92 
98 #define arraysize(arrayname) (sizeof(arrayname)/sizeof(*(arrayname)))
99 
100 /* Moved these structures from struct.h to this file in 0.94.3 - they
101  * are not needed anyplace else, so why have them globally declared?
102  */
103 
108 struct title {
109  const char *name;
110  const char *authour;
111  const char *archname;
112  unsigned int level;
113  size_t size;
114  int msg_index;
116 };
117 
121 struct titlelist {
122  int number;
125 };
126 
128 struct arttypename {
129  const char *name;
130  int type;
131 };
132 
133 static void add_book(title *book, int type, const char *fname, int lineno);
134 
139 static titlelist *booklist = NULL;
140 
142 static std::vector<object *> monsters;
143 
149 static const uint32_t spellpathdef[NRSPELLPATHS] = {
150  PATH_PROT,
151  PATH_FIRE,
152  PATH_FROST,
153  PATH_ELEC,
154  PATH_MISSILE,
155  PATH_SELF,
156  PATH_SUMMON,
157  PATH_ABJURE,
158  PATH_RESTORE,
160  PATH_MIND,
161  PATH_CREATE,
162  PATH_TELE,
163  PATH_INFO,
166  PATH_TURNING,
168  PATH_DEATH,
169  PATH_LIGHT
170 };
171 
173 static const char *const path_book_name[] = {
174  "codex",
175  "compendium",
176  "documentary",
177  "exposition",
178  "tables",
179  "treatise"
180 };
181 
183 static const char *const path_author[] = {
184  "aether",
185  "arcana",
186  "astral byways",
187  "connections",
188  "the Grey Council",
189  "deep pathways",
190  "knowledge",
191  "magic",
192  "mystic ways",
193  "pathways",
194  "power",
195  "spells",
196  "transforms",
197  "the mystic veil",
198  "unknown spells"
199 };
200 
207 static const arttypename art_name_array[] = {
208  { "Helmet", HELMET },
209  { "Amulet", AMULET },
210  { "Shield", SHIELD },
211  { "Bracers", BRACERS },
212  { "Boots", BOOTS },
213  { "Cloak", CLOAK },
214  { "Gloves", GLOVES },
215  { "Gridle", GIRDLE },
216  { "Ring", RING },
217  { "Horn", ROD },
218  { "Missile Weapon", BOW },
219  { "Missile", ARROW },
220  { "Hand Weapon", WEAPON },
221  { "Artifact", SKILL },
222  { "Food", FOOD },
223  { "Body Armour", ARMOUR }
224 };
225 
227 static const char *const art_book_name[] = {
228  "assemblage",
229  "collection",
230  "file",
231  "files",
232  "guide",
233  "handbook",
234  "index",
235  "inventory",
236  "list",
237  "listing",
238  "omnibus",
239  "record",
240  "record book",
241  "trove"
242 };
243 
245 static const char *const art_author[] = {
246  "ancient things",
247  "artifacts",
248  "equipment",
249  "Havlor", /* ancient warrior scribe :) */
250  "hoards",
251  "items",
252  "lost artifacts",
253  "the ancients",
254  "treasures",
255  "useful things"
256 };
257 
261 static const char *const mon_book_name[] = {
262  "beastuary",
263  "catalog",
264  "compilation",
265  "collection",
266  "encyclopedia",
267  "field notes",
268  "guide",
269  "handbook",
270  "list",
271  "manual",
272  "notes",
273  "omnibus",
274  "record",
275  "reference",
276  "register",
277  "traveller's guide",
278  "volume"
279 };
280 
282 static const char *const mon_author[] = {
283  "beasts",
284  "beings",
285  "creatures",
286  "dezidens",
287  "dwellers",
288  "evil nature",
289  "Inioda", /* ancient wizard and biologist */
290  "life",
291  "monsters",
292  "nature",
293  "new life",
294  "residents",
295  "the spawn",
296  "the living",
297  "the wilds",
298  "things"
299 };
300 
304 static const char *const gods_book_name[] = {
305  "devotional",
306  "devout notes",
307  "divine text",
308  "divine work",
309  "holy book",
310  "holy record",
311  "hymnal",
312  "illuminated text",
313  "moral text",
314  "pious pamphlet",
315  "sacred guide",
316  "testament",
317  "transcript",
318 };
319 
321 static const char *const gods_author[] = {
322  "cults",
323  "dieties",
324  "joy",
325  "lasting curse",
326  "madness",
327  "religions",
328  "rituals",
329  "the dead",
330  "the gods",
331  "the heirophant",
332  "the poor priest",
333  "the priestess",
334  "pain",
335  "white",
336  "worship"
337 };
338 
342 static const char *const formula_book_name[] = {
343  "cookbook",
344  "formulary",
345  "lab book",
346  "lab notes",
347  "recipe book",
348  "experiment record",
349  "work plan",
350  "design notes",
351  "research notes",
352  "crafting manual"
353 };
354 
356 static const char *const formula_author[] = {
357  "Albertus Magnus",
358  "alchemy",
359  "balms",
360  "creation",
361  "dusts",
362  "magical manufacture",
363  "making",
364  "philosophical items",
365  "potions",
366  "powders",
367  "the cauldron",
368  "the lamp black",
369  "transmutation",
370  "waters"
371 };
372 
378 static const char *const light_book_name[] = {
379  "calendar",
380  "datebook",
381  "diary",
382  "essay",
383  "guidebook",
384  "handbook",
385  "ledger",
386  "notes",
387  "notebook",
388  "octavo",
389  "opuscule",
390  "pamphlet",
391  "practicum",
392  "script",
393  "transcript"
394 };
395 
397 static const char *const heavy_book_name[] = {
398  "catalog",
399  "compendium",
400  "dissertation",
401  "guide",
402  "manual",
403  "opus",
404  "tome",
405  "treatise",
406  "volume",
407  "work"
408 };
409 
411 static const char *const book_author[] = {
412  "Abdulah",
413  "Al'hezred",
414  "Alywn",
415  "Arundel",
416  "Arvind",
417  "Aerlingas",
418  "Bacon",
419  "Baliqendii",
420  "Bosworth",
421  "Beathis",
422  "Bertil",
423  "Cauchy",
424  "Chakrabarti",
425  "der Waalis",
426  "Dirk",
427  "Djwimii",
428  "Eisenstaadt",
429  "Fendris",
430  "Frank",
431  "Habbi",
432  "Harlod",
433  "Ichibod",
434  "Janus",
435  "June",
436  "Laplace",
437  "Magnuson",
438  "Nandii",
439  "Nitfeder",
440  "Norris",
441  "Parael",
442  "Penhew",
443  "Sophia",
444  "Skilly",
445  "Tahir",
446  "Thockmorton",
447  "Thomas",
448  "van Helsing",
449  "van Pelt",
450  "Voormis",
451  "Xavier",
452  "Xeno",
453  "Zardoz",
454  "Zagy"
455 };
456 
458 static const char *const book_descrpt[] = {
459  "ancient",
460  "cryptic",
461  "cryptical",
462  "dusty",
463  "hierarchical",
464  "grizzled",
465  "gold-gilt",
466  "great",
467  "lost",
468  "magnificent",
469  "musty",
470  "mythical",
471  "mystical",
472  "rustic",
473  "stained",
474  "silvered",
475  "transcendental",
476  "weathered"
477 };
478 
486  /*subtype 0 */ { 0, 0 },
487  /* book messages subtypes */
488  /*subtype 1 */ { MSG_TYPE_BOOK, MSG_TYPE_BOOK_CLASP_1 },
497  /*subtype 10 */ { MSG_TYPE_BOOK, MSG_TYPE_BOOK_SPELL_SORCERER },
499  /* card messages subtypes*/
508  /*subtype 20 */ { MSG_TYPE_CARD, MSG_TYPE_CARD_STRANGE_3 },
512  /* Paper messages subtypes */
519  /*subtype 30 */ { MSG_TYPE_PAPER, MSG_TYPE_PAPER_LETTER_NEW_2 },
527  /* road signs messages subtypes */
530  /*subtype 40 */ { MSG_TYPE_SIGN, MSG_TYPE_SIGN_DIR_RIGHT },
532  /* stones and monument messages */
546 };
547 
550 
552 static const int max_titles[6] = {
554  arraysize(mon_book_name)*arraysize(mon_author), /* MSGTYPE_MONSTER */
555  arraysize(art_book_name)*arraysize(art_author), /* MSGTYPE_ARTIFACT */
556  arraysize(path_book_name)*arraysize(path_author), /* MSGTYPE_SPELLPATH */
557  arraysize(formula_book_name)*arraysize(formula_author), /* MSGTYPE_ALCHEMY */
558  arraysize(gods_book_name)*arraysize(gods_author), /* MSGTYPE_GODS */
559 };
560 
561 /******************************************************************************
562  *
563  * Start of misc. readable functions used by others functions in this file
564  *
565  *****************************************************************************/
566 
577  titlelist *bl = (titlelist *)calloc(1, sizeof(titlelist));
578 
579  if (bl == NULL)
581  return bl;
582 }
583 
593 static title *get_empty_book(void) {
594  title *t = (title *)calloc(1, sizeof(title));
595 
596  if (t == NULL)
598  return t;
599 }
600 
611 static titlelist *get_titlelist(int i) {
612  titlelist *tl;
613  int number;
614 
615  if (i < 0 || i >= (int)arraysize(max_titles)) {
616  LOG(llevInfo, "Warning: invalid book index %d, using 0 instead\n", i);
617  return booklist;
618  }
619 
620  for (tl = booklist, number = i; tl && number; tl = tl->next, number--) {
621  if (!tl->next)
622  tl->next = get_empty_booklist();
623  }
624 
625  return tl;
626 }
627 
628 /* HANDMADE STRING FUNCTIONS.., perhaps these belong in another file
629  * (shstr.c ?), but the quantity BOOK_BUF will need to be defined. */
630 
642 int nstrtok(const char *buf1, const char *buf2) {
643  char *tbuf, buf[MAX_BUF];
644  int number = 0;
645 
646  if (!buf1 || !buf2)
647  return 0;
648 
649  strlcpy(buf, buf1, sizeof(buf));
650  for (tbuf = strtok(buf, buf2); tbuf; tbuf = strtok(NULL, buf2)) {
651  number++;
652  }
653  return number;
654 }
655 
661 const char *trim(const char *buf) {
662  while ((*buf) == ' ') {
663  buf++;
664  }
665  return buf;
666 }
667 
684 char *strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size) {
685  int maxi, i = nstrtok(buf1, buf2);
686  char *tbuf, buf[MAX_BUF];
687 
688  maxi = i;
689  strlcpy(buf, buf1, sizeof(buf));
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));
693  i--;
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), ", ");
698  else {
699  // Remove a trailing newline if it is there.
700  int end = strlen(retbuf);
701  if (retbuf[end-1] == '\n')
702  end--;
703  snprintf(retbuf+end, size-end, ".");
704  }
705  }
706  return retbuf;
707 }
708 
719 int book_overflow(const char *buf1, const char *buf2, size_t booksize) {
720  if (buf_overflow(buf1, buf2, BOOK_BUF-2) /* 2 less so always room for trailing \n */
721  || buf_overflow(buf1, buf2, booksize))
722  return 1;
723  return 0;
724 }
725 
726 /*****************************************************************************
727  *
728  * Start of initialization related functions.
729  *
730  ****************************************************************************/
731 
738 static void init_book_archive(void) {
739  FILE *fp;
740 #ifdef BOOK_MSG_DEBUG
741  int nroftitle = 0;
742 #endif
743  char buf[MAX_BUF], fname[MAX_BUF], *cp;
744  static int did_init_barch = 0;
745 
746  if (did_init_barch)
747  return;
748  did_init_barch = 1;
749 
750  if (!booklist)
752 
753  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
754  LOG(llevDebug, " Reading bookarch from %s...\n", fname);
755 
756  fp = fopen(fname, "r");
757  if (fp != NULL) {
758  int type;
759  size_t i;
760  titlelist *bl;
761  int lineno;
762  title *book;
763  int skipping;
764 
765  skipping = 0;
766  book = NULL;
767  type = -1;
768  for (lineno = 1; fgets(buf, MAX_BUF, fp) != NULL; lineno++) {
769  int len;
770  int value;
771 
772  if (*buf == '#')
773  continue;
774  cp = strchr(buf, '\n');
775  if (cp != NULL) {
776  while (cp > buf && (cp[-1] == ' ' || cp[-1] == '\t'))
777  cp--;
778  *cp = '\0';
779  }
780  cp = buf;
781  if (strncmp(buf, "title ", 6) == 0) {
782  skipping = 0;
783  cp = buf+6;
784  while (*cp == ' ' || *cp == '\t')
785  cp++;
786  if (*cp == '\0') {
787  LOG(llevInfo, "Warning: missing book title at %s, line %d\n", fname, lineno);
788  book = NULL;
789  } else {
790  book = get_empty_book(); /* init new book entry */
791  book->name = add_string(cp);
792  type = -1;
793 #ifdef BOOK_MSG_DEBUG
794  nroftitle++;
795 #endif
796  }
797  } else if (book == NULL) {
798  if (!skipping) {
799  skipping = 1;
800  LOG(llevInfo, "Warning: expecting 'title' at %s, line %d\n", fname, lineno);
801  }
802  } else if (strncmp(buf, "authour ", 8) == 0) {
803  cp = buf+8;
804  while (*cp == ' ' || *cp == '\t')
805  cp++;
806  if (*cp == '\0') {
807  LOG(llevInfo, "Warning: missing book authour at %s, line %d\n", fname, lineno);
808  } else {
809  book->authour = add_string(cp);
810  }
811  } else if (strncmp(buf, "arch ", 5) == 0) {
812  cp = buf+5;
813  while (*cp == ' ' || *cp == '\t')
814  cp++;
815  if (*cp == '\0') {
816  LOG(llevInfo, "Warning: missing book arch at %s, line %d\n", fname, lineno);
817  } else {
818  book->archname = add_string(cp);
819  }
820  } else if (sscanf(buf, "level %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
821  book->level = value;
822  } else if (sscanf(buf, "type %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
823  type = value;
824  } else if (sscanf(buf, "size %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
825  book->size = value;
826  } else if (sscanf(buf, "index %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
827  book->msg_index = value;
828  } else if (strcmp(buf, "end") == 0) { /* link it */
829  add_book(book, type, fname, lineno);
830  book = NULL;
831  type = -1;
832  } else {
833  LOG(llevInfo, "Warning: syntax error at %s, line %d\n", fname, lineno);
834  }
835  }
836  if (book != NULL) {
837  LOG(llevInfo, "Warning: missing 'end' at %s, line %d\n", fname, lineno);
838  add_book(book, type, fname, lineno);
839  }
840  LOG(llevDebug, " book archives(used/avail):\n");
841  for (bl = booklist, i = 0; bl != NULL && i < arraysize(max_titles); bl = bl->next, i++) {
842  LOG(llevDebug, "(%d/%d)\n", bl->number, max_titles[i]);
843  }
844  fclose(fp);
845  }
846 
847 #ifdef BOOK_MSG_DEBUG
848  LOG(llevDebug, "\n init_book_archive() got %d titles.\n", nroftitle);
849 #endif
850  LOG(llevDebug, " done.\n");
851 }
852 
860 static void add_book(title *book, int type, const char *fname, int lineno) {
861  titlelist *bl;
862 
863  if (type == -1) {
864  LOG(llevInfo, "Warning: book with no type at %s, line %d; using type 0\n", fname, lineno);
865  type = 0;
866  }
867 
868  bl = get_titlelist(type);
869  book->next = bl->first_book;
870  bl->first_book = book;
871  bl->number++;
872 }
873 
874 static void do_monster(archetype *at) {
875  if (QUERY_FLAG(&at->clone, FLAG_MONSTER) && (!at->head)
878  monsters.push_back(&at->clone);
879  }
880 }
881 
886 static void init_mon_info(void) {
887  static int did_init_mon_info = 0;
888 
889  if (did_init_mon_info)
890  return;
891  did_init_mon_info = 1;
892 
894 
895  LOG(llevDebug, "init_mon_info() got %zu monsters\n", monsters.size());
896 }
897 
904 void init_readable(void) {
905  static int did_this = 0;
906 
907  if (did_this)
908  return;
909  did_this = 1;
910 
911  LOG(llevDebug, "Initializing reading data...\n");
913  init_mon_info();
914  LOG(llevDebug, " done reading data\n");
915 }
916 
917 /*****************************************************************************
918  *
919  * This is the start of the administrative functions when creating
920  * new books (ie, updating title and the like)
921  *
922  *****************************************************************************/
923 
935 static title *find_title(const object *book, int msgtype) {
936  title *t;
937  titlelist *tl;
938  size_t length;
939  int index;
940 
941  if (msgtype < 0)
942  return (title *)NULL;
943 
944  tl = get_titlelist(msgtype);
945  if (!tl)
946  return (title *)NULL;
947 
948  length = strlen(book->msg);
949  index = strtoint(book->msg);
950  for (t = tl->first_book; t; t = t->next)
951  if (t->size == length && t->msg_index == index) {
952 #ifdef ARCHIVE_DEBUG
953  LOG(llevDebug, "Found title match (list %d): %s %s (%d)\n", msgtype, t->name, t->authour, t->msg_index);
954 #endif
955  return t;
956  }
957 
958  return (title *)NULL;
959 }
960 
974 static void new_text_name(object *book, int msgtype) {
975  const char *name;
976 
977  if (book->type != BOOK)
978  return;
979 
980  switch (msgtype) {
981  case MSGTYPE_MONSTER:
983  break;
984 
985  case MSGTYPE_ARTIFACT:
987  break;
988 
989  case MSGTYPE_SPELLPATH:
991  break;
992 
993  case MSGTYPE_ALCHEMY:
995  break;
996 
997  case MSGTYPE_GODS:
999  break;
1000 
1001  case MSGTYPE_MSGFILE:
1002  default:
1003  if (book->weight > 2000) { /* based on weight */
1005  } else {
1007  }
1008  break;
1009  }
1010  free_string(book->name);
1011  book->name = add_string(name);
1012 }
1013 
1023 static void add_author(object *op, int msgtype) {
1024  char title[MAX_BUF];
1025  const char *name;
1026 
1027  if (msgtype < 0 || strlen(op->msg) < 5)
1028  return;
1029 
1030  switch (msgtype) {
1031  case MSGTYPE_MONSTER:
1033  break;
1034 
1035  case MSGTYPE_ARTIFACT:
1037  break;
1038 
1039  case MSGTYPE_SPELLPATH:
1041  break;
1042 
1043  case MSGTYPE_ALCHEMY:
1045  break;
1046 
1047  case MSGTYPE_GODS:
1049  break;
1050 
1051  case MSGTYPE_MSGFILE:
1052  default:
1054  }
1055 
1056  snprintf(title, sizeof(title), "of %s", name);
1057  op->title = add_string(title);
1058 }
1059 
1071 static int unique_book(const object *book, int msgtype) {
1072  title *test;
1073 
1074  if (!booklist)
1075  return 1; /* No archival entries! Must be unique! */
1076 
1077  /* Go through the booklist. If the author and name match, not unique so
1078  * return 0.
1079  */
1080  for (test = get_titlelist(msgtype)->first_book; test; test = test->next) {
1081  if (!strcmp(test->name, book->name) && !strcmp(book->title, test->authour))
1082  return 0;
1083  }
1084  return 1;
1085 }
1086 
1095 static void add_book_to_list(const object *book, int msgtype) {
1096  titlelist *tl = get_titlelist(msgtype);
1097  title *t;
1098 
1099  if (!tl) {
1100  LOG(llevError, "add_book_to_list can't get booklist!\n");
1101  return;
1102  }
1103 
1104  t = get_empty_book();
1105  t->name = add_string(book->name);
1106  t->authour = add_string(book->title);
1107  t->size = strlen(book->msg);
1108  t->msg_index = strtoint(book->msg);
1109  t->archname = add_string(book->arch->name);
1110  t->level = book->level;
1111 
1112  t->next = tl->first_book;
1113  tl->first_book = t;
1114  tl->number++;
1115 
1116  /* We have stuff we need to write now */
1118 
1119 #ifdef ARCHIVE_DEBUG
1120  LOG(llevDebug, "Archiving new title: %s %s (%d)\n", book->name, book->title, msgtype);
1121 #endif
1122 }
1123 
1137 static void change_book(object *book, int msgtype) {
1138  titlelist *tl;
1139  title *t;
1140  int tries;
1141 
1142  if (book->type != BOOK) {
1143  LOG(llevError, "change_book_name() called w/ illegal obj type.\n");
1144  return;
1145  }
1146 
1147  tl = get_titlelist(msgtype);
1148  t = NULL;
1149  tries = 0;
1150 
1151  /* look to see if our msg already been archived. If so, alter
1152  * the book to match the archival text. If we fail to match,
1153  * then we archive the new title/name/msg combo if there is
1154  * room on the titlelist.
1155  */
1156 
1157  if (strlen(book->msg) > 5 && (t = find_title(book, msgtype))) {
1158  object *tmpbook;
1159  sstring marker = object_get_value(book, "knowledge_marker");
1160 
1161  /* alter book properties */
1162  tmpbook = create_archetype(t->archname);
1163  if (marker != NULL)
1164  /* need to copy the knowledge_marker */
1165  object_set_value(tmpbook, "knowledge_marker", marker, 1);
1166  object_set_msg(tmpbook, book->msg);
1167  object_copy(tmpbook, book);
1168  object_free_drop_inventory(tmpbook);
1169 
1170  book->title = add_string(t->authour);
1171  free_string(book->name);
1172  book->name = add_string(t->name);
1173  book->level = t->level;
1174  } else { /* Don't have any default title, so lets make up a new one */
1175  int numb, maxnames = max_titles[msgtype];
1176  const char *old_title;
1177  const char *old_name;
1178 
1179  old_title = book->title ? add_string(book->title) : NULL;
1180  old_name = add_string(book->name);
1181 
1182  /* some pre-generated books have title already set (from
1183  * maps), also don't bother looking for unique title if
1184  * we already used up all the available names! */
1185 
1186  if (!tl) {
1187  LOG(llevError, "change_book_name(): can't find title list\n");
1188  numb = 0;
1189  } else
1190  numb = tl->number;
1191 
1192  if (numb == maxnames) {
1193 #ifdef ARCHIVE_DEBUG
1194  LOG(llevDebug, "titles for list %d full (%d possible).\n", msgtype, maxnames);
1195 #endif
1196  // Set tries to maximum. That way we get the descriptors on books when the
1197  // title set is full, too.
1198  tries = MAX_TITLE_CHECK;
1199  }
1200  /* shouldnt change map-maker books */
1201  else if (!book->title)
1202  do {
1203  /* random book name */
1204  new_text_name(book, msgtype);
1205  add_author(book, msgtype); /* random author */
1206  tries++;
1207  } while (!unique_book(book, msgtype) && tries < MAX_TITLE_CHECK);
1208 
1209  /* Now deal with 2 cases.
1210  * 1) If no space for a new title exists lets just restore
1211  * the old book properties. Remember, if the book had
1212  * matchd an older entry on the titlelist, we shouldnt
1213  * have called this routine in the first place!
1214  * 2) If we got a unique title, we need to add it to
1215  * the list.
1216  */
1217 
1218  if (tries == MAX_TITLE_CHECK) {
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);
1221 #endif
1222  /* restore old book properties here */
1223  free_string(book->name);
1224  if (book->title)
1225  free_string(book->title);
1226  book->title = old_title != NULL ? add_string(old_title) : NULL;
1227 
1228  if (RANDOM()%4) {
1229  /* Lets give the book a description to individualize it some */
1230  char new_name[MAX_BUF];
1231 
1232  snprintf(new_name, MAX_BUF, "%s %s", book_descrpt[RANDOM()%arraysize(book_descrpt)], old_name);
1233  book->name = add_string(new_name);
1234  } else {
1235  book->name = add_string(old_name);
1236  }
1237  } else if (book->title && strlen(book->msg) > 5) { /* archive if long msg texts */
1238  add_book_to_list(book, msgtype);
1239  }
1240 
1241  if (old_title != NULL)
1242  free_string(old_title);
1243  free_string(old_name);
1244  }
1245 }
1246 
1247 /*****************************************************************************
1248  *
1249  * This is the start of the area that generates the actual contents
1250  * of the book.
1251  *
1252  *****************************************************************************/
1253 
1254 /*****************************************************************************
1255  * Monster msg generation code.
1256  ****************************************************************************/
1257 
1269 object *get_random_mon(int level) {
1270 
1271  /* safety check. Problem w/ init_mon_info list? */
1272  if (monsters.empty())
1273  return (object *)NULL;
1274 
1275  if (!level) {
1276  return monsters[RANDOM() % monsters.size()];
1277  }
1278 
1279  std::vector<object *> select;
1280  std::copy_if(monsters.cbegin(), monsters.cend(), std::back_inserter(select), [&] (auto ob) { return ob->level >= level; });
1281 
1282  if (select.empty()) {
1283  LOG(llevError, "get_random_mon() couldn't return monster for level %d\n", level);
1284  return NULL;
1285  }
1286  return select[RANDOM() % select.size()];
1287 }
1288 
1298 static StringBuffer *mon_desc(const object *mon) {
1299  StringBuffer *desc = stringbuffer_new();
1300  stringbuffer_append_printf(desc, "\n---\n *** %s ***\n", mon->name);
1301  describe_item(mon, NULL, 0, desc);
1302  // If a monster has lore, print it here.
1303  if (mon->lore) {
1304  stringbuffer_append_printf(desc, "\n ^ %s", mon->lore);
1305  }
1306  return desc;
1307 }
1308 
1320 static object *get_next_mon(const object *tmp) {
1321  auto it = std::find(monsters.begin(), monsters.end(), tmp);
1322  if (it == monsters.end())
1323  return nullptr;
1324  ++it;
1325  if (it == monsters.end())
1326  it = monsters.begin();
1327 
1328  return *it;
1329 }
1330 
1343 static StringBuffer *mon_info_msg(int level, size_t booksize, object *book) {
1344  object *tmp;
1345  StringBuffer *marker = stringbuffer_new(), *desc = stringbuffer_new(), *mon = NULL;
1346  int added = 0;
1347  sstring final;
1348  const char *sep = ":";
1349 
1350  /*preamble */
1351  stringbuffer_append_string(desc, "This beastiary contains:");
1352  stringbuffer_append_string(marker, "monster");
1353 
1354  /* lets print info on as many monsters as will fit in our
1355  * document.
1356  * 8-96 Had to change this a bit, otherwise there would
1357  * have been an impossibly large number of combinations
1358  * of text! (and flood out the available number of titles
1359  * in the archive in a snap!) -b.t.
1360  */
1361  for (tmp = get_random_mon(level*3); tmp; tmp = get_next_mon(tmp)) {
1362  /* monster description */
1363  mon = mon_desc(tmp);
1364 
1366  break;
1367  added++;
1368  stringbuffer_append_printf(marker, "%s%s", sep, tmp->arch->name);
1369  sep = "/";
1372  mon = NULL;
1373  }
1374 
1375  if (mon != NULL) {
1377  }
1378 
1379  final = stringbuffer_finish_shared(marker);
1380  if (added)
1381  object_set_value(book, "knowledge_marker", final, 1);
1382  free_string(final);
1383 
1384  return desc;
1385 }
1386 
1387 /*****************************************************************************
1388  * Artifact msg generation code.
1389  ****************************************************************************/
1390 
1400 static StringBuffer *artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator) {
1401  object *tmp;
1402  int chance;
1403  StringBuffer *desc = stringbuffer_new(), *sbuf;
1404 
1405  if (separator)
1406  stringbuffer_append_string(desc, "---\n");
1407 
1408  /* Name */
1409  if (!art->allowed.empty()) {
1410  archetype *arch;
1411  auto name = art->allowed[RANDOM() % art->allowed.size()];
1412  int inv = 0;
1413 
1414  if (name[0] == '!')
1415  inv = 1;
1416 
1419  if (!arch)
1421 
1422  if (!arch)
1423  LOG(llevError, "artifact_msg: missing archetype %s for artifact %s (type %d)\n", name + inv, art->item->name, art->item->type);
1424  else {
1425  if (inv)
1426  stringbuffer_append_printf(desc, " A %s (excepted %s) of %s", art_name_array[art_name].name, arch->clone.name_pl, art->item->name);
1427  else
1428  stringbuffer_append_printf(desc, " A %s of %s", arch->clone.name, art->item->name);
1429  }
1430  } else { /* default name is used */
1431  /* use the base 'generic' name for our artifact */
1432  stringbuffer_append_printf(desc, " The %s of %s", art_name_array[art_name].name, art->item->name);
1433  }
1434 
1435  /* chance of finding */
1436  stringbuffer_append_string(desc, " is ");
1437  chance = 100*((float)art->chance/al->total_chance);
1438  if (chance >= 20)
1439  stringbuffer_append_string(desc, "an uncommon");
1440  else if (chance >= 10)
1441  stringbuffer_append_string(desc, "an unusual");
1442  else if (chance >= 5)
1443  stringbuffer_append_string(desc, "a rare");
1444  else
1445  stringbuffer_append_string(desc, "a very rare");
1446 
1447  /* value of artifact */
1448  stringbuffer_append_printf(desc, " item with a value that is %d times normal.\n", art->item->value);
1449 
1450  /* include the message about the artifact, if exists, and book
1451  * level is kinda high */
1452  if (message && !(strlen(art->item->msg) > BOOK_BUF))
1453  stringbuffer_append_string(desc, art->item->msg);
1454 
1455  /* properties of the artifact */
1456  tmp = object_new();
1457  add_abilities(tmp, art->item);
1458  tmp->type = al->type;
1460  sbuf = describe_item(tmp, NULL, 0, NULL);
1461  if (stringbuffer_length(sbuf) > 1) {
1462  stringbuffer_append_string(desc, " Properties of this artifact include:\n ");
1464  stringbuffer_append_string(desc, "\n");
1465  }
1466  free(stringbuffer_finish(sbuf));
1468 
1469  return desc;
1470 }
1471 
1483 static StringBuffer *artifact_msg(unsigned int level, size_t booksize) {
1484  const artifactlist *al;
1485  const artifact *art;
1486  int i, type, index;
1487  int book_entries = level > 5 ? RANDOM()%3+RANDOM()%3+2 : RANDOM()%level+1;
1489 
1490  /* values greater than 5 create msg buffers that are too big! */
1491  if (book_entries > 5)
1492  book_entries = 5;
1493 
1494  /* lets determine what kind of artifact type randomly.
1495  * Right now legal artifacts only come from those listed
1496  * in art_name_array. Also, we check to be sure an artifactlist
1497  * for that type exists!
1498  */
1499  i = 0;
1500  do {
1503  al = find_artifactlist(type);
1504  i++;
1505  } while (al == NULL && i < 10);
1506 
1507  if (i == 10) { /* Unable to find a message */
1509  return message;
1510  }
1511 
1512  /* There is no reason to start on the artifact list at the beginning. Lets
1513  * take our starting position randomly... */
1514  auto iart = al->items.cbegin();
1515  for (i = RANDOM()%level+RANDOM()%2+1; i > 0; i--) {
1516  if (iart == al->items.cend())
1517  iart = al->items.cbegin(); /* hmm, out of stuff, loop back around */
1518  ++iart;
1519  }
1520 
1521  /* Ok, lets print out the contents */
1522  stringbuffer_append_printf(message, "Herein %s detailed %s...\n", book_entries > 1 ? "are" : "is", book_entries > 1 ? "some artifacts" : "an artifact");
1523 
1524  i = 0;
1525  /* artifact msg attributes loop. Lets keep adding entries to the 'book'
1526  * as long as we have space up to the allowed max # (book_entires)
1527  */
1528  while (book_entries > 0) {
1529  int with_message;
1530  if (iart == al->items.cend())
1531  iart = al->items.cbegin();
1532  art = *iart;
1533  with_message = (art->item->msg && RANDOM()%4+1 < level) ? 1 : 0;
1534 
1535  desc = artifact_describe(art, al, with_message, index, i++);
1536 
1538  stringbuffer_delete(desc);
1539  break;
1540  }
1541 
1543  stringbuffer_delete(desc);
1544 
1545  ++iart;
1546  book_entries--;
1547  }
1548 
1549  return message;
1550 }
1551 
1552 /*****************************************************************************
1553  * Spellpath message generation
1554  *****************************************************************************/
1555 
1557 static struct {
1558  int prayers;
1559  int did_first_sp;
1560  uint32_t pnum;
1561  int level;
1562  size_t booksize;
1564  int done;
1568 static void do_spellpath_msg(archetype *at) {
1569  /* Determine if this is an appropriate spell. Must
1570  * be of matching path, must be of appropriate type (prayer
1571  * or not), and must be within the valid level range.
1572  */
1573  if (at->clone.type == SPELL
1574  && at->clone.path_attuned & sp_params.pnum
1575  && ((at->clone.stats.grace && sp_params.prayers) || (at->clone.stats.sp && !sp_params.prayers))
1576  && at->clone.level < sp_params.level*8) {
1577  if (strlen(at->clone.name) + stringbuffer_length(sp_params.buf) >= sp_params.booksize) {
1578  sp_params.done = 1;
1579  return;
1580  }
1581 
1582  if (sp_params.did_first_sp)
1584  sp_params.did_first_sp = 1;
1586  }
1587 }
1588 
1603  int path = RANDOM()%NRSPELLPATHS;
1604  sp_params.prayers = RANDOM()%2;
1605  sp_params.did_first_sp = 0;
1606  sp_params.pnum = spellpathdef[path];
1607  sp_params.done = 0;
1608 
1609  if (buf == NULL) {
1610  buf = stringbuffer_new();
1611  /* Preamble */
1612  stringbuffer_append_printf(buf, "Herein are detailed the names of %s", sp_params.prayers ? "prayers" : "incantations");
1613  stringbuffer_append_printf(buf, " belonging to the path of %s:\n ", spellpathnames[path]);
1614  }
1615  sp_params.level = level;
1616  sp_params.booksize = booksize;
1617  sp_params.buf = buf;
1618 
1620 
1621  /* Geez, no spells were generated. */
1622  if (!sp_params.did_first_sp) {
1623  if (RANDOM()%4) { /* usually, lets make a recursive call... */
1624  // If we do a recursive call, we reset the spell path, so we will want to reset our text as well.
1626  return spellpath_msg(level, booksize, NULL);
1627  }
1628  /* give up, cause knowing no spells exist for path is info too. need the header too. */
1629  stringbuffer_append_string(buf, "- no known spells exist -\n");
1630  }
1631  return buf;
1632 }
1633 
1642 static void make_formula_book(object *book, int level) {
1643  recipelist *fl;
1644  recipe *formula;
1645  int chance, count = 0;
1646  const char *op_name;
1647  archetype *at;
1648  StringBuffer *text, *title;
1649  char *final, km[MAX_BUF];
1650 
1651  /* the higher the book level, the more complex (ie number of
1652  * ingredients) the formula can be.
1653  */
1654  fl = get_formulalist((RANDOM()%level)/3+1);
1655  if (!fl)
1656  fl = get_formulalist(1); /* safety */
1657 
1658  if (fl->total_chance == 0) {
1659  object_set_msg(book, " <indecipherable text>\n");
1661  add_author(book, MSGTYPE_ALCHEMY);
1662  return;
1663  }
1664 
1665  /* get a random formula, weighted by its bookchance */
1666  chance = RANDOM()%fl->total_chance;
1667  for (formula = fl->items; formula != NULL; formula = formula->next) {
1668  chance -= formula->chance;
1669  if (chance <= 0 && formula->chance != 0 && !formula->is_combination)
1670  break;
1671  }
1672 
1673  if (!formula || formula->arch_names <= 0) {
1674  object_set_msg(book, " <indecipherable text>\n");
1676  add_author(book, MSGTYPE_ALCHEMY);
1677  return;
1678  }
1679 
1680  /* looks like a formula was found. Base the amount
1681  * of information on the booklevel and the spellevel
1682  * of the formula. */
1683 
1684  op_name = formula->arch_name[RANDOM()%formula->arch_names];
1685  at = find_archetype(op_name);
1686  if (at == (archetype *)NULL) {
1687  LOG(llevError, "formula_msg() can't find arch %s for formula.\n", op_name);
1688  object_set_msg(book, " <indecipherable text>\n");
1690  add_author(book, MSGTYPE_ALCHEMY);
1691  return;
1692  }
1693  op_name = at->clone.name;
1694 
1695  text = stringbuffer_new();
1696  title = stringbuffer_new();
1697 
1698  /* preamble */
1699  stringbuffer_append_printf(text, "Herein is described a%s %s project using %s:\n",
1700  formula->diff >= 10 && formula->diff < 15 ? "n" : "",
1702  formula->skill ? formula->skill : "an unknown skill");
1703 
1704  /* item name */
1705  if (strcmp(formula->title, "NONE")) {
1706  stringbuffer_append_printf(text, "The %s of %s", op_name, formula->title);
1707  /* This results in things like pile of philo. sulfur.
1708  * while philo. sulfur may look better, without this,
1709  * you get things like 'the wise' because its missing the
1710  * water of section.
1711  */
1713  } else {
1714  stringbuffer_append_printf(text, "The %s", op_name);
1716  if (at->clone.title) {
1719  }
1720  }
1721  /* Lets name the book something meaningful ! */
1722  if (book->name)
1723  free_string(book->name);
1725  if (book->title) {
1726  free_string(book->title);
1727  book->title = NULL;
1728  }
1729 
1730  /* ingredients to make it */
1731  if (formula->ingred != NULL) {
1732  linked_char *next;
1733  archetype *at;
1734  char name[MAX_BUF];
1735 
1736  at = find_archetype(formula->cauldron);
1737  if (at)
1738  query_name(&at->clone, name, MAX_BUF);
1739  else
1740  snprintf(name, sizeof(name), "an unknown place");
1741 
1742  stringbuffer_append_printf(text, " may be made at %s using the following ingredients:\n", name);
1743 
1744  for (next = formula->ingred; next != NULL; next = next->next) {
1745  count++;
1746  stringbuffer_append_printf(text, "%s\n", next->name);
1747  }
1748  } else {
1749  LOG(llevError, "formula_msg() no ingredient list for object %s of %s\n", op_name, formula->title);
1751  }
1752 
1753  final = stringbuffer_finish(text);
1754  object_set_msg(book, final);
1755  free(final);
1756 
1759  snprintf(km, sizeof(km), "alchemy:%d:%d:%s", count, formula->index, formula->title);
1760  object_set_value(book, "knowledge_marker", km, 1);
1761 }
1762 
1773 static StringBuffer *msgfile_msg(object *book, size_t booksize) {
1774  StringBuffer *ret = stringbuffer_new();
1775 
1777 
1778  if (msg && strlen(msg->message) <= booksize) {
1779  stringbuffer_append_string(ret, msg->message);
1780  if (msg->identifier != NULL) {
1781  char km[HUGE_BUF];
1784  snprintf(km, sizeof(km), "message:%s", msg->identifier);
1785  object_set_value(book, "knowledge_marker", km, 1);
1786  }
1787  if (msg->quest_code) {
1788  /* add a 'apply' hook to launch the quest */
1789  archetype *at = find_archetype("quest_advance_apply");
1790  if (at != NULL) {
1791  object *event = object_create_arch(at);
1792  FREE_AND_COPY(event->name, msg->quest_code);
1793  object_insert_in_ob(event, book);
1794  }
1795  }
1796  } else {
1797 #ifdef BOOK_MSG_DEBUG
1798  // If msg was defined when we got here, we overflowed a book.
1799  if (msg)
1800  LOG(llevDebug, "Could not fit message %s into %s (%ld > %ld)\n", msg->identifier, book->name, strlen(msg->message), booksize);
1801 #endif
1802  stringbuffer_append_string(ret, "\n <undecipherable text>");
1803  }
1804 
1805  return ret;
1806 }
1807 
1822 static StringBuffer *god_info_msg(int level, size_t booksize, object *book) {
1823  int what = 0;
1824  const object *god = get_rand_god();
1825  StringBuffer *desc = NULL;
1826 
1827  if (!god)
1828  return NULL; /* oops, problems... */
1829 
1830  if (booksize > BOOK_BUF) {
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);
1832  booksize = BOOK_BUF;
1833  }
1834 
1835  if (level >= 2 && RANDOM()%2) {
1836  what |= GOD_ENEMY;
1837  }
1838  if (level >= 3 && RANDOM()%2) {
1839  what |= GOD_HOLYWORD;
1840  }
1841  if (level >= 4 && RANDOM()%2) {
1842  what |= GOD_RESISTANCES;
1843  }
1844  if (level >= 5 && RANDOM()%2) {
1845  what |= GOD_SACRED;
1846  }
1847  if (level >= 6 && RANDOM()%2) {
1848  what |= GOD_BLESSED;
1849  }
1850  if (level >= 8 && RANDOM()%2) {
1851  what |= GOD_IMMUNITIES;
1852  }
1853  if (level >= 12 && RANDOM()%2) {
1854  what |= GOD_PATHS;
1855  }
1856 
1857  desc = stringbuffer_new();
1858  what = describe_god(god, what, desc, booksize);
1859 
1860  /* check to be sure new buffer size dont exceed either
1861  * the maximum buffer size, or the 'natural' size of the
1862  * book... */
1863  if (stringbuffer_length(desc) > 1 && stringbuffer_length(desc) <= booksize) {
1864  char buf[BOOK_BUF];
1865  snprintf(buf, sizeof(buf), "god:%s:%d", god->name, what);
1866  object_set_value(book, "knowledge_marker", buf, 1);
1867  return desc;
1868  }
1869 
1870  stringbuffer_delete(desc);
1871  return NULL;
1872 }
1873 
1892 void tailor_readable_ob(object *book, int msg_type) {
1893  int level = book->level ? RANDOM()%book->level+1 : 1;
1894  size_t book_buf_size;
1895  StringBuffer *message = NULL;
1896 
1897  /* safety */
1898  if (book->type != BOOK)
1899  return;
1900 
1901  if (level <= 0)
1902  return; /* if no level no point in doing any more... */
1903 
1904  /* Max text length this book can have. */
1905  book_buf_size = BOOKSIZE(book);
1906  book_buf_size -= strlen("\n"); /* Keep enough for final \n. */
1907  assert(book_buf_size < BOOK_BUF);
1908 
1909  /* &&& The message switch &&& */
1910  /* Below all of the possible types of messages in the "book"s.
1911  */
1912  /*
1913  * IF you add a new type of book msg, you will have to do several things.
1914  * 1) make sure there is an entry in the msg switch below!
1915  * 2) make sure there is an entry in max_titles[] array.
1916  * 3) make sure there are entries for your case in new_text_title()
1917  * and add_authour().
1918  * 4) you may want separate authour/book name arrays in read.h
1919  */
1920 
1921  if (msg_type >= (int)arraysize(max_titles))
1922  msg_type = 0;
1923 
1924  msg_type = msg_type > 0 ? msg_type : (int)(RANDOM()%6);
1925  switch (msg_type) {
1926  case MSGTYPE_MONSTER:
1927  message = mon_info_msg(level, book_buf_size, book);
1928  break;
1929 
1930  case MSGTYPE_ARTIFACT:
1931  message = artifact_msg(level, book_buf_size);
1932  break;
1933 
1934  case MSGTYPE_SPELLPATH: /* grouping incantations/prayers by path */
1935  message = spellpath_msg(level, book_buf_size, NULL);
1936  break;
1937 
1938  case MSGTYPE_ALCHEMY: /* describe an alchemy formula */
1939  make_formula_book(book, level);
1940  /* make_formula_book already gives title */
1941  return;
1942  break;
1943 
1944  case MSGTYPE_GODS: /* bits of information about a god */
1945  message = god_info_msg(level, book_buf_size, book);
1946  break;
1947 
1948  case MSGTYPE_LIB: /* use info list in lib/ */
1949  default:
1950  message = msgfile_msg(book, book_buf_size);
1951  break;
1952  }
1953 
1954  if (message != NULL) {
1955  char *final;
1957  final = stringbuffer_finish(message);
1958  object_set_msg(book, final);
1959  free(final);
1960  /* lets give the "book" a new name, which may be a compound word */
1961  change_book(book, msg_type);
1962  }
1963 }
1964 
1965 /*****************************************************************************
1966  *
1967  * Cleanup routine for readable stuff.
1968  *
1969  *****************************************************************************/
1970 
1974 void free_all_readable(void) {
1975  titlelist *tlist, *tnext;
1976  title *title1, *titlenext;
1977 
1978  LOG(llevDebug, "freeing all book information\n");
1979 
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;
1984  if (title1->name)
1985  free_string(title1->name);
1986  if (title1->authour)
1987  free_string(title1->authour);
1988  if (title1->archname)
1989  free_string(title1->archname);
1990  free(title1);
1991  }
1992  free(tlist);
1993  }
1994 }
1995 
1996 /*****************************************************************************
1997  *
1998  * Writeback routine for updating the bookarchive.
1999  *
2000  ****************************************************************************/
2001 
2006  FILE *fp;
2007  OutputFile of;
2008  int index;
2009  char fname[MAX_BUF];
2010  title *book;
2011  titlelist *bl;
2012 
2013  /* If nothing changed, don't write anything */
2015  return;
2016 
2017  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
2018  LOG(llevDebug, "Updating book archive: %s...\n", fname);
2019 
2020  fp = of_open(&of, fname);
2021  if (fp == NULL)
2022  return;
2023 
2024  for (bl = get_titlelist(0), index = 0; bl; bl = bl->next, index++) {
2025  for (book = bl->first_book; book; book = book->next)
2026  if (book && book->authour) {
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);
2032  /* C89 doesn't have %zu... */
2033  fprintf(fp, "size %lu\n", (unsigned long)book->size);
2034  fprintf(fp, "index %d\n", book->msg_index);
2035  fprintf(fp, "end\n");
2036  }
2037  }
2038  if (!of_close(&of))
2039  return;
2040 
2041  if (chmod(fname, SAVE_MODE) != 0) {
2042  LOG(llevError, "Could not set permissions on '%s'\n", fname);
2043  }
2044 
2046 }
2047 
2056  uint8_t subtype = readable->subtype;
2057 
2058  if (subtype > last_readable_subtype)
2059  return &readable_message_types[0];
2060  return &readable_message_types[subtype];
2061 }
2062 
2069  return message->title;
2070 }
2071 
2078  return message->message;
2079 }
2080 
2087  return message->face;
2088 }
write_book_archive
void write_book_archive(void)
Definition: readable.cpp:2005
PATH_TURNING
#define PATH_TURNING
Definition: spells.h:29
MSG_TYPE_MONUMENT_WALL_2
#define MSG_TYPE_MONUMENT_WALL_2
Definition: newclient.h:486
give.next
def next
Definition: give.py:44
Face
Definition: face.h:14
formula_book_name
static const char *const formula_book_name[]
Definition: readable.cpp:342
MSG_TYPE_BOOK_SPELL_PRAYER
#define MSG_TYPE_BOOK_SPELL_PRAYER
Definition: newclient.h:433
output_file.h
global.h
GOD_IMMUNITIES
#define GOD_IMMUNITIES
Definition: god.h:18
change_book
static void change_book(object *book, int msgtype)
Definition: readable.cpp:1137
settings
struct Settings settings
Definition: init.cpp:139
path_book_name
static const char *const path_book_name[]
Definition: readable.cpp:173
stringbuffer_length
size_t stringbuffer_length(StringBuffer *sb)
Definition: stringbuffer.cpp:218
GeneralMessage
Definition: book.h:44
get_formulalist
recipelist * get_formulalist(int i)
Definition: recipe.cpp:98
SAVE_MODE
#define SAVE_MODE
Definition: config.h:563
title::authour
const char * authour
Definition: readable.cpp:110
get_empty_booklist
static titlelist * get_empty_booklist(void)
Definition: readable.cpp:576
do_spellpath_msg
static void do_spellpath_msg(archetype *at)
Definition: readable.cpp:1568
mon_author
static const char *const mon_author[]
Definition: readable.cpp:282
BOW
@ BOW
Definition: object.h:123
BRACERS
@ BRACERS
Definition: object.h:222
PATH_LIGHT
#define PATH_LIGHT
Definition: spells.h:32
llevError
@ llevError
Definition: logger.h:11
init_mon_info
static void init_mon_info(void)
Definition: readable.cpp:886
GOD_PATHS
#define GOD_PATHS
Definition: god.h:19
PATH_RESTORE
#define PATH_RESTORE
Definition: spells.h:21
object::path_attuned
uint32_t path_attuned
Definition: object.h:353
get_empty_book
static title * get_empty_book(void)
Definition: readable.cpp:593
MSG_TYPE_PAPER_LETTER_OLD_2
#define MSG_TYPE_PAPER_LETTER_OLD_2
Definition: newclient.h:457
PATH_INFO
#define PATH_INFO
Definition: spells.h:26
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
arraysize
#define arraysize(arrayname)
Definition: readable.cpp:98
MSG_TYPE_BOOK_SPELL_SUMMONER
#define MSG_TYPE_BOOK_SPELL_SUMMONER
Definition: newclient.h:436
book_author
static const char *const book_author[]
Definition: readable.cpp:411
of_close
int of_close(OutputFile *of)
Definition: output_file.cpp:61
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
MONSTER_EXCLUDE_FROM_READABLE_KEY
#define MONSTER_EXCLUDE_FROM_READABLE_KEY
Definition: object.h:596
free_all_readable
void free_all_readable(void)
Definition: readable.cpp:1974
AssetsManager::messages
Messages * messages()
Definition: AssetsManager.h:59
PATH_ELEC
#define PATH_ELEC
Definition: spells.h:16
monsters
static std::vector< object * > monsters
Definition: readable.cpp:142
of_open
FILE * of_open(OutputFile *of, const char *fname)
Definition: output_file.cpp:30
GLOVES
@ GLOVES
Definition: object.h:218
arttypename::name
const char * name
Definition: readable.cpp:129
GIRDLE
@ GIRDLE
Definition: object.h:228
PATH_FIRE
#define PATH_FIRE
Definition: spells.h:14
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
recipe::arch_names
size_t arch_names
Definition: recipe.h:12
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
archetypes_for_each
void archetypes_for_each(arch_op op)
Definition: assets.cpp:301
AssetsManager.h
spellpathnames
const char *const spellpathnames[NRSPELLPATHS]
Definition: init.cpp:240
mon_book_name
static const char *const mon_book_name[]
Definition: readable.cpp:261
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.cpp:138
path_author
static const char *const path_author[]
Definition: readable.cpp:183
artifact_msg
static StringBuffer * artifact_msg(unsigned int level, size_t booksize)
Definition: readable.cpp:1483
MSG_TYPE_PAPER
#define MSG_TYPE_PAPER
Definition: newclient.h:400
MSG_TYPE_PAPER_LETTER_NEW_2
#define MSG_TYPE_PAPER_LETTER_NEW_2
Definition: newclient.h:459
object::arch
struct archetype * arch
Definition: object.h:424
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
MSG_TYPE_BOOK_QUARTO_1
#define MSG_TYPE_BOOK_QUARTO_1
Definition: newclient.h:430
PATH_SELF
#define PATH_SELF
Definition: spells.h:18
MSG_TYPE_SIGN_BASIC
#define MSG_TYPE_SIGN_BASIC
Definition: newclient.h:469
artifactlist::items
std::vector< artifact * > items
Definition: artifact.h:28
gods_book_name
static const char *const gods_book_name[]
Definition: readable.cpp:304
ARMOUR
@ ARMOUR
Definition: object.h:125
MSG_TYPE_PAPER_SCROLL_NEW_2
#define MSG_TYPE_PAPER_SCROLL_NEW_2
Definition: newclient.h:465
WEAPON
@ WEAPON
Definition: object.h:124
MSG_TYPE_PAPER_SCROLL_OLD_2
#define MSG_TYPE_PAPER_SCROLL_OLD_2
Definition: newclient.h:463
MSG_TYPE_PAPER_NOTE_2
#define MSG_TYPE_PAPER_NOTE_2
Definition: newclient.h:454
guildjoin.ob
ob
Definition: guildjoin.py:42
MSG_TYPE_CARD_MONEY_2
#define MSG_TYPE_CARD_MONEY_2
Definition: newclient.h:449
MSG_TYPE_MONUMENT_STATUE_3
#define MSG_TYPE_MONUMENT_STATUE_3
Definition: newclient.h:481
artifact::item
object * item
Definition: artifact.h:15
commongive.inv
inv
Definition: commongive.py:29
god_info_msg
static StringBuffer * god_info_msg(int level, size_t booksize, object *book)
Definition: readable.cpp:1822
add_abilities
void add_abilities(object *op, const object *change)
Definition: artifact.cpp:320
AMULET
@ AMULET
Definition: object.h:144
recipelist::items
recipe * items
Definition: recipe.h:40
archetype::head
archetype * head
Definition: object.h:485
MSG_TYPE_PAPER_LETTER_OLD_1
#define MSG_TYPE_PAPER_LETTER_OLD_1
Definition: newclient.h:456
strtoktolin
char * strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size)
Definition: readable.cpp:684
MSG_TYPE_SIGN_DIR_RIGHT
#define MSG_TYPE_SIGN_DIR_RIGHT
Definition: newclient.h:471
mon
object * mon
Definition: comet_perf.cpp:75
gods_author
static const char *const gods_author[]
Definition: readable.cpp:321
title::name
const char * name
Definition: readable.cpp:109
MSG_TYPE_CARD_SIMPLE_2
#define MSG_TYPE_CARD_SIMPLE_2
Definition: newclient.h:440
SKILL
@ SKILL
Definition: object.h:148
titlelist
Definition: readable.cpp:121
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
Ice.tmp
int tmp
Definition: Ice.py:207
recipe::arch_name
char ** arch_name
Definition: recipe.h:13
artifact::allowed
std::vector< sstring > allowed
Definition: artifact.h:18
MSG_TYPE_BOOK_CLASP_2
#define MSG_TYPE_BOOK_CLASP_2
Definition: newclient.h:427
MSG_TYPE_CARD
#define MSG_TYPE_CARD
Definition: newclient.h:399
prayers
int prayers
Definition: readable.cpp:1560
booksize
size_t booksize
Definition: readable.cpp:1564
MSGTYPE_MONSTER
#define MSGTYPE_MONSTER
Definition: readable.cpp:81
MSG_TYPE_BOOK_ELEGANT_1
#define MSG_TYPE_BOOK_ELEGANT_1
Definition: newclient.h:428
object::title
sstring title
Definition: object.h:325
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4346
GOD_BLESSED
#define GOD_BLESSED
Definition: god.h:17
object::level
int16_t level
Definition: object.h:361
buf
StringBuffer * buf
Definition: readable.cpp:1565
title::size
size_t size
Definition: readable.cpp:113
getManager
AssetsManager * getManager()
Definition: assets.cpp:305
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2857
recipelist::total_chance
int total_chance
Definition: recipe.h:38
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
PATH_ABJURE
#define PATH_ABJURE
Definition: spells.h:20
readable_message_types
static const readable_message_type readable_message_types[]
Definition: readable.cpp:485
GOD_HOLYWORD
#define GOD_HOLYWORD
Definition: god.h:14
titlelist::first_book
title * first_book
Definition: readable.cpp:123
linked_char
Definition: global.h:96
recipe::is_combination
int is_combination
Definition: recipe.h:31
find_title
static title * find_title(const object *book, int msgtype)
Definition: readable.cpp:935
get_next_mon
static object * get_next_mon(const object *tmp)
Definition: readable.cpp:1320
MSG_TYPE_PAPER_SCROLL_OLD_1
#define MSG_TYPE_PAPER_SCROLL_OLD_1
Definition: newclient.h:462
need_to_write_bookarchive
static int need_to_write_bookarchive
Definition: readable.cpp:144
MSG_TYPE_CARD_STRANGE_1
#define MSG_TYPE_CARD_STRANGE_1
Definition: newclient.h:445
PATH_MISSILE
#define PATH_MISSILE
Definition: spells.h:17
CLOAK
@ CLOAK
Definition: object.h:209
Messages::random
GeneralMessage * random()
Definition: Messages.cpp:50
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
MSGTYPE_MSGFILE
#define MSGTYPE_MSGFILE
Definition: readable.cpp:91
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1560
add_author
static void add_author(object *op, int msgtype)
Definition: readable.cpp:1023
HELMET
@ HELMET
Definition: object.h:141
get_rand_god
const object * get_rand_god(void)
Definition: holy.cpp:73
object::subtype
uint8_t subtype
Definition: object.h:349
recipelist
Definition: recipe.h:37
MSG_TYPE_MONUMENT_GRAVESTONE_1
#define MSG_TYPE_MONUMENT_GRAVESTONE_1
Definition: newclient.h:482
PATH_WOUNDING
#define PATH_WOUNDING
Definition: spells.h:30
MSG_TYPE_MONUMENT
#define MSG_TYPE_MONUMENT
Definition: newclient.h:402
PATH_CREATE
#define PATH_CREATE
Definition: spells.h:24
MSG_TYPE_CARD_STRANGE_2
#define MSG_TYPE_CARD_STRANGE_2
Definition: newclient.h:446
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:588
MSG_TYPE_SIGN_DIR_BOTH
#define MSG_TYPE_SIGN_DIR_BOTH
Definition: newclient.h:472
MSG_TYPE_MONUMENT_GRAVESTONE_2
#define MSG_TYPE_MONUMENT_GRAVESTONE_2
Definition: newclient.h:483
get_titlelist
static titlelist * get_titlelist(int i)
Definition: readable.cpp:611
PATH_DETONATE
#define PATH_DETONATE
Definition: spells.h:22
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.cpp:85
MSG_TYPE_SIGN_DIR_LEFT
#define MSG_TYPE_SIGN_DIR_LEFT
Definition: newclient.h:470
archetype::clone
object clone
Definition: object.h:487
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
MSG_TYPE_BOOK_CLASP_1
#define MSG_TYPE_BOOK_CLASP_1
Definition: newclient.h:426
book_descrpt
static const char *const book_descrpt[]
Definition: readable.cpp:458
ROD
@ ROD
Definition: object.h:114
init_readable
void init_readable(void)
Definition: readable.cpp:904
titlelist::next
titlelist * next
Definition: readable.cpp:124
python_init.path
path
Definition: python_init.py:8
done
int done
Definition: readable.cpp:1566
init_book_archive
static void init_book_archive(void)
Definition: readable.cpp:738
tailor_readable_ob
void tailor_readable_ob(object *book, int msg_type)
Definition: readable.cpp:1892
spellpath_msg
static StringBuffer * spellpath_msg(int level, size_t booksize, StringBuffer *buf)
Definition: readable.cpp:1602
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
object::value
int32_t value
Definition: object.h:360
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Definition: global.h:204
MSG_TYPE_MONUMENT_STATUE_2
#define MSG_TYPE_MONUMENT_STATUE_2
Definition: newclient.h:480
add_book_to_list
static void add_book_to_list(const object *book, int msgtype)
Definition: readable.cpp:1095
object::type
uint8_t type
Definition: object.h:348
PATH_SUMMON
#define PATH_SUMMON
Definition: spells.h:19
MSG_TYPE_CARD_ELEGANT_1
#define MSG_TYPE_CARD_ELEGANT_1
Definition: newclient.h:442
recipe::index
int index
Definition: recipe.h:18
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:298
book.h
MAX_TITLE_CHECK
#define MAX_TITLE_CHECK
Definition: readable.cpp:76
title
Definition: readable.cpp:108
artifactlist
Definition: artifact.h:24
arttypename
Definition: readable.cpp:128
PATH_TRANSFER
#define PATH_TRANSFER
Definition: spells.h:28
disinfect.count
int count
Definition: disinfect.py:7
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
MSG_TYPE_CARD_ELEGANT_3
#define MSG_TYPE_CARD_ELEGANT_3
Definition: newclient.h:444
artifact_describe
static StringBuffer * artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator)
Definition: readable.cpp:1400
PATH_FROST
#define PATH_FROST
Definition: spells.h:15
archetype
Definition: object.h:483
MSG_TYPE_CARD_MONEY_3
#define MSG_TYPE_CARD_MONEY_3
Definition: newclient.h:450
MSG_TYPE_BOOK_SPELL_EVOKER
#define MSG_TYPE_BOOK_SPELL_EVOKER
Definition: newclient.h:432
ARROW
@ ARROW
Definition: object.h:122
MSG_TYPE_MONUMENT_GRAVESTONE_3
#define MSG_TYPE_MONUMENT_GRAVESTONE_3
Definition: newclient.h:484
living::sp
int16_t sp
Definition: living.h:42
get_message_body
sstring get_message_body(const GeneralMessage *message)
Definition: readable.cpp:2077
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.cpp:95
MSG_TYPE_MONUMENT_STONE_3
#define MSG_TYPE_MONUMENT_STONE_3
Definition: newclient.h:478
MSG_TYPE_MONUMENT_WALL_3
#define MSG_TYPE_MONUMENT_WALL_3
Definition: newclient.h:487
titlelist::number
int number
Definition: readable.cpp:122
BOOK
@ BOOK
Definition: object.h:119
trim
const char * trim(const char *buf)
Definition: readable.cpp:661
MSG_TYPE_PAPER_ENVELOPE_2
#define MSG_TYPE_PAPER_ENVELOPE_2
Definition: newclient.h:461
MSG_TYPE_CARD_ELEGANT_2
#define MSG_TYPE_CARD_ELEGANT_2
Definition: newclient.h:443
MSG_TYPE_PAPER_NOTE_1
#define MSG_TYPE_PAPER_NOTE_1
Definition: newclient.h:453
RING
@ RING
Definition: object.h:190
MSG_TYPE_BOOK_SPELL_SORCERER
#define MSG_TYPE_BOOK_SPELL_SORCERER
Definition: newclient.h:435
MSG_TYPE_BOOK_SPELL_PYRO
#define MSG_TYPE_BOOK_SPELL_PYRO
Definition: newclient.h:434
PATH_TRANSMUTE
#define PATH_TRANSMUTE
Definition: spells.h:27
title::archname
const char * archname
Definition: readable.cpp:111
MSGTYPE_GODS
#define MSGTYPE_GODS
Definition: readable.cpp:89
MSG_TYPE_SIGN_MAGIC_MOUTH
#define MSG_TYPE_SIGN_MAGIC_MOUTH
Definition: newclient.h:473
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
guild_entry.text
text
Definition: guild_entry.py:41
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:590
mon_desc
static StringBuffer * mon_desc(const object *mon)
Definition: readable.cpp:1298
MAX_BUF
#define MAX_BUF
Definition: define.h:35
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.cpp:222
object_new
object * object_new(void)
Definition: object.cpp:1273
describe_item
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Definition: item.cpp:951
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
object::weight
int32_t weight
Definition: object.h:375
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
RANDOM
#define RANDOM()
Definition: define.h:644
arttypename::type
int type
Definition: readable.cpp:130
StringBuffer
Definition: stringbuffer.cpp:25
PATH_DEATH
#define PATH_DEATH
Definition: spells.h:31
recipe
Definition: recipe.h:10
art_book_name
static const char *const art_book_name[]
Definition: readable.cpp:227
GOD_RESISTANCES
#define GOD_RESISTANCES
Definition: god.h:15
MSG_TYPE_CARD_MONEY_1
#define MSG_TYPE_CARD_MONEY_1
Definition: newclient.h:448
diamondslots.message
string message
Definition: diamondslots.py:57
object::lore
sstring lore
Definition: object.h:332
PATH_TELE
#define PATH_TELE
Definition: spells.h:25
llevInfo
@ llevInfo
Definition: logger.h:12
Floor.t
t
Definition: Floor.py:62
find_archetype_by_object_name
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.cpp:53
MSG_TYPE_PAPER_ENVELOPE_1
#define MSG_TYPE_PAPER_ENVELOPE_1
Definition: newclient.h:460
spells.h
object::name
sstring name
Definition: object.h:319
get_message_title
sstring get_message_title(const GeneralMessage *message)
Definition: readable.cpp:2068
did_first_sp
int did_first_sp
Definition: readable.cpp:1561
MSGTYPE_LIB
#define MSGTYPE_LIB
Definition: readable.cpp:79
MSG_TYPE_CARD_SIMPLE_3
#define MSG_TYPE_CARD_SIMPLE_3
Definition: newclient.h:441
spellpathdef
static const uint32_t spellpathdef[NRSPELLPATHS]
Definition: readable.cpp:149
stringbuffer_delete
void stringbuffer_delete(StringBuffer *sb)
Definition: stringbuffer.cpp:71
msgfile_msg
static StringBuffer * msgfile_msg(object *book, size_t booksize)
Definition: readable.cpp:1773
PATH_PROT
#define PATH_PROT
Definition: spells.h:13
recipe::chance
int chance
Definition: recipe.h:14
artifact::chance
uint16_t chance
Definition: artifact.h:16
MSGTYPE_ALCHEMY
#define MSGTYPE_ALCHEMY
Definition: readable.cpp:87
sstring
const typedef char * sstring
Definition: sstring.h:2
MSG_TYPE_PAPER_LETTER_NEW_1
#define MSG_TYPE_PAPER_LETTER_NEW_1
Definition: newclient.h:458
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:266
MSG_TYPE_BOOK_ELEGANT_2
#define MSG_TYPE_BOOK_ELEGANT_2
Definition: newclient.h:429
strtoint
int strtoint(const char *buf)
Definition: recipe.cpp:709
GOD_ENEMY
#define GOD_ENEMY
Definition: god.h:13
PATH_MIND
#define PATH_MIND
Definition: spells.h:23
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.cpp:4811
recipe::diff
int diff
Definition: recipe.h:16
object::msg
sstring msg
Definition: object.h:330
BOOK_BUF
#define BOOK_BUF
Definition: book.h:16
title::next
title * next
Definition: readable.cpp:115
assets.h
artifactlist::total_chance
uint16_t total_chance
Definition: artifact.h:26
MSGTYPE_ARTIFACT
#define MSGTYPE_ARTIFACT
Definition: readable.cpp:83
npc_dialog.index
int index
Definition: npc_dialog.py:102
do_monster
static void do_monster(archetype *at)
Definition: readable.cpp:874
art_name_array
static const arttypename art_name_array[]
Definition: readable.cpp:207
MSG_TYPE_MONUMENT_STONE_2
#define MSG_TYPE_MONUMENT_STONE_2
Definition: newclient.h:477
stringbuffer_append_stringbuffer
void stringbuffer_append_stringbuffer(StringBuffer *sb, const StringBuffer *sb2)
Definition: stringbuffer.cpp:165
new_text_name
static void new_text_name(object *book, int msgtype)
Definition: readable.cpp:974
heavy_book_name
static const char *const heavy_book_name[]
Definition: readable.cpp:397
level
int level
Definition: readable.cpp:1563
MSGTYPE_SPELLPATH
#define MSGTYPE_SPELLPATH
Definition: readable.cpp:85
readable_message_type
Definition: book.h:36
make_face_from_files.int
int
Definition: make_face_from_files.py:32
formula_author
static const char *const formula_author[]
Definition: readable.cpp:356
booklist
static titlelist * booklist
Definition: readable.cpp:139
MSG_TYPE_MONUMENT_STATUE_1
#define MSG_TYPE_MONUMENT_STATUE_1
Definition: newclient.h:479
title::level
unsigned int level
Definition: readable.cpp:112
MSG_TYPE_MONUMENT_WALL_1
#define MSG_TYPE_MONUMENT_WALL_1
Definition: newclient.h:485
get_readable_message_type
const readable_message_type * get_readable_message_type(object *readable)
Definition: readable.cpp:2055
art_author
static const char *const art_author[]
Definition: readable.cpp:245
last_readable_subtype
static const int last_readable_subtype
Definition: readable.cpp:549
get_random_mon
object * get_random_mon(int level)
Definition: readable.cpp:1269
book_overflow
int book_overflow(const char *buf1, const char *buf2, size_t booksize)
Definition: readable.cpp:719
FOOD
@ FOOD
Definition: object.h:117
MSG_TYPE_PAPER_NOTE_3
#define MSG_TYPE_PAPER_NOTE_3
Definition: newclient.h:455
MSG_TYPE_BOOK_QUARTO_2
#define MSG_TYPE_BOOK_QUARTO_2
Definition: newclient.h:431
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:270
animate.event
event
DIALOGCHECK MINARGS 1 MAXARGS 2
Definition: animate.py:17
mon_info_msg
static StringBuffer * mon_info_msg(int level, size_t booksize, object *book)
Definition: readable.cpp:1343
unique_book
static int unique_book(const object *book, int msgtype)
Definition: readable.cpp:1071
recipe::ingred
linked_char * ingred
Definition: recipe.h:22
MSG_TYPE_CARD_SIMPLE_1
#define MSG_TYPE_CARD_SIMPLE_1
Definition: newclient.h:439
light_book_name
static const char *const light_book_name[]
Definition: readable.cpp:378
MSG_TYPE_MONUMENT_STONE_1
#define MSG_TYPE_MONUMENT_STONE_1
Definition: newclient.h:476
archetype::name
sstring name
Definition: object.h:484
recipe::next
recipe * next
Definition: recipe.h:24
recipe::skill
sstring skill
Definition: recipe.h:26
living::grace
int16_t grace
Definition: living.h:44
object::stats
living stats
Definition: object.h:378
MSG_TYPE_SIGN
#define MSG_TYPE_SIGN
Definition: newclient.h:401
MSG_TYPE_BOOK
#define MSG_TYPE_BOOK
Definition: newclient.h:398
artifact
Definition: artifact.h:14
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.cpp:4499
buf_overflow
int buf_overflow(const char *buf1, const char *buf2, size_t bufsize)
Definition: shstr.cpp:398
describe_god
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Definition: holy.cpp:109
add_book
static void add_book(title *book, int type, const char *fname, int lineno)
Definition: readable.cpp:860
MSG_TYPE_PAPER_SCROLL_MAGIC
#define MSG_TYPE_PAPER_SCROLL_MAGIC
Definition: newclient.h:466
BOOTS
@ BOOTS
Definition: object.h:217
make_formula_book
static void make_formula_book(object *book, int level)
Definition: readable.cpp:1642
FLAG_CHANGING
#define FLAG_CHANGING
Definition: define.h:263
title::msg_index
int msg_index
Definition: readable.cpp:114
SPELL
@ SPELL
Definition: object.h:219
MSG_TYPE_PAPER_SCROLL_NEW_1
#define MSG_TYPE_PAPER_SCROLL_NEW_1
Definition: newclient.h:464
sp_params
static struct @0 sp_params
SHIELD
@ SHIELD
Definition: object.h:140
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
BOOKSIZE
#define BOOKSIZE(xyz)
Definition: book.h:31
max_titles
static const int max_titles[6]
Definition: readable.cpp:552
nstrtok
int nstrtok(const char *buf1, const char *buf2)
Definition: readable.cpp:642
living.h
find_artifactlist
artifactlist * find_artifactlist(int type)
Definition: artifact.cpp:574
artifactlist::type
uint8_t type
Definition: artifact.h:25
MSG_TYPE_CARD_STRANGE_3
#define MSG_TYPE_CARD_STRANGE_3
Definition: newclient.h:447
get_message_face
const Face * get_message_face(const GeneralMessage *message)
Definition: readable.cpp:2086
pnum
uint32_t pnum
Definition: readable.cpp:1562
recipe_get_difficulty_string
const char * recipe_get_difficulty_string(int difficulty)
Definition: recipe.cpp:962
llevDebug
@ llevDebug
Definition: logger.h:13
NRSPELLPATHS
#define NRSPELLPATHS
Definition: spells.h:40
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25
GOD_SACRED
#define GOD_SACRED
Definition: god.h:16
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
give.name
name
Definition: give.py:27
OutputFile
Definition: output_file.h:41
recipe::cauldron
sstring cauldron
Definition: recipe.h:27
recipe::title
sstring title
Definition: recipe.h:11
level
Definition: level.py:1
Settings::localdir
const char * localdir
Definition: global.h:249