int news(void) { struct natstr *natp; time_t now; int page; time_t then; time_t delta; struct nwsstr nws; struct nstr_item nstr; int page_has_news[N_MAX_PAGE + 1]; int there_is_news = 0; short sectors_taken[MAXNOC][MAXNOC]; short sectors_delta; short max_delta = -1; short abs_delta; short k; int sectors_were_taken = 0; natid i, j; char num[128]; char *verb; if (!snxtitem(&nstr, EF_NEWS, "*", NULL)) return RET_SYN; memset(page_has_news, 0, sizeof(page_has_news)); memset(sectors_taken, 0, sizeof(sectors_taken)); (void)time(&now); natp = getnatp(player->cnum); then = natp->nat_newstim; if (player->argp[1]) { /* * We want to hide events before contact. Proper solution * would be to timestamp the contact. Cheesy approximation: * disable old news. */ if (opt_HIDDEN && !player->god) { pr("Sorry, argument doesn't work with HIDDEN enabled\n"); return RET_FAIL; } delta = days(atoi(player->argp[1])); then = now - delta; } natp->nat_newstim = now; head(); pr("\nThe details of Empire news since %s", ctime(&then)); while (nxtitem(&nstr, &nws)) { if (!nws.nws_vrb || CANT_HAPPEN(nws.nws_vrb > N_MAX_VERB)) continue; if (nws.nws_when < then) continue; if (opt_HIDDEN) { if (!player->god && !(getcontact(getnatp(player->cnum), nws.nws_ano) && getcontact(getnatp(player->cnum), nws.nws_vno))) continue; } ++page_has_news[rpt[(int)nws.nws_vrb].r_newspage]; ++there_is_news; } for (page = 1; page <= N_MAX_PAGE; page++) { if (!page_has_news[page]) continue; pr("\n\t === %s ===\n", page_headings[page].name); snxtitem_rewind(&nstr); while (nxtitem(&nstr, &nws)) { if (CANT_HAPPEN(nws.nws_vrb > N_MAX_VERB)) continue; if (rpt[(int)nws.nws_vrb].r_newspage != page) continue; if (nws.nws_when < then) continue; if (nws.nws_ntm == 0) nws.nws_ntm = 1; if (opt_HIDDEN) { if (!player->god && !(getcontact(getnatp(player->cnum), nws.nws_ano) && getcontact(getnatp(player->cnum), nws.nws_vno))) continue; } if (page == N_FRONT && (nws.nws_vrb == N_WON_SECT || nws.nws_vrb == N_AWON_SECT || nws.nws_vrb == N_PWON_SECT)) { sectors_taken[nws.nws_ano][nws.nws_vno] += nws.nws_ntm; sectors_were_taken += nws.nws_ntm; } preport(&nws); } } if (sectors_were_taken) { for (i = 0; i < MAXNOC; ++i) { for (j = 0; j < i; ++j) { sectors_delta = sectors_taken[i][j] - sectors_taken[j][i]; if (max_delta < abs(sectors_delta)) max_delta = abs(sectors_delta); } } pr("\n\t === The Bottom Line ==\n"); for (k = max_delta; k > 0; --k) { for (i = 0; i < MAXNOC; ++i) { for (j = 0; j < i; ++j) { sectors_delta = sectors_taken[i][j] - sectors_taken[j][i]; abs_delta = abs(sectors_delta); if (abs_delta != k) continue; if (abs_delta == 1) verb = "stole"; else if (abs_delta < 4) verb = "took"; else if (abs_delta < 8) verb = "captured"; else verb = "seized"; if (sectors_delta > 0) { numstr(num, abs_delta); pr("%s %s %s sector%s from %s\n", cname(i), verb, num, splur(sectors_delta), cname(j)); } else if (sectors_delta < 0) { numstr(num, abs_delta); pr("%s %s %s sector%s from %s\n", cname(j), verb, num, splur(-sectors_delta), cname(i)); } } } } } if (!there_is_news) pr("\nNo news at the moment...\n"); return 0; }
int scra(void) { struct nstr_item ni; union empobj_storage item; int type, n; struct sctstr sect; struct mchrstr *mp; struct plchrstr *pp; struct lchrstr *lp; char *p; i_type i; char prompt[128]; char buf[1024]; float eff; short *mvec; int amt; if (!(p = getstarg(player->argp[1], "Ship, land, or plane? ", buf))) return RET_SYN; switch (*p) { case 's': type = EF_SHIP; break; case 'p': type = EF_PLANE; break; case 'l': type = EF_LAND; break; default: pr("Ships, land units, or planes only! (s, l, p)\n"); return RET_SYN; } if (!snxtitem(&ni, type, player->argp[2], NULL)) return RET_SYN; n = 0; while (nxtitem(&ni, &item)) { if (!player->owner) continue; n++; } snprintf(prompt, sizeof(prompt), "Really scrap %d %s%s [n]? ", n, ef_nameof(type), splur(n)); if (!confirm(prompt)) return RET_FAIL; snxtitem_rewind(&ni); while (nxtitem(&ni, &item)) { if (!player->owner) continue; if (opt_MARKET) { if (ontradingblock(type, &item.ship)) { pr("You cannot scrap an item on the trading block!\n"); continue; } } getsect(item.gen.x, item.gen.y, §); if (type == EF_SHIP) { if (!player->owner && relations_with(sect.sct_own, player->cnum) < FRIENDLY) { pr("%s is not in a friendly harbor!\n", prship(&item.ship)); continue; } if (sect.sct_type != SCT_HARBR || sect.sct_effic < 60) { pr("%s is not in a 60%% efficient harbor!\n", prship(&item.ship)); continue; } if (mchr[item.ship.shp_type].m_flags & M_TRADE) { pr("WARNING: You only collect money from trade ships if you \"scuttle\" them!\n"); sprintf(prompt, "Are you really sure that you want to scrap %s (n)? ", prship(&item.ship)); if (!confirm(prompt)) { pr("%s not scrapped\n", prship(&item.ship)); continue; } } } else { if (!player->owner && relations_with(sect.sct_own, player->cnum) != ALLIED) { pr("%s is not in an allied sector!\n", unit_nameof(&item.gen)); continue; } if (type == EF_PLANE && (sect.sct_type != SCT_AIRPT || sect.sct_effic < 60)) { pr("%s is not in a 60%% efficient airfield!\n", prplane(&item.plane)); continue; } } pr("%s scrapped in %s\n", unit_nameof(&item.gen), xyas(item.gen.x, item.gen.y, player->cnum)); unit_drop_cargo(&item.gen, sect.sct_own); if (type == EF_SHIP) { eff = item.ship.shp_effic / 100.0; mp = &mchr[(int)item.ship.shp_type]; for (i = I_NONE + 1; i <= I_MAX; i++) { if (load_comm_ok(§, item.ship.shp_own, i, -item.ship.shp_item[i])) sect.sct_item[i] += item.ship.shp_item[i]; } mvec = mp->m_mat; if (item.ship.shp_pstage == PLG_INFECT && sect.sct_pstage == PLG_HEALTHY) sect.sct_pstage = PLG_EXPOSED; } else if (type == EF_LAND) { eff = item.land.lnd_effic / 100.0; lp = &lchr[(int)item.land.lnd_type]; for (i = I_NONE + 1; i <= I_MAX; i++) { if (load_comm_ok(§, item.land.lnd_own, i, -item.land.lnd_item[i])) sect.sct_item[i] += item.land.lnd_item[i]; } mvec = lp->l_mat; if (item.land.lnd_pstage == PLG_INFECT && sect.sct_pstage == PLG_HEALTHY) sect.sct_pstage = PLG_EXPOSED; } else { eff = item.land.lnd_effic / 100.0; pp = &plchr[(int)item.plane.pln_type]; mvec = pp->pl_mat; } item.gen.effic = 0; put_empobj(type, item.gen.uid, &item.gen); for (i = I_NONE + 1; i <= I_MAX; i++) { if (i == I_CIVIL || i == I_MILIT || i == I_UW) amt = sect.sct_item[i] + mvec[i] * eff; else amt = sect.sct_item[i] + mvec[i] * 2 / 3 * eff; if (amt > ITEM_MAX) amt = ITEM_MAX; sect.sct_item[i] = amt; } putsect(§); } return RET_OK; }
int torp(void) { natid vshipown; int range; int dam; int subno; int victno; int erange; double hitchance; struct shpstr vship; struct shpstr sub; struct mchrstr *sub_mcp; char *ptr; struct nstr_item nbst; char buf[1024]; int ntorping = 0; char prompt[128]; if (!snxtitem(&nbst, EF_SHIP, player->argp[1], "From ship(s)? ")) return RET_SYN; while (nxtitem(&nbst, &sub)) { if (sub.shp_own != player->cnum) continue; if ((mchr[(int)sub.shp_type].m_flags & M_TORP) == 0) continue; if (sub.shp_item[I_GUN] == 0 || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS) continue; if (sub.shp_item[I_MILIT] < 1) continue; if (sub.shp_effic < 60) continue; if (sub.shp_mobil <= 0) continue; ntorping++; } pr("%d ships are eligible to torpedo\n", ntorping); snxtitem_rewind(&nbst); while (nxtitem(&nbst, &sub)) { if (!sub.shp_own) continue; if (sub.shp_own != player->cnum) { continue; } sub_mcp = &mchr[sub.shp_type]; if (!(sub_mcp->m_flags & M_TORP)) { pr("Ship # %d: A %s can't fire torpedoes!\n", sub.shp_uid, sub_mcp->m_name); continue; } if (sub.shp_item[I_GUN] == 0 || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS) { pr("Ship #%d has insufficient armament\n", sub.shp_uid); continue; } if (sub.shp_item[I_MILIT] < 1) { pr("Ship #%d has insufficient crew\n", sub.shp_uid); continue; } if (sub.shp_effic < 60) { pr("Ship #%d torpedo tubes inoperative.\n", sub.shp_uid); continue; } if (sub.shp_mobil <= 0) { pr("Ship #%d has insufficient mobility\n", sub.shp_uid); continue; } subno = sub.shp_uid; sprintf(prompt, "Ship %d, target? ", sub.shp_uid); if (!(ptr = getstarg(player->argp[2], prompt, buf))) return RET_SYN; if (!check_ship_ok(&sub)) return RET_FAIL; if ((victno = atoi(ptr)) < 0) return RET_SYN; if (!getship(victno, &vship)) return RET_FAIL; if (!vship.shp_own) return RET_FAIL; vshipown = vship.shp_own; if (victno == subno) { pr("Shooting yourself, eh? How strange...\n"); continue; } if (mchr[(int)vship.shp_type].m_flags & M_SUB) { if (!(sub_mcp->m_flags & M_SUBT)) { pr("You can't torpedo a submarine!\n"); continue; } } dam = shp_torp(&sub, 1); sub.shp_mission = 0; putship(sub.shp_uid, &sub); if (CANT_HAPPEN(dam < 0)) { pr("Ship #%d has insufficient armament\n", sub.shp_uid); continue; } if (!(sub_mcp->m_flags & M_SUB)) { pr("Starting our attack run...\n"); anti_torp(sub.shp_uid, ntorping, vshipown); } getship(sub.shp_uid, &sub); if (sub.shp_own == 0) continue; erange = roundrange(torprange(&sub)); pr("Effective torpedo range is %d.0\n", erange); pr("Whooosh... "); getship(victno, &vship); vshipown = vship.shp_own; range = mapdist(sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y); hitchance = shp_torp_hitchance(&sub, range); if (range <= erange) { pr("Hitchance = %.0f%%\n", hitchance * 100); } if (range > erange) pr("Out of range\n"); else if (!line_of_sight(NULL, sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y)) { pr("BOOM!... Torpedo slams into land before reaching target.\n"); /* We only tell the victim if we were within range. */ if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "Torpedo sighted @ %s by %s\n", xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship)); } else if (chance(hitchance)) { pr("BOOM!...\n"); if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "%s in %s torpedoed %s for %d damage.\n", sub_mcp->m_flags & M_SUB ? "sub" : prship(&sub), xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship), dam); pr("Torpedo hit %s for %d damage.\n", prsub(&vship), dam); if (!(mchr[vship.shp_type].m_flags & M_SUB)) { if (mchr[sub.shp_type].m_flags & M_SUB) nreport(vshipown, N_TORP_SHIP, 0, 1); else nreport(vshipown, N_SHIP_TORP, player->cnum, 1); } shipdamage(&vship, dam); if (vship.shp_effic < SHIP_MINEFF) pr("%s sunk!\n", prsub(&vship)); if (vship.shp_rflags & RET_TORPED) retreat_ship(&vship, vshipown, 't'); putship(vship.shp_uid, &vship); } else { pr("Missed\n"); if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "Torpedo sighted @ %s by %s\n", xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship)); } if (sub_mcp->m_flags & M_SUB) anti_torp(sub.shp_uid, ntorping, vshipown); } return RET_OK; }