00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <config.h>
00036
00037 #include "land.h"
00038 #include "lost.h"
00039 #include "news.h"
00040 #include "nsc.h"
00041 #include "path.h"
00042 #include "plane.h"
00043 #include "update.h"
00044
00045 static void take_casualties(struct sctstr *, int);
00046
00047 void
00048 revolt(struct sctstr *sp)
00049 {
00050 int che_civ;
00051 int che_uw;
00052 int civ;
00053 int uw;
00054 int che;
00055 int n;
00056
00057 che = sp->sct_che;
00058 if (che != 0 && (sp->sct_che_target != sp->sct_own || che >= CHE_MAX))
00059 return;
00060 civ = sp->sct_item[I_CIVIL];
00061 uw = sp->sct_item[I_UW];
00062 if (che > (civ + uw) * 3)
00063 return;
00064 che_uw = 0;
00065 che_civ = 0;
00066
00067 n = 10 - (random() % 20);
00068 che_civ = 3 + (civ * n / 500);
00069 if (che_civ < 0)
00070 che_civ = 0;
00071 else if (che_civ * 3 > civ)
00072 che_civ = civ / 3;
00073 if (che + che_civ > CHE_MAX)
00074 che_civ = CHE_MAX - che;
00075 che += che_civ;
00076 if (che < CHE_MAX) {
00077
00078 n = 10 + (random() % 30);
00079 che_uw = 5 + (uw * n / 500);
00080 if (che_uw > uw)
00081 che_uw = uw;
00082 if (che + che_uw > CHE_MAX)
00083 che_uw = CHE_MAX - che_uw;
00084 che += che_uw;
00085 }
00086 if (che_civ + che_uw > 0) {
00087 civ -= che_civ;
00088 uw -= che_uw;
00089 sp->sct_che_target = sp->sct_own;
00090 sp->sct_che = che;
00091 if (che_civ > 0)
00092 sp->sct_item[I_CIVIL] = civ;
00093 if (che_uw > 0)
00094 sp->sct_item[I_UW] = uw;
00095 #ifdef DEBUG
00096 logerror("(#%d) %d che fired up in %s",
00097 sp->sct_own, che, ownxy(sp));
00098 #endif
00099 }
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 void
00125 guerrilla(struct sctstr *sp)
00126 {
00127 struct sctstr *nsp;
00128 int recruit;
00129 int move;
00130 int ratio;
00131 int che;
00132 int mil;
00133 int cc, mc;
00134 double odds;
00135 int civ;
00136 int n;
00137 int uw;
00138 natid target;
00139 struct natstr *tnat;
00140 int convert;
00141 natid actor;
00142 natid victim;
00143 int tmp;
00144 int min_mil;
00145 int val;
00146 int oldmob;
00147 struct lndstr *lp;
00148 struct nstr_item ni;
00149
00150 mc = cc = 0;
00151 recruit = 0;
00152 convert = 0;
00153 move = 0;
00154 if (!sp->sct_che)
00155 return;
00156 civ = sp->sct_item[I_CIVIL];
00157 uw = sp->sct_item[I_UW];
00158 victim = sp->sct_own;
00159 actor = sp->sct_oldown;
00160 che = sp->sct_che;
00161 mil = sp->sct_item[I_MILIT];
00162
00163 snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
00164
00165 while (NULL != (lp = nxtitemp(&ni))) {
00166 if (lp->lnd_own != sp->sct_own)
00167 continue;
00168
00169 mil += lp->lnd_item[I_MILIT];
00170
00171 if (sp->sct_che_target != sp->sct_own)
00172 continue;
00173
00174
00175
00176 if (lchr[(int)lp->lnd_type].l_flags & L_SECURITY) {
00177 int che_kill, r;
00178
00179 mil += lp->lnd_item[I_MILIT];
00180 r = (lp->lnd_item[I_MILIT] * lp->lnd_effic) / 500;
00181 che_kill = r < 1 ? 0 : roll(r);
00182 if (che_kill > che)
00183 che_kill = che;
00184 if (che_kill) {
00185 wu(0, sp->sct_own,
00186 "%s kills %d guerrilla%s in raid at %s!\n",
00187 prland(lp), che_kill, splur(che_kill), ownxy(sp));
00188 che -= che_kill;
00189 }
00190 }
00191 }
00192
00193
00194 if (che <= 0) {
00195 sp->sct_che = 0;
00196 sp->sct_che_target = 0;
00197 return;
00198 }
00199
00200 target = sp->sct_che_target;
00201 if (CANT_HAPPEN(target == 0))
00202 return;
00203 tnat = getnatp(target);
00204 if (tnat->nat_stat == STAT_UNUSED) {
00205
00206 logerror("%d Che targeted at country %d retiring", che, target);
00207 sp->sct_che = 0;
00208 sp->sct_che_target = 0;
00209 sp->sct_item[I_CIVIL] = MIN(civ + che, ITEM_MAX);
00210 return;
00211 }
00212
00213 if (sp->sct_own != target) {
00214
00215 move++;
00216 goto domove;
00217 }
00218
00219 ratio = mil / che;
00220 odds = (double)che / (mil + che);
00221 odds /= hap_fact(tnat, getnatp(sp->sct_oldown));
00222 if (mil == 0) {
00223 wu(0, sp->sct_own, "Revolutionary subversion reported in %s!\n",
00224 ownxy(sp));
00225 recruit++;
00226 convert++;
00227 } else if (che > mil && mil > 0) {
00228
00229
00230
00231
00232
00233
00234 while (che > 0 && mil > 0) {
00235 if (chance(odds)) {
00236 mc++;
00237 mil--;
00238 } else {
00239 cc++;
00240 che--;
00241 }
00242 }
00243 if (mil > 0) {
00244
00245 n = sp->sct_loyal - (random() % 15);
00246 if (n < 0)
00247 n = 0;
00248 sp->sct_loyal = n;
00249
00250
00251 } else {
00252 convert++;
00253 recruit++;
00254
00255
00256 }
00257 take_casualties(sp, mc);
00258 } else if (ratio < 5) {
00259
00260
00261
00262
00263 n = 0;
00264 n = (random() % 10) + (random() % che);
00265 if (n > 100)
00266 n = 100;
00267 tmp = sp->sct_work - n;
00268 if (tmp < 0)
00269 tmp = 0;
00270 sp->sct_work = tmp;
00271 wu(0, sp->sct_own,
00272 "Production %s disrupted by terrorists in %s\n",
00273 effadv(n), ownxy(sp));
00274 sect_damage(sp, n / 10, 0);
00275
00276
00277 recruit++;
00278 } else {
00279
00280
00281
00282 move++;
00283 }
00284 if (mil > 0 && che > 0) {
00285
00286
00287
00288
00289
00290 if (chance(ratio * 0.10)) {
00291 n = (mil / 5) + 1;
00292 odds = (double)che / (n + che);
00293 odds /= hap_fact(tnat, getnatp(sp->sct_oldown));
00294 while (che > 0 && n > 0) {
00295 if (chance(odds)) {
00296 mc++;
00297 n--;
00298 } else {
00299 cc++;
00300 che--;
00301 }
00302 }
00303 take_casualties(sp, mc);
00304 recruit = 0;
00305
00306 }
00307 }
00308 if (convert && sp->sct_loyal >= 50) {
00309 int n;
00310
00311 oldmob = sp->sct_mobil;
00312
00313 if (sp->sct_own == sp->sct_oldown)
00314 sp->sct_oldown = 0;
00315 else
00316 takeover(sp, sp->sct_oldown);
00317 sp->sct_mobil = oldmob;
00318 civ += uw;
00319 uw = 0;
00320 n = civ / 20;
00321 civ -= n;
00322 if (civ > ITEM_MAX) {
00323 uw = civ - ITEM_MAX;
00324 civ = ITEM_MAX;
00325 }
00326 sp->sct_item[I_CIVIL] = civ;
00327 sp->sct_item[I_UW] = uw;
00328 sp->sct_item[I_MILIT] = n;
00329 move++;
00330 recruit = 0;
00331 if (sp->sct_own)
00332 wu(0, sp->sct_own, "Sector %s has been retaken!\n",
00333 xyas(sp->sct_x, sp->sct_y, sp->sct_own));
00334 }
00335 if (recruit && che > 0) {
00336
00337 n = sp->sct_loyal;
00338 if (n < 30)
00339 n += (random() % 5) + 1;
00340 else if (n < 70)
00341 n += (random() % 10) + 4;
00342 if (n > 127)
00343 n = 127;
00344 sp->sct_loyal = n;
00345 if (sp->sct_oldown != sp->sct_own || n > 100) {
00346 n = civ * (random() % 3) / 200;
00347 n /= hap_fact(tnat, getnatp(sp->sct_oldown));
00348 if (n + che > CHE_MAX)
00349 n = CHE_MAX - che;
00350 che += n;
00351 civ -= n;
00352 sp->sct_item[I_CIVIL] = civ;
00353 }
00354 n = uw * (random() % 3) / 200;
00355 if (n + che > CHE_MAX)
00356 n = CHE_MAX - che;
00357 che += n;
00358 uw -= n;
00359 sp->sct_item[I_UW] = uw;
00360 }
00361 domove:
00362 if (move && che > 0) {
00363 struct sctstr *nicest_sp = 0;
00364 if (convert)
00365 min_mil = 999;
00366 else
00367 min_mil = mil;
00368
00369 for (n = 1; n <= 6; n++) {
00370 nsp = getsectp(sp->sct_x + diroff[n][0],
00371 sp->sct_y + diroff[n][1]);
00372 if (dchr[nsp->sct_type].d_mob0 < 0)
00373 continue;
00374 if (nsp->sct_own != target)
00375 continue;
00376 if (nsp->sct_che > 0) {
00377 if (nsp->sct_che_target != target)
00378 continue;
00379 if (nsp->sct_che + che > CHE_MAX)
00380 continue;
00381 }
00382 val = nsp->sct_item[I_MILIT];
00383
00384 val = roundintby(val, 10);
00385
00386
00387 val += random() % 10 - 5;
00388 if (val >= min_mil)
00389 continue;
00390 nicest_sp = nsp;
00391 min_mil = val;
00392 }
00393
00394 if (nicest_sp != 0) {
00395 nicest_sp->sct_che += che;
00396 nicest_sp->sct_che_target = target;
00397 che = 0;
00398 }
00399 }
00400 if (che > 0) {
00401 sp->sct_che = che;
00402 sp->sct_che_target = target;
00403 } else {
00404 sp->sct_che = 0;
00405 sp->sct_che_target = 0;
00406 }
00407 if (mc > 0 || cc > 0) {
00408 wu(0, target,
00409 "Guerrilla warfare in %s\n",
00410 xyas(sp->sct_x, sp->sct_y, target));
00411 if (sp->sct_own == target)
00412 wu(0, target, " body count: troops: %d, rebels: %d\n", mc, cc);
00413 else
00414 wu(0, target,
00415 " rebels murder %d military\n", mc);
00416 nreport(actor, N_FREEDOM_FIGHT, victim, 1);
00417 }
00418 if (sp->sct_own != victim)
00419 wu(0, victim, "Partisans take over %s!\n",
00420 xyas(sp->sct_x, sp->sct_y, victim));
00421 }
00422
00423 static void
00424 take_casualties(struct sctstr *sp, int mc)
00425 {
00426 int orig_mil;
00427 int cantake;
00428 int nunits = 0, each, deq;
00429 struct lndstr *lp;
00430 struct nstr_item ni;
00431
00432
00433 orig_mil = sp->sct_item[I_MILIT];
00434
00435 if (mc <= orig_mil) {
00436 sp->sct_item[I_MILIT] = orig_mil - mc;
00437 return;
00438 }
00439 sp->sct_item[I_MILIT] = 0;
00440
00441
00442 mc -= orig_mil;
00443
00444
00445
00446
00447
00448
00449
00450 snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
00451 while (NULL != (lp = nxtitemp(&ni))) {
00452 nunits++;
00453 if (lchr[(int)lp->lnd_type].l_flags & L_SECURITY)
00454 nunits++;
00455 }
00456
00457 if (nunits == 0)
00458 return;
00459
00460 each = (mc / nunits) + 2;
00461
00462
00463 snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
00464 while (NULL != (lp = nxtitemp(&ni))) {
00465 if (!(lchr[(int)lp->lnd_type].l_flags & L_SECURITY))
00466 continue;
00467
00468 cantake = ((lp->lnd_effic - 40) / 100.0) * lp->lnd_item[I_MILIT];
00469
00470 if (cantake >= each) {
00471 deq = ((double)each / lp->lnd_item[I_MILIT]) * 100.0;
00472 mc -= 2 * each;
00473 } else if (cantake > 0) {
00474 deq = ((double)cantake / lp->lnd_item[I_MILIT]) * 100.0;
00475 mc -= 2 * cantake;
00476 } else
00477 deq = 0;
00478
00479 lp->lnd_effic -= deq;
00480 lp->lnd_mobil -= deq / 2;
00481 deq = lchr[(int)lp->lnd_type].l_mil * (deq / 100.0);
00482 lnd_submil(lp, deq);
00483 if (mc <= 0)
00484 return;
00485 }
00486
00487
00488 snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
00489 while (NULL != (lp = nxtitemp(&ni))) {
00490 if (lchr[(int)lp->lnd_type].l_flags & L_SECURITY)
00491 continue;
00492
00493 cantake = ((lp->lnd_effic - 40) / 100.0) * lp->lnd_item[I_MILIT];
00494
00495 if (cantake >= each) {
00496 deq = ((double)each / lp->lnd_item[I_MILIT]) * 100.0;
00497 mc -= each;
00498 } else if (cantake > 0) {
00499 deq = ((double)cantake / lp->lnd_item[I_MILIT]) * 100.0;
00500 mc -= cantake;
00501 } else
00502 deq = 0;
00503
00504 lp->lnd_effic -= deq;
00505 lp->lnd_mobil -= deq / 2;
00506 deq = lchr[(int)lp->lnd_type].l_mil * (deq / 100.0);
00507 lnd_submil(lp, deq);
00508 if (mc <= 0)
00509 return;
00510 }
00511
00512
00513
00514 snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
00515 while (NULL != (lp = nxtitemp(&ni))) {
00516 if (lchr[(int)lp->lnd_type].l_flags & L_SECURITY)
00517 continue;
00518
00519 mc -= (lp->lnd_effic / 100.0) * lp->lnd_item[I_MILIT];
00520 lp->lnd_effic = 0;
00521 lnd_submil(lp, 1000);
00522 wu(0, lp->lnd_own, "%s dies fighting guerrillas in %s\n",
00523 prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own));
00524 makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y);
00525 lp->lnd_own = 0;
00526 if (mc <= 0)
00527 return;
00528 }
00529
00530
00531
00532 snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
00533 while (NULL != (lp = nxtitemp(&ni))) {
00534 if (!(lchr[(int)lp->lnd_type].l_flags & L_SECURITY))
00535 continue;
00536
00537 mc -= (lp->lnd_effic / 100.0) * lp->lnd_item[I_MILIT] * 2.0;
00538 lp->lnd_effic = 0;
00539 lnd_submil(lp, 1000);
00540 wu(0, lp->lnd_own, "%s dies fighting guerrillas in %s\n",
00541 prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own));
00542 makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y);
00543 lp->lnd_own = 0;
00544 if (mc <= 0)
00545 return;
00546 }
00547
00548
00549 }