/* Enemy.c: Routines for the enemy player */ #include #include "defs.h" #include "structs.h" #include "vars.h" #include "protos.h" /* Return TRUE if we should all flee from this battle */ boolean best_withdraw_plan(int starnum, float enodds) { tplanet *pplanet; int size; tteam team; team = none; size = 0; for (pplanet = stars[starnum].first_planet; pplanet; pplanet = pplanet->next) { if ( pplanet->capacity > size ) { size = pplanet->capacity; team = pplanet->team; } } if (((enodds<0.70) && (size<30)) || ((enodds<0.50) && (team==player)) || ((enodds<0.30) && (size<60)) || ( enodds<0.20)) return(TRUE); else return(FALSE); } /* Enemy attack at a planet */ void enemy_attack(int starnum) { int attack_factors,def_factors; float odds,best_score; struct stplanet *pplanet,*best_planet; int en_tf,i; boolean first[8]; for (i = 1 ; i<=7; i++) first[i] = true; en_tf = 1; while ((tf[ENEMY][en_tf].dest!=starnum) || (tf[ENEMY][en_tf].eta != 0 )) en_tf++; do { attack_factors = tf[ENEMY][en_tf].c + 6*tf[ENEMY][en_tf].b; best_planet = nil; best_score = 1000; /* Calculate the best one to attack */ for (pplanet = stars[starnum].first_planet; pplanet != NULL; pplanet = pplanet->next) { if (pplanet->team == player) { def_factors = pplanet->esee_def; odds = (float)def_factors / attack_factors; if (pplanet->capacity > 30) odds = (odds - 2) * pplanet->capacity; else odds = (odds - 1.5) * pplanet->capacity; if (odds < best_score) { best_score = odds; best_planet = pplanet; } } } /* Found one that was worth attacking */ if (best_score < 0) { clear_left(); point(1,19); printf("Enemy attacks: %c%d", starnum+'A'-1, best_planet->number); point(50,1); print_star(starnum); clear_field(); pause(); fire_salvo(ENEMY, en_tf, best_planet, first[best_planet->number]); first[best_planet->number] = false; zero_tf(ENEMY,en_tf); best_planet->esee_def = best_planet->mb + 6*best_planet->amb; pause(); } } while ((best_score < 0) && any_bc(ENEMY, starnum)); revolt(starnum); } void depart(int starnum) { if ((tf_stars[starnum][player] + col_stars[starnum][player]) > 0) en_departures[starnum]=true; } /* How much do we care about moving ships to this planet */ int eval_bc_col(struct stplanet *planet) { int result; if (!(stars[planet->pstar].visit[ENEMY])) result = 600; else { switch (planet->esee_team) { case none: result=100; break; case ENEMY: if (planet->conquered) result = 1000; else { if (((6*planet->amb + planet->mb) <= (planet->iu/15)) && (planet->iu >= mb_cost)) result = 300; else result = 0; } if (planet->amb >= 4) result = result - 250; break; case player: if (planet->conquered) result = 400; else result = 200; break; } if ((planet->capacity < 40) && (planet->iu < 15)) result = result - 100; } result = result + rnd(20); return (result); } int eval_t_col(struct stplanet *planet, float range) { int result; if (!stars[planet->pstar].visit[ENEMY]) result=60; else { switch (planet->esee_team) { case none: result = 40; break; case ENEMY: result= 30; break; case player: result = 0; } if ((planet->esee_team != player) && (planet->capacity-planet->inhabitants > 40-(turn/2))) result = result + 40; } result -= (int)(2*range + .5); return(result); } void inputmach() { int tfnum,starnum; float slist[MAX_NUM_STARS+1]; for (tfnum = 1 ; tfnum<=26; tfnum++) { if ((tf[ENEMY][tfnum].eta==0) && (tf[ENEMY][tfnum].dest!=0)) { starnum = tf[ENEMY][tfnum].dest; get_stars(starnum,slist); send_scouts(slist,&tf[ENEMY][tfnum]); send_transports(slist,&tf[ENEMY][tfnum]); move_bc(&tf[ENEMY][tfnum],slist); zero_tf(ENEMY,tfnum); } } } void move_bc(struct sttf *task, float slist[]) { int best_star, top_score, starnum, score, factors; struct stplanet *pplanet, *best_planet; if ((task->b>0) || (task->c > 0)) { for (starnum = 1; starnum <= nstars; starnum++) { if (slist[starnum] > 0) { best_star = starnum; break; } } best_planet = NULL; top_score = -1000; for (starnum = 1; starnum<=nstars; starnum++) { if ((slist[starnum] > 0) || (starnum==task->dest)) { pplanet = stars[starnum].first_planet; while (pplanet != NULL ) { score = eval_bc_col(pplanet) ; if (starnum == task->dest) score += 250; if (tf_stars[starnum][ENEMY] > 0) score -= 150; if (score > top_score) { top_score = score; best_planet = pplanet; best_star = starnum; } pplanet = pplanet->next; } } } if (best_star == task->dest) { /* stay put */ if ((best_planet != NULL) && (best_planet->team == ENEMY) && (best_planet->conquered)) { if (best_planet->iu < 20) /* Blast it! */ { factors = weapons[ENEMY] * ((task->c*c_guns)+(task->b*b_guns)); factors = min(factors, 4 * best_planet->inhabitants); blast(best_planet,factors); if ((tf_stars[best_planet->pstar][player] > 0) || (col_stars[best_planet->pstar][player] > 0)) best_planet->psee_capacity = best_planet->capacity; } else { /* Decide whether to split*/ if ((((task->b > 3) || (task->c > 3)) && (rnd(4)==4)) || (task->b > 8)) wander_bc(task,slist); } } } else { /*move*/ tf_stars[task->dest][ENEMY]--; depart(task->dest); task->dest = best_star; task->eta = (int)((slist[best_star]-0.01)/vel[ENEMY])+1; } } } void send_transports(float slist[], struct sttf *task) { int new_tf, to_land, sec_star, sec_score, best_star, top_score, score,starnum; struct stplanet *pplan, *best_plan; int trash; if (task->t > 0) { best_star = 0; sec_star = 0; sec_score = -11000; top_score = -10000; best_plan = nil; for (starnum = 1; starnum<=nstars; starnum++) { if ((slist[starnum] > 0) || (starnum == task->dest)) { pplan = stars[starnum].first_planet; while (pplan != nil) { score = eval_t_col(pplan,slist[starnum]); if (score > sec_score) { if (score > top_score) { sec_score = top_score; sec_star = best_star; top_score = score; best_star = starnum; best_plan = pplan; } else { sec_score = score; sec_star = starnum; } } pplan = pplan->next; } } } /* For */ if (best_star == task->dest) { /* Land */ if ((tf_stars[best_star][player]==0) && (best_plan->team != player)) { trash = (best_plan->capacity - best_plan->inhabitants)/3; to_land = min(task->t, trash); if (to_land > 0) { if (best_plan->inhabitants == 0) { best_plan->team = ENEMY; best_plan->esee_team = ENEMY; col_stars[best_star][ENEMY]++; } best_plan->inhabitants += to_land; best_plan->iu += to_land; task->t -= to_land; send_transports(slist, task); } } } else { /* Move */ if ((task->t >= 10) && (sec_star > 0)) { /* First send half to the best star, if two stars */ new_tf = get_tf(ENEMY,task->dest); tf[ENEMY][new_tf].t = task->t/2; task->t = task->t-tf[ENEMY][new_tf].t; if ((task->c > 0) && (!underdefended(task->dest))) { tf[ENEMY][new_tf].c = 1; task->c--; } send_t_tf(&tf[ENEMY][new_tf],slist,best_star); best_star = sec_star; } new_tf = get_tf(ENEMY,task->dest); tf[ENEMY][new_tf].t = task->t; task->t = 0; if ((task->c > 0) && (!underdefended(task->dest))) { tf[ENEMY][new_tf].c = 1; task->c--; } send_t_tf(&tf[ENEMY][new_tf], slist, best_star); } } } void send_t_tf(struct sttf *task, float slist[], int dest_star) { depart(task->dest); task->dest = dest_star; task->eta = (int)((slist[dest_star]-0.01)/vel[ENEMY])+1; } void send_scouts(float slist[], struct sttf *task) { int dest, new_tf, j, doind; int doable[MAX_NUM_STARS+1]; if (task->s > 0) { doind=0; for (j = 1; j<=nstars; j++) { if ((!stars[j].visit[ENEMY]) && (slist[j]>0)) { doind++; doable[doind]=j; } } while ((doind>0) && (task->s > 0)) { new_tf = get_tf(ENEMY,task->dest); tf[ENEMY][new_tf].s = 1; dest = rnd(doind); tf[ENEMY][new_tf].dest = doable[dest]; tf[ENEMY][new_tf].eta = (int)((slist[doable[dest]]-0.01)/vel[ENEMY])+1; depart(task->dest); doable[dest] = doable[doind]; doind--; task->s--; } while (task->s > 0) { do { dest = rnd(nstars); } while (slist[dest] <= 0); new_tf = get_tf(ENEMY,task->dest); tf[ENEMY][new_tf].s = 1; tf[ENEMY][new_tf].dest = dest; tf[ENEMY][new_tf].eta = (int)((slist[dest]-0.01)/vel[ENEMY])+1; depart(task->dest); task->s--; } } } boolean underdefended(int starnum) { struct stplanet *pplanet; boolean result; result = false; pplanet = stars[starnum].first_planet; while ((pplanet != NULL) && (!result)) { if ((pplanet->team==ENEMY) && (pplanet->iu > 10) && ((6*pplanet->amb+pplanet->mb) < round(pplanet->iu/15.0))) return(TRUE); pplanet = pplanet->next; } return(FALSE); } void wander_bc(struct sttf *task, float slist[]) { int ships,i,count,dest,new_tf; if ((task->b > 1) || (task->c > 1)) { count = 0; for (i = 1 ; i<=nstars; i++) { if (slist[i] != 0) count++; } if (count > 0) { dest = rnd(count); for (count = 0, i = 0; count != dest; i++) if (slist[i]>0) count++; new_tf = get_tf(ENEMY, task->dest); ships = task->b/2; tf[ENEMY][new_tf].b = ships; task->b = task->b - ships; ships = task->c/2; tf[ENEMY][new_tf].c = ships; task->c = task->c - ships; if (task->t > 3) { tf[ENEMY][new_tf].t = 2; task->t = task->t-2; } tf[ENEMY][new_tf].dest = i; tf[ENEMY][new_tf].eta = (int)((slist[i]-0.01)/vel[ENEMY])+1; depart(task->dest); } } } void inv_enemy(int x, int y, struct stplanet *planet) { int inv_amount,balance,min_mb,transports,new_tf; balance = planet->iu; if (tf_stars[planet->pstar][ENEMY] == 0) { new_tf = get_tf(ENEMY,planet->pstar); tf_stars[planet->pstar][ENEMY]=1; } else { /*use present tf*/ new_tf = 1; while ((tf[ENEMY][new_tf].dest != planet->pstar) || (tf[ENEMY][new_tf].eta != 0)) new_tf++; } /* Build a minimum of missile bases */ min_mb = planet->capacity/20; while ((planet->amb == 0) && (!planet->conquered) && (planet->mb < min_mb) && (balance >= mb_cost)) { balance = balance - mb_cost; planet->mb++; } /* Build an amb more */ if ((balance >= b_cost) && (planet->amb > 1) && (rnd(5) != 1) && (rnd(7) <= planet->amb+3)) { balance = balance - b_cost; tf[ENEMY][new_tf].b++; } /* Maybe build the first one */ if ((balance >= amb_cost) && (!planet->conquered) && ((planet->amb < 4) || (rnd(2)==2))) { balance = balance - amb_cost; planet->amb++; } while (balance >= 9) { switch (rnd(12)) { case 1: /* Research something */ case 2: research(ENEMY, en_research, 8); balance = balance-8; break; case 3: case 4: case 10: /* Build some small things */ if (balance >= c_cost) { balance = balance - c_cost; tf[ENEMY][new_tf].c++; } else if ((!planet->conquered) && (balance >= mb_cost)) { balance = balance - mb_cost; planet->mb++; } else { balance = balance - 9; research(ENEMY, en_research, 9); } break; case 11: /* Build some transports */ case 12: if (((float)planet->inhabitants/planet->capacity < 0.6) || ((planet->capacity >= b_cost/iu_ratio) && (planet->iu < b_cost+10))) { /* No t's - invest instead*/ inv_amount = min(3, planet->inhabitants*iu_ratio - planet->iu); balance = balance - inv_amount*i_cost; planet->iu = planet->iu + inv_amount; } else /*build transports*/ if(!(planet->conquered)) { transports = min(rnd(2)+6, planet->inhabitants-1); if (planet->iu > b_cost) transports = min(transports,planet->iu - b_cost); balance = balance - transports; planet->inhabitants = planet->inhabitants - transports; planet->iu = min(planet->iu-transports,planet->inhabitants*iu_ratio); tf[ENEMY][new_tf].t = tf[ENEMY][new_tf].t + transports; } break; default: /* Just invest some */ inv_amount = min(3,planet->inhabitants*iu_ratio - planet->iu); balance = balance - i_cost*inv_amount; planet->iu = planet->iu + inv_amount; break; } /*switch */ } /*while */ zero_tf(ENEMY,new_tf); research(ENEMY,en_research,balance); }