Crossfire Server, Trunk
readable.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
23 /* laid down initial file - dec 1995. -b.t. thomas@astro.psu.edu */
24 
25 #include "global.h"
26 
27 #include <assert.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/stat.h>
32 
33 #include "book.h"
34 #include "living.h"
35 #include "output_file.h"
36 #include "spells.h"
37 #include "assets.h"
38 #include "AssetsManager.h"
39 
40 /* Define this if you want to archive book titles by contents.
41  * This option should enforce UNIQUE combinations of titles,authors and
42  * msg contents during and *between *game sessions.
43  * Note: a slight degeneracy exists since books are archived based on an integer
44  * index value calculated from the message text (similar to alchemy formulae).
45  * Sometimes two widely different messages have the same index value (rare). In
46  * this case, it is possible to occasionally generate 2 books with same title and
47  * different message content. Not really a bug, but rather a feature. This action
48  * should keeps player on their toes ;).
49  * Also, note that there is *finite *space available for archiving message and titles.
50  * Once this space is used, books will stop being archived. Not a serious problem
51  * under the current regime, since there are generally fewer possible (random)
52  * messages than space available on the titlelists.
53  * One exception (for sure) are the monster messages. But no worries, you should
54  * see all of the monster info in some order (but not all possble combinations)
55  * before the monster titlelist space is run out. You can increase titlelist
56  * space by increasing the array sizes for the monster book_authours and book_names
57  * (see max_titles[] array and include/read.h). Since the unique_book algorthm is
58  * kinda stupid, this program *may *slow down program execution if defined (but I don't
59  * think its a significant problem, at least, I have no problems running this option
60  * on a Sparc 10! Also, once archive title lists are filled and/or all possible msg
61  * combinations have been generated, unique_book isnt called anymore. It takes 5-10
62  * sessions for this to happen).
63  * Final note: the game remembers book/title/msg combinations from reading the
64  * file lib/bookarch. If you REMOVE this file, you will lose your archive. So
65  * be sure to copy it over to the new lib directory when you change versions.
66  * -b.t.
67  */
68 
69 /* This flag is useful to see what kind of output messages are created */
70 /* #define BOOK_MSG_DEBUG */
71 
72 /* This flag is useful for debugging archiving action */
73 /* #define ARCHIVE_DEBUG */
74 
76 #define MAX_TITLE_CHECK 20
77 
79 #define MSGTYPE_LIB 0
80 
81 #define MSGTYPE_MONSTER 1
82 
83 #define MSGTYPE_ARTIFACT 2
84 
85 #define MSGTYPE_SPELLPATH 3
86 
87 #define MSGTYPE_ALCHEMY 4
88 
89 #define MSGTYPE_GODS 5
90 
91 #define MSGTYPE_MSGFILE 6
92 
98 #define arraysize(arrayname) (sizeof(arrayname)/sizeof(*(arrayname)))
99 
100 /* Moved these structures from struct.h to this file in 0.94.3 - they
101  * are not needed anyplace else, so why have them globally declared?
102  */
103 
108 typedef struct titlestruct {
109  const char *name;
110  const char *authour;
111  const char *archname;
112  unsigned int level;
113  size_t size;
114  int msg_index;
115  struct titlestruct *next;
116 } title;
117 
121 typedef struct titleliststruct {
122  int number;
125 } titlelist;
126 
128 typedef struct namebytype {
129  const char *name;
130  int type;
131 } arttypename;
132 
133 static void add_book(title *book, int type, const char *fname, int lineno);
134 
139 static titlelist *booklist = NULL;
140 
142 static objectlink *first_mon_info = NULL;
143 
144 static int nrofmon = 0,
150 static const uint32_t spellpathdef[NRSPELLPATHS] = {
151  PATH_PROT,
152  PATH_FIRE,
153  PATH_FROST,
154  PATH_ELEC,
155  PATH_MISSILE,
156  PATH_SELF,
157  PATH_SUMMON,
158  PATH_ABJURE,
159  PATH_RESTORE,
161  PATH_MIND,
162  PATH_CREATE,
163  PATH_TELE,
164  PATH_INFO,
167  PATH_TURNING,
169  PATH_DEATH,
170  PATH_LIGHT
171 };
172 
174 static const char *const path_book_name[] = {
175  "codex",
176  "compendium",
177  "documentary",
178  "exposition",
179  "tables",
180  "treatise"
181 };
182 
184 static const char *const path_author[] = {
185  "aether",
186  "arcana",
187  "astral byways",
188  "connections",
189  "the Grey Council",
190  "deep pathways",
191  "knowledge",
192  "magic",
193  "mystic ways",
194  "pathways",
195  "power",
196  "spells",
197  "transforms",
198  "the mystic veil",
199  "unknown spells"
200 };
201 
208 static const arttypename art_name_array[] = {
209  { "Helmet", HELMET },
210  { "Amulet", AMULET },
211  { "Shield", SHIELD },
212  { "Bracers", BRACERS },
213  { "Boots", BOOTS },
214  { "Cloak", CLOAK },
215  { "Gloves", GLOVES },
216  { "Gridle", GIRDLE },
217  { "Ring", RING },
218  { "Horn", ROD },
219  { "Missile Weapon", BOW },
220  { "Missile", ARROW },
221  { "Hand Weapon", WEAPON },
222  { "Artifact", SKILL },
223  { "Food", FOOD },
224  { "Body Armour", ARMOUR }
225 };
226 
228 static const char *const art_book_name[] = {
229  "collection",
230  "file",
231  "files",
232  "guide",
233  "handbook",
234  "index",
235  "inventory",
236  "list",
237  "listing",
238  "omnibus",
239  "record",
240  "record book"
241 };
242 
244 static const char *const art_author[] = {
245  "ancient things",
246  "artifacts",
247  "Havlor", /* ancient warrior scribe :) */
248  "items",
249  "lost artifacts",
250  "the ancients",
251  "treasures",
252  "useful things"
253 };
254 
258 static const char *const mon_book_name[] = {
259  "beastuary",
260  "catalog",
261  "compilation",
262  "collection",
263  "encyclopedia",
264  "guide",
265  "handbook",
266  "list",
267  "manual",
268  "notes",
269  "omnibus",
270  "record",
271  "register",
272  "volume"
273 };
274 
276 static const char *const mon_author[] = {
277  "beasts",
278  "creatures",
279  "dezidens",
280  "dwellers",
281  "evil nature",
282  "life",
283  "monsters",
284  "nature",
285  "new life",
286  "residents",
287  "the spawn",
288  "the living",
289  "things"
290 };
291 
295 static const char *const gods_book_name[] = {
296  "devotional",
297  "devout notes",
298  "divine text",
299  "divine work",
300  "holy book",
301  "holy record",
302  "illuminated text",
303  "moral text",
304  "sacred guide",
305  "testament",
306  "transcript"
307 };
308 
310 static const char *const gods_author[] = {
311  "cults",
312  "joy",
313  "lasting curse",
314  "madness",
315  "religions",
316  "the dead",
317  "the gods",
318  "the heirophant",
319  "the poor priest",
320  "the priestess",
321  "pain",
322  "white"
323 };
324 
328 static const char *const formula_book_name[] = {
329  "cookbook",
330  "formulary",
331  "lab book",
332  "lab notes",
333  "recipe book",
334  "experiment record",
335  "work plan",
336  "design notes",
337  "research notes",
338  "crafting manual"
339 };
340 
342 static const char *const formula_author[] = {
343  "Albertus Magnus",
344  "alchemy",
345  "balms",
346  "creation",
347  "dusts",
348  "magical manufacture",
349  "making",
350  "philosophical items",
351  "potions",
352  "powders",
353  "the cauldron",
354  "the lamp black",
355  "transmutation",
356  "waters"
357 };
358 
364 static const char *const light_book_name[] = {
365  "calendar",
366  "datebook",
367  "diary",
368  "essay",
369  "guidebook",
370  "handbook",
371  "ledger",
372  "notes",
373  "notebook",
374  "octavo",
375  "opuscule",
376  "pamphlet",
377  "practicum",
378  "script",
379  "transcript"
380 };
381 
383 static const char *const heavy_book_name[] = {
384  "catalog",
385  "compendium",
386  "dissertation",
387  "guide",
388  "manual",
389  "opus",
390  "tome",
391  "treatise",
392  "volume",
393  "work"
394 };
395 
397 static const char *const book_author[] = {
398  "Abdulah",
399  "Al'hezred",
400  "Alywn",
401  "Arundel",
402  "Arvind",
403  "Aerlingas",
404  "Bacon",
405  "Baliqendii",
406  "Bosworth",
407  "Beathis",
408  "Bertil",
409  "Cauchy",
410  "Chakrabarti",
411  "der Waalis",
412  "Dirk",
413  "Djwimii",
414  "Eisenstaadt",
415  "Fendris",
416  "Frank",
417  "Habbi",
418  "Harlod",
419  "Ichibod",
420  "Janus",
421  "June",
422  "Laplace",
423  "Magnuson",
424  "Nandii",
425  "Nitfeder",
426  "Norris",
427  "Parael",
428  "Penhew",
429  "Sophia",
430  "Skilly",
431  "Tahir",
432  "Thockmorton",
433  "Thomas",
434  "van Helsing",
435  "van Pelt",
436  "Voormis",
437  "Xavier",
438  "Xeno",
439  "Zardoz",
440  "Zagy"
441 };
442 
444 static const char *const book_descrpt[] = {
445  "ancient",
446  "cryptic",
447  "cryptical",
448  "dusty",
449  "hierarchical",
450  "grizzled",
451  "gold-gilt",
452  "great",
453  "lost",
454  "magnificent",
455  "musty",
456  "mythical",
457  "mystical",
458  "rustic",
459  "stained",
460  "silvered",
461  "transcendental",
462  "weathered"
463 };
464 
472  /*subtype 0 */ { 0, 0 },
473  /* book messages subtypes */
474  /*subtype 1 */ { MSG_TYPE_BOOK, MSG_TYPE_BOOK_CLASP_1 },
483  /*subtype 10 */ { MSG_TYPE_BOOK, MSG_TYPE_BOOK_SPELL_SORCERER },
485  /* card messages subtypes*/
494  /*subtype 20 */ { MSG_TYPE_CARD, MSG_TYPE_CARD_STRANGE_3 },
498  /* Paper messages subtypes */
505  /*subtype 30 */ { MSG_TYPE_PAPER, MSG_TYPE_PAPER_LETTER_NEW_2 },
513  /* road signs messages subtypes */
516  /*subtype 40 */ { MSG_TYPE_SIGN, MSG_TYPE_SIGN_DIR_RIGHT },
518  /* stones and monument messages */
532 };
533 
536 
538 static const int max_titles[6] = {
540  arraysize(mon_book_name)*arraysize(mon_author), /* MSGTYPE_MONSTER */
541  arraysize(art_book_name)*arraysize(art_author), /* MSGTYPE_ARTIFACT */
542  arraysize(path_book_name)*arraysize(path_author), /* MSGTYPE_SPELLPATH */
543  arraysize(formula_book_name)*arraysize(formula_author), /* MSGTYPE_ALCHEMY */
544  arraysize(gods_book_name)*arraysize(gods_author), /* MSGTYPE_GODS */
545 };
546 
547 /******************************************************************************
548  *
549  * Start of misc. readable functions used by others functions in this file
550  *
551  *****************************************************************************/
552 
563  titlelist *bl = (titlelist *)malloc(sizeof(titlelist));
564 
565  if (bl == NULL)
567  bl->number = 0;
568  bl->first_book = NULL;
569  bl->next = NULL;
570  return bl;
571 }
572 
582 static title *get_empty_book(void) {
583  title *t = (title *)malloc(sizeof(title));
584 
585  if (t == NULL)
587  t->name = NULL;
588  t->archname = NULL;
589  t->authour = NULL;
590  t->level = 0;
591  t->size = 0;
592  t->msg_index = 0;
593  t->next = NULL;
594  return t;
595 }
596 
607 static titlelist *get_titlelist(int i) {
608  titlelist *tl;
609  int number;
610 
611  if (i < 0 || i >= (int)arraysize(max_titles)) {
612  LOG(llevInfo, "Warning: invalid book index %d, using 0 instead\n", i);
613  return booklist;
614  }
615 
616  for (tl = booklist, number = i; tl && number; tl = tl->next, number--) {
617  if (!tl->next)
618  tl->next = get_empty_booklist();
619  }
620 
621  return tl;
622 }
623 
624 /* HANDMADE STRING FUNCTIONS.., perhaps these belong in another file
625  * (shstr.c ?), but the quantity BOOK_BUF will need to be defined. */
626 
638 int nstrtok(const char *buf1, const char *buf2) {
639  char *tbuf, buf[MAX_BUF];
640  int number = 0;
641 
642  if (!buf1 || !buf2)
643  return 0;
644 
645  strlcpy(buf, buf1, sizeof(buf));
646  for (tbuf = strtok(buf, buf2); tbuf; tbuf = strtok(NULL, buf2)) {
647  number++;
648  }
649  return number;
650 }
651 
657 const char *trim(const char *buf) {
658  while ((*buf) == ' ') {
659  buf++;
660  }
661  return buf;
662 }
663 
680 char *strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size) {
681  int maxi, i = nstrtok(buf1, buf2);
682  char *tbuf, buf[MAX_BUF];
683 
684  maxi = i;
685  strlcpy(buf, buf1, sizeof(buf));
686  snprintf(retbuf, size, " ");
687  for (tbuf = strtok(buf, buf2); tbuf && i > 0; tbuf = strtok(NULL, buf2)) {
688  snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "%s", trim(tbuf));
689  i--;
690  if (i == 1 && maxi > 1)
691  snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), " and ");
692  else if (i > 0 && maxi > 1)
693  snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), ", ");
694  else
695  snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), ".");
696  }
697  return retbuf;
698 }
699 
710 int book_overflow(const char *buf1, const char *buf2, size_t booksize) {
711  if (buf_overflow(buf1, buf2, BOOK_BUF-2) /* 2 less so always room for trailing \n */
712  || buf_overflow(buf1, buf2, booksize))
713  return 1;
714  return 0;
715 }
716 
717 /*****************************************************************************
718  *
719  * Start of initialization related functions.
720  *
721  ****************************************************************************/
722 
729 static void init_book_archive(void) {
730  FILE *fp;
731 #ifdef BOOK_MSG_DEBUG
732  int nroftitle = 0;
733 #endif
734  char buf[MAX_BUF], fname[MAX_BUF], *cp;
735  static int did_init_barch = 0;
736 
737  if (did_init_barch)
738  return;
739  did_init_barch = 1;
740 
741  if (!booklist)
743 
744  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
745  LOG(llevDebug, " Reading bookarch from %s...\n", fname);
746 
747  fp = fopen(fname, "r");
748  if (fp != NULL) {
749  int type;
750  size_t i;
751  titlelist *bl;
752  int lineno;
753  title *book;
754  int skipping;
755 
756  skipping = 0;
757  book = NULL;
758  type = -1;
759  for (lineno = 1; fgets(buf, MAX_BUF, fp) != NULL; lineno++) {
760  int len;
761  int value;
762 
763  if (*buf == '#')
764  continue;
765  cp = strchr(buf, '\n');
766  if (cp != NULL) {
767  while (cp > buf && (cp[-1] == ' ' || cp[-1] == '\t'))
768  cp--;
769  *cp = '\0';
770  }
771  cp = buf;
772  if (strncmp(buf, "title ", 6) == 0) {
773  skipping = 0;
774  cp = buf+6;
775  while (*cp == ' ' || *cp == '\t')
776  cp++;
777  if (*cp == '\0') {
778  LOG(llevInfo, "Warning: missing book title at %s, line %d\n", fname, lineno);
779  book = NULL;
780  } else {
781  book = get_empty_book(); /* init new book entry */
782  book->name = add_string(cp);
783  type = -1;
784 #ifdef BOOK_MSG_DEBUG
785  nroftitle++;
786 #endif
787  }
788  } else if (book == NULL) {
789  if (!skipping) {
790  skipping = 1;
791  LOG(llevInfo, "Warning: expecting 'title' at %s, line %d\n", fname, lineno);
792  }
793  } else if (strncmp(buf, "authour ", 8) == 0) {
794  cp = buf+8;
795  while (*cp == ' ' || *cp == '\t')
796  cp++;
797  if (*cp == '\0') {
798  LOG(llevInfo, "Warning: missing book authour at %s, line %d\n", fname, lineno);
799  } else {
800  book->authour = add_string(cp);
801  }
802  } else if (strncmp(buf, "arch ", 5) == 0) {
803  cp = buf+5;
804  while (*cp == ' ' || *cp == '\t')
805  cp++;
806  if (*cp == '\0') {
807  LOG(llevInfo, "Warning: missing book arch at %s, line %d\n", fname, lineno);
808  } else {
809  book->archname = add_string(cp);
810  }
811  } else if (sscanf(buf, "level %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
812  book->level = value;
813  } else if (sscanf(buf, "type %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
814  type = value;
815  } else if (sscanf(buf, "size %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
816  book->size = value;
817  } else if (sscanf(buf, "index %d%n", &value, &len) == 1 && len == (int)strlen(buf)) {
818  book->msg_index = value;
819  } else if (strcmp(buf, "end") == 0) { /* link it */
820  add_book(book, type, fname, lineno);
821  book = NULL;
822  type = -1;
823  } else {
824  LOG(llevInfo, "Warning: syntax error at %s, line %d\n", fname, lineno);
825  }
826  }
827  if (book != NULL) {
828  LOG(llevInfo, "Warning: missing 'end' at %s, line %d\n", fname, lineno);
829  add_book(book, type, fname, lineno);
830  }
831  LOG(llevDebug, " book archives(used/avail):\n");
832  for (bl = booklist, i = 0; bl != NULL && i < arraysize(max_titles); bl = bl->next, i++) {
833  LOG(llevDebug, "(%d/%d)\n", bl->number, max_titles[i]);
834  }
835  fclose(fp);
836  }
837 
838 #ifdef BOOK_MSG_DEBUG
839  LOG(llevDebug, "\n init_book_archive() got %d titles.\n", nroftitle);
840 #endif
841  LOG(llevDebug, " done.\n");
842 }
843 
851 static void add_book(title *book, int type, const char *fname, int lineno) {
852  titlelist *bl;
853 
854  if (type == -1) {
855  LOG(llevInfo, "Warning: book with no type at %s, line %d; using type 0\n", fname, lineno);
856  type = 0;
857  }
858 
859  bl = get_titlelist(type);
860  book->next = bl->first_book;
861  bl->first_book = book;
862  bl->number++;
863 }
864 
865 static void do_monster(archetype *at) {
866  if (QUERY_FLAG(&at->clone, FLAG_MONSTER) && (!at->head)
869  objectlink *mon = (objectlink *)malloc(sizeof(objectlink));
870  if (!mon) {
871  LOG(llevError, "init_mon_info: malloc failed!\n");
872  abort();
873  }
874  mon->ob = &at->clone;
875  mon->id = nrofmon;
878  nrofmon++;
879  }
880 }
881 
886 static void init_mon_info(void) {
887  static int did_init_mon_info = 0;
888 
889  if (did_init_mon_info)
890  return;
891  did_init_mon_info = 1;
892 
894 
895  LOG(llevDebug, "init_mon_info() got %d monsters\n", nrofmon);
896 }
897 
904 void init_readable(void) {
905  static int did_this = 0;
906 
907  if (did_this)
908  return;
909  did_this = 1;
910 
911  LOG(llevDebug, "Initializing reading data...\n");
913  init_mon_info();
914  LOG(llevDebug, " done reading data\n");
915 }
916 
917 /*****************************************************************************
918  *
919  * This is the start of the administrative functions when creating
920  * new books (ie, updating title and the like)
921  *
922  *****************************************************************************/
923 
935 static title *find_title(const object *book, int msgtype) {
936  title *t;
937  titlelist *tl;
938  size_t length;
939  int index;
940 
941  if (msgtype < 0)
942  return (title *)NULL;
943 
944  tl = get_titlelist(msgtype);
945  if (!tl)
946  return (title *)NULL;
947 
948  length = strlen(book->msg);
949  index = strtoint(book->msg);
950  for (t = tl->first_book; t; t = t->next)
951  if (t->size == length && t->msg_index == index) {
952 #ifdef ARCHIVE_DEBUG
953  LOG(llevDebug, "Found title match (list %d): %s %s (%d)\n", msgtype, t->name, t->authour, t->msg_index);
954 #endif
955  return t;
956  }
957 
958  return (title *)NULL;
959 }
960 
974 static void new_text_name(object *book, int msgtype) {
975  const char *name;
976 
977  if (book->type != BOOK)
978  return;
979 
980  switch (msgtype) {
981  case MSGTYPE_MONSTER:
983  break;
984 
985  case MSGTYPE_ARTIFACT:
987  break;
988 
989  case MSGTYPE_SPELLPATH:
991  break;
992 
993  case MSGTYPE_ALCHEMY:
995  break;
996 
997  case MSGTYPE_GODS:
999  break;
1000 
1001  case MSGTYPE_MSGFILE:
1002  default:
1003  if (book->weight > 2000) { /* based on weight */
1005  } else {
1007  }
1008  break;
1009  }
1010  free_string(book->name);
1011  book->name = add_string(name);
1012 }
1013 
1023 static void add_author(object *op, int msgtype) {
1024  char title[MAX_BUF];
1025  const char *name;
1026 
1027  if (msgtype < 0 || strlen(op->msg) < 5)
1028  return;
1029 
1030  switch (msgtype) {
1031  case MSGTYPE_MONSTER:
1033  break;
1034 
1035  case MSGTYPE_ARTIFACT:
1037  break;
1038 
1039  case MSGTYPE_SPELLPATH:
1041  break;
1042 
1043  case MSGTYPE_ALCHEMY:
1045  break;
1046 
1047  case MSGTYPE_GODS:
1049  break;
1050 
1051  case MSGTYPE_MSGFILE:
1052  default:
1054  }
1055 
1056  snprintf(title, sizeof(title), "of %s", name);
1057  op->title = add_string(title);
1058 }
1059 
1071 static int unique_book(const object *book, int msgtype) {
1072  title *test;
1073 
1074  if (!booklist)
1075  return 1; /* No archival entries! Must be unique! */
1076 
1077  /* Go through the booklist. If the author and name match, not unique so
1078  * return 0.
1079  */
1080  for (test = get_titlelist(msgtype)->first_book; test; test = test->next) {
1081  if (!strcmp(test->name, book->name) && !strcmp(book->title, test->authour))
1082  return 0;
1083  }
1084  return 1;
1085 }
1086 
1095 static void add_book_to_list(const object *book, int msgtype) {
1096  titlelist *tl = get_titlelist(msgtype);
1097  title *t;
1098 
1099  if (!tl) {
1100  LOG(llevError, "add_book_to_list can't get booklist!\n");
1101  return;
1102  }
1103 
1104  t = get_empty_book();
1105  t->name = add_string(book->name);
1106  t->authour = add_string(book->title);
1107  t->size = strlen(book->msg);
1108  t->msg_index = strtoint(book->msg);
1109  t->archname = add_string(book->arch->name);
1110  t->level = book->level;
1111 
1112  t->next = tl->first_book;
1113  tl->first_book = t;
1114  tl->number++;
1115 
1116  /* We have stuff we need to write now */
1118 
1119 #ifdef ARCHIVE_DEBUG
1120  LOG(llevDebug, "Archiving new title: %s %s (%d)\n", book->name, book->title, msgtype);
1121 #endif
1122 }
1123 
1137 static void change_book(object *book, int msgtype) {
1138  titlelist *tl;
1139  title *t;
1140  int tries;
1141 
1142  if (book->type != BOOK) {
1143  LOG(llevError, "change_book_name() called w/ illegal obj type.\n");
1144  return;
1145  }
1146 
1147  tl = get_titlelist(msgtype);
1148  t = NULL;
1149  tries = 0;
1150 
1151  /* look to see if our msg already been archived. If so, alter
1152  * the book to match the archival text. If we fail to match,
1153  * then we archive the new title/name/msg combo if there is
1154  * room on the titlelist.
1155  */
1156 
1157  if (strlen(book->msg) > 5 && (t = find_title(book, msgtype))) {
1158  object *tmpbook;
1159  sstring marker = object_get_value(book, "knowledge_marker");
1160 
1161  /* alter book properties */
1162  tmpbook = create_archetype(t->archname);
1163  if (marker != NULL)
1164  /* need to copy the knowledge_marker */
1165  object_set_value(tmpbook, "knowledge_marker", marker, 1);
1166  object_set_msg(tmpbook, book->msg);
1167  object_copy(tmpbook, book);
1168  object_free_drop_inventory(tmpbook);
1169 
1170  book->title = add_string(t->authour);
1171  free_string(book->name);
1172  book->name = add_string(t->name);
1173  book->level = t->level;
1174  } else { /* Don't have any default title, so lets make up a new one */
1175  int numb, maxnames = max_titles[msgtype];
1176  const char *old_title;
1177  const char *old_name;
1178 
1179  old_title = book->title ? add_string(book->title) : NULL;
1180  old_name = add_string(book->name);
1181 
1182  /* some pre-generated books have title already set (from
1183  * maps), also don't bother looking for unique title if
1184  * we already used up all the available names! */
1185 
1186  if (!tl) {
1187  LOG(llevError, "change_book_name(): can't find title list\n");
1188  numb = 0;
1189  } else
1190  numb = tl->number;
1191 
1192  if (numb == maxnames) {
1193 #ifdef ARCHIVE_DEBUG
1194  LOG(llevDebug, "titles for list %d full (%d possible).\n", msgtype, maxnames);
1195 #endif
1196  if (old_title != NULL)
1197  free_string(old_title);
1198  free_string(old_name);
1199  return;
1200  }
1201  /* shouldnt change map-maker books */
1202  if (!book->title)
1203  do {
1204  /* random book name */
1205  new_text_name(book, msgtype);
1206  add_author(book, msgtype); /* random author */
1207  tries++;
1208  } while (!unique_book(book, msgtype) && tries < MAX_TITLE_CHECK);
1209 
1210  /* Now deal with 2 cases.
1211  * 1) If no space for a new title exists lets just restore
1212  * the old book properties. Remember, if the book had
1213  * matchd an older entry on the titlelist, we shouldnt
1214  * have called this routine in the first place!
1215  * 2) If we got a unique title, we need to add it to
1216  * the list.
1217  */
1218 
1219  if (tries == MAX_TITLE_CHECK) {
1220 #ifdef ARCHIVE_DEBUG
1221  LOG(llevDebug, "Failed to obtain unique title for %s %s (names:%d/%d)\n", book->name, book->title, numb, maxnames);
1222 #endif
1223  /* restore old book properties here */
1224  free_string(book->name);
1225  free_string(book->title);
1226  book->title = old_title != NULL ? add_string(old_title) : NULL;
1227 
1228  if (RANDOM()%4) {
1229  /* Lets give the book a description to individualize it some */
1230  char new_name[MAX_BUF];
1231 
1232  snprintf(new_name, MAX_BUF, "%s %s", book_descrpt[RANDOM()%arraysize(book_descrpt)], old_name);
1233  book->name = add_string(new_name);
1234  } else {
1235  book->name = add_string(old_name);
1236  }
1237  } else if (book->title && strlen(book->msg) > 5) { /* archive if long msg texts */
1238  add_book_to_list(book, msgtype);
1239  }
1240 
1241  if (old_title != NULL)
1242  free_string(old_title);
1243  free_string(old_name);
1244  }
1245 }
1246 
1247 /*****************************************************************************
1248  *
1249  * This is the start of the area that generates the actual contents
1250  * of the book.
1251  *
1252  *****************************************************************************/
1253 
1254 /*****************************************************************************
1255  * Monster msg generation code.
1256  ****************************************************************************/
1257 
1269 object *get_random_mon(int level) {
1270  objectlink *mon;
1271  int i, monnr;
1272 
1273  /* safety check. Problem w/ init_mon_info list? */
1274  if (!nrofmon || !first_mon_info)
1275  return (object *)NULL;
1276 
1277  if (!level) {
1278  /* lets get a random monster from the mon_info linked list */
1279  monnr = RANDOM()%nrofmon;
1280 
1281  for (mon = first_mon_info, i = 0; mon; mon = mon->next, i++)
1282  if (i == monnr)
1283  break;
1284 
1285  if (!mon) {
1286  LOG(llevError, "get_random_mon: Didn't find a monster when we should have\n");
1287  return NULL;
1288  }
1289  return mon->ob;
1290  }
1291 
1292  /* Case where we are searching by level. Redone 971225 to be clearer
1293  * and more random. Before, it looks like it took a random monster from
1294  * the list, and then returned the first monster after that which was
1295  * appropriate level. This wasn't very random because if you had a
1296  * bunch of low level monsters and then a high level one, if the random
1297  * determine took one of the low level ones, it would just forward to the
1298  * high level one and return that. Thus, monsters that immediately followed
1299  * a bunch of low level monsters would be more heavily returned. It also
1300  * means some of the dragons would be poorly represented, since they
1301  * are a group of high level monsters all around each other.
1302  */
1303 
1304  /* First count number of monsters meeting level criteria */
1305  for (mon = first_mon_info, i = 0; mon; mon = mon->next)
1306  if (mon->ob->level >= level)
1307  i++;
1308 
1309  if (i == 0) {
1310  LOG(llevError, "get_random_mon() couldn't return monster for level %d\n", level);
1311  return NULL;
1312  }
1313 
1314  monnr = RANDOM()%i;
1315  for (mon = first_mon_info; mon; mon = mon->next)
1316  if (mon->ob->level >= level && monnr-- == 0)
1317  return mon->ob;
1318 
1319  LOG(llevError, "get_random_mon(): didn't find a monster when we should have\n");
1320  return NULL;
1321 }
1322 
1332 static StringBuffer *mon_desc(const object *mon) {
1333  StringBuffer *desc = stringbuffer_new();
1334  stringbuffer_append_printf(desc, "\n---\n *** %s ***\n", mon->name);
1335  describe_item(mon, NULL, 0, desc);
1336  return desc;
1337 }
1338 
1350 static object *get_next_mon(const object *tmp) {
1351  objectlink *mon;
1352 
1353  for (mon = first_mon_info; mon; mon = mon->next)
1354  if (mon->ob == tmp)
1355  break;
1356 
1357  /* didn't find a match */
1358  if (!mon)
1359  return NULL;
1360  if (mon->next)
1361  return mon->next->ob;
1362  else
1363  return first_mon_info->ob;
1364 }
1365 
1378 static StringBuffer *mon_info_msg(int level, size_t booksize, object *book) {
1379  object *tmp;
1380  StringBuffer *marker = stringbuffer_new(), *desc = stringbuffer_new(), *mon = NULL;
1381  int added = 0;
1382  sstring final;
1383  const char *sep = ":";
1384 
1385  /*preamble */
1386  stringbuffer_append_string(desc, "This beastiary contains:");
1387  stringbuffer_append_string(marker, "monster");
1388 
1389  /* lets print info on as many monsters as will fit in our
1390  * document.
1391  * 8-96 Had to change this a bit, otherwise there would
1392  * have been an impossibly large number of combinations
1393  * of text! (and flood out the available number of titles
1394  * in the archive in a snap!) -b.t.
1395  */
1396  for (tmp = get_random_mon(level*3); tmp; tmp = get_next_mon(tmp)) {
1397  /* monster description */
1398  mon = mon_desc(tmp);
1399 
1401  break;
1402  added++;
1403  stringbuffer_append_printf(marker, "%s%s", sep, tmp->arch->name);
1404  sep = "/";
1407  mon = NULL;
1408  }
1409 
1410  if (mon != NULL) {
1412  }
1413 
1414  final = stringbuffer_finish_shared(marker);
1415  if (added)
1416  object_set_value(book, "knowledge_marker", final, 1);
1417  free_string(final);
1418 
1419  return desc;
1420 }
1421 
1422 /*****************************************************************************
1423  * Artifact msg generation code.
1424  ****************************************************************************/
1425 
1435 static StringBuffer *artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator) {
1436  object *tmp;
1437  int chance;
1438  StringBuffer *desc = stringbuffer_new(), *sbuf;
1439 
1440  if (separator)
1441  stringbuffer_append_string(desc, "---\n");
1442 
1443  /* Name */
1444  if (art->allowed != NULL) {
1445  archetype *arch;
1446  linked_char *temp = art->allowed;
1447  int inv = 0, w;
1448 
1449  assert(art->allowed_size > 0);
1450  if (art->allowed_size > 1)
1451  w = 1 + RANDOM() % art->allowed_size;
1452  else
1453  w = 1;
1454 
1455  while (w > 1) {
1456  assert(temp);
1457  temp = temp->next;
1458  w--;
1459  }
1460 
1461  if (temp->name[0] == '!')
1462  inv = 1;
1463 
1465  arch = try_find_archetype(temp->name + inv);
1466  if (!arch)
1468 
1469  if (!arch)
1470  LOG(llevError, "artifact_msg: missing archetype %s for artifact %s (type %d)\n", temp->name + inv, art->item->name, art->item->type);
1471  else {
1472  if (inv)
1473  stringbuffer_append_printf(desc, " A %s (excepted %s) of %s", art_name_array[art_name].name, arch->clone.name_pl, art->item->name);
1474  else
1475  stringbuffer_append_printf(desc, " A %s of %s", arch->clone.name, art->item->name);
1476  }
1477  } else { /* default name is used */
1478  /* use the base 'generic' name for our artifact */
1479  stringbuffer_append_printf(desc, " The %s of %s", art_name_array[art_name].name, art->item->name);
1480  }
1481 
1482  /* chance of finding */
1483  stringbuffer_append_string(desc, " is ");
1484  chance = 100*((float)art->chance/al->total_chance);
1485  if (chance >= 20)
1486  stringbuffer_append_string(desc, "an uncommon");
1487  else if (chance >= 10)
1488  stringbuffer_append_string(desc, "an unusual");
1489  else if (chance >= 5)
1490  stringbuffer_append_string(desc, "a rare");
1491  else
1492  stringbuffer_append_string(desc, "a very rare");
1493 
1494  /* value of artifact */
1495  stringbuffer_append_printf(desc, " item with a value that is %d times normal.\n", art->item->value);
1496 
1497  /* include the message about the artifact, if exists, and book
1498  * level is kinda high */
1499  if (message && !(strlen(art->item->msg) > BOOK_BUF))
1500  stringbuffer_append_string(desc, art->item->msg);
1501 
1502  /* properties of the artifact */
1503  tmp = object_new();
1504  add_abilities(tmp, art->item);
1505  tmp->type = al->type;
1507  sbuf = describe_item(tmp, NULL, 0, NULL);
1508  if (stringbuffer_length(sbuf) > 1) {
1509  stringbuffer_append_string(desc, " Properties of this artifact include:\n ");
1511  stringbuffer_append_string(desc, "\n");
1512  }
1513  free(stringbuffer_finish(sbuf));
1515 
1516  return desc;
1517 }
1518 
1530 static StringBuffer *artifact_msg(unsigned int level, size_t booksize) {
1531  const artifactlist *al;
1532  const artifact *art;
1533  int i, type, index;
1534  int book_entries = level > 5 ? RANDOM()%3+RANDOM()%3+2 : RANDOM()%level+1;
1536 
1537  /* values greater than 5 create msg buffers that are too big! */
1538  if (book_entries > 5)
1539  book_entries = 5;
1540 
1541  /* lets determine what kind of artifact type randomly.
1542  * Right now legal artifacts only come from those listed
1543  * in art_name_array. Also, we check to be sure an artifactlist
1544  * for that type exists!
1545  */
1546  i = 0;
1547  do {
1550  al = find_artifactlist(type);
1551  i++;
1552  } while (al == NULL && i < 10);
1553 
1554  if (i == 10) { /* Unable to find a message */
1556  return message;
1557  }
1558 
1559  /* There is no reason to start on the artifact list at the beginning. Lets
1560  * take our starting position randomly... */
1561  art = al->items;
1562  for (i = RANDOM()%level+RANDOM()%2+1; i > 0; i--) {
1563  if (art == NULL)
1564  art = al->items; /* hmm, out of stuff, loop back around */
1565  art = art->next;
1566  }
1567 
1568  /* Ok, lets print out the contents */
1569  stringbuffer_append_printf(message, "Herein %s detailed %s...\n", book_entries > 1 ? "are" : "is", book_entries > 1 ? "some artifacts" : "an artifact");
1570 
1571  i = 0;
1572  /* artifact msg attributes loop. Lets keep adding entries to the 'book'
1573  * as long as we have space up to the allowed max # (book_entires)
1574  */
1575  while (book_entries > 0) {
1576  int with_message;
1577  if (art == NULL)
1578  art = al->items;
1579  with_message = (art->item->msg && RANDOM()%4+1 < level) ? 1 : 0;
1580 
1581  desc = artifact_describe(art, al, with_message, index, i++);
1582 
1584  stringbuffer_delete(desc);
1585  break;
1586  }
1587 
1589  stringbuffer_delete(desc);
1590 
1591  art = art->next;
1592  book_entries--;
1593  }
1594 
1595  return message;
1596 }
1597 
1598 /*****************************************************************************
1599  * Spellpath message generation
1600  *****************************************************************************/
1601 
1603 static struct {
1604  int prayers;
1605  int did_first_sp;
1606  uint32_t pnum;
1607  int level;
1608  size_t booksize;
1610  int done;
1614 static void do_spellpath_msg(archetype *at) {
1615  /* Determine if this is an appropriate spell. Must
1616  * be of matching path, must be of appropriate type (prayer
1617  * or not), and must be within the valid level range.
1618  */
1619  if (at->clone.type == SPELL
1620  && at->clone.path_attuned & sp_params.pnum
1621  && ((at->clone.stats.grace && sp_params.prayers) || (at->clone.stats.sp && !sp_params.prayers))
1622  && at->clone.level < sp_params.level*8) {
1623  if (strlen(at->clone.name) + stringbuffer_length(sp_params.buf) >= sp_params.booksize) {
1624  sp_params.done = 1;
1625  return;
1626  }
1627 
1628  if (sp_params.did_first_sp)
1630  sp_params.did_first_sp = 1;
1632  }
1633 }
1634 
1649  int path = RANDOM()%NRSPELLPATHS;
1650  sp_params.prayers = RANDOM()%2;
1651  sp_params.did_first_sp = 0;
1652  sp_params.pnum = spellpathdef[path];
1653  sp_params.done = 0;
1654 
1655  if (buf == NULL) {
1656  buf = stringbuffer_new();
1657  /* Preamble */
1658  stringbuffer_append_printf(buf, "Herein are detailed the names of %s", sp_params.prayers ? "prayers" : "incantations");
1659  stringbuffer_append_printf(buf, " belonging to the path of %s:\n ", spellpathnames[path]);
1660  }
1661  sp_params.level = level;
1662  sp_params.booksize = booksize;
1663  sp_params.buf = buf;
1664 
1666 
1667  /* Geez, no spells were generated. */
1668  if (!sp_params.did_first_sp) {
1669  if (RANDOM()%4) { /* usually, lets make a recursive call... */
1670  // If we do a recursive call, we reset the spell path, so we will want to reset our text as well.
1672  return spellpath_msg(level, booksize, NULL);
1673  }
1674  /* give up, cause knowing no spells exist for path is info too. need the header too. */
1675  stringbuffer_append_string(buf, "- no known spells exist -\n");
1676  }
1677  return buf;
1678 }
1679 
1688 static void make_formula_book(object *book, int level) {
1689  recipelist *fl;
1690  recipe *formula;
1691  int chance, count = 0;
1692  const char *op_name;
1693  archetype *at;
1694  StringBuffer *text, *title;
1695  char *final, km[MAX_BUF];
1696 
1697  /* the higher the book level, the more complex (ie number of
1698  * ingredients) the formula can be.
1699  */
1700  fl = get_formulalist((RANDOM()%level)/3+1);
1701  if (!fl)
1702  fl = get_formulalist(1); /* safety */
1703 
1704  if (fl->total_chance == 0) {
1705  object_set_msg(book, " <indecipherable text>\n");
1707  add_author(book, MSGTYPE_ALCHEMY);
1708  return;
1709  }
1710 
1711  /* get a random formula, weighted by its bookchance */
1712  chance = RANDOM()%fl->total_chance;
1713  for (formula = fl->items; formula != NULL; formula = formula->next) {
1714  chance -= formula->chance;
1715  if (chance <= 0 && formula->chance != 0 && !formula->is_combination)
1716  break;
1717  }
1718 
1719  if (!formula || formula->arch_names <= 0) {
1720  object_set_msg(book, " <indecipherable text>\n");
1722  add_author(book, MSGTYPE_ALCHEMY);
1723  return;
1724  }
1725 
1726  /* looks like a formula was found. Base the amount
1727  * of information on the booklevel and the spellevel
1728  * of the formula. */
1729 
1730  op_name = formula->arch_name[RANDOM()%formula->arch_names];
1731  at = find_archetype(op_name);
1732  if (at == (archetype *)NULL) {
1733  LOG(llevError, "formula_msg() can't find arch %s for formula.\n", op_name);
1734  object_set_msg(book, " <indecipherable text>\n");
1736  add_author(book, MSGTYPE_ALCHEMY);
1737  return;
1738  }
1739  op_name = at->clone.name;
1740 
1741  text = stringbuffer_new();
1742  title = stringbuffer_new();
1743 
1744  /* preamble */
1745  stringbuffer_append_printf(text, "Herein is described a project using %s:\n", formula->skill ? formula->skill : "an unknown skill");
1746 
1747  /* item name */
1748  if (strcmp(formula->title, "NONE")) {
1749  stringbuffer_append_printf(text, "The %s of %s", op_name, formula->title);
1750  /* This results in things like pile of philo. sulfur.
1751  * while philo. sulfur may look better, without this,
1752  * you get things like 'the wise' because its missing the
1753  * water of section.
1754  */
1756  } else {
1757  stringbuffer_append_printf(text, "The %s", op_name);
1759  if (at->clone.title) {
1762  }
1763  }
1764  /* Lets name the book something meaningful ! */
1765  if (book->name)
1766  free_string(book->name);
1768  if (book->title) {
1769  free_string(book->title);
1770  book->title = NULL;
1771  }
1772 
1773  /* ingredients to make it */
1774  if (formula->ingred != NULL) {
1775  linked_char *next;
1776  archetype *at;
1777  char name[MAX_BUF];
1778 
1779  at = find_archetype(formula->cauldron);
1780  if (at)
1781  query_name(&at->clone, name, MAX_BUF);
1782  else
1783  snprintf(name, sizeof(name), "an unknown place");
1784 
1785  stringbuffer_append_printf(text, " may be made at %s using the following ingredients:\n", name);
1786 
1787  for (next = formula->ingred; next != NULL; next = next->next) {
1788  count++;
1789  stringbuffer_append_printf(text, "%s\n", next->name);
1790  }
1791  } else {
1792  LOG(llevError, "formula_msg() no ingredient list for object %s of %s\n", op_name, formula->title);
1794  }
1795 
1796  final = stringbuffer_finish(text);
1797  object_set_msg(book, final);
1798  free(final);
1799 
1802  snprintf(km, sizeof(km), "alchemy:%d:%d:%s", count, formula->index, formula->title);
1803  object_set_value(book, "knowledge_marker", km, 1);
1804 }
1805 
1816 static StringBuffer *msgfile_msg(object *book, size_t booksize) {
1817  StringBuffer *ret = stringbuffer_new();
1818 
1820 
1821  if (msg && strlen(msg->message) <= booksize) {
1822  stringbuffer_append_string(ret, msg->message);
1823  if (msg->identifier != NULL) {
1824  char km[HUGE_BUF];
1827  snprintf(km, sizeof(km), "message:%s", msg->identifier);
1828  object_set_value(book, "knowledge_marker", km, 1);
1829  }
1830  if (msg->quest_code) {
1831  /* add a 'apply' hook to launch the quest */
1832  archetype *at = find_archetype("quest_advance_apply");
1833  if (at != NULL) {
1834  object *event = object_create_arch(at);
1835  FREE_AND_COPY(event->name, msg->quest_code);
1836  object_insert_in_ob(event, book);
1837  }
1838  }
1839  } else
1840  stringbuffer_append_string(ret, "\n <undecipherable text>");
1841 
1842  return ret;
1843 }
1844 
1859 static StringBuffer *god_info_msg(int level, size_t booksize, object *book) {
1860  int what = 0;
1861  const object *god = get_rand_god();
1862  StringBuffer *desc = NULL;
1863 
1864  if (!god)
1865  return NULL; /* oops, problems... */
1866 
1867  if (booksize > BOOK_BUF) {
1868  LOG(llevError, "common/readable.c:god_info_msg() - passed in booksize (%lu) is larger than book buffer (%d)\n", (unsigned long)booksize, BOOK_BUF);
1869  booksize = BOOK_BUF;
1870  }
1871 
1872  if (level >= 2 && RANDOM()%2) {
1873  what |= GOD_ENEMY;
1874  }
1875  if (level >= 3 && RANDOM()%2) {
1876  what |= GOD_HOLYWORD;
1877  }
1878  if (level >= 4 && RANDOM()%2) {
1879  what |= GOD_RESISTANCES;
1880  }
1881  if (level >= 5 && RANDOM()%2) {
1882  what |= GOD_SACRED;
1883  }
1884  if (level >= 6 && RANDOM()%2) {
1885  what |= GOD_BLESSED;
1886  }
1887  if (level >= 8 && RANDOM()%2) {
1888  what |= GOD_IMMUNITIES;
1889  }
1890  if (level >= 12 && RANDOM()%2) {
1891  what |= GOD_PATHS;
1892  }
1893 
1894  desc = stringbuffer_new();
1895  what = describe_god(god, what, desc, booksize);
1896 
1897  /* check to be sure new buffer size dont exceed either
1898  * the maximum buffer size, or the 'natural' size of the
1899  * book... */
1900  if (stringbuffer_length(desc) > 1 && stringbuffer_length(desc) <= booksize) {
1901  char buf[BOOK_BUF];
1902  snprintf(buf, sizeof(buf), "god:%s:%d", god->name, what);
1903  object_set_value(book, "knowledge_marker", buf, 1);
1904  return desc;
1905  }
1906 
1907  stringbuffer_delete(desc);
1908  return NULL;
1909 }
1910 
1929 void tailor_readable_ob(object *book, int msg_type) {
1930  int level = book->level ? RANDOM()%book->level+1 : 1;
1931  size_t book_buf_size;
1932  StringBuffer *message = NULL;
1933 
1934  /* safety */
1935  if (book->type != BOOK)
1936  return;
1937 
1938  if (level <= 0)
1939  return; /* if no level no point in doing any more... */
1940 
1941  /* Max text length this book can have. */
1942  book_buf_size = BOOKSIZE(book);
1943  book_buf_size -= strlen("\n"); /* Keep enough for final \n. */
1944  assert(book_buf_size < BOOK_BUF);
1945 
1946  /* &&& The message switch &&& */
1947  /* Below all of the possible types of messages in the "book"s.
1948  */
1949  /*
1950  * IF you add a new type of book msg, you will have to do several things.
1951  * 1) make sure there is an entry in the msg switch below!
1952  * 2) make sure there is an entry in max_titles[] array.
1953  * 3) make sure there are entries for your case in new_text_title()
1954  * and add_authour().
1955  * 4) you may want separate authour/book name arrays in read.h
1956  */
1957 
1958  if (msg_type >= (int)arraysize(max_titles))
1959  msg_type = 0;
1960 
1961  msg_type = msg_type > 0 ? msg_type : (int)(RANDOM()%6);
1962  switch (msg_type) {
1963  case MSGTYPE_MONSTER:
1964  message = mon_info_msg(level, book_buf_size, book);
1965  break;
1966 
1967  case MSGTYPE_ARTIFACT:
1968  message = artifact_msg(level, book_buf_size);
1969  break;
1970 
1971  case MSGTYPE_SPELLPATH: /* grouping incantations/prayers by path */
1972  message = spellpath_msg(level, book_buf_size, NULL);
1973  break;
1974 
1975  case MSGTYPE_ALCHEMY: /* describe an alchemy formula */
1976  make_formula_book(book, level);
1977  /* make_formula_book already gives title */
1978  return;
1979  break;
1980 
1981  case MSGTYPE_GODS: /* bits of information about a god */
1982  message = god_info_msg(level, book_buf_size, book);
1983  break;
1984 
1985  case MSGTYPE_LIB: /* use info list in lib/ */
1986  default:
1987  message = msgfile_msg(book, book_buf_size);
1988  break;
1989  }
1990 
1991  if (message != NULL) {
1992  char *final;
1994  final = stringbuffer_finish(message);
1995  object_set_msg(book, final);
1996  free(final);
1997  /* lets give the "book" a new name, which may be a compound word */
1998  change_book(book, msg_type);
1999  }
2000 }
2001 
2002 /*****************************************************************************
2003  *
2004  * Cleanup routine for readable stuff.
2005  *
2006  *****************************************************************************/
2007 
2011 void free_all_readable(void) {
2012  titlelist *tlist, *tnext;
2013  title *title1, *titlenext;
2014  objectlink *monlink, *nextmon;
2015 
2016  LOG(llevDebug, "freeing all book information\n");
2017 
2018  for (tlist = booklist; tlist != NULL; tlist = tnext) {
2019  tnext = tlist->next;
2020  for (title1 = tlist->first_book; title1; title1 = titlenext) {
2021  titlenext = title1->next;
2022  if (title1->name)
2023  free_string(title1->name);
2024  if (title1->authour)
2025  free_string(title1->authour);
2026  if (title1->archname)
2027  free_string(title1->archname);
2028  free(title1);
2029  }
2030  free(tlist);
2031  }
2032  for (monlink = first_mon_info; monlink; monlink = nextmon) {
2033  nextmon = monlink->next;
2034  free(monlink);
2035  }
2036 }
2037 
2038 /*****************************************************************************
2039  *
2040  * Writeback routine for updating the bookarchive.
2041  *
2042  ****************************************************************************/
2043 
2048  FILE *fp;
2049  OutputFile of;
2050  int index;
2051  char fname[MAX_BUF];
2052  title *book;
2053  titlelist *bl;
2054 
2055  /* If nothing changed, don't write anything */
2057  return;
2058 
2059  snprintf(fname, sizeof(fname), "%s/bookarch", settings.localdir);
2060  LOG(llevDebug, "Updating book archive: %s...\n", fname);
2061 
2062  fp = of_open(&of, fname);
2063  if (fp == NULL)
2064  return;
2065 
2066  for (bl = get_titlelist(0), index = 0; bl; bl = bl->next, index++) {
2067  for (book = bl->first_book; book; book = book->next)
2068  if (book && book->authour) {
2069  fprintf(fp, "title %s\n", book->name);
2070  fprintf(fp, "authour %s\n", book->authour);
2071  fprintf(fp, "arch %s\n", book->archname);
2072  fprintf(fp, "level %d\n", book->level);
2073  fprintf(fp, "type %d\n", index);
2074  /* C89 doesn't have %zu... */
2075  fprintf(fp, "size %lu\n", (unsigned long)book->size);
2076  fprintf(fp, "index %d\n", book->msg_index);
2077  fprintf(fp, "end\n");
2078  }
2079  }
2080  if (!of_close(&of))
2081  return;
2082 
2083  if (chmod(fname, SAVE_MODE) != 0) {
2084  LOG(llevError, "Could not set permissions on '%s'\n", fname);
2085  }
2086 
2088 }
2089 
2098  uint8_t subtype = readable->subtype;
2099 
2100  if (subtype > last_readable_subtype)
2101  return &readable_message_types[0];
2102  return &readable_message_types[subtype];
2103 }
2104 
2111  return message->title;
2112 }
2113 
2120  return message->message;
2121 }
2122 
2129  return message->face;
2130 }
write_book_archive
void write_book_archive(void)
Definition: readable.cpp:2047
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
formula_book_name
static const char *const formula_book_name[]
Definition: readable.cpp:328
MSG_TYPE_BOOK_SPELL_PRAYER
#define MSG_TYPE_BOOK_SPELL_PRAYER
Definition: newclient.h:430
output_file.h
global.h
GOD_IMMUNITIES
#define GOD_IMMUNITIES
Definition: god.h:18
change_book
static void change_book(object *book, int msgtype)
Definition: readable.cpp:1137
settings
struct Settings settings
Definition: init.cpp:139
path_book_name
static const char *const path_book_name[]
Definition: readable.cpp:174
stringbuffer_length
size_t stringbuffer_length(StringBuffer *sb)
Definition: stringbuffer.cpp:218
GeneralMessage
Definition: book.h:44
get_formulalist
recipelist * get_formulalist(int i)
Definition: recipe.cpp:97
SAVE_MODE
#define SAVE_MODE
Definition: config.h:555
get_empty_booklist
static titlelist * get_empty_booklist(void)
Definition: readable.cpp:562
do_spellpath_msg
static void do_spellpath_msg(archetype *at)
Definition: readable.cpp:1614
mon_author
static const char *const mon_author[]
Definition: readable.cpp:276
BOW
@ BOW
Definition: object.h:121
BRACERS
@ BRACERS
Definition: object.h:220
PATH_LIGHT
#define PATH_LIGHT
Definition: spells.h:32
archt::head
struct archt * head
Definition: object.h:474
llevError
@ llevError
Definition: logger.h:11
init_mon_info
static void init_mon_info(void)
Definition: readable.cpp:886
GOD_PATHS
#define GOD_PATHS
Definition: god.h:19
PATH_RESTORE
#define PATH_RESTORE
Definition: spells.h:21
get_empty_book
static title * get_empty_book(void)
Definition: readable.cpp:582
MSG_TYPE_PAPER_LETTER_OLD_2
#define MSG_TYPE_PAPER_LETTER_OLD_2
Definition: newclient.h:454
PATH_INFO
#define PATH_INFO
Definition: spells.h:26
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
arraysize
#define arraysize(arrayname)
Definition: readable.cpp:98
MSG_TYPE_BOOK_SPELL_SUMMONER
#define MSG_TYPE_BOOK_SPELL_SUMMONER
Definition: newclient.h:433
book_author
static const char *const book_author[]
Definition: readable.cpp:397
of_close
int of_close(OutputFile *of)
Definition: output_file.cpp:61
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
MONSTER_EXCLUDE_FROM_READABLE_KEY
#define MONSTER_EXCLUDE_FROM_READABLE_KEY
Definition: object.h:585
free_all_readable
void free_all_readable(void)
Definition: readable.cpp:2011
AssetsManager::messages
Messages * messages()
Definition: AssetsManager.h:59
PATH_ELEC
#define PATH_ELEC
Definition: spells.h:16
of_open
FILE * of_open(OutputFile *of, const char *fname)
Definition: output_file.cpp:30
GLOVES
@ GLOVES
Definition: object.h:216
GIRDLE
@ GIRDLE
Definition: object.h:226
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
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:305
AssetsManager.h
spellpathnames
const char *const spellpathnames[NRSPELLPATHS]
Definition: init.cpp:239
obj::value
int32_t value
Definition: object.h:358
namebytype
Definition: readable.cpp:128
mon_book_name
static const char *const mon_book_name[]
Definition: readable.cpp:258
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.cpp:138
path_author
static const char *const path_author[]
Definition: readable.cpp:184
artifact_msg
static StringBuffer * artifact_msg(unsigned int level, size_t booksize)
Definition: readable.cpp:1530
MSG_TYPE_PAPER
#define MSG_TYPE_PAPER
Definition: newclient.h:397
MSG_TYPE_PAPER_LETTER_NEW_2
#define MSG_TYPE_PAPER_LETTER_NEW_2
Definition: newclient.h:456
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
MSG_TYPE_BOOK_QUARTO_1
#define MSG_TYPE_BOOK_QUARTO_1
Definition: newclient.h:427
PATH_SELF
#define PATH_SELF
Definition: spells.h:18
MSG_TYPE_SIGN_BASIC
#define MSG_TYPE_SIGN_BASIC
Definition: newclient.h:466
obj::path_attuned
uint32_t path_attuned
Definition: object.h:351
titlestruct::msg_index
int msg_index
Definition: readable.cpp:114
gods_book_name
static const char *const gods_book_name[]
Definition: readable.cpp:295
ARMOUR
@ ARMOUR
Definition: object.h:123
MSG_TYPE_PAPER_SCROLL_NEW_2
#define MSG_TYPE_PAPER_SCROLL_NEW_2
Definition: newclient.h:462
WEAPON
@ WEAPON
Definition: object.h:122
MSG_TYPE_PAPER_SCROLL_OLD_2
#define MSG_TYPE_PAPER_SCROLL_OLD_2
Definition: newclient.h:460
MSG_TYPE_PAPER_NOTE_2
#define MSG_TYPE_PAPER_NOTE_2
Definition: newclient.h:451
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
god_info_msg
static StringBuffer * god_info_msg(int level, size_t booksize, object *book)
Definition: readable.cpp:1859
add_abilities
void add_abilities(object *op, const object *change)
Definition: artifact.cpp:329
AMULET
@ AMULET
Definition: object.h:142
MSG_TYPE_PAPER_LETTER_OLD_1
#define MSG_TYPE_PAPER_LETTER_OLD_1
Definition: newclient.h:453
strtoktolin
char * strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size)
Definition: readable.cpp:680
MSG_TYPE_SIGN_DIR_RIGHT
#define MSG_TYPE_SIGN_DIR_RIGHT
Definition: newclient.h:468
recipestruct::title
sstring title
Definition: recipe.h:11
mon
object * mon
Definition: comet_perf.cpp:75
gods_author
static const char *const gods_author[]
Definition: readable.cpp:310
MSG_TYPE_CARD_SIMPLE_2
#define MSG_TYPE_CARD_SIMPLE_2
Definition: newclient.h:437
SKILL
@ SKILL
Definition: object.h:146
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
artifactliststruct::items
struct artifactstruct * items
Definition: artifact.h:30
Ice.tmp
int tmp
Definition: Ice.py:207
MSG_TYPE_BOOK_CLASP_2
#define MSG_TYPE_BOOK_CLASP_2
Definition: newclient.h:424
MSG_TYPE_CARD
#define MSG_TYPE_CARD
Definition: newclient.h:396
obj::msg
sstring msg
Definition: object.h:328
prayers
int prayers
Definition: readable.cpp:1606
booksize
size_t booksize
Definition: readable.cpp:1610
MSGTYPE_MONSTER
#define MSGTYPE_MONSTER
Definition: readable.cpp:81
MSG_TYPE_BOOK_ELEGANT_1
#define MSG_TYPE_BOOK_ELEGANT_1
Definition: newclient.h:425
titlestruct::archname
const char * archname
Definition: readable.cpp:111
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4339
GOD_BLESSED
#define GOD_BLESSED
Definition: god.h:17
arttypename
struct namebytype arttypename
buf
StringBuffer * buf
Definition: readable.cpp:1611
getManager
AssetsManager * getManager()
Definition: assets.cpp:309
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2851
recipestruct::chance
int chance
Definition: recipe.h:14
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
PATH_ABJURE
#define PATH_ABJURE
Definition: spells.h:20
readable_message_types
static const readable_message_type readable_message_types[]
Definition: readable.cpp:471
GOD_HOLYWORD
#define GOD_HOLYWORD
Definition: god.h:14
linked_char
Definition: global.h:89
find_title
static title * find_title(const object *book, int msgtype)
Definition: readable.cpp:935
get_next_mon
static object * get_next_mon(const object *tmp)
Definition: readable.cpp:1350
archt
Definition: object.h:472
MSG_TYPE_PAPER_SCROLL_OLD_1
#define MSG_TYPE_PAPER_SCROLL_OLD_1
Definition: newclient.h:459
need_to_write_bookarchive
static int need_to_write_bookarchive
Definition: readable.cpp:145
MSG_TYPE_CARD_STRANGE_1
#define MSG_TYPE_CARD_STRANGE_1
Definition: newclient.h:442
PATH_MISSILE
#define PATH_MISSILE
Definition: spells.h:17
recipestruct
Definition: recipe.h:10
titlestruct::level
unsigned int level
Definition: readable.cpp:112
CLOAK
@ CLOAK
Definition: object.h:207
Messages::random
GeneralMessage * random()
Definition: Messages.cpp:50
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
MSGTYPE_MSGFILE
#define MSGTYPE_MSGFILE
Definition: readable.cpp:91
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1560
add_author
static void add_author(object *op, int msgtype)
Definition: readable.cpp:1023
titlelist
struct titleliststruct titlelist
HELMET
@ HELMET
Definition: object.h:139
artifactstruct::chance
uint16_t chance
Definition: artifact.h:16
get_rand_god
const object * get_rand_god(void)
Definition: holy.cpp:75
titlestruct
Definition: readable.cpp:108
oblnk::next
struct oblnk * next
Definition: object.h:451
recipeliststruct::total_chance
int total_chance
Definition: recipe.h:38
obj::name
sstring name
Definition: object.h:317
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
titleliststruct::first_book
struct titlestruct * first_book
Definition: readable.cpp:123
MSG_TYPE_CARD_STRANGE_2
#define MSG_TYPE_CARD_STRANGE_2
Definition: newclient.h:443
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:585
MSG_TYPE_SIGN_DIR_BOTH
#define MSG_TYPE_SIGN_DIR_BOTH
Definition: newclient.h:469
MSG_TYPE_MONUMENT_GRAVESTONE_2
#define MSG_TYPE_MONUMENT_GRAVESTONE_2
Definition: newclient.h:480
get_titlelist
static titlelist * get_titlelist(int i)
Definition: readable.cpp:607
PATH_DETONATE
#define PATH_DETONATE
Definition: spells.h:22
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.cpp:85
MSG_TYPE_SIGN_DIR_LEFT
#define MSG_TYPE_SIGN_DIR_LEFT
Definition: newclient.h:467
artifactstruct::next
struct artifactstruct * next
Definition: artifact.h:18
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
MSG_TYPE_BOOK_CLASP_1
#define MSG_TYPE_BOOK_CLASP_1
Definition: newclient.h:423
recipestruct::cauldron
sstring cauldron
Definition: recipe.h:27
titlestruct::size
size_t size
Definition: readable.cpp:113
book_descrpt
static const char *const book_descrpt[]
Definition: readable.cpp:444
ROD
@ ROD
Definition: object.h:112
recipestruct::arch_name
char ** arch_name
Definition: recipe.h:13
init_readable
void init_readable(void)
Definition: readable.cpp:904
python_init.path
path
Definition: python_init.py:8
done
int done
Definition: readable.cpp:1612
namebytype::name
const char * name
Definition: readable.cpp:129
init_book_archive
static void init_book_archive(void)
Definition: readable.cpp:729
tailor_readable_ob
void tailor_readable_ob(object *book, int msg_type)
Definition: readable.cpp:1929
spellpath_msg
static StringBuffer * spellpath_msg(int level, size_t booksize, StringBuffer *buf)
Definition: readable.cpp:1648
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Definition: global.h:204
MSG_TYPE_MONUMENT_STATUE_2
#define MSG_TYPE_MONUMENT_STATUE_2
Definition: newclient.h:477
add_book_to_list
static void add_book_to_list(const object *book, int msgtype)
Definition: readable.cpp:1095
PATH_SUMMON
#define PATH_SUMMON
Definition: spells.h:19
MSG_TYPE_CARD_ELEGANT_1
#define MSG_TYPE_CARD_ELEGANT_1
Definition: newclient.h:439
artifactstruct::allowed_size
int allowed_size
Definition: artifact.h:20
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:299
book.h
MAX_TITLE_CHECK
#define MAX_TITLE_CHECK
Definition: readable.cpp:76
artifactliststruct
Definition: artifact.h:26
sstring
const typedef char * sstring
Definition: global.h:43
PATH_TRANSFER
#define PATH_TRANSFER
Definition: spells.h:28
disinfect.count
int count
Definition: disinfect.py:7
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
MSG_TYPE_CARD_ELEGANT_3
#define MSG_TYPE_CARD_ELEGANT_3
Definition: newclient.h:441
artifact_describe
static StringBuffer * artifact_describe(const artifact *art, const artifactlist *al, int message, int art_name, int separator)
Definition: readable.cpp:1435
PATH_FROST
#define PATH_FROST
Definition: spells.h:15
MSG_TYPE_CARD_MONEY_3
#define MSG_TYPE_CARD_MONEY_3
Definition: newclient.h:447
MSG_TYPE_BOOK_SPELL_EVOKER
#define MSG_TYPE_BOOK_SPELL_EVOKER
Definition: newclient.h:429
ARROW
@ ARROW
Definition: object.h:120
MSG_TYPE_MONUMENT_GRAVESTONE_3
#define MSG_TYPE_MONUMENT_GRAVESTONE_3
Definition: newclient.h:481
get_message_body
sstring get_message_body(const GeneralMessage *message)
Definition: readable.cpp:2119
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.cpp:95
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:117
trim
const char * trim(const char *buf)
Definition: readable.cpp:657
MSG_TYPE_PAPER_ENVELOPE_2
#define MSG_TYPE_PAPER_ENVELOPE_2
Definition: newclient.h:458
MSG_TYPE_CARD_ELEGANT_2
#define MSG_TYPE_CARD_ELEGANT_2
Definition: newclient.h:440
MSG_TYPE_PAPER_NOTE_1
#define MSG_TYPE_PAPER_NOTE_1
Definition: newclient.h:450
RING
@ RING
Definition: object.h:188
MSG_TYPE_BOOK_SPELL_SORCERER
#define MSG_TYPE_BOOK_SPELL_SORCERER
Definition: newclient.h:432
MSG_TYPE_BOOK_SPELL_PYRO
#define MSG_TYPE_BOOK_SPELL_PYRO
Definition: newclient.h:431
PATH_TRANSMUTE
#define PATH_TRANSMUTE
Definition: spells.h:27
MSGTYPE_GODS
#define MSGTYPE_GODS
Definition: readable.cpp:89
MSG_TYPE_SIGN_MAGIC_MOUTH
#define MSG_TYPE_SIGN_MAGIC_MOUTH
Definition: newclient.h:470
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
recipestruct::ingred
linked_char * ingred
Definition: recipe.h:22
guild_entry.text
text
Definition: guild_entry.py:44
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:580
mon_desc
static StringBuffer * mon_desc(const object *mon)
Definition: readable.cpp:1332
MAX_BUF
#define MAX_BUF
Definition: define.h:35
artifactstruct
Definition: artifact.h:14
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.cpp:222
object_new
object * object_new(void)
Definition: object.cpp:1273
describe_item
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Definition: item.cpp:941
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:279
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
obj::next
struct obj * next
Definition: object.h:283
RANDOM
#define RANDOM()
Definition: define.h:644
titleliststruct::number
int number
Definition: readable.cpp:122
titlestruct::authour
const char * authour
Definition: readable.cpp:110
StringBuffer
Definition: stringbuffer.cpp:25
recipestruct::skill
sstring skill
Definition: recipe.h:26
PATH_DEATH
#define PATH_DEATH
Definition: spells.h:31
art_book_name
static const char *const art_book_name[]
Definition: readable.cpp:228
GOD_RESISTANCES
#define GOD_RESISTANCES
Definition: god.h:15
obj::title
sstring title
Definition: object.h:323
obj::arch
struct archt * arch
Definition: object.h:420
MSG_TYPE_CARD_MONEY_1
#define MSG_TYPE_CARD_MONEY_1
Definition: newclient.h:445
diamondslots.message
string message
Definition: diamondslots.py:57
PATH_TELE
#define PATH_TELE
Definition: spells.h:25
llevInfo
@ llevInfo
Definition: logger.h:12
obj::type
uint8_t type
Definition: object.h:346
Floor.t
t
Definition: Floor.py:62
titlestruct::next
struct titlestruct * next
Definition: readable.cpp:115
find_archetype_by_object_name
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.cpp:53
MSG_TYPE_PAPER_ENVELOPE_1
#define MSG_TYPE_PAPER_ENVELOPE_1
Definition: newclient.h:457
spells.h
obj::stats
living stats
Definition: object.h:376
get_message_title
sstring get_message_title(const GeneralMessage *message)
Definition: readable.cpp:2110
archt::clone
object clone
Definition: object.h:476
did_first_sp
int did_first_sp
Definition: readable.cpp:1607
MSGTYPE_LIB
#define MSGTYPE_LIB
Definition: readable.cpp:79
MSG_TYPE_CARD_SIMPLE_3
#define MSG_TYPE_CARD_SIMPLE_3
Definition: newclient.h:438
spellpathdef
static const uint32_t spellpathdef[NRSPELLPATHS]
Definition: readable.cpp:150
obj::weight
int32_t weight
Definition: object.h:373
stringbuffer_delete
void stringbuffer_delete(StringBuffer *sb)
Definition: stringbuffer.cpp:71
msgfile_msg
static StringBuffer * msgfile_msg(object *book, size_t booksize)
Definition: readable.cpp:1816
PATH_PROT
#define PATH_PROT
Definition: spells.h:13
MSGTYPE_ALCHEMY
#define MSGTYPE_ALCHEMY
Definition: readable.cpp:87
liv::grace
int16_t grace
Definition: living.h:44
MSG_TYPE_PAPER_LETTER_NEW_1
#define MSG_TYPE_PAPER_LETTER_NEW_1
Definition: newclient.h:455
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:270
MSG_TYPE_BOOK_ELEGANT_2
#define MSG_TYPE_BOOK_ELEGANT_2
Definition: newclient.h:426
strtoint
int strtoint(const char *buf)
Definition: recipe.cpp:710
GOD_ENEMY
#define GOD_ENEMY
Definition: god.h:13
PATH_MIND
#define PATH_MIND
Definition: spells.h:23
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.cpp:4804
BOOK_BUF
#define BOOK_BUF
Definition: book.h:16
oblnk::ob
object * ob
Definition: object.h:450
assets.h
MSGTYPE_ARTIFACT
#define MSGTYPE_ARTIFACT
Definition: readable.cpp:83
npc_dialog.index
int index
Definition: npc_dialog.py:102
do_monster
static void do_monster(archetype *at)
Definition: readable.cpp:865
art_name_array
static const arttypename art_name_array[]
Definition: readable.cpp:208
titlestruct::name
const char * name
Definition: readable.cpp:109
recipestruct::next
struct recipestruct * next
Definition: recipe.h:24
MSG_TYPE_MONUMENT_STONE_2
#define MSG_TYPE_MONUMENT_STONE_2
Definition: newclient.h:474
stringbuffer_append_stringbuffer
void stringbuffer_append_stringbuffer(StringBuffer *sb, const StringBuffer *sb2)
Definition: stringbuffer.cpp:165
new_text_name
static void new_text_name(object *book, int msgtype)
Definition: readable.cpp:974
obj::subtype
uint8_t subtype
Definition: object.h:347
heavy_book_name
static const char *const heavy_book_name[]
Definition: readable.cpp:383
level
int level
Definition: readable.cpp:1609
titleliststruct
Definition: readable.cpp:121
MSGTYPE_SPELLPATH
#define MSGTYPE_SPELLPATH
Definition: readable.cpp:85
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
formula_author
static const char *const formula_author[]
Definition: readable.cpp:342
booklist
static titlelist * booklist
Definition: readable.cpp:139
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
get_readable_message_type
const readable_message_type * get_readable_message_type(object *readable)
Definition: readable.cpp:2097
art_author
static const char *const art_author[]
Definition: readable.cpp:244
last_readable_subtype
static const int last_readable_subtype
Definition: readable.cpp:535
recipeliststruct::items
struct recipestruct * items
Definition: recipe.h:40
get_random_mon
object * get_random_mon(int level)
Definition: readable.cpp:1269
book_overflow
int book_overflow(const char *buf1, const char *buf2, size_t booksize)
Definition: readable.cpp:710
FOOD
@ FOOD
Definition: object.h:115
namebytype::type
int type
Definition: readable.cpp:130
recipestruct::index
int index
Definition: recipe.h:18
nrofmon
static int nrofmon
Definition: readable.cpp:144
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:274
animate.event
event
DIALOGCHECK MINARGS 1 MAXARGS 2
Definition: animate.py:17
mon_info_msg
static StringBuffer * mon_info_msg(int level, size_t booksize, object *book)
Definition: readable.cpp:1378
unique_book
static int unique_book(const object *book, int msgtype)
Definition: readable.cpp:1071
MSG_TYPE_CARD_SIMPLE_1
#define MSG_TYPE_CARD_SIMPLE_1
Definition: newclient.h:436
light_book_name
static const char *const light_book_name[]
Definition: readable.cpp:364
archt::name
sstring name
Definition: object.h:473
MSG_TYPE_MONUMENT_STONE_1
#define MSG_TYPE_MONUMENT_STONE_1
Definition: newclient.h:473
MSG_TYPE_SIGN
#define MSG_TYPE_SIGN
Definition: newclient.h:398
titleliststruct::next
struct titleliststruct * next
Definition: readable.cpp:124
first_mon_info
static objectlink * first_mon_info
Definition: readable.cpp:142
MSG_TYPE_BOOK
#define MSG_TYPE_BOOK
Definition: newclient.h:395
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.cpp:4492
buf_overflow
int buf_overflow(const char *buf1, const char *buf2, size_t bufsize)
Definition: shstr.cpp:398
describe_god
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Definition: holy.cpp:111
add_book
static void add_book(title *book, int type, const char *fname, int lineno)
Definition: readable.cpp:851
oblnk
Definition: object.h:449
MSG_TYPE_PAPER_SCROLL_MAGIC
#define MSG_TYPE_PAPER_SCROLL_MAGIC
Definition: newclient.h:463
BOOTS
@ BOOTS
Definition: object.h:215
make_formula_book
static void make_formula_book(object *book, int level)
Definition: readable.cpp:1688
FLAG_CHANGING
#define FLAG_CHANGING
Definition: define.h:263
SPELL
@ SPELL
Definition: object.h:217
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
sp_params
static struct @0 sp_params
title
struct titlestruct title
guildbuy.temp
def temp
Definition: guildbuy.py:26
SHIELD
@ SHIELD
Definition: object.h:138
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
BOOKSIZE
#define BOOKSIZE(xyz)
Definition: book.h:31
max_titles
static const int max_titles[6]
Definition: readable.cpp:538
nstrtok
int nstrtok(const char *buf1, const char *buf2)
Definition: readable.cpp:638
artifactliststruct::type
uint8_t type
Definition: artifact.h:27
living.h
find_artifactlist
artifactlist * find_artifactlist(int type)
Definition: artifact.cpp:575
MSG_TYPE_CARD_STRANGE_3
#define MSG_TYPE_CARD_STRANGE_3
Definition: newclient.h:444
get_message_face
const Face * get_message_face(const GeneralMessage *message)
Definition: readable.cpp:2128
pnum
uint32_t pnum
Definition: readable.cpp:1608
obj::level
int16_t level
Definition: object.h:359
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
OutputFile
Definition: output_file.h:41
level
Definition: level.py:1
Settings::localdir
const char * localdir
Definition: global.h:249