Crossfire Server, Trunk
knowledge.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 
58 #include "global.h"
59 
60 #include <assert.h>
61 #include <ctype.h>
62 #include <stdlib.h>
63 #include <string.h>
64 
65 #include "sproto.h"
66 #include "output_file.h"
67 
68 /* Media tags for information messages prefix. */
69 #define TAG_START "[color=#ff6611]"
70 #define TAG_END "[/color]"
71 
72 struct knowledge_player;
73 struct knowledge_type;
74 
80 typedef void (*knowledge_summary)(const char *code, StringBuffer *buf);
81 
87 typedef void (*knowledge_detail)(const char *code, StringBuffer *buf);
88 
94 typedef int (*knowledge_is_valid_item)(const char *code);
95 
103 typedef int (*knowledge_add_item)(struct knowledge_player *current, const char *item, const struct knowledge_type *type);
104 
113 typedef StringBuffer* (*knowledge_can_use_alchemy)(sstring code, const char *item, StringBuffer *buf, int index);
114 
120 typedef const Face *(*knowledge_face)(sstring code);
121 
122 struct knowledge_item;
123 
129 typedef void (*knowledge_attempt)(player *pl, const struct knowledge_item *item);
130 
132 typedef struct knowledge_type {
133  const char *type;
138  const char *name;
141  const char *face;
144 
145 
147 typedef struct knowledge_item {
151 
153 typedef struct knowledge_player {
162 
165 
166 
172 static const recipe* knowledge_alchemy_get_recipe(const char *value) {
173  const recipe *rec;
174  recipelist *rl;
175  int count, index;
176  const char *dot;
177 
178  dot = strchr(value, ':');
179  if (!dot) {
180  /* warn? */
181  return NULL;
182  }
183 
184  count = atoi(value);
185  index = atoi(dot + 1);
186  dot = strchr(dot + 1, ':');
187  if (!dot)
188  /* warn? */
189  return NULL;
190  dot++;
191 
192  rl = get_formulalist(count);
193  rec = rl->items;
194  while (rec) {
195  if (rec->index == index && strcmp(rec->title, dot) == 0)
196  return rec;
197 
198  rec = rec->next;
199  }
200 
201  return NULL;
202 }
203 
210 static void knowledge_alchemy_summary(const char *value, StringBuffer *buf) {
212  const archetype *arch;
213 
214  if (!rec)
215  /* warn? */
216  return;
217 
219  if (!arch)
220  /* not supposed to happen */
221  return;
222 
223  if (strcmp(rec->title, "NONE"))
224  stringbuffer_append_printf(buf, "%s of %s", arch->clone.name, rec->title);
225  else {
226  if (arch->clone.title != NULL) {
227  stringbuffer_append_printf(buf, "%s %s", arch->clone.name, arch->clone.title);
228  }
229  else
230  stringbuffer_append_printf(buf, "%s", arch->clone.name);
231  }
232 }
233 
240 static void knowledge_alchemy_detail(const char *value, StringBuffer *buf) {
242  const linked_char *next;
243  const archetype *arch;
244  char name[MAX_BUF];
245 
246 
247  if (!rec)
248  /* warn? */
249  return;
250 
252  if (!arch)
253  /* not supposed to happen */
254  return;
255 
256  if (strcmp(rec->title, "NONE"))
257  stringbuffer_append_printf(buf, "The %s of %s", arch->clone.name, rec->title);
258  else {
259  if (arch->clone.title != NULL) {
260  stringbuffer_append_printf(buf, "The %s %s", arch->clone.name, arch->clone.title);
261  }
262  else
263  stringbuffer_append_printf(buf, "The %s", arch->clone.name);
264  }
265 
267  if (arch)
268  query_name(&arch->clone, name, MAX_BUF);
269  else
270  snprintf(name, sizeof(name), "an unknown place");
271 
272  stringbuffer_append_printf(buf, " is made with %s at %s and uses the following ingredients:", rec->skill ? rec->skill : "an unknown skill", name);
273 
274  for (next = rec->ingred; next != NULL; next = next->next) {
275  stringbuffer_append_printf(buf, "\n - %s", next->name);
276  }
277 
278 }
279 
285 static int knowledge_alchemy_validate(const char *item) {
286  return knowledge_alchemy_get_recipe(item) != NULL;
287 }
288 
298  const recipe *rec = knowledge_alchemy_get_recipe(code);
299  const linked_char *next;
300  const archetype *arch;
301  const char *name;
302 
303  if (!rec)
304  /* warn? */
305  return buf;
306 
308  if (!arch)
309  /* not supposed to happen */
310  return buf;
311 
312  for (next = rec->ingred; next != NULL; next = next->next) {
313  name = next->name;
314  while ((*name) != '\0' && (isdigit(*name) || (*name) == ' '))
315  name++;
316 
317  if (strcmp(item, name) == 0) {
318  if (buf == NULL) {
319  buf = stringbuffer_new();
320  stringbuffer_append_string(buf, "It can be used in the following recipes: ");
321  } else
323 
324  if (strcmp(rec->title, "NONE"))
325  stringbuffer_append_printf(buf, "%s of %s", arch->clone.name, rec->title);
326  else {
327  if (arch->clone.title != NULL) {
328  stringbuffer_append_printf(buf, "%s %s", arch->clone.name, arch->clone.title);
329  }
330  else
331  stringbuffer_append_printf(buf, "%s", arch->clone.name);
332  }
334 
335  break;
336  }
337  }
338 
339  return buf;
340 }
341 
348  const recipe *rp = knowledge_alchemy_get_recipe(item->item);
349  object *cauldron = NULL, *inv;
350  object *ingredients[50];
351  int index, x, y;
352  uint32_t count, counts[50];
353  char name[MAX_BUF];
354  const char *ingname;
355  linked_char *ing;
356  tag_t cauldron_tag;
357  mapstruct *map;
358 
359  if (!rp) {
360  LOG(llevError, "knowledge: couldn't find recipe for %s", item->item);
361  return;
362  }
363 
364  if (rp->ingred_count > 50) {
365  LOG(llevError, "knowledge: recipe %s has more than 50 ingredients!", item->item);
366  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "This recipe is too complicated.");
367  return;
368  }
369 
370  /* first, check for a cauldron */
371  for (cauldron = pl->ob->below; cauldron; cauldron = cauldron->below) {
372  if (strcmp(rp->cauldron, cauldron->arch->name) == 0)
373  break;
374  }
375 
376  if (cauldron == NULL) {
378  return;
379  }
380 
381  cauldron_tag = cauldron->count;
382 
383  /* find ingredients in player's inventory */
384  for (index = 0; index < 50; index++) {
385  ingredients[index] = NULL;
386  }
387  for (inv = pl->ob->inv; inv != NULL; inv = inv->below) {
388 
390  continue;
391 
392  if (inv->title == NULL)
393  safe_strncpy(name, inv->name, sizeof(name));
394  else
395  snprintf(name, sizeof(name), "%s %s", inv->name, inv->title);
396 
397  index = 0;
398  for (ing = rp->ingred; ing != NULL; ing = ing->next) {
399 
400  if (ingredients[index] != NULL) {
401  index++;
402  continue;
403  }
404 
405  ingname = ing->name;
406  count = 0;
407  while (isdigit(*ingname)) {
408  count = 10 * count + (*ingname - '0');
409  ingname++;
410  }
411  if (count == 0)
412  count = 1;
413  while (*ingname == ' ')
414  ingname++;
415 
416  if (strcmp(name, ingname) == 0 && ((inv->nrof == 0 && count == 1) || (inv->nrof >= count))) {
417  ingredients[index] = inv;
418  // If nrof is 0, we want to keep a count of 0 so put_object_in_sack() later doesn't call
419  // object_split() which would destroy tmp and mess up our tags.
420  counts[index] = inv->nrof == 0 ? 0 : count;
421  break;
422  }
423 
424  index++;
425  }
426  }
427 
428  index = 0;
429  for (ing = rp->ingred; ing != NULL; ing = ing->next) {
430  if (ingredients[index] == NULL) {
431  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "You don't have %s.", ing->name);
432  return;
433  }
434 
435  index++;
436  }
437 
438  /* ensure cauldron is applied */
439  if (pl->ob->container != cauldron) {
441  if (pl->ob->container != cauldron) {
442  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Couldn't activate the %s.", rp->cauldron);
443  return;
444  }
445  }
446 
447  /* ensure cauldron is empty */
448  while (cauldron->inv != NULL) {
449  inv = cauldron->inv;
450  command_take(pl->ob, "");
451  if (cauldron->inv == inv) {
453  return;
454  }
455  }
456 
457  /* drop ingredients */
458  for (index = 0; index < rp->ingred_count; index++) {
459  tag_t tag = ingredients[index]->count;
460  count = ingredients[index]->nrof;
461  put_object_in_sack(pl->ob, cauldron, ingredients[index], counts[index]);
462  if (object_was_destroyed(ingredients[index], tag)) {
463  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Hum, some item disappeared, stopping the attempt.");
464  return;
465 
466  }
467  if (count == ingredients[index]->nrof && ingredients[index]->env == pl->ob) {
468  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Hum, couldn't drop some items, stopping the attempt.");
469  return;
470  }
471  }
472 
473  map = pl->ob->map;
474  x = pl->ob->x;
475  y = pl->ob->y;
476 
477  /* do alchemy */
478  use_alchemy(pl->ob);
479 
480  /* don't forget to slow the player: 1 for alchemy itself, 1 for each ingredient put,
481  * ingredients taken are handled by command_take() */
482  pl->ob->speed_left -= 1.0 * (rp->ingred_count + 1);
483 
484  /* safety: ensure cauldron is still there, and player is still above */
485  if (object_was_destroyed(cauldron, cauldron_tag) || map != pl->ob->map || x != pl->ob->x || y != pl->ob->y) {
486  return;
487  }
488 
489  /* get back the result */
490  while (cauldron->inv) {
491  /* Examining may lead to identifying part of items and thus introducing
492  * extra items in the cauldron. Therefore we'll set inv only after examining,
493  * even if that means that potentially the player will examine twice some items. */
494  examine(pl->ob, cauldron->inv);
495  inv = cauldron->inv;
496  command_take(pl->ob, "");
497  pl->ob->speed_left -= 1.0;
498  if (inv == cauldron->inv)
499  break;
500  }
501 }
502 
508 static const Face *knowledge_alchemy_face(sstring code) {
509  const recipe *rp = knowledge_alchemy_get_recipe(code);
510 
511  if (!rp) {
512  LOG(llevError, "knowledge: couldn't find recipe for %s", code);
513  return NULL;
514  }
515 
516  return recipe_get_face(rp);
517 }
518 
526 static int knowledge_known(const knowledge_player *current, const char *item, const knowledge_type *kt) {
527  int i;
528  for (i = 0; i < current->item_count; i++) {
529  if (strcmp(kt->type, current->items[i]->handler->type) == 0 && strcmp(item, current->items[i]->item) == 0) {
530  /* already known, bailout */
531  return 1;
532  }
533  }
534  return 0;
535 }
536 
544 static int knowledge_add(knowledge_player *current, const char *item, const knowledge_type *kt) {
546 
547  if (knowledge_known(current, item, kt)) {
548  return 0;
549  }
550 
551  /* keep the knowledge */
556  check = malloc(sizeof(knowledge_item));
557  check->item = add_string(item);
558  check->handler = kt;
559  if (current->item_count >= current->item_allocated) {
560  current->item_allocated += 10;
561  current->items = realloc(current->items, current->item_allocated * sizeof(knowledge_item*));
562  }
563  current->items[current->item_count] = check;
564  current->item_count++;
565 
566  return 1;
567 }
568 
575 static void knowledge_monster_summary(const char *item, StringBuffer *buf) {
576  archetype *monster = try_find_archetype(item);
577  if (!monster)
578  return;
579 
580  stringbuffer_append_printf(buf, "%s", monster->clone.name);
581 }
582 
589 static void knowledge_monster_detail(const char *item, StringBuffer *buf) {
590  archetype *monster = try_find_archetype(item);
591 
592  if (!monster)
593  return;
594 
595  stringbuffer_append_printf(buf, " *** %s ***\n", monster->clone.name);
596  describe_item(&monster->clone, NULL, 1, buf);
597 }
598 
604 static int knowledge_monster_validate(const char *item) {
605  const archetype *monster = try_find_archetype(item);
606  if (monster == NULL || monster->clone.type != 0 || monster->head || object_get_value(&monster->clone, MONSTER_EXCLUDE_FROM_READABLE_KEY) != NULL)
607  return 0;
608  return 1;
609 }
610 
618 static int knowledge_monster_add(struct knowledge_player *current, const char *item, const struct knowledge_type *type) {
619  char *dup = strdup_local(item);
620  char *pos, *first = dup;
621  int added = 0;
622 
623  while (first) {
624  pos = strchr(first, ':');
625  if (pos)
626  *pos = '\0';
627  added += knowledge_add(current, first, type);
628  first = pos ? pos + 1 : NULL;
629  }
630 
631  free(dup);
632  return added;
633 }
634 
640 static const Face *knowledge_monster_face(sstring code) {
641  const archetype *monster = try_find_archetype(code);
642 
643  if (!monster || monster->clone.face == blank_face || monster->clone.face == NULL)
644  return NULL;
645 
646  return monster->clone.face;
647 }
648 
655 static void knowledge_god_summary(const char *item, StringBuffer *buf) {
656  char *dup = strdup_local(item), *pos = strchr(dup, ':');
657 
658  if (pos)
659  *pos = '\0';
660 
661  stringbuffer_append_printf(buf, "%s [god]", dup);
662  free(dup);
663 }
664 
671 static void knowledge_god_detail(const char *item, StringBuffer *buf) {
672  char *dup = strdup_local(item), *pos = strchr(dup, ':');
673  const archetype *god;
674  int what;
675 
676  if (!pos) {
677  LOG(llevError, "knowledge_god_detail: invalid god item %s\n", item);
678  free(dup);
679  return;
680  }
681 
682  *pos = '\0';
683  what = atoi(pos + 1);
685  free(dup);
686 
687  if (!god) {
688  LOG(llevError, "knowledge_god_detail: couldn't find god %s?\n", item);
689  return;
690  }
691 
692  describe_god(&god->clone, what, buf, 0);
693 }
694 
700 static int knowledge_god_validate(const char *item) {
701  char *dup = strdup_local(item), *pos = strchr(dup, ':');
702  int valid;
703 
704  if (!pos) {
705  LOG(llevError, "knowledge_god_validate: invalid god item %s\n", item);
706  free(dup);
707  return 0;
708  }
709  *pos = '\0';
710  valid = find_archetype_by_object_name(dup) != NULL;
711  free(dup);
712  return valid;
713 }
714 
722 static int knowledge_god_add(struct knowledge_player *current, const char *item, const struct knowledge_type *type) {
723  char *dup = strdup_local(item), *pos = strchr(dup, ':');
724  StringBuffer *buf;
725  int what, i;
727 
728  if (!pos) {
729  LOG(llevError, "knowledge_god_add: invalid god item %s\n", item);
730  free(dup);
731  return 0;
732  }
733 
734  *pos = '\0';
735  what = atoi(pos + 1);
736 
737  for (i = 0; i < current->item_count; i++) {
738  check = current->items[i];
739  if (check->handler != type)
740  /* Only consider our own type. */
741  continue;
742  if (strncmp(check->item, dup, strlen(dup)) == 0) {
743  /* Already known, update information. */
744  int known, result;
745  pos = strchr(check->item, ':');
746  known = atoi(pos + 1);
747  result = known | what;
748  buf = stringbuffer_new();
749  stringbuffer_append_printf(buf, "%s:%d", dup, result);
750  free_string(check->item);
752  free(dup);
753  return (result != known);
754  }
755  }
756 
757  free(dup);
758 
759  /* Not known, so just add it regularly. */
760  return knowledge_add(current, item, type);
761 }
762 
768 static const Face *knowledge_god_face(sstring code) {
769  char buf[MAX_BUF];
770  size_t letter;
771  const archetype *altar_arch;
772 
773  snprintf(buf, MAX_BUF, "altar_");
774  letter = strlen(buf);
775  strncpy(buf+letter, code, MAX_BUF-letter);
776  for (; letter < strlen(buf); letter++) {
777  if (buf[letter] == ':') {
778  buf[letter] = '\0';
779  break;
780  }
781  buf[letter] = tolower(buf[letter]);
782  }
783  altar_arch = try_find_archetype(buf);
784  if (altar_arch == NULL)
785  return NULL;
786 
787  return altar_arch->clone.face;
788 }
789 
796 static void knowledge_message_summary(const char *value, StringBuffer *buf) {
798 
799  if (!msg)
800  /* warn? */
801  return;
802 
804 }
805 
812 static void knowledge_message_detail(const char *value, StringBuffer *buf) {
814 
815  if (!msg)
816  /* warn? */
817  return;
818 
820 }
821 
827 static int knowledge_message_validate(const char *item) {
828  return get_message_from_identifier(item) != NULL;
829 }
830 
836 static const Face *knowledge_message_face(sstring code) {
838 
839  if (!msg)
840  /* warn? */
841  return NULL;
842 
843  return get_message_face(msg);
844 }
845 
847 static const knowledge_type knowledges[] = {
849  { "monster", knowledge_monster_summary, knowledge_monster_detail, knowledge_monster_validate, knowledge_monster_add, "monsters", NULL, NULL, "knowledge_monsters.111", knowledge_monster_face },
850  { "god", knowledge_god_summary, knowledge_god_detail, knowledge_god_validate, knowledge_god_add, "gods", NULL, NULL, "knowledge_gods.111", knowledge_god_face },
851  { "message", knowledge_message_summary, knowledge_message_detail, knowledge_message_validate, knowledge_add, "messages", NULL, NULL, "knowledge_messages.111", knowledge_message_face },
852  { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
853 };
854 
855 
861 static const knowledge_type *knowledge_find(const char *type) {
862  int i = 0;
863  while (knowledges[i].type != NULL) {
864  if (strcmp(knowledges[i].type, type) == 0)
865  return &knowledges[i];
866  i++;
867  }
868 
869  return NULL;
870 }
871 
877  FILE *file;
878  OutputFile of;
879  char fname[MAX_BUF];
880  const knowledge_item *item;
881  int i;
882 
883  snprintf(fname, sizeof(fname), "%s/%s/%s/%s.knowledge", settings.localdir, settings.playerdir, kp->player_name, kp->player_name);
884 
885  file = of_open(&of, fname);
886  if (!file) {
887  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
888  return;
889  }
890 
891  for (i = 0; i < kp->item_count; i++) {
892  item = kp->items[i];
893  fprintf(file, "%s:%s\n", item->handler->type, item->item);
894  }
895 
896  if (!of_close(&of)) {
897  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
898  return;
899  }
901 }
902 
908  FILE *file;
909  char final[MAX_BUF], read[MAX_BUF], *dot;
911  const knowledge_type *type;
912 
913  snprintf(final, sizeof(final), "%s/%s/%s/%s.knowledge", settings.localdir, settings.playerdir, kp->player_name, kp->player_name);
914 
915  file = fopen(final, "r");
916  if (!file) {
917  /* no knowledge yet, no big deal */
918  return;
919  }
920 
921  while (fgets(read, sizeof(read), file) != NULL) {
922  if (strlen(read) > 0)
923  read[strlen(read) - 1] = '\0';
924 
925  dot = strchr(read, ':');
926  if (!dot) {
927  LOG(llevError, "knowledge: invalid line in file %s\n", final);
928  continue;
929  }
930 
931  *dot = '\0';
932 
933  type = knowledge_find(read);
934  if (!type) {
935  LOG(llevError, "knowledge: invalid type %s in file %s\n", read, final);
936  continue;
937  }
938  if (!type->validate(dot + 1)) {
939  LOG(llevDebug, "knowledge: ignoring now invalid %s in file %s\n", read, final);
940  continue;
941  }
942 
943  item = malloc(sizeof(knowledge_item));
944  item->item = add_string(dot + 1);
945  item->handler = type;
946  if (kp->item_count == kp->item_allocated) {
947  kp->item_allocated += 10;
948  kp->items = realloc(kp->items, kp->item_allocated * sizeof(knowledge_item*));
949  }
950  kp->items[kp->item_count] = item;
951  kp->item_count++;
952  }
953  fclose(file);
954 }
955 
964 
965  while (cur) {
966  if (cur->player_name == pl->ob->name)
967  return cur;
968  cur = cur->next;
969  }
970 
971  cur = calloc(1, sizeof(knowledge_player));
972  if (!cur)
974  cur->player_name = add_refcount(pl->ob->name);
975  cur->next = knowledge_global;
976  knowledge_global = cur;
977  /* read knowledge for this player */
979  if (pl->socket.notifications < 2)
980  cur->sent_up_to = -1;
981  return cur;
982 }
983 
990 void knowledge_give(player *pl, const char *marker, const object *book) {
991  char *dot, *copy, *code;
992  const knowledge_type *type;
993  int none, added = 0;
995 
996  /* process marker, find if already known */
997  dot = strchr(marker, ':');
998  if (dot == NULL)
999  return;
1000 
1001  copy = strdup(marker);
1002  if (!copy)
1004 
1005  dot = strchr(copy, ':');
1006  *dot = '\0';
1007  dot++;
1008 
1009  type = knowledge_find(copy);
1010  if (!type) {
1011  LOG(llevError, "knowledge: invalid marker type %s in %s\n", copy, book == NULL ? "(null)" : book->name);
1012  free(copy);
1013  return;
1014  }
1015 
1016  none = (current->items == NULL);
1017 
1018  code = dot;
1019  while (code && code[0] != '\0') {
1020  dot = strchr(code, '/');
1021  if (dot) {
1022  *dot = '\0';
1023  dot++;
1024  }
1025  if (type->validate(code)) {
1026  added += type->add(current, code, type);
1027  }
1028  code = dot;
1029  }
1030 
1031  free(copy);
1032 
1033  if (added) {
1034  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, TAG_START "%s" TAG_END, "You keep that in mind for future reference.");
1035  if (none) {
1036  /* first information ever written down, be nice and give hint to recover it. */
1037  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, TAG_START "%s" TAG_END, "Use the 'knowledge' command to see what you keep in mind (this message will not appear anymore).");
1038  }
1039  }
1040 
1041  if (pl->has_directory)
1043 }
1044 
1050 void knowledge_read(player *pl, object *book) {
1051  sstring marker = object_get_value(book, "knowledge_marker");
1052  if (marker != NULL)
1053  knowledge_give(pl, marker, book);
1054 }
1055 
1062 static void knowledge_do_display(object *pl, const knowledge_type *show_only, const char *search) {
1063  knowledge_player *kp;
1065  int header = 0, show, i;
1066  StringBuffer *summary;
1067  char *final;
1068 
1069  assert(search == NULL || search[0] != '\0');
1070 
1071  kp = knowledge_get_or_create(pl->contr);
1072  for (i = 0; i < kp->item_count; i++) {
1073  item = kp->items[i];
1074  show = 1;
1075 
1076  summary = stringbuffer_new();
1077  item->handler->summary(item->item, summary);
1078  final = stringbuffer_finish(summary);
1079 
1080  if (show_only != NULL && item->handler != show_only) {
1081  show = 0;
1082  }
1083  if (search != NULL && search[0] != '\0') {
1084  if (strstr(final, search) == NULL) {
1085  char *fd;
1086  StringBuffer *detail = stringbuffer_new();
1087  item->handler->detail(item->item, detail);
1088  fd = stringbuffer_finish(detail);
1089  if (strstr(fd, search) == NULL)
1090  show = 0;
1091  free(fd);
1092  }
1093  }
1094 
1095  if (show == 1) {
1096  if (header == 0) {
1097  if (search != NULL)
1098  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You have knowledge of the following %s concerning '%s':", show_only == NULL ? "things" : show_only->type, search);
1099  else if (show_only != NULL)
1100  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You have knowledge of those %s:", show_only->name);
1101  else
1102  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You have knowledge of:");
1103  header = 1;
1104  }
1105 
1106  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "(%3d) %s", i + 1, final);
1107  }
1108 
1109  free(final);
1110  }
1111 
1112  if (header == 0) {
1113  if (search != NULL)
1114  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You don't know yet any relevant information about '%s'.", search);
1115  else if (show_only != NULL)
1116  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You don't know yet any relevant information about %s.", show_only->name);
1117  else
1118  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You don't know yet any relevant information.");
1119  }
1120 }
1121 
1127 static void knowledge_display(object *pl, const char *params) {
1128  const knowledge_type *show_only = NULL;
1129 
1130  if (params && params[0] == ' ') {
1131  const char *type = params + 1;
1132  int idx = 0;
1133  for (; knowledges[idx].type != NULL; idx++) {
1134  if (strcmp(knowledges[idx].name, type) == 0) {
1135  show_only = &knowledges[idx];
1136  break;
1137  }
1138  }
1139 
1140  if (show_only == NULL) {
1141  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "Invalid type, valid types are:");
1142  for (idx = 0; knowledges[idx].type != NULL; idx++) {
1144  }
1145  return;
1146  }
1147  }
1148 
1149  knowledge_do_display(pl, show_only, NULL);
1150 }
1151 
1157 static void knowledge_show(object *pl, const char *params) {
1158  knowledge_player *kp;
1160  int count = atoi(params) - 1;
1161  StringBuffer *buf;
1162  char *final;
1163 
1164  kp = knowledge_get_or_create(pl->contr);
1165  if (count < 0 || count >= kp->item_count) {
1166  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Invalid knowledge number");
1167  return;
1168  }
1169 
1170  item = kp->items[count];
1171  buf = stringbuffer_new();
1172  item->handler->detail(item->item, buf);
1173  final = stringbuffer_finish(buf);
1175  free(final);
1176 }
1177 
1183 static void knowledge_do_attempt(object *pl, const char *params) {
1184  knowledge_player *kp;
1186  int count = atoi(params) - 1;
1187 
1188  kp = knowledge_get_or_create(pl->contr);
1189  if (count < 0 || count >= kp->item_count) {
1190  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Invalid knowledge number");
1191  return;
1192  }
1193 
1194  item = kp->items[count];
1195  if (item->handler->attempt_alchemy == NULL) {
1196  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "You can't do anything with that knowledge.");
1197  } else {
1198  item->handler->attempt_alchemy(pl->contr, item);
1199  }
1200 }
1201 
1207 void command_knowledge(object *pl, const char *params) {
1208 
1209  if (!pl->contr) {
1210  LOG(llevError, "command_knowledge: called for %s not a player!\n", pl->name);
1211  return;
1212  }
1213 
1214  if (!params || *params == '\0') {
1215  command_help(pl, "knowledge");
1216  return;
1217  }
1218 
1219  if (strncmp(params, "list", 4) == 0) {
1220  knowledge_display(pl, params + 4);
1221  return;
1222  }
1223 
1224  if (strncmp(params, "search ", 7) == 0) {
1225  knowledge_do_display(pl, NULL, params + 7);
1226  return;
1227  }
1228 
1229  if (strncmp(params, "show ", 5) == 0) {
1230  knowledge_show(pl, params + 5);
1231  return;
1232  }
1233 
1234  if (strncmp(params, "attempt ", 8) == 0) {
1236  return;
1237  }
1238 
1239  command_help(pl, "knowledge");
1240 }
1241 
1248  int i;
1249 
1250  for (i = 0; i < kp->item_count; i++) {
1251  item = kp->items[i];
1252  free_string(item->item);
1253  free(item);
1254  }
1255  free(kp->items);
1256  kp->items = NULL;
1257  kp->item_count = 0;
1258  kp->item_allocated = 0;
1259 }
1260 
1267  free_string(kp->player_name);
1268  free(kp);
1269 }
1270 
1274 void free_knowledge(void) {
1275  knowledge_player *kp, *next;
1276 
1277  kp = knowledge_global;
1278  while (kp) {
1279  next = kp->next;
1281  kp = next;
1282  }
1283  knowledge_global = NULL;
1284 }
1285 
1292 int knowledge_player_knows(const player *pl, const char *knowledge) {
1293  const knowledge_type *type;
1294  char copy[MAX_BUF], *pos;
1295  const knowledge_player *current;
1296 
1297  if (strlen(knowledge) >= MAX_BUF - 1) {
1298  LOG(llevError, "knowledge_player_knows: too long knowledge %s\n", knowledge);
1299  return 0;
1300  }
1301 
1302  strlcpy(copy, knowledge, sizeof(copy));
1303  pos = strchr(copy, ':');
1304  if (pos == NULL) {
1305  LOG(llevError, "knowledge_player_knows: invalid knowledge item %s\n", knowledge);
1306  return 0;
1307  }
1308 
1309  *pos = '\0';
1310  pos++;
1311 
1312  type = knowledge_find(copy);
1313  if (type == NULL) {
1314  LOG(llevError, "knowledge_player_knows: invalid knowledge type %s\n", knowledge);
1315  return 0;
1316  }
1317 
1319 
1320  return knowledge_known(current, pos, type);
1321 }
1322 
1328 void knowledge_item_can_be_used_alchemy(object *op, const object *item) {
1329  knowledge_player *cur;
1330  knowledge_item *ki;
1331  char item_name[MAX_BUF], *result;
1332  const char *name;
1333  StringBuffer *buf = NULL;
1334  int i;
1335 
1336  if (op->type != PLAYER || op->contr == NULL)
1337  return;
1338 
1339  cur = knowledge_get_or_create(op->contr);
1340 
1341  if (item->title != NULL) {
1342  snprintf(item_name, sizeof(item_name), "%s %s", item->name, item->title);
1343  name = item_name;
1344  } else
1345  name = item->name;
1346 
1347  for (i = 0; i < cur->item_count; i++) {
1348  ki = cur->items[i];
1349  if (ki->handler->use_alchemy != NULL) {
1350  buf = ki->handler->use_alchemy(ki->item, name, buf, i + 1);
1351  }
1352  }
1353 
1354  if (buf == NULL)
1355  return;
1356 
1358  result = stringbuffer_finish(buf);
1360  result);
1361  free(result);
1362 }
1363 
1369  int i;
1370  const Face *face;
1371  SockList sl;
1372 
1373  face = try_find_face("knowledge_generic.111", NULL);
1374  if (face != NULL && (!(ns->faces_sent[face->number] & NS_FACESENT_FACE)))
1375  esrv_send_face(ns, face, 0);
1376 
1377  SockList_Init(&sl);
1378  SockList_AddString(&sl, "replyinfo knowledge_info\n");
1379  SockList_AddPrintf(&sl, "::%u:0\n", face ? face->number : 0);
1380 
1381  for (i = 0; knowledges[i].type != NULL; i++) {
1382  face = try_find_face(knowledges[i].face, NULL);
1383  if (face != NULL && (!(ns->faces_sent[face->number] & NS_FACESENT_FACE)))
1384  esrv_send_face(ns, face, 0);
1385 
1386  SockList_AddPrintf(&sl, "%s:%s:%u:%s\n", knowledges[i].type, knowledges[i].name, face ? face->number : 0, knowledges[i].attempt_alchemy != NULL ? "1" : "0");
1387  }
1388 
1389  Send_With_Handling(ns, &sl);
1390  SockList_Term(&sl);
1391 }
1392 
1398  knowledge_player *kp;
1399 
1400  if (pl->socket.notifications < 2)
1401  return;
1402 
1403  /* merely loading the knowledge will mark it as to be sent through knowledge_process_incremental(),
1404  * but we need to reset the sent_up_to field if eg the player was the last one to leave
1405  * then joins again - no knowledge processing is done at that point. */
1407  kp->sent_up_to = 0;
1408 }
1409 
1419 
1420  while (cur) {
1421  if (cur->player_name == pl->ob->name) {
1423  }
1424  cur = cur->next;
1425  }
1426 
1427 }
1428 
1434  int i, last;
1435  SockList sl;
1436  size_t size;
1437  const knowledge_item *item;
1438  StringBuffer *buf;
1439  char *title;
1440  const Face *face;
1441  knowledge_player *cur = knowledge_global, *prev = NULL;
1442  player *pl;
1443 
1444  while (cur) {
1445 
1446  for (pl = first_player; pl != NULL; pl = pl->next) {
1447  if (pl->ob->name == cur->player_name) {
1448  break;
1449  }
1450  }
1451 
1452  /* player left, remove knowledge */
1453  if (pl == NULL) {
1454  if (prev == NULL) {
1455  knowledge_global = cur->next;
1456  } else {
1457  prev->next = cur->next;
1458  }
1459 
1460  free_knowledge_player(cur);
1461 
1462  /* wait until next tick to do something else */
1463  return;
1464  }
1465 
1466  if (cur->sent_up_to == -1 || cur->sent_up_to == cur->item_count) {
1467  prev = cur;
1468  cur = cur->next;
1469  continue;
1470  }
1471 
1472  last = MIN(cur->sent_up_to + 50, cur->item_count);
1473  SockList_Init(&sl);
1474  SockList_AddString(&sl, "addknowledge ");
1475  for (i = cur->sent_up_to; i < last; i++) {
1476  item = cur->items[i];
1477 
1478  buf = stringbuffer_new();
1479  item->handler->summary(item->item, buf);
1481 
1482  face = NULL;
1483  if (item->handler->item_face != NULL)
1484  face = item->handler->item_face(item->item);
1485 
1486  if (face == NULL)
1487  face = try_find_face(item->handler->face, NULL);
1488 
1489  size = 4 + (2 + strlen(item->handler->type)) + (2 + strlen(title)) + 4;
1490 
1491  if (SockList_Avail(&sl) < size) {
1492  Send_With_Handling(&pl->socket, &sl);
1493  SockList_Reset(&sl);
1494  SockList_AddString(&sl, "addknowledge ");
1495  }
1496 
1497  SockList_AddInt(&sl, i + 1);
1498  SockList_AddLen16Data(&sl, item->handler->type, strlen(item->handler->type));
1499  if (face != NULL && !(pl->socket.faces_sent[face->number]&NS_FACESENT_FACE))
1500  esrv_send_face(&pl->socket, face, 0);
1501  SockList_AddLen16Data(&sl, title, strlen(title));
1502  SockList_AddInt(&sl, face ? face->number : 0);
1503 
1504  free(title);
1505  }
1506 
1507  cur->sent_up_to = last;
1508 
1509  Send_With_Handling(&pl->socket, &sl);
1510  SockList_Term(&sl);
1511 
1512  /* don't send more this tick */
1513  break;
1514  }
1515 }
1516 
1522 void knowledge_show_monster_detail(object *op, const char *name) {
1523  knowledge_player *kp;
1524  StringBuffer *buf = NULL;
1525  char *result;
1526 
1527  if (op->contr == NULL)
1528  return;
1529 
1530  kp = knowledge_get_or_create(op->contr);
1531 
1532  if (!knowledge_known(kp, name, &knowledges[1]))
1533  return;
1534 
1535  buf = stringbuffer_new();
1537  result = stringbuffer_finish(buf);
1539  free(result);
1540 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
recipestruct::arch_names
size_t arch_names
Definition: recipe.h:12
knowledge_type::name
const char * name
Definition: knowledge.c:138
give.next
def next
Definition: give.py:44
Face
Definition: face.h:14
PLAYER
@ PLAYER
Definition: object.h:107
knowledge_alchemy_validate
static int knowledge_alchemy_validate(const char *item)
Definition: knowledge.c:285
knowledge_player::next
struct knowledge_player * next
Definition: knowledge.c:160
output_file.h
SockList_AddInt
void SockList_AddInt(SockList *sl, uint32_t data)
Definition: lowlevel.c:124
global.h
knowledge_send_info
void knowledge_send_info(socket_struct *ns)
Definition: knowledge.c:1368
tolower
#define tolower(C)
Definition: c_new.c:30
NS_FACESENT_FACE
#define NS_FACESENT_FACE
Definition: newserver.h:137
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.c:210
knowledge_type
Definition: knowledge.c:132
get_formulalist
recipelist * get_formulalist(int i)
Definition: recipe.c:96
knowledge_is_valid_item
int(* knowledge_is_valid_item)(const char *code)
Definition: knowledge.c:94
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
GeneralMessage
Definition: book.h:44
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
knowledge_process_incremental
void knowledge_process_incremental(void)
Definition: knowledge.c:1433
obj::face
const Face * face
Definition: object.h:334
knowledge_message_summary
static void knowledge_message_summary(const char *value, StringBuffer *buf)
Definition: knowledge.c:796
archt::head
struct archt * head
Definition: object.h:470
llevError
@ llevError
Definition: logger.h:11
use_alchemy
int use_alchemy(object *op)
Definition: alchemy.c:1047
MONSTER_EXCLUDE_FROM_READABLE_KEY
#define MONSTER_EXCLUDE_FROM_READABLE_KEY
Definition: object.h:583
strdup_local
#define strdup_local
Definition: compat.h:29
knowledge_monster_summary
static void knowledge_monster_summary(const char *item, StringBuffer *buf)
Definition: knowledge.c:575
diamondslots.x
x
Definition: diamondslots.py:15
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
obj::count
tag_t count
Definition: object.h:300
knowledge_read_player_data
static void knowledge_read_player_data(knowledge_player *kp)
Definition: knowledge.c:907
obj::map
struct mapdef * map
Definition: object.h:298
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
socket_struct
Definition: newserver.h:89
free_knowledge
void free_knowledge(void)
Definition: knowledge.c:1274
knowledge_can_use_alchemy
StringBuffer *(* knowledge_can_use_alchemy)(sstring code, const char *item, StringBuffer *buf, int index)
Definition: knowledge.c:113
manor.params
params
Definition: manor.py:295
command_knowledge
void command_knowledge(object *pl, const char *params)
Definition: knowledge.c:1207
SockList_AddString
void SockList_AddString(SockList *sl, const char *data)
Definition: lowlevel.c:154
pl::socket
socket_struct socket
Definition: player.h:94
knowledge_player::item_count
int item_count
Definition: knowledge.c:156
pl
Definition: player.h:92
knowledge_monster_face
static const Face * knowledge_monster_face(sstring code)
Definition: knowledge.c:640
knowledge_type::item_face
knowledge_face item_face
Definition: knowledge.c:142
knowledge_type::attempt_alchemy
knowledge_attempt attempt_alchemy
Definition: knowledge.c:140
knowledge_known
static int knowledge_known(const knowledge_player *current, const char *item, const knowledge_type *kt)
Definition: knowledge.c:526
commongive.inv
inv
Definition: commongive.py:28
blank_face
const Face * blank_face
Definition: image.c:35
giveknowledge.knowledge
knowledge
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: giveknowledge.py:15
knowledge_face
const typedef Face *(* knowledge_face)(sstring code)
Definition: knowledge.c:120
mad_mage_user.file
file
Definition: mad_mage_user.py:15
recipestruct::title
sstring title
Definition: recipe.h:11
MIN
#define MIN(x, y)
Definition: compat.h:21
pl::ob
object * ob
Definition: player.h:162
NDI_ALL_DMS
#define NDI_ALL_DMS
Definition: newclient.h:264
knowledge_item
struct knowledge_item knowledge_item
MSG_TYPE_COMMAND_EXAMINE
#define MSG_TYPE_COMMAND_EXAMINE
Definition: newclient.h:532
knowledge_type::face
const char * face
Definition: knowledge.c:141
knowledge_god_validate
static int knowledge_god_validate(const char *item)
Definition: knowledge.c:700
knowledge_player
struct knowledge_player knowledge_player
describe_item
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Definition: item.c:940
recipestruct::ingred_count
int ingred_count
Definition: recipe.h:23
SockList_AddLen16Data
void SockList_AddLen16Data(SockList *sl, const void *data, size_t len)
Definition: lowlevel.c:188
FLAG_INV_LOCKED
#define FLAG_INV_LOCKED
Definition: define.h:329
SockList_Reset
void SockList_Reset(SockList *sl)
Definition: lowlevel.c:71
knowledge_god_detail
static void knowledge_god_detail(const char *item, StringBuffer *buf)
Definition: knowledge.c:671
apply_by_living_below
void apply_by_living_below(object *pl)
Definition: apply.c:695
MSG_TYPE_MISC
#define MSG_TYPE_MISC
Definition: newclient.h:413
get_message_body
sstring get_message_body(const GeneralMessage *message)
Definition: readable.c:2114
knowledge_god_summary
static void knowledge_god_summary(const char *item, StringBuffer *buf)
Definition: knowledge.c:655
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
obj::nrof
uint32_t nrof
Definition: object.h:335
linked_char
Definition: global.h:86
reputation_trigger_connect.check
def check()
Definition: reputation_trigger_connect.py:18
archt
Definition: object.h:468
settings
struct Settings settings
Definition: init.c:39
SockList_Avail
size_t SockList_Avail(const SockList *sl)
Definition: lowlevel.c:243
knowledge_item::item
sstring item
Definition: knowledge.c:148
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4354
describe_god
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Definition: holy.c:136
free_string
void free_string(sstring str)
Definition: shstr.c:280
knowledge_do_attempt
static void knowledge_do_attempt(object *pl, const char *params)
Definition: knowledge.c:1183
recipestruct
Definition: recipe.h:10
pl::next
struct pl * next
Definition: player.h:93
knowledge_player::sent_up_to
int sent_up_to
Definition: knowledge.c:158
disinfect.map
map
Definition: disinfect.py:4
knowledge_type::summary
knowledge_summary summary
Definition: knowledge.c:134
titlestruct
Definition: readable.c:107
obj::name
sstring name
Definition: object.h:312
linked_char::name
const char * name
Definition: global.h:87
knowledge_show_monster_detail
void knowledge_show_monster_detail(object *op, const char *name)
Definition: knowledge.c:1522
esrv_send_face
void esrv_send_face(socket_struct *ns, const Face *face, int nocache)
Definition: image.c:71
knowledge_monster_detail
static void knowledge_monster_detail(const char *item, StringBuffer *buf)
Definition: knowledge.c:589
command_take
void command_take(object *op, const char *params)
Definition: c_object.c:845
knowledge_god_add
static int knowledge_god_add(struct knowledge_player *current, const char *item, const struct knowledge_type *type)
Definition: knowledge.c:722
knowledge_type::add
knowledge_add_item add
Definition: knowledge.c:137
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:584
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.c:85
of_close
int of_close(OutputFile *of)
Definition: output_file.c:61
Face::number
uint16_t number
Definition: face.h:15
MSG_TYPE_COMMAND_INFO
#define MSG_TYPE_COMMAND_INFO
Definition: newclient.h:526
recipestruct::cauldron
sstring cauldron
Definition: recipe.h:27
fatal
void fatal(enum fatal_error err)
Definition: utils.c:597
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:95
recipestruct::arch_name
char ** arch_name
Definition: recipe.h:13
obj::speed_left
float speed_left
Definition: object.h:331
knowledge_write_player_data
static void knowledge_write_player_data(const knowledge_player *kp)
Definition: knowledge.c:876
knowledge_type::type
const char * type
Definition: knowledge.c:133
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
first_player
EXTERN player * first_player
Definition: global.h:115
obj::x
int16_t x
Definition: object.h:328
obj::container
struct obj * container
Definition: object.h:292
command_help
void command_help(object *op, const char *params)
Definition: c_misc.c:1766
CFweardisguise.tag
tag
Definition: CFweardisguise.py:25
knowledge_player_knows
int knowledge_player_knows(const player *pl, const char *knowledge)
Definition: knowledge.c:1292
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
knowledge_type::detail
knowledge_detail detail
Definition: knowledge.c:135
linked_char::next
struct linked_char * next
Definition: global.h:88
sstring
const typedef char * sstring
Definition: global.h:40
disinfect.count
int count
Definition: disinfect.py:7
knowledge_find
static const knowledge_type * knowledge_find(const char *type)
Definition: knowledge.c:861
tag_t
uint32_t tag_t
Definition: object.h:12
obj::below
struct obj * below
Definition: object.h:288
sproto.h
recipeliststruct
Definition: recipe.h:37
mapdef
Definition: map.h:324
recipe_get_face
const Face * recipe_get_face(const recipe *rp)
Definition: recipe.c:788
knowledge_alchemy_get_recipe
static const recipe * knowledge_alchemy_get_recipe(const char *value)
Definition: knowledge.c:172
knowledge_type::validate
knowledge_is_valid_item validate
Definition: knowledge.c:136
SockList_Init
void SockList_Init(SockList *sl)
Definition: lowlevel.c:52
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
get_message_from_identifier
const GeneralMessage * get_message_from_identifier(const char *identifier)
Definition: assets.cpp:352
knowledge_alchemy_detail
static void knowledge_alchemy_detail(const char *value, StringBuffer *buf)
Definition: knowledge.c:240
recipestruct::ingred
linked_char * ingred
Definition: recipe.h:22
knowledge_player::items
struct knowledge_item ** items
Definition: knowledge.c:155
knowledge_type
struct knowledge_type knowledge_type
knowledge_display
static void knowledge_display(object *pl, const char *params)
Definition: knowledge.c:1127
knowledge_monster_validate
static int knowledge_monster_validate(const char *item)
Definition: knowledge.c:604
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:220
env
static std::shared_ptr< inja::Environment > env
Definition: mapper.cpp:2215
MAX_BUF
#define MAX_BUF
Definition: define.h:35
MSG_TYPE_ADMIN_LOADSAVE
#define MSG_TYPE_ADMIN_LOADSAVE
Definition: newclient.h:499
knowledge_first_player_save
void knowledge_first_player_save(player *pl)
Definition: knowledge.c:1417
get_message_face
const Face * get_message_face(const GeneralMessage *message)
Definition: readable.c:2123
title
struct titlestruct title
SockList_Term
void SockList_Term(SockList *sl)
Definition: lowlevel.c:62
Settings::playerdir
const char * playerdir
Definition: global.h:246
RANDOM
#define RANDOM()
Definition: define.h:642
StringBuffer
Definition: stringbuffer.c:25
recipestruct::skill
sstring skill
Definition: recipe.h:26
obj::y
int16_t y
Definition: object.h:328
knowledge_item
Definition: knowledge.c:147
obj::arch
struct archt * arch
Definition: object.h:416
knowledge_player::item_allocated
int item_allocated
Definition: knowledge.c:157
knowledge_get_or_create
static knowledge_player * knowledge_get_or_create(const player *pl)
Definition: knowledge.c:962
obj::type
uint8_t type
Definition: object.h:341
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
find_archetype_by_object_name
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.cpp:55
knowledges
static const knowledge_type knowledges[]
Definition: knowledge.c:847
archt::clone
object clone
Definition: object.h:472
knowledge_detail
void(* knowledge_detail)(const char *code, StringBuffer *buf)
Definition: knowledge.c:87
knowledge_global
static knowledge_player * knowledge_global
Definition: knowledge.c:164
item
Definition: item.py:1
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
TAG_START
#define TAG_START
Definition: knowledge.c:69
of_open
FILE * of_open(OutputFile *of, const char *fname)
Definition: output_file.c:30
give.op
op
Definition: give.py:33
pl::has_directory
uint32_t has_directory
Definition: player.h:136
autojail.value
value
Definition: autojail.py:6
knowledge_alchemy_attempt
static void knowledge_alchemy_attempt(player *pl, const knowledge_item *item)
Definition: knowledge.c:347
knowledge_player::player_name
sstring player_name
Definition: knowledge.c:154
knowledge_alchemy_can_use_item
static StringBuffer * knowledge_alchemy_can_use_item(sstring code, const char *item, StringBuffer *buf, int index)
Definition: knowledge.c:297
diamondslots.y
y
Definition: diamondslots.py:16
npc_dialog.index
int index
Definition: npc_dialog.py:102
buf
StringBuffer * buf
Definition: readable.c:1606
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:104
recipestruct::next
struct recipestruct * next
Definition: recipe.h:24
socket_struct::faces_sent
uint8_t * faces_sent
Definition: newserver.h:96
knowledge_summary
void(* knowledge_summary)(const char *code, StringBuffer *buf)
Definition: knowledge.c:80
MSG_TYPE_CLIENT_NOTICE
#define MSG_TYPE_CLIENT_NOTICE
Definition: newclient.h:665
make_face_from_files.int
int
Definition: make_face_from_files.py:26
free_knowledge_items
static void free_knowledge_items(knowledge_player *kp)
Definition: knowledge.c:1246
recipeliststruct::items
struct recipestruct * items
Definition: recipe.h:40
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:309
knowledge_item::handler
const knowledge_type * handler
Definition: knowledge.c:149
recipestruct::index
int index
Definition: recipe.h:18
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:282
try_find_face
const Face * try_find_face(const char *name, const Face *error)
Definition: assets.cpp:306
knowledge_add_item
int(* knowledge_add_item)(struct knowledge_player *current, const char *item, const struct knowledge_type *type)
Definition: knowledge.c:103
knowledge_attempt
void(* knowledge_attempt)(player *pl, const struct knowledge_item *item)
Definition: knowledge.c:129
archt::name
sstring name
Definition: object.h:469
knowledge_message_validate
static int knowledge_message_validate(const char *item)
Definition: knowledge.c:827
knowledge_type::use_alchemy
knowledge_can_use_alchemy use_alchemy
Definition: knowledge.c:139
socket_struct::notifications
uint16_t notifications
Definition: newserver.h:129
knowledge_alchemy_summary
static void knowledge_alchemy_summary(const char *value, StringBuffer *buf)
Definition: knowledge.c:210
say.item
dictionary item
Definition: say.py:149
knowledge_do_display
static void knowledge_do_display(object *pl, const knowledge_type *show_only, const char *search)
Definition: knowledge.c:1062
TAG_END
#define TAG_END
Definition: knowledge.c:70
hall_of_fame.header
list header
Definition: hall_of_fame.py:38
knowledge_item_can_be_used_alchemy
void knowledge_item_can_be_used_alchemy(object *op, const object *item)
Definition: knowledge.c:1328
knowledge_read
void knowledge_read(player *pl, object *book)
Definition: knowledge.c:1050
knowledge_message_detail
static void knowledge_message_detail(const char *value, StringBuffer *buf)
Definition: knowledge.c:812
replace.current
current
Definition: replace.py:64
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
knowledge_message_face
static const Face * knowledge_message_face(sstring code)
Definition: knowledge.c:836
knowledge_alchemy_face
static const Face * knowledge_alchemy_face(sstring code)
Definition: knowledge.c:508
examine
void examine(object *op, object *tmp)
Definition: c_object.c:1702
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
Send_With_Handling
void Send_With_Handling(socket_struct *ns, SockList *sl)
Definition: lowlevel.c:440
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:402
knowledge_monster_add
static int knowledge_monster_add(struct knowledge_player *current, const char *item, const struct knowledge_type *type)
Definition: knowledge.c:618
knowledge_player
Definition: knowledge.c:153
SockList
Definition: newclient.h:681
knowledge_send_known
void knowledge_send_known(player *pl)
Definition: knowledge.c:1397
knowledge_show
static void knowledge_show(object *pl, const char *params)
Definition: knowledge.c:1157
free_knowledge_player
static void free_knowledge_player(knowledge_player *kp)
Definition: knowledge.c:1265
knowledge_god_face
static const Face * knowledge_god_face(sstring code)
Definition: knowledge.c:768
knowledge_give
void knowledge_give(player *pl, const char *marker, const object *book)
Definition: knowledge.c:990
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
llevDebug
@ llevDebug
Definition: logger.h:13
knowledge_add
static int knowledge_add(knowledge_player *current, const char *item, const knowledge_type *kt)
Definition: knowledge.c:544
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25
SockList_AddPrintf
void SockList_AddPrintf(SockList *sl, const char *format,...)
Definition: lowlevel.c:199
obj::inv
struct obj * inv
Definition: object.h:291
give.name
name
Definition: give.py:27
get_message_title
sstring get_message_title(const GeneralMessage *message)
Definition: readable.c:2105
put_object_in_sack
void put_object_in_sack(object *op, object *sack, object *tmp, uint32_t nrof)
Definition: c_object.c:937
OutputFile
Definition: output_file.h:41
Settings::localdir
const char * localdir
Definition: global.h:245