X-Git-Url: https://jxself.org/git/?p=super-star-trek.git;a=blobdiff_plain;f=src%2Fai.c;h=31d19ad13bdcf06293ab473679a9abfc09a817a5;hp=4b1aa23b274ef783850492f21d3c50ea78b1ee2d;hb=2c5438d3c22fe863ad8054d214f2afdd061ad43a;hpb=52265793501a00845a0d6108d1af6e50e3ece379 diff --git a/src/ai.c b/src/ai.c index 4b1aa23..31d19ad 100644 --- a/src/ai.c +++ b/src/ai.c @@ -1,78 +1,122 @@ #include "sst.h" -static int tryexit(int lookx, int looky, int ienm, int loccom, int irun) +static bool tryexit(coord look, int ienm, int loccom, bool irun) +/* a bad guy attempts to bug out */ { - int iqx, iqy, l; + int n; + coord iq; - iqx = game.quadx+(lookx+(QUADSIZE-1))/QUADSIZE - 1; - iqy = game.quady+(looky+(QUADSIZE-1))/QUADSIZE - 1; - if (!VALID_QUADRANT(iqx,iqy) || - game.state.galaxy[iqx][iqy].supernova || - game.state.galaxy[iqx][iqy].klingons > 8) - return 0; /* no can do -- neg energy, supernovae, or >8 Klingons */ - if (ienm == IHR) return 0; /* Romulans cannot escape! */ - if (irun == 0) { + iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1; + iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1; + if (!VALID_QUADRANT(iq.x,iq.y) || + game.state.galaxy[iq.x][iq.y].supernova || + game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1) + return false; /* no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons */ + if (ienm == IHR) + return false; /* Romulans cannot escape! */ + if (!irun) { /* avoid intruding on another commander's territory */ if (ienm == IHC) { - for_commanders(l) - if (game.state.cx[l]==iqx && game.state.cy[l]==iqy) return 0; + for (n = 1; n <= game.state.remcom; n++) + if (same(game.state.kcmdr[n],iq)) + return false; /* refuse to leave if currently attacking starbase */ - if (game.batx==game.quadx && game.baty==game.quady) return 0; + if (same(game.battle, game.quadrant)) + return false; } /* don't leave if over 1000 units of energy */ - if (game.kpower[loccom] > 1000.) return 0; + if (game.kpower[loccom] > 1000.0) + return false; } - /* print escape message and move out of quadrant. - We know this if either short or long range sensors are working */ - if (game.damage[DSRSENS] == 0.0 || game.damage[DLRSENS] == 0.0 || - game.condit == IHDOCKED) { - crmena(1, ienm, 2, game.kx[loccom], game.ky[loccom]); - prout(" escapes to %s (and regains strength).", - cramlc(quadrant, iqx, iqy)); + // print escape message and move out of quadrant. + // We know this if either short or long range sensors are working + if (!damaged(DSRSENS) || !damaged(DLRSENS) || + game.condition == docked) { + crmena(true, ienm, sector, game.ks[loccom]); + prout(_(" escapes to %s (and regains strength)."), + cramlc(quadrant, iq)); } /* handle local matters related to escape */ - game.quad[game.kx[loccom]][game.ky[loccom]] = IHDOT; - game.kx[loccom] = game.kx[game.nenhere]; - game.ky[loccom] = game.ky[game.nenhere]; + game.quad[game.ks[loccom].x][game.ks[loccom].y] = IHDOT; + game.ks[loccom] = game.ks[game.nenhere]; game.kavgd[loccom] = game.kavgd[game.nenhere]; game.kpower[loccom] = game.kpower[game.nenhere]; game.kdist[loccom] = game.kdist[game.nenhere]; game.klhere--; game.nenhere--; - if (game.condit != IHDOCKED) newcnd(); + if (game.condition != docked) + newcnd(); /* Handle global matters related to escape */ - game.state.galaxy[game.quadx][game.quady].klingons--; - game.state.galaxy[iqx][iqy].klingons++; + game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons--; + game.state.galaxy[iq.x][iq.y].klingons++; if (ienm==IHS) { - game.ishere=0; - game.iscate=0; - game.ientesc=0; - game.isatb=0; - game.future[FSCMOVE]=0.2777+game.state.date; - game.future[FSCDBAS]=FOREVER; - game.state.isx=iqx; - game.state.isy=iqy; + game.ishere = false; + game.iscate = false; + game.ientesc = false; + game.isatb = 0; + schedule(FSCMOVE, 0.2777); + unschedule(FSCDBAS); + game.state.kscmdr=iq; } else { - for_commanders(l) { - if (game.state.cx[l]==game.quadx && game.state.cy[l]==game.quady) { - game.state.cx[l]=iqx; - game.state.cy[l]=iqy; + for (n = 1; n <= game.state.remcom; n++) { + if (same(game.state.kcmdr[n], game.quadrant)) { + game.state.kcmdr[n]=iq; break; } } - game.comhere = 0; + game.comhere = false; } - return 1; /* success */ + return true; /* success */ } +/************************************************************************* +The bad-guy movement algorithm: + +1. Enterprise has "force" based on condition of phaser and photon torpedoes. +If both are operating full strength, force is 1000. If both are damaged, +force is -1000. Having shields down subtracts an additional 1000. + +2. Enemy has forces equal to the energy of the attacker plus +100*(K+R) + 500*(C+S) - 400 for novice through good levels OR +346*K + 400*R + 500*(C+S) - 400 for expert and emeritus. + +Attacker Initial energy levels (nominal): +Klingon Romulan Commander Super-Commander +Novice 400 700 1200 +Fair 425 750 1250 +Good 450 800 1300 1750 +Expert 475 850 1350 1875 +Emeritus 500 900 1400 2000 +VARIANCE 75 200 200 200 + +Enemy vessels only move prior to their attack. In Novice - Good games +only commanders move. In Expert games, all enemy vessels move if there +is a commander present. In Emeritus games all enemy vessels move. + +3. If Enterprise is not docked, an agressive action is taken if enemy +forces are 1000 greater than Enterprise. -static void movebaddy(int comx, int comy, int loccom, int ienm) +Agressive action on average cuts the distance between the ship and +the enemy to 1/4 the original. + +4. At lower energy advantage, movement units are proportional to the +advantage with a 650 advantage being to hold ground, 800 to move forward +1, 950 for two, 150 for back 4, etc. Variance of 100. + +If docked, is reduced by roughly 1.75*game.skill, generally forcing a +retreat, especially at high skill levels. + +5. Motion is limited to skill level, except for SC hi-tailing it out. +**************************************************************************/ + +static void movebaddy(coord com, int loccom, feature ienm) +/* tactical movement for the bad guys */ { - int motion, mdist, nsteps, mx, my, nextx, nexty, lookx, looky, ll; - int irun = 0; + int motion, mdist, nsteps, mx, my, ll; + coord next, look; int krawlx, krawly; - int success; + bool success, irun = false; int attempts; /* This should probably be just game.comhere + game.ishere */ int nbaddys = game.skill >= SKILL_EXPERT ? @@ -85,58 +129,21 @@ static void movebaddy(int comx, int comy, int loccom, int ienm) /* If SC, check with spy to see if should hi-tail it */ if (ienm==IHS && - (game.kpower[loccom] <= 500.0 || (game.condit==IHDOCKED && game.damage[DPHOTON]==0))) { - irun = 1; + (game.kpower[loccom] <= 500.0 || (game.condition==docked && !damaged(DPHOTON)))) { + irun = true; motion = -QUADSIZE; } else { /* decide whether to advance, retreat, or hold position */ -/* Algorithm: - * Enterprise has "force" based on condition of phaser and photon torpedoes. - If both are operating full strength, force is 1000. If both are damaged, - force is -1000. Having shields down subtracts an additional 1000. - - * Enemy has forces equal to the energy of the attacker plus - 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR - 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus. - - Attacker Initial energy levels (nominal): - Klingon Romulan Commander Super-Commander - Novice 400 700 1200 - Fair 425 750 1250 - Good 450 800 1300 1750 - Expert 475 850 1350 1875 - Emeritus 500 900 1400 2000 - VARIANCE 75 200 200 200 - - Enemy vessels only move prior to their attack. In Novice - Good games - only commanders move. In Expert games, all enemy vessels move if there - is a commander present. In Emeritus games all enemy vessels move. - - * If Enterprise is not docked, an agressive action is taken if enemy - forces are 1000 greater than Enterprise. - - Agressive action on average cuts the distance between the ship and - the enemy to 1/4 the original. - - * At lower energy advantage, movement units are proportional to the - advantage with a 650 advantage being to hold ground, 800 to move forward - 1, 950 for two, 150 for back 4, etc. Variance of 100. - - If docked, is reduced by roughly 1.75*game.skill, generally forcing a - retreat, especially at high skill levels. - - * Motion is limited to skill level, except for SC hi-tailing it out. - */ - forces = game.kpower[loccom]+100.0*game.nenhere+400*(nbaddys-1); - if (game.shldup==0) forces += 1000; /* Good for enemy if shield is down! */ - if (game.damage[DPHASER] == 0.0 || game.damage[DPHOTON] == 0.0) { - if (game.damage[DPHASER] != 0) /* phasers damaged */ + if (!game.shldup) + forces += 1000; /* Good for enemy if shield is down! */ + if (!damaged(DPHASER) || !damaged(DPHOTON)) { + if (damaged(DPHASER)) /* phasers damaged */ forces += 300.0; else forces -= 0.2*(game.energy - 2500.0); - if (game.damage[DPHOTON] != 0) /* photon torpedoes damaged */ + if (damaged(DPHOTON)) /* photon torpedoes damaged */ forces += 300.0; else forces -= 50.0*game.torps; @@ -146,271 +153,271 @@ static void movebaddy(int comx, int comy, int loccom, int ienm) forces += 1000.0; } motion = 0; - if (forces <= 1000.0 && game.condit != IHDOCKED) /* Typical situation */ + if (forces <= 1000.0 && game.condition != docked) /* Typical situation */ motion = ((forces+200.0*Rand())/150.0) - 5.0; else { if (forces > 1000.0) /* Very strong -- move in for kill */ motion = (1.0-square(Rand()))*dist1 + 1.0; - if (game.condit==IHDOCKED && (game.options & OPTION_BASE)) /* protected by base -- back off ! */ + if (game.condition==docked && (game.options & OPTION_BASE)) /* protected by base -- back off ! */ motion -= game.skill*(2.0-square(Rand())); } -#ifdef DEBUG - if (game.idebug) { - proutn("MOTION = %1.2f", motion); - proutn(" FORCES = %1,2f", forces); - } -#endif + if (idebug) + proutn("=== MOTION = %d, FORCES = %1.2f, ", motion, forces); /* don't move if no motion */ - if (motion==0) return; + if (motion==0) + return; /* Limit motion according to skill */ - if (abs(motion) > game.skill) motion = (motion < 0) ? -game.skill : game.skill; + if (abs(motion) > game.skill) + motion = (motion < 0) ? -game.skill : game.skill; } /* calculate preferred number of steps */ nsteps = motion < 0 ? -motion : motion; - if (motion > 0 && nsteps > mdist) nsteps = mdist; /* don't overshoot */ - if (nsteps > QUADSIZE) nsteps = QUADSIZE; /* This shouldn't be necessary */ - if (nsteps < 1) nsteps = 1; /* This shouldn't be necessary */ -#ifdef DEBUG - if (game.idebug) { - prout("NSTEPS = %d", nsteps); + if (motion > 0 && nsteps > mdist) + nsteps = mdist; /* don't overshoot */ + if (nsteps > QUADSIZE) + nsteps = QUADSIZE; /* This shouldn't be necessary */ + if (nsteps < 1) + nsteps = 1; /* This shouldn't be necessary */ + if (idebug) { + proutn("NSTEPS = %d:", nsteps); } -#endif /* Compute preferred values of delta X and Y */ - mx = game.sectx - comx; - my = game.secty - comy; - if (2.0 * abs(mx) < abs(my)) mx = 0; - if (2.0 * abs(my) < abs(game.sectx-comx)) my = 0; - if (mx != 0) mx = mx*motion < 0 ? -1 : 1; - if (my != 0) my = my*motion < 0 ? -1 : 1; - nextx = comx; - nexty = comy; + mx = game.sector.x - com.x; + my = game.sector.y - com.y; + if (2.0 * abs(mx) < abs(my)) + mx = 0; + if (2.0 * abs(my) < abs(game.sector.x-com.x)) + my = 0; + if (mx != 0) + mx = mx*motion < 0 ? -1 : 1; + if (my != 0) + my = my*motion < 0 ? -1 : 1; + next = com; /* main move loop */ for (ll = 0; ll < nsteps; ll++) { -#ifdef DEBUG - if (game.idebug) { - prout("%d", ll+1); - } -#endif + if (idebug) + proutn(" %d", ll+1); /* Check if preferred position available */ - lookx = nextx + mx; - looky = nexty + my; + look.x = next.x + mx; + look.y = next.y + my; krawlx = mx < 0 ? 1 : -1; krawly = my < 0 ? 1 : -1; - success = 0; + success = false; attempts = 0; /* Settle mysterious hang problem */ while (attempts++ < 20 && !success) { - if (lookx < 1 || lookx > QUADSIZE) { - if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun)) + if (look.x < 1 || look.x > QUADSIZE) { + if (motion < 0 && tryexit(look, ienm, loccom, irun)) return; - if (krawlx == mx || my == 0) break; - lookx = nextx + krawlx; + if (krawlx == mx || my == 0) + break; + look.x = next.x + krawlx; krawlx = -krawlx; } - else if (looky < 1 || looky > QUADSIZE) { - if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun)) + else if (look.y < 1 || look.y > QUADSIZE) { + if (motion < 0 && tryexit(look, ienm, loccom, irun)) return; - if (krawly == my || mx == 0) break; - looky = nexty + krawly; + if (krawly == my || mx == 0) + break; + look.y = next.y + krawly; krawly = -krawly; } - else if ((game.options & OPTION_RAMMING) && game.quad[lookx][looky] != IHDOT) { + else if ((game.options & OPTION_RAMMING) && game.quad[look.x][look.y] != IHDOT) { /* See if we should ram ship */ - if (game.quad[lookx][looky] == game.ship && + if (game.quad[look.x][look.y] == game.ship && (ienm == IHC || ienm == IHS)) { - ram(1, ienm, comx, comy); + ram(true, ienm, com); return; } if (krawlx != mx && my != 0) { - lookx = nextx + krawlx; + look.x = next.x + krawlx; krawlx = -krawlx; } else if (krawly != my && mx != 0) { - looky = nexty + krawly; + look.y = next.y + krawly; krawly = -krawly; } - else break; /* we have failed */ + else + break; /* we have failed */ } - else success = 1; + else + success = true; } if (success) { - nextx = lookx; - nexty = looky; -#ifdef DEBUG - if (game.idebug) { - prout(cramlc(neither, nextx, nexty)); - } -#endif + next = look; + if (idebug) + proutn(cramlc(neither, next)); } - else break; /* done early */ + else + break; /* done early */ + } + if (idebug) + skip(1); /* Put commander in place within same quadrant */ - game.quad[comx][comy] = IHDOT; - game.quad[nextx][nexty] = ienm; - if (nextx != comx || nexty != comy) { + game.quad[com.x][com.y] = IHDOT; + game.quad[next.x][next.y] = ienm; + if (!same(next, com)) { /* it moved */ - game.kx[loccom] = nextx; - game.ky[loccom] = nexty; - game.kdist[loccom] = game.kavgd[loccom] = - sqrt(square(game.sectx-nextx)+square(game.secty-nexty)); - if (game.damage[DSRSENS] == 0 || game.condit == IHDOCKED) { + game.ks[loccom] = next; + game.kdist[loccom] = game.kavgd[loccom] = distance(game.sector, next); + if (!damaged(DSRSENS) || game.condition == docked) { proutn("***"); cramen(ienm); - proutn(" from %s", cramlc(2, comx, comy)); - if (game.kdist[loccom] < dist1) proutn(" advances to "); - else proutn(" retreats to "); - prout(cramlc(sector, nextx, nexty)); + proutn(_(" from %s"), cramlc(2, com)); + if (game.kdist[loccom] < dist1) + proutn(_(" advances to ")); + else + proutn(_(" retreats to ")); + prout(cramlc(sector, next)); } } } -void movcom(void) +void moveklings(void) +/* Klingon tactical movement */ { - int ix, iy, i; + coord w; + int i; -#ifdef DEBUG - if (game.idebug) prout("MOVCOM"); -#endif + if (idebug) + prout("== MOVCOM"); - /* Figure out which Klingon is the commander (or Supercommander) - and do move */ + // Figure out which Klingon is the commander (or Supercommander) + // and do move if (game.comhere) - for_local_enemies(i) { - ix = game.kx[i]; - iy = game.ky[i]; - if (game.quad[ix][iy] == IHC) { - movebaddy(ix, iy, i, IHC); + for (i = 1; i <= game.nenhere; i++) { + w = game.ks[i]; + if (game.quad[w.x][w.y] == IHC) { + movebaddy(w, i, IHC); break; } } if (game.ishere) - for_local_enemies(i) { - ix = game.kx[i]; - iy = game.ky[i]; - if (game.quad[ix][iy] == IHS) { - movebaddy(ix, iy, i, IHS); + for (i = 1; i <= game.nenhere; i++) { + w = game.ks[i]; + if (game.quad[w.x][w.y] == IHS) { + movebaddy(w, i, IHS); break; } } - /* if skill level is high, move other Klingons and Romulans too! - Move these last so they can base their actions on what the - commander(s) do. */ + // if skill level is high, move other Klingons and Romulans too! + // Move these last so they can base their actions on what the + // commander(s) do. if (game.skill >= SKILL_EXPERT && (game.options & OPTION_MVBADDY)) - for_local_enemies(i) { - ix = game.kx[i]; - iy = game.ky[i]; - if (game.quad[ix][iy] == IHK || game.quad[ix][iy] == IHR) - movebaddy(ix, iy, i, game.quad[ix][iy]); + for (i = 1; i <= game.nenhere; i++) { + w = game.ks[i]; + if (game.quad[w.x][w.y] == IHK || game.quad[w.x][w.y] == IHR) + movebaddy(w, i, game.quad[w.x][w.y]); } - sortkl(); + sortklings(); } -static int movescom(int iqx, int iqy, int flag, int *ipage) +static bool movescom(coord iq, bool avoid) +/* commander movement helper */ { int i; - if ((iqx==game.quadx && iqy==game.quady) || - !VALID_QUADRANT(iqx, iqy) || - game.state.galaxy[iqx][iqy].supernova || - game.state.galaxy[iqx][iqy].klingons > 8) + if (same(iq, game.quadrant) || !VALID_QUADRANT(iq.x, iq.y) || + game.state.galaxy[iq.x][iq.y].supernova || + game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1) return 1; - if (flag) { + if (avoid) { /* Avoid quadrants with bases if we want to avoid Enterprise */ - for_starbases(i) - if (game.state.baseqx[i]==iqx && game.state.baseqy[i]==iqy) return 1; + for (i = 1; i <= game.state.rembase; i++) + if (same(game.state.baseq[i], iq)) + return true; } - if (game.justin && !game.iscate) return 1; + if (game.justin && !game.iscate) + return true; /* do the move */ - game.state.galaxy[game.state.isx][game.state.isy].klingons--; - game.state.isx = iqx; - game.state.isy = iqy; - game.state.galaxy[game.state.isx][game.state.isy].klingons++; + game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons--; + game.state.kscmdr = iq; + game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons++; if (game.ishere) { /* SC has scooted, Remove him from current quadrant */ - game.iscate=0; + game.iscate=false; game.isatb=0; - game.ishere=0; - game.ientesc=0; - game.future[FSCDBAS]=FOREVER; - for_local_enemies(i) - if (game.quad[game.kx[i]][game.ky[i]] == IHS) break; - game.quad[game.kx[i]][game.ky[i]] = IHDOT; - game.kx[i] = game.kx[game.nenhere]; - game.ky[i] = game.ky[game.nenhere]; + game.ishere = false; + game.ientesc = false; + unschedule(FSCDBAS); + for (i = 1; i <= game.nenhere; i++) + if (game.quad[game.ks[i].x][game.ks[i].y] == IHS) + break; + game.quad[game.ks[i].x][game.ks[i].y] = IHDOT; + game.ks[i] = game.ks[game.nenhere]; game.kdist[i] = game.kdist[game.nenhere]; game.kavgd[i] = game.kavgd[game.nenhere]; game.kpower[i] = game.kpower[game.nenhere]; game.klhere--; game.nenhere--; - if (game.condit!=IHDOCKED) newcnd(); - sortkl(); + if (game.condition!=docked) + newcnd(); + sortklings(); } /* check for a helpful planet */ for (i = 0; i < game.inplan; i++) { - if (game.state.plnets[i].x==game.state.isx && game.state.plnets[i].y==game.state.isy && - game.state.plnets[i].crystals == 1) { + if (same(game.state.planets[i].w, game.state.kscmdr) && + game.state.planets[i].crystals == present) { /* destroy the planet */ - DESTROY(&game.state.plnets[i]); - game.state.galaxy[game.state.isx][game.state.isy].planet = NULL; - if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED) { - if (*ipage==0) pause_game(1); - *ipage = 1; - prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports"); - proutn(" a planet in "); - proutn(cramlc(quadrant, game.state.isx, game.state.isy)); - prout(" has been destroyed"); - prout(" by the Super-commander.\""); + game.state.planets[i].pclass = destroyed; + game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = NOPLANET; + if (!damaged(DRADIO) || game.condition == docked) { + pause_game(true); + prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports")); + proutn(_(" a planet in ")); + proutn(cramlc(quadrant, game.state.kscmdr)); + prout(_(" has been destroyed")); + prout(_(" by the Super-commander.\"")); } break; } } - return 0; /* looks good! */ + return false; /* looks good! */ } -void scom(int *ipage) +void supercommander(void) +/* move the Super Commander */ { - int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb; - int iqx, iqy; + int i, i2, j, ideltax, ideltay, ifindit, iwhichb; + coord iq, sc, ibq; int basetbl[BASEMAX+1]; double bdist[BASEMAX+1]; - int flag; -#ifdef DEBUG - if (game.idebug) prout("SCOM"); -#endif + bool avoid; + + if (idebug) + prout("== SUPERCOMMANDER"); /* Decide on being active or passive */ - flag = ((NKILLC+NKILLK)/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) || + avoid = ((NKILLC+NKILLK)/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) || (game.state.date-game.indate) < 3.0); - if (game.iscate==0 && flag) { + if (!game.iscate && avoid) { /* compute move away from Enterprise */ - ideltax = game.state.isx-game.quadx; - ideltay = game.state.isy-game.quady; + ideltax = game.state.kscmdr.x-game.quadrant.x; + ideltay = game.state.kscmdr.y-game.quadrant.y; if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) { /* circulate in space */ - ideltax = game.state.isy-game.quady; - ideltay = game.quadx-game.state.isx; + ideltax = game.state.kscmdr.y-game.quadrant.y; + ideltay = game.quadrant.x-game.state.kscmdr.x; } } else { /* compute distances to starbases */ if (game.state.rembase <= 0) { /* nothing left to do */ - game.future[FSCMOVE] = FOREVER; + unschedule(FSCMOVE); return; } - sx = game.state.isx; - sy = game.state.isy; - for_starbases(i) { + sc = game.state.kscmdr; + for (i = 1; i <= game.state.rembase; i++) { basetbl[i] = i; - ibqx = game.state.baseqx[i]; - ibqy = game.state.baseqy[i]; - bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy)); + bdist[i] = distance(game.state.baseq[i], sc); } if (game.state.rembase > 1) { /* sort into nearest first order */ - int iswitch; + bool iswitch; do { - iswitch = 0; + iswitch = false; for (i=1; i < game.state.rembase-1; i++) { if (bdist[i] > bdist[i+1]) { int ti = basetbl[i]; @@ -419,7 +426,7 @@ void scom(int *ipage) bdist[i+1] = t; basetbl[i] = basetbl[i+1]; basetbl[i+1] =ti; - iswitch = 1; + iswitch = true; } } } while (iswitch); @@ -428,19 +435,17 @@ void scom(int *ipage) without too many Klingons, and not already under attack. */ ifindit = iwhichb = 0; - for_starbases(i2) { + for (i2 = 1; i2 <= game.state.rembase; i2++) { i = basetbl[i2]; /* bug in original had it not finding nearest*/ - ibqx = game.state.baseqx[i]; - ibqy = game.state.baseqy[i]; - if ((ibqx == game.quadx && ibqy == game.quady) || - (ibqx == game.batx && ibqy == game.baty) || - game.state.galaxy[ibqx][ibqy].supernova || - game.state.galaxy[ibqx][ibqy].klingons > 8) + ibq = game.state.baseq[i]; + if (same(ibq, game.quadrant) || same(ibq, game.battle) || + game.state.galaxy[ibq.x][ibq.y].supernova || + game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1) continue; - /* if there is a commander, an no other base is appropriate, - we will take the one with the commander */ - for_commanders (j) { - if (ibqx==game.state.cx[j] && ibqy==game.state.cy[j] && ifindit!= 2) { + // if there is a commander, and no other base is appropriate, + // we will take the one with the commander + for (j = 1; j <= game.state.remcom; j++) { + if (same(ibq, game.state.kcmdr[j]) && ifindit!= 2) { ifindit = 2; iwhichb = i; break; @@ -452,164 +457,175 @@ void scom(int *ipage) break; } } - if (ifindit==0) return; /* Nothing suitable -- wait until next time*/ - ibqx = game.state.baseqx[iwhichb]; - ibqy = game.state.baseqy[iwhichb]; + if (ifindit==0) + return; /* Nothing suitable -- wait until next time*/ + ibq = game.state.baseq[iwhichb]; /* decide how to move toward base */ - ideltax = ibqx - game.state.isx; - ideltay = ibqy - game.state.isy; + ideltax = ibq.x - game.state.kscmdr.x; + ideltay = ibq.y - game.state.kscmdr.y; } /* Maximum movement is 1 quadrant in either or both axis */ - if (ideltax > 1) ideltax = 1; - if (ideltax < -1) ideltax = -1; - if (ideltay > 1) ideltay = 1; - if (ideltay < -1) ideltay = -1; + if (ideltax > 1) + ideltax = 1; + if (ideltax < -1) + ideltax = -1; + if (ideltay > 1) + ideltay = 1; + if (ideltay < -1) + ideltay = -1; /* try moving in both x and y directions */ - iqx = game.state.isx + ideltax; - iqy = game.state.isy + ideltax; - if (movescom(iqx, iqy, flag, ipage)) { + iq.x = game.state.kscmdr.x + ideltax; + iq.y = game.state.kscmdr.y + ideltax; + if (movescom(iq, avoid)) { /* failed -- try some other maneuvers */ if (ideltax==0 || ideltay==0) { /* attempt angle move */ if (ideltax != 0) { - iqy = game.state.isy + 1; - if (movescom(iqx, iqy, flag, ipage)) { - iqy = game.state.isy - 1; - movescom(iqx, iqy, flag, ipage); + iq.y = game.state.kscmdr.y + 1; + if (movescom(iq, avoid)) { + iq.y = game.state.kscmdr.y - 1; + movescom(iq, avoid); } } else { - iqx = game.state.isx + 1; - if (movescom(iqx, iqy, flag, ipage)) { - iqx = game.state.isx - 1; - movescom(iqx, iqy, flag, ipage); + iq.x = game.state.kscmdr.x + 1; + if (movescom(iq, avoid)) { + iq.x = game.state.kscmdr.x - 1; + movescom(iq, avoid); } } } else { /* try moving just in x or y */ - iqy = game.state.isy; - if (movescom(iqx, iqy, flag, ipage)) { - iqy = game.state.isy + ideltay; - iqx = game.state.isx; - movescom(iqx, iqy, flag, ipage); + iq.y = game.state.kscmdr.y; + if (movescom(iq, avoid)) { + iq.y = game.state.kscmdr.y + ideltay; + iq.x = game.state.kscmdr.x; + movescom(iq, avoid); } } } /* check for a base */ if (game.state.rembase == 0) { - game.future[FSCMOVE] = FOREVER; + unschedule(FSCMOVE); } - else for_starbases(i) { - ibqx = game.state.baseqx[i]; - ibqy = game.state.baseqy[i]; - if (ibqx==game.state.isx && ibqy == game.state.isy && game.state.isx != game.batx && game.state.isy != game.baty) { - /* attack the base */ - if (flag) return; /* no, don't attack base! */ - game.iseenit = 0; - game.isatb=1; - game.future[FSCDBAS] = game.state.date + 1.0 +2.0*Rand(); - if (game.future[FCDBAS] < FOREVER) game.future[FSCDBAS] += - game.future[FCDBAS]-game.state.date; - if (game.damage[DRADIO] > 0 && game.condit != IHDOCKED) - return; /* no warning */ - game.iseenit = 1; - if (*ipage == 0) pause_game(1); - *ipage=1; - proutn("Lt. Uhura- \"Captain, the starbase in "); - proutn(cramlc(quadrant, game.state.isx, game.state.isy)); - skip(1); - prout(" reports that it is under attack from the Klingon Super-commander."); - proutn(" It can survive until stardate %d.\"", - (int)game.future[FSCDBAS]); - if (game.resting==0) return; - prout("Mr. Spock- \"Captain, shall we cancel the rest period?\""); - if (ja()==0) return; - game.resting = 0; - game.optime = 0.0; /* actually finished */ - return; + else { + for (i = 1; i <= game.state.rembase; i++) { + ibq = game.state.baseq[i]; + if (same(ibq, game.state.kscmdr) && same(game.state.kscmdr, game.battle)) { + /* attack the base */ + if (avoid) + return; /* no, don't attack base! */ + game.iseenit = false; + game.isatb = 1; + schedule(FSCDBAS, 1.0 +2.0*Rand()); + if (is_scheduled(FCDBAS)) + postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date); + if (damaged(DRADIO) && game.condition != docked) + return; /* no warning */ + game.iseenit = true; + pause_game(true); + proutn(_("Lt. Uhura- \"Captain, the starbase in ")); + proutn(cramlc(quadrant, game.state.kscmdr)); + skip(1); + prout(_(" reports that it is under attack from the Klingon Super-commander.")); + proutn(_(" It can survive until stardate %d.\""), + (int)scheduled(FSCDBAS)); + if (!game.resting) + return; + prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\"")); + if (ja() == false) + return; + game.resting = false; + game.optime = 0.0; /* actually finished */ + return; + } } } /* Check for intelligence report */ if ( -#ifdef DEBUG - game.idebug==0 && -#endif + !idebug && (Rand() > 0.2 || - (game.damage[DRADIO] > 0.0 && game.condit != IHDOCKED) || - !game.state.galaxy[game.state.isx][game.state.isy].charted)) + (damaged(DRADIO) && game.condition != docked) || + !game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted)) return; - if (*ipage==0) pause_game(1); - *ipage = 1; - prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports"); - proutn(" the Super-commander is in "); - proutn(cramlc(quadrant, game.state.isx, game.state. isy)); + pause_game(true); + prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports")); + proutn(_(" the Super-commander is in ")); + proutn(cramlc(quadrant, game.state.kscmdr)); prout(".\""); return; } -void movetho(void) +void movetholian(void) +/* move the Tholian */ { - int idx, idy, im, i, dum, my; - /* Move the Tholian */ - if (game.ithere==0 || game.justin == 1) return; + int idx, idy, im, i; + if (!game.ithere || game.justin) + return; - if (game.ithx == 1 && game.ithy == 1) { + if (game.tholian.x == 1 && game.tholian.y == 1) { idx = 1; idy = QUADSIZE; } - else if (game.ithx == 1 && game.ithy == QUADSIZE) { + else if (game.tholian.x == 1 && game.tholian.y == QUADSIZE) { idx = QUADSIZE; idy = QUADSIZE; } - else if (game.ithx == QUADSIZE && game.ithy == QUADSIZE) { + else if (game.tholian.x == QUADSIZE && game.tholian.y == QUADSIZE) { idx = QUADSIZE; idy = 1; } - else if (game.ithx == QUADSIZE && game.ithy == 1) { + else if (game.tholian.x == QUADSIZE && game.tholian.y == 1) { idx = 1; idy = 1; } else { /* something is wrong! */ - game.ithere = 0; + game.ithere = false; return; } - /* Do nothing if we are blocked */ - if (game.quad[idx][idy]!= IHDOT && game.quad[idx][idy]!= IHWEB) return; - game.quad[game.ithx][game.ithy] = IHWEB; + /* do nothing if we are blocked */ + if (game.quad[idx][idy]!= IHDOT && game.quad[idx][idy]!= IHWEB) + return; + game.quad[game.tholian.x][game.tholian.y] = IHWEB; - if (game.ithx != idx) { + if (game.tholian.x != idx) { /* move in x axis */ - im = fabs((double)idx - game.ithx)/((double)idx - game.ithx); - while (game.ithx != idx) { - game.ithx += im; - if (game.quad[game.ithx][game.ithy]==IHDOT) game.quad[game.ithx][game.ithy] = IHWEB; + im = fabs((double)idx - game.tholian.x)/((double)idx - game.tholian.x); + while (game.tholian.x != idx) { + game.tholian.x += im; + if (game.quad[game.tholian.x][game.tholian.y]==IHDOT) + game.quad[game.tholian.x][game.tholian.y] = IHWEB; } } - else if (game.ithy != idy) { + else if (game.tholian.y != idy) { /* move in y axis */ - im = fabs((double)idy - game.ithy)/((double)idy - game.ithy); - while (game.ithy != idy) { - game.ithy += im; - if (game.quad[game.ithx][game.ithy]==IHDOT) game.quad[game.ithx][game.ithy] = IHWEB; + im = fabs((double)idy - game.tholian.y)/((double)idy - game.tholian.y); + while (game.tholian.y != idy) { + game.tholian.y += im; + if (game.quad[game.tholian.x][game.tholian.y]==IHDOT) + game.quad[game.tholian.x][game.tholian.y] = IHWEB; } } - game.quad[game.ithx][game.ithy] = IHT; - game.kx[game.nenhere]=game.ithx; - game.ky[game.nenhere]=game.ithy; + game.quad[game.tholian.x][game.tholian.y] = IHT; + game.ks[game.nenhere] = game.tholian; /* check to see if all holes plugged */ - for_sectors(i) { - if (game.quad[1][i]!=IHWEB && game.quad[1][i]!=IHT) return; - if (game.quad[QUADSIZE][i]!=IHWEB && game.quad[QUADSIZE][i]!=IHT) return; - if (game.quad[i][1]!=IHWEB && game.quad[i][1]!=IHT) return; - if (game.quad[i][QUADSIZE]!=IHWEB && game.quad[i][QUADSIZE]!=IHT) return; + for (i = 1; i <= QUADSIZE; i++) { + if (game.quad[1][i]!=IHWEB && game.quad[1][i]!=IHT) + return; + if (game.quad[QUADSIZE][i]!=IHWEB && game.quad[QUADSIZE][i]!=IHT) + return; + if (game.quad[i][1]!=IHWEB && game.quad[i][1]!=IHT) + return; + if (game.quad[i][QUADSIZE]!=IHWEB && game.quad[i][QUADSIZE]!=IHT) + return; } /* All plugged up -- Tholian splits */ - game.quad[game.ithx][game.ithy]=IHWEB; - dropin(IHBLANK, &dum, &my); - crmena(1,IHT, 2, game.ithx, game.ithy); - prout(" completes web."); - game.ithere = game.ithx = game.ithy = 0; + game.quad[game.tholian.x][game.tholian.y]=IHWEB; + dropin(IHBLANK); + crmena(true, IHT, sector, game.tholian); + prout(_(" completes web.")); + game.ithere = false; game.nenhere--; return; }