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 #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  objectlink *mon = (objectlink *)malloc(sizeof(objectlink));
869  if (!mon) {
870  LOG(llevError, "init_mon_info: malloc failed!\n");
871  abort();
872  }
873  mon->ob = &at->clone;
874  mon->id = nrofmon;
877  nrofmon++;
878  }
879 }
880 
885 static void init_mon_info(void) {
886  static int did_init_mon_info = 0;
887 
888  if (did_init_mon_info)
889  return;
890  did_init_mon_info = 1;
891 
893 
894  LOG(llevDebug, "init_mon_info() got %d monsters\n", nrofmon);
895 }
896 
903 void init_readable(void) {
904  static int did_this = 0;
905 
906  if (did_this)
907  return;
908  did_this = 1;
909 
910  LOG(llevDebug, "Initializing reading data...\n");
912  init_mon_info();
913  LOG(llevDebug, " done reading data\n");
914 }
915 
916 /*****************************************************************************
917  *
918  * This is the start of the administrative functions when creating
919  * new books (ie, updating title and the like)
920  *
921  *****************************************************************************/
922 
934 static title *find_title(const object *book, int msgtype) {
935  title *t;
936  titlelist *tl;
937  size_t length;
938  int index;
939 
940  if (msgtype < 0)
941  return (title *)NULL;
942 
943  tl = get_titlelist(msgtype);
944  if (!tl)
945  return (title *)NULL;
946 
947  length = strlen(book->msg);
948  index = strtoint(book->msg);
949  for (t = tl->first_book; t; t = t->next)
950  if (t->size == length && t->msg_index == index) {
951 #ifdef ARCHIVE_DEBUG
952  LOG(llevDebug, "Found title match (list %d): %s %s (%d)\n", msgtype, t->name, t->authour, t->msg_index);
953 #endif
954  return t;
955  }
956 
957  return (title *)NULL;
958 }
959 
973 static void new_text_name(object *book, int msgtype) {
974  const char *name;
975 
976  if (book->type != BOOK)
977  return;
978 
979  switch (msgtype) {
980  case MSGTYPE_MONSTER:
982  break;
983 
984  case MSGTYPE_ARTIFACT:
986  break;
987 
988  case MSGTYPE_SPELLPATH:
990  break;
991 
992  case MSGTYPE_ALCHEMY:
994  break;
995 
996  case MSGTYPE_GODS:
998  break;
999 
1000  case MSGTYPE_MSGFILE:
1001  default:
1002  if (book->weight > 2000) { /* based on weight */
1004  } else {
1006  }
1007  break;
1008  }
1009  free_string(book->name);
1010  book->name = add_string(name);
1011 }
1012 
1022 static void add_author(object *op, int msgtype) {
1023  char title[MAX_BUF];
1024  const char *name;
1025 
1026  if (msgtype < 0 || strlen(op->msg) < 5)
1027  return;
1028 
1029  switch (msgtype) {
1030  case MSGTYPE_MONSTER:
1032  break;
1033 
1034  case MSGTYPE_ARTIFACT:
1036  break;
1037 
1038  case MSGTYPE_SPELLPATH:
1040  break;
1041 
1042  case MSGTYPE_ALCHEMY:
1044  break;
1045 
1046  case MSGTYPE_GODS:
1048  break;
1049 
1050  case MSGTYPE_MSGFILE:
1051  default:
1053  }
1054 
1055  snprintf(title, sizeof(title), "of %s", name);
1056  op->title = add_string(title);
1057 }
1058 
1070 static int unique_book(const object *book, int msgtype) {
1071  title *test;
1072 
1073  if (!booklist)
1074  return 1; /* No archival entries! Must be unique! */
1075 
1076  /* Go through the booklist. If the author and name match, not unique so
1077  * return 0.
1078  */
1079  for (test = get_titlelist(msgtype)->first_book; test; test = test->next) {
1080  if (!strcmp(test->name, book->name) && !strcmp(book->title, test->authour))
1081  return 0;
1082  }
1083  return 1;
1084 }
1085 
1094 static void add_book_to_list(const object *book, int msgtype) {
1095  titlelist *tl = get_titlelist(msgtype);
1096  title *t;
1097 
1098  if (!tl) {
1099  LOG(llevError, "add_book_to_list can't get booklist!\n");
1100  return;
1101  }
1102 
1103  t = get_empty_book();
1104  t->name = add_string(book->name);
1105  t->authour = add_string(book->title);
1106  t->size = strlen(book->msg);
1107  t->msg_index = strtoint(book->msg);
1108  t->archname = add_string(book->arch->name);
1109  t->level = book->level;
1110 
1111  t->next = tl->first_book;
1112  tl->first_book = t;
1113  tl->number++;
1114 
1115  /* We have stuff we need to write now */
1117 
1118 #ifdef ARCHIVE_DEBUG
1119  LOG(llevDebug, "Archiving new title: %s %s (%d)\n", book->name, book->title, msgtype);
1120 #endif
1121 }
1122 
1136 static void change_book(object *book, int msgtype) {
1137  titlelist *tl;
1138  title *t;
1139  int tries;
1140 
1141  if (book->type != BOOK) {
1142  LOG(llevError, "change_book_name() called w/ illegal obj type.\n");
1143  return;
1144  }
1145 
1146  tl = get_titlelist(msgtype);
1147  t = NULL;
1148  tries = 0;
1149 
1150  /* look to see if our msg already been archived. If so, alter
1151  * the book to match the archival text. If we fail to match,
1152  * then we archive the new title/name/msg combo if there is
1153  * room on the titlelist.
1154  */
1155 
1156  if (strlen(book->msg) > 5 && (t = find_title(book, msgtype))) {
1157  object *tmpbook;
1158  sstring marker = object_get_value(book, "knowledge_marker");
1159 
1160  /* alter book properties */
1161  tmpbook = create_archetype(t->archname);
1162  if (marker != NULL)
1163  /* need to copy the knowledge_marker */
1164  object_set_value(tmpbook, "knowledge_marker", marker, 1);
1165  object_set_msg(tmpbook, book->msg);
1166  object_copy(tmpbook, book);
1167  object_free_drop_inventory(tmpbook);
1168 
1169  book->title = add_string(t->authour);
1170  free_string(book->name);
1171  book->name = add_string(t->name);
1172  book->level = t->level;
1173  } else { /* Don't have any default title, so lets make up a new one */
1174  int numb, maxnames = max_titles[msgtype];
1175  const char *old_title;
1176  const char *old_name;
1177 
1178  old_title = book->title ? add_string(book->title) : NULL;
1179  old_name = add_string(book->name);
1180 
1181  /* some pre-generated books have title already set (from
1182  * maps), also don't bother looking for unique title if
1183  * we already used up all the available names! */
1184 
1185  if (!tl) {
1186  LOG(llevError, "change_book_name(): can't find title list\n");
1187  numb = 0;
1188  } else
1189  numb = tl->number;
1190 
1191  if (numb == maxnames) {
1192 #ifdef ARCHIVE_DEBUG
1193  LOG(llevDebug, "titles for list %d full (%d possible).\n", msgtype, maxnames);
1194 #endif
1195  if (old_title != NULL)
1196  free_string(old_title);
1197  free_string(old_name);
1198  return;
1199  }
1200  /* shouldnt change map-maker books */
1201  if (!book->title)
1202  do {
1203  /* random book name */
1204  new_text_name(book, msgtype);
1205  add_author(book, msgtype); /* random author */
1206  tries++;
1207  } while (!unique_book(book, msgtype) && tries < MAX_TITLE_CHECK);
1208 
1209  /* Now deal with 2 cases.
1210  * 1) If no space for a new title exists lets just restore
1211  * the old book properties. Remember, if the book had
1212  * matchd an older entry on the titlelist, we shouldnt
1213  * have called this routine in the first place!
1214  * 2) If we got a unique title, we need to add it to
1215  * the list.
1216  */
1217 
1218  if (tries == MAX_TITLE_CHECK) {
1219 #ifdef ARCHIVE_DEBUG
1220  LOG(llevDebug, "Failed to obtain unique title for %s %s (names:%d/%d)\n", book->name, book->title, numb, maxnames);
1221 #endif
1222  /* restore old book properties here */
1223  free_string(book->name);
1224  free_string(book->title);
1225  book->title = old_title != NULL ? add_string(old_title) : NULL;
1226 
1227  if (RANDOM()%4) {
1228  /* Lets give the book a description to individualize it some */
1229  char new_name[MAX_BUF];
1230 
1231  snprintf(new_name, MAX_BUF, "%s %s", book_descrpt[RANDOM()%arraysize(book_descrpt)], old_name);
1232  book->name = add_string(new_name);
1233  } else {
1234  book->name = add_string(old_name);
1235  }
1236  } else if (book->title && strlen(book->msg) > 5) { /* archive if long msg texts */
1237  add_book_to_list(book, msgtype);
1238  }
1239 
1240  if (old_title != NULL)
1241  free_string(old_title);
1242  free_string(old_name);
1243  }
1244 }
1245 
1246 /*****************************************************************************
1247  *
1248  * This is the start of the area that generates the actual contents
1249  * of the book.
1250  *
1251  *****************************************************************************/
1252 
1253 /*****************************************************************************
1254  * Monster msg generation code.
1255  ****************************************************************************/
1256 
1268 object *get_random_mon(int level) {
1269  objectlink *mon;
1270  int i, monnr;
1271 
1272  /* safety check. Problem w/ init_mon_info list? */
1273  if (!nrofmon || !first_mon_info)
1274  return (object *)NULL;
1275 
1276  if (!level) {
1277  /* lets get a random monster from the mon_info linked list */
1278  monnr = RANDOM()%nrofmon;
1279 
1280  for (mon = first_mon_info, i = 0; mon; mon = mon->next, i++)
1281  if (i == monnr)
1282  break;
1283 
1284  if (!mon) {
1285  LOG(llevError, "get_random_mon: Didn't find a monster when we should have\n");
1286  return NULL;
1287  }
1288  return mon->ob;
1289  }
1290 
1291  /* Case where we are searching by level. Redone 971225 to be clearer
1292  * and more random. Before, it looks like it took a random monster from
1293  * the list, and then returned the first monster after that which was
1294  * appropriate level. This wasn't very random because if you had a
1295  * bunch of low level monsters and then a high level one, if the random
1296  * determine took one of the low level ones, it would just forward to the
1297  * high level one and return that. Thus, monsters that immediately followed
1298  * a bunch of low level monsters would be more heavily returned. It also
1299  * means some of the dragons would be poorly represented, since they
1300  * are a group of high level monsters all around each other.
1301  */
1302 
1303  /* First count number of monsters meeting level criteria */
1304  for (mon = first_mon_info, i = 0; mon; mon = mon->next)
1305  if (mon->ob->level >= level)
1306  i++;
1307 
1308  if (i == 0) {
1309  LOG(llevError, "get_random_mon() couldn't return monster for level %d\n", level);
1310  return NULL;
1311  }
1312 
1313  monnr = RANDOM()%i;
1314  for (mon = first_mon_info; mon; mon = mon->next)
1315  if (mon->ob->level >= level && monnr-- == 0)
1316  return mon->ob;
1317 
1318  LOG(llevError, "get_random_mon(): didn't find a monster when we should have\n");
1319  return NULL;
1320 }
1321 
1331 static StringBuffer *mon_desc(const object *mon) {
1332  StringBuffer *desc = stringbuffer_new();
1333  stringbuffer_append_printf(desc, "\n---\n *** %s ***\n", mon->name);
1334  describe_item(mon, NULL, 0, desc);
1335  return desc;
1336 }
1337 
1349 static object *get_next_mon(const object *tmp) {
1350  objectlink *mon;
1351 
1352  for (mon = first_mon_info; mon; mon = mon->next)
1353  if (mon->ob == tmp)
1354  break;
1355 
1356  /* didn't find a match */
1357  if (!mon)
1358  return NULL;
1359  if (mon->next)
1360  return mon->next->ob;
1361  else
1362  return first_mon_info->ob;
1363 }
1364 
1377 static StringBuffer *mon_info_msg(int level, size_t booksize, object *book) {
1378  object *tmp;
1379  StringBuffer *marker = stringbuffer_new(), *desc = stringbuffer_new(), *mon = NULL;
1380  int added = 0;
1381  sstring final;
1382  const char *sep = ":";
1383 
1384  /*preamble */
1385  stringbuffer_append_string(desc, "This beastiary contains:");
1386  stringbuffer_append_string(marker, "monster");
1387 
1388  /* lets print info on as many monsters as will fit in our
1389  * document.
1390  * 8-96 Had to change this a bit, otherwise there would
1391  * have been an impossibly large number of combinations
1392  * of text! (and flood out the available number of titles
1393  * in the archive in a snap!) -b.t.
1394  */
1395  for (tmp = get_random_mon(level*3); tmp; tmp = get_next_mon(tmp)) {
1396  /* monster description */
1397  mon = mon_desc(tmp);
1398 
1400  break;
1401  added++;
1402  stringbuffer_append_printf(marker, "%s%s", sep, tmp->arch->name);
1403  sep = "/";
1406  mon = NULL;
1407  }
1408 
1409  if (mon != NULL) {
1411  }
1412 
1413  final = stringbuffer_finish_shared(marker);
1414  if (added)
1415  object_set_value(book, "knowledge_marker", final, 1);
1416  free_string(final);
1417 
1418  return desc;
1419 }
1420 
1421 /*****************************************************************************
1422  * Artifact msg generation code.
1423  ****************************************************************************/
1424 
1434 static StringBuffer *artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator) {
1435  object *tmp;
1436  int chance;
1437  StringBuffer *desc = stringbuffer_new(), *sbuf;
1438 
1439  if (separator)
1440  stringbuffer_append_string(desc, "---\n");
1441 
1442  /* Name */
1443  if (art->allowed != NULL) {
1444  archetype *arch;
1445  linked_char *temp = art->allowed;
1446  int inv = 0, w;
1447 
1448  assert(art->allowed_size > 0);
1449  if (art->allowed_size > 1)
1450  w = 1 + RANDOM() % art->allowed_size;
1451  else
1452  w = 1;
1453 
1454  while (w > 1) {
1455  assert(temp);
1456  temp = temp->next;
1457  w--;
1458  }
1459 
1460  if (temp->name[0] == '!')
1461  inv = 1;
1462 
1464  arch = try_find_archetype(temp->name + inv);
1465  if (!arch)
1467 
1468  if (!arch)
1469  LOG(llevError, "artifact_msg: missing archetype %s for artifact %s (type %d)\n", temp->name + inv, art->item->name, art->item->type);
1470  else {
1471  if (inv)
1472  stringbuffer_append_printf(desc, " A %s (excepted %s) of %s", art_name_array[art_name].name, arch->clone.name_pl, art->item->name);
1473  else
1474  stringbuffer_append_printf(desc, " A %s of %s", arch->clone.name, art->item->name);
1475  }
1476  } else { /* default name is used */
1477  /* use the base 'generic' name for our artifact */
1478  stringbuffer_append_printf(desc, " The %s of %s", art_name_array[art_name].name, art->item->name);
1479  }
1480 
1481  /* chance of finding */
1482  stringbuffer_append_string(desc, " is ");
1483  chance = 100*((float)art->chance/al->total_chance);
1484  if (chance >= 20)
1485  stringbuffer_append_string(desc, "an uncommon");
1486  else if (chance >= 10)
1487  stringbuffer_append_string(desc, "an unusual");
1488  else if (chance >= 5)
1489  stringbuffer_append_string(desc, "a rare");
1490  else
1491  stringbuffer_append_string(desc, "a very rare");
1492 
1493  /* value of artifact */
1494  stringbuffer_append_printf(desc, " item with a value that is %d times normal.\n", art->item->value);
1495 
1496  /* include the message about the artifact, if exists, and book
1497  * level is kinda high */
1498  if (message && !(strlen(art->item->msg) > BOOK_BUF))
1499  stringbuffer_append_string(desc, art->item->msg);
1500 
1501  /* properties of the artifact */
1502  tmp = object_new();
1503  add_abilities(tmp, art->item);
1504  tmp->type = al->type;
1506  sbuf = describe_item(tmp, NULL, 0, NULL);
1507  if (stringbuffer_length(sbuf) > 1) {
1508  stringbuffer_append_string(desc, " Properties of this artifact include:\n ");
1510  stringbuffer_append_string(desc, "\n");
1511  }
1512  free(stringbuffer_finish(sbuf));
1514 
1515  return desc;
1516 }
1517 
1529 static StringBuffer *artifact_msg(unsigned int level, size_t booksize) {
1530  const artifactlist *al;
1531  const artifact *art;
1532  int i, type, index;
1533  int book_entries = level > 5 ? RANDOM()%3+RANDOM()%3+2 : RANDOM()%level+1;
1535 
1536  /* values greater than 5 create msg buffers that are too big! */
1537  if (book_entries > 5)
1538  book_entries = 5;
1539 
1540  /* lets determine what kind of artifact type randomly.
1541  * Right now legal artifacts only come from those listed
1542  * in art_name_array. Also, we check to be sure an artifactlist
1543  * for that type exists!
1544  */
1545  i = 0;
1546  do {
1549  al = find_artifactlist(type);
1550  i++;
1551  } while (al == NULL && i < 10);
1552 
1553  if (i == 10) { /* Unable to find a message */
1555  return message;
1556  }
1557 
1558  /* There is no reason to start on the artifact list at the beginning. Lets
1559  * take our starting position randomly... */
1560  art = al->items;
1561  for (i = RANDOM()%level+RANDOM()%2+1; i > 0; i--) {
1562  if (art == NULL)
1563  art = al->items; /* hmm, out of stuff, loop back around */
1564  art = art->next;
1565  }
1566 
1567  /* Ok, lets print out the contents */
1568  stringbuffer_append_printf(message, "Herein %s detailed %s...\n", book_entries > 1 ? "are" : "is", book_entries > 1 ? "some artifacts" : "an artifact");
1569 
1570  i = 0;
1571  /* artifact msg attributes loop. Lets keep adding entries to the 'book'
1572  * as long as we have space up to the allowed max # (book_entires)
1573  */
1574  while (book_entries > 0) {
1575  int with_message;
1576  if (art == NULL)
1577  art = al->items;
1578  with_message = (art->item->msg && RANDOM()%4+1 < level) ? 1 : 0;
1579 
1580  desc = artifact_describe(art, al, with_message, index, i++);
1581 
1583  stringbuffer_delete(desc);
1584  break;
1585  }
1586 
1588  stringbuffer_delete(desc);
1589 
1590  art = art->next;
1591  book_entries--;
1592  }
1593 
1594  return message;
1595 }
1596 
1597 /*****************************************************************************
1598  * Spellpath message generation
1599  *****************************************************************************/
1600 
1602 static struct {
1603  int prayers;
1604  int did_first_sp;
1605  uint32_t pnum;
1606  int level;
1607  size_t booksize;
1609  int done;
1613 static void do_spellpath_msg(archetype *at) {
1614  /* Determine if this is an appropriate spell. Must
1615  * be of matching path, must be of appropriate type (prayer
1616  * or not), and must be within the valid level range.
1617  */
1618  if (at->clone.type == SPELL
1619  && at->clone.path_attuned & sp_params.pnum
1620  && ((at->clone.stats.grace && sp_params.prayers) || (at->clone.stats.sp && !sp_params.prayers))
1621  && at->clone.level < sp_params.level*8) {
1622  if (strlen(at->clone.name) + stringbuffer_length(sp_params.buf) >= sp_params.booksize) {
1623  sp_params.done = 1;
1624  return;
1625  }
1626 
1627  if (sp_params.did_first_sp)
1629  sp_params.did_first_sp = 1;
1631  }
1632 }
1633 
1648  int path = RANDOM()%NRSPELLPATHS;
1649  sp_params.prayers = RANDOM()%2;
1650  sp_params.did_first_sp = 0;
1651  sp_params.pnum = spellpathdef[path];
1652  sp_params.done = 0;
1653 
1654  if (buf == NULL) {
1655  buf = stringbuffer_new();
1656  /* Preamble */
1657  stringbuffer_append_printf(buf, "Herein are detailed the names of %s", sp_params.prayers ? "prayers" : "incantations");
1658  stringbuffer_append_printf(buf, " belonging to the path of %s:\n ", spellpathnames[path]);
1659  }
1660  sp_params.level = level;
1661  sp_params.booksize = booksize;
1662  sp_params.buf = buf;
1663 
1665 
1666  /* Geez, no spells were generated. */
1667  if (!sp_params.did_first_sp) {
1668  if (RANDOM()%4) { /* usually, lets make a recursive call... */
1669  // If we do a recursive call, we reset the spell path, so we will want to reset our text as well.
1671  return spellpath_msg(level, booksize, NULL);
1672  }
1673  /* give up, cause knowing no spells exist for path is info too. need the header too. */
1674  stringbuffer_append_string(buf, "- no known spells exist -\n");
1675  }
1676  return buf;
1677 }
1678 
1687 static void make_formula_book(object *book, int level) {
1688  recipelist *fl;
1689  recipe *formula;
1690  int chance, count = 0;
1691  const char *op_name;
1692  archetype *at;
1693  StringBuffer *text, *title;
1694  char *final, km[MAX_BUF];
1695 
1696  /* the higher the book level, the more complex (ie number of
1697  * ingredients) the formula can be.
1698  */
1699  fl = get_formulalist((RANDOM()%level)/3+1);
1700  if (!fl)
1701  fl = get_formulalist(1); /* safety */
1702 
1703  if (fl->total_chance == 0) {
1704  object_set_msg(book, " <indecipherable text>\n");
1706  add_author(book, MSGTYPE_ALCHEMY);
1707  return;
1708  }
1709 
1710  /* get a random formula, weighted by its bookchance */
1711  chance = RANDOM()%fl->total_chance;
1712  for (formula = fl->items; formula != NULL; formula = formula->next) {
1713  chance -= formula->chance;
1714  if (chance <= 0 && formula->chance != 0 && !formula->is_combination)
1715  break;
1716  }
1717 
1718  if (!formula || formula->arch_names <= 0) {
1719  object_set_msg(book, " <indecipherable text>\n");
1721  add_author(book, MSGTYPE_ALCHEMY);
1722  return;
1723  }
1724 
1725  /* looks like a formula was found. Base the amount
1726  * of information on the booklevel and the spellevel
1727  * of the formula. */
1728 
1729  op_name = formula->arch_name[RANDOM()%formula->arch_names];
1730  at = find_archetype(op_name);
1731  if (at == (archetype *)NULL) {
1732  LOG(llevError, "formula_msg() can't find arch %s for formula.\n", op_name);
1733  object_set_msg(book, " <indecipherable text>\n");
1735  add_author(book, MSGTYPE_ALCHEMY);
1736  return;
1737  }
1738  op_name = at->clone.name;
1739 
1740  text = stringbuffer_new();
1741  title = stringbuffer_new();
1742 
1743  /* preamble */
1744  stringbuffer_append_printf(text, "Herein is described a project using %s:\n", formula->skill ? formula->skill : "an unknown skill");
1745 
1746  /* item name */
1747  if (strcmp(formula->title, "NONE")) {
1748  stringbuffer_append_printf(text, "The %s of %s", op_name, formula->title);
1749  /* This results in things like pile of philo. sulfur.
1750  * while philo. sulfur may look better, without this,
1751  * you get things like 'the wise' because its missing the
1752  * water of section.
1753  */
1755  } else {
1756  stringbuffer_append_printf(text, "The %s", op_name);
1758  if (at->clone.title) {
1761  }
1762  }
1763  /* Lets name the book something meaningful ! */
1764  if (book->name)
1765  free_string(book->name);
1767  if (book->title) {
1768  free_string(book->title);
1769  book->title = NULL;
1770  }
1771 
1772  /* ingredients to make it */
1773  if (formula->ingred != NULL) {
1774  linked_char *next;
1775  archetype *at;
1776  char name[MAX_BUF];
1777 
1778  at = find_archetype(formula->cauldron);
1779  if (at)
1780  query_name(&at->clone, name, MAX_BUF);
1781  else
1782  snprintf(name, sizeof(name), "an unknown place");
1783 
1784  stringbuffer_append_printf(text, " may be made at %s using the following ingredients:\n", name);
1785 
1786  for (next = formula->ingred; next != NULL; next = next->next) {
1787  count++;
1788  stringbuffer_append_printf(text, "%s\n", next->name);
1789  }
1790  } else {
1791  LOG(llevError, "formula_msg() no ingredient list for object %s of %s\n", op_name, formula->title);
1793  }
1794 
1795  final = stringbuffer_finish(text);
1796  object_set_msg(book, final);
1797  free(final);
1798 
1801  snprintf(km, sizeof(km), "alchemy:%d:%d:%s", count, formula->index, formula->title);
1802  object_set_value(book, "knowledge_marker", km, 1);
1803 }
1804 
1815 static StringBuffer *msgfile_msg(object *book, size_t booksize) {
1816  StringBuffer *ret = stringbuffer_new();
1817 
1819 
1820  if (msg && strlen(msg->message) <= booksize) {
1821  stringbuffer_append_string(ret, msg->message);
1822  if (msg->identifier != NULL) {
1823  char km[HUGE_BUF];
1826  snprintf(km, sizeof(km), "message:%s", msg->identifier);
1827  object_set_value(book, "knowledge_marker", km, 1);
1828  }
1829  if (msg->quest_code) {
1830  /* add a 'apply' hook to launch the quest */
1831  archetype *at = find_archetype("quest_advance_apply");
1832  if (at != NULL) {
1833  object *event = object_create_arch(at);
1834  FREE_AND_COPY(event->name, msg->quest_code);
1835  object_insert_in_ob(event, book);
1836  }
1837  }
1838  } else
1839  stringbuffer_append_string(ret, "\n <undecipherable text>");
1840 
1841  return ret;
1842 }
1843 
1858 static StringBuffer *god_info_msg(int level, size_t booksize, object *book) {
1859  int what = 0;
1860  const object *god = get_rand_god();
1861  StringBuffer *desc = NULL;
1862 
1863  if (!god)
1864  return NULL; /* oops, problems... */
1865 
1866  if (booksize > BOOK_BUF) {
1867  LOG(llevError, "common/readable.c:god_info_msg() - passed in booksize (%lu) is larger than book buffer (%d)\n", (unsigned long)booksize, BOOK_BUF);
1868  booksize = BOOK_BUF;
1869  }
1870 
1871  if (level >= 2 && RANDOM()%2) {
1872  what |= GOD_ENEMY;
1873  }
1874  if (level >= 3 && RANDOM()%2) {
1875  what |= GOD_HOLYWORD;
1876  }
1877  if (level >= 4 && RANDOM()%2) {
1878  what |= GOD_RESISTANCES;
1879  }
1880  if (level >= 5 && RANDOM()%2) {
1881  what |= GOD_SACRED;
1882  }
1883  if (level >= 6 && RANDOM()%2) {
1884  what |= GOD_BLESSED;
1885  }
1886  if (level >= 8 && RANDOM()%2) {
1887  what |= GOD_IMMUNITIES;
1888  }
1889  if (level >= 12 && RANDOM()%2) {
1890  what |= GOD_PATHS;
1891  }
1892 
1893  desc = stringbuffer_new();
1894  what = describe_god(god, what, desc, booksize);
1895 
1896  /* check to be sure new buffer size dont exceed either
1897  * the maximum buffer size, or the 'natural' size of the
1898  * book... */
1899  if (stringbuffer_length(desc) > 1 && stringbuffer_length(desc) <= booksize) {
1900  char buf[BOOK_BUF];
1901  snprintf(buf, sizeof(buf), "god:%s:%d", god->name, what);
1902  object_set_value(book, "knowledge_marker", buf, 1);
1903  return desc;
1904  }
1905 
1906  stringbuffer_delete(desc);
1907  return NULL;
1908 }
1909 
1928 void tailor_readable_ob(object *book, int msg_type) {
1929  int level = book->level ? RANDOM()%book->level+1 : 1;
1930  size_t book_buf_size;
1931  StringBuffer *message = NULL;
1932 
1933  /* safety */
1934  if (book->type != BOOK)
1935  return;
1936 
1937  if (level <= 0)
1938  return; /* if no level no point in doing any more... */
1939 
1940  /* Max text length this book can have. */
1941  book_buf_size = BOOKSIZE(book);
1942  book_buf_size -= strlen("\n"); /* Keep enough for final \n. */
1943  assert(book_buf_size < BOOK_BUF);
1944 
1945  /* &&& The message switch &&& */
1946  /* Below all of the possible types of messages in the "book"s.
1947  */
1948  /*
1949  * IF you add a new type of book msg, you will have to do several things.
1950  * 1) make sure there is an entry in the msg switch below!
1951  * 2) make sure there is an entry in max_titles[] array.
1952  * 3) make sure there are entries for your case in new_text_title()
1953  * and add_authour().
1954  * 4) you may want separate authour/book name arrays in read.h
1955  */
1956 
1957  if (msg_type >= (int)arraysize(max_titles))
1958  msg_type = 0;
1959 
1960  msg_type = msg_type > 0 ? msg_type : (int)(RANDOM()%6);
1961  switch (msg_type) {
1962  case MSGTYPE_MONSTER:
1963  message = mon_info_msg(level, book_buf_size, book);
1964  break;
1965 
1966  case MSGTYPE_ARTIFACT:
1967  message = artifact_msg(level, book_buf_size);
1968  break;
1969 
1970  case MSGTYPE_SPELLPATH: /* grouping incantations/prayers by path */
1971  message = spellpath_msg(level, book_buf_size, NULL);
1972  break;
1973 
1974  case MSGTYPE_ALCHEMY: /* describe an alchemy formula */
1975  make_formula_book(book, level);
1976  /* make_formula_book already gives title */
1977  return;
1978  break;
1979 
1980  case MSGTYPE_GODS: /* bits of information about a god */
1981  message = god_info_msg(level, book_buf_size, book);
1982  break;
1983 
1984  case MSGTYPE_LIB: /* use info list in lib/ */
1985  default:
1986  message = msgfile_msg(book, book_buf_size);
1987  break;
1988  }
1989 
1990  if (message != NULL) {
1991  char *final;
1993  final = stringbuffer_finish(message);
1994  object_set_msg(book, final);
1995  free(final);
1996  /* lets give the "book" a new name, which may be a compound word */
1997  change_book(book, msg_type);
1998  }
1999 }
2000 
2001 /*****************************************************************************
2002  *
2003  * Cleanup routine for readable stuff.
2004  *
2005  *****************************************************************************/
2006 
2010 void free_all_readable(void) {
2011  titlelist *tlist, *tnext;
2012  title *title1, *titlenext;
2013  objectlink *monlink, *nextmon;
2014 
2015  LOG(llevDebug, "freeing all book information\n");
2016 
2017  for (tlist = booklist; tlist != NULL; tlist = tnext) {
2018  tnext = tlist->next;
2019  for (title1 = tlist->first_book; title1; title1 = titlenext) {
2020  titlenext = title1->next;
2021  if (title1->name)
2022  free_string(title1->name);
2023  if (title1->authour)
2024  free_string(title1->authour);
2025  if (title1->archname)
2026  free_string(title1->archname);
2027  free(title1);
2028  }
2029  free(tlist);
2030  }
2031  for (monlink = first_mon_info; monlink; monlink = nextmon) {
2032  nextmon = monlink->next;
2033  free(monlink);
2034  }
2035 }
2036 
2037 /*****************************************************************************
2038  *
2039  * Writeback routine for updating the bookarchive.
2040  *
2041  ****************************************************************************/
2042 
2047  FILE *fp;
2048  OutputFile of;
2049  int index;
2050  char fname[MAX_BUF];
2051  title *book;
2052  titlelist *bl;
2053 
2054  /* If nothing changed, don't write anything */
2056  return;
2057 
2058  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
2059  LOG(llevDebug, "Updating book archive: %s...\n", fname);
2060 
2061  fp = of_open(&of, fname);
2062  if (fp == NULL)
2063  return;
2064 
2065  for (bl = get_titlelist(0), index = 0; bl; bl = bl->next, index++) {
2066  for (book = bl->first_book; book; book = book->next)
2067  if (book && book->authour) {
2068  fprintf(fp, "title %s\n", book->name);
2069  fprintf(fp, "authour %s\n", book->authour);
2070  fprintf(fp, "arch %s\n", book->archname);
2071  fprintf(fp, "level %d\n", book->level);
2072  fprintf(fp, "type %d\n", index);
2073  /* C89 doesn't have %zu... */
2074  fprintf(fp, "size %lu\n", (unsigned long)book->size);
2075  fprintf(fp, "index %d\n", book->msg_index);
2076  fprintf(fp, "end\n");
2077  }
2078  }
2079  if (!of_close(&of))
2080  return;
2081 
2082  if (chmod(fname, SAVE_MODE) != 0) {
2083  LOG(llevError, "Could not set permissions on '%s'\n", fname);
2084  }
2085 
2087 }
2088 
2097  uint8_t subtype = readable->subtype;
2098 
2099  if (subtype > last_readable_subtype)
2100  return &readable_message_types[0];
2101  return &readable_message_types[subtype];
2102 }
2103 
2110  return message->title;
2111 }
2112 
2119  return message->message;
2120 }
2121 
2128  return message->face;
2129 }
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:1605
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:18
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
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
BOW
@ BOW
Definition: object.h:118
BRACERS
@ BRACERS
Definition: object.h:217
PATH_LIGHT
#define PATH_LIGHT
Definition: spells.h:32
archt::head
struct archt * head
Definition: object.h:471
llevError
@ llevError
Definition: logger.h:11
GOD_PATHS
#define GOD_PATHS
Definition: god.h:19
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
MONSTER_EXCLUDE_FROM_READABLE_KEY
#define MONSTER_EXCLUDE_FROM_READABLE_KEY
Definition: object.h:582
spellpathdef
static const uint32_t spellpathdef[NRSPELLPATHS]
Definition: readable.c:149
PATH_ELEC
#define PATH_ELEC
Definition: spells.h:16
GLOVES
@ GLOVES
Definition: object.h:213
formula_author
static const char *const formula_author[]
Definition: readable.c:341
GIRDLE
@ GIRDLE
Definition: object.h:223
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:331
obj::value
int32_t value
Definition: object.h:355
namebytype
Definition: readable.c:127
MSGTYPE_SPELLPATH
#define MSGTYPE_SPELLPATH
Definition: readable.c:84
MSG_TYPE_PAPER
#define MSG_TYPE_PAPER
Definition: newclient.h:397
do_spellpath_msg
static void do_spellpath_msg(archetype *at)
Definition: readable.c:1613
object_new
object * object_new(void)
Definition: object.c:1255
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:1022
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
obj::path_attuned
uint32_t path_attuned
Definition: object.h:348
god_info_msg
static StringBuffer * god_info_msg(int level, size_t booksize, object *book)
Definition: readable.c:1858
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
ARMOUR
@ ARMOUR
Definition: object.h:120
get_random_message
GeneralMessage * get_random_message()
Definition: assets.cpp:349
MSG_TYPE_PAPER_SCROLL_NEW_2
#define MSG_TYPE_PAPER_SCROLL_NEW_2
Definition: newclient.h:462
WEAPON
@ WEAPON
Definition: object.h:119
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
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
AMULET
@ AMULET
Definition: object.h:139
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:1070
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:1094
SKILL
@ SKILL
Definition: object.h:143
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:1611
add_book
static void add_book(title *book, int type, const char *fname, int lineno)
Definition: readable.c:850
MSG_TYPE_CARD
#define MSG_TYPE_CARD
Definition: newclient.h:396
obj::msg
sstring msg
Definition: object.h:325
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:941
pnum
uint32_t pnum
Definition: readable.c:1607
titlestruct::archname
const char * archname
Definition: readable.c:110
find_title
static title * find_title(const object *book, int msgtype)
Definition: readable.c:934
GOD_BLESSED
#define GOD_BLESSED
Definition: god.h:17
get_message_body
sstring get_message_body(const GeneralMessage *message)
Definition: readable.c:2118
mon_desc
static StringBuffer * mon_desc(const object *mon)
Definition: readable.c:1331
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
nstrtok
int nstrtok(const char *buf1, const char *buf2)
Definition: readable.c:637
GOD_HOLYWORD
#define GOD_HOLYWORD
Definition: god.h:14
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:1529
archt
Definition: object.h:469
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:903
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4317
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:583
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:1349
CLOAK
@ CLOAK
Definition: object.h:204
strtoktolin
char * strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size)
Definition: readable.c:679
HELMET
@ HELMET
Definition: object.h:136
artifact_describe
static StringBuffer * artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator)
Definition: readable.c:1434
artifactstruct::chance
uint16_t chance
Definition: artifact.h:16
get_rand_god
const object * get_rand_god(void)
Definition: holy.cpp:77
titlestruct
Definition: readable.c:107
oblnk::next
struct oblnk * next
Definition: object.h:448
get_readable_message_type
const readable_message_type * get_readable_message_type(object *readable)
Definition: readable.c:2096
recipeliststruct::total_chance
int total_chance
Definition: recipe.h:38
obj::name
sstring name
Definition: object.h:314
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
find_artifactlist
artifactlist * find_artifactlist(int type)
Definition: artifact.c:575
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:1064
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:585
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:580
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
ROD
@ ROD
Definition: object.h:109
recipestruct::arch_name
char ** arch_name
Definition: recipe.h:13
python_init.path
path
Definition: python_init.py:8
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:201
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:864
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:4470
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
ARROW
@ ARROW
Definition: object.h:117
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
BOOK
@ BOOK
Definition: object.h:114
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:185
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:1268
get_message_face
const Face * get_message_face(const GeneralMessage *message)
Definition: readable.c:2127
add_abilities
void add_abilities(object *op, const object *change)
Definition: artifact.c:329
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:281
title
struct titlestruct title
obj::next
struct obj * next
Definition: object.h:280
RANDOM
#define RANDOM()
Definition: define.h:644
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:1687
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:15
book_descrpt
static const char *const book_descrpt[]
Definition: readable.c:443
obj::title
sstring title
Definition: object.h:320
obj::arch
struct archt * arch
Definition: object.h:417
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.c:4781
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:1928
diamondslots.message
string message
Definition: diamondslots.py:57
write_book_archive
void write_book_archive(void)
Definition: readable.c:2046
PATH_TELE
#define PATH_TELE
Definition: spells.h:25
llevInfo
@ llevInfo
Definition: logger.h:12
obj::type
uint8_t type
Definition: object.h:343
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:107
obj::stats
living stats
Definition: object.h:373
mon_author
static const char *const mon_author[]
Definition: readable.c:275
archt::clone
object clone
Definition: object.h:473
MSG_TYPE_CARD_SIMPLE_3
#define MSG_TYPE_CARD_SIMPLE_3
Definition: newclient.h:438
obj::weight
int32_t weight
Definition: object.h:370
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
liv::grace
int16_t grace
Definition: living.h:44
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:1609
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:284
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:1136
stringbuffer_length
size_t stringbuffer_length(StringBuffer *sb)
Definition: stringbuffer.c:218
init_mon_info
static void init_mon_info(void)
Definition: readable.c:885
GOD_ENEMY
#define GOD_ENEMY
Definition: god.h:13
msgfile_msg
static StringBuffer * msgfile_msg(object *book, size_t booksize)
Definition: readable.c:1815
PATH_MIND
#define PATH_MIND
Definition: spells.h:23
BOOK_BUF
#define BOOK_BUF
Definition: book.h:16
oblnk::ob
object * ob
Definition: object.h:447
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:1610
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:138
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:2833
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:1647
obj::subtype
uint8_t subtype
Definition: object.h:344
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:1546
FOOD
@ FOOD
Definition: object.h:112
namebytype::type
int type
Definition: readable.c:129
did_first_sp
int did_first_sp
Definition: readable.c:1606
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:288
animate.event
event
DIALOGCHECK MINARGS 1 MAXARGS 2
Definition: animate.py:17
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:165
level
int level
Definition: readable.c:1608
archt::name
sstring name
Definition: object.h:470
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
describe_god
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Definition: holy.cpp:113
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
oblnk
Definition: object.h:446
MSG_TYPE_PAPER_SCROLL_MAGIC
#define MSG_TYPE_PAPER_SCROLL_MAGIC
Definition: newclient.h:463
BOOTS
@ BOOTS
Definition: object.h:212
FLAG_CHANGING
#define FLAG_CHANGING
Definition: define.h:263
SPELL
@ SPELL
Definition: object.h:214
liv::sp
int16_t sp
Definition: living.h:42
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
SHIELD
@ SHIELD
Definition: object.h:135
mon_info_msg
static StringBuffer * mon_info_msg(int level, size_t booksize, object *book)
Definition: readable.c:1377
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:973
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:2010
obj::level
int16_t level
Definition: object.h:356
llevDebug
@ llevDebug
Definition: logger.h:13
artifactstruct::allowed
linked_char * allowed
Definition: artifact.h:19
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
get_message_title
sstring get_message_title(const GeneralMessage *message)
Definition: readable.c:2109
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