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  "collection",
229  "file",
230  "files",
231  "guide",
232  "handbook",
233  "index",
234  "inventory",
235  "list",
236  "listing",
237  "omnibus",
238  "record",
239  "record book"
240 };
241 
243 static const char *const art_author[] = {
244  "ancient things",
245  "artifacts",
246  "Havlor", /* ancient warrior scribe :) */
247  "items",
248  "lost artifacts",
249  "the ancients",
250  "treasures",
251  "useful things"
252 };
253 
257 static const char *const mon_book_name[] = {
258  "beastuary",
259  "catalog",
260  "compilation",
261  "collection",
262  "encyclopedia",
263  "guide",
264  "handbook",
265  "list",
266  "manual",
267  "notes",
268  "omnibus",
269  "record",
270  "register",
271  "volume"
272 };
273 
275 static const char *const mon_author[] = {
276  "beasts",
277  "creatures",
278  "dezidens",
279  "dwellers",
280  "evil nature",
281  "life",
282  "monsters",
283  "nature",
284  "new life",
285  "residents",
286  "the spawn",
287  "the living",
288  "things"
289 };
290 
294 static const char *const gods_book_name[] = {
295  "devotional",
296  "devout notes",
297  "divine text",
298  "divine work",
299  "holy book",
300  "holy record",
301  "illuminated text",
302  "moral text",
303  "sacred guide",
304  "testament",
305  "transcript"
306 };
307 
309 static const char *const gods_author[] = {
310  "cults",
311  "joy",
312  "lasting curse",
313  "madness",
314  "religions",
315  "the dead",
316  "the gods",
317  "the heirophant",
318  "the poor priest",
319  "the priestess",
320  "pain",
321  "white"
322 };
323 
327 static const char *const formula_book_name[] = {
328  "cookbook",
329  "formulary",
330  "lab book",
331  "lab notes",
332  "recipe book",
333  "experiment record",
334  "work plan",
335  "design notes",
336  "research notes",
337  "crafting manual"
338 };
339 
341 static const char *const formula_author[] = {
342  "Albertus Magnus",
343  "alchemy",
344  "balms",
345  "creation",
346  "dusts",
347  "magical manufacture",
348  "making",
349  "philosophical items",
350  "potions",
351  "powders",
352  "the cauldron",
353  "the lamp black",
354  "transmutation",
355  "waters"
356 };
357 
363 static const char *const light_book_name[] = {
364  "calendar",
365  "datebook",
366  "diary",
367  "essay",
368  "guidebook",
369  "handbook",
370  "ledger",
371  "notes",
372  "notebook",
373  "octavo",
374  "opuscule",
375  "pamphlet",
376  "practicum",
377  "script",
378  "transcript"
379 };
380 
382 static const char *const heavy_book_name[] = {
383  "catalog",
384  "compendium",
385  "dissertation",
386  "guide",
387  "manual",
388  "opus",
389  "tome",
390  "treatise",
391  "volume",
392  "work"
393 };
394 
396 static const char *const book_author[] = {
397  "Abdulah",
398  "Al'hezred",
399  "Alywn",
400  "Arundel",
401  "Arvind",
402  "Aerlingas",
403  "Bacon",
404  "Baliqendii",
405  "Bosworth",
406  "Beathis",
407  "Bertil",
408  "Cauchy",
409  "Chakrabarti",
410  "der Waalis",
411  "Dirk",
412  "Djwimii",
413  "Eisenstaadt",
414  "Fendris",
415  "Frank",
416  "Habbi",
417  "Harlod",
418  "Ichibod",
419  "Janus",
420  "June",
421  "Laplace",
422  "Magnuson",
423  "Nandii",
424  "Nitfeder",
425  "Norris",
426  "Parael",
427  "Penhew",
428  "Sophia",
429  "Skilly",
430  "Tahir",
431  "Thockmorton",
432  "Thomas",
433  "van Helsing",
434  "van Pelt",
435  "Voormis",
436  "Xavier",
437  "Xeno",
438  "Zardoz",
439  "Zagy"
440 };
441 
443 static const char *const book_descrpt[] = {
444  "ancient",
445  "cryptic",
446  "cryptical",
447  "dusty",
448  "hierarchical",
449  "grizzled",
450  "gold-gilt",
451  "great",
452  "lost",
453  "magnificent",
454  "musty",
455  "mythical",
456  "mystical",
457  "rustic",
458  "stained",
459  "silvered",
460  "transcendental",
461  "weathered"
462 };
463 
471  /*subtype 0 */ { 0, 0 },
472  /* book messages subtypes */
473  /*subtype 1 */ { MSG_TYPE_BOOK, MSG_TYPE_BOOK_CLASP_1 },
482  /*subtype 10 */ { MSG_TYPE_BOOK, MSG_TYPE_BOOK_SPELL_SORCERER },
484  /* card messages subtypes*/
493  /*subtype 20 */ { MSG_TYPE_CARD, MSG_TYPE_CARD_STRANGE_3 },
497  /* Paper messages subtypes */
504  /*subtype 30 */ { MSG_TYPE_PAPER, MSG_TYPE_PAPER_LETTER_NEW_2 },
512  /* road signs messages subtypes */
515  /*subtype 40 */ { MSG_TYPE_SIGN, MSG_TYPE_SIGN_DIR_RIGHT },
517  /* stones and monument messages */
531 };
532 
535 
537 static const int max_titles[6] = {
539  arraysize(mon_book_name)*arraysize(mon_author), /* MSGTYPE_MONSTER */
540  arraysize(art_book_name)*arraysize(art_author), /* MSGTYPE_ARTIFACT */
541  arraysize(path_book_name)*arraysize(path_author), /* MSGTYPE_SPELLPATH */
542  arraysize(formula_book_name)*arraysize(formula_author), /* MSGTYPE_ALCHEMY */
543  arraysize(gods_book_name)*arraysize(gods_author), /* MSGTYPE_GODS */
544 };
545 
546 /******************************************************************************
547  *
548  * Start of misc. readable functions used by others functions in this file
549  *
550  *****************************************************************************/
551 
562  titlelist *bl = (titlelist *)malloc(sizeof(titlelist));
563 
564  if (bl == NULL)
566  bl->number = 0;
567  bl->first_book = NULL;
568  bl->next = NULL;
569  return bl;
570 }
571 
581 static title *get_empty_book(void) {
582  title *t = (title *)malloc(sizeof(title));
583 
584  if (t == NULL)
586  t->name = NULL;
587  t->archname = NULL;
588  t->authour = NULL;
589  t->level = 0;
590  t->size = 0;
591  t->msg_index = 0;
592  t->next = NULL;
593  return t;
594 }
595 
606 static titlelist *get_titlelist(int i) {
607  titlelist *tl;
608  int number;
609 
610  if (i < 0 || i >= (int)arraysize(max_titles)) {
611  LOG(llevInfo, "Warning: invalid book index %d, using 0 instead\n", i);
612  return booklist;
613  }
614 
615  for (tl = booklist, number = i; tl && number; tl = tl->next, number--) {
616  if (!tl->next)
617  tl->next = get_empty_booklist();
618  }
619 
620  return tl;
621 }
622 
623 /* HANDMADE STRING FUNCTIONS.., perhaps these belong in another file
624  * (shstr.c ?), but the quantity BOOK_BUF will need to be defined. */
625 
637 int nstrtok(const char *buf1, const char *buf2) {
638  char *tbuf, buf[MAX_BUF];
639  int number = 0;
640 
641  if (!buf1 || !buf2)
642  return 0;
643 
644  strlcpy(buf, buf1, sizeof(buf));
645  for (tbuf = strtok(buf, buf2); tbuf; tbuf = strtok(NULL, buf2)) {
646  number++;
647  }
648  return number;
649 }
650 
656 const char *trim(const char *buf) {
657  while ((*buf) == ' ') {
658  buf++;
659  }
660  return buf;
661 }
662 
679 char *strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size) {
680  int maxi, i = nstrtok(buf1, buf2);
681  char *tbuf, buf[MAX_BUF];
682 
683  maxi = i;
684  strlcpy(buf, buf1, sizeof(buf));
685  snprintf(retbuf, size, " ");
686  for (tbuf = strtok(buf, buf2); tbuf && i > 0; tbuf = strtok(NULL, buf2)) {
687  snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "%s", trim(tbuf));
688  i--;
689  if (i == 1 && maxi > 1)
690  snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), " and ");
691  else if (i > 0 && maxi > 1)
692  snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), ", ");
693  else
694  snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), ".");
695  }
696  return retbuf;
697 }
698 
709 int book_overflow(const char *buf1, const char *buf2, size_t booksize) {
710  if (buf_overflow(buf1, buf2, BOOK_BUF-2) /* 2 less so always room for trailing \n */
711  || buf_overflow(buf1, buf2, booksize))
712  return 1;
713  return 0;
714 }
715 
716 /*****************************************************************************
717  *
718  * Start of initialization related functions.
719  *
720  ****************************************************************************/
721 
728 static void init_book_archive(void) {
729  FILE *fp;
730 #ifdef BOOK_MSG_DEBUG
731  int nroftitle = 0;
732 #endif
733  char buf[MAX_BUF], fname[MAX_BUF], *cp;
734  static int did_init_barch = 0;
735 
736  if (did_init_barch)
737  return;
738  did_init_barch = 1;
739 
740  if (!booklist)
742 
743  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
744  LOG(llevDebug, " Reading bookarch from %s...\n", fname);
745 
746  fp = fopen(fname, "r");
747  if (fp != NULL) {
748  int type;
749  size_t i;
750  titlelist *bl;
751  int lineno;
752  title *book;
753  int skipping;
754 
755  skipping = 0;
756  book = NULL;
757  type = -1;
758  for (lineno = 1; fgets(buf, MAX_BUF, fp) != NULL; lineno++) {
759  int len;
760  int value;
761 
762  if (*buf == '#')
763  continue;
764  cp = strchr(buf, '\n');
765  if (cp != NULL) {
766  while (cp > buf && (cp[-1] == ' ' || cp[-1] == '\t'))
767  cp--;
768  *cp = '\0';
769  }
770  cp = buf;
771  if (strncmp(buf, "title ", 6) == 0) {
772  skipping = 0;
773  cp = buf+6;
774  while (*cp == ' ' || *cp == '\t')
775  cp++;
776  if (*cp == '\0') {
777  LOG(llevInfo, "Warning: missing book title at %s, line %d\n", fname, lineno);
778  book = NULL;
779  } else {
780  book = get_empty_book(); /* init new book entry */
781  book->name = add_string(cp);
782  type = -1;
783 #ifdef BOOK_MSG_DEBUG
784  nroftitle++;
785 #endif
786  }
787  } else if (book == NULL) {
788  if (!skipping) {
789  skipping = 1;
790  LOG(llevInfo, "Warning: expecting 'title' at %s, line %d\n", fname, lineno);
791  }
792  } else if (strncmp(buf, "authour ", 8) == 0) {
793  cp = buf+8;
794  while (*cp == ' ' || *cp == '\t')
795  cp++;
796  if (*cp == '\0') {
797  LOG(llevInfo, "Warning: missing book authour at %s, line %d\n", fname, lineno);
798  } else {
799  book->authour = add_string(cp);
800  }
801  } else if (strncmp(buf, "arch ", 5) == 0) {
802  cp = buf+5;
803  while (*cp == ' ' || *cp == '\t')
804  cp++;
805  if (*cp == '\0') {
806  LOG(llevInfo, "Warning: missing book arch at %s, line %d\n", fname, lineno);
807  } else {
808  book->archname = add_string(cp);
809  }
810  } else if (sscanf(buf, "level %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
811  book->level = value;
812  } else if (sscanf(buf, "type %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
813  type = value;
814  } else if (sscanf(buf, "size %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
815  book->size = value;
816  } else if (sscanf(buf, "index %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
817  book->msg_index = value;
818  } else if (strcmp(buf, "end") == 0) { /* link it */
819  add_book(book, type, fname, lineno);
820  book = NULL;
821  type = -1;
822  } else {
823  LOG(llevInfo, "Warning: syntax error at %s, line %d\n", fname, lineno);
824  }
825  }
826  if (book != NULL) {
827  LOG(llevInfo, "Warning: missing 'end' at %s, line %d\n", fname, lineno);
828  add_book(book, type, fname, lineno);
829  }
830  LOG(llevDebug, " book archives(used/avail):\n");
831  for (bl = booklist, i = 0; bl != NULL && i < arraysize(max_titles); bl = bl->next, i++) {
832  LOG(llevDebug, "(%d/%d)\n", bl->number, max_titles[i]);
833  }
834  fclose(fp);
835  }
836 
837 #ifdef BOOK_MSG_DEBUG
838  LOG(llevDebug, "\n init_book_archive() got %d titles.\n", nroftitle);
839 #endif
840  LOG(llevDebug, " done.\n");
841 }
842 
850 static void add_book(title *book, int type, const char *fname, int lineno) {
851  titlelist *bl;
852 
853  if (type == -1) {
854  LOG(llevInfo, "Warning: book with no type at %s, line %d; using type 0\n", fname, lineno);
855  type = 0;
856  }
857 
858  bl = get_titlelist(type);
859  book->next = bl->first_book;
860  bl->first_book = book;
861  bl->number++;
862 }
863 
864 static void do_monster(archetype *at) {
865  if (QUERY_FLAG(&at->clone, FLAG_MONSTER) && (!at->head)
868  monsters.push_back(&at->clone);
869  }
870 }
871 
876 static void init_mon_info(void) {
877  static int did_init_mon_info = 0;
878 
879  if (did_init_mon_info)
880  return;
881  did_init_mon_info = 1;
882 
884 
885  LOG(llevDebug, "init_mon_info() got %zu monsters\n", monsters.size());
886 }
887 
894 void init_readable(void) {
895  static int did_this = 0;
896 
897  if (did_this)
898  return;
899  did_this = 1;
900 
901  LOG(llevDebug, "Initializing reading data...\n");
903  init_mon_info();
904  LOG(llevDebug, " done reading data\n");
905 }
906 
907 /*****************************************************************************
908  *
909  * This is the start of the administrative functions when creating
910  * new books (ie, updating title and the like)
911  *
912  *****************************************************************************/
913 
925 static title *find_title(const object *book, int msgtype) {
926  title *t;
927  titlelist *tl;
928  size_t length;
929  int index;
930 
931  if (msgtype < 0)
932  return (title *)NULL;
933 
934  tl = get_titlelist(msgtype);
935  if (!tl)
936  return (title *)NULL;
937 
938  length = strlen(book->msg);
939  index = strtoint(book->msg);
940  for (t = tl->first_book; t; t = t->next)
941  if (t->size == length && t->msg_index == index) {
942 #ifdef ARCHIVE_DEBUG
943  LOG(llevDebug, "Found title match (list %d): %s %s (%d)\n", msgtype, t->name, t->authour, t->msg_index);
944 #endif
945  return t;
946  }
947 
948  return (title *)NULL;
949 }
950 
964 static void new_text_name(object *book, int msgtype) {
965  const char *name;
966 
967  if (book->type != BOOK)
968  return;
969 
970  switch (msgtype) {
971  case MSGTYPE_MONSTER:
973  break;
974 
975  case MSGTYPE_ARTIFACT:
977  break;
978 
979  case MSGTYPE_SPELLPATH:
981  break;
982 
983  case MSGTYPE_ALCHEMY:
985  break;
986 
987  case MSGTYPE_GODS:
989  break;
990 
991  case MSGTYPE_MSGFILE:
992  default:
993  if (book->weight > 2000) { /* based on weight */
995  } else {
997  }
998  break;
999  }
1000  free_string(book->name);
1001  book->name = add_string(name);
1002 }
1003 
1013 static void add_author(object *op, int msgtype) {
1014  char title[MAX_BUF];
1015  const char *name;
1016 
1017  if (msgtype < 0 || strlen(op->msg) < 5)
1018  return;
1019 
1020  switch (msgtype) {
1021  case MSGTYPE_MONSTER:
1023  break;
1024 
1025  case MSGTYPE_ARTIFACT:
1027  break;
1028 
1029  case MSGTYPE_SPELLPATH:
1031  break;
1032 
1033  case MSGTYPE_ALCHEMY:
1035  break;
1036 
1037  case MSGTYPE_GODS:
1039  break;
1040 
1041  case MSGTYPE_MSGFILE:
1042  default:
1044  }
1045 
1046  snprintf(title, sizeof(title), "of %s", name);
1047  op->title = add_string(title);
1048 }
1049 
1061 static int unique_book(const object *book, int msgtype) {
1062  title *test;
1063 
1064  if (!booklist)
1065  return 1; /* No archival entries! Must be unique! */
1066 
1067  /* Go through the booklist. If the author and name match, not unique so
1068  * return 0.
1069  */
1070  for (test = get_titlelist(msgtype)->first_book; test; test = test->next) {
1071  if (!strcmp(test->name, book->name) && !strcmp(book->title, test->authour))
1072  return 0;
1073  }
1074  return 1;
1075 }
1076 
1085 static void add_book_to_list(const object *book, int msgtype) {
1086  titlelist *tl = get_titlelist(msgtype);
1087  title *t;
1088 
1089  if (!tl) {
1090  LOG(llevError, "add_book_to_list can't get booklist!\n");
1091  return;
1092  }
1093 
1094  t = get_empty_book();
1095  t->name = add_string(book->name);
1096  t->authour = add_string(book->title);
1097  t->size = strlen(book->msg);
1098  t->msg_index = strtoint(book->msg);
1099  t->archname = add_string(book->arch->name);
1100  t->level = book->level;
1101 
1102  t->next = tl->first_book;
1103  tl->first_book = t;
1104  tl->number++;
1105 
1106  /* We have stuff we need to write now */
1108 
1109 #ifdef ARCHIVE_DEBUG
1110  LOG(llevDebug, "Archiving new title: %s %s (%d)\n", book->name, book->title, msgtype);
1111 #endif
1112 }
1113 
1127 static void change_book(object *book, int msgtype) {
1128  titlelist *tl;
1129  title *t;
1130  int tries;
1131 
1132  if (book->type != BOOK) {
1133  LOG(llevError, "change_book_name() called w/ illegal obj type.\n");
1134  return;
1135  }
1136 
1137  tl = get_titlelist(msgtype);
1138  t = NULL;
1139  tries = 0;
1140 
1141  /* look to see if our msg already been archived. If so, alter
1142  * the book to match the archival text. If we fail to match,
1143  * then we archive the new title/name/msg combo if there is
1144  * room on the titlelist.
1145  */
1146 
1147  if (strlen(book->msg) > 5 && (t = find_title(book, msgtype))) {
1148  object *tmpbook;
1149  sstring marker = object_get_value(book, "knowledge_marker");
1150 
1151  /* alter book properties */
1152  tmpbook = create_archetype(t->archname);
1153  if (marker != NULL)
1154  /* need to copy the knowledge_marker */
1155  object_set_value(tmpbook, "knowledge_marker", marker, 1);
1156  object_set_msg(tmpbook, book->msg);
1157  object_copy(tmpbook, book);
1158  object_free_drop_inventory(tmpbook);
1159 
1160  book->title = add_string(t->authour);
1161  free_string(book->name);
1162  book->name = add_string(t->name);
1163  book->level = t->level;
1164  } else { /* Don't have any default title, so lets make up a new one */
1165  int numb, maxnames = max_titles[msgtype];
1166  const char *old_title;
1167  const char *old_name;
1168 
1169  old_title = book->title ? add_string(book->title) : NULL;
1170  old_name = add_string(book->name);
1171 
1172  /* some pre-generated books have title already set (from
1173  * maps), also don't bother looking for unique title if
1174  * we already used up all the available names! */
1175 
1176  if (!tl) {
1177  LOG(llevError, "change_book_name(): can't find title list\n");
1178  numb = 0;
1179  } else
1180  numb = tl->number;
1181 
1182  if (numb == maxnames) {
1183 #ifdef ARCHIVE_DEBUG
1184  LOG(llevDebug, "titles for list %d full (%d possible).\n", msgtype, maxnames);
1185 #endif
1186  if (old_title != NULL)
1187  free_string(old_title);
1188  free_string(old_name);
1189  return;
1190  }
1191  /* shouldnt change map-maker books */
1192  if (!book->title)
1193  do {
1194  /* random book name */
1195  new_text_name(book, msgtype);
1196  add_author(book, msgtype); /* random author */
1197  tries++;
1198  } while (!unique_book(book, msgtype) && tries < MAX_TITLE_CHECK);
1199 
1200  /* Now deal with 2 cases.
1201  * 1) If no space for a new title exists lets just restore
1202  * the old book properties. Remember, if the book had
1203  * matchd an older entry on the titlelist, we shouldnt
1204  * have called this routine in the first place!
1205  * 2) If we got a unique title, we need to add it to
1206  * the list.
1207  */
1208 
1209  if (tries == MAX_TITLE_CHECK) {
1210 #ifdef ARCHIVE_DEBUG
1211  LOG(llevDebug, "Failed to obtain unique title for %s %s (names:%d/%d)\n", book->name, book->title, numb, maxnames);
1212 #endif
1213  /* restore old book properties here */
1214  free_string(book->name);
1215  free_string(book->title);
1216  book->title = old_title != NULL ? add_string(old_title) : NULL;
1217 
1218  if (RANDOM()%4) {
1219  /* Lets give the book a description to individualize it some */
1220  char new_name[MAX_BUF];
1221 
1222  snprintf(new_name, MAX_BUF, "%s %s", book_descrpt[RANDOM()%arraysize(book_descrpt)], old_name);
1223  book->name = add_string(new_name);
1224  } else {
1225  book->name = add_string(old_name);
1226  }
1227  } else if (book->title && strlen(book->msg) > 5) { /* archive if long msg texts */
1228  add_book_to_list(book, msgtype);
1229  }
1230 
1231  if (old_title != NULL)
1232  free_string(old_title);
1233  free_string(old_name);
1234  }
1235 }
1236 
1237 /*****************************************************************************
1238  *
1239  * This is the start of the area that generates the actual contents
1240  * of the book.
1241  *
1242  *****************************************************************************/
1243 
1244 /*****************************************************************************
1245  * Monster msg generation code.
1246  ****************************************************************************/
1247 
1259 object *get_random_mon(int level) {
1260 
1261  /* safety check. Problem w/ init_mon_info list? */
1262  if (monsters.empty())
1263  return (object *)NULL;
1264 
1265  if (!level) {
1266  return monsters[RANDOM() % monsters.size()];
1267  }
1268 
1269  std::vector<object *> select;
1270  std::copy_if(monsters.cbegin(), monsters.cend(), std::back_inserter(select), [&] (auto ob) { return ob->level >= level; });
1271 
1272  if (select.empty()) {
1273  LOG(llevError, "get_random_mon() couldn't return monster for level %d\n", level);
1274  return NULL;
1275  }
1276  return select[RANDOM() % select.size()];
1277 }
1278 
1288 static StringBuffer *mon_desc(const object *mon) {
1289  StringBuffer *desc = stringbuffer_new();
1290  stringbuffer_append_printf(desc, "\n---\n *** %s ***\n", mon->name);
1291  describe_item(mon, NULL, 0, desc);
1292  return desc;
1293 }
1294 
1306 static object *get_next_mon(const object *tmp) {
1307  auto it = std::find(monsters.begin(), monsters.end(), tmp);
1308  if (it == monsters.end())
1309  return nullptr;
1310  ++it;
1311  if (it == monsters.end())
1312  it = monsters.begin();
1313 
1314  return *it;
1315 }
1316 
1329 static StringBuffer *mon_info_msg(int level, size_t booksize, object *book) {
1330  object *tmp;
1331  StringBuffer *marker = stringbuffer_new(), *desc = stringbuffer_new(), *mon = NULL;
1332  int added = 0;
1333  sstring final;
1334  const char *sep = ":";
1335 
1336  /*preamble */
1337  stringbuffer_append_string(desc, "This beastiary contains:");
1338  stringbuffer_append_string(marker, "monster");
1339 
1340  /* lets print info on as many monsters as will fit in our
1341  * document.
1342  * 8-96 Had to change this a bit, otherwise there would
1343  * have been an impossibly large number of combinations
1344  * of text! (and flood out the available number of titles
1345  * in the archive in a snap!) -b.t.
1346  */
1347  for (tmp = get_random_mon(level*3); tmp; tmp = get_next_mon(tmp)) {
1348  /* monster description */
1349  mon = mon_desc(tmp);
1350 
1352  break;
1353  added++;
1354  stringbuffer_append_printf(marker, "%s%s", sep, tmp->arch->name);
1355  sep = "/";
1358  mon = NULL;
1359  }
1360 
1361  if (mon != NULL) {
1363  }
1364 
1365  final = stringbuffer_finish_shared(marker);
1366  if (added)
1367  object_set_value(book, "knowledge_marker", final, 1);
1368  free_string(final);
1369 
1370  return desc;
1371 }
1372 
1373 /*****************************************************************************
1374  * Artifact msg generation code.
1375  ****************************************************************************/
1376 
1386 static StringBuffer *artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator) {
1387  object *tmp;
1388  int chance;
1389  StringBuffer *desc = stringbuffer_new(), *sbuf;
1390 
1391  if (separator)
1392  stringbuffer_append_string(desc, "---\n");
1393 
1394  /* Name */
1395  if (!art->allowed.empty()) {
1396  archetype *arch;
1397  auto name = art->allowed[RANDOM() % art->allowed.size()];
1398  int inv = 0;
1399 
1400  if (name[0] == '!')
1401  inv = 1;
1402 
1405  if (!arch)
1407 
1408  if (!arch)
1409  LOG(llevError, "artifact_msg: missing archetype %s for artifact %s (type %d)\n", name + inv, art->item->name, art->item->type);
1410  else {
1411  if (inv)
1412  stringbuffer_append_printf(desc, " A %s (excepted %s) of %s", art_name_array[art_name].name, arch->clone.name_pl, art->item->name);
1413  else
1414  stringbuffer_append_printf(desc, " A %s of %s", arch->clone.name, art->item->name);
1415  }
1416  } else { /* default name is used */
1417  /* use the base 'generic' name for our artifact */
1418  stringbuffer_append_printf(desc, " The %s of %s", art_name_array[art_name].name, art->item->name);
1419  }
1420 
1421  /* chance of finding */
1422  stringbuffer_append_string(desc, " is ");
1423  chance = 100*((float)art->chance/al->total_chance);
1424  if (chance >= 20)
1425  stringbuffer_append_string(desc, "an uncommon");
1426  else if (chance >= 10)
1427  stringbuffer_append_string(desc, "an unusual");
1428  else if (chance >= 5)
1429  stringbuffer_append_string(desc, "a rare");
1430  else
1431  stringbuffer_append_string(desc, "a very rare");
1432 
1433  /* value of artifact */
1434  stringbuffer_append_printf(desc, " item with a value that is %d times normal.\n", art->item->value);
1435 
1436  /* include the message about the artifact, if exists, and book
1437  * level is kinda high */
1438  if (message && !(strlen(art->item->msg) > BOOK_BUF))
1439  stringbuffer_append_string(desc, art->item->msg);
1440 
1441  /* properties of the artifact */
1442  tmp = object_new();
1443  add_abilities(tmp, art->item);
1444  tmp->type = al->type;
1446  sbuf = describe_item(tmp, NULL, 0, NULL);
1447  if (stringbuffer_length(sbuf) > 1) {
1448  stringbuffer_append_string(desc, " Properties of this artifact include:\n ");
1450  stringbuffer_append_string(desc, "\n");
1451  }
1452  free(stringbuffer_finish(sbuf));
1454 
1455  return desc;
1456 }
1457 
1469 static StringBuffer *artifact_msg(unsigned int level, size_t booksize) {
1470  const artifactlist *al;
1471  const artifact *art;
1472  int i, type, index;
1473  int book_entries = level > 5 ? RANDOM()%3+RANDOM()%3+2 : RANDOM()%level+1;
1475 
1476  /* values greater than 5 create msg buffers that are too big! */
1477  if (book_entries > 5)
1478  book_entries = 5;
1479 
1480  /* lets determine what kind of artifact type randomly.
1481  * Right now legal artifacts only come from those listed
1482  * in art_name_array. Also, we check to be sure an artifactlist
1483  * for that type exists!
1484  */
1485  i = 0;
1486  do {
1489  al = find_artifactlist(type);
1490  i++;
1491  } while (al == NULL && i < 10);
1492 
1493  if (i == 10) { /* Unable to find a message */
1495  return message;
1496  }
1497 
1498  /* There is no reason to start on the artifact list at the beginning. Lets
1499  * take our starting position randomly... */
1500  auto iart = al->items.cbegin();
1501  for (i = RANDOM()%level+RANDOM()%2+1; i > 0; i--) {
1502  if (iart == al->items.cend())
1503  iart = al->items.cbegin(); /* hmm, out of stuff, loop back around */
1504  ++iart;
1505  }
1506 
1507  /* Ok, lets print out the contents */
1508  stringbuffer_append_printf(message, "Herein %s detailed %s...\n", book_entries > 1 ? "are" : "is", book_entries > 1 ? "some artifacts" : "an artifact");
1509 
1510  i = 0;
1511  /* artifact msg attributes loop. Lets keep adding entries to the 'book'
1512  * as long as we have space up to the allowed max # (book_entires)
1513  */
1514  while (book_entries > 0) {
1515  int with_message;
1516  if (iart == al->items.cend())
1517  iart = al->items.cbegin();
1518  art = *iart;
1519  with_message = (art->item->msg && RANDOM()%4+1 < level) ? 1 : 0;
1520 
1521  desc = artifact_describe(art, al, with_message, index, i++);
1522 
1524  stringbuffer_delete(desc);
1525  break;
1526  }
1527 
1529  stringbuffer_delete(desc);
1530 
1531  ++iart;
1532  book_entries--;
1533  }
1534 
1535  return message;
1536 }
1537 
1538 /*****************************************************************************
1539  * Spellpath message generation
1540  *****************************************************************************/
1541 
1543 static struct {
1544  int prayers;
1545  int did_first_sp;
1546  uint32_t pnum;
1547  int level;
1548  size_t booksize;
1550  int done;
1554 static void do_spellpath_msg(archetype *at) {
1555  /* Determine if this is an appropriate spell. Must
1556  * be of matching path, must be of appropriate type (prayer
1557  * or not), and must be within the valid level range.
1558  */
1559  if (at->clone.type == SPELL
1560  && at->clone.path_attuned & sp_params.pnum
1561  && ((at->clone.stats.grace && sp_params.prayers) || (at->clone.stats.sp && !sp_params.prayers))
1562  && at->clone.level < sp_params.level*8) {
1563  if (strlen(at->clone.name) + stringbuffer_length(sp_params.buf) >= sp_params.booksize) {
1564  sp_params.done = 1;
1565  return;
1566  }
1567 
1568  if (sp_params.did_first_sp)
1570  sp_params.did_first_sp = 1;
1572  }
1573 }
1574 
1589  int path = RANDOM()%NRSPELLPATHS;
1590  sp_params.prayers = RANDOM()%2;
1591  sp_params.did_first_sp = 0;
1592  sp_params.pnum = spellpathdef[path];
1593  sp_params.done = 0;
1594 
1595  if (buf == NULL) {
1596  buf = stringbuffer_new();
1597  /* Preamble */
1598  stringbuffer_append_printf(buf, "Herein are detailed the names of %s", sp_params.prayers ? "prayers" : "incantations");
1599  stringbuffer_append_printf(buf, " belonging to the path of %s:\n ", spellpathnames[path]);
1600  }
1601  sp_params.level = level;
1602  sp_params.booksize = booksize;
1603  sp_params.buf = buf;
1604 
1606 
1607  /* Geez, no spells were generated. */
1608  if (!sp_params.did_first_sp) {
1609  if (RANDOM()%4) { /* usually, lets make a recursive call... */
1610  // If we do a recursive call, we reset the spell path, so we will want to reset our text as well.
1612  return spellpath_msg(level, booksize, NULL);
1613  }
1614  /* give up, cause knowing no spells exist for path is info too. need the header too. */
1615  stringbuffer_append_string(buf, "- no known spells exist -\n");
1616  }
1617  return buf;
1618 }
1619 
1628 static void make_formula_book(object *book, int level) {
1629  recipelist *fl;
1630  recipe *formula;
1631  int chance, count = 0;
1632  const char *op_name;
1633  archetype *at;
1634  StringBuffer *text, *title;
1635  char *final, km[MAX_BUF];
1636 
1637  /* the higher the book level, the more complex (ie number of
1638  * ingredients) the formula can be.
1639  */
1640  fl = get_formulalist((RANDOM()%level)/3+1);
1641  if (!fl)
1642  fl = get_formulalist(1); /* safety */
1643 
1644  if (fl->total_chance == 0) {
1645  object_set_msg(book, " <indecipherable text>\n");
1647  add_author(book, MSGTYPE_ALCHEMY);
1648  return;
1649  }
1650 
1651  /* get a random formula, weighted by its bookchance */
1652  chance = RANDOM()%fl->total_chance;
1653  for (formula = fl->items; formula != NULL; formula = formula->next) {
1654  chance -= formula->chance;
1655  if (chance <= 0 && formula->chance != 0 && !formula->is_combination)
1656  break;
1657  }
1658 
1659  if (!formula || formula->arch_names <= 0) {
1660  object_set_msg(book, " <indecipherable text>\n");
1662  add_author(book, MSGTYPE_ALCHEMY);
1663  return;
1664  }
1665 
1666  /* looks like a formula was found. Base the amount
1667  * of information on the booklevel and the spellevel
1668  * of the formula. */
1669 
1670  op_name = formula->arch_name[RANDOM()%formula->arch_names];
1671  at = find_archetype(op_name);
1672  if (at == (archetype *)NULL) {
1673  LOG(llevError, "formula_msg() can't find arch %s for formula.\n", op_name);
1674  object_set_msg(book, " <indecipherable text>\n");
1676  add_author(book, MSGTYPE_ALCHEMY);
1677  return;
1678  }
1679  op_name = at->clone.name;
1680 
1681  text = stringbuffer_new();
1682  title = stringbuffer_new();
1683 
1684  /* preamble */
1685  stringbuffer_append_printf(text, "Herein is described a project using %s:\n", formula->skill ? formula->skill : "an unknown skill");
1686 
1687  /* item name */
1688  if (strcmp(formula->title, "NONE")) {
1689  stringbuffer_append_printf(text, "The %s of %s", op_name, formula->title);
1690  /* This results in things like pile of philo. sulfur.
1691  * while philo. sulfur may look better, without this,
1692  * you get things like 'the wise' because its missing the
1693  * water of section.
1694  */
1696  } else {
1697  stringbuffer_append_printf(text, "The %s", op_name);
1699  if (at->clone.title) {
1702  }
1703  }
1704  /* Lets name the book something meaningful ! */
1705  if (book->name)
1706  free_string(book->name);
1708  if (book->title) {
1709  free_string(book->title);
1710  book->title = NULL;
1711  }
1712 
1713  /* ingredients to make it */
1714  if (formula->ingred != NULL) {
1715  linked_char *next;
1716  archetype *at;
1717  char name[MAX_BUF];
1718 
1719  at = find_archetype(formula->cauldron);
1720  if (at)
1721  query_name(&at->clone, name, MAX_BUF);
1722  else
1723  snprintf(name, sizeof(name), "an unknown place");
1724 
1725  stringbuffer_append_printf(text, " may be made at %s using the following ingredients:\n", name);
1726 
1727  for (next = formula->ingred; next != NULL; next = next->next) {
1728  count++;
1729  stringbuffer_append_printf(text, "%s\n", next->name);
1730  }
1731  } else {
1732  LOG(llevError, "formula_msg() no ingredient list for object %s of %s\n", op_name, formula->title);
1734  }
1735 
1736  final = stringbuffer_finish(text);
1737  object_set_msg(book, final);
1738  free(final);
1739 
1742  snprintf(km, sizeof(km), "alchemy:%d:%d:%s", count, formula->index, formula->title);
1743  object_set_value(book, "knowledge_marker", km, 1);
1744 }
1745 
1756 static StringBuffer *msgfile_msg(object *book, size_t booksize) {
1757  StringBuffer *ret = stringbuffer_new();
1758 
1760 
1761  if (msg && strlen(msg->message) <= booksize) {
1762  stringbuffer_append_string(ret, msg->message);
1763  if (msg->identifier != NULL) {
1764  char km[HUGE_BUF];
1767  snprintf(km, sizeof(km), "message:%s", msg->identifier);
1768  object_set_value(book, "knowledge_marker", km, 1);
1769  }
1770  if (msg->quest_code) {
1771  /* add a 'apply' hook to launch the quest */
1772  archetype *at = find_archetype("quest_advance_apply");
1773  if (at != NULL) {
1774  object *event = object_create_arch(at);
1775  FREE_AND_COPY(event->name, msg->quest_code);
1776  object_insert_in_ob(event, book);
1777  }
1778  }
1779  } else
1780  stringbuffer_append_string(ret, "\n <undecipherable text>");
1781 
1782  return ret;
1783 }
1784 
1799 static StringBuffer *god_info_msg(int level, size_t booksize, object *book) {
1800  int what = 0;
1801  const object *god = get_rand_god();
1802  StringBuffer *desc = NULL;
1803 
1804  if (!god)
1805  return NULL; /* oops, problems... */
1806 
1807  if (booksize > BOOK_BUF) {
1808  LOG(llevError, "common/readable.c:god_info_msg() - passed in booksize (%lu) is larger than book buffer (%d)\n", (unsigned long)booksize, BOOK_BUF);
1809  booksize = BOOK_BUF;
1810  }
1811 
1812  if (level >= 2 && RANDOM()%2) {
1813  what |= GOD_ENEMY;
1814  }
1815  if (level >= 3 && RANDOM()%2) {
1816  what |= GOD_HOLYWORD;
1817  }
1818  if (level >= 4 && RANDOM()%2) {
1819  what |= GOD_RESISTANCES;
1820  }
1821  if (level >= 5 && RANDOM()%2) {
1822  what |= GOD_SACRED;
1823  }
1824  if (level >= 6 && RANDOM()%2) {
1825  what |= GOD_BLESSED;
1826  }
1827  if (level >= 8 && RANDOM()%2) {
1828  what |= GOD_IMMUNITIES;
1829  }
1830  if (level >= 12 && RANDOM()%2) {
1831  what |= GOD_PATHS;
1832  }
1833 
1834  desc = stringbuffer_new();
1835  what = describe_god(god, what, desc, booksize);
1836 
1837  /* check to be sure new buffer size dont exceed either
1838  * the maximum buffer size, or the 'natural' size of the
1839  * book... */
1840  if (stringbuffer_length(desc) > 1 && stringbuffer_length(desc) <= booksize) {
1841  char buf[BOOK_BUF];
1842  snprintf(buf, sizeof(buf), "god:%s:%d", god->name, what);
1843  object_set_value(book, "knowledge_marker", buf, 1);
1844  return desc;
1845  }
1846 
1847  stringbuffer_delete(desc);
1848  return NULL;
1849 }
1850 
1869 void tailor_readable_ob(object *book, int msg_type) {
1870  int level = book->level ? RANDOM()%book->level+1 : 1;
1871  size_t book_buf_size;
1872  StringBuffer *message = NULL;
1873 
1874  /* safety */
1875  if (book->type != BOOK)
1876  return;
1877 
1878  if (level <= 0)
1879  return; /* if no level no point in doing any more... */
1880 
1881  /* Max text length this book can have. */
1882  book_buf_size = BOOKSIZE(book);
1883  book_buf_size -= strlen("\n"); /* Keep enough for final \n. */
1884  assert(book_buf_size < BOOK_BUF);
1885 
1886  /* &&& The message switch &&& */
1887  /* Below all of the possible types of messages in the "book"s.
1888  */
1889  /*
1890  * IF you add a new type of book msg, you will have to do several things.
1891  * 1) make sure there is an entry in the msg switch below!
1892  * 2) make sure there is an entry in max_titles[] array.
1893  * 3) make sure there are entries for your case in new_text_title()
1894  * and add_authour().
1895  * 4) you may want separate authour/book name arrays in read.h
1896  */
1897 
1898  if (msg_type >= (int)arraysize(max_titles))
1899  msg_type = 0;
1900 
1901  msg_type = msg_type > 0 ? msg_type : (int)(RANDOM()%6);
1902  switch (msg_type) {
1903  case MSGTYPE_MONSTER:
1904  message = mon_info_msg(level, book_buf_size, book);
1905  break;
1906 
1907  case MSGTYPE_ARTIFACT:
1908  message = artifact_msg(level, book_buf_size);
1909  break;
1910 
1911  case MSGTYPE_SPELLPATH: /* grouping incantations/prayers by path */
1912  message = spellpath_msg(level, book_buf_size, NULL);
1913  break;
1914 
1915  case MSGTYPE_ALCHEMY: /* describe an alchemy formula */
1916  make_formula_book(book, level);
1917  /* make_formula_book already gives title */
1918  return;
1919  break;
1920 
1921  case MSGTYPE_GODS: /* bits of information about a god */
1922  message = god_info_msg(level, book_buf_size, book);
1923  break;
1924 
1925  case MSGTYPE_LIB: /* use info list in lib/ */
1926  default:
1927  message = msgfile_msg(book, book_buf_size);
1928  break;
1929  }
1930 
1931  if (message != NULL) {
1932  char *final;
1934  final = stringbuffer_finish(message);
1935  object_set_msg(book, final);
1936  free(final);
1937  /* lets give the "book" a new name, which may be a compound word */
1938  change_book(book, msg_type);
1939  }
1940 }
1941 
1942 /*****************************************************************************
1943  *
1944  * Cleanup routine for readable stuff.
1945  *
1946  *****************************************************************************/
1947 
1951 void free_all_readable(void) {
1952  titlelist *tlist, *tnext;
1953  title *title1, *titlenext;
1954 
1955  LOG(llevDebug, "freeing all book information\n");
1956 
1957  for (tlist = booklist; tlist != NULL; tlist = tnext) {
1958  tnext = tlist->next;
1959  for (title1 = tlist->first_book; title1; title1 = titlenext) {
1960  titlenext = title1->next;
1961  if (title1->name)
1962  free_string(title1->name);
1963  if (title1->authour)
1964  free_string(title1->authour);
1965  if (title1->archname)
1966  free_string(title1->archname);
1967  free(title1);
1968  }
1969  free(tlist);
1970  }
1971 }
1972 
1973 /*****************************************************************************
1974  *
1975  * Writeback routine for updating the bookarchive.
1976  *
1977  ****************************************************************************/
1978 
1983  FILE *fp;
1984  OutputFile of;
1985  int index;
1986  char fname[MAX_BUF];
1987  title *book;
1988  titlelist *bl;
1989 
1990  /* If nothing changed, don't write anything */
1992  return;
1993 
1994  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
1995  LOG(llevDebug, "Updating book archive: %s...\n", fname);
1996 
1997  fp = of_open(&of, fname);
1998  if (fp == NULL)
1999  return;
2000 
2001  for (bl = get_titlelist(0), index = 0; bl; bl = bl->next, index++) {
2002  for (book = bl->first_book; book; book = book->next)
2003  if (book && book->authour) {
2004  fprintf(fp, "title %s\n", book->name);
2005  fprintf(fp, "authour %s\n", book->authour);
2006  fprintf(fp, "arch %s\n", book->archname);
2007  fprintf(fp, "level %d\n", book->level);
2008  fprintf(fp, "type %d\n", index);
2009  /* C89 doesn't have %zu... */
2010  fprintf(fp, "size %lu\n", (unsigned long)book->size);
2011  fprintf(fp, "index %d\n", book->msg_index);
2012  fprintf(fp, "end\n");
2013  }
2014  }
2015  if (!of_close(&of))
2016  return;
2017 
2018  if (chmod(fname, SAVE_MODE) != 0) {
2019  LOG(llevError, "Could not set permissions on '%s'\n", fname);
2020  }
2021 
2023 }
2024 
2033  uint8_t subtype = readable->subtype;
2034 
2035  if (subtype > last_readable_subtype)
2036  return &readable_message_types[0];
2037  return &readable_message_types[subtype];
2038 }
2039 
2046  return message->title;
2047 }
2048 
2055  return message->message;
2056 }
2057 
2064  return message->face;
2065 }
write_book_archive
void write_book_archive(void)
Definition: readable.cpp:1982
PATH_TURNING
#define PATH_TURNING
Definition: spells.h:29
MSG_TYPE_MONUMENT_WALL_2
#define MSG_TYPE_MONUMENT_WALL_2
Definition: newclient.h:483
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:327
MSG_TYPE_BOOK_SPELL_PRAYER
#define MSG_TYPE_BOOK_SPELL_PRAYER
Definition: newclient.h:430
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:1127
settings
struct Settings settings
Definition: init.cpp:138
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:561
do_spellpath_msg
static void do_spellpath_msg(archetype *at)
Definition: readable.cpp:1554
mon_author
static const char *const mon_author[]
Definition: readable.cpp:275
BOW
@ BOW
Definition: object.h:121
BRACERS
@ BRACERS
Definition: object.h:220
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:876
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:351
get_empty_book
static title * get_empty_book(void)
Definition: readable.cpp:581
MSG_TYPE_PAPER_LETTER_OLD_2
#define MSG_TYPE_PAPER_LETTER_OLD_2
Definition: newclient.h:454
PATH_INFO
#define PATH_INFO
Definition: spells.h:26
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
arraysize
#define arraysize(arrayname)
Definition: readable.cpp:98
MSG_TYPE_BOOK_SPELL_SUMMONER
#define MSG_TYPE_BOOK_SPELL_SUMMONER
Definition: newclient.h:433
book_author
static const char *const book_author[]
Definition: readable.cpp:396
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:585
free_all_readable
void free_all_readable(void)
Definition: readable.cpp:1951
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:216
arttypename::name
const char * name
Definition: readable.cpp:129
GIRDLE
@ GIRDLE
Definition: object.h:226
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:238
mon_book_name
static const char *const mon_book_name[]
Definition: readable.cpp:257
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:1469
MSG_TYPE_PAPER
#define MSG_TYPE_PAPER
Definition: newclient.h:397
MSG_TYPE_PAPER_LETTER_NEW_2
#define MSG_TYPE_PAPER_LETTER_NEW_2
Definition: newclient.h:456
object::arch
struct archetype * arch
Definition: object.h:420
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
MSG_TYPE_BOOK_QUARTO_1
#define MSG_TYPE_BOOK_QUARTO_1
Definition: newclient.h:427
PATH_SELF
#define PATH_SELF
Definition: spells.h:18
MSG_TYPE_SIGN_BASIC
#define MSG_TYPE_SIGN_BASIC
Definition: newclient.h:466
artifactlist::items
std::vector< artifact * > items
Definition: artifact.h:28
gods_book_name
static const char *const gods_book_name[]
Definition: readable.cpp:294
ARMOUR
@ ARMOUR
Definition: object.h:123
MSG_TYPE_PAPER_SCROLL_NEW_2
#define MSG_TYPE_PAPER_SCROLL_NEW_2
Definition: newclient.h:462
WEAPON
@ WEAPON
Definition: object.h:122
MSG_TYPE_PAPER_SCROLL_OLD_2
#define MSG_TYPE_PAPER_SCROLL_OLD_2
Definition: newclient.h:460
MSG_TYPE_PAPER_NOTE_2
#define MSG_TYPE_PAPER_NOTE_2
Definition: newclient.h:451
guildjoin.ob
ob
Definition: guildjoin.py:42
MSG_TYPE_CARD_MONEY_2
#define MSG_TYPE_CARD_MONEY_2
Definition: newclient.h:446
MSG_TYPE_MONUMENT_STATUE_3
#define MSG_TYPE_MONUMENT_STATUE_3
Definition: newclient.h:478
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:1799
add_abilities
void add_abilities(object *op, const object *change)
Definition: artifact.cpp:320
AMULET
@ AMULET
Definition: object.h:142
recipelist::items
recipe * items
Definition: recipe.h:40
archetype::head
archetype * head
Definition: object.h:474
MSG_TYPE_PAPER_LETTER_OLD_1
#define MSG_TYPE_PAPER_LETTER_OLD_1
Definition: newclient.h:453
strtoktolin
char * strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size)
Definition: readable.cpp:679
MSG_TYPE_SIGN_DIR_RIGHT
#define MSG_TYPE_SIGN_DIR_RIGHT
Definition: newclient.h:468
mon
object * mon
Definition: comet_perf.cpp:75
gods_author
static const char *const gods_author[]
Definition: readable.cpp:309
title::name
const char * name
Definition: readable.cpp:109
MSG_TYPE_CARD_SIMPLE_2
#define MSG_TYPE_CARD_SIMPLE_2
Definition: newclient.h:437
SKILL
@ SKILL
Definition: object.h:146
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:424
MSG_TYPE_CARD
#define MSG_TYPE_CARD
Definition: newclient.h:396
prayers
int prayers
Definition: readable.cpp:1546
booksize
size_t booksize
Definition: readable.cpp:1550
MSGTYPE_MONSTER
#define MSGTYPE_MONSTER
Definition: readable.cpp:81
MSG_TYPE_BOOK_ELEGANT_1
#define MSG_TYPE_BOOK_ELEGANT_1
Definition: newclient.h:425
object::title
sstring title
Definition: object.h:323
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4339
GOD_BLESSED
#define GOD_BLESSED
Definition: god.h:17
object::level
int16_t level
Definition: object.h:359
buf
StringBuffer * buf
Definition: readable.cpp:1551
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:2851
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:470
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:925
get_next_mon
static object * get_next_mon(const object *tmp)
Definition: readable.cpp:1306
MSG_TYPE_PAPER_SCROLL_OLD_1
#define MSG_TYPE_PAPER_SCROLL_OLD_1
Definition: newclient.h:459
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:442
PATH_MISSILE
#define PATH_MISSILE
Definition: spells.h:17
CLOAK
@ CLOAK
Definition: object.h:207
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:1013
HELMET
@ HELMET
Definition: object.h:139
get_rand_god
const object * get_rand_god(void)
Definition: holy.cpp:73
object::subtype
uint8_t subtype
Definition: object.h:347
recipelist
Definition: recipe.h:37
MSG_TYPE_MONUMENT_GRAVESTONE_1
#define MSG_TYPE_MONUMENT_GRAVESTONE_1
Definition: newclient.h:479
PATH_WOUNDING
#define PATH_WOUNDING
Definition: spells.h:30
MSG_TYPE_MONUMENT
#define MSG_TYPE_MONUMENT
Definition: newclient.h:399
PATH_CREATE
#define PATH_CREATE
Definition: spells.h:24
MSG_TYPE_CARD_STRANGE_2
#define MSG_TYPE_CARD_STRANGE_2
Definition: newclient.h:443
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:585
MSG_TYPE_SIGN_DIR_BOTH
#define MSG_TYPE_SIGN_DIR_BOTH
Definition: newclient.h:469
MSG_TYPE_MONUMENT_GRAVESTONE_2
#define MSG_TYPE_MONUMENT_GRAVESTONE_2
Definition: newclient.h:480
get_titlelist
static titlelist * get_titlelist(int i)
Definition: readable.cpp:606
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:467
archetype::clone
object clone
Definition: object.h:476
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:423
book_descrpt
static const char *const book_descrpt[]
Definition: readable.cpp:443
ROD
@ ROD
Definition: object.h:112
init_readable
void init_readable(void)
Definition: readable.cpp:894
titlelist::next
titlelist * next
Definition: readable.cpp:124
python_init.path
path
Definition: python_init.py:8
done
int done
Definition: readable.cpp:1552
init_book_archive
static void init_book_archive(void)
Definition: readable.cpp:728
tailor_readable_ob
void tailor_readable_ob(object *book, int msg_type)
Definition: readable.cpp:1869
spellpath_msg
static StringBuffer * spellpath_msg(int level, size_t booksize, StringBuffer *buf)
Definition: readable.cpp:1588
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
object::value
int32_t value
Definition: object.h:358
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:477
add_book_to_list
static void add_book_to_list(const object *book, int msgtype)
Definition: readable.cpp:1085
object::type
uint8_t type
Definition: object.h:346
PATH_SUMMON
#define PATH_SUMMON
Definition: spells.h:19
MSG_TYPE_CARD_ELEGANT_1
#define MSG_TYPE_CARD_ELEGANT_1
Definition: newclient.h:439
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
sstring
const typedef char * sstring
Definition: global.h:47
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:441
artifact_describe
static StringBuffer * artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator)
Definition: readable.cpp:1386
PATH_FROST
#define PATH_FROST
Definition: spells.h:15
archetype
Definition: object.h:472
MSG_TYPE_CARD_MONEY_3
#define MSG_TYPE_CARD_MONEY_3
Definition: newclient.h:447
MSG_TYPE_BOOK_SPELL_EVOKER
#define MSG_TYPE_BOOK_SPELL_EVOKER
Definition: newclient.h:429
ARROW
@ ARROW
Definition: object.h:120
MSG_TYPE_MONUMENT_GRAVESTONE_3
#define MSG_TYPE_MONUMENT_GRAVESTONE_3
Definition: newclient.h:481
living::sp
int16_t sp
Definition: living.h:42
get_message_body
sstring get_message_body(const GeneralMessage *message)
Definition: readable.cpp:2054
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:475
MSG_TYPE_MONUMENT_WALL_3
#define MSG_TYPE_MONUMENT_WALL_3
Definition: newclient.h:484
titlelist::number
int number
Definition: readable.cpp:122
BOOK
@ BOOK
Definition: object.h:117
trim
const char * trim(const char *buf)
Definition: readable.cpp:656
MSG_TYPE_PAPER_ENVELOPE_2
#define MSG_TYPE_PAPER_ENVELOPE_2
Definition: newclient.h:458
MSG_TYPE_CARD_ELEGANT_2
#define MSG_TYPE_CARD_ELEGANT_2
Definition: newclient.h:440
MSG_TYPE_PAPER_NOTE_1
#define MSG_TYPE_PAPER_NOTE_1
Definition: newclient.h:450
RING
@ RING
Definition: object.h:188
MSG_TYPE_BOOK_SPELL_SORCERER
#define MSG_TYPE_BOOK_SPELL_SORCERER
Definition: newclient.h:432
MSG_TYPE_BOOK_SPELL_PYRO
#define MSG_TYPE_BOOK_SPELL_PYRO
Definition: newclient.h:431
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:470
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
guild_entry.text
text
Definition: guild_entry.py:44
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:570
mon_desc
static StringBuffer * mon_desc(const object *mon)
Definition: readable.cpp:1288
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:941
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
object::weight
int32_t weight
Definition: object.h:373
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:445
diamondslots.message
string message
Definition: diamondslots.py:57
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:457
spells.h
object::name
sstring name
Definition: object.h:317
get_message_title
sstring get_message_title(const GeneralMessage *message)
Definition: readable.cpp:2045
did_first_sp
int did_first_sp
Definition: readable.cpp:1547
MSGTYPE_LIB
#define MSGTYPE_LIB
Definition: readable.cpp:79
MSG_TYPE_CARD_SIMPLE_3
#define MSG_TYPE_CARD_SIMPLE_3
Definition: newclient.h:438
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:1756
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
MSG_TYPE_PAPER_LETTER_NEW_1
#define MSG_TYPE_PAPER_LETTER_NEW_1
Definition: newclient.h:455
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:426
strtoint
int strtoint(const char *buf)
Definition: recipe.cpp:711
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:4804
object::msg
sstring msg
Definition: object.h:328
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:864
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:474
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:964
heavy_book_name
static const char *const heavy_book_name[]
Definition: readable.cpp:382
level
int level
Definition: readable.cpp:1549
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:26
formula_author
static const char *const formula_author[]
Definition: readable.cpp:341
booklist
static titlelist * booklist
Definition: readable.cpp:139
MSG_TYPE_MONUMENT_STATUE_1
#define MSG_TYPE_MONUMENT_STATUE_1
Definition: newclient.h:476
title::level
unsigned int level
Definition: readable.cpp:112
MSG_TYPE_MONUMENT_WALL_1
#define MSG_TYPE_MONUMENT_WALL_1
Definition: newclient.h:482
get_readable_message_type
const readable_message_type * get_readable_message_type(object *readable)
Definition: readable.cpp:2032
art_author
static const char *const art_author[]
Definition: readable.cpp:243
last_readable_subtype
static const int last_readable_subtype
Definition: readable.cpp:534
get_random_mon
object * get_random_mon(int level)
Definition: readable.cpp:1259
book_overflow
int book_overflow(const char *buf1, const char *buf2, size_t booksize)
Definition: readable.cpp:709
FOOD
@ FOOD
Definition: object.h:115
MSG_TYPE_PAPER_NOTE_3
#define MSG_TYPE_PAPER_NOTE_3
Definition: newclient.h:452
MSG_TYPE_BOOK_QUARTO_2
#define MSG_TYPE_BOOK_QUARTO_2
Definition: newclient.h:428
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:1329
unique_book
static int unique_book(const object *book, int msgtype)
Definition: readable.cpp:1061
recipe::ingred
linked_char * ingred
Definition: recipe.h:22
MSG_TYPE_CARD_SIMPLE_1
#define MSG_TYPE_CARD_SIMPLE_1
Definition: newclient.h:436
light_book_name
static const char *const light_book_name[]
Definition: readable.cpp:363
MSG_TYPE_MONUMENT_STONE_1
#define MSG_TYPE_MONUMENT_STONE_1
Definition: newclient.h:473
archetype::name
sstring name
Definition: object.h:473
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:376
MSG_TYPE_SIGN
#define MSG_TYPE_SIGN
Definition: newclient.h:398
MSG_TYPE_BOOK
#define MSG_TYPE_BOOK
Definition: newclient.h:395
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:4492
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:850
MSG_TYPE_PAPER_SCROLL_MAGIC
#define MSG_TYPE_PAPER_SCROLL_MAGIC
Definition: newclient.h:463
BOOTS
@ BOOTS
Definition: object.h:215
make_formula_book
static void make_formula_book(object *book, int level)
Definition: readable.cpp:1628
FLAG_CHANGING
#define FLAG_CHANGING
Definition: define.h:263
title::msg_index
int msg_index
Definition: readable.cpp:114
SPELL
@ SPELL
Definition: object.h:217
MSG_TYPE_PAPER_SCROLL_NEW_1
#define MSG_TYPE_PAPER_SCROLL_NEW_1
Definition: newclient.h:461
sp_params
static struct @0 sp_params
SHIELD
@ SHIELD
Definition: object.h:138
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:537
nstrtok
int nstrtok(const char *buf1, const char *buf2)
Definition: readable.cpp:637
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:444
get_message_face
const Face * get_message_face(const GeneralMessage *message)
Definition: readable.cpp:2063
pnum
uint32_t pnum
Definition: readable.cpp:1548
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