Combat
Source: src/dungeon_combat.c · 79 lines · 7 functions.
Module responsibility
Creates encounters and resolves attacks, escape attempts, enemy turns and health-potion use.
Module entry points
These functions are exposed to the rest of the Dungeon system. Open one to follow its decisions and helper calls.
How to read these diagrams
Each function has an expandable structural diagram derived from the current C source. Decisions split into True and False, loop bodies are indented, and arrows show statement order.
These are source diagrams before preprocessing, not runtime traces. Callback execution, task scheduling and macro expansion are not inferred.
Functions in this file
combatDamage() · source line 6
static uint32_t combatDamage(uint16_t attack, uint16_t defence)
Calls into this documentation:
- Execute
const DungeonConfig *config = getDungeonConfig(); - Execute
const uint32_t roll = 1U + esp_random() % config->combatDiceSides; - Execute
const uint32_t total = (uint32_t)attack + roll; - Exit this function
return total > defence && total - defence > config->combatMinimumDamage ? total - defence : config->combatMinimumDamage;
Read original function source
static uint32_t combatDamage(uint16_t attack, uint16_t defence)
{
const DungeonConfig *config = getDungeonConfig();
const uint32_t roll = 1U + esp_random() % config->combatDiceSides;
const uint32_t total = (uint32_t)attack + roll;
return total > defence && total - defence > config->combatMinimumDamage ? total - defence : config->combatMinimumDamage;
}applyDamage() · source line 14
static void applyDamage(uint16_t *health, uint32_t damage)
- Execute
*health = damage >= *health ? 0U : (uint16_t)(*health - damage);
Read original function source
static void applyDamage(uint16_t *health, uint32_t damage)
{
*health = damage >= *health ? 0U : (uint16_t)(*health - damage);
}enemyAttack() · source line 19
static DungeonCombatResult enemyAttack(DungeonCombatState *state, DungeonPlayerState *player)
Calls into this documentation:
- Execute
state->lastEnemyDamage = combatDamage(state->attack, player->defence); - Execute
applyDamage(&player->health, state->lastEnemyDamage); - Exit this function
return player->health == 0U ? DUNGEON_COMBAT_PLAYER_DEFEATED : DUNGEON_COMBAT_CONTINUES;
Read original function source
static DungeonCombatResult enemyAttack(DungeonCombatState *state, DungeonPlayerState *player)
{
state->lastEnemyDamage = combatDamage(state->attack, player->defence);
applyDamage(&player->health, state->lastEnemyDamage);
return player->health == 0U ? DUNGEON_COMBAT_PLAYER_DEFEATED : DUNGEON_COMBAT_CONTINUES;
}startDungeonCombat() · source line 26
bool startDungeonCombat(uint8_t enemy_type, DungeonCombatState *state)
Calls into this documentation:
- Decision
state == NULLTrue- Exit this function
return false;
FalseContinue after this decision.
- Execute
const DungeonConfig *config = getDungeonConfig(); - Execute
memset(state, 0, sizeof(*state)); - Execute
state->enemyType = enemy_type; - Select a case
enemy_typeEnter matching case; follow source fall-through until a break, return or end.
- Case / label
case DUNGEON_ENEMY_LEVEL_1: - Execute
state->health = config->enemyLevel1Health; - Execute
state->attack = config->enemyLevel1Attack; - Execute
state->defence = config->enemyLevel1Defence; - Execute
state->xpReward = config->enemyLevel1Xp; - Exit enclosing loop or switch
break; - Case / label
case DUNGEON_ENEMY_LEVEL_2: - Execute
state->health = config->enemyLevel2Health; - Execute
state->attack = config->enemyLevel2Attack; - Execute
state->defence = config->enemyLevel2Defence; - Execute
state->xpReward = config->enemyLevel2Xp; - Exit enclosing loop or switch
break; - Case / label
case DUNGEON_ENEMY_LEVEL_3: - Execute
state->health = config->enemyLevel3Health; - Execute
state->attack = config->enemyLevel3Attack; - Execute
state->defence = config->enemyLevel3Defence; - Execute
state->xpReward = config->enemyLevel3Xp; - Exit enclosing loop or switch
break; - Case / label
case DUNGEON_ENEMY_LEVEL_4: - Execute
state->health = config->enemyLevel4Health; - Execute
state->attack = config->enemyLevel4Attack; - Execute
state->defence = config->enemyLevel4Defence; - Execute
state->xpReward = config->enemyLevel4Xp; - Exit enclosing loop or switch
break; - Case / label
case DUNGEON_ENEMY_DRAGON: - Execute
state->health = config->dragonHealth; - Execute
state->attack = config->dragonAttack; - Execute
state->defence = config->dragonDefence; - Execute
state->xpReward = config->dragonXp; - Exit enclosing loop or switch
break; - Case / label
default: - Exit this function
return false;
- Execute
state->maxHealth = state->health; - Exit this function
return true;
Read original function source
bool startDungeonCombat(uint8_t enemy_type, DungeonCombatState *state)
{
if (state == NULL) return false;
const DungeonConfig *config = getDungeonConfig();
memset(state, 0, sizeof(*state));
state->enemyType = enemy_type;
switch (enemy_type) {
case DUNGEON_ENEMY_LEVEL_1:
state->health = config->enemyLevel1Health; state->attack = config->enemyLevel1Attack;
state->defence = config->enemyLevel1Defence; state->xpReward = config->enemyLevel1Xp; break;
case DUNGEON_ENEMY_LEVEL_2:
state->health = config->enemyLevel2Health; state->attack = config->enemyLevel2Attack;
state->defence = config->enemyLevel2Defence; state->xpReward = config->enemyLevel2Xp; break;
case DUNGEON_ENEMY_LEVEL_3:
state->health = config->enemyLevel3Health; state->attack = config->enemyLevel3Attack;
state->defence = config->enemyLevel3Defence; state->xpReward = config->enemyLevel3Xp; break;
case DUNGEON_ENEMY_LEVEL_4:
state->health = config->enemyLevel4Health; state->attack = config->enemyLevel4Attack;
state->defence = config->enemyLevel4Defence; state->xpReward = config->enemyLevel4Xp; break;
case DUNGEON_ENEMY_DRAGON:
state->health = config->dragonHealth; state->attack = config->dragonAttack;
state->defence = config->dragonDefence; state->xpReward = config->dragonXp; break;
default: return false;
}
state->maxHealth = state->health;
return true;
}dungeonCombatAttack() · source line 54
DungeonCombatResult dungeonCombatAttack(DungeonCombatState *state, DungeonPlayerState *player)
Calls into this documentation:
- Execute
state->lastPlayerDamage = 0U; - Execute
state->lastEnemyDamage = 0U; - Execute
state->lastPlayerDamage = combatDamage(player->attack, state->defence); - Execute
applyDamage(&state->health, state->lastPlayerDamage); - Exit this function
return state->health == 0U ? DUNGEON_COMBAT_ENEMY_DEFEATED : enemyAttack(state, player);
Read original function source
DungeonCombatResult dungeonCombatAttack(DungeonCombatState *state, DungeonPlayerState *player)
{
state->lastPlayerDamage = 0U;
state->lastEnemyDamage = 0U;
state->lastPlayerDamage = combatDamage(player->attack, state->defence);
applyDamage(&state->health, state->lastPlayerDamage);
return state->health == 0U ? DUNGEON_COMBAT_ENEMY_DEFEATED : enemyAttack(state, player);
}dungeonCombatAttemptRun() · source line 63
DungeonCombatResult dungeonCombatAttemptRun(DungeonCombatState *state, DungeonPlayerState *player)
Calls into this documentation:
- Execute
state->lastPlayerDamage = 0U; - Execute
state->lastEnemyDamage = 0U; - Decision
esp_random() % 100U < getDungeonConfig()->runChancePercentTrue- Exit this function
return DUNGEON_COMBAT_ESCAPED;
FalseContinue after this decision.
- Exit this function
return enemyAttack(state, player) == DUNGEON_COMBAT_PLAYER_DEFEATED ? DUNGEON_COMBAT_PLAYER_DEFEATED : DUNGEON_COMBAT_RUN_FAILED;
Read original function source
DungeonCombatResult dungeonCombatAttemptRun(DungeonCombatState *state, DungeonPlayerState *player)
{
state->lastPlayerDamage = 0U;
state->lastEnemyDamage = 0U;
if (esp_random() % 100U < getDungeonConfig()->runChancePercent) return DUNGEON_COMBAT_ESCAPED;
return enemyAttack(state, player) == DUNGEON_COMBAT_PLAYER_DEFEATED ? DUNGEON_COMBAT_PLAYER_DEFEATED : DUNGEON_COMBAT_RUN_FAILED;
}dungeonCombatUsePotion() · source line 71
DungeonCombatResult dungeonCombatUsePotion(DungeonCombatState *state, DungeonPlayerState *player)
Calls into this documentation:
- Execute
state->lastPlayerDamage = 0U; - Execute
state->lastEnemyDamage = 0U; - Decision
player->healthPotions == 0UTrue- Exit this function
return DUNGEON_COMBAT_POTION_UNAVAILABLE;
FalseContinue after this decision.
- Execute
--player->healthPotions; - Execute
player->health = player->maxHealth; - Exit this function
return enemyAttack(state, player);
Read original function source
DungeonCombatResult dungeonCombatUsePotion(DungeonCombatState *state, DungeonPlayerState *player)
{
state->lastPlayerDamage = 0U;
state->lastEnemyDamage = 0U;
if (player->healthPotions == 0U) return DUNGEON_COMBAT_POTION_UNAVAILABLE;
--player->healthPotions;
player->health = player->maxHealth;
return enemyAttack(state, player);
}Complete original file, including constants and data
/* Coded By JD(2026) */
#error "Reference listing only — not provided as build-ready source."
#include "dungeon_combat.h"
#include "dungeon_config.h"
#include "esp_random.h"
#include <string.h>
static uint32_t combatDamage(uint16_t attack, uint16_t defence)
{
const DungeonConfig *config = getDungeonConfig();
const uint32_t roll = 1U + esp_random() % config->combatDiceSides;
const uint32_t total = (uint32_t)attack + roll;
return total > defence && total - defence > config->combatMinimumDamage ? total - defence : config->combatMinimumDamage;
}
static void applyDamage(uint16_t *health, uint32_t damage)
{
*health = damage >= *health ? 0U : (uint16_t)(*health - damage);
}
static DungeonCombatResult enemyAttack(DungeonCombatState *state, DungeonPlayerState *player)
{
state->lastEnemyDamage = combatDamage(state->attack, player->defence);
applyDamage(&player->health, state->lastEnemyDamage);
return player->health == 0U ? DUNGEON_COMBAT_PLAYER_DEFEATED : DUNGEON_COMBAT_CONTINUES;
}
bool startDungeonCombat(uint8_t enemy_type, DungeonCombatState *state)
{
if (state == NULL) return false;
const DungeonConfig *config = getDungeonConfig();
memset(state, 0, sizeof(*state));
state->enemyType = enemy_type;
switch (enemy_type) {
case DUNGEON_ENEMY_LEVEL_1:
state->health = config->enemyLevel1Health; state->attack = config->enemyLevel1Attack;
state->defence = config->enemyLevel1Defence; state->xpReward = config->enemyLevel1Xp; break;
case DUNGEON_ENEMY_LEVEL_2:
state->health = config->enemyLevel2Health; state->attack = config->enemyLevel2Attack;
state->defence = config->enemyLevel2Defence; state->xpReward = config->enemyLevel2Xp; break;
case DUNGEON_ENEMY_LEVEL_3:
state->health = config->enemyLevel3Health; state->attack = config->enemyLevel3Attack;
state->defence = config->enemyLevel3Defence; state->xpReward = config->enemyLevel3Xp; break;
case DUNGEON_ENEMY_LEVEL_4:
state->health = config->enemyLevel4Health; state->attack = config->enemyLevel4Attack;
state->defence = config->enemyLevel4Defence; state->xpReward = config->enemyLevel4Xp; break;
case DUNGEON_ENEMY_DRAGON:
state->health = config->dragonHealth; state->attack = config->dragonAttack;
state->defence = config->dragonDefence; state->xpReward = config->dragonXp; break;
default: return false;
}
state->maxHealth = state->health;
return true;
}
DungeonCombatResult dungeonCombatAttack(DungeonCombatState *state, DungeonPlayerState *player)
{
state->lastPlayerDamage = 0U;
state->lastEnemyDamage = 0U;
state->lastPlayerDamage = combatDamage(player->attack, state->defence);
applyDamage(&state->health, state->lastPlayerDamage);
return state->health == 0U ? DUNGEON_COMBAT_ENEMY_DEFEATED : enemyAttack(state, player);
}
DungeonCombatResult dungeonCombatAttemptRun(DungeonCombatState *state, DungeonPlayerState *player)
{
state->lastPlayerDamage = 0U;
state->lastEnemyDamage = 0U;
if (esp_random() % 100U < getDungeonConfig()->runChancePercent) return DUNGEON_COMBAT_ESCAPED;
return enemyAttack(state, player) == DUNGEON_COMBAT_PLAYER_DEFEATED ? DUNGEON_COMBAT_PLAYER_DEFEATED : DUNGEON_COMBAT_RUN_FAILED;
}
DungeonCombatResult dungeonCombatUsePotion(DungeonCombatState *state, DungeonPlayerState *player)
{
state->lastPlayerDamage = 0U;
state->lastEnemyDamage = 0U;
if (player->healthPotions == 0U) return DUNGEON_COMBAT_POTION_UNAVAILABLE;
--player->healthPotions;
player->health = player->maxHealth;
return enemyAttack(state, player);
}