kitchen: README + MISSIONS/engine-c keep-drop notes
This commit is contained in:
parent
1d351918da
commit
575d7d29b8
130 changed files with 9817 additions and 1 deletions
124
engine-c/src/ai.c
Normal file
124
engine-c/src/ai.c
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue