Crossfire Server, Trunk
readable.c
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 
39 /* Define this if you want to archive book titles by contents.
40  * This option should enforce UNIQUE combinations of titles,authors and
41  * msg contents during and *between *game sessions.
42  * Note: a slight degeneracy exists since books are archived based on an integer
43  * index value calculated from the message text (similar to alchemy formulae).
44  * Sometimes two widely different messages have the same index value (rare). In
45  * this case, it is possible to occasionally generate 2 books with same title and
46  * different message content. Not really a bug, but rather a feature. This action
47  * should keeps player on their toes ;).
48  * Also, note that there is *finite *space available for archiving message and titles.
49  * Once this space is used, books will stop being archived. Not a serious problem
50  * under the current regime, since there are generally fewer possible (random)
51  * messages than space available on the titlelists.
52  * One exception (for sure) are the monster messages. But no worries, you should
53  * see all of the monster info in some order (but not all possble combinations)
54  * before the monster titlelist space is run out. You can increase titlelist
55  * space by increasing the array sizes for the monster book_authours and book_names
56  * (see max_titles[] array and include/read.h). Since the unique_book algorthm is
57  * kinda stupid, this program *may *slow down program execution if defined (but I don't
58  * think its a significant problem, at least, I have no problems running this option
59  * on a Sparc 10! Also, once archive title lists are filled and/or all possible msg
60  * combinations have been generated, unique_book isnt called anymore. It takes 5-10
61  * sessions for this to happen).
62  * Final note: the game remembers book/title/msg combinations from reading the
63  * file lib/bookarch. If you REMOVE this file, you will lose your archive. So
64  * be sure to copy it over to the new lib directory when you change versions.
65  * -b.t.
66  */
67 
68 /* This flag is useful to see what kind of output messages are created */
69 /* #define BOOK_MSG_DEBUG */
70 
71 /* This flag is useful for debugging archiving action */
72 /* #define ARCHIVE_DEBUG */
73 
75 #define MAX_TITLE_CHECK 20
76 
78 #define MSGTYPE_LIB 0
79 
80 #define MSGTYPE_MONSTER 1
81 
82 #define MSGTYPE_ARTIFACT 2
83 
84 #define MSGTYPE_SPELLPATH 3
85 
86 #define MSGTYPE_ALCHEMY 4
87 
88 #define MSGTYPE_GODS 5
89 
90 #define MSGTYPE_MSGFILE 6
91 
97 #define arraysize(arrayname) (sizeof(arrayname)/sizeof(*(arrayname)))
98 
99 /* Moved these structures from struct.h to this file in 0.94.3 - they
100  * are not needed anyplace else, so why have them globally declared?
101  */
102 
107 typedef struct titlestruct {
108  const char *name;
109  const char *authour;
110  const char *archname;
111  unsigned int level;
112  size_t size;
113  int msg_index;
114  struct titlestruct *next;
115 } title;
116 
120 typedef struct titleliststruct {
121  int number;
124 } titlelist;
125 
127 typedef struct namebytype {
128  const char *name;
129  int type;
130 } arttypename;
131 
132 static void add_book(title *book, int type, const char *fname, int lineno);
133 
138 static titlelist *booklist = NULL;
139 
141 static objectlink *first_mon_info = NULL;
142 
143 static int nrofmon = 0,
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  int nroftitle = 0;
731  char buf[MAX_BUF], fname[MAX_BUF], *cp;
732  static int did_init_barch = 0;
733 
734  if (did_init_barch)
735  return;
736  did_init_barch = 1;
737 
738  if (!booklist)
740 
741  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
742  LOG(llevDebug, " Reading bookarch from %s...\n", fname);
743 
744  fp = fopen(fname, "r");
745  if (fp != NULL) {
746  int type;
747  size_t i;
748  titlelist *bl;
749  int lineno;
750  title *book;
751  int skipping;
752 
753  skipping = 0;
754  book = NULL;
755  type = -1;
756  for (lineno = 1; fgets(buf, MAX_BUF, fp) != NULL; lineno++) {
757  int len;
758  int value;
759 
760  if (*buf == '#')
761  continue;
762  cp = strchr(buf, '\n');
763  if (cp != NULL) {
764  while (cp > buf && (cp[-1] == ' ' || cp[-1] == '\t'))
765  cp--;
766  *cp = '\0';
767  }
768  cp = buf;
769  if (strncmp(buf, "title ", 6) == 0) {
770  skipping = 0;
771  cp = buf+6;
772  while (*cp == ' ' || *cp == '\t')
773  cp++;
774  if (*cp == '\0') {
775  LOG(llevInfo, "Warning: missing book title at %s, line %d\n", fname, lineno);
776  book = NULL;
777  } else {
778  book = get_empty_book(); /* init new book entry */
779  book->name = add_string(cp);
780  type = -1;
781  nroftitle++;
782  }
783  } else if (book == NULL) {
784  if (!skipping) {
785  skipping = 1;
786  LOG(llevInfo, "Warning: expecting 'title' at %s, line %d\n", fname, lineno);
787  }
788  } else if (strncmp(buf, "authour ", 8) == 0) {
789  cp = buf+8;
790  while (*cp == ' ' || *cp == '\t')
791  cp++;
792  if (*cp == '\0') {
793  LOG(llevInfo, "Warning: missing book authour at %s, line %d\n", fname, lineno);
794  } else {
795  book->authour = add_string(cp);
796  }
797  } else if (strncmp(buf, "arch ", 5) == 0) {
798  cp = buf+5;
799  while (*cp == ' ' || *cp == '\t')
800  cp++;
801  if (*cp == '\0') {
802  LOG(llevInfo, "Warning: missing book arch at %s, line %d\n", fname, lineno);
803  } else {
804  book->archname = add_string(cp);
805  }
806  } else if (sscanf(buf, "level %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
807  book->level = value;
808  } else if (sscanf(buf, "type %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
809  type = value;
810  } else if (sscanf(buf, "size %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
811  book->size = value;
812  } else if (sscanf(buf, "index %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
813  book->msg_index = value;
814  } else if (strcmp(buf, "end") == 0) { /* link it */
815  add_book(book, type, fname, lineno);
816  book = NULL;
817  type = -1;
818  } else {
819  LOG(llevInfo, "Warning: syntax error at %s, line %d\n", fname, lineno);
820  }
821  }
822  if (book != NULL) {
823  LOG(llevInfo, "Warning: missing 'end' at %s, line %d\n", fname, lineno);
824  add_book(book, type, fname, lineno);
825  }
826  LOG(llevDebug, " book archives(used/avail):\n");
827  for (bl = booklist, i = 0; bl != NULL && i < arraysize(max_titles); bl = bl->next, i++) {
828  LOG(llevDebug, "(%d/%d)\n", bl->number, max_titles[i]);
829  }
830  fclose(fp);
831  }
832 
833 #ifdef BOOK_MSG_DEBUG
834  LOG(llevDebug, "\n init_book_archive() got %d titles.\n", nroftitle);
835 #endif
836  LOG(llevDebug, " done.\n");
837 }
838 
846 static void add_book(title *book, int type, const char *fname, int lineno) {
847  titlelist *bl;
848 
849  if (type == -1) {
850  LOG(llevInfo, "Warning: book with no type at %s, line %d; using type 0\n", fname, lineno);
851  type = 0;
852  }
853 
854  bl = get_titlelist(type);
855  book->next = bl->first_book;
856  bl->first_book = book;
857  bl->number++;
858 }
859 
860 static void do_monster(archetype *at) {
861  if (QUERY_FLAG(&at->clone, FLAG_MONSTER) && (!at->head)
862  && (object_get_value(&at->clone, MONSTER_EXCLUDE_FROM_READABLE_KEY) == NULL)
863  && (!QUERY_FLAG(&at->clone, FLAG_CHANGING) || QUERY_FLAG(&at->clone, FLAG_UNAGGRESSIVE))) {
864  objectlink *mon = (objectlink *)malloc(sizeof(objectlink));
865  if (!mon) {
866  LOG(llevError, "init_mon_info: malloc failed!\n");
867  abort();
868  }
869  mon->ob = &at->clone;
870  mon->id = nrofmon;
871  mon->next = first_mon_info;
873  nrofmon++;
874  }
875 }
876 
881 static void init_mon_info(void) {
882  static int did_init_mon_info = 0;
883 
884  if (did_init_mon_info)
885  return;
886  did_init_mon_info = 1;
887 
889 
890  LOG(llevDebug, "init_mon_info() got %d monsters\n", nrofmon);
891 }
892 
899 void init_readable(void) {
900  static int did_this = 0;
901 
902  if (did_this)
903  return;
904  did_this = 1;
905 
906  LOG(llevDebug, "Initializing reading data...\n");
908  init_mon_info();
909  LOG(llevDebug, " done reading data\n");
910 }
911 
912 /*****************************************************************************
913  *
914  * This is the start of the administrative functions when creating
915  * new books (ie, updating title and the like)
916  *
917  *****************************************************************************/
918 
930 static title *find_title(const object *book, int msgtype) {
931  title *t;
932  titlelist *tl;
933  size_t length;
934  int index;
935 
936  if (msgtype < 0)
937  return (title *)NULL;
938 
939  tl = get_titlelist(msgtype);
940  if (!tl)
941  return (title *)NULL;
942 
943  length = strlen(book->msg);
944  index = strtoint(book->msg);
945  for (t = tl->first_book; t; t = t->next)
946  if (t->size == length && t->msg_index == index) {
947 #ifdef ARCHIVE_DEBUG
948  LOG(llevDebug, "Found title match (list %d): %s %s (%d)\n", msgtype, t->name, t->authour, t->msg_index);
949 #endif
950  return t;
951  }
952 
953  return (title *)NULL;
954 }
955 
969 static void new_text_name(object *book, int msgtype) {
970  const char *name;
971 
972  if (book->type != BOOK)
973  return;
974 
975  switch (msgtype) {
976  case MSGTYPE_MONSTER:
978  break;
979 
980  case MSGTYPE_ARTIFACT:
982  break;
983 
984  case MSGTYPE_SPELLPATH:
986  break;
987 
988  case MSGTYPE_ALCHEMY:
990  break;
991 
992  case MSGTYPE_GODS:
994  break;
995 
996  case MSGTYPE_MSGFILE:
997  default:
998  if (book->weight > 2000) { /* based on weight */
1000  } else {
1002  }
1003  break;
1004  }
1005  free_string(book->name);
1006  book->name = add_string(name);
1007 }
1008 
1018 static void add_author(object *op, int msgtype) {
1019  char title[MAX_BUF];
1020  const char *name;
1021 
1022  if (msgtype < 0 || strlen(op->msg) < 5)
1023  return;
1024 
1025  switch (msgtype) {
1026  case MSGTYPE_MONSTER:
1028  break;
1029 
1030  case MSGTYPE_ARTIFACT:
1032  break;
1033 
1034  case MSGTYPE_SPELLPATH:
1036  break;
1037 
1038  case MSGTYPE_ALCHEMY:
1040  break;
1041 
1042  case MSGTYPE_GODS:
1044  break;
1045 
1046  case MSGTYPE_MSGFILE:
1047  default:
1049  }
1050 
1051  snprintf(title, sizeof(title), "of %s", name);
1052  op->title = add_string(title);
1053 }
1054 
1066 static int unique_book(const object *book, int msgtype) {
1067  title *test;
1068 
1069  if (!booklist)
1070  return 1; /* No archival entries! Must be unique! */
1071 
1072  /* Go through the booklist. If the author and name match, not unique so
1073  * return 0.
1074  */
1075  for (test = get_titlelist(msgtype)->first_book; test; test = test->next) {
1076  if (!strcmp(test->name, book->name) && !strcmp(book->title, test->authour))
1077  return 0;
1078  }
1079  return 1;
1080 }
1081 
1090 static void add_book_to_list(const object *book, int msgtype) {
1091  titlelist *tl = get_titlelist(msgtype);
1092  title *t;
1093 
1094  if (!tl) {
1095  LOG(llevError, "add_book_to_list can't get booklist!\n");
1096  return;
1097  }
1098 
1099  t = get_empty_book();
1100  t->name = add_string(book->name);
1101  t->authour = add_string(book->title);
1102  t->size = strlen(book->msg);
1103  t->msg_index = strtoint(book->msg);
1104  t->archname = add_string(book->arch->name);
1105  t->level = book->level;
1106 
1107  t->next = tl->first_book;
1108  tl->first_book = t;
1109  tl->number++;
1110 
1111  /* We have stuff we need to write now */
1113 
1114 #ifdef ARCHIVE_DEBUG
1115  LOG(llevDebug, "Archiving new title: %s %s (%d)\n", book->name, book->title, msgtype);
1116 #endif
1117 }
1118 
1132 static void change_book(object *book, int msgtype) {
1133  titlelist *tl;
1134  title *t;
1135  int tries;
1136 
1137  if (book->type != BOOK) {
1138  LOG(llevError, "change_book_name() called w/ illegal obj type.\n");
1139  return;
1140  }
1141 
1142  tl = get_titlelist(msgtype);
1143  t = NULL;
1144  tries = 0;
1145 
1146  /* look to see if our msg already been archived. If so, alter
1147  * the book to match the archival text. If we fail to match,
1148  * then we archive the new title/name/msg combo if there is
1149  * room on the titlelist.
1150  */
1151 
1152  if (strlen(book->msg) > 5 && (t = find_title(book, msgtype))) {
1153  object *tmpbook;
1154  sstring marker = object_get_value(book, "knowledge_marker");
1155 
1156  /* alter book properties */
1157  tmpbook = create_archetype(t->archname);
1158  if (marker != NULL)
1159  /* need to copy the knowledge_marker */
1160  object_set_value(tmpbook, "knowledge_marker", marker, 1);
1161  object_set_msg(tmpbook, book->msg);
1162  object_copy(tmpbook, book);
1163  object_free_drop_inventory(tmpbook);
1164 
1165  book->title = add_string(t->authour);
1166  free_string(book->name);
1167  book->name = add_string(t->name);
1168  book->level = t->level;
1169  } else { /* Don't have any default title, so lets make up a new one */
1170  int numb, maxnames = max_titles[msgtype];
1171  const char *old_title;
1172  const char *old_name;
1173 
1174  old_title = book->title ? add_string(book->title) : NULL;
1175  old_name = add_string(book->name);
1176 
1177  /* some pre-generated books have title already set (from
1178  * maps), also don't bother looking for unique title if
1179  * we already used up all the available names! */
1180 
1181  if (!tl) {
1182  LOG(llevError, "change_book_name(): can't find title list\n");
1183  numb = 0;
1184  } else
1185  numb = tl->number;
1186 
1187  if (numb == maxnames) {
1188 #ifdef ARCHIVE_DEBUG
1189  LOG(llevDebug, "titles for list %d full (%d possible).\n", msgtype, maxnames);
1190 #endif
1191  if (old_title != NULL)
1192  free_string(old_title);
1193  free_string(old_name);
1194  return;
1195  }
1196  /* shouldnt change map-maker books */
1197  if (!book->title)
1198  do {
1199  /* random book name */
1200  new_text_name(book, msgtype);
1201  add_author(book, msgtype); /* random author */
1202  tries++;
1203  } while (!unique_book(book, msgtype) && tries < MAX_TITLE_CHECK);
1204 
1205  /* Now deal with 2 cases.
1206  * 1) If no space for a new title exists lets just restore
1207  * the old book properties. Remember, if the book had
1208  * matchd an older entry on the titlelist, we shouldnt
1209  * have called this routine in the first place!
1210  * 2) If we got a unique title, we need to add it to
1211  * the list.
1212  */
1213 
1214  if (tries == MAX_TITLE_CHECK) {
1215 #ifdef ARCHIVE_DEBUG
1216  LOG(llevDebug, "Failed to obtain unique title for %s %s (names:%d/%d)\n", book->name, book->title, numb, maxnames);
1217 #endif
1218  /* restore old book properties here */
1219  free_string(book->name);
1220  free_string(book->title);
1221  book->title = old_title != NULL ? add_string(old_title) : NULL;
1222 
1223  if (RANDOM()%4) {
1224  /* Lets give the book a description to individualize it some */
1225  char new_name[MAX_BUF];
1226 
1227  snprintf(new_name, MAX_BUF, "%s %s", book_descrpt[RANDOM()%arraysize(book_descrpt)], old_name);
1228  book->name = add_string(new_name);
1229  } else {
1230  book->name = add_string(old_name);
1231  }
1232  } else if (book->title && strlen(book->msg) > 5) { /* archive if long msg texts */
1233  add_book_to_list(book, msgtype);
1234  }
1235 
1236  if (old_title != NULL)
1237  free_string(old_title);
1238  free_string(old_name);
1239  }
1240 }
1241 
1242 /*****************************************************************************
1243  *
1244  * This is the start of the area that generates the actual contents
1245  * of the book.
1246  *
1247  *****************************************************************************/
1248 
1249 /*****************************************************************************
1250  * Monster msg generation code.
1251  ****************************************************************************/
1252 
1264 object *get_random_mon(int level) {
1265  objectlink *mon;
1266  int i, monnr;
1267 
1268  /* safety check. Problem w/ init_mon_info list? */
1269  if (!nrofmon || !first_mon_info)
1270  return (object *)NULL;
1271 
1272  if (!level) {
1273  /* lets get a random monster from the mon_info linked list */
1274  monnr = RANDOM()%nrofmon;
1275 
1276  for (mon = first_mon_info, i = 0; mon; mon = mon->next, i++)
1277  if (i == monnr)
1278  break;
1279 
1280  if (!mon) {
1281  LOG(llevError, "get_random_mon: Didn't find a monster when we should have\n");
1282  return NULL;
1283  }
1284  return mon->ob;
1285  }
1286 
1287  /* Case where we are searching by level. Redone 971225 to be clearer
1288  * and more random. Before, it looks like it took a random monster from
1289  * the list, and then returned the first monster after that which was
1290  * appropriate level. This wasn't very random because if you had a
1291  * bunch of low level monsters and then a high level one, if the random
1292  * determine took one of the low level ones, it would just forward to the
1293  * high level one and return that. Thus, monsters that immediately followed
1294  * a bunch of low level monsters would be more heavily returned. It also
1295  * means some of the dragons would be poorly represented, since they
1296  * are a group of high level monsters all around each other.
1297  */
1298 
1299  /* First count number of monsters meeting level criteria */
1300  for (mon = first_mon_info, i = 0; mon; mon = mon->next)
1301  if (mon->ob->level >= level)
1302  i++;
1303 
1304  if (i == 0) {
1305  LOG(llevError, "get_random_mon() couldn't return monster for level %d\n", level);
1306  return NULL;
1307  }
1308 
1309  monnr = RANDOM()%i;
1310  for (mon = first_mon_info; mon; mon = mon->next)
1311  if (mon->ob->level >= level && monnr-- == 0)
1312  return mon->ob;
1313 
1314  LOG(llevError, "get_random_mon(): didn't find a monster when we should have\n");
1315  return NULL;
1316 }
1317 
1327 static StringBuffer *mon_desc(const object *mon) {
1328  StringBuffer *desc = stringbuffer_new();
1329  stringbuffer_append_printf(desc, "\n---\n *** %s ***\n", mon->name);
1330  describe_item(mon, NULL, 0, desc);
1331  return desc;
1332 }
1333 
1345 static object *get_next_mon(const object *tmp) {
1346  objectlink *mon;
1347 
1348  for (mon = first_mon_info; mon; mon = mon->next)
1349  if (mon->ob == tmp)
1350  break;
1351 
1352  /* didn't find a match */
1353  if (!mon)
1354  return NULL;
1355  if (mon->next)
1356  return mon->next->ob;
1357  else
1358  return first_mon_info->ob;
1359 }
1360 
1373 static StringBuffer *mon_info_msg(int level, size_t booksize, object *book) {
1374  object *tmp;
1375  StringBuffer *marker = stringbuffer_new(), *desc = stringbuffer_new(), *mon = NULL;
1376  int added = 0;
1377  sstring final;
1378  const char *sep = ":";
1379 
1380  /*preamble */
1381  stringbuffer_append_string(desc, "This beastiary contains:");
1382  stringbuffer_append_string(marker, "monster");
1383 
1384  /* lets print info on as many monsters as will fit in our
1385  * document.
1386  * 8-96 Had to change this a bit, otherwise there would
1387  * have been an impossibly large number of combinations
1388  * of text! (and flood out the available number of titles
1389  * in the archive in a snap!) -b.t.
1390  */
1391  for (tmp = get_random_mon(level*3); tmp; tmp = get_next_mon(tmp)) {
1392  /* monster description */
1393  mon = mon_desc(tmp);
1394 
1396  break;
1397  added++;
1398  stringbuffer_append_printf(marker, "%s%s", sep, tmp->arch->name);
1399  sep = "/";
1402  mon = NULL;
1403  }
1404 
1405  if (mon != NULL) {
1407  }
1408 
1409  final = stringbuffer_finish_shared(marker);
1410  if (added)
1411  object_set_value(book, "knowledge_marker", final, 1);
1412  free_string(final);
1413 
1414  return desc;
1415 }
1416 
1417 /*****************************************************************************
1418  * Artifact msg generation code.
1419  ****************************************************************************/
1420 
1430 static StringBuffer *artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator) {
1431  object *tmp;
1432  int chance;
1433  StringBuffer *desc = stringbuffer_new(), *sbuf;
1434 
1435  if (separator)
1436  stringbuffer_append_string(desc, "---\n");
1437 
1438  /* Name */
1439  if (art->allowed != NULL) {
1440  archetype *arch;
1441  linked_char *temp = art->allowed;
1442  int inv = 0, w;
1443 
1444  assert(art->allowed_size > 0);
1445  if (art->allowed_size > 1)
1446  w = 1 + RANDOM() % art->allowed_size;
1447  else
1448  w = 1;
1449 
1450  while (w > 1) {
1451  assert(temp);
1452  temp = temp->next;
1453  w--;
1454  }
1455 
1456  if (temp->name[0] == '!')
1457  inv = 1;
1458 
1460  arch = try_find_archetype(temp->name + inv);
1461  if (!arch)
1463 
1464  if (!arch)
1465  LOG(llevError, "artifact_msg: missing archetype %s for artifact %s (type %d)\n", temp->name + inv, art->item->name, art->item->type);
1466  else {
1467  if (inv)
1468  stringbuffer_append_printf(desc, " A %s (excepted %s) of %s", art_name_array[art_name].name, arch->clone.name_pl, art->item->name);
1469  else
1470  stringbuffer_append_printf(desc, " A %s of %s", arch->clone.name, art->item->name);
1471  }
1472  } else { /* default name is used */
1473  /* use the base 'generic' name for our artifact */
1474  stringbuffer_append_printf(desc, " The %s of %s", art_name_array[art_name].name, art->item->name);
1475  }
1476 
1477  /* chance of finding */
1478  stringbuffer_append_string(desc, " is ");
1479  chance = 100*((float)art->chance/al->total_chance);
1480  if (chance >= 20)
1481  stringbuffer_append_string(desc, "an uncommon");
1482  else if (chance >= 10)
1483  stringbuffer_append_string(desc, "an unusual");
1484  else if (chance >= 5)
1485  stringbuffer_append_string(desc, "a rare");
1486  else
1487  stringbuffer_append_string(desc, "a very rare");
1488 
1489  /* value of artifact */
1490  stringbuffer_append_printf(desc, " item with a value that is %d times normal.\n", art->item->value);
1491 
1492  /* include the message about the artifact, if exists, and book
1493  * level is kinda high */
1494  if (message && !(strlen(art->item->msg) > BOOK_BUF))
1495  stringbuffer_append_string(desc, art->item->msg);
1496 
1497  /* properties of the artifact */
1498  tmp = object_new();
1499  add_abilities(tmp, art->item);
1500  tmp->type = al->type;
1502  sbuf = describe_item(tmp, NULL, 0, NULL);
1503  if (stringbuffer_length(sbuf) > 1) {
1504  stringbuffer_append_string(desc, " Properties of this artifact include:\n ");
1506  stringbuffer_append_string(desc, "\n");
1507  }
1508  free(stringbuffer_finish(sbuf));
1510 
1511  return desc;
1512 }
1513 
1525 static StringBuffer *artifact_msg(unsigned int level, size_t booksize) {
1526  const artifactlist *al;
1527  const artifact *art;
1528  int i, type, index;
1529  int book_entries = level > 5 ? RANDOM()%3+RANDOM()%3+2 : RANDOM()%level+1;
1531 
1532  /* values greater than 5 create msg buffers that are too big! */
1533  if (book_entries > 5)
1534  book_entries = 5;
1535 
1536  /* lets determine what kind of artifact type randomly.
1537  * Right now legal artifacts only come from those listed
1538  * in art_name_array. Also, we check to be sure an artifactlist
1539  * for that type exists!
1540  */
1541  i = 0;
1542  do {
1545  al = find_artifactlist(type);
1546  i++;
1547  } while (al == NULL && i < 10);
1548 
1549  if (i == 10) { /* Unable to find a message */
1551  return message;
1552  }
1553 
1554  /* There is no reason to start on the artifact list at the beginning. Lets
1555  * take our starting position randomly... */
1556  art = al->items;
1557  for (i = RANDOM()%level+RANDOM()%2+1; i > 0; i--) {
1558  if (art == NULL)
1559  art = al->items; /* hmm, out of stuff, loop back around */
1560  art = art->next;
1561  }
1562 
1563  /* Ok, lets print out the contents */
1564  stringbuffer_append_printf(message, "Herein %s detailed %s...\n", book_entries > 1 ? "are" : "is", book_entries > 1 ? "some artifacts" : "an artifact");
1565 
1566  i = 0;
1567  /* artifact msg attributes loop. Lets keep adding entries to the 'book'
1568  * as long as we have space up to the allowed max # (book_entires)
1569  */
1570  while (book_entries > 0) {
1571  int with_message;
1572  if (art == NULL)
1573  art = al->items;
1574  with_message = (art->item->msg && RANDOM()%4+1 < level) ? 1 : 0;
1575 
1576  desc = artifact_describe(art, al, with_message, index, i++);
1577 
1579  stringbuffer_delete(desc);
1580  break;
1581  }
1582 
1584  stringbuffer_delete(desc);
1585 
1586  art = art->next;
1587  book_entries--;
1588  }
1589 
1590  return message;
1591 }
1592 
1593 /*****************************************************************************
1594  * Spellpath message generation
1595  *****************************************************************************/
1596 
1598 static struct {
1599  int prayers;
1600  int did_first_sp;
1601  uint32_t pnum;
1602  int level;
1603  size_t booksize;
1605  int done;
1609 static void do_spellpath_msg(archetype *at) {
1610  /* Determine if this is an appropriate spell. Must
1611  * be of matching path, must be of appropriate type (prayer
1612  * or not), and must be within the valid level range.
1613  */
1614  if (at->clone.type == SPELL
1615  && at->clone.path_attuned & sp_params.pnum
1616  && ((at->clone.stats.grace && sp_params.prayers) || (at->clone.stats.sp && !sp_params.prayers))
1617  && at->clone.level < sp_params.level*8) {
1618  if (strlen(at->clone.name) + stringbuffer_length(sp_params.buf) >= sp_params.booksize) {
1619  sp_params.done = 1;
1620  return;
1621  }
1622 
1623  if (sp_params.did_first_sp)
1625  sp_params.did_first_sp = 1;
1626  stringbuffer_append_string(sp_params.buf,at->clone.name);
1627  }
1628 }
1629 
1644  int path = RANDOM()%NRSPELLPATHS;
1645  sp_params.prayers = RANDOM()%2;
1646  sp_params.did_first_sp = 0;
1647  sp_params.pnum = spellpathdef[path];
1648  sp_params.done = 0;
1649 
1650  if (buf == NULL) {
1651  buf = stringbuffer_new();
1652  /* Preamble */
1653  stringbuffer_append_printf(buf, "Herein are detailed the names of %s", sp_params.prayers ? "prayers" : "incantations");
1654  stringbuffer_append_printf(buf, " belonging to the path of %s:\n ", spellpathnames[path]);
1655  }
1656  sp_params.level = level;
1657  sp_params.booksize = booksize;
1658  sp_params.buf = buf;
1659 
1661 
1662  /* Geez, no spells were generated. */
1663  if (!sp_params.did_first_sp) {
1664  if (RANDOM()%4) { /* usually, lets make a recursive call... */
1665  // If we do a recursive call, we reset the spell path, so we will want to reset our text as well.
1667  return spellpath_msg(level, booksize, NULL);
1668  }
1669  /* give up, cause knowing no spells exist for path is info too. need the header too. */
1670  stringbuffer_append_string(buf, "- no known spells exist -\n");
1671  }
1672  return buf;
1673 }
1674 
1683 static void make_formula_book(object *book, int level) {
1684  recipelist *fl;
1685  recipe *formula;
1686  int chance, count = 0;
1687  const char *op_name;
1688  archetype *at;
1689  StringBuffer *text, *title;
1690  char *final, km[MAX_BUF];
1691 
1692  /* the higher the book level, the more complex (ie number of
1693  * ingredients) the formula can be.
1694  */
1695  fl = get_formulalist((RANDOM()%level)/3+1);
1696  if (!fl)
1697  fl = get_formulalist(1); /* safety */
1698 
1699  if (fl->total_chance == 0) {
1700  object_set_msg(book, " <indecipherable text>\n");
1702  add_author(book, MSGTYPE_ALCHEMY);
1703  return;
1704  }
1705 
1706  /* get a random formula, weighted by its bookchance */
1707  chance = RANDOM()%fl->total_chance;
1708  for (formula = fl->items; formula != NULL; formula = formula->next) {
1709  chance -= formula->chance;
1710  if (chance <= 0 && formula->chance != 0 && !formula->is_combination)
1711  break;
1712  }
1713 
1714  if (!formula || formula->arch_names <= 0) {
1715  object_set_msg(book, " <indecipherable text>\n");
1717  add_author(book, MSGTYPE_ALCHEMY);
1718  return;
1719  }
1720 
1721  /* looks like a formula was found. Base the amount
1722  * of information on the booklevel and the spellevel
1723  * of the formula. */
1724 
1725  op_name = formula->arch_name[RANDOM()%formula->arch_names];
1726  at = find_archetype(op_name);
1727  if (at == (archetype *)NULL) {
1728  LOG(llevError, "formula_msg() can't find arch %s for formula.\n", op_name);
1729  object_set_msg(book, " <indecipherable text>\n");
1731  add_author(book, MSGTYPE_ALCHEMY);
1732  return;
1733  }
1734  op_name = at->clone.name;
1735 
1736  text = stringbuffer_new();
1737  title = stringbuffer_new();
1738 
1739  /* preamble */
1740  stringbuffer_append_printf(text, "Herein is described a project using %s:\n", formula->skill ? formula->skill : "an unknown skill");
1741 
1742  /* item name */
1743  if (strcmp(formula->title, "NONE")) {
1744  stringbuffer_append_printf(text, "The %s of %s", op_name, formula->title);
1745  /* This results in things like pile of philo. sulfur.
1746  * while philo. sulfur may look better, without this,
1747  * you get things like 'the wise' because its missing the
1748  * water of section.
1749  */
1751  } else {
1752  stringbuffer_append_printf(text, "The %s", op_name);
1754  if (at->clone.title) {
1755  stringbuffer_append_printf(text, " %s", at->clone.title);
1756  stringbuffer_append_printf(title, " %s", at->clone.title);
1757  }
1758  }
1759  /* Lets name the book something meaningful ! */
1760  if (book->name)
1761  free_string(book->name);
1762  book->name = stringbuffer_finish_shared(title);
1763  if (book->title) {
1764  free_string(book->title);
1765  book->title = NULL;
1766  }
1767 
1768  /* ingredients to make it */
1769  if (formula->ingred != NULL) {
1770  linked_char *next;
1771  archetype *at;
1772  char name[MAX_BUF];
1773 
1774  at = find_archetype(formula->cauldron);
1775  if (at)
1776  query_name(&at->clone, name, MAX_BUF);
1777  else
1778  snprintf(name, sizeof(name), "an unknown place");
1779 
1780  stringbuffer_append_printf(text, " may be made at %s using the following ingredients:\n", name);
1781 
1782  for (next = formula->ingred; next != NULL; next = next->next) {
1783  count++;
1784  stringbuffer_append_printf(text, "%s\n", next->name);
1785  }
1786  } else {
1787  LOG(llevError, "formula_msg() no ingredient list for object %s of %s\n", op_name, formula->title);
1789  }
1790 
1791  final = stringbuffer_finish(text);
1792  object_set_msg(book, final);
1793  free(final);
1794 
1797  snprintf(km, sizeof(km), "alchemy:%d:%d:%s", count, formula->index, formula->title);
1798  object_set_value(book, "knowledge_marker", km, 1);
1799 }
1800 
1811 static StringBuffer *msgfile_msg(object *book, size_t booksize) {
1812  StringBuffer *ret = stringbuffer_new();
1813 
1815 
1816  if (msg && strlen(msg->message) <= booksize) {
1817  stringbuffer_append_string(ret, msg->message);
1818  if (msg->identifier != NULL) {
1819  char km[HUGE_BUF];
1822  snprintf(km, sizeof(km), "message:%s", msg->identifier);
1823  object_set_value(book, "knowledge_marker", km, 1);
1824  }
1825  if (msg->quest_code) {
1826  /* add a 'apply' hook to launch the quest */
1827  archetype *at = find_archetype("quest_advance_apply");
1828  if (at != NULL) {
1829  object *event = object_create_arch(at);
1830  FREE_AND_COPY(event->name, msg->quest_code);
1831  object_insert_in_ob(event, book);
1832  }
1833  }
1834  } else
1835  stringbuffer_append_string(ret, "\n <undecipherable text>");
1836 
1837  return ret;
1838 }
1839 
1854 static StringBuffer *god_info_msg(int level, size_t booksize, object *book) {
1855  int what = 0;
1856  const object *god = pntr_to_god_obj(get_rand_god());
1857  StringBuffer *desc = NULL;
1858 
1859  if (!god)
1860  return NULL; /* oops, problems... */
1861 
1862  if (booksize > BOOK_BUF) {
1863  LOG(llevError, "common/readable.c:god_info_msg() - passed in booksize (%lu) is larger than book buffer (%d)\n", (unsigned long)booksize, BOOK_BUF);
1864  booksize = BOOK_BUF;
1865  }
1866 
1867  if (level >= 2 && RANDOM()%2) {
1868  what |= GOD_ENEMY;
1869  }
1870  if (level >= 3 && RANDOM()%2) {
1871  what |= GOD_HOLYWORD;
1872  }
1873  if (level >= 4 && RANDOM()%2) {
1874  what |= GOD_RESISTANCES;
1875  }
1876  if (level >= 5 && RANDOM()%2) {
1877  what |= GOD_SACRED;
1878  }
1879  if (level >= 6 && RANDOM()%2) {
1880  what |= GOD_BLESSED;
1881  }
1882  if (level >= 8 && RANDOM()%2) {
1883  what |= GOD_IMMUNITIES;
1884  }
1885  if (level >= 12 && RANDOM()%2) {
1886  what |= GOD_PATHS;
1887  }
1888 
1889  desc = stringbuffer_new();
1890  what = describe_god(god, what, desc, booksize);
1891 
1892  /* check to be sure new buffer size dont exceed either
1893  * the maximum buffer size, or the 'natural' size of the
1894  * book... */
1895  if (stringbuffer_length(desc) > 1 && stringbuffer_length(desc) <= booksize) {
1896  char buf[BOOK_BUF];
1897  snprintf(buf, sizeof(buf), "god:%s:%d", god->name, what);
1898  object_set_value(book, "knowledge_marker", buf, 1);
1899  return desc;
1900  }
1901 
1902  stringbuffer_delete(desc);
1903  return NULL;
1904 }
1905 
1924 void tailor_readable_ob(object *book, int msg_type) {
1925  int level = book->level ? RANDOM()%book->level+1 : 1;
1926  size_t book_buf_size;
1927  StringBuffer *message = NULL;
1928 
1929  /* safety */
1930  if (book->type != BOOK)
1931  return;
1932 
1933  if (level <= 0)
1934  return; /* if no level no point in doing any more... */
1935 
1936  /* Max text length this book can have. */
1937  book_buf_size = BOOKSIZE(book);
1938  book_buf_size -= strlen("\n"); /* Keep enough for final \n. */
1939  assert(book_buf_size < BOOK_BUF);
1940 
1941  /* &&& The message switch &&& */
1942  /* Below all of the possible types of messages in the "book"s.
1943  */
1944  /*
1945  * IF you add a new type of book msg, you will have to do several things.
1946  * 1) make sure there is an entry in the msg switch below!
1947  * 2) make sure there is an entry in max_titles[] array.
1948  * 3) make sure there are entries for your case in new_text_title()
1949  * and add_authour().
1950  * 4) you may want separate authour/book name arrays in read.h
1951  */
1952 
1953  if (msg_type >= (int)arraysize(max_titles))
1954  msg_type = 0;
1955 
1956  msg_type = msg_type > 0 ? msg_type : (int)(RANDOM()%6);
1957  switch (msg_type) {
1958  case MSGTYPE_MONSTER:
1959  message = mon_info_msg(level, book_buf_size, book);
1960  break;
1961 
1962  case MSGTYPE_ARTIFACT:
1963  message = artifact_msg(level, book_buf_size);
1964  break;
1965 
1966  case MSGTYPE_SPELLPATH: /* grouping incantations/prayers by path */
1967  message = spellpath_msg(level, book_buf_size, NULL);
1968  break;
1969 
1970  case MSGTYPE_ALCHEMY: /* describe an alchemy formula */
1971  make_formula_book(book, level);
1972  /* make_formula_book already gives title */
1973  return;
1974  break;
1975 
1976  case MSGTYPE_GODS: /* bits of information about a god */
1977  message = god_info_msg(level, book_buf_size, book);
1978  break;
1979 
1980  case MSGTYPE_LIB: /* use info list in lib/ */
1981  default:
1982  message = msgfile_msg(book, book_buf_size);
1983  break;
1984  }
1985 
1986  if (message != NULL) {
1987  char *final;
1989  final = stringbuffer_finish(message);
1990  object_set_msg(book, final);
1991  free(final);
1992  /* lets give the "book" a new name, which may be a compound word */
1993  change_book(book, msg_type);
1994  }
1995 }
1996 
1997 /*****************************************************************************
1998  *
1999  * Cleanup routine for readable stuff.
2000  *
2001  *****************************************************************************/
2002 
2006 void free_all_readable(void) {
2007  titlelist *tlist, *tnext;
2008  title *title1, *titlenext;
2009  objectlink *monlink, *nextmon;
2010 
2011  LOG(llevDebug, "freeing all book information\n");
2012 
2013  for (tlist = booklist; tlist != NULL; tlist = tnext) {
2014  tnext = tlist->next;
2015  for (title1 = tlist->first_book; title1; title1 = titlenext) {
2016  titlenext = title1->next;
2017  if (title1->name)
2018  free_string(title1->name);
2019  if (title1->authour)
2020  free_string(title1->authour);
2021  if (title1->archname)
2022  free_string(title1->archname);
2023  free(title1);
2024  }
2025  free(tlist);
2026  }
2027  for (monlink = first_mon_info; monlink; monlink = nextmon) {
2028  nextmon = monlink->next;
2029  free(monlink);
2030  }
2031 }
2032 
2033 /*****************************************************************************
2034  *
2035  * Writeback routine for updating the bookarchive.
2036  *
2037  ****************************************************************************/
2038 
2043  FILE *fp;
2044  OutputFile of;
2045  int index;
2046  char fname[MAX_BUF];
2047  title *book;
2048  titlelist *bl;
2049 
2050  /* If nothing changed, don't write anything */
2052  return;
2053 
2054  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
2055  LOG(llevDebug, "Updating book archive: %s...\n", fname);
2056 
2057  fp = of_open(&of, fname);
2058  if (fp == NULL)
2059  return;
2060 
2061  for (bl = get_titlelist(0), index = 0; bl; bl = bl->next, index++) {
2062  for (book = bl->first_book; book; book = book->next)
2063  if (book && book->authour) {
2064  fprintf(fp, "title %s\n", book->name);
2065  fprintf(fp, "authour %s\n", book->authour);
2066  fprintf(fp, "arch %s\n", book->archname);
2067  fprintf(fp, "level %d\n", book->level);
2068  fprintf(fp, "type %d\n", index);
2069  /* C89 doesn't have %zu... */
2070  fprintf(fp, "size %lu\n", (unsigned long)book->size);
2071  fprintf(fp, "index %d\n", book->msg_index);
2072  fprintf(fp, "end\n");
2073  }
2074  }
2075  if (!of_close(&of))
2076  return;
2077 
2078  if (chmod(fname, SAVE_MODE) != 0) {
2079  LOG(llevError, "Could not set permissions on '%s'\n", fname);
2080  }
2081 
2083 }
2084 
2093  uint8_t subtype = readable->subtype;
2094 
2095  if (subtype > last_readable_subtype)
2096  return &readable_message_types[0];
2097  return &readable_message_types[subtype];
2098 }
2099 
2106  return message->title;
2107 }
2108 
2115  return message->message;
2116 }
2117 
2124  return message->face;
2125 }
PATH_TURNING
#define PATH_TURNING
Definition: spells.h:29
recipestruct::arch_names
size_t arch_names
Definition: recipe.h:12
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
prayers
int prayers
Definition: readable.c:1601
readable_message_types
static const readable_message_type readable_message_types[]
Definition: readable.c:470
need_to_write_bookarchive
static int need_to_write_bookarchive
Definition: readable.c:144
MSG_TYPE_BOOK_SPELL_PRAYER
#define MSG_TYPE_BOOK_SPELL_PRAYER
Definition: newclient.h:430
output_file.h
book_author
static const char *const book_author[]
Definition: readable.c:396
global.h
GOD_IMMUNITIES
#define GOD_IMMUNITIES
Definition: god.h:29
get_formulalist
recipelist * get_formulalist(int i)
Definition: recipe.c:96
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
GeneralMessage
Definition: book.h:44
spell_arrow.archetype
archetype
Definition: spell_arrow.py:11
init_book_archive
static void init_book_archive(void)
Definition: readable.c:728
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
SAVE_MODE
#define SAVE_MODE
Definition: config.h:555
PATH_LIGHT
#define PATH_LIGHT
Definition: spells.h:32
llevError
@ llevError
Definition: logger.h:11
GOD_PATHS
#define GOD_PATHS
Definition: god.h:30
PATH_RESTORE
#define PATH_RESTORE
Definition: spells.h:21
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
MSG_TYPE_BOOK_SPELL_SUMMONER
#define MSG_TYPE_BOOK_SPELL_SUMMONER
Definition: newclient.h:433
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
spellpathdef
static const uint32_t spellpathdef[NRSPELLPATHS]
Definition: readable.c:149
PATH_ELEC
#define PATH_ELEC
Definition: spells.h:16
formula_author
static const char *const formula_author[]
Definition: readable.c:341
artifactliststruct::total_chance
uint16_t total_chance
Definition: artifact.h:28
PATH_FIRE
#define PATH_FIRE
Definition: spells.h:14
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
get_empty_book
static title * get_empty_book(void)
Definition: readable.c:581
MSGTYPE_MONSTER
#define MSGTYPE_MONSTER
Definition: readable.c:80
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:313
namebytype
Definition: readable.c:127
MSGTYPE_SPELLPATH
#define MSGTYPE_SPELLPATH
Definition: readable.c:84
make_face_from_files.type
type
Definition: make_face_from_files.py:24
MSG_TYPE_PAPER
#define MSG_TYPE_PAPER
Definition: newclient.h:397
do_spellpath_msg
static void do_spellpath_msg(archetype *at)
Definition: readable.c:1609
object_new
object * object_new(void)
Definition: object.c:1236
MSG_TYPE_PAPER_LETTER_NEW_2
#define MSG_TYPE_PAPER_LETTER_NEW_2
Definition: newclient.h:456
add_author
static void add_author(object *op, int msgtype)
Definition: readable.c:1018
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
god_info_msg
static StringBuffer * god_info_msg(int level, size_t booksize, object *book)
Definition: readable.c:1854
titlestruct::msg_index
int msg_index
Definition: readable.c:113
sp_params
static struct @0 sp_params
gods_book_name
static const char *const gods_book_name[]
Definition: readable.c:294
MSGTYPE_ALCHEMY
#define MSGTYPE_ALCHEMY
Definition: readable.c:86
get_random_message
GeneralMessage * get_random_message()
Definition: assets.cpp:331
MSG_TYPE_PAPER_SCROLL_NEW_2
#define MSG_TYPE_PAPER_SCROLL_NEW_2
Definition: newclient.h:462
trim
const char * trim(const char *buf)
Definition: readable.c:656
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
python_event.path
path
Definition: python_event.py:11
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
commongive.inv
inv
Definition: commongive.py:28
MSG_TYPE_PAPER_LETTER_OLD_1
#define MSG_TYPE_PAPER_LETTER_OLD_1
Definition: newclient.h:453
MSG_TYPE_SIGN_DIR_RIGHT
#define MSG_TYPE_SIGN_DIR_RIGHT
Definition: newclient.h:468
recipestruct::title
sstring title
Definition: recipe.h:11
get_empty_booklist
static titlelist * get_empty_booklist(void)
Definition: readable.c:561
unique_book
static int unique_book(const object *book, int msgtype)
Definition: readable.c:1066
MSG_TYPE_CARD_SIMPLE_2
#define MSG_TYPE_CARD_SIMPLE_2
Definition: newclient.h:437
add_book_to_list
static void add_book_to_list(const object *book, int msgtype)
Definition: readable.c:1090
artifactliststruct::items
struct artifactstruct * items
Definition: artifact.h:30
formula_book_name
static const char *const formula_book_name[]
Definition: readable.c:327
Ice.tmp
int tmp
Definition: Ice.py:207
MSG_TYPE_BOOK_CLASP_2
#define MSG_TYPE_BOOK_CLASP_2
Definition: newclient.h:424
done
int done
Definition: readable.c:1607
add_book
static void add_book(title *book, int type, const char *fname, int lineno)
Definition: readable.c:846
MSG_TYPE_CARD
#define MSG_TYPE_CARD
Definition: newclient.h:396
MSG_TYPE_BOOK_ELEGANT_1
#define MSG_TYPE_BOOK_ELEGANT_1
Definition: newclient.h:425
describe_item
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Definition: item.c:940
pnum
uint32_t pnum
Definition: readable.c:1603
titlestruct::archname
const char * archname
Definition: readable.c:110
find_title
static title * find_title(const object *book, int msgtype)
Definition: readable.c:930
GOD_BLESSED
#define GOD_BLESSED
Definition: god.h:28
get_message_body
sstring get_message_body(const GeneralMessage *message)
Definition: readable.c:2114
mon_desc
static StringBuffer * mon_desc(const object *mon)
Definition: readable.c:1327
recipestruct::chance
int chance
Definition: recipe.h:14
booklist
static titlelist * booklist
Definition: readable.c:138
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
PATH_ABJURE
#define PATH_ABJURE
Definition: spells.h:20
find_artifactlist
const artifactlist * find_artifactlist(int type)
Definition: artifact.c:647
nstrtok
int nstrtok(const char *buf1, const char *buf2)
Definition: readable.c:637
GOD_HOLYWORD
#define GOD_HOLYWORD
Definition: god.h:25
art_name_array
static const arttypename art_name_array[]
Definition: readable.c:207
linked_char
Definition: global.h:86
artifact_msg
static StringBuffer * artifact_msg(unsigned int level, size_t booksize)
Definition: readable.c:1525
settings
struct Settings settings
Definition: init.c:39
MSG_TYPE_PAPER_SCROLL_OLD_1
#define MSG_TYPE_PAPER_SCROLL_OLD_1
Definition: newclient.h:459
init_readable
void init_readable(void)
Definition: readable.c:899
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4362
describe_god
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Definition: holy.c:136
MSG_TYPE_CARD_STRANGE_1
#define MSG_TYPE_CARD_STRANGE_1
Definition: newclient.h:442
free_string
void free_string(sstring str)
Definition: shstr.c:280
strtoint
int strtoint(const char *buf)
Definition: recipe.c:574
light_book_name
static const char *const light_book_name[]
Definition: readable.c:363
PATH_MISSILE
#define PATH_MISSILE
Definition: spells.h:17
recipestruct
Definition: recipe.h:10
titlestruct::level
unsigned int level
Definition: readable.c:111
get_next_mon
static object * get_next_mon(const object *tmp)
Definition: readable.c:1345
strtoktolin
char * strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size)
Definition: readable.c:679
artifact_describe
static StringBuffer * artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator)
Definition: readable.c:1430
artifactstruct::chance
uint16_t chance
Definition: artifact.h:16
titlestruct
Definition: readable.c:107
get_readable_message_type
const readable_message_type * get_readable_message_type(object *readable)
Definition: readable.c:2092
recipeliststruct::total_chance
int total_chance
Definition: recipe.h:38
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
get_titlelist
static titlelist * get_titlelist(int i)
Definition: readable.c:606
titleliststruct::first_book
struct titlestruct * first_book
Definition: readable.c:122
MSGTYPE_GODS
#define MSGTYPE_GODS
Definition: readable.c:88
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.c:1047
MSG_TYPE_CARD_STRANGE_2
#define MSG_TYPE_CARD_STRANGE_2
Definition: newclient.h:443
MSG_TYPE_SIGN_DIR_BOTH
#define MSG_TYPE_SIGN_DIR_BOTH
Definition: newclient.h:469
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:584
MSG_TYPE_MONUMENT_GRAVESTONE_2
#define MSG_TYPE_MONUMENT_GRAVESTONE_2
Definition: newclient.h:480
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.c:85
mon
object * mon
Definition: comet_perf.c:75
PATH_DETONATE
#define PATH_DETONATE
Definition: spells.h:22
of_close
int of_close(OutputFile *of)
Definition: output_file.c:61
MSG_TYPE_SIGN_DIR_LEFT
#define MSG_TYPE_SIGN_DIR_LEFT
Definition: newclient.h:467
titlelist
struct titleliststruct titlelist
artifactstruct::next
struct artifactstruct * next
Definition: artifact.h:18
MSG_TYPE_BOOK_CLASP_1
#define MSG_TYPE_BOOK_CLASP_1
Definition: newclient.h:423
recipestruct::cauldron
sstring cauldron
Definition: recipe.h:27
fatal
void fatal(enum fatal_error err)
Definition: utils.c:597
titlestruct::size
size_t size
Definition: readable.c:112
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:95
recipestruct::arch_name
char ** arch_name
Definition: recipe.h:13
namebytype::name
const char * name
Definition: readable.c:128
max_titles
static const int max_titles[6]
Definition: readable.c:537
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Definition: global.h:202
MSG_TYPE_MONUMENT_STATUE_2
#define MSG_TYPE_MONUMENT_STATUE_2
Definition: newclient.h:477
PATH_SUMMON
#define PATH_SUMMON
Definition: spells.h:19
MSG_TYPE_CARD_ELEGANT_1
#define MSG_TYPE_CARD_ELEGANT_1
Definition: newclient.h:439
path_book_name
static const char *const path_book_name[]
Definition: readable.c:173
artifactstruct::allowed_size
int allowed_size
Definition: artifact.h:20
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:301
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
book.h
buf_overflow
int buf_overflow(const char *buf1, const char *buf2, size_t bufsize)
Definition: shstr.c:398
do_monster
static void do_monster(archetype *at)
Definition: readable.c:860
artifactliststruct
Definition: artifact.h:26
nrofmon
static int nrofmon
Definition: readable.c:143
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4497
sstring
const typedef char * sstring
Definition: global.h:40
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
PATH_FROST
#define PATH_FROST
Definition: spells.h:15
MSG_TYPE_CARD_MONEY_3
#define MSG_TYPE_CARD_MONEY_3
Definition: newclient.h:447
mon_book_name
static const char *const mon_book_name[]
Definition: readable.c:257
last_readable_subtype
static const int last_readable_subtype
Definition: readable.c:534
MSG_TYPE_BOOK_SPELL_EVOKER
#define MSG_TYPE_BOOK_SPELL_EVOKER
Definition: newclient.h:429
MSG_TYPE_MONUMENT_GRAVESTONE_3
#define MSG_TYPE_MONUMENT_GRAVESTONE_3
Definition: newclient.h:481
recipeliststruct
Definition: recipe.h:37
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
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
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
MSG_TYPE_SIGN_MAGIC_MOUTH
#define MSG_TYPE_SIGN_MAGIC_MOUTH
Definition: newclient.h:470
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
recipestruct::ingred
linked_char * ingred
Definition: recipe.h:22
guild_entry.text
text
Definition: guild_entry.py:44
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:220
MAX_BUF
#define MAX_BUF
Definition: define.h:35
artifactstruct
Definition: artifact.h:14
arraysize
#define arraysize(arrayname)
Definition: readable.c:97
get_random_mon
object * get_random_mon(int level)
Definition: readable.c:1264
get_message_face
const Face * get_message_face(const GeneralMessage *message)
Definition: readable.c:2123
add_abilities
void add_abilities(object *op, const object *change)
Definition: artifact.c:285
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:281
title
struct titlestruct title
RANDOM
#define RANDOM()
Definition: define.h:642
titleliststruct::number
int number
Definition: readable.c:121
titlestruct::authour
const char * authour
Definition: readable.c:109
StringBuffer
Definition: stringbuffer.c:25
recipestruct::skill
sstring skill
Definition: recipe.h:26
make_formula_book
static void make_formula_book(object *book, int level)
Definition: readable.c:1683
PATH_DEATH
#define PATH_DEATH
Definition: spells.h:31
MSGTYPE_MSGFILE
#define MSGTYPE_MSGFILE
Definition: readable.c:90
GOD_RESISTANCES
#define GOD_RESISTANCES
Definition: god.h:26
book_descrpt
static const char *const book_descrpt[]
Definition: readable.c:443
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.c:4806
MSG_TYPE_CARD_MONEY_1
#define MSG_TYPE_CARD_MONEY_1
Definition: newclient.h:445
tailor_readable_ob
void tailor_readable_ob(object *book, int msg_type)
Definition: readable.c:1924
diamondslots.message
string message
Definition: diamondslots.py:57
write_book_archive
void write_book_archive(void)
Definition: readable.c:2042
PATH_TELE
#define PATH_TELE
Definition: spells.h:25
llevInfo
@ llevInfo
Definition: logger.h:12
Floor.t
t
Definition: Floor.py:62
titlestruct::next
struct titlestruct * next
Definition: readable.c:114
find_archetype_by_object_name
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.cpp:55
MSG_TYPE_PAPER_ENVELOPE_1
#define MSG_TYPE_PAPER_ENVELOPE_1
Definition: newclient.h:457
spells.h
spellpathnames
const char *const spellpathnames[NRSPELLPATHS]
Definition: init.c:106
mon_author
static const char *const mon_author[]
Definition: readable.c:275
MSG_TYPE_CARD_SIMPLE_3
#define MSG_TYPE_CARD_SIMPLE_3
Definition: newclient.h:438
PATH_PROT
#define PATH_PROT
Definition: spells.h:13
arttypename
struct namebytype arttypename
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
of_open
FILE * of_open(OutputFile *of, const char *fname)
Definition: output_file.c:30
MSG_TYPE_PAPER_LETTER_NEW_1
#define MSG_TYPE_PAPER_LETTER_NEW_1
Definition: newclient.h:455
give.op
op
Definition: give.py:33
booksize
size_t booksize
Definition: readable.c:1605
autojail.value
value
Definition: autojail.py:6
heavy_book_name
static const char *const heavy_book_name[]
Definition: readable.c:382
MSGTYPE_ARTIFACT
#define MSGTYPE_ARTIFACT
Definition: readable.c:82
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
change_book
static void change_book(object *book, int msgtype)
Definition: readable.c:1132
stringbuffer_length
size_t stringbuffer_length(StringBuffer *sb)
Definition: stringbuffer.c:162
init_mon_info
static void init_mon_info(void)
Definition: readable.c:881
GOD_ENEMY
#define GOD_ENEMY
Definition: god.h:24
msgfile_msg
static StringBuffer * msgfile_msg(object *book, size_t booksize)
Definition: readable.c:1811
PATH_MIND
#define PATH_MIND
Definition: spells.h:23
BOOK_BUF
#define BOOK_BUF
Definition: book.h:16
assets.h
MSGTYPE_LIB
#define MSGTYPE_LIB
Definition: readable.c:78
npc_dialog.index
int index
Definition: npc_dialog.py:102
buf
StringBuffer * buf
Definition: readable.c:1606
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:104
titlestruct::name
const char * name
Definition: readable.c:108
recipestruct::next
struct recipestruct * next
Definition: recipe.h:24
MSG_TYPE_MONUMENT_STONE_2
#define MSG_TYPE_MONUMENT_STONE_2
Definition: newclient.h:474
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2828
path_author
static const char *const path_author[]
Definition: readable.c:183
spellpath_msg
static StringBuffer * spellpath_msg(int level, size_t booksize, StringBuffer *buf)
Definition: readable.c:1643
get_rand_god
godlink * get_rand_god(void)
Definition: holy.c:100
titleliststruct
Definition: readable.c:120
readable_message_type
Definition: book.h:36
artifactstruct::item
object * item
Definition: artifact.h:15
make_face_from_files.int
int
Definition: make_face_from_files.py:26
MSG_TYPE_MONUMENT_STATUE_1
#define MSG_TYPE_MONUMENT_STATUE_1
Definition: newclient.h:476
MSG_TYPE_MONUMENT_WALL_1
#define MSG_TYPE_MONUMENT_WALL_1
Definition: newclient.h:482
recipestruct::is_combination
int is_combination
Definition: recipe.h:31
recipeliststruct::items
struct recipestruct * items
Definition: recipe.h:40
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.c:1541
namebytype::type
int type
Definition: readable.c:129
did_first_sp
int did_first_sp
Definition: readable.c:1602
recipestruct::index
int index
Definition: recipe.h:18
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
pntr_to_god_obj
const object * pntr_to_god_obj(godlink *godlnk)
Definition: holy.c:122
MSG_TYPE_CARD_SIMPLE_1
#define MSG_TYPE_CARD_SIMPLE_1
Definition: newclient.h:436
stringbuffer_append_stringbuffer
void stringbuffer_append_stringbuffer(StringBuffer *sb, const StringBuffer *sb2)
Definition: stringbuffer.c:131
level
int level
Definition: readable.c:1604
MSG_TYPE_MONUMENT_STONE_1
#define MSG_TYPE_MONUMENT_STONE_1
Definition: newclient.h:473
gods_author
static const char *const gods_author[]
Definition: readable.c:309
MSG_TYPE_SIGN
#define MSG_TYPE_SIGN
Definition: newclient.h:398
titleliststruct::next
struct titleliststruct * next
Definition: readable.c:123
MSG_TYPE_BOOK
#define MSG_TYPE_BOOK
Definition: newclient.h:395
MAX_TITLE_CHECK
#define MAX_TITLE_CHECK
Definition: readable.c:75
art_author
static const char *const art_author[]
Definition: readable.c:243
stringbuffer_delete
void stringbuffer_delete(StringBuffer *sb)
Definition: stringbuffer.c:71
book_overflow
int book_overflow(const char *buf1, const char *buf2, size_t booksize)
Definition: readable.c:709
MSG_TYPE_PAPER_SCROLL_MAGIC
#define MSG_TYPE_PAPER_SCROLL_MAGIC
Definition: newclient.h:463
FLAG_CHANGING
#define FLAG_CHANGING
Definition: define.h:263
MSG_TYPE_PAPER_SCROLL_NEW_1
#define MSG_TYPE_PAPER_SCROLL_NEW_1
Definition: newclient.h:461
guildbuy.temp
def temp
Definition: guildbuy.py:26
mon_info_msg
static StringBuffer * mon_info_msg(int level, size_t booksize, object *book)
Definition: readable.c:1373
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
BOOKSIZE
#define BOOKSIZE(xyz)
Definition: book.h:31
artifactliststruct::type
uint8_t type
Definition: artifact.h:27
living.h
new_text_name
static void new_text_name(object *book, int msgtype)
Definition: readable.c:969
MSG_TYPE_CARD_STRANGE_3
#define MSG_TYPE_CARD_STRANGE_3
Definition: newclient.h:444
free_all_readable
void free_all_readable(void)
Definition: readable.c:2006
llevDebug
@ llevDebug
Definition: logger.h:13
artifactstruct::allowed
linked_char * allowed
Definition: artifact.h:19
NRSPELLPATHS
#define NRSPELLPATHS
Definition: spells.h:40
GOD_SACRED
#define GOD_SACRED
Definition: god.h:27
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
give.name
name
Definition: give.py:27
get_message_title
sstring get_message_title(const GeneralMessage *message)
Definition: readable.c:2105
first_mon_info
static objectlink * first_mon_info
Definition: readable.c:141
OutputFile
Definition: output_file.h:41
art_book_name
static const char *const art_book_name[]
Definition: readable.c:227
level
Definition: level.py:1
Settings::localdir
const char * localdir
Definition: global.h:244