home · contact · privacy
Add basic food clock (but no consumables yet to re-set it).
authorChristian Heller <c.heller@plomlompom.de>
Sun, 8 Feb 2015 04:31:17 +0000 (05:31 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Sun, 8 Feb 2015 04:31:17 +0000 (05:31 +0100)
13 files changed:
SERVER_COMMANDS
confserver/world
src/client/draw_wins.c
src/client/io.c
src/client/world.h
src/server/god_commands.c
src/server/hardcoded_strings.c
src/server/hardcoded_strings.h
src/server/io.c
src/server/run.c
src/server/thing_actions.c
src/server/thing_actions.h
src/server/things.h

index 754538e3444eba6959f73e7c3fbb0f52a5ec4a37..a5a83a2d4bea8be6948f32cccec42ea6f6a4daa7 100644 (file)
@@ -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.
index c967a1955ff041ab0329269982df7d41634f644d..d0a20efbebe9097dae805d479d3a71cf5b565b2b 100644 (file)
@@ -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
index ec2917347903b5ae6b44f4907fe7b291127c26c3..9857af522565dee13086b9deeaa3250c7065a826 100644 (file)
@@ -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);
index ee4dcc2151a7a2ce87792a61a502ab03e6f47b11..54b65c2b438ce73e97da7f0819678f75bd60523e 100644 (file)
@@ -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);
index a1613258da0f56a5a0534563206f55729b4ad99d..5681210ed04ec58f1c41cd851f9e48dc25f6dc5c 100644 (file)
@@ -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()*/
index a76f058cf3f18fa5d7dadc04a146ddf1882df8d1..d785d8cb0068663d29d606ef6f8cbdeb2d31a71f 100644 (file)
@@ -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))
index 00b9e02c5b6aff05ac3b355a61f74c5458ba54a6..fcb201110aa3d450b4a9ad43464342c76ef60cea 100644 (file)
@@ -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";
index 15d79bd5d5b8f08ad32e6023340e522126b4cddf..c9f720b4d736d0165d002ff076e777075b87b20a 100644 (file)
@@ -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];
 
 
 
index 3c75bd8842d15801fa3baff43186b46a477ed59e..9e55b0114d436b6b5f096af6a27d9638cf83785d 100644 (file)
@@ -10,7 +10,7 @@
 #include <errno.h> /* global errno */
 #include <limits.h> /* PIPE_BUF */
 #include <stddef.h> /* NULL */
-#include <stdint.h> /* uint8_t, uint16_t, uint32_t, UINT8_MAX */
+#include <stdint.h> /* uint8_t, uint16_t, uint32_t, int32_t, UINT8_MAX */
 #include <stdio.h> /* defines FILE, sprintf(), fprintf() */
 #include <stdlib.h> /* free() */
 #include <string.h> /* strlen(), snprintf(), memcpy(), strchr() */
 
 /* 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);
 }
index c160e9fcea3d19900f1e9a7d6dabb285a88952c1..212a37e16d62d6adb9a957b0cb11aa1136769e41 100644 (file)
@@ -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);
         }
index 31b70af8ebc5f327cd4c4820d075f9dbf1bcd995..839a6e36d85eaa84644e723f576c9fa069c2cf6c 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "thing_actions.h"
 #include <stddef.h> /* NULL */
-#include <stdint.h> /* uint8_t */
+#include <stdint.h> /* uint8_t, INT16_MIN */
 #include <stdio.h> /* sprintf() */
 #include <stdlib.h> /* free() */
 #include <string.h> /* 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 */
 
 /* 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);
+    }
+}
index 376e50434d0a928344d965f0addc96235a24e2ef..0f9b962401d63dffc1de74730505462419b67fa6 100644 (file)
@@ -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
index cd4040a6dd5b4a107624dd7a1abafad687e1f1e4..494d1a5aade2461d07c723e9f10ab53c68abc0f5 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef THINGS_H
 #define THINGS_H
 
-#include <stdint.h> /* uint8_t, int16_t */
+#include <stdint.h> /* 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 */