aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElias Fleckenstein <eliasfleckenstein@web.de>2021-06-11 21:11:37 +0200
committerElias Fleckenstein <eliasfleckenstein@web.de>2021-06-11 21:11:37 +0200
commit30c560e271499cb461372a6798e53bf122a7495e (patch)
tree8d3022047c8b83d5a95e14c1fa488b0c8702be52
parent14d315712d372932b27a118171865118a6b415c7 (diff)
downloaddungeon_game-30c560e271499cb461372a6798e53bf122a7495e.tar.xz
Add inventory and cherries (collectable food)
-rw-r--r--plugins/cherry/Makefile4
-rw-r--r--plugins/cherry/cherry.c71
-rw-r--r--plugins/cherry/dependencies.txt3
-rw-r--r--plugins/game/game.c33
-rw-r--r--plugins/game/game.h8
-rw-r--r--plugins/inventory/Makefile4
-rw-r--r--plugins/inventory/dependencies.txt1
-rw-r--r--plugins/inventory/inventory.c203
-rw-r--r--plugins/inventory/inventory.h30
9 files changed, 341 insertions, 16 deletions
diff --git a/plugins/cherry/Makefile b/plugins/cherry/Makefile
new file mode 100644
index 0000000..edb1f44
--- /dev/null
+++ b/plugins/cherry/Makefile
@@ -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
index 0000000..072aec0
--- /dev/null
+++ b/plugins/cherry/cherry.c
@@ -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
index 0000000..4952514
--- /dev/null
+++ b/plugins/cherry/dependencies.txt
@@ -0,0 +1,3 @@
+game
+score
+inventory
diff --git a/plugins/game/game.c b/plugins/game/game.c
index 40bfa51..8dacf4a 100644
--- a/plugins/game/game.c
+++ b/plugins/game/game.c
@@ -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"),
diff --git a/plugins/game/game.h b/plugins/game/game.h
index f4cd53b..11d39ba 100644
--- a/plugins/game/game.h
+++ b/plugins/game/game.h
@@ -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
index 0000000..a665b55
--- /dev/null
+++ b/plugins/inventory/Makefile
@@ -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
index 0000000..dc22e61
--- /dev/null
+++ b/plugins/inventory/dependencies.txt
@@ -0,0 +1 @@
+game
diff --git a/plugins/inventory/inventory.c b/plugins/inventory/inventory.c
new file mode 100644
index 0000000..c3b533d
--- /dev/null
+++ b/plugins/inventory/inventory.c
@@ -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
index 0000000..4b13f94
--- /dev/null
+++ b/plugins/inventory/inventory.h
@@ -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