69 #define TAG_START "[color=#ff6611]" 70 #define TAG_END "[/color]" 178 dot = strchr(value,
':');
185 index = atoi(dot + 1);
186 dot = strchr(dot + 1,
':');
195 if (rec->
index == index && strcmp(rec->
title, dot) == 0)
223 if (strcmp(rec->
title,
"NONE"))
256 if (strcmp(rec->
title,
"NONE"))
270 snprintf(name,
sizeof(name),
"an unknown place");
273 rec->
diff >= 10 && rec->
diff < 15 ?
"n" :
"",
275 rec->
skill ? rec->
skill :
"an unknown skill", name);
277 for (next = rec->
ingred; next != NULL; next = next->
next) {
318 for (next = rec->
ingred; next != NULL; next = next->
next) {
320 while ((*name) !=
'\0' && (isdigit(*name) || (*name) ==
' '))
323 if (strcmp(item, name) == 0) {
330 if (strcmp(rec->
title,
"NONE"))
355 object *cauldron = NULL, *inv;
356 object *ingredients[50];
358 uint32_t count, counts[50];
371 LOG(
llevError,
"knowledge: recipe %s has more than 50 ingredients!", item->
item);
377 for (cauldron = pl->
ob->
below; cauldron; cauldron = cauldron->
below) {
382 if (cauldron == NULL) {
387 cauldron_tag = cauldron->
count;
390 for (index = 0; index < 50; index++) {
391 ingredients[index] = NULL;
393 for (inv = pl->
ob->
inv; inv != NULL; inv = inv->
below) {
398 if (inv->title == NULL)
401 snprintf(name,
sizeof(name),
"%s %s", inv->name, inv->title);
404 for (ing = rp->
ingred; ing != NULL; ing = ing->
next) {
406 if (ingredients[index] != NULL) {
413 while (isdigit(*ingname)) {
414 count = 10 * count + (*ingname -
'0');
419 while (*ingname ==
' ')
422 if (strcmp(name, ingname) == 0 && ((inv->nrof == 0 && count == 1) || (inv->nrof >= count))) {
423 ingredients[index] = inv;
426 counts[index] = inv->
nrof == 0 ? 0 : count;
435 for (ing = rp->
ingred; ing != NULL; ing = ing->
next) {
436 if (ingredients[index] == NULL) {
454 while (cauldron->
inv != NULL) {
457 if (cauldron->
inv == inv) {
466 count = ingredients[index]->
nrof;
473 if (count == ingredients[index]->nrof && ingredients[index]->
env == pl->
ob) {
496 while (cauldron->
inv) {
504 if (inv == cauldron->
inv)
518 LOG(
llevError,
"knowledge: couldn't find recipe for %s", code);
626 char *pos, *first = dup;
630 pos = strchr(first,
':');
634 first = pos ? pos + 1 : NULL;
662 char *dup =
strdup_local(item), *pos = strchr(dup,
':');
678 char *dup =
strdup_local(item), *pos = strchr(dup,
':');
683 LOG(
llevError,
"knowledge_god_detail: invalid god item %s\n", item);
689 what = atoi(pos + 1);
694 LOG(
llevError,
"knowledge_god_detail: couldn't find god %s?\n", item);
707 char *dup =
strdup_local(item), *pos = strchr(dup,
':');
711 LOG(
llevError,
"knowledge_god_validate: invalid god item %s\n", item);
729 char *dup =
strdup_local(item), *pos =
const_cast<char *
>(strchr(dup,
':'));
735 LOG(
llevError,
"knowledge_god_add: invalid god item %s\n", item);
741 what = atoi(pos + 1);
744 check = current->
items[i];
748 if (strncmp(check->
item, dup, strlen(dup)) == 0) {
751 pos =
const_cast<char *
>(strchr(check->
item,
':'));
752 known = atoi(pos + 1);
753 result = known | what;
759 return (result != known);
779 snprintf(buf,
MAX_BUF,
"altar_");
780 letter = strlen(buf);
781 strncpy(buf+letter, code,
MAX_BUF-letter);
782 for (; letter < strlen(buf); letter++) {
783 if (buf[letter] ==
':') {
787 buf[letter] =
tolower(buf[letter]);
790 if (altar_arch == NULL)
854 {
"alchemy",
knowledge_alchemy_summary,
knowledge_alchemy_detail,
knowledge_alchemy_validate,
knowledge_add,
"recipes",
knowledge_alchemy_can_use_item,
knowledge_alchemy_attempt,
"knowledge_recipes.111",
knowledge_alchemy_face },
855 {
"monster",
knowledge_monster_summary,
knowledge_monster_detail,
knowledge_monster_validate,
knowledge_monster_add,
"monsters", NULL, NULL,
"knowledge_monsters.111",
knowledge_monster_face },
856 {
"god",
knowledge_god_summary,
knowledge_god_detail,
knowledge_god_validate,
knowledge_god_add,
"gods", NULL, NULL,
"knowledge_gods.111",
knowledge_god_face },
857 {
"message",
knowledge_message_summary,
knowledge_message_detail,
knowledge_message_validate,
knowledge_add,
"messages", NULL, NULL,
"knowledge_messages.111",
knowledge_message_face },
858 { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
869 while (knowledges[i].type != NULL) {
870 if (strcmp(knowledges[i].type, type) == 0)
871 return &knowledges[i];
921 file = fopen(
final,
"r");
927 while (fgets(read,
sizeof(read), file) != NULL) {
928 if (strlen(read) > 0)
929 read[strlen(read) - 1] =
'\0';
931 dot = strchr(read,
':');
933 LOG(
llevError,
"knowledge: invalid line in file %s\n",
final);
941 LOG(
llevError,
"knowledge: invalid type %s in file %s\n", read,
final);
945 LOG(
llevDebug,
"knowledge: ignoring now invalid %s in file %s\n", read,
final);
982 knowledge_global = cur;
997 char *copy, *code, *dot;
1003 dot =
const_cast<char *
>(strchr(marker,
':'));
1007 copy = strdup(marker);
1011 dot =
const_cast<char *
>(strchr(copy,
':'));
1017 LOG(
llevError,
"knowledge: invalid marker type %s in %s\n", copy, book == NULL ?
"(null)" : book->
name);
1022 none = (current->
items == NULL);
1025 while (code && code[0] !=
'\0') {
1026 dot = strchr(code,
'/');
1032 added += type->
add(current, code, type);
1071 int header = 0, show, i;
1075 assert(search == NULL || search[0] !=
'\0');
1079 item = kp->
items[i];
1086 if (show_only != NULL && item->
handler != show_only) {
1089 if (search != NULL && search[0] !=
'\0') {
1090 if (strstr(
final, search) == NULL) {
1095 if (strstr(fd, search) == NULL)
1105 else if (show_only != NULL)
1121 else if (show_only != NULL)
1136 if (params && params[0] ==
' ') {
1137 const char *
type = params + 1;
1139 for (; knowledges[idx].
type != NULL; idx++) {
1140 if (strcmp(knowledges[idx].
name, type) == 0) {
1141 show_only = &knowledges[idx];
1146 if (show_only == NULL) {
1148 for (idx = 0; knowledges[idx].
type != NULL; idx++) {
1166 int count = atoi(params) - 1;
1176 item = kp->
items[count];
1192 int count = atoi(params) - 1;
1200 item = kp->
items[count];
1216 LOG(
llevError,
"command_knowledge: called for %s not a player!\n", pl->
name);
1220 if (!params || *params ==
'\0') {
1225 if (strncmp(params,
"list", 4) == 0) {
1230 if (strncmp(params,
"search ", 7) == 0) {
1235 if (strncmp(params,
"show ", 5) == 0) {
1240 if (strncmp(params,
"attempt ", 8) == 0) {
1257 item = kp->
items[i];
1289 knowledge_global = NULL;
1303 if (strlen(knowledge) >=
MAX_BUF - 1) {
1304 LOG(
llevError,
"knowledge_player_knows: too long knowledge %s\n", knowledge);
1308 strlcpy(copy, knowledge,
sizeof(copy));
1309 pos = strchr(copy,
':');
1311 LOG(
llevError,
"knowledge_player_knows: invalid knowledge item %s\n", knowledge);
1320 LOG(
llevError,
"knowledge_player_knows: invalid knowledge type %s\n", knowledge);
1337 char item_name[
MAX_BUF], *result;
1347 if (item->
title != NULL) {
1348 snprintf(item_name,
sizeof(item_name),
"%s %s", item->
name, item->
title);
1387 for (i = 0; knowledges[i].
type != NULL; i++) {
1461 knowledge_global = cur->
next;
1482 item = cur->
items[i];
1495 size = 4 + (2 + strlen(item->
handler->
type)) + (2 + strlen(title)) + 4;
1532 if (op->
contr == NULL)
static int knowledge_monster_validate(const char *item)
Check if a monster knowledge item is still valid.
void apply_by_living_below(object *pl)
Attempt to apply the object 'below' the player.
static int knowledge_message_validate(const char *item)
Check if a message is still valid.
void SockList_AddPrintf(SockList *sl, const char *format,...)
Adds a printf like formatted string.
#define MSG_TYPE_MISC
Messages that don't go elsewhere.
void(* knowledge_summary)(const char *code, StringBuffer *buf)
Function to fill the StringBuffer with the short description of an item.
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
void SockList_Reset(SockList *sl)
Resets the length of the stored data for writing.
struct archetype * arch
Pointer to archetype.
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Describes an item, in all its details.
#define NS_FACESENT_FACE
Bitmask for the faces_sent[] array - what portion of the face have we sent?
static knowledge_player * knowledge_get_or_create(const player *pl)
Find or create the knowledge store for a player.
int diff
Alchemical dfficulty level.
const char * name
Type name for player, to use with 'list'.
void SockList_Init(SockList *sl)
Initializes the SockList instance.
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
void knowledge_read(player *pl, object *book)
Player is reading a book, give knowledge if needed, warn player, and such.
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
const Face * get_message_face(const GeneralMessage *message)
Get a message's face.
static void knowledge_display(object *pl, const char *params)
Display all a player's knowledge.
One known item for a player.
player * first_player
First player.
New face structure - this enforces the notion that data is face by face only - you can not change the...
const char * playerdir
Where the player files are.
object * below
Pointer to the object stacked below this one.
#define MSG_TYPE_COMMAND_EXAMINE
Player examining something.
sstring add_string(const char *str)
Share a string.
Socket structure, represents a client-server connection.
void SockList_AddLen16Data(SockList *sl, const void *data, size_t len)
Adds a data block prepended with an 16 bit length field.
sstring title
Distinguishing name of product.
void knowledge_item_can_be_used_alchemy(object *op, const object *item)
Displays known alchemy recipes an item can be used in.
int16_t y
Position in the map for this object.
#define MSG_TYPE_ADMIN_LOADSAVE
load/save operations
sstring add_refcount(sstring str)
Like add_string(), but the string is already a shared string.
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
linked_char * ingred
List of ingredients.
void SockList_AddInt(SockList *sl, uint32_t data)
Adds a 32 bit value.
static const recipe * knowledge_alchemy_get_recipe(const char *value)
Get a recipe from the internal code.
recipe * items
Pointer to first recipe in this list.
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
static const knowledge_type knowledges[]
All handled knowledge items.
static void knowledge_show(object *pl, const char *params)
Show the details of a knowledge item.
int index
Index value derived from formula ingredients.
int(* knowledge_add_item)(knowledge_player *current, const char *item, const knowledge_type *type)
Add knowledge information to the player's knowledge.
knowledge_player * next
Next player on the list.
const char * recipe_get_difficulty_string(int difficulty)
A method to produce a difficulty adjective to describe alchemy projects.
void free_knowledge(void)
Free all knowledge data.
Global type definitions and header inclusions.
void command_knowledge(object *pl, const char *params)
Handle the 'knowledge' for a player.
struct player * contr
Pointer to the player which control this object.
Information about a player.
int knowledge_player_knows(const player *pl, const char *knowledge)
Determines whether a player knows a specific knowledge or not.
sstring skill
Skill name used to make this recipe.
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
int(* knowledge_is_valid_item)(const char *code)
Function to check if the specified item is valid.
#define ST_PLAYING
Usual state.
static void knowledge_message_detail(const char *value, StringBuffer *buf)
Give the full description of a message.
knowledge_item ** items
Known knowledge.
sstring stringbuffer_finish_shared(StringBuffer *sb)
Deallocate the string buffer instance and return the string as a shared string.
archetype * try_find_archetype(const char *name)
knowledge_face item_face
Face for an item, if not defined the face it used.
void knowledge_first_player_save(player *pl)
Ensure the knowledge state is correctly saved for the player.
archetype * head
The main part of a linked object.
static std::shared_ptr< inja::Environment > env
Rendering environment.
knowledge_detail detail
Display the detailed description.
static void knowledge_monster_summary(const char *item, StringBuffer *buf)
Monster information summary.
One item type that may be known to the player.
uint16_t notifications
Notifications this client wants to get.
const Face * blank_face
Following can just as easily be pointers, but it is easier to keep them like this.
void knowledge_process_incremental(void)
Incrementally send knowledge information to players, and remove information for players who left...
const Face * try_find_face(const char *name, const Face *error)
knowledge_attempt attempt_alchemy
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
static void knowledge_alchemy_attempt(player *pl, const knowledge_item *item)
Attempt an alchemy recipe through the knowledge system.
player * next
Pointer to next player, NULL if this is last.
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
const char * face
Face for the type, as a basename.
static const Face * knowledge_alchemy_face(sstring code)
Try to get a face for an alchemy recipe.
const char * type
Type internal code, musn't have a double dot, must be unique ingame.
FILE * of_open(OutputFile *of, const char *fname)
Opens an output file.
void knowledge_send_known(player *pl)
Send initial known knowledge to player, if requested.
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
sstring player_name
Player's name.
sstring name
More definite name, like "generate_kobold".
#define MSG_TYPE_CLIENT_NOTICE
Non-critical note to player.
size_t arch_names
Size of the arch_name[] array.
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Describe a god.
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
#define NDI_ALL_DMS
Inform all logged in DMs.
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
#define QUERY_FLAG(xyz, p)
Information on one title.
static int knowledge_known(const knowledge_player *current, const char *item, const knowledge_type *kt)
Check whether a player already knows a knowledge item or not.
void SockList_Term(SockList *sl)
Frees all resources allocated by a SockList instance.
static const Face * knowledge_message_face(sstring code)
Get the face for a message.
knowledge_add_item add
Add the item to the knowledge store.
const knowledge_type * handler
How to handle this item.
uint32_t has_directory
If 0, the player was not yet saved, its directory doesn't exist.
void query_name(const object *op, char *buf, size_t size)
Describes an item.
struct linked_char * next
socket_struct * socket
Socket information for this player.
void knowledge_send_info(socket_struct *ns)
Send the reply_info for 'knowledge_info'.
List of recipes with a certain number of ingredients.
knowledge_is_valid_item validate
Validate the specific value.
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
static void knowledge_do_display(object *pl, const knowledge_type *show_only, const char *search)
Actually display knowledge list.
void SockList_AddString(SockList *sl, const char *data)
Adds a string without length.
uint8_t state
Input state of the player (name, password, etc).
sstring get_message_title(const GeneralMessage *message)
Get a message's title.
object * ob
The object representing the player.
const Face * face
Face with colors.
knowledge_summary summary
Display the short description.
void examine(object *op, object *tmp)
Player examines some object.
struct Settings settings
Global settings.
recipelist * get_formulalist(int i)
Gets a formula list by ingredients count.
size_t SockList_Avail(const SockList *sl)
Returns the available bytes in a SockList instance.
uint16_t number
This is the image unique identifier.
uint32_t tag_t
Object tag, unique during the whole game.
static const knowledge_type * knowledge_find(const char *type)
Find a knowledge handler from its type.
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
const Face *(* knowledge_face)(sstring code)
Get the face for a knowledge item.
#define MAX_BUF
Used for all kinds of things.
void put_object_in_sack(object *op, object *sack, object *tmp, uint32_t nrof)
Something tries to put an object into another.
void knowledge_add_probe_monster(object *op, object *mon)
Display monster details, then add to a player's knowledge if not already.
#define MONSTER_EXCLUDE_FROM_READABLE_KEY
If set (any value), then monster is not listed in books.
int item_count
How many items this players knows.
size_t strlcpy(char *dst, const char *src, size_t size)
Portable implementation of strlcpy(3).
float speed_left
How much speed is left to spend this round.
struct mapstruct * map
Pointer to the map in which this object is present.
void command_help(object *op, const char *params)
Player is asking for some help.
static void knowledge_do_attempt(object *pl, const char *params)
Player attempts something on a knowledge, get item and try it.
static void knowledge_god_detail(const char *item, StringBuffer *buf)
Describe in detail a god.
static int knowledge_god_add(struct knowledge_player *current, const char *item, const struct knowledge_type *type)
Add god information to the player's knowledge, handling the multiple monster case.
object * container
Current container being used.
void esrv_send_face(socket_struct *ns, const Face *face, int nocache)
Sends a face to a client if they are in pixmap mode, nothing gets sent in bitmap mode.
StringBuffer *(* knowledge_can_use_alchemy)(sstring code, const char *item, StringBuffer *buf, int index)
Check if an item can be used for a recipe, and fill the return buffer if it's the case...
static void free_knowledge_items(knowledge_player *kp)
Free all knowledge items for a player.
const char * localdir
Read/write data files.
void knowledge_give(player *pl, const char *marker, const object *book)
Give a knowledge item from its code.
void command_take(object *op, const char *params)
This takes (picks up) an item.
sstring name
The name of the object, obviously...
sstring title
Of foo, etc.
Only for debugging purposes.
uint32_t nrof
Number of objects.
int of_close(OutputFile *of)
Closes an output file.
static int knowledge_add(knowledge_player *current, const char *item, const knowledge_type *kt)
Add a knowledge item to a player's store if not found yet.
#define MSG_TYPE_COMMAND_INFO
Generic info: resistances, etc.
sstring item
Internal item code.
uint8_t type
PLAYER, BULLET, etc.
int sent_up_to
Largest index that was sent to the client with notifications, -1 means the client doesn't want this i...
Functions for creating text output files.
static void knowledge_god_summary(const char *item, StringBuffer *buf)
God information summary.
static int knowledge_god_validate(const char *item)
Check if a god knowledge item is still valid.
object * inv
Pointer to the first object in the inventory.
static const Face * knowledge_god_face(sstring code)
Get the face for a god.
static void knowledge_alchemy_detail(const char *value, StringBuffer *buf)
Give the full description of the alchemy recpie.
#define FLAG_STARTEQUIP
Object was given to player at start.
int item_allocated
How many items are allocated for items.
sstring get_message_body(const GeneralMessage *message)
Get a message's body.
recipe * next
Next recipe with the same number of ingredients.
char ** arch_name
Possible archetypes of the final product made.
static void free_knowledge_player(knowledge_player *kp)
Totally free a knowledge structure, and its items.
const GeneralMessage * get_message_from_identifier(const char *identifier)
Find the message from its identifier.
archetype * find_archetype_by_object_name(const char *name)
This function retrieves an archetype given the name that appears during the game (for example...
#define NDI_UNIQUE
Print immediately, don't buffer.
const Face * recipe_get_face(const recipe *rp)
Return the best face associated with a recipe.
static void knowledge_alchemy_summary(const char *value, StringBuffer *buf)
Give the title of the alchemy recpie.
One general message, from the lib/messages file.
A buffer that will be expanded as content is added to it.
static knowledge_player * knowledge_global
All known loaded knowledge for a player.
Contains the base information we use to make up a packet we want to send.
int ingred_count
Number of items in ingred.
tag_t count
Unique object number for this object.
knowledge_can_use_alchemy use_alchemy
If not null, checks if an item can be used in alchemy.
#define tolower(C)
Simple macro to convert a letter to lowercase.
static int knowledge_monster_add(struct knowledge_player *current, const char *item, const struct knowledge_type *type)
Add monster information to the player's knowledge, handling the multiple monster case.
#define FLAG_INV_LOCKED
Item will not be dropped from inventory.
sstring cauldron
Arch of the cauldron/workbench used to house the formulae.
static void knowledge_read_player_data(knowledge_player *kp)
Read all knowledge data for a player from disk, discarding invalid data.
static StringBuffer * knowledge_alchemy_can_use_item(sstring code, const char *item, StringBuffer *buf, int index)
Check if an item can be used for a recipe, and fill the return buffer if it's the case...
static const Face * knowledge_monster_face(sstring code)
Get the face for a monster.
uint8_t * faces_sent
This is a bitmap on sent face status.
object clone
An object from which to do object_copy()
static int knowledge_alchemy_validate(const char *item)
Check if an alchemy recipe is still ok.
static void knowledge_monster_detail(const char *item, StringBuffer *buf)
Describe in detail a monster.
void(* knowledge_detail)(const char *code, StringBuffer *buf)
Function to fill the StringBuffer with a detailed description of an item.
static void knowledge_write_player_data(const knowledge_player *kp)
Store all knowledge data for a player to disk.
void(* knowledge_attempt)(player *pl, const knowledge_item *item)
Attempt an alchemy based on the specified knowledge.
void Send_With_Handling(socket_struct *ns, SockList *sl)
Calls Write_To_Socket to send data to the client.
static void knowledge_message_summary(const char *value, StringBuffer *buf)
Give the title of a message.