]> git.lizzy.rs Git - dungeon_game.git/commitdiff
Add inventory and cherries (collectable food)
authorElias Fleckenstein <eliasfleckenstein@web.de>
Fri, 11 Jun 2021 19:11:37 +0000 (21:11 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Fri, 11 Jun 2021 19:11:37 +0000 (21:11 +0200)
plugins/cherry/Makefile [new file with mode: 0644]
plugins/cherry/cherry.c [new file with mode: 0644]
plugins/cherry/dependencies.txt [new file with mode: 0644]
plugins/game/game.c
plugins/game/game.h
plugins/inventory/Makefile [new file with mode: 0644]
plugins/inventory/dependencies.txt [new file with mode: 0644]
plugins/inventory/inventory.c [new file with mode: 0644]
plugins/inventory/inventory.h [new file with mode: 0644]

diff --git a/plugins/cherry/Makefile b/plugins/cherry/Makefile
new file mode 100644 (file)
index 0000000..edb1f44
--- /dev/null
@@ -0,0 +1,4 @@
+plugins/cherry/cherry.so: plugins/cherry/cherry.c plugins/game/game.h plugins/score/score.h plugins/inventory/inventory.h
+       cc -g -shared -fpic -o plugins/cherry/cherry.so plugins/cherry/cherry.c
+
+PLUGINS := ${PLUGINS} plugins/cherry/cherry.so
diff --git a/plugins/cherry/cherry.c b/plugins/cherry/cherry.c
new file mode 100644 (file)
index 0000000..072aec0
--- /dev/null
@@ -0,0 +1,71 @@
+#include <stddef.h>
+#include <stdlib.h>
+#include "../game/game.h"
+#include "../score/score.h"
+#include "../inventory/inventory.h"
+
+static struct entity cherry_entity;
+
+static bool use_cherry(struct itemstack *stack)
+{
+       (void) stack;
+
+       add_health(&player, 2);
+       return true;
+}
+
+static struct item cherry_item = {
+       .name = "Cherry",
+       .stackable = true,
+
+       .on_use = &use_cherry,
+       .on_destroy = NULL,
+};
+
+static void cherry_step(struct entity *self, struct entity_step_data stepdata)
+{
+       if (stepdata.dx == 0 && stepdata.dy == 0) {
+               add_score(2);
+               inventory_add(&player_inventory, (struct itemstack) {
+                       .item = &cherry_item,
+                       .count = 1,
+                       .meta = NULL,
+               });
+               self->remove = true;
+       }
+}
+
+static void spawn_cherry(int x, int y)
+{
+       spawn(cherry_entity, x, y, NULL);
+}
+
+__attribute__((constructor)) static void init()
+{
+       cherry_entity = (struct entity) {
+               .name = "cherry",
+               .x = 0,
+               .y = 0,
+               .color = get_color("#FF2A53"),
+               .texture = "🍒",
+               .remove = false,
+               .meta = NULL,
+               .health = 1,
+               .max_health = 1,
+               .collide_with_entities = false,
+
+               .on_step = &cherry_step,
+               .on_collide = NULL,
+               .on_collide_with_entity = NULL,
+               .on_spawn = NULL,
+               .on_remove = NULL,
+               .on_death = NULL,
+               .on_damage = NULL,
+       };
+
+       register_air_function((struct generator_function) {
+               .chance = 100,
+               .callback = &spawn_cherry,
+       });
+}
+
diff --git a/plugins/cherry/dependencies.txt b/plugins/cherry/dependencies.txt
new file mode 100644 (file)
index 0000000..4952514
--- /dev/null
@@ -0,0 +1,3 @@
+game
+score
+inventory
index 40bfa51121da41e844ddc9cfad7f21f76389f2e5..8dacf4ad088e6f54eebea0beb2e342952bb4c8cd 100644 (file)
@@ -1,7 +1,5 @@
 #include <stdio.h>
-#include <stdbool.h>
 #include <stdlib.h>
-#include <stddef.h>
 #include <unistd.h>
 #include <assert.h>
 #include <ctype.h>
@@ -10,8 +8,8 @@
 #include <termios.h>
 #include <math.h>
 #include <pthread.h>
+#include <string.h>
 #include "game.h"
-#define MAKEBUF(type) type *buf = malloc(sizeof(type)); *buf = arg;
 
 /* Shared variables */
 
@@ -119,6 +117,14 @@ int min(int a, int b)
        return a < b ? a : b;
 }
 
+void *make_buffer(void *ptr, size_t size)
+{
+       void *buf = malloc(size);
+       memcpy(buf, ptr, size);
+
+       return buf;
+}
+
 /* Game-related utility functions */
 
 void quit()
@@ -216,24 +222,22 @@ void add_health(struct entity *entity, int health)
 
 /* Register callback functions */
 
-void register_air_function(struct generator_function arg)
+void register_air_function(struct generator_function func)
 {
-       MAKEBUF(struct generator_function);
-       air_functions = add_element(air_functions, buf);
+       air_functions = add_element(air_functions, make_buffer(&func, sizeof(struct generator_function)));
 }
 
-void register_input_handler(unsigned char c, struct input_handler arg)
+void register_input_handler(unsigned char c, struct input_handler handler)
 {
        if (input_handlers[c])
                return;
 
-       MAKEBUF(struct input_handler);
-       input_handlers[c] = buf;
+       input_handlers[c] = make_buffer(&handler, sizeof(struct input_handler));
 }
 
-void register_render_component(void (*arg)(struct winsize ws))
+void register_render_component(void (*callback)(struct winsize ws))
 {
-       render_components = add_element(render_components, arg);
+       render_components = add_element(render_components, callback);
 };
 
 /* Player */
@@ -254,9 +258,12 @@ static void mapgen_set_air(int x, int y)
 {
        if (is_outside(x, y))
                return;
+
        if (map[x][y].material == &air)
                return;
+
        map[x][y] = (struct node) {&air};
+
        for (struct list *ptr = air_functions; ptr != NULL; ptr = ptr->next) {
                struct generator_function *func = ptr->element;
 
@@ -456,8 +463,6 @@ static void *input_thread(void *unused)
 
 void game()
 {
-       srand(time(0));
-
        struct sigaction sa;
        sa.sa_handler = &handle_interrupt;
        sigaction(SIGINT, &sa, NULL);
@@ -553,6 +558,8 @@ void game()
 
 __attribute__ ((constructor)) static void init()
 {
+       srand(time(0));
+
        wall = (struct material) {
                .solid = true,
                .color = get_color("#5B2F00"),
index f4cd53be6eea93fe201898769bf3d67f7aa930d2..11d39ba3107e885c5f1bd1637b9d6a8182a633ae 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdbool.h>
 #include <sys/ioctl.h>
+#include <stddef.h>
 #define MAP_HEIGHT 1000
 #define MAP_WIDTH 1000
 #define LIGHT 10
@@ -102,6 +103,7 @@ struct list *add_element(struct list *list, void *element);
 int clamp(int v, int max, int min);
 int max(int a, int b);
 int min(int a, int b);
+void *make_buffer(void *ptr, size_t size);
 
 void quit();
 bool player_dead();
@@ -114,8 +116,8 @@ bool spawn(struct entity def, int x, int y, void *data);
 bool move(struct entity *entity, int xoff, int yoff);
 void add_health(struct entity *entity, int health);
 
-void register_air_function(struct generator_function arg);
-void register_input_handler(unsigned char c, struct input_handler arg);
-void register_render_component(void (*arg)(struct winsize ws));
+void register_air_function(struct generator_function func);
+void register_input_handler(unsigned char c, struct input_handler handler);
+void register_render_component(void (*callback)(struct winsize ws));
 
 #endif
diff --git a/plugins/inventory/Makefile b/plugins/inventory/Makefile
new file mode 100644 (file)
index 0000000..a665b55
--- /dev/null
@@ -0,0 +1,4 @@
+plugins/inventory/inventory.so: plugins/inventory/inventory.c plugins/inventory/inventory.h plugins/game/game.h
+       cc -g -shared -fpic -o plugins/inventory/inventory.so plugins/inventory/inventory.c
+
+PLUGINS := ${PLUGINS} plugins/inventory/inventory.so
diff --git a/plugins/inventory/dependencies.txt b/plugins/inventory/dependencies.txt
new file mode 100644 (file)
index 0000000..dc22e61
--- /dev/null
@@ -0,0 +1 @@
+game
diff --git a/plugins/inventory/inventory.c b/plugins/inventory/inventory.c
new file mode 100644 (file)
index 0000000..c3b533d
--- /dev/null
@@ -0,0 +1,203 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "../inventory/inventory.h"
+
+static struct color gray;
+static struct color darkgray;
+
+static bool use_item(struct itemstack *stack)
+{
+       (void) stack;
+       return true;
+}
+
+struct inventory player_inventory = {NULL};
+
+static int selected_index = 0;
+
+void inventory_add(struct inventory *self, struct itemstack stack)
+{
+       struct list **ptr = &self->stacks;
+
+       if (stack.item->stackable) {
+               for (; *ptr != NULL; ptr = &(*ptr)->next) {
+                       struct itemstack *other = (*ptr)->element;
+                       if (other->item == stack.item) {
+                               other->count += stack.count;
+                               return;
+                       }
+               }
+       }
+
+       *ptr = add_element(*ptr, make_buffer(&stack, sizeof(struct itemstack)));
+}
+
+/*
+
+bool inventory_remove(struct inventory *self, struct itemstack *stack)
+{
+       stack.count = -stack.count;
+
+       for (struct list **ptr = &self->stacks; *ptr != NULL; ) {
+               struct itemstack *other = (*ptr)->element;
+
+               if (other->item == stack.item) {
+                       stack.count += other->count;
+
+                       if (stack.count > 0) {
+                               other->count = stack.count;
+                               return true;
+                       } else {
+                               struct list *next = ptr->next;
+
+                               other->count = 0;
+
+                               if (other->item->on_destroy)
+                                       other->item->on_destroy(other);
+
+                               free(other);
+                               free(*ptr);
+
+                               *ptr = next;
+                               continue;
+                       }
+               }
+
+               ptr = &(*ptr)->next;
+       }
+
+       return false;
+}
+
+*/
+
+static void decrease_item_count(struct list **ptr, struct itemstack *stack)
+{
+       stack->count--;
+
+       if (stack->count == 0) {
+               struct list *next = (*ptr)->next;
+
+               if (stack->item->on_destroy)
+                       stack->item->on_destroy(stack);
+
+               free(stack);
+               free(*ptr);
+
+               *ptr = next;
+       }
+}
+
+bool inventory_remove(struct inventory *self, struct item *item)
+{
+       for (struct list **ptr = &self->stacks; *ptr != NULL; ptr = &(*ptr)->next) {
+               struct itemstack *stack = (*ptr)->element;
+
+               if (stack->item == item) {
+                       decrease_item_count(ptr, stack);
+
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static void handle_enter()
+{
+       int i = 0;
+
+       for (struct list **ptr = &player_inventory.stacks; *ptr != NULL; ptr = &(*ptr)->next, i++) {
+               if (i == selected_index) {
+                       struct itemstack *stack = (*ptr)->element;
+
+                       if (stack->item->on_use && stack->item->on_use(stack))
+                               decrease_item_count(ptr, stack);
+
+                       return;
+               }
+       }
+}
+
+static void handle_arrow()
+{
+       char c = fgetc(stdin);
+       if (c == '[') {
+               char dir = fgetc(stdin);
+
+               int count = 0;
+
+               for (struct list *ptr = player_inventory.stacks; ptr != NULL; ptr = ptr->next)
+                       count++;
+
+               if (count == 0)
+                       return;
+
+               switch (dir) {
+                       case 'A':
+                               selected_index--;
+
+                               if (selected_index < 0)
+                                       selected_index = count - 1;
+                               break;
+                       case 'B':
+                               selected_index++;
+
+                               if (selected_index >= count)
+                                       selected_index = 0;
+
+                               break;
+               }
+       } else {
+               ungetc(c, stdin);
+       }
+}
+
+static void render_inventory(struct winsize ws)
+{
+       printf("\e[3;0H");
+
+       printf(" \e[1mInventory\e[21m\n");
+
+       set_color(gray, false);
+
+       int i = 0;
+       for (struct list *ptr = player_inventory.stacks; ptr != NULL; ptr = ptr->next, i++) {
+               struct itemstack *stack = ptr->element;
+
+               if (i == selected_index) {
+                       printf(" \e[39m→ ");
+                       set_color(gray, false);
+               } else {
+                       printf("   ");
+               }
+
+               printf("%s", stack->item->name);
+
+               if (stack->count > 1) {
+                       set_color(darkgray, false);
+                       printf(" (x%u)", stack->count);
+                       set_color(gray, false);
+               }
+
+               printf("\n");
+       }
+}
+
+__attribute__ ((constructor)) static void init()
+{
+       gray = get_color("#9E9E9E");
+       darkgray = get_color("#555555");
+
+       register_render_component(&render_inventory);
+
+       register_input_handler('\033', (struct input_handler) {
+               .run_if_dead = false,
+               .callback = &handle_arrow,
+       });
+
+       register_input_handler('\n', (struct input_handler) {
+               .run_if_dead = false,
+               .callback = &handle_enter,
+       });
+}
diff --git a/plugins/inventory/inventory.h b/plugins/inventory/inventory.h
new file mode 100644 (file)
index 0000000..4b13f94
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _INVENTORY_H_
+#define _INVENTORY_H_
+#include "../game/game.h"
+
+struct itemstack
+{
+       struct item *item;
+       int count;
+       void *meta;
+};
+
+struct item
+{
+       char *name;
+       bool stackable;
+
+       bool (*on_use)(struct itemstack *stack);
+       void (*on_destroy)(struct itemstack *stack);
+};
+
+struct inventory
+{
+       struct list *stacks;
+};
+
+void inventory_add(struct inventory *self, struct itemstack stack);
+bool inventory_remove(struct inventory *self, struct item *item);
+
+extern struct inventory player_inventory;
+#endif