2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-1999, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * shpsub.c: Ship subroutine stuff
30 * Known contributors to this file:
32 * Steve McClure, 1996-2000
53 #include "prototypes.h"
55 extern double tfactfire(natid, double);
57 extern int etu_per_update;
60 shp_sel(struct nstr_item *ni, struct emp_qelem *list)
72 while (nxtitem(ni, (s_char *)&ship)) {
75 mcp = &mchr[(int)ship.shp_type];
76 /* if (wantflags && (mcp->m_flags & wantflags) != wantflags)
78 if (nowantflags && mcp->m_flags & nowantflags)
82 if (ontradingblock(EF_SHIP, (int *)&ship)) {
83 pr("ship #%d inelligible - it's for sale.\n", ship.shp_uid);
87 /* This abuse is better fixed by building a ship with the normal negative
88 mobility that everything else is built with */
91 if (ship.shp_effic < 21 &&
92 ship.shp_mobil < etu_per_update) {
93 pr("%s needs at least %d mob to navigate.\n",
94 prship(&ship), etu_per_update);
101 bzero(ship.shp_rpath,RET_LEN);
102 putship(ship.shp_uid, &ship);
103 mlp = (struct mlist *) malloc(sizeof(struct mlist));
105 bcopy((s_char *)&ship, (s_char *)&mlp->ship,
106 sizeof(struct shpstr));
107 mlp->mobil = (double)ship.shp_mobil;
108 emp_insque(&mlp->queue, list);
112 /* This function assumes that the list was created by shp_sel */
114 shp_nav(struct emp_qelem *list, double *minmobp, double *maxmobp, int *togetherp, natid actor)
116 extern int update_pending;
117 struct emp_qelem *qp;
118 struct emp_qelem *next;
130 for (qp = list->q_back; qp != list; qp = next) {
132 mlp = (struct mlist *) qp;
133 getship(mlp->ship.shp_uid, &ship);
134 if (ship.shp_own != actor) {
135 mpr(actor, "%s was sunk at %s\n",
137 xyas(ship.shp_x, ship.shp_y, actor));
138 emp_remque((struct emp_qelem *)mlp);
143 if (*ship.shp_path && !update_pending) {
144 shp_mess("has a sail path", mlp);
145 mpr(actor, "Use `sail <#> -' to reset\n");
149 /* check crew - uws don't count */
150 getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP);
151 if (vec[I_MILIT] == 0 && vec[I_CIVIL] == 0) {
152 shp_mess("is crewless", mlp);
155 if (!getsect(ship.shp_x, ship.shp_y, §)) {
156 shp_mess("was sucked into the sky by a strange looking spaceship", mlp); /* heh -KHS */
159 switch (shp_check_nav(§)) {
160 case CN_CONSTRUCTION:
161 shp_mess("is caught in a construction zone", mlp);
164 shp_mess("is landlocked", mlp);
170 shp_mess("was just swallowed by a big green worm", mlp);
178 if (ship.shp_x != allx ||
181 if (ship.shp_mobil + 1 < (int)mlp->mobil) {
182 mlp->mobil = (double)ship.shp_mobil;
184 if (mlp->mobil < *minmobp)
185 *minmobp = mlp->mobil;
186 if (mlp->mobil > *maxmobp)
187 *maxmobp = mlp->mobil;
188 bcopy((s_char *)&ship, (s_char *)&mlp->ship,
189 sizeof(struct shpstr));
194 shp_put(struct emp_qelem *list, natid actor)
196 register struct emp_qelem *qp;
197 register struct emp_qelem *newqp;
202 mlp = (struct mlist *) qp;
203 mpr(actor, "%s stopped at %s\n", prship(&mlp->ship),
204 xyas(mlp->ship.shp_x, mlp->ship.shp_y, mlp->ship.shp_own));
205 mlp->ship.shp_mobil = (int)mlp->mobil;
206 putship(mlp->ship.shp_uid, &mlp->ship);
215 shp_sweep(struct emp_qelem *ship_list, int verbose, natid actor)
217 struct emp_qelem *qp;
218 struct emp_qelem *next;
221 int mines, m, max, shells;
226 for (qp=ship_list->q_back;qp!=ship_list;qp=next) {
228 mlp = (struct mlist *) qp;
229 if (!(mlp->mcp->m_flags & M_SWEEP)) {
231 mpr(actor, "%s doesn't have minesweeping capability!\n", prship(&mlp->ship));
234 if (mlp->mobil <= 0.0) {
236 mpr(actor, "%s is out of mobility!\n", prship(&mlp->ship));
239 getsect(mlp->ship.shp_x,mlp->ship.shp_y,§);
240 if (sect.sct_type != SCT_WATER) {
242 mpr(actor, "%s is not at sea. No mines there!\n", prship(&mlp->ship));
245 mobcost = mlp->ship.shp_effic * 0.01 * mlp->ship.shp_speed;
246 mobcost = 480.0 / (mobcost +
247 techfact(mlp->ship.shp_tech,mobcost));
248 mlp->mobil -= mobcost;
249 mlp->ship.shp_mobil = (int)mlp->mobil;
250 putship(mlp->ship.shp_uid, &mlp->ship);
251 if (!(mines=getvar(V_MINE,(s_char *)§,EF_SECTOR)))
253 max = vl_find(V_SHELL, mlp->mcp->m_vtype,
254 mlp->mcp->m_vamt, (int)mlp->mcp->m_nv);
255 shells = getvar(V_SHELL, (s_char *)&mlp->ship, EF_SHIP);
256 for (m=0; mines > 0 && m < 5; m++) {
258 mpr(actor, "Sweep...\n");
260 shells = min(max, shells + 1);
261 changed |= map_set(actor,
267 putvar(V_MINE, mines, (s_char *)§, EF_SECTOR);
268 putvar(V_SHELL, shells, (s_char *)&mlp->ship, EF_SHIP);
269 if (shp_check_one_mines(mlp)) {
274 putship(mlp->ship.shp_uid, &mlp->ship);
283 shp_check_one_mines(struct mlist *mlp)
290 getsect(mlp->ship.shp_x, mlp->ship.shp_y, §);
291 if (sect.sct_type != SCT_WATER)
293 if (!(mines = getvar(V_MINE, (s_char *)§, EF_SECTOR)))
295 if (chance(DMINE_HITCHANCE(mines))) {
296 actor = mlp->ship.shp_own;
297 shp_hit_mine(&mlp->ship, mlp->mcp);
299 changed |= map_set(actor, sect.sct_x, sect.sct_y, 'X', 0);
302 putvar(V_MINE, mines, (s_char *)§, EF_SECTOR);
304 putship(mlp->ship.shp_uid, (s_char *)&mlp->ship);
305 if (!mlp->ship.shp_own)
312 shp_check_mines(struct emp_qelem *ship_list)
314 struct emp_qelem *qp;
315 struct emp_qelem *next;
319 for (qp=ship_list->q_back;qp!=ship_list;qp=next) {
321 mlp = (struct mlist *) qp;
322 if (shp_check_one_mines(mlp)) {
332 shp_list(struct emp_qelem *ship_list)
334 struct emp_qelem *qp;
335 struct emp_qelem *next;
340 pr("shp# ship type x,y fl eff mil sh gun pn he xl ln mob tech\n");
342 for (qp=ship_list->q_back;qp!=ship_list;qp=next) {
344 mlp = (struct mlist *) qp;
346 pr("%4d ", shp->shp_uid);
347 pr("%-16.16s ", mlp->mcp->m_name);
348 prxy("%4d,%-4d ", shp->shp_x, shp->shp_y, mlp->ship.shp_own);
349 pr("%1c", shp->shp_fleet);
350 pr("%4d%%", shp->shp_effic);
351 getvec(VT_ITEM, vec, (s_char *)shp, EF_SHIP);
352 pr("%4d", vec[I_MILIT]);
353 pr("%4d", vec[I_SHELL]);
354 pr("%4d", vec[I_GUN]);
356 pr("%3d", shp->shp_nplane);
357 pr("%3d",shp->shp_nchoppers);
358 pr("%3d",shp->shp_nxlight);
360 pr("%3d", shp->shp_nland);
361 pr("%4d", shp->shp_mobil);
362 pr("%4d\n", shp->shp_tech);
367 shp_mess(s_char *str, struct mlist *mlp)
369 mpr(mlp->ship.shp_own, "%s %s & stays in %s\n",
371 str, xyas(mlp->ship.shp_x, mlp->ship.shp_y, mlp->ship.shp_own));
372 mlp->ship.shp_mobil = (int)mlp->mobil;
373 putship(mlp->ship.shp_uid, &mlp->ship);
374 emp_remque((struct emp_qelem *)mlp);
379 shp_check_nav(struct sctstr *sect)
381 extern struct dchrstr dchr[];
383 switch (dchr[sect->sct_type].d_flg & 03) {
388 if (sect->sct_effic < 2)
389 return CN_CONSTRUCTION;
392 if (sect->sct_effic < 60)
393 return CN_CONSTRUCTION;
396 return CN_LANDLOCKED;
402 shp_count(struct emp_qelem *list, int wantflags, int nowantflags, int x, int y)
404 struct emp_qelem *qp;
405 struct emp_qelem *next;
409 for (qp = list->q_back; qp != list; qp = next) {
411 mlp = (struct mlist *) qp;
412 if (mlp->ship.shp_x != x || mlp->ship.shp_y != y)
414 if (wantflags && (mlp->mcp->m_flags & wantflags) != wantflags)
416 if (nowantflags && mlp->mcp->m_flags & nowantflags)
424 shp_damage_one(struct mlist *mlp, int dam)
426 shipdamage(&mlp->ship, dam);
427 putship(mlp->ship.shp_uid, &mlp->ship);
428 if (!mlp->ship.shp_own) {
429 emp_remque((struct emp_qelem *)mlp);
435 shp_damage(struct emp_qelem *list, int totdam, int wantflags, int nowantflags, int x, int y)
437 struct emp_qelem *qp;
438 struct emp_qelem *next;
443 if (!totdam || !(count = shp_count(list, wantflags, nowantflags, x, y)))
445 dam = ldround(((double)totdam/(double)count),1);
446 for (qp = list->q_back; qp != list; qp = next) {
448 mlp = (struct mlist *) qp;
449 if (mlp->ship.shp_x != x || mlp->ship.shp_y != y)
451 if (wantflags && (mlp->mcp->m_flags & wantflags) != wantflags)
453 if (nowantflags && mlp->mcp->m_flags & nowantflags)
455 shp_damage_one(mlp, dam);
461 shp_contains(struct emp_qelem *list, int newx, int newy, int wantflags, int nowantflags)
463 struct emp_qelem *qp;
464 struct emp_qelem *next;
467 for (qp = list->q_back; qp != list; qp = next) {
469 mlp = (struct mlist *) qp;
470 /* If the ship isn't in the requested sector, then continue */
471 if (newx != mlp->ship.shp_x || newy != mlp->ship.shp_y)
473 if (wantflags && (mlp->mcp->m_flags & wantflags) != wantflags)
475 if (nowantflags && mlp->mcp->m_flags & nowantflags)
482 static struct mlist *
483 most_valuable_ship(struct emp_qelem *list)
485 struct emp_qelem *qp;
486 struct emp_qelem *next;
488 struct mlist *mvs = 0;
490 for (qp = list->q_back; qp != list; qp = next) {
492 mlp = (struct mlist *) qp;
493 if (mlp->mcp->m_flags & M_SUB)
495 if (!mlp->mcp->m_nxlight &&
496 !mlp->mcp->m_nchoppers &&
497 mlp->mcp->m_cost < 1000 &&
498 !mlp->mcp->m_nplanes &&
505 if (mlp->mcp->m_cost * mlp->ship.shp_effic >
506 mvs->mcp->m_cost * mvs->ship.shp_effic)
512 static int shp_easiest_target(struct emp_qelem *list, int wantflags, int nowantflags)
514 struct emp_qelem *qp;
515 struct emp_qelem *next;
518 int easiest = 9876; /* things start great for victim */
521 for (qp = list->q_back; qp != list; qp = next) {
523 mlp = (struct mlist *) qp;
524 if (wantflags && (mlp->mcp->m_flags & wantflags) != wantflags)
526 if (nowantflags && mlp->mcp->m_flags & nowantflags)
528 hard = shp_hardtarget(&mlp->ship);
530 easiest = hard; /* things get worse for victim */
533 return easiest - count;
537 shp_missile_interdiction(struct emp_qelem *list, coord newx, coord newy, natid victim)
542 struct emp_qelem msl_list, *qp, *newqp;
546 msl_sel(&msl_list, newx, newy, victim, P_T|P_MAR, 0, MI_INTERDICT);
549 while (!QEMPTY(&msl_list) && (mvs = most_valuable_ship(list))) {
550 sprintf(what, "%s", prship(&mvs->ship));
551 dam = msl_launch_mindam(&msl_list, newx, newy,
552 shp_hardtarget(&mvs->ship),
555 what, victim, MI_INTERDICT);
557 mpr(victim, "missile interdiction mission does %d damage to %s!\n", dam, what);
558 shp_damage_one(mvs, dam);
561 } else if (++twotries >= 2) {
565 qp = msl_list.q_forw;
566 while(qp != msl_list.q_forw) {
576 /* Note that this function has a side effect - it uses coastwatch
577 * ranges to see if it should fire upon a ship. So, this function
578 * is expected to return positive if a ship is in range, and 0 if a
579 * ship is not in range. */
581 notify_coastguard(struct emp_qelem *list, int trange, struct sctstr *sectp)
583 struct emp_qelem *qp;
584 struct emp_qelem *next;
589 natp = getnatp(sectp->sct_own);
591 vrange = sectp->sct_type==SCT_RADAR?14:4;
592 vrange *= tfact(sectp->sct_own, 1.0) * sectp->sct_effic / 100.0;
600 /* We got here, so we could theoretically see the ship. Now,
601 * do we want to see it in our telebox? If not, return positive
602 * since we could see the ship and want forts to fire. */
603 if (!(natp->nat_flags & NF_COASTWATCH))
606 for (qp = list->q_back; qp != list; qp = next) {
608 mlp = (struct mlist *) qp;
609 if (mlp->mcp->m_flags & M_SUB)
611 wu(0, sectp->sct_own,
612 "%s %s sighted at %s\n",
613 cname(mlp->ship.shp_own),
615 xyas(mlp->ship.shp_x, mlp->ship.shp_y, sectp->sct_own));
617 setcont(sectp->sct_own, mlp->ship.shp_own, FOUND_LOOK);
625 shp_fort_interdiction(struct emp_qelem *list, coord newx, coord newy, natid victim)
627 extern int fort_max_interdiction_range;
631 double range, range2, guneff;
635 s_char notified[MAXNOC];
638 /* Inform neutral and worse */
639 for (i = 0; i < MAXNOC; ++i) {
640 if (getrel(getnatp(i),victim) <= NEUTRAL)
646 snxtsct_dist(&ns,newx,newy,fort_max_interdiction_range);
647 while (nxtsct(&ns,&fsect)){
650 if (fsect.sct_own == victim)
652 if (notified[fsect.sct_own])
654 trange = mapdist(newx, newy,
655 fsect.sct_x, fsect.sct_y);
656 if (notify_coastguard(list, trange, &fsect))
657 notified[fsect.sct_own] = 1;
659 if (opt_NO_FORT_FIRE) return 0; /* Only coastwatch notify in nofortfire */
660 /* Only fire at Hostile ships */
661 for (i = 0; i < MAXNOC; ++i) {
662 if (getrel(getnatp(i),victim) >= NEUTRAL)
665 snxtsct_dist(&ns,newx,newy,fort_max_interdiction_range);
666 while (nxtsct(&ns,&fsect)){
667 if (!notified[fsect.sct_own])
669 if (fsect.sct_type != SCT_FORTR)
671 gun=getvar(V_GUN,(s_char *)&fsect,EF_SECTOR);
674 range = tfactfire(fsect.sct_own,(double)min(gun,7));
675 if (fsect.sct_effic > 59)
677 range2 = roundrange(range);
678 trange = mapdist(newx, newy,
679 fsect.sct_x, fsect.sct_y);
682 if (getvar(V_MILIT,(s_char *)&fsect,EF_SECTOR)<5)
684 shell = getvar(V_SHELL,(s_char *)&fsect,EF_SECTOR);
686 shell += supply_commod(fsect.sct_own,
687 fsect.sct_x,fsect.sct_y,I_SHELL,
692 putvar(V_SHELL,shell,(s_char *)&fsect,EF_SECTOR);
696 guneff = landgun((int)fsect.sct_effic, gun);
699 mpr(victim, "Incoming fire does %d damage!\n", dam);
701 mpr(victim, "%s fires at you for %d!\n",
702 xyas(fsect.sct_x,fsect.sct_y,victim),
706 "%s fires at %s ships in %s for %d!\n",
707 xyas(fsect.sct_x,fsect.sct_y,
710 xyas(newx,newy,fsect.sct_own), dam);
711 nreport(fsect.sct_own, N_SHP_SHELL, victim, 1);
714 return shp_damage(list, totdam, 0, M_SUB, newx, newy);
719 shp_interdict(struct emp_qelem *list, coord newx, coord newy, natid victim)
723 if (shp_contains(list, newx, newy, 0, M_SUB)) {
724 stopping |= shp_fort_interdiction(list, newx, newy, victim);
726 if (shp_contains(list, newx, newy, 0, M_SUB)) {
727 stopping |= shp_damage(list, unit_interdict(newx,newy,victim,"ships", shp_easiest_target(list, 0, M_SUB), MI_INTERDICT), 0, M_SUB, newx, newy);
728 if (most_valuable_ship(list)) {
729 stopping |= shp_missile_interdiction(list,newx,newy,victim);
733 if (shp_contains(list, newx, newy, M_SUB, 0)) {
734 stopping |= shp_damage(list, unit_interdict(newx, newy, victim, "subs", shp_easiest_target(list, M_SUB, 0), MI_SINTERDICT), M_SUB, 0, newx, newy);
739 /* high value of hardtarget is harder to hit */
740 int shp_hardtarget(struct shpstr *sp)
744 struct mchrstr *mcp = mchr + sp->shp_type;
747 getsect(sp->shp_x,sp->shp_y, §);
748 onsea = (sect.sct_type == SCT_WATER);
749 if (mcp->m_flags & M_SUB)
751 return (int)(((double)sp->shp_effic/100.0) *
752 (20 + (double)sp->shp_speed * onsea/2.0 - vis));
756 shp_hit_mine(struct shpstr *sp, struct mchrstr *mcp)
760 mpr(sp->shp_own, "Kawhomp! Mine detected in %s!\n",
761 xyas(sp->shp_x, sp->shp_y, sp->shp_own));
763 nreport(sp->shp_own, N_HIT_MINE, 0, 1);
765 m = 22.0 + (double)(random() % 21);
766 if (mcp->m_flags & M_SWEEP)
769 shipdamage(sp, ldround(m,1));
775 shp_view(struct emp_qelem *list)
778 struct emp_qelem *qp;
779 struct emp_qelem *next;
782 for (qp=list->q_back;qp!=list;qp=next) {
784 mlp = (struct mlist *)qp;
785 getsect(mlp->ship.shp_x,mlp->ship.shp_y,§);
786 if (mlp->mcp->m_flags & M_FOOD)
787 mpr(mlp->ship.shp_own, "[fert:%d] ", sect.sct_fertil);
788 if (mlp->mcp->m_flags & M_OIL)
789 mpr(mlp->ship.shp_own, "[oil:%d] ", sect.sct_oil);
790 mpr(mlp->ship.shp_own, "%s @ %s %d%% %s\n",
792 xyas(mlp->ship.shp_x, mlp->ship.shp_y, player->cnum),
794 dchr[sect.sct_type].d_name);
799 shp_nav_one_sector(struct emp_qelem *list, int dir, natid actor, int together)
802 struct emp_qelem *qp;
803 struct emp_qelem *next;
804 struct emp_qelem *nqp;
805 struct emp_qelem *nnext;
813 double tech; /* for mapping */
814 double tf; /* for mapping */
817 if (dir <= DIR_STOP || dir >= DIR_VIEW) {
818 shp_put(list, actor);
823 for (qp=list->q_back;qp!=list;qp=next) {
825 mlp = (struct mlist *)qp;
826 newx = xnorm(mlp->ship.shp_x + dx);
827 newy = ynorm(mlp->ship.shp_y + dy);
828 getsect(newx, newy, §);
829 if (shp_check_nav(§) != CN_NAVIGABLE ||
830 (sect.sct_own && actor != sect.sct_own &&
831 getrel(getnatp(sect.sct_own), actor) < FRIENDLY)) {
833 mpr(actor,"can't go to %s\n",xyas(newx, newy, actor));
836 sprintf(dp, "can't go to %s",
837 xyas(newx, newy, actor));
842 if (opt_BIG_CITY && sect.sct_type == SCT_CAPIT) {
843 if (mlp->mcp->m_lcm + 2 * mlp->mcp->m_hcm >= 60) {
844 sprintf(dp, "is too large to fit into the canal system at %s", xyas(newx, newy, actor));
849 if (mlp->mobil <= 0.0) {
850 shp_mess("is out of mobility", mlp);
853 mobcost = mlp->ship.shp_effic * 0.01 * mlp->ship.shp_speed;
855 (mobcost + techfact(mlp->ship.shp_tech, mobcost));
856 mlp->ship.shp_x = newx;
857 mlp->ship.shp_y = newy;
858 if (mlp->mobil - mobcost < -127) {
861 mlp->mobil -= mobcost;
863 mlp->ship.shp_mobil = (int)mlp->mobil;
864 putship(mlp->ship.shp_uid, &mlp->ship);
865 mlp->done = 0; /* We haven't interdicted this ship yet */
867 /* Now update the map for this ship */
868 tech = techfact(mlp->ship.shp_tech, (double)mlp->mcp->m_vrnge);
869 if (mlp->mcp->m_flags & M_SONAR)
870 tf = techfact(mlp->ship.shp_tech, 1.0);
873 radmapupd(mlp->ship.shp_own, mlp->ship.shp_x, mlp->ship.shp_y,
874 (int)mlp->ship.shp_effic, (int)tech, tf);
878 stopping |= shp_sweep(list, 0, actor);
881 stopping |= shp_check_mines(list);
885 /* Ok, run through each ship and interdict each coordinate */
886 for (qp = list->q_back; qp != list; qp = next) {
888 mlp = (struct mlist *) qp;
889 /* Has this ship been interdicted yet? */
892 newx = mlp->ship.shp_x;
893 newy = mlp->ship.shp_y;
894 stopping |= shp_interdict(list, newx, newy, actor);
897 /* Now, set all ships in this coordinate to done */
898 for (nqp = list->q_back; nqp != list; nqp = nnext) {
900 mlp = (struct mlist *)nqp;
901 if (mlp->ship.shp_x == newx && mlp->ship.shp_y == newy)
911 * Check for incoming missiles with a P_MAR flag.
912 * Return True=1 if the missile was shotdown.
915 * Chad Zabel, July 95
919 shp_missile_defense(coord dx, coord dy, natid bombown, int hardtarget)
927 snxtitem_dist(&ni,EF_SHIP,dx,dy,1);
929 while (nxtitem(&ni,(caddr_t)&ship)) {
933 if (!(mchr[(int)ship.shp_type].m_flags & M_ANTIMISSILE))
936 if (getrel(getnatp(ship.shp_own), bombown) >= NEUTRAL)
939 if (ship.shp_effic < 60)
942 if (getvec(VT_ITEM,vec,(caddr_t)&ship,EF_SHIP) < 0)
944 if (vec[I_MILIT] < 1) /* do we have mil? */
946 if (vec[I_SHELL] < 2) { /* do we need shells */
947 if (vec[I_SHELL] += supply_commod(ship.shp_own,
953 if (vec[I_GUN] < 1) /* we need at least 1 gun */
956 /* now calculate the odds */
957 gun = ((double)min(vec[I_GUN],ship.shp_glim));
958 eff = (double)ship.shp_effic / 100.0;
959 teff = (((double)ship.shp_tech)/(((double)ship.shp_tech)+200.0));
960 /* raise 4.5 for better interception -KHS */
961 hitchance = (int)(gun*eff*teff*4.5) - hardtarget;
967 mpr(bombown,"%s anti-missile system activated...",cname(ship.shp_own));
969 "Ship #%i anti-missile system activated!\n",ship.shp_uid);
971 "%d%% hitchance...", hitchance);
973 putvar (V_SHELL, vec[I_SHELL]-2,(caddr_t)&ship, EF_SHIP);
974 putship(ship.shp_uid,&ship);
976 if (roll(100) <= hitchance) {
977 mpr(bombown,"KABOOOM!! Missile destroyed\n\n");
979 "KABOOOM!! Incoming missile destroyed!\n\n");
982 mpr(bombown, "SWOOSH!! anti-missile system failed!!\n");
984 "SWOOSH!! Missile evades anti-missile systems\n\n");
987 return 0; /* all attempts failed */
991 shp_path(int together, struct shpstr *shp, s_char *buf)
995 struct sctstr d_sect;
998 if (!sarg_xy(buf, &destx, &desty))
1001 mpr(shp->shp_own, "Cannot go to a destination sector if not all starting in the same sector\n");
1004 if (!getsect(destx, desty, &d_sect)) {
1005 mpr(shp->shp_own, "%d,%d is not a sector\n", destx, desty);
1009 cp = (s_char *)BestShipPath(buf, shp->shp_x, shp->shp_y,
1010 d_sect.sct_x, d_sect.sct_y, player->cnum);
1011 if (!cp || shp->shp_mobil <= 0) {
1012 mpr(shp->shp_own, "Can't get to '%s' right now.\n",
1013 xyas(d_sect.sct_x, d_sect.sct_y, player->cnum));
1019 /* Fire missiles at a ship which has fired shells */
1021 shp_missdef(struct shpstr *sp, natid victim)
1023 struct emp_qelem list;
1030 mlp = (struct mlist *) malloc(sizeof(struct mlist));
1031 mlp->mcp = &mchr[(int)sp->shp_type];
1032 bcopy((s_char *)sp, (s_char *)&mlp->ship, sizeof(struct shpstr));
1033 mlp->mobil = (double)sp->shp_mobil;
1034 emp_insque(&mlp->queue, &list);
1035 sprintf(buf, "%s", prship(&mlp->ship));
1037 eff = sp->shp_effic;
1038 if (most_valuable_ship(&list)) {
1039 shp_missile_interdiction(&list, sp->shp_x, sp->shp_y, sp->shp_own);
1040 getship(sp->shp_uid, sp);
1043 wu(0, victim, "missiles launched in defense did 100%% damage to %s\n", buf);
1044 wu(0, victim, "%s sunk!\n", buf);
1045 } else if (eff > 0 && sp->shp_effic < eff) {
1046 wu(0, victim, "missiles launched in defense did %d%% damage to %s\n", 100*(eff - sp->shp_effic)/eff, buf);