/* * Get assembly point argument. * If INPUT is not empty, use it, else prompt for more input using PROMPT. * If this yields a valid assembly point, read it into *AP_SECT and * return AP_SECT. * Else complain and return NULL. * *AP_SECT and BUF[1024] may be modified in either case. */ struct sctstr * get_assembly_point(char *input, struct sctstr *ap_sect, char *buf) { char *p; coord x, y; struct nstr_item ni; struct shpstr ship; p = getstarg(input, "assembly point? ", buf); if (!p || *p == 0) return NULL; if (!sarg_xy(p, &x, &y) || !getsect(x, y, ap_sect)) return NULL; /* over own or allied sector is fine */ if (relations_with(ap_sect->sct_own, player->cnum) == ALLIED) return ap_sect; /* over own or allied ship is fine */ snxtitem_xy(&ni, EF_SHIP, x, y); while (nxtitem(&ni, &ship)) { if (ship.shp_effic < SHIP_MINEFF || ship.shp_own == 0) continue; if (relations_with(ship.shp_own, player->cnum) == ALLIED) return ap_sect; } pr("Assembly point not owned by you or an ally!\n"); return NULL; }
void takeover(struct sctstr *sp, natid newown) { struct plnstr *pp; struct lndstr *lp; int civ; int che_count; int oldche; int n; struct nstr_item ni; struct plnstr p; struct lndstr land; /* Wipe all the distribution info */ memset(sp->sct_dist, 0, sizeof(sp->sct_dist)); memset(sp->sct_del, 0, sizeof(sp->sct_del)); if (sp->sct_own == 0) sp->sct_off = 0; else sp->sct_off = 1; sp->sct_dist_x = sp->sct_x; sp->sct_dist_y = sp->sct_y; pp = &p; /* Take over planes */ snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); while (nxtitem(&ni, pp)) { if (pp->pln_own != sp->sct_own) continue; takeover_plane(pp, newown); } /* Take over land units */ lp = &land; snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); while (nxtitem(&ni, lp)) { if ((lp->lnd_own == newown) || (lp->lnd_own == 0)) continue; if (lp->lnd_own != sp->sct_own) continue; if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) continue; /* Spies get a chance to hide */ if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic)))) continue; } n = lp->lnd_effic - (29 + roll(100)); if (n < 0) n = 0; lp->lnd_effic = n; if (lp->lnd_effic < LAND_MINEFF) { lp->lnd_effic = 0; mpr(newown, "%s blown up by the crew!\n", prland(lp)); wu(0, lp->lnd_own, "%s blown up by the crew when %s took %s!\n", prland(lp), cname(newown), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); } else { mpr(newown, "We have captured %s!\n", prland(lp)); wu(0, lp->lnd_own, "%s captured when %s took %s!\n", prland(lp), cname(newown), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); } takeover_land(lp, newown); } sp->sct_avail = 0; civ = sp->sct_item[I_CIVIL]; oldche = sp->sct_che; /* * create guerrillas from civilians * how spunky are these guys? * n: random number from -25:75 + (50 - loyalty) */ n = (50 - sp->sct_loyal) + (roll(100) - 26); if (n > 0 && sp->sct_own == sp->sct_oldown) { che_count = (civ * n / 3000) + 5; if (che_count * 2 > civ) che_count = civ / 2; che_count /= hap_fact(getnatp(newown), getnatp(sp->sct_own)); if (che_count + oldche > CHE_MAX) che_count = CHE_MAX - oldche; if (che_count > 0) { civ -= che_count; che_count += oldche; } else che_count = oldche; } else che_count = oldche; sp->sct_che = che_count; if (newown != sp->sct_oldown) sp->sct_che_target = newown; if (sp->sct_che_target == 0) sp->sct_che = 0; sp->sct_item[I_CIVIL] = civ; if (sp->sct_oldown == newown || civ == 0) { /* * taking over one of your old sectors */ sp->sct_loyal = 0; sp->sct_oldown = newown; } else { /* * taking over someone else's sector */ sp->sct_loyal = 50; } sp->sct_own = newown; if (opt_MOB_ACCESS) { game_tick_to_now(&sp->sct_access); sp->sct_mobil = -(etu_per_update / sect_mob_neg_factor); } else { sp->sct_mobil = 0; } }
/* Knock down a bridge span. Note that this does NOT write the * sector out to the database, it's up to the caller to do that. */ static void knockdown(struct sctstr *sp) { struct lndstr land; struct plnstr plane; struct nukstr nuke; struct nstr_item ni; mpr(sp->sct_own, "Crumble... SCREEEECH! Splash! Bridge%s falls at %s!\n", sp->sct_type == SCT_BTOWER ? " tower" : "", xyas(sp->sct_x, sp->sct_y, sp->sct_own)); if (!SCT_MINES_ARE_SEAMINES(sp)) sp->sct_mines = 0; sp->sct_type = SCT_WATER; sp->sct_newtype = SCT_WATER; sp->sct_own = 0; sp->sct_oldown = 0; sp->sct_mobil = 0; sp->sct_effic = 0; /* Sink all the units */ snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &land)) { if (land.lnd_own == 0) continue; if (land.lnd_ship >= 0) continue; mpr(land.lnd_own, " AARGH! %s tumbles to its doom!\n", prland(&land)); land.lnd_effic = 0; putland(land.lnd_uid, &land); } /* Sink all the planes */ snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &plane)) { if (plane.pln_own == 0) continue; if (plane.pln_flags & PLN_LAUNCHED) continue; if (plane.pln_ship >= 0) continue; mpr(plane.pln_own, " AARGH! %s tumbles to its doom!\n", prplane(&plane)); plane.pln_effic = 0; putplane(plane.pln_uid, &plane); } /* Sink all the nukes */ snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &nuke)) { if (nuke.nuk_own == 0) continue; if (nuke.nuk_plane >= 0) continue; mpr(nuke.nuk_own, " %s sinks to the bottom of the sea!\n", prnuke(&nuke)); nuke.nuk_effic = 0; putnuke(nuke.nuk_uid, &nuke); } memset(sp->sct_item, 0, sizeof(sp->sct_item)); memset(sp->sct_del, 0, sizeof(sp->sct_del)); memset(sp->sct_dist, 0, sizeof(sp->sct_dist)); sp->sct_pstage = PLG_HEALTHY; sp->sct_ptime = 0; sp->sct_che = 0; sp->sct_che_target = 0; }
int boar(void) { struct combat off[1]; /* boarding ship or sector */ struct combat def[1]; /* defending ship */ struct emp_qelem olist; /* boarding units */ struct emp_qelem dlist; /* defending units */ int ototal; /* total boarding strength */ int a_engineer = 0; /* boarder engineers are present */ int a_spy = 0; /* the best boarder scout */ struct shpstr ship; /* for retreating */ struct sctstr sect; struct lndstr land; struct nstr_item ni; int foundland, def_uid; natid def_own; char *p; char buf[1024]; att_combat_init(def, EF_SHIP); /* * Collect input from the boarder */ /* What are we boarding? */ p = getstarg(player->argp[1], "Victim ship #? ", buf); if (!p || (def->shp_uid = atoi(p)) < 0) return RET_SYN; /* * Ask the boarder what he wants to board with */ if (!(p = getstarg(player->argp[2], "Boarding party from? ", buf))) return RET_SYN; if (issector(p)) { att_combat_init(off, EF_SECTOR); if (!sarg_xy(p, &off->x, &off->y)) return RET_SYN; getsect(off->x, off->y, §); if (sect.sct_own != player->cnum) { pr("You don't own %s!\n", xyas(off->x, off->y, player->cnum)); return RET_SYN; } if (sect.sct_mobil <= 0) { /* Look for land units with mobility */ snxtitem_xy(&ni, EF_LAND, off->x, off->y); foundland = 0; while (nxtitem(&ni, &land)) { if (land.lnd_own != player->cnum) continue; if (land.lnd_ship >= 0 || land.lnd_land >= 0) continue; if (land.lnd_mobil <= 0) continue; /* Only land units with assault can board */ if (!(lchr[(int)land.lnd_type].l_flags & L_ASSAULT)) continue; foundland = 1; } if (!foundland) { pr("You don't have any mobility (sector or land units) in %s!\n", xyas(off->x, off->y, player->cnum)); return RET_SYN; } } } else { att_combat_init(off, EF_SHIP); if ((off->shp_uid = atoi(p)) < 0) return RET_SYN; } if (att_abort(A_BOARD, off, def)) { pr("Board aborted\n"); return RET_OK; } /* Fire at the attacking ship */ att_approach(off, def); if (att_abort(A_BOARD, off, def)) { pr("Board aborted\n"); att_empty_attack(A_BOARD, 0, def); return RET_OK; } /* Show what we're boarding */ att_show(def); /* Ask the player what he wants to board with */ att_ask_offense(A_BOARD, off, def, &olist, &a_spy, &a_engineer); if (att_abort(A_BOARD, off, def)) { pr("Board aborted\n"); att_empty_attack(A_BOARD, 0, def); return att_free_lists(&olist, NULL); } ototal = att_get_offense(A_BOARD, off, &olist, def); if (att_abort(A_BOARD, off, def)) { pr("Board aborted\n"); att_empty_attack(A_BOARD, 0, def); return att_free_lists(&olist, NULL); } /* * We have now got all the answers from the boarder. From this point * forward, we can assume that this battle is the _only_ thing * happening in the game. */ /* Get the real defense */ att_get_defense(&olist, def, &dlist, a_spy, ototal); /* * Death, carnage, and destruction. */ /* * Careful: when the fight sinks the ship, put_combat() clobbers * *def (see FIXME there). */ def_uid = def->shp_uid; def_own = def->own; if (!(att_fight(A_BOARD, off, &olist, 1.0, def, &dlist, 1.0))) { getship(def_uid, &ship); if (ship.shp_rflags & RET_BOARDED) { retreat_ship(&ship, def_own, 'u'); putship(def_uid, &ship); } } return RET_OK; }