2023-11-26 15:11:45 -05:00
|
|
|
/*
|
|
|
|
Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic
|
|
|
|
|
|
|
|
Xhartae is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation.
|
|
|
|
And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version.
|
|
|
|
It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "../chapter/chapter_0.c"
|
|
|
|
#include "../chapter/chapter_1.c"
|
|
|
|
#include "../chapter/chapter_2.c"
|
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
static int entity_define (char * name, int character, int colour, int effect, int value, int logic, void (* trigger) (void));
|
2023-11-29 10:32:11 -05:00
|
|
|
static void entity_create (int entity, int amount);
|
|
|
|
static void entity_render (int entity);
|
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
static void entity_clean_up (void);
|
|
|
|
static void entity_update_logic (void);
|
|
|
|
|
|
|
|
static int player_x = 0;
|
|
|
|
static int player_y = 0;
|
|
|
|
static int player_coins = 0;
|
2023-11-29 10:32:11 -05:00
|
|
|
|
|
|
|
static int entity_count = 0;
|
|
|
|
static char * * entity_name = NULL;
|
|
|
|
static char * entity_character = '\0';
|
|
|
|
static int * entity_colour = 0;
|
|
|
|
static int * entity_effect = 0;
|
|
|
|
static int * entity_value = 0;
|
|
|
|
static int * entity_logic = 0;
|
2023-11-30 10:38:53 -05:00
|
|
|
|
|
|
|
static void (* * entity_trigger) (void) = NULL;
|
|
|
|
|
|
|
|
static int entity_usage = 0;
|
|
|
|
static int * entity_index = 0;
|
|
|
|
static int * entity_x = 0;
|
|
|
|
static int * entity_y = 0;
|
2023-11-29 10:32:11 -05:00
|
|
|
|
2023-11-26 15:11:45 -05:00
|
|
|
static void player_move_up (void) { player_y -= 1; limit (& player_y, 0, curses_screen_height - 1); }
|
|
|
|
static void player_move_down (void) { player_y += 1; limit (& player_y, 0, curses_screen_height - 1); }
|
|
|
|
static void player_move_left (void) { player_x -= 1; limit (& player_x, 0, curses_screen_width - 1); }
|
|
|
|
static void player_move_right (void) { player_x += 1; limit (& player_x, 0, curses_screen_width - 1); }
|
2023-11-30 10:38:53 -05:00
|
|
|
static void player_take_coin (void) { ++player_coins; }
|
|
|
|
static void player_died (void) { curses_active = 0; }
|
2023-11-26 15:11:45 -05:00
|
|
|
|
|
|
|
int main (void) {
|
|
|
|
terminal_show_cursor (FALSE);
|
|
|
|
|
|
|
|
curses_configure ();
|
2023-11-28 15:30:55 -05:00
|
|
|
|
2023-11-29 05:22:44 -05:00
|
|
|
curses_bind (SIGNAL_W, player_move_up);
|
|
|
|
curses_bind (SIGNAL_S, player_move_down);
|
|
|
|
curses_bind (SIGNAL_A, player_move_left);
|
|
|
|
curses_bind (SIGNAL_D, player_move_right);
|
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
int coin = entity_define ("Coin", '+', COLOUR_YELLOW, EFFECT_BOLD, 1, FALSE, player_take_coin);
|
|
|
|
int goblin = entity_define ("Goblin", 'g', COLOUR_RED, EFFECT_NORMAL, 3, TRUE, player_died);
|
|
|
|
int hob_goblin = entity_define ("Hob Goblin", 'G', COLOUR_RED, EFFECT_BOLD, 7, TRUE, player_died);
|
2023-11-29 10:32:11 -05:00
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
entity_create (coin, 11);
|
|
|
|
entity_create (goblin, 7);
|
|
|
|
entity_create (hob_goblin, 3);
|
2023-11-29 10:32:11 -05:00
|
|
|
|
2023-11-26 15:11:45 -05:00
|
|
|
while (curses_active) {
|
2023-11-29 05:22:44 -05:00
|
|
|
curses_render_background ('.', COLOUR_GREY, EFFECT_BOLD);
|
|
|
|
|
2023-11-29 06:56:22 -05:00
|
|
|
curses_render_rectangle_fill (',', COLOUR_GREEN, EFFECT_NORMAL, 10, 10, 80, 24);
|
|
|
|
curses_render_rectangle_line ('#', COLOUR_WHITE, EFFECT_NORMAL, 10, 10, 80, 24);
|
2023-11-29 05:22:44 -05:00
|
|
|
|
2023-11-29 10:32:11 -05:00
|
|
|
for (int entity = 0; entity < entity_usage; ++entity) {
|
|
|
|
entity_render (entity);
|
|
|
|
}
|
|
|
|
|
2023-11-29 05:22:44 -05:00
|
|
|
curses_render_character ('@', COLOUR_CYAN, EFFECT_BOLD, player_x, player_y);
|
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
curses_render_number (player_coins, COLOUR_YELLOW, EFFECT_BOLD, 0, 0);
|
|
|
|
|
|
|
|
entity_update_logic ();
|
|
|
|
|
2023-11-26 15:11:45 -05:00
|
|
|
curses_synchronize ();
|
|
|
|
}
|
|
|
|
|
2023-11-29 10:32:11 -05:00
|
|
|
entity_clean_up ();
|
|
|
|
|
2023-11-26 15:11:45 -05:00
|
|
|
terminal_show_cursor (TRUE);
|
|
|
|
|
|
|
|
return (EXIT_SUCCESS);
|
|
|
|
}
|
2023-11-29 10:32:11 -05:00
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
static int entity_define (char * name, int character, int colour, int effect, int value, int logic, void (* trigger) (void)) {
|
|
|
|
int entity = entity_count;
|
2023-11-29 10:32:11 -05:00
|
|
|
|
|
|
|
++entity_count;
|
|
|
|
|
|
|
|
entity_name = reallocate (entity_name, entity_count * (int) sizeof (* entity_name));
|
|
|
|
entity_character = reallocate (entity_character, entity_count * (int) sizeof (* entity_character));
|
|
|
|
entity_colour = reallocate (entity_colour, entity_count * (int) sizeof (* entity_colour));
|
|
|
|
entity_effect = reallocate (entity_effect, entity_count * (int) sizeof (* entity_effect));
|
|
|
|
entity_value = reallocate (entity_value, entity_count * (int) sizeof (* entity_value));
|
|
|
|
entity_logic = reallocate (entity_logic, entity_count * (int) sizeof (* entity_logic));
|
2023-11-30 10:38:53 -05:00
|
|
|
entity_trigger = reallocate (entity_trigger, entity_count * (int) sizeof (* entity_trigger));
|
2023-11-29 10:32:11 -05:00
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
string_copy ((entity_name [entity] = allocate (string_length (name) + 1)), name);
|
2023-11-29 10:32:11 -05:00
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
entity_character [entity] = character;
|
|
|
|
entity_colour [entity] = colour;
|
|
|
|
entity_effect [entity] = effect;
|
|
|
|
entity_value [entity] = value;
|
|
|
|
entity_logic [entity] = logic;
|
|
|
|
entity_trigger [entity] = trigger;
|
2023-11-29 10:32:11 -05:00
|
|
|
|
2023-11-30 10:38:53 -05:00
|
|
|
return (entity);
|
2023-11-29 10:32:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void entity_create (int entity, int amount) {
|
|
|
|
int index;
|
|
|
|
|
|
|
|
for (index = 0; index < amount; ++index) {
|
|
|
|
++entity_usage;
|
|
|
|
|
|
|
|
entity_index = reallocate (entity_index, entity_usage * (int) sizeof (* entity_index));
|
|
|
|
entity_x = reallocate (entity_x, entity_usage * (int) sizeof (* entity_x));
|
|
|
|
entity_y = reallocate (entity_y, entity_usage * (int) sizeof (* entity_y));
|
|
|
|
|
|
|
|
entity_index [entity_usage - 1] = entity;
|
|
|
|
entity_x [entity_usage - 1] = randomize (0, curses_screen_width - 1);
|
|
|
|
entity_y [entity_usage - 1] = randomize (0, curses_screen_height - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void entity_render (int entity) {
|
2023-11-30 10:38:53 -05:00
|
|
|
if (entity_index [entity] == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-11-29 10:32:11 -05:00
|
|
|
curses_render_character (entity_character [entity_index [entity]],
|
|
|
|
entity_colour [entity_index [entity]],
|
|
|
|
entity_effect [entity_index [entity]],
|
|
|
|
entity_x [entity],
|
|
|
|
entity_y [entity]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void entity_clean_up (void) {
|
|
|
|
for (int entity = 0; entity < entity_count; ++entity) {
|
|
|
|
entity_name [entity] = deallocate (entity_name [entity]);
|
|
|
|
}
|
|
|
|
|
|
|
|
entity_name = deallocate (entity_name);
|
|
|
|
entity_character = deallocate (entity_character);
|
|
|
|
entity_colour = deallocate (entity_colour);
|
|
|
|
entity_effect = deallocate (entity_effect);
|
|
|
|
entity_value = deallocate (entity_value);
|
|
|
|
entity_logic = deallocate (entity_logic);
|
2023-11-30 10:38:53 -05:00
|
|
|
entity_trigger = deallocate (entity_trigger);
|
2023-11-29 10:32:11 -05:00
|
|
|
entity_index = deallocate (entity_index);
|
|
|
|
entity_x = deallocate (entity_x);
|
|
|
|
entity_y = deallocate (entity_y);
|
|
|
|
|
|
|
|
entity_count = 0;
|
|
|
|
entity_usage = 0;
|
|
|
|
}
|
2023-11-30 10:38:53 -05:00
|
|
|
|
|
|
|
void entity_update_logic (void) {
|
|
|
|
for (int entity = 0; entity < entity_usage; ++entity) {
|
|
|
|
if (entity_index [entity] == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entity_logic [entity_index [entity]] == TRUE) {
|
|
|
|
entity_x [entity] += randomize (0, 1) * ((randomize (0, 1) == 0) ? +1 : -1);
|
|
|
|
entity_y [entity] += randomize (0, 1) * ((randomize (0, 1) == 0) ? +1 : -1);
|
|
|
|
|
|
|
|
limit (& entity_x [entity], 0, curses_screen_width - 1);
|
|
|
|
limit (& entity_y [entity], 0, curses_screen_height - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((player_x == entity_x [entity]) && (player_y == entity_y [entity])) {
|
|
|
|
if (entity_trigger [entity_index [entity]] != NULL) {
|
|
|
|
entity_trigger [entity_index [entity]] ();
|
|
|
|
}
|
|
|
|
|
|
|
|
entity_index [entity] = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|