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 (!item)
304  return NULL;
305 
306  if (!rec)
307  /* warn? */
308  return buf;
309 
311  if (!arch)
312  /* not supposed to happen */
313  return buf;
314 
315  for (next = rec->ingred; next != NULL; next = next->next) {
316  name = next->name;
317  while ((*name) != '\0' && (isdigit(*name) || (*name) == ' '))
318  name++;
319 
320  if (strcmp(item, name) == 0) {
321  if (buf == NULL) {
322  buf = stringbuffer_new();
323  stringbuffer_append_string(buf, "It can be used in the following recipes: ");
324  } else
326 
327  if (strcmp(rec->title, "NONE"))
328  stringbuffer_append_printf(buf, "%s of %s", arch->clone.name, rec->title);
329  else {
330  if (arch->clone.title != NULL) {
331  stringbuffer_append_printf(buf, "%s %s", arch->clone.name, arch->clone.title);
332  }
333  else
334  stringbuffer_append_printf(buf, "%s", arch->clone.name);
335  }
337 
338  break;
339  }
340  }
341 
342  return buf;
343 }
344 
351  const recipe *rp = knowledge_alchemy_get_recipe(item->item);
352  object *cauldron = NULL, *inv;
353  object *ingredients[50];
354  int index, x, y;
355  uint32_t count, counts[50];
356  char name[MAX_BUF];
357  const char *ingname;
358  linked_char *ing;
359  tag_t cauldron_tag;
360  mapstruct *map;
361 
362  if (!rp) {
363  LOG(llevError, "knowledge: couldn't find recipe for %s", item->item);
364  return;
365  }
366 
367  if (rp->ingred_count > 50) {
368  LOG(llevError, "knowledge: recipe %s has more than 50 ingredients!", item->item);
369  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "This recipe is too complicated.");
370  return;
371  }
372 
373  /* first, check for a cauldron */
374  for (cauldron = pl->ob->below; cauldron; cauldron = cauldron->below) {
375  if (strcmp(rp->cauldron, cauldron->arch->name) == 0)
376  break;
377  }
378 
379  if (cauldron == NULL) {
381  return;
382  }
383 
384  cauldron_tag = cauldron->count;
385 
386  /* find ingredients in player's inventory */
387  for (index = 0; index < 50; index++) {
388  ingredients[index] = NULL;
389  }
390  for (inv = pl->ob->inv; inv != NULL; inv = inv->below) {
391 
393  continue;
394 
395  if (inv->title == NULL)
396  safe_strncpy(name, inv->name, sizeof(name));
397  else
398  snprintf(name, sizeof(name), "%s %s", inv->name, inv->title);
399 
400  index = 0;
401  for (ing = rp->ingred; ing != NULL; ing = ing->next) {
402 
403  if (ingredients[index] != NULL) {
404  index++;
405  continue;
406  }
407 
408  ingname = ing->name;
409  count = 0;
410  while (isdigit(*ingname)) {
411  count = 10 * count + (*ingname - '0');
412  ingname++;
413  }
414  if (count == 0)
415  count = 1;
416  while (*ingname == ' ')
417  ingname++;
418 
419  if (strcmp(name, ingname) == 0 && ((inv->nrof == 0 && count == 1) || (inv->nrof >= count))) {
420  ingredients[index] = inv;
421  // If nrof is 0, we want to keep a count of 0 so put_object_in_sack() later doesn't call
422  // object_split() which would destroy tmp and mess up our tags.
423  counts[index] = inv->nrof == 0 ? 0 : count;
424  break;
425  }
426 
427  index++;
428  }
429  }
430 
431  index = 0;
432  for (ing = rp->ingred; ing != NULL; ing = ing->next) {
433  if (ingredients[index] == NULL) {
434  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "You don't have %s.", ing->name);
435  return;
436  }
437 
438  index++;
439  }
440 
441  /* ensure cauldron is applied */
442  if (pl->ob->container != cauldron) {
444  if (pl->ob->container != cauldron) {
445  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Couldn't activate the %s.", rp->cauldron);
446  return;
447  }
448  }
449 
450  /* ensure cauldron is empty */
451  while (cauldron->inv != NULL) {
452  inv = cauldron->inv;
453  command_take(pl->ob, "");
454  if (cauldron->inv == inv) {
456  return;
457  }
458  }
459 
460  /* drop ingredients */
461  for (index = 0; index < rp->ingred_count; index++) {
462  tag_t tag = ingredients[index]->count;
463  count = ingredients[index]->nrof;
464  put_object_in_sack(pl->ob, cauldron, ingredients[index], counts[index]);
465  if (object_was_destroyed(ingredients[index], tag)) {
466  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Hum, some item disappeared, stopping the attempt.");
467  return;
468 
469  }
470  if (count == ingredients[index]->nrof && ingredients[index]->env == pl->ob) {
471  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Hum, couldn't drop some items, stopping the attempt.");
472  return;
473  }
474  }
475 
476  map = pl->ob->map;
477  x = pl->ob->x;
478  y = pl->ob->y;
479 
480  /* do alchemy */
481  use_alchemy(pl->ob);
482 
483  /* don't forget to slow the player: 1 for alchemy itself, 1 for each ingredient put,
484  * ingredients taken are handled by command_take() */
485  pl->ob->speed_left -= 1.0 * (rp->ingred_count + 1);
486 
487  /* safety: ensure cauldron is still there, and player is still above */
488  if (object_was_destroyed(cauldron, cauldron_tag) || map != pl->ob->map || x != pl->ob->x || y != pl->ob->y) {
489  return;
490  }
491 
492  /* get back the result */
493  while (cauldron->inv) {
494  /* Examining may lead to identifying part of items and thus introducing
495  * extra items in the cauldron. Therefore we'll set inv only after examining,
496  * even if that means that potentially the player will examine twice some items. */
497  examine(pl->ob, cauldron->inv);
498  inv = cauldron->inv;
499  command_take(pl->ob, "");
500  pl->ob->speed_left -= 1.0;
501  if (inv == cauldron->inv)
502  break;
503  }
504 }
505 
511 static const Face *knowledge_alchemy_face(sstring code) {
512  const recipe *rp = knowledge_alchemy_get_recipe(code);
513 
514  if (!rp) {
515  LOG(llevError, "knowledge: couldn't find recipe for %s", code);
516  return NULL;
517  }
518 
519  return recipe_get_face(rp);
520 }
521 
529 static int knowledge_known(const knowledge_player *current, const char *item, const knowledge_type *kt) {
530  int i;
531  for (i = 0; i < current->item_count; i++) {
532  if (strcmp(kt->type, current->items[i]->handler->type) == 0 && strcmp(item, current->items[i]->item) == 0) {
533  /* already known, bailout */
534  return 1;
535  }
536  }
537  return 0;
538 }
539 
547 static int knowledge_add(knowledge_player *current, const char *item, const knowledge_type *kt) {
549 
550  if (knowledge_known(current, item, kt)) {
551  return 0;
552  }
553 
554  /* keep the knowledge */
559  check = malloc(sizeof(knowledge_item));
560  check->item = add_string(item);
561  check->handler = kt;
562  if (current->item_count >= current->item_allocated) {
563  current->item_allocated += 10;
564  current->items = realloc(current->items, current->item_allocated * sizeof(knowledge_item*));
565  }
566  current->items[current->item_count] = check;
567  current->item_count++;
568 
569  return 1;
570 }
571 
578 static void knowledge_monster_summary(const char *item, StringBuffer *buf) {
579  archetype *monster = try_find_archetype(item);
580  if (!monster)
581  return;
582 
583  stringbuffer_append_printf(buf, "%s", monster->clone.name);
584 }
585 
592 static void knowledge_monster_detail(const char *item, StringBuffer *buf) {
593  archetype *monster = try_find_archetype(item);
594 
595  if (!monster)
596  return;
597 
598  stringbuffer_append_printf(buf, " *** %s ***\n", monster->clone.name);
599  describe_item(&monster->clone, NULL, 1, buf);
600 }
601 
607 static int knowledge_monster_validate(const char *item) {
608  const archetype *monster = try_find_archetype(item);
609  if (monster == NULL || monster->clone.type != 0 || monster->head || object_get_value(&monster->clone, MONSTER_EXCLUDE_FROM_READABLE_KEY) != NULL)
610  return 0;
611  return 1;
612 }
613 
621 static int knowledge_monster_add(struct knowledge_player *current, const char *item, const struct knowledge_type *type) {
622  char *dup = strdup_local(item);
623  char *pos, *first = dup;
624  int added = 0;
625 
626  while (first) {
627  pos = strchr(first, ':');
628  if (pos)
629  *pos = '\0';
630  added += knowledge_add(current, first, type);
631  first = pos ? pos + 1 : NULL;
632  }
633 
634  free(dup);
635  return added;
636 }
637 
643 static const Face *knowledge_monster_face(sstring code) {
644  const archetype *monster = try_find_archetype(code);
645 
646  if (!monster || monster->clone.face == blank_face || monster->clone.face == NULL)
647  return NULL;
648 
649  return monster->clone.face;
650 }
651 
658 static void knowledge_god_summary(const char *item, StringBuffer *buf) {
659  char *dup = strdup_local(item), *pos = strchr(dup, ':');
660 
661  if (pos)
662  *pos = '\0';
663 
664  stringbuffer_append_printf(buf, "%s [god]", dup);
665  free(dup);
666 }
667 
674 static void knowledge_god_detail(const char *item, StringBuffer *buf) {
675  char *dup = strdup_local(item), *pos = strchr(dup, ':');
676  const archetype *god;
677  int what;
678 
679  if (!pos) {
680  LOG(llevError, "knowledge_god_detail: invalid god item %s\n", item);
681  free(dup);
682  return;
683  }
684 
685  *pos = '\0';
686  what = atoi(pos + 1);
688  free(dup);
689 
690  if (!god) {
691  LOG(llevError, "knowledge_god_detail: couldn't find god %s?\n", item);
692  return;
693  }
694 
695  describe_god(&god->clone, what, buf, 0);
696 }
697 
703 static int knowledge_god_validate(const char *item) {
704  char *dup = strdup_local(item), *pos = strchr(dup, ':');
705  int valid;
706 
707  if (!pos) {
708  LOG(llevError, "knowledge_god_validate: invalid god item %s\n", item);
709  free(dup);
710  return 0;
711  }
712  *pos = '\0';
713  valid = find_archetype_by_object_name(dup) != NULL;
714  free(dup);
715  return valid;
716 }
717 
725 static int knowledge_god_add(struct knowledge_player *current, const char *item, const struct knowledge_type *type) {
726  char *dup = strdup_local(item), *pos = strchr(dup, ':');
727  StringBuffer *buf;
728  int what, i;
730 
731  if (!pos) {
732  LOG(llevError, "knowledge_god_add: invalid god item %s\n", item);
733  free(dup);
734  return 0;
735  }
736 
737  *pos = '\0';
738  what = atoi(pos + 1);
739 
740  for (i = 0; i < current->item_count; i++) {
741  check = current->items[i];
742  if (check->handler != type)
743  /* Only consider our own type. */
744  continue;
745  if (strncmp(check->item, dup, strlen(dup)) == 0) {
746  /* Already known, update information. */
747  int known, result;
748  pos = strchr(check->item, ':');
749  known = atoi(pos + 1);
750  result = known | what;
751  buf = stringbuffer_new();
752  stringbuffer_append_printf(buf, "%s:%d", dup, result);
753  free_string(check->item);
755  free(dup);
756  return (result != known);
757  }
758  }
759 
760  free(dup);
761 
762  /* Not known, so just add it regularly. */
763  return knowledge_add(current, item, type);
764 }
765 
771 static const Face *knowledge_god_face(sstring code) {
772  char buf[MAX_BUF];
773  size_t letter;
774  const archetype *altar_arch;
775 
776  snprintf(buf, MAX_BUF, "altar_");
777  letter = strlen(buf);
778  strncpy(buf+letter, code, MAX_BUF-letter);
779  for (; letter < strlen(buf); letter++) {
780  if (buf[letter] == ':') {
781  buf[letter] = '\0';
782  break;
783  }
784  buf[letter] = tolower(buf[letter]);
785  }
786  altar_arch = try_find_archetype(buf);
787  if (altar_arch == NULL)
788  return NULL;
789 
790  return altar_arch->clone.face;
791 }
792 
799 static void knowledge_message_summary(const char *value, StringBuffer *buf) {
801 
802  if (!msg)
803  /* warn? */
804  return;
805 
807 }
808 
815 static void knowledge_message_detail(const char *value, StringBuffer *buf) {
817 
818  if (!msg)
819  /* warn? */
820  return;
821 
823 }
824 
830 static int knowledge_message_validate(const char *item) {
831  return get_message_from_identifier(item) != NULL;
832 }
833 
839 static const Face *knowledge_message_face(sstring code) {
841 
842  if (!msg)
843  /* warn? */
844  return NULL;
845 
846  return get_message_face(msg);
847 }
848 
850 static const knowledge_type knowledges[] = {
852  { "monster", knowledge_monster_summary, knowledge_monster_detail, knowledge_monster_validate, knowledge_monster_add, "monsters", NULL, NULL, "knowledge_monsters.111", knowledge_monster_face },
853  { "god", knowledge_god_summary, knowledge_god_detail, knowledge_god_validate, knowledge_god_add, "gods", NULL, NULL, "knowledge_gods.111", knowledge_god_face },
854  { "message", knowledge_message_summary, knowledge_message_detail, knowledge_message_validate, knowledge_add, "messages", NULL, NULL, "knowledge_messages.111", knowledge_message_face },
855  { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
856 };
857 
858 
864 static const knowledge_type *knowledge_find(const char *type) {
865  int i = 0;
866  while (knowledges[i].type != NULL) {
867  if (strcmp(knowledges[i].type, type) == 0)
868  return &knowledges[i];
869  i++;
870  }
871 
872  return NULL;
873 }
874 
880  FILE *file;
881  OutputFile of;
882  char fname[MAX_BUF];
883  const knowledge_item *item;
884  int i;
885 
886  snprintf(fname, sizeof(fname), "%s/%s/%s/%s.knowledge", settings.localdir, settings.playerdir, kp->player_name, kp->player_name);
887 
888  file = of_open(&of, fname);
889  if (!file) {
890  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
891  return;
892  }
893 
894  for (i = 0; i < kp->item_count; i++) {
895  item = kp->items[i];
896  fprintf(file, "%s:%s\n", item->handler->type, item->item);
897  }
898 
899  if (!of_close(&of)) {
900  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
901  return;
902  }
904 }
905 
911  FILE *file;
912  char final[MAX_BUF], read[MAX_BUF], *dot;
914  const knowledge_type *type;
915 
916  snprintf(final, sizeof(final), "%s/%s/%s/%s.knowledge", settings.localdir, settings.playerdir, kp->player_name, kp->player_name);
917 
918  file = fopen(final, "r");
919  if (!file) {
920  /* no knowledge yet, no big deal */
921  return;
922  }
923 
924  while (fgets(read, sizeof(read), file) != NULL) {
925  if (strlen(read) > 0)
926  read[strlen(read) - 1] = '\0';
927 
928  dot = strchr(read, ':');
929  if (!dot) {
930  LOG(llevError, "knowledge: invalid line in file %s\n", final);
931  continue;
932  }
933 
934  *dot = '\0';
935 
936  type = knowledge_find(read);
937  if (!type) {
938  LOG(llevError, "knowledge: invalid type %s in file %s\n", read, final);
939  continue;
940  }
941  if (!type->validate(dot + 1)) {
942  LOG(llevDebug, "knowledge: ignoring now invalid %s in file %s\n", read, final);
943  continue;
944  }
945 
946  item = malloc(sizeof(knowledge_item));
947  item->item = add_string(dot + 1);
948  item->handler = type;
949  if (kp->item_count == kp->item_allocated) {
950  kp->item_allocated += 10;
951  kp->items = realloc(kp->items, kp->item_allocated * sizeof(knowledge_item*));
952  }
953  kp->items[kp->item_count] = item;
954  kp->item_count++;
955  }
956  fclose(file);
957 }
958 
967 
968  while (cur) {
969  if (cur->player_name == pl->ob->name)
970  return cur;
971  cur = cur->next;
972  }
973 
974  cur = calloc(1, sizeof(knowledge_player));
975  if (!cur)
977  cur->player_name = add_refcount(pl->ob->name);
978  cur->next = knowledge_global;
979  knowledge_global = cur;
980  /* read knowledge for this player */
982  if (pl->socket.notifications < 2)
983  cur->sent_up_to = -1;
984  return cur;
985 }
986 
993 void knowledge_give(player *pl, const char *marker, const object *book) {
994  char *dot, *copy, *code;
995  const knowledge_type *type;
996  int none, added = 0;
998 
999  /* process marker, find if already known */
1000  dot = strchr(marker, ':');
1001  if (dot == NULL)
1002  return;
1003 
1004  copy = strdup(marker);
1005  if (!copy)
1007 
1008  dot = strchr(copy, ':');
1009  *dot = '\0';
1010  dot++;
1011 
1012  type = knowledge_find(copy);
1013  if (!type) {
1014  LOG(llevError, "knowledge: invalid marker type %s in %s\n", copy, book == NULL ? "(null)" : book->name);
1015  free(copy);
1016  return;
1017  }
1018 
1019  none = (current->items == NULL);
1020 
1021  code = dot;
1022  while (code && code[0] != '\0') {
1023  dot = strchr(code, '/');
1024  if (dot) {
1025  *dot = '\0';
1026  dot++;
1027  }
1028  if (type->validate(code)) {
1029  added += type->add(current, code, type);
1030  }
1031  code = dot;
1032  }
1033 
1034  free(copy);
1035 
1036  if (added) {
1037  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.");
1038  if (none) {
1039  /* first information ever written down, be nice and give hint to recover it. */
1040  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).");
1041  }
1042  }
1043 
1044  if (pl->has_directory)
1046 }
1047 
1053 void knowledge_read(player *pl, object *book) {
1054  sstring marker = object_get_value(book, "knowledge_marker");
1055  if (marker != NULL)
1056  knowledge_give(pl, marker, book);
1057 }
1058 
1065 static void knowledge_do_display(object *pl, const knowledge_type *show_only, const char *search) {
1066  knowledge_player *kp;
1068  int header = 0, show, i;
1069  StringBuffer *summary;
1070  char *final;
1071 
1072  assert(search == NULL || search[0] != '\0');
1073 
1074  kp = knowledge_get_or_create(pl->contr);
1075  for (i = 0; i < kp->item_count; i++) {
1076  item = kp->items[i];
1077  show = 1;
1078 
1079  summary = stringbuffer_new();
1080  item->handler->summary(item->item, summary);
1081  final = stringbuffer_finish(summary);
1082 
1083  if (show_only != NULL && item->handler != show_only) {
1084  show = 0;
1085  }
1086  if (search != NULL && search[0] != '\0') {
1087  if (strstr(final, search) == NULL) {
1088  char *fd;
1089  StringBuffer *detail = stringbuffer_new();
1090  item->handler->detail(item->item, detail);
1091  fd = stringbuffer_finish(detail);
1092  if (strstr(fd, search) == NULL)
1093  show = 0;
1094  free(fd);
1095  }
1096  }
1097 
1098  if (show == 1) {
1099  if (header == 0) {
1100  if (search != NULL)
1101  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);
1102  else if (show_only != NULL)
1103  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You have knowledge of those %s:", show_only->name);
1104  else
1105  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You have knowledge of:");
1106  header = 1;
1107  }
1108 
1109  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "(%3d) %s", i + 1, final);
1110  }
1111 
1112  free(final);
1113  }
1114 
1115  if (header == 0) {
1116  if (search != NULL)
1117  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);
1118  else if (show_only != NULL)
1119  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);
1120  else
1121  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "You don't know yet any relevant information.");
1122  }
1123 }
1124 
1130 static void knowledge_display(object *pl, const char *params) {
1131  const knowledge_type *show_only = NULL;
1132 
1133  if (params && params[0] == ' ') {
1134  const char *type = params + 1;
1135  int idx = 0;
1136  for (; knowledges[idx].type != NULL; idx++) {
1137  if (strcmp(knowledges[idx].name, type) == 0) {
1138  show_only = &knowledges[idx];
1139  break;
1140  }
1141  }
1142 
1143  if (show_only == NULL) {
1144  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_MISC, MSG_TYPE_CLIENT_NOTICE, "Invalid type, valid types are:");
1145  for (idx = 0; knowledges[idx].type != NULL; idx++) {
1147  }
1148  return;
1149  }
1150  }
1151 
1152  knowledge_do_display(pl, show_only, NULL);
1153 }
1154 
1160 static void knowledge_show(object *pl, const char *params) {
1161  knowledge_player *kp;
1163  int count = atoi(params) - 1;
1164  StringBuffer *buf;
1165  char *final;
1166 
1167  kp = knowledge_get_or_create(pl->contr);
1168  if (count < 0 || count >= kp->item_count) {
1169  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Invalid knowledge number");
1170  return;
1171  }
1172 
1173  item = kp->items[count];
1174  buf = stringbuffer_new();
1175  item->handler->detail(item->item, buf);
1176  final = stringbuffer_finish(buf);
1178  free(final);
1179 }
1180 
1186 static void knowledge_do_attempt(object *pl, const char *params) {
1187  knowledge_player *kp;
1189  int count = atoi(params) - 1;
1190 
1191  kp = knowledge_get_or_create(pl->contr);
1192  if (count < 0 || count >= kp->item_count) {
1193  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Invalid knowledge number");
1194  return;
1195  }
1196 
1197  item = kp->items[count];
1198  if (item->handler->attempt_alchemy == NULL) {
1199  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "You can't do anything with that knowledge.");
1200  } else {
1201  item->handler->attempt_alchemy(pl->contr, item);
1202  }
1203 }
1204 
1210 void command_knowledge(object *pl, const char *params) {
1211 
1212  if (!pl->contr) {
1213  LOG(llevError, "command_knowledge: called for %s not a player!\n", pl->name);
1214  return;
1215  }
1216 
1217  if (!params || *params == '\0') {
1218  command_help(pl, "knowledge");
1219  return;
1220  }
1221 
1222  if (strncmp(params, "list", 4) == 0) {
1223  knowledge_display(pl, params + 4);
1224  return;
1225  }
1226 
1227  if (strncmp(params, "search ", 7) == 0) {
1228  knowledge_do_display(pl, NULL, params + 7);
1229  return;
1230  }
1231 
1232  if (strncmp(params, "show ", 5) == 0) {
1233  knowledge_show(pl, params + 5);
1234  return;
1235  }
1236 
1237  if (strncmp(params, "attempt ", 8) == 0) {
1239  return;
1240  }
1241 
1242  command_help(pl, "knowledge");
1243 }
1244 
1251  int i;
1252 
1253  for (i = 0; i < kp->item_count; i++) {
1254  item = kp->items[i];
1255  free_string(item->item);
1256  free(item);
1257  }
1258  free(kp->items);
1259  kp->items = NULL;
1260  kp->item_count = 0;
1261  kp->item_allocated = 0;
1262 }
1263 
1270  free_string(kp->player_name);
1271  free(kp);
1272 }
1273 
1277 void free_knowledge(void) {
1278  knowledge_player *kp, *next;
1279 
1280  kp = knowledge_global;
1281  while (kp) {
1282  next = kp->next;
1284  kp = next;
1285  }
1286  knowledge_global = NULL;
1287 }
1288 
1295 int knowledge_player_knows(const player *pl, const char *knowledge) {
1296  const knowledge_type *type;
1297  char copy[MAX_BUF], *pos;
1298  const knowledge_player *current;
1299 
1300  if (strlen(knowledge) >= MAX_BUF - 1) {
1301  LOG(llevError, "knowledge_player_knows: too long knowledge %s\n", knowledge);
1302  return 0;
1303  }
1304 
1305  strlcpy(copy, knowledge, sizeof(copy));
1306  pos = strchr(copy, ':');
1307  if (pos == NULL) {
1308  LOG(llevError, "knowledge_player_knows: invalid knowledge item %s\n", knowledge);
1309  return 0;
1310  }
1311 
1312  *pos = '\0';
1313  pos++;
1314 
1315  type = knowledge_find(copy);
1316  if (type == NULL) {
1317  LOG(llevError, "knowledge_player_knows: invalid knowledge type %s\n", knowledge);
1318  return 0;
1319  }
1320 
1322 
1323  return knowledge_known(current, pos, type);
1324 }
1325 
1331 void knowledge_item_can_be_used_alchemy(object *op, const object *item) {
1332  knowledge_player *cur;
1333  knowledge_item *ki;
1334  char item_name[MAX_BUF], *result;
1335  const char *name;
1336  StringBuffer *buf = NULL;
1337  int i;
1338 
1339  if (op->type != PLAYER || op->contr == NULL)
1340  return;
1341 
1342  cur = knowledge_get_or_create(op->contr);
1343 
1344  if (item->title != NULL) {
1345  snprintf(item_name, sizeof(item_name), "%s %s", item->name, item->title);
1346  name = item_name;
1347  } else
1348  name = item->name;
1349 
1350  for (i = 0; i < cur->item_count; i++) {
1351  ki = cur->items[i];
1352  if (ki->handler->use_alchemy != NULL) {
1353  buf = ki->handler->use_alchemy(ki->item, name, buf, i + 1);
1354  }
1355  }
1356 
1357  if (buf == NULL)
1358  return;
1359 
1363  result);
1364  free(result);
1365 }
1366 
1372  int i;
1373  const Face *face;
1374  SockList sl;
1375 
1376  face = try_find_face("knowledge_generic.111", NULL);
1377  if (face != NULL && (!(ns->faces_sent[face->number] & NS_FACESENT_FACE)))
1378  esrv_send_face(ns, face, 0);
1379 
1380  SockList_Init(&sl);
1381  SockList_AddString(&sl, "replyinfo knowledge_info\n");
1382  SockList_AddPrintf(&sl, "::%u:0\n", face ? face->number : 0);
1383 
1384  for (i = 0; knowledges[i].type != NULL; i++) {
1385  face = try_find_face(knowledges[i].face, NULL);
1386  if (face != NULL && (!(ns->faces_sent[face->number] & NS_FACESENT_FACE)))
1387  esrv_send_face(ns, face, 0);
1388 
1389  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");
1390  }
1391 
1392  Send_With_Handling(ns, &sl);
1393  SockList_Term(&sl);
1394 }
1395 
1401  knowledge_player *kp;
1402 
1403  if (pl->socket.notifications < 2)
1404  return;
1405 
1406  /* merely loading the knowledge will mark it as to be sent through knowledge_process_incremental(),
1407  * but we need to reset the sent_up_to field if eg the player was the last one to leave
1408  * then joins again - no knowledge processing is done at that point. */
1410  kp->sent_up_to = 0;
1411 }
1412 
1422 
1423  while (cur) {
1424  if (cur->player_name == pl->ob->name) {
1426  }
1427  cur = cur->next;
1428  }
1429 
1430 }
1431 
1437  int i, last;
1438  SockList sl;
1439  size_t size;
1440  const knowledge_item *item;
1441  StringBuffer *buf;
1442  char *title;
1443  const Face *face;
1444  knowledge_player *cur = knowledge_global, *prev = NULL;
1445  player *pl;
1446 
1447  while (cur) {
1448 
1449  for (pl = first_player; pl != NULL; pl = pl->next) {
1450  if (pl->ob->name == cur->player_name) {
1451  break;
1452  }
1453  }
1454 
1455  /* player left, remove knowledge */
1456  if (pl == NULL) {
1457  if (prev == NULL) {
1458  knowledge_global = cur->next;
1459  } else {
1460  prev->next = cur->next;
1461  }
1462 
1463  free_knowledge_player(cur);
1464 
1465  /* wait until next tick to do something else */
1466  return;
1467  }
1468 
1469  if (cur->sent_up_to == -1 || cur->sent_up_to == cur->item_count) {
1470  prev = cur;
1471  cur = cur->next;
1472  continue;
1473  }
1474 
1475  last = MIN(cur->sent_up_to + 50, cur->item_count);
1476  SockList_Init(&sl);
1477  SockList_AddString(&sl, "addknowledge ");
1478  for (i = cur->sent_up_to; i < last; i++) {
1479  item = cur->items[i];
1480 
1481  buf = stringbuffer_new();
1482  item->handler->summary(item->item, buf);
1484 
1485  face = NULL;
1486  if (item->handler->item_face != NULL)
1487  face = item->handler->item_face(item->item);
1488 
1489  if (face == NULL)
1490  face = try_find_face(item->handler->face, NULL);
1491 
1492  size = 4 + (2 + strlen(item->handler->type)) + (2 + strlen(title)) + 4;
1493 
1494  if (SockList_Avail(&sl) < size) {
1495  Send_With_Handling(&pl->socket, &sl);
1496  SockList_Reset(&sl);
1497  SockList_AddString(&sl, "addknowledge ");
1498  }
1499 
1500  SockList_AddInt(&sl, i + 1);
1501  SockList_AddLen16Data(&sl, item->handler->type, strlen(item->handler->type));
1502  if (face != NULL && !(pl->socket.faces_sent[face->number]&NS_FACESENT_FACE))
1503  esrv_send_face(&pl->socket, face, 0);
1504  SockList_AddLen16Data(&sl, title, strlen(title));
1505  SockList_AddInt(&sl, face ? face->number : 0);
1506 
1507  free(title);
1508  }
1509 
1510  cur->sent_up_to = last;
1511 
1512  Send_With_Handling(&pl->socket, &sl);
1513  SockList_Term(&sl);
1514 
1515  /* don't send more this tick */
1516  break;
1517  }
1518 }
1519 
1525 void knowledge_add_probe_monster(object *op, object *mon) {
1526  StringBuffer *buf = NULL;
1527  char *result;
1528 
1529  if (op->contr == NULL)
1530  return;
1531 
1532  buf = stringbuffer_new();
1533  stringbuffer_append_printf(buf, " *** %s ***\n", mon->name);
1534  describe_item(mon, NULL, 1, buf);
1537  free(result);
1538 
1539  /*
1540  * TODO: Add to player's knowledge. This is disabled for now because the
1541  * monster being probed could be custom, but when the player goes to query
1542  * their knowledge they will only get information about the monster's
1543  * archetype.
1544  knowledge_player *kp;
1545  kp = knowledge_get_or_create(op->contr);
1546  knowledge_add(kp, mon->name, &knowledges[1]);
1547  */
1548 }
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:1371
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:1436
obj::face
const Face * face
Definition: object.h:336
knowledge_message_summary
static void knowledge_message_summary(const char *value, StringBuffer *buf)
Definition: knowledge.c:799
archt::head
struct archt * head
Definition: object.h:471
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:582
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:578
diamondslots.x
x
Definition: diamondslots.py:15
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
obj::count
tag_t count
Definition: object.h:302
knowledge_read_player_data
static void knowledge_read_player_data(knowledge_player *kp)
Definition: knowledge.c:910
obj::map
struct mapdef * map
Definition: object.h:300
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:1277
knowledge_can_use_alchemy
StringBuffer *(* knowledge_can_use_alchemy)(sstring code, const char *item, StringBuffer *buf, int index)
Definition: knowledge.c:113
command_knowledge
void command_knowledge(object *pl, const char *params)
Definition: knowledge.c:1210
SockList_AddString
void SockList_AddString(SockList *sl, const char *data)
Definition: lowlevel.c:154
pl::socket
socket_struct socket
Definition: player.h:107
knowledge_player::item_count
int item_count
Definition: knowledge.c:156
pl
Definition: player.h:105
knowledge_monster_face
static const Face * knowledge_monster_face(sstring code)
Definition: knowledge.c:643
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:529
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:176
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:703
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:941
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:674
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:2118
knowledge_god_summary
static void knowledge_god_summary(const char *item, StringBuffer *buf)
Definition: knowledge.c:658
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
obj::nrof
uint32_t nrof
Definition: object.h:337
linked_char
Definition: global.h:86
reputation_trigger_connect.check
def check()
Definition: reputation_trigger_connect.py:18
archt
Definition: object.h:469
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:4317
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:1186
recipestruct
Definition: recipe.h:10
pl::next
struct pl * next
Definition: player.h:106
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:314
linked_char::name
const char * name
Definition: global.h:87
rotate-tower.result
bool result
Definition: rotate-tower.py:13
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:592
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:725
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:585
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.c:85
mon
object * mon
Definition: comet_perf.c:75
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:580
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:333
knowledge_write_player_data
static void knowledge_write_player_data(const knowledge_player *kp)
Definition: knowledge.c:879
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
knowledge_add_probe_monster
void knowledge_add_probe_monster(object *op, object *mon)
Definition: knowledge.c:1525
obj::x
int16_t x
Definition: object.h:330
obj::container
struct obj * container
Definition: object.h:294
command_help
void command_help(object *op, const char *params)
Definition: c_misc.c:1769
CFweardisguise.tag
tag
Definition: CFweardisguise.py:25
knowledge_player_knows
int knowledge_player_knows(const player *pl, const char *knowledge)
Definition: knowledge.c:1295
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:864
tag_t
uint32_t tag_t
Definition: object.h:12
obj::below
struct obj * below
Definition: object.h:290
sproto.h
recipeliststruct
Definition: recipe.h:37
mapdef
Definition: map.h:317
recipe_get_face
const Face * recipe_get_face(const recipe *rp)
Definition: recipe.c:797
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:358
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:1130
knowledge_monster_validate
static int knowledge_monster_validate(const char *item)
Definition: knowledge.c:607
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:2216
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:1420
get_message_face
const Face * get_message_face(const GeneralMessage *message)
Definition: readable.c:2127
title
struct titlestruct title
SockList_Term
void SockList_Term(SockList *sl)
Definition: lowlevel.c:62
Settings::playerdir
const char * playerdir
Definition: global.h:245
RANDOM
#define RANDOM()
Definition: define.h:644
StringBuffer
Definition: stringbuffer.c:25
recipestruct::skill
sstring skill
Definition: recipe.h:26
obj::y
int16_t y
Definition: object.h:330
knowledge_item
Definition: knowledge.c:147
obj::arch
struct archt * arch
Definition: object.h:417
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:965
obj::type
uint8_t type
Definition: object.h:343
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:850
archt::clone
object clone
Definition: object.h:473
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:149
autojail.value
value
Definition: autojail.py:6
knowledge_alchemy_attempt
static void knowledge_alchemy_attempt(player *pl, const knowledge_item *item)
Definition: knowledge.c:350
knowledge_player::player_name
sstring player_name
Definition: knowledge.c:154
roll-o-matic.params
params
Definition: roll-o-matic.py:193
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:1610
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:138
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:1249
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:288
try_find_face
const Face * try_find_face(const char *name, const Face *error)
Definition: assets.cpp:312
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:470
knowledge_message_validate
static int knowledge_message_validate(const char *item)
Definition: knowledge.c:830
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
describe_god
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Definition: holy.cpp:113
knowledge_do_display
static void knowledge_do_display(object *pl, const knowledge_type *show_only, const char *search)
Definition: knowledge.c:1065
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:1331
knowledge_read
void knowledge_read(player *pl, object *book)
Definition: knowledge.c:1053
knowledge_message_detail
static void knowledge_message_detail(const char *value, StringBuffer *buf)
Definition: knowledge.c:815
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:839
knowledge_alchemy_face
static const Face * knowledge_alchemy_face(sstring code)
Definition: knowledge.c:511
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:621
knowledge_player
Definition: knowledge.c:153
SockList
Definition: newclient.h:681
knowledge_send_known
void knowledge_send_known(player *pl)
Definition: knowledge.c:1400
knowledge_show
static void knowledge_show(object *pl, const char *params)
Definition: knowledge.c:1160
free_knowledge_player
static void free_knowledge_player(knowledge_player *kp)
Definition: knowledge.c:1268
knowledge_god_face
static const Face * knowledge_god_face(sstring code)
Definition: knowledge.c:771
knowledge_give
void knowledge_give(player *pl, const char *marker, const object *book)
Definition: knowledge.c:993
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:547
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:293
give.name
name
Definition: give.py:27
get_message_title
sstring get_message_title(const GeneralMessage *message)
Definition: readable.c:2109
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:244