From 3fb2cb493ae564f8b14ddb4143b6c1f5bf16f16a Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Sun, 8 Feb 2015 05:31:17 +0100 Subject: [PATCH] Add basic food clock (but no consumables yet to re-set it). --- SERVER_COMMANDS | 11 ++++ confserver/world | 4 ++ src/client/draw_wins.c | 9 ++-- src/client/io.c | 19 +++---- src/client/world.h | 1 + src/server/god_commands.c | 10 +++- src/server/hardcoded_strings.c | 4 +- src/server/hardcoded_strings.h | 4 +- src/server/io.c | 90 ++++++++++++++++++------------- src/server/run.c | 2 + src/server/thing_actions.c | 99 ++++++++++++++++++++++++---------- src/server/thing_actions.h | 5 ++ src/server/things.h | 4 +- 13 files changed, 181 insertions(+), 81 deletions(-) diff --git a/SERVER_COMMANDS b/SERVER_COMMANDS index 754538e..a5a83a2 100644 --- a/SERVER_COMMANDS +++ b/SERVER_COMMANDS @@ -165,6 +165,9 @@ performing the action) value to argument. T_LIFEPOINTS [0 to 255] Set selected thing's lifepoints to argument. +T_SATIATION [-32768 to 32767] +Set selected thing's satiation score. + T_CARRIES [0 to 255] Add thing of ID in argument to inventory of selected thing, if said thing is available for carrying and not the selected thing. @@ -216,3 +219,11 @@ If non-zero, there is a chance of 1 divided by the given value each turn for any thing of the selected type to emit an offspring to a random neighbor cell if one is available that is passable and not inhabited by a thing of the same same type or, if the proliferating thing is animate, any other animate thing. + +TT_STOMACH [0-32767] +Set degree to which things of the selected type suffer from hunger or +over-satiation: If 0, not at all. Else, each turn a thing of the given type may +suffer a lifepoint decrement to the chance of the rounded down quotient of the +satiation score's absolute value by the given value, then again divided by the +latter. This means that the chance is always zero when the absolute value of the +satiation score is lower than the given value. diff --git a/confserver/world b/confserver/world index c967a19..d0a20ef 100644 --- a/confserver/world +++ b/confserver/world @@ -27,6 +27,7 @@ TT_LIFEPOINTS 5 TT_SYMBOL @ TT_NAME HUMAN TT_CONSUMABLE 0 +TT_STOMACH 2048 TT_ID 1 TT_START_NUMBER 27 @@ -34,6 +35,7 @@ TT_LIFEPOINTS 1 TT_SYMBOL a TT_NAME ANT TT_CONSUMABLE 0 +TT_STOMACH 4096 TT_ID 2 TT_START_NUMBER 9 @@ -41,6 +43,7 @@ TT_LIFEPOINTS 3 TT_SYMBOL z TT_NAME ZOMBIE TT_CONSUMABLE 0 +TT_STOMACH 1024 TT_ID 3 TT_START_NUMBER 3 @@ -48,6 +51,7 @@ TT_LIFEPOINTS 9 TT_SYMBOL S TT_NAME SHOGGOTH TT_CONSUMABLE 0 +TT_STOMACH 512 TT_ID 4 TT_START_NUMBER 9 diff --git a/src/client/draw_wins.c b/src/client/draw_wins.c index ec29173..9857af5 100644 --- a/src/client/draw_wins.c +++ b/src/client/draw_wins.c @@ -426,10 +426,13 @@ extern void draw_win_info(struct Win * win) { char * dsc_turn = "Turn: "; char * dsc_hitpoints = "\nHitpoints: "; - uint16_t maxl = strlen(dsc_turn) + 5 + strlen(dsc_hitpoints) + 3; + char * dsc_satiation = "\nSatiation: "; + uint16_t maxl = strlen(dsc_turn) + 5 + strlen(dsc_hitpoints) + + strlen(dsc_satiation) + 6 + 3; char * text = try_malloc(maxl + 1, __func__); - int test = sprintf(text, "%s%d%s%d", dsc_turn, world.turn, dsc_hitpoints, - world.player_lifepoints); + int test = sprintf(text, "%s%d%s%d%s%d", dsc_turn, world.turn, dsc_hitpoints, + world.player_lifepoints, dsc_satiation, + world.player_satiation); exit_trouble(test < 0, __func__, "sprintf"); add_text_with_linebreaks(win, text); free(text); diff --git a/src/client/io.c b/src/client/io.c index ee4dcc2..54b65c2 100644 --- a/src/client/io.c +++ b/src/client/io.c @@ -49,8 +49,7 @@ static void read_map_cells(FILE * file, char ** map); /* Return value seen by atoi() in next line of "file" when passed to try_fgets() * with the given arguments. */ -static uint16_t read_value_from_line(char * read_buf, uint32_t linemax, - FILE * file); +static int32_t read_value_from_line(char* read_buf,int32_t linemax,FILE* file); /* If the server's worldstate file has changed since the last read_worldstate(), * return a pointer to its file descriptor; else, return NULL. @@ -142,8 +141,7 @@ static void read_map_cells(FILE * file, char ** map) -static uint16_t read_value_from_line(char * read_buf, uint32_t linemax, - FILE * file) +static int32_t read_value_from_line(char * read_buf,int32_t linemax,FILE * file) { try_fgets(read_buf, linemax + 1, file, __func__); return atoi(read_buf); @@ -186,12 +184,15 @@ static uint8_t read_worldstate() } uint32_t linemax = textfile_width(file); char * read_buf = try_malloc(linemax + 1, __func__); - world.turn = read_value_from_line(read_buf, linemax, file); - world.player_lifepoints = read_value_from_line(read_buf, linemax, file); + world.turn = (uint16_t) read_value_from_line(read_buf, linemax, file); + world.player_lifepoints = (uint16_t) read_value_from_line(read_buf, linemax, + file); + world.player_satiation = (int16_t) read_value_from_line(read_buf, linemax, + file); read_inventory(read_buf, linemax, file); - world.player_pos.y = read_value_from_line(read_buf, linemax, file); - world.player_pos.x = read_value_from_line(read_buf, linemax, file); - world.map.length = read_value_from_line(read_buf, linemax, file); + world.player_pos.y = (uint8_t) read_value_from_line(read_buf,linemax,file); + world.player_pos.x = (uint8_t) read_value_from_line(read_buf,linemax,file); + world.map.length = (uint16_t) read_value_from_line(read_buf, linemax, file); read_map_cells(file, &world.map.cells); read_map_cells(file, &world.mem_map); free(read_buf); diff --git a/src/client/world.h b/src/client/world.h index a161325..5681210 100644 --- a/src/client/world.h +++ b/src/client/world.h @@ -42,6 +42,7 @@ struct World struct yx_uint8 player_pos; /* coordinates of player on map */ struct yx_uint8 look_pos; /* coordinates of look cursor */ uint16_t turn; /* world/game turn */ + int16_t player_satiation; /* player's belly fullness */ uint8_t player_inventory_select; /* index of selected item in inventory */ uint8_t player_lifepoints; /* how alive the player is */ uint8_t winch; /* if set, SIGWINCH was registered; trigger reset_windows()*/ diff --git a/src/server/god_commands.c b/src/server/god_commands.c index a76f058..d785d8c 100644 --- a/src/server/god_commands.c +++ b/src/server/god_commands.c @@ -100,7 +100,11 @@ static uint8_t parse_thingtype_manipulation(char * tok0, char * tok1) || parse_val(tok0,tok1,s[S_CMD_TT_STARTN],'8',(char *) &tt->start_n) || parse_val(tok0,tok1,s[S_CMD_TT_SYMB],'c',(char *) &tt->char_on_map) || parse_val(tok0,tok1,s[S_CMD_TT_PROL],'8',(char *) &tt->proliferate) - || parse_val(tok0,tok1,s[S_CMD_TT_NAME],'s',(char *) &tt->name)); + || parse_val(tok0,tok1,s[S_CMD_TT_STOMACH], 'u', (char *) &tt->stomach) + || parse_val(tok0,tok1,s[S_CMD_TT_NAME],'s',(char *) &tt->name)) + { + ; + } else if (parse_val(tok0, tok1, s[S_CMD_TT_CORPS],'8',(char *)&id)) { if (!get_thing_type(id)) @@ -292,7 +296,8 @@ static uint8_t parse_thing_manipulation_1arg(char * tok0, char * tok1) ( !strcmp(tok0, s[S_CMD_T_PROGRESS]) || !strcmp(tok0, s[S_CMD_T_TYPE]) || !strcmp(tok0, s[S_CMD_T_CARRIES]) || !strcmp(tok0, s[S_CMD_T_POSY]) || !strcmp(tok0, s[S_CMD_T_POSY]) || !strcmp(tok0, s[S_CMD_T_ARGUMENT]) - || !strcmp(tok0, s[S_CMD_T_HP]) || !strcmp(tok0, s[S_CMD_T_COMMAND]))) + || !strcmp(tok0, s[S_CMD_T_HP]) || !strcmp(tok0, s[S_CMD_T_COMMAND]) + || !strcmp(tok0, s[S_CMD_T_SATIATION]))) { return err_line(1, "No thing defined to manipulate yet."); } @@ -302,6 +307,7 @@ static uint8_t parse_thing_manipulation_1arg(char * tok0, char * tok1) || parse_val(tok0,tok1, s[S_CMD_T_ARGUMENT], '8', (char *)&t->arg) || parse_val(tok0,tok1, s[S_CMD_T_PROGRESS], '8', (char *)&t->progress) || parse_val(tok0,tok1, s[S_CMD_T_HP], '8', (char *) &t->lifepoints) + || parse_val(tok0,tok1, s[S_CMD_T_SATIATION], 'i',(char *)&t->satiation) || parse_position(tok0, tok1, t) || parse_carry(tok0, tok1, t)); else if (parse_val(tok0, tok1, s[S_CMD_T_ID], 'i', (char *) &id)) diff --git a/src/server/hardcoded_strings.c b/src/server/hardcoded_strings.c index 00b9e02..fcb2011 100644 --- a/src/server/hardcoded_strings.c +++ b/src/server/hardcoded_strings.c @@ -9,7 +9,7 @@ -char * s[43]; +char * s[45]; @@ -33,6 +33,7 @@ extern void init_strings() s[S_CMD_TT_NAME] = "TT_NAME"; s[S_CMD_TT_CORPS] = "TT_CORPSE_ID"; s[S_CMD_TT_PROL] = "TT_PROLIFERATE"; + s[S_CMD_TT_STOMACH] = "TT_STOMACH"; s[S_CMD_T_ID] = "T_ID"; s[S_CMD_T_TYPE] = "T_TYPE"; s[S_CMD_T_POSY] = "T_POSY"; @@ -41,6 +42,7 @@ extern void init_strings() s[S_CMD_T_ARGUMENT] = "T_ARGUMENT"; s[S_CMD_T_PROGRESS] = "T_PROGRESS"; s[S_CMD_T_HP] = "T_LIFEPOINTS"; + s[S_CMD_T_SATIATION] = "T_SATIATION"; s[S_CMD_T_CARRIES] = "T_CARRIES"; s[S_CMD_T_MEMMAP] = "T_MEMMAP"; s[S_CMD_T_MEMDEPTHMAP] = "T_MEMDEPTHMAP"; diff --git a/src/server/hardcoded_strings.h b/src/server/hardcoded_strings.h index 15d79bd..c9f720b 100644 --- a/src/server/hardcoded_strings.h +++ b/src/server/hardcoded_strings.h @@ -32,6 +32,7 @@ enum string_num S_CMD_TT_NAME, S_CMD_TT_CORPS, S_CMD_TT_PROL, + S_CMD_TT_STOMACH, S_CMD_T_ID, S_CMD_T_TYPE, S_CMD_T_POSY, @@ -40,6 +41,7 @@ enum string_num S_CMD_T_ARGUMENT, S_CMD_T_PROGRESS, S_CMD_T_HP, + S_CMD_T_SATIATION, S_CMD_T_CARRIES, S_CMD_T_MEMMAP, S_CMD_T_MEMDEPTHMAP, @@ -61,7 +63,7 @@ enum string_num extern void init_strings(); -extern char * s[43]; +extern char * s[45]; diff --git a/src/server/io.c b/src/server/io.c index 3c75bd8..9e55b01 100644 --- a/src/server/io.c +++ b/src/server/io.c @@ -10,7 +10,7 @@ #include /* global errno */ #include /* PIPE_BUF */ #include /* NULL */ -#include /* uint8_t, uint16_t, uint32_t, UINT8_MAX */ +#include /* uint8_t, uint16_t, uint32_t, int32_t, UINT8_MAX */ #include /* defines FILE, sprintf(), fprintf() */ #include /* free() */ #include /* strlen(), snprintf(), memcpy(), strchr() */ @@ -35,9 +35,10 @@ /* Helpers to write lines of god commands to recreate thing "t". */ static void write_key_space(FILE * file, char * key); -static void write_value(FILE * file, uint32_t value); +static void write_uvalue(FILE * file, uint32_t value); static void write_string(FILE * file, char * string); -static void write_key_space_value(FILE * file, char * key, uint32_t value); +static void write_key_space_uvalue(FILE * file, char * key, uint32_t value); +static void write_key_space_svalue(FILE * file, char * key, int32_t value); static void write_key_space_string(FILE * file, char * key, char * string); /* Write to "file" game-map-sized "map" in "command"-prefixed numbered lines. */ @@ -57,7 +58,7 @@ static void try_growing_queue(); static void update_worldstate_file(); /* Write "value" to new \n-delimited line of "file". */ -static void write_value_as_line(uint32_t value, FILE * file); +static void write_value_as_line(int32_t value, FILE * file); /* Write to "file" player's inventory, one item name per line. End in "%\n". */ static void write_inventory(struct Thing * player, FILE * file); @@ -85,7 +86,7 @@ static void write_key_space(FILE * file, char * key) -static void write_value(FILE * file, uint32_t value) +static void write_uvalue(FILE * file, uint32_t value) { char * line = try_malloc(11, __func__); exit_trouble(-1 == sprintf(line, "%u", value), __func__, s[S_FCN_SPRINTF]); @@ -111,10 +112,22 @@ static void write_string(FILE * file, char * string) -static void write_key_space_value(FILE * file, char * key, uint32_t value) +static void write_key_space_uvalue(FILE * file, char * key, uint32_t value) { write_key_space(file, key); - write_value(file, value); + write_uvalue(file, value); + try_fputc('\n', file, __func__); +} + + + +static void write_key_space_svalue(FILE * file, char * key, int32_t value) +{ + write_key_space(file, key); + char * line = try_malloc(11, __func__); + exit_trouble(-1 == sprintf(line, "%d", value), __func__, s[S_FCN_SPRINTF]); + try_fwrite(line, strlen(line), 1, file, __func__); + free(line); try_fputc('\n', file, __func__); } @@ -145,7 +158,7 @@ static void write_mem_map(FILE * file, char * map, char * command) map_copy + (y * world.map.length)); exit_trouble(test < 0, __func__, "snprintf()"); write_key_space(file, command); - write_value(file, y); + write_uvalue(file, y); try_fputc(' ', file, __func__); write_string(file, string); try_fputc('\n', file, __func__); @@ -163,17 +176,18 @@ static void write_thing(FILE * file, struct Thing * t) { write_thing(file, o); } - write_key_space_value(file, s[S_CMD_T_ID], t->id); - write_key_space_value(file, s[S_CMD_T_TYPE], t->type); - write_key_space_value(file, s[S_CMD_T_POSY], t->pos.y); - write_key_space_value(file, s[S_CMD_T_POSX], t->pos.x); - write_key_space_value(file, s[S_CMD_T_COMMAND], t->command); - write_key_space_value(file, s[S_CMD_T_ARGUMENT], t->arg); - write_key_space_value(file, s[S_CMD_T_PROGRESS], t->progress); - write_key_space_value(file, s[S_CMD_T_HP], t->lifepoints); + write_key_space_uvalue(file, s[S_CMD_T_ID], t->id); + write_key_space_uvalue(file, s[S_CMD_T_TYPE], t->type); + write_key_space_uvalue(file, s[S_CMD_T_POSY], t->pos.y); + write_key_space_uvalue(file, s[S_CMD_T_POSX], t->pos.x); + write_key_space_uvalue(file, s[S_CMD_T_COMMAND], t->command); + write_key_space_uvalue(file, s[S_CMD_T_ARGUMENT], t->arg); + write_key_space_uvalue(file, s[S_CMD_T_PROGRESS], t->progress); + write_key_space_uvalue(file, s[S_CMD_T_HP], t->lifepoints); + write_key_space_svalue(file, s[S_CMD_T_SATIATION], t->satiation); for (o = t->owns; o; o = o->next) { - write_key_space_value(file, s[S_CMD_T_CARRIES], o->id); + write_key_space_uvalue(file, s[S_CMD_T_CARRIES], o->id); } write_mem_map(file, t->mem_depth_map, s[S_CMD_T_MEMDEPTHMAP]); write_mem_map(file, t->mem_map, s[S_CMD_T_MEMMAP]); @@ -181,11 +195,11 @@ static void write_thing(FILE * file, struct Thing * t) for (; tm; tm = tm->next) { write_key_space(file, s[S_CMD_T_MEMTHING]); - write_value(file, tm->type); + write_uvalue(file, tm->type); try_fputc(' ', file, __func__); - write_value(file, tm->pos.y); + write_uvalue(file, tm->pos.y); try_fputc(' ', file, __func__); - write_value(file, tm->pos.x); + write_uvalue(file, tm->pos.x); try_fputc('\n', file, __func__); } try_fputc('\n', file, __func__); @@ -223,6 +237,7 @@ static void update_worldstate_file() struct Thing * player = get_player(); write_value_as_line(world.turn, file); write_value_as_line(player->lifepoints, file); + write_value_as_line(player->satiation, file); write_inventory(player, file); write_value_as_line(player->pos.y, file); write_value_as_line(player->pos.x, file); @@ -237,9 +252,9 @@ static void update_worldstate_file() -static void write_value_as_line(uint32_t value, FILE * file) +static void write_value_as_line(int32_t value, FILE * file) { - char write_buf[12]; /* Holds 10 digits of uint32_t maximum + \n + \0. */ + char write_buf[13]; /* Hold "+"/"-" + 10 digits of int32_t max + \n + \0. */ exit_trouble(sprintf(write_buf,"%u\n",value) < 0,__func__,s[S_FCN_SPRINTF]); try_fwrite(write_buf, strlen(write_buf), 1, file, __func__); } @@ -380,45 +395,46 @@ extern void save_world() { char * path_tmp; FILE * file = atomic_write_start(s[S_PATH_SAVE], &path_tmp); - write_key_space_value(file, s[S_CMD_MAPLENGTH], world.map.length); - write_key_space_value(file, s[S_CMD_PLAYTYPE], world.player_type); + write_key_space_uvalue(file, s[S_CMD_MAPLENGTH], world.map.length); + write_key_space_uvalue(file, s[S_CMD_PLAYTYPE], world.player_type); try_fputc('\n', file, __func__); struct ThingAction * ta; for (ta = world.thing_actions; ta; ta = ta->next) { - write_key_space_value(file, s[S_CMD_TA_ID], ta->id); - write_key_space_value(file, s[S_CMD_TA_EFFORT], ta->effort); + write_key_space_uvalue(file, s[S_CMD_TA_ID], ta->id); + write_key_space_uvalue(file, s[S_CMD_TA_EFFORT], ta->effort); write_key_space_string(file, s[S_CMD_TA_NAME], ta->name); try_fputc('\n', file, __func__); } struct ThingType * tt; for (tt = world.thing_types; tt; tt = tt->next) { - write_key_space_value(file, s[S_CMD_TT_ID], tt->id); - write_key_space_value(file, s[S_CMD_TT_STARTN], tt->start_n); - write_key_space_value(file, s[S_CMD_TT_HP], tt->lifepoints); + write_key_space_uvalue(file, s[S_CMD_TT_ID], tt->id); + write_key_space_uvalue(file, s[S_CMD_TT_STARTN], tt->start_n); + write_key_space_uvalue(file, s[S_CMD_TT_HP], tt->lifepoints); int test = fprintf(file, "%s %c\n", s[S_CMD_TT_SYMB], tt->char_on_map); exit_trouble(test < 0, __func__, "fprintf"); write_key_space_string(file, s[S_CMD_TT_NAME], tt->name); - write_key_space_value(file, s[S_CMD_TT_CONSUM], tt->consumable); - write_key_space_value(file, s[S_CMD_TT_PROL], tt->proliferate); + write_key_space_uvalue(file, s[S_CMD_TT_CONSUM], tt->consumable); + write_key_space_uvalue(file, s[S_CMD_TT_PROL], tt->proliferate); + write_key_space_uvalue(file, s[S_CMD_TT_STOMACH], tt->stomach); try_fputc('\n', file, __func__); } for (tt = world.thing_types; tt; tt = tt->next) { - write_key_space_value(file, s[S_CMD_TT_ID], tt->id); - write_key_space_value(file, s[S_CMD_TT_CORPS], tt->corpse_id); + write_key_space_uvalue(file, s[S_CMD_TT_ID], tt->id); + write_key_space_uvalue(file, s[S_CMD_TT_CORPS], tt->corpse_id); } try_fputc('\n', file, __func__); - write_key_space_value(file, s[S_CMD_SEED_MAP], world.seed_map); - write_key_space_value(file, s[S_CMD_SEED_RAND], world.seed); - write_key_space_value(file, s[S_CMD_TURN], world.turn); + write_key_space_uvalue(file, s[S_CMD_SEED_MAP], world.seed_map); + write_key_space_uvalue(file, s[S_CMD_SEED_RAND], world.seed); + write_key_space_uvalue(file, s[S_CMD_TURN], world.turn); try_fputc('\n', file, __func__); struct Thing * t; for (t = world.things; t; t = t->next) { write_thing(file, t); } - write_key_space_value(file, s[S_CMD_WORLD_ACTIVE], 1); + write_key_space_uvalue(file, s[S_CMD_WORLD_ACTIVE], 1); atomic_write_finish(file, s[S_PATH_SAVE], path_tmp); } diff --git a/src/server/run.c b/src/server/run.c index c160e9f..212a37e 100644 --- a/src/server/run.c +++ b/src/server/run.c @@ -30,6 +30,7 @@ #include "god_commands.h" /* parse_god_command_(1|2|3)arg() */ #include "hardcoded_strings.h" /* s */ #include "io.h" /* io_round(), save_world() */ +#include "thing_actions.h" /* hunger() */ #include "things.h" /* Thing, ThingType, ThingInMemory, get_player(), * get_thing_action_id_by_name(), try_thing_proliferation() */ @@ -342,6 +343,7 @@ static void turn_over() thing->command = 0; thing->progress = 0; } + hunger(thing); } try_thing_proliferation(thing); } diff --git a/src/server/thing_actions.c b/src/server/thing_actions.c index 31b70af..839a6e3 100644 --- a/src/server/thing_actions.c +++ b/src/server/thing_actions.c @@ -7,7 +7,7 @@ #include "thing_actions.h" #include /* NULL */ -#include /* uint8_t */ +#include /* uint8_t, INT16_MIN */ #include /* sprintf() */ #include /* free() */ #include /* strlen() */ @@ -20,6 +20,7 @@ * own_thing(), set_thing_position(), get_thing_type(), */ #include "map.h" /* mv_yx_in_dir_legal() */ +#include "rrand.h" /* rrand() */ #include "run.h" /* send_to_outfile() */ #include "world.h" /* global world */ @@ -28,9 +29,10 @@ /* Send "text" as log message to server out file. */ static void update_log(char * text); -/* One actor "wounds" another actor, decrementing his lifepoints and, if they - * reach zero in the process, killing it. Generates appropriate log message. - */ +/* Decrement "t"'s lifepoints, and if to zero, kill it with log update. */ +static void decrement_lifepoints(struct Thing * t); + +/* One actor "wounds" another actor, decrementing his lifepoints. */ static void actor_hits_actor(struct Thing * hitter, struct Thing * hitted); /* Bonus stuff to actor_*() to happen if actor==player. Mostly writing of log @@ -55,6 +57,36 @@ static void update_log(char * text) +static void decrement_lifepoints(struct Thing * t) +{ + struct Thing * player = get_player(); + t->lifepoints--; + if (0 == t->lifepoints) + { + t->type = get_thing_type(t->type)->corpse_id; + if (player == t) + { + update_log("You die."); + memset(t->fov_map, ' ', world.map.length * world.map.length); + return; + } + else + { + free(t->fov_map); + t->fov_map = NULL; + free(t->mem_map); + t->mem_map = NULL; + free(t->mem_depth_map); + t->mem_depth_map = NULL; + free_things_in_memory(t->t_mem); + t->t_mem = NULL; + } + update_log("It dies."); + } +} + + + static void actor_hits_actor(struct Thing * hitter, struct Thing * hitted) { struct ThingType * tt_hitter = get_thing_type(hitter->type); @@ -78,29 +110,7 @@ static void actor_hits_actor(struct Thing * hitter, struct Thing * hitted) exit_trouble(test < 0, __func__, s[S_FCN_SPRINTF]); update_log(msg); free(msg); - hitted->lifepoints--; - if (0 == hitted->lifepoints) - { - hitted->type = tt_hitted->corpse_id; - if (player == hitted) - { - update_log("You die."); - memset(hitted->fov_map, ' ', world.map.length * world.map.length); - return; - } - else - { - free(hitted->fov_map); - hitted->fov_map = NULL; - free(hitted->mem_map); - hitted->mem_map = NULL; - free(hitted->mem_depth_map); - hitted->mem_depth_map = NULL; - free_things_in_memory(hitted->t_mem); - hitted->t_mem = NULL; - } - update_log("It dies."); - } + decrement_lifepoints(hitted); } @@ -315,3 +325,38 @@ extern void actor_use(struct Thing * t) playerbonus_use(no_thing, wrong_thing); } } + + + +extern void hunger(struct Thing * t) +{ + struct ThingType * tt = get_thing_type(t->type); + if (!(tt->stomach)) + { + return; + } + if (t->satiation > INT16_MIN) + { + t->satiation--; + } + uint16_t testbase = t->satiation < 0 ? -(t->satiation) : t->satiation; + uint16_t endurance = tt->stomach; + if ((testbase / endurance) / ((rrand() % endurance) + 1)) + { + if (get_player() == t) + { + update_log("You suffer from hunger."); + } + else + { + char * msg_part = " suffers from hunger."; + uint8_t len = strlen(tt->name) + strlen(msg_part) + 1; + char * msg = try_malloc(len, __func__); + int test = sprintf(msg, "%s%s", tt->name, msg_part); + exit_trouble(test < 0, __func__, s[S_FCN_SPRINTF]); + update_log(msg); + free(msg); + } + decrement_lifepoints(t); + } +} diff --git a/src/server/thing_actions.h b/src/server/thing_actions.h index 376e504..0f9b962 100644 --- a/src/server/thing_actions.h +++ b/src/server/thing_actions.h @@ -38,6 +38,11 @@ extern void actor_pick(struct Thing * t); */ extern void actor_use(struct Thing * t); +/* Decrement "t"'s satiation and trigger a chance (dependent on over-/under- + * satiation value) of lifepoint decrement, when its type's .stomach is >0. + */ +extern void hunger(struct Thing * t); + #endif diff --git a/src/server/things.h b/src/server/things.h index cd4040a..494d1a5 100644 --- a/src/server/things.h +++ b/src/server/things.h @@ -11,7 +11,7 @@ #ifndef THINGS_H #define THINGS_H -#include /* uint8_t, int16_t */ +#include /* uint8_t, int16_t, uint16_t */ #include "../common/yx_uint8.h" /* yx_uint8 */ @@ -26,6 +26,7 @@ struct Thing char * fov_map; /* thing's FOV map; 'v':visible, 'H':hidden */ char * mem_map; /* map knowledge of thing by FOV and memory */ char * mem_depth_map; /* map of map memory up-to-dateness */ + int16_t satiation; /* negative: hungry; positive: over-fed */ uint8_t type; /* ID of appropriate thing definition */ uint8_t lifepoints; /* 0: thing is inanimate; >0: hitpoints */ uint8_t command; /* thing's current action; 0 if none */ @@ -46,6 +47,7 @@ struct ThingType uint8_t id; /* thing type identifier / sets .type */ char char_on_map; /* thing symbol to appear on map */ char * name; /* string to describe thing in game log */ + uint16_t stomach; /* if >0, defines onset & chance of hunger suffering */ uint8_t corpse_id; /* type to change thing into upon destruction */ uint8_t lifepoints; /* default start value for thing's .lifepoints */ uint8_t consumable; /* can be eaten if !0, for so much hitpoint win */ -- 2.30.2