kitchen: README + MISSIONS/engine-c keep-drop notes

This commit is contained in:
Hernâni Marques 2026-09-17 21:48:48 +02:00
parent 1d351918da
commit 575d7d29b8
No known key found for this signature in database
130 changed files with 9817 additions and 1 deletions

124
engine-c/src/ai.c Normal file
View file

@ -0,0 +1,124 @@
#include "kknd.h"
/* =========================================================================
* ai.c - Enemy/human commander. Grows an economy and launches attack waves.
* ========================================================================= */
static Building *ai_find_bld(Game *g, Faction f, BuildingType t) {
for (int i = 0; i < g->bld_count; i++) {
Building *b = &g->buildings[i];
if (b->dead || b->faction != f || b->type != t) continue;
if (b->build < 1.0f) continue;
return b;
}
return NULL;
}
static int ai_count_units(Game *g, Faction f, int combat_only) {
int n = 0;
for (int i = 0; i < g->unit_count; i++) {
Unit *u = &g->units[i];
if (u->dead || u->faction != f) continue;
if (combat_only && (u->type == UT_HARVESTER)) continue;
n++;
}
return n;
}
static int ai_count_harvesters(Game *g, Faction f) {
int n = 0;
for (int i = 0; i < g->unit_count; i++) {
Unit *u = &g->units[i];
if (u->dead || u->faction != f) continue;
if (u->type == UT_HARVESTER) n++;
}
return n;
}
static void ai_run_faction(Game *g, Faction f) {
Building *base = ai_find_bld(g, f, BT_BASE);
Building *wf = ai_find_bld(g, f, BT_WARFACTORY);
Building *ref = ai_find_bld(g, f, BT_REFINERY);
if (!base) return;
/* early defensive turret */
if (g->time < 60 && g->scrap[f] > 600) {
int bx = base->tx + 3, by = base->ty - 2;
if (bld_can_place(g, BT_TURRET, bx, by)) {
if (bld_spawn(g, BT_TURRET, f, bx, by) >= 0)
g->scrap[f] -= bld_def(BT_TURRET)->cost;
}
}
/* research lab + upgrades */
if (!ai_find_bld(g, f, BT_RESEARCH) && g->scrap[f] > 400) {
int bx = base->tx - 3, by = base->ty + 2;
if (bld_can_place(g, BT_RESEARCH, bx, by)) {
int r = bld_spawn(g, BT_RESEARCH, f, bx, by);
if (r >= 0) g->scrap[f] -= bld_def(BT_RESEARCH)->cost;
}
}
if (g->research_lab[f] > 0 && g->research_cur[f] < 0) {
int best = -1, bestlv = 99;
for (int u = 0; u < UP_COUNT; u++) {
if (g->upg[f].lvl[u] >= UP_MAX_LVL) continue;
if (g->upg[f].lvl[u] < bestlv) { bestlv = g->upg[f].lvl[u]; best = u; }
}
if (best >= 0) bld_research(g, f, best);
}
/* keep harvesters flowing */
if (ref && ai_count_harvesters(g, f) < 4 && g->scrap[f] >= 300)
bld_queue_unit(g, (int)(ref - g->buildings), UT_HARVESTER);
/* pump combat units */
if (wf) {
int combat = ai_count_units(g, f, 1);
int cap = (g->diff == DIFF_HARD) ? 40 : (g->diff == DIFF_NORMAL ? 28 : 18);
if (combat < cap) {
int r = rng_range(&(RNG){0}, 0, 6);
UnitType pick = (r == 0) ? UT_BUGGY : (r == 1) ? UT_TANK
: (r == 2) ? UT_ARTILLERY : (r == 3) ? UT_JEEP
: (r == 4) ? UT_RAVAGER : (r == 5) ? UT_FLAME
: UT_MISSILE;
bld_queue_unit(g, (int)(wf - g->buildings), pick);
}
}
/* attack wave every ~35s once we have a force */
g->ai_wave[f] += (g->diff == DIFF_HARD ? 4.0f : (g->diff == DIFF_NORMAL ? 6.0f : 9.0f));
if (g->ai_wave[f] >= 35.0f) {
g->ai_wave[f] = 0;
Faction foe = (f == g->human) ? g->enemy : g->human;
int hx = g->map.spawn_x[foe], hy = g->map.spawn_y[foe];
float tx, ty; map_tile_to_world(hx, hy, &tx, &ty);
int launched = 0;
for (int i = 0; i < g->unit_count; i++) {
Unit *u = &g->units[i];
if (u->dead || u->faction != f) continue;
if (u->type == UT_HARVESTER) continue;
unit_issue_move(g, (int)(u - g->units), tx, ty, 1);
launched++;
}
if (launched > 0) {
engine_log("%s warband (%d) advances on the %s!",
faction_name(f), launched, faction_name(foe));
if (f == g->human)
game_log(g, "Warband (%d units) sent to attack!", launched);
}
}
}
void ai_command(Faction f, int diff) { (void)f; (void)diff; }
void ai_update(Game *g, float dt) {
g->ai_timer -= dt;
if (g->ai_timer > 0) return;
float interval = (g->diff == DIFF_HARD) ? 4.0f :
(g->diff == DIFF_NORMAL ? 6.0f : 9.0f);
g->ai_timer = interval;
ai_run_faction(g, g->enemy);
if (g_auto) ai_run_faction(g, g->human);
}