#include "things.h"
#include <stddef.h> /* NULL */
-#include <stdint.h> /* uint8_t, uint16_t, UINT16_MAX */
+#include <stdint.h> /* uint8_t, uint16_t, UINT8_MAX, UINT16_MAX */
#include <stdlib.h> /* free() */
#include <string.h> /* memset(), strlen() */
#include "../common/rexit.h" /* exit_err() */
#include "../common/try_malloc.h" /* try_malloc() */
-#include "../common/yx_uint8.h" /* yx_uint8 struct */
+#include "../common/yx_uint8.h" /* yx_uint8 */
#include "map.h" /* is_passable() */
#include "rrand.h" /* rrand() */
#include "world.h" /* global world */
-/* Return pointer to thing of "id" in chain starting at "ptr". */
-static struct Thing * get_thing(struct Thing * ptr, uint8_t id);
-/* Add thing of "type" to map on passable position. Don't put actor on actor. */
-static void add_thing(uint8_t type);
+/* Return lowest unused id for new thing. */
+static uint8_t get_lowest_unused_id();
-static struct Thing * get_thing(struct Thing * ptr, uint8_t id)
+static uint8_t get_lowest_unused_id()
+{
+ uint8_t i = 0;
+ while (1)
+ {
+ if (!get_thing(world.things, i, 1))
+ {
+ return i;
+ }
+ exit_err(i == UINT8_MAX, "No unused ID available to add new thing.");
+ i++;
+ }
+}
+
+
+
+extern struct Thing * get_thing(struct Thing * ptr, uint8_t id, uint8_t deep)
{
while (1)
{
{
return ptr;
}
- struct Thing * owned_thing = get_thing(ptr->owns, id);
- if (NULL != owned_thing)
+ if (deep)
{
- return ptr;
+ struct Thing * owned_thing = get_thing(ptr->owns, id, 1);
+ if (NULL != owned_thing)
+ {
+ return ptr;
+ }
}
ptr = ptr->next;
}
-static void add_thing(uint8_t type)
+extern void free_thing_types(struct ThingType * tt_start)
+{
+ if (NULL == tt_start)
+ {
+ return;
+ }
+ free_thing_types(tt_start->next);
+ free(tt_start->name);
+ free(tt_start);
+}
+
+
+
+extern struct Thing * add_thing(int16_t id, uint8_t type, uint8_t find_pos)
{
char * f_name = "add_thing()";
struct ThingType * tt = get_thing_type(type);
struct Thing * t = try_malloc(sizeof(struct Thing), f_name);
memset(t, 0, sizeof(struct Thing));
- t->id = world.thing_count++;
+ t->id = (0 <= id && id <= UINT8_MAX) ? id : get_lowest_unused_id();
t->type = tt->id;
t->lifepoints = tt->lifepoints;
char * err = "Space to put thing on too hard to find. Map too small?";
uint16_t i = 0;
- while (1)
+ memset(&(t->pos), 0, sizeof(struct yx_uint8));
+ while (find_pos)
{
struct yx_uint8 pos;
for (pos.y = pos.x = 0; 0 == is_passable(pos); i++)
struct Thing ** t_ptr_ptr = &world.things;
for (; NULL != * t_ptr_ptr; t_ptr_ptr = &(*t_ptr_ptr)->next);
* t_ptr_ptr = t;
-}
-
-
-
-extern void free_thing_types(struct ThingType * tt_start)
-{
- if (NULL == tt_start)
- {
- return;
- }
- free_thing_types(tt_start->next);
- free(tt_start->name);
- free(tt_start);
+ return t;
}
uint8_t i;
for (i = 0; i < n; i++)
{
- add_thing(type);
+ add_thing(-1, type, 1);
}
}
extern struct Thing * get_player()
{
- return get_thing(world.things, 0);
+ return get_thing(world.things, 0, 1);
}
extern struct ThingType * get_thing_type(uint8_t id)
{
+ char * f_name = "get_thing_type()";
struct ThingType * tt = world.thing_types;
for (; NULL != tt && id != tt->id; tt = tt->next);
char * err_intro = "Requested thing type of unused ID ";
- char err[strlen(err_intro) + 3 + 1 + 1];
+ uint16_t size = strlen(err_intro) + 3 + 1 + 1;
+ char * err = try_malloc(size, f_name);
sprintf(err, "%s%d.", err_intro, id);
exit_err(NULL == tt, err);
+ free(err);
return tt;
}