diff --git a/src/audio.h b/src/audio.h index 8950980..a574a9a 100644 --- a/src/audio.h +++ b/src/audio.h @@ -25,4 +25,4 @@ void audio_play_player_damage(void); // Play stairs/level change sound void audio_play_stairs(void); -#endif // AUDIO_H +#endif // AUDIO_H diff --git a/src/combat.c b/src/combat.c index 2caa0e5..064e4c8 100644 --- a/src/combat.c +++ b/src/combat.c @@ -11,11 +11,17 @@ typedef struct { static CombatEvent last_event = {NULL, 0, 0}; -const char *combat_get_last_message(void) { return last_event.message; } +const char *combat_get_last_message(void) { + return last_event.message; +} -int combat_get_last_damage(void) { return last_event.damage; } +int combat_get_last_damage(void) { + return last_event.damage; +} -int combat_was_player_damage(void) { return last_event.is_player_damage; } +int combat_was_player_damage(void) { + return last_event.is_player_damage; +} void combat_player_attack(Player *p, Enemy *e) { if (e == NULL || !e->alive) diff --git a/src/combat.h b/src/combat.h index cc44794..e969754 100644 --- a/src/combat.h +++ b/src/combat.h @@ -21,4 +21,4 @@ void combat_player_attack(Player *p, Enemy *e); // Enemy attacks player void combat_enemy_attack(Enemy *e, Player *p); -#endif // COMBAT_H +#endif // COMBAT_H diff --git a/src/enemy.h b/src/enemy.h index fdd260b..d7b2e6c 100644 --- a/src/enemy.h +++ b/src/enemy.h @@ -10,6 +10,6 @@ void enemy_spawn(Enemy enemies[], int *count, Map *map, Player *p, int floor); void enemy_update_all(Enemy enemies[], int count, Player *p, Map *map); // Check if position has an enemy -int is_enemy_at(Enemy *enemies, int count, int x, int y); +int is_enemy_at(const Enemy *enemies, int count, int x, int y); -#endif // ENEMY_H +#endif // ENEMY_H diff --git a/src/items.c b/src/items.c index ebe41eb..b5d3e6b 100644 --- a/src/items.c +++ b/src/items.c @@ -40,15 +40,15 @@ void item_spawn(Item items[], int *count, Map *map, int floor) { if (type_roll < 50) { // 50% chance for potion item.type = ITEM_POTION; - item.power = 5 + rng_int(0, floor * 2); // healing: 5 + 0-2*floor + item.power = 5 + rng_int(0, floor * 2); // healing: 5 + 0-2*floor } else if (type_roll < 80) { // 30% chance for weapon item.type = ITEM_WEAPON; - item.power = 1 + rng_int(0, floor); // attack bonus: 1 + 0-floor + item.power = 1 + rng_int(0, floor); // attack bonus: 1 + 0-floor } else { // 20% chance for armor item.type = ITEM_ARMOR; - item.power = 1 + rng_int(0, floor / 2); // defense bonus + item.power = 1 + rng_int(0, floor / 2); // defense bonus } items[i] = item; diff --git a/src/items.h b/src/items.h index c54e827..7798323 100644 --- a/src/items.h +++ b/src/items.h @@ -11,4 +11,4 @@ void item_spawn(Item items[], int *count, Map *map, int floor); // Use an item void item_use(Player *p, Item *i); -#endif // ITEMS_H +#endif // ITEMS_H diff --git a/src/main.c b/src/main.c index e08d341..9430bfd 100644 --- a/src/main.c +++ b/src/main.c @@ -10,57 +10,42 @@ #include "rng.h" #include "settings.h" #include - -// Global game state -static Player player; -static Map map; -static Dungeon dungeon; -static Enemy enemies[MAX_ENEMIES]; -static int enemy_count; -static Item items[MAX_ITEMS]; -static int item_count; -static int game_over = 0; -static int game_won = 0; -static const char *last_message = NULL; -static int message_timer = 0; - -// Turn counter for enemy movement (enemies move every other turn) -static int turn_count = 0; +#include // Initialize a new floor -static void init_floor(int floor_num) { +static void init_floor(GameState *gs, int floor_num) { // Generate dungeon - dungeon_generate(&dungeon, &map, floor_num); + dungeon_generate(&gs->dungeon, &gs->map, floor_num); // Seed rng for this floor's content rng_seed(floor_num * 54321); // Find spawn position int start_x, start_y; - get_random_floor_tile(&map, &start_x, &start_y, 100); + get_random_floor_tile(&gs->map, &start_x, &start_y, 100); // Initialize player position if first floor if (floor_num == 1) { - player_init(&player, start_x, start_y); + player_init(&gs->player, start_x, start_y); } else { // Move player to new floor position - player.x = start_x; - player.y = start_y; + gs->player.x = start_x; + gs->player.y = start_y; } - player.floor = floor_num; + gs->player.floor = floor_num; // Spawn enemies - enemy_spawn(enemies, &enemy_count, &map, &player, floor_num); + enemy_spawn(gs->enemies, &gs->enemy_count, &gs->map, &gs->player, floor_num); // Spawn items - item_spawn(items, &item_count, &map, floor_num); + item_spawn(gs->items, &gs->item_count, &gs->map, floor_num); // Reset turn counter - turn_count = 0; + gs->turn_count = 0; } -// Handle player input - returns: 0=continue, -1=quit -static int handle_input(void) { +// Handle player input - returns: 0=continue, 1=acted, -1=quit +static int handle_input(GameState *gs) { int dx = 0, dy = 0; // Check for quit first (always works) @@ -69,21 +54,20 @@ static int handle_input(void) { } // Check for restart (works during game over) - if (IsKeyPressed(KEY_R) && game_over) { - game_over = 0; - game_won = 0; - init_floor(1); + if (IsKeyPressed(KEY_R) && gs->game_over) { + memset(gs, 0, sizeof(GameState)); + init_floor(gs, 1); return 0; } // Check for item usage (U key) - if (IsKeyPressed(KEY_U) && !game_over) { - if (player.inventory_count > 0) { - if (player_use_first_item(&player)) { - last_message = "Used item!"; - message_timer = 60; + if (IsKeyPressed(KEY_U) && !gs->game_over) { + if (gs->player.inventory_count > 0) { + if (player_use_first_item(&gs->player)) { + gs->last_message = "Used item!"; + gs->message_timer = 60; audio_play_item_pickup(); - return 1; // consume a turn + return 1; // consume a turn } } } @@ -103,45 +87,56 @@ static int handle_input(void) { // Reset combat message combat_reset_event(); - // Player action + // Check for item at target position before moving + int new_x = gs->player.x + dx; + int new_y = gs->player.y + dy; + int will_pickup = 0; + for (int i = 0; i < gs->item_count; i++) { + if (!gs->items[i].picked_up && gs->items[i].x == new_x && gs->items[i].y == new_y) { + will_pickup = 1; + break; + } + } - int action = player_move(&player, dx, dy, &map, enemies, enemy_count, items, - item_count); + // Player action + int action = player_move(&gs->player, dx, dy, &gs->map, gs->enemies, gs->enemy_count, gs->items, gs->item_count); if (action) { + // Play pickup sound if item was picked up + if (will_pickup) { + audio_play_item_pickup(); + } // Increment turn counter - turn_count++; + gs->turn_count++; // Check if stepped on stairs - - if (map.tiles[player.y][player.x] == TILE_STAIRS) { + if (gs->map.tiles[gs->player.y][gs->player.x] == TILE_STAIRS) { // Go to next floor - if (player.floor < NUM_FLOORS) { + if (gs->player.floor < NUM_FLOORS) { audio_play_stairs(); - init_floor(player.floor + 1); - last_message = "Descended to next floor!"; - message_timer = 60; + init_floor(gs, gs->player.floor + 1); + gs->last_message = "Descended to next floor!"; + gs->message_timer = 60; } else { // Won the game - game_won = 1; - game_over = 1; + gs->game_won = 1; + gs->game_over = 1; } } // Check if killed enemy - if (combat_get_last_message() != NULL && !combat_was_player_damage()) { // Check if enemy died - for (int i = 0; i < enemy_count; i++) { - if (!enemies[i].alive) { + for (int i = 0; i < gs->enemy_count; i++) { + if (!gs->enemies[i].alive) { audio_play_enemy_death(); } } } // Enemy turn - only every other turn for fairness - if (turn_count % 2 == 0) { - enemy_update_all(enemies, enemy_count, &player, &map); + if (gs->turn_count % 2 == 0) { + enemy_update_all(gs->enemies, gs->enemy_count, &gs->player, &gs->map); } // Check if player took damage @@ -150,12 +145,12 @@ static int handle_input(void) { } // Set message - last_message = combat_get_last_message(); - message_timer = 60; + gs->last_message = combat_get_last_message(); + gs->message_timer = 60; // Check game over - if (player.hp <= 0) { - game_over = 1; + if (gs->player.hp <= 0) { + gs->game_over = 1; } } } @@ -165,17 +160,20 @@ static int handle_input(void) { // Main game loop static void game_loop(void) { + GameState gs; + memset(&gs, 0, sizeof(GameState)); + // Initialize first floor rng_seed(12345); - init_floor(1); + init_floor(&gs, 1); // Disable esc to exit SetExitKey(0); while (!WindowShouldClose()) { // Handle input - if (!game_over) { - int quit = handle_input(); + if (!gs.game_over) { + int quit = handle_input(&gs); if (quit == -1) break; } else { @@ -183,41 +181,41 @@ static void game_loop(void) { if (IsKeyPressed(KEY_Q)) break; if (IsKeyPressed(KEY_R)) { - game_over = 0; - game_won = 0; - init_floor(1); + memset(&gs, 0, sizeof(GameState)); + gs.game_over = 0; + gs.game_won = 0; + init_floor(&gs, 1); } } // Update message timer - if (message_timer > 0) - message_timer--; + if (gs.message_timer > 0) + gs.message_timer--; // Render BeginDrawing(); ClearBackground(BLACK); // Draw game elements - render_map(&map); - render_items(items, item_count); - render_enemies(enemies, enemy_count); - render_player(&player); - render_ui(&player); + render_map(&gs.map); + render_items(gs.items, gs.item_count); + render_enemies(gs.enemies, gs.enemy_count); + render_player(&gs.player); + render_ui(&gs.player); // Draw message if any - if (last_message != NULL && message_timer > 0) { - render_message(last_message); + if (gs.last_message != NULL && gs.message_timer > 0) { + render_message(gs.last_message); } // Draw game over screen - if (game_over) { + if (gs.game_over) { render_game_over(); - if (game_won) { + if (gs.game_won) { // Draw win message const char *win_msg = "YOU WIN! ESCAPED THE DUNGEON!"; int msg_w = MeasureText(win_msg, 30); - DrawText(win_msg, (SCREEN_WIDTH - msg_w) / 2, SCREEN_HEIGHT / 2 - 80, - 30, GOLD); + DrawText(win_msg, (SCREEN_WIDTH - msg_w) / 2, SCREEN_HEIGHT / 2 - 80, 30, GOLD); } } diff --git a/src/player.h b/src/player.h index c7cd3fa..0ccab25 100644 --- a/src/player.h +++ b/src/player.h @@ -7,8 +7,7 @@ void player_init(Player *p, int x, int y); // Move player, return 1 if moved/attacked, 0 if blocked -int player_move(Player *p, int dx, int dy, Map *map, Enemy *enemies, - int enemy_count, Item *items, int item_count); +int player_move(Player *p, int dx, int dy, Map *map, Enemy *enemies, int enemy_count, Item *items, int item_count); // Player attacks enemy (deal damage) void player_attack(Player *p, Enemy *e); @@ -25,4 +24,4 @@ int player_use_first_item(Player *p); // Get item at inventory index, returns NULL if invalid Item *player_get_inventory_item(Player *p, int index); -#endif // PLAYER_H +#endif // PLAYER_H diff --git a/src/render.h b/src/render.h index 32e26e7..6ec6469 100644 --- a/src/render.h +++ b/src/render.h @@ -4,19 +4,19 @@ #include "common.h" // Render the map tiles -void render_map(Map *map); +void render_map(const Map *map); // Render the player -void render_player(Player *p); +void render_player(const Player *p); // Render all enemies -void render_enemies(Enemy *enemies, int count); +void render_enemies(const Enemy *enemies, int count); // Render all items -void render_items(Item *items, int count); +void render_items(const Item *items, int count); // Render UI overlay -void render_ui(Player *p); +void render_ui(const Player *p); // Render game over screen void render_game_over(void); @@ -24,4 +24,4 @@ void render_game_over(void); // Render a message popup void render_message(const char *message); -#endif // RENDER_H +#endif // RENDER_H diff --git a/src/rng.c b/src/rng.c index 2efcce7..62d6fcf 100644 --- a/src/rng.c +++ b/src/rng.c @@ -6,7 +6,7 @@ static unsigned int g_seed = 1; // LCG parameters (from numerical recipes) #define LCG_A 1664525 #define LCG_C 1013904223 -#define LCG_MOD 4294967294 // 2^32 - 2 (avoid 0) +#define LCG_MOD 4294967294 // 2^32 - 2 (avoid 0) void rng_seed(unsigned int seed) { // Ensure seed is never 0 diff --git a/src/rng.h b/src/rng.h index 94bad67..a89c798 100644 --- a/src/rng.h +++ b/src/rng.h @@ -7,4 +7,4 @@ void rng_seed(unsigned int seed); // Get a random integer in range [min, max] int rng_int(int min, int max); -#endif // RNG_H +#endif // RNG_H diff --git a/src/settings.h b/src/settings.h index d5978fb..47f3c12 100644 --- a/src/settings.h +++ b/src/settings.h @@ -25,4 +25,4 @@ #define NUM_FLOORS 5 #define MAX_INVENTORY 10 -#endif // SETTINGS_H +#endif // SETTINGS_H diff --git a/src/utils.h b/src/utils.h index e638c0d..211cf44 100644 --- a/src/utils.h +++ b/src/utils.h @@ -7,4 +7,4 @@ int clamp(int value, int min, int max); // Check if coordinates are within map bounds int in_bounds(int x, int y, int width, int height); -#endif // UTILS_H +#endif // UTILS_H