dr_1.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /* $NetBSD: dr_1.c,v 1.21 2004/11/05 21:30:32 dsl Exp $ */
  2. /*
  3. * Copyright (c) 1983, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #include <sys/cdefs.h>
  31. #ifndef lint
  32. #if 0
  33. static char sccsid[] = "@(#)dr_1.c 8.1 (Berkeley) 5/31/93";
  34. #else
  35. __RCSID("$NetBSD: dr_1.c,v 1.21 2004/11/05 21:30:32 dsl Exp $");
  36. #endif
  37. #endif /* not lint */
  38. #include <ctype.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include "extern.h"
  43. #include "driver.h"
  44. static int fightitout(struct ship *, struct ship *, int);
  45. void
  46. unfoul(void)
  47. {
  48. struct ship *sp;
  49. struct ship *to;
  50. int nat;
  51. int i;
  52. foreachship(sp) {
  53. if (sp->file->captain[0])
  54. continue;
  55. nat = capship(sp)->nationality;
  56. foreachship(to) {
  57. if (nat != capship(to)->nationality &&
  58. !is_toughmelee(sp, to, 0, 0))
  59. continue;
  60. for (i = fouled2(sp, to); --i >= 0;)
  61. if (dieroll() <= 2)
  62. cleanfoul(sp, to, 0);
  63. }
  64. }
  65. }
  66. void
  67. boardcomp(void)
  68. {
  69. int crew[3];
  70. struct ship *sp, *sq;
  71. foreachship(sp) {
  72. if (*sp->file->captain)
  73. continue;
  74. if (sp->file->dir == 0)
  75. continue;
  76. if (sp->file->struck || sp->file->captured != 0)
  77. continue;
  78. if (!snagged(sp))
  79. continue;
  80. crew[0] = sp->specs->crew1 != 0;
  81. crew[1] = sp->specs->crew2 != 0;
  82. crew[2] = sp->specs->crew3 != 0;
  83. foreachship(sq) {
  84. if (!Xsnagged2(sp, sq))
  85. continue;
  86. if (meleeing(sp, sq))
  87. continue;
  88. if (!sq->file->dir
  89. || sp->nationality == capship(sq)->nationality)
  90. continue;
  91. switch (sp->specs->class - sq->specs->class) {
  92. case -3: case -4: case -5:
  93. if (crew[0]) {
  94. /* OBP */
  95. sendbp(sp, sq, crew[0]*100, 0);
  96. crew[0] = 0;
  97. } else if (crew[1]){
  98. /* OBP */
  99. sendbp(sp, sq, crew[1]*10, 0);
  100. crew[1] = 0;
  101. }
  102. break;
  103. case -2:
  104. if (crew[0] || crew[1]) {
  105. /* OBP */
  106. sendbp(sp, sq, crew[0]*100+crew[1]*10,
  107. 0);
  108. crew[0] = crew[1] = 0;
  109. }
  110. break;
  111. case -1: case 0: case 1:
  112. if (crew[0]) {
  113. /* OBP */
  114. sendbp(sp, sq, crew[0]*100+crew[1]*10,
  115. 0);
  116. crew[0] = crew[1] = 0;
  117. }
  118. break;
  119. case 2: case 3: case 4: case 5:
  120. /* OBP */
  121. sendbp(sp, sq, crew[0]*100+crew[1]*10+crew[2],
  122. 0);
  123. crew[0] = crew[1] = crew[2] = 0;
  124. break;
  125. }
  126. }
  127. }
  128. }
  129. static int
  130. fightitout(struct ship *from, struct ship *to, int key)
  131. {
  132. struct ship *fromcap, *tocap;
  133. int crewfrom[3], crewto[3], menfrom, mento;
  134. int pcto, pcfrom, fromstrength, strengthto, frominjured, toinjured;
  135. int topoints;
  136. int index, totalfrom = 0, totalto = 0;
  137. int count;
  138. char message[60];
  139. menfrom = mensent(from, to, crewfrom, &fromcap, &pcfrom, key);
  140. mento = mensent(to, from, crewto, &tocap, &pcto, 0);
  141. if (fromcap == 0)
  142. fromcap = from;
  143. if (tocap == 0)
  144. tocap = to;
  145. if (key) {
  146. if (!menfrom) { /* if crew surprised */
  147. if (fromcap == from)
  148. menfrom = from->specs->crew1
  149. + from->specs->crew2
  150. + from->specs->crew3;
  151. else
  152. menfrom = from->file->pcrew;
  153. } else {
  154. menfrom *= 2; /* DBP's fight at an advantage */
  155. }
  156. }
  157. fromstrength = menfrom * fromcap->specs->qual;
  158. strengthto = mento * tocap->specs->qual;
  159. for (count = 0;
  160. ((fromstrength < strengthto * 3 && strengthto < fromstrength * 3)
  161. || fromstrength == -1) && count < 4;
  162. count++) {
  163. index = fromstrength/10;
  164. if (index > 8)
  165. index = 8;
  166. toinjured = MT[index][2 - dieroll() / 3];
  167. totalto += toinjured;
  168. index = strengthto/10;
  169. if (index > 8)
  170. index = 8;
  171. frominjured = MT[index][2 - dieroll() / 3];
  172. totalfrom += frominjured;
  173. menfrom -= frominjured;
  174. mento -= toinjured;
  175. fromstrength = menfrom * fromcap->specs->qual;
  176. strengthto = mento * tocap->specs->qual;
  177. }
  178. if (fromstrength >= strengthto * 3 || count == 4) {
  179. unboard(to, from, 0);
  180. subtract(from, fromcap, totalfrom, crewfrom, pcfrom);
  181. subtract(to, tocap, totalto, crewto, pcto);
  182. makemsg(from, "boarders from %s repelled", to->shipname);
  183. sprintf(message, "killed in melee: %d. %s: %d",
  184. totalto, from->shipname, totalfrom);
  185. Writestr(W_SIGNAL, to, message);
  186. if (key)
  187. return 1;
  188. } else if (strengthto >= fromstrength * 3) {
  189. unboard(from, to, 0);
  190. subtract(from, fromcap, totalfrom, crewfrom, pcfrom);
  191. subtract(to, tocap, totalto, crewto, pcto);
  192. if (key) {
  193. if (fromcap != from)
  194. Write(W_POINTS, fromcap,
  195. fromcap->file->points -
  196. from->file->struck
  197. ? from->specs->pts
  198. : 2 * from->specs->pts,
  199. 0, 0, 0);
  200. /* ptr1 points to the shipspec for the ship that was just unboarded.
  201. I guess that what is going on here is that the pointer is multiplied
  202. or something. */
  203. Write(W_CAPTURED, from, to->file->index, 0, 0, 0);
  204. topoints = 2 * from->specs->pts + to->file->points;
  205. if (from->file->struck)
  206. topoints -= from->specs->pts;
  207. Write(W_POINTS, to, topoints, 0, 0, 0);
  208. mento = crewto[0] ? crewto[0] : crewto[1];
  209. if (mento) {
  210. subtract(to, tocap, mento, crewto, pcto);
  211. subtract(from, to, - mento, crewfrom, 0);
  212. }
  213. sprintf(message, "captured by the %s!", to->shipname);
  214. Writestr(W_SIGNAL, from, message);
  215. sprintf(message, "killed in melee: %d. %s: %d",
  216. totalto, from->shipname, totalfrom);
  217. Writestr(W_SIGNAL, to, message);
  218. mento = 0;
  219. return 0;
  220. }
  221. }
  222. return 0;
  223. }
  224. void
  225. resolve(void)
  226. {
  227. int thwart;
  228. struct ship *sp, *sq;
  229. foreachship(sp) {
  230. if (sp->file->dir == 0)
  231. continue;
  232. for (sq = sp + 1; sq < ls; sq++)
  233. if (sq->file->dir && meleeing(sp, sq) && meleeing(sq, sp))
  234. fightitout(sp, sq, 0);
  235. thwart = 2;
  236. foreachship(sq) {
  237. if (sq->file->dir && meleeing(sq, sp))
  238. thwart = fightitout(sp, sq, 1);
  239. if (!thwart)
  240. break;
  241. }
  242. if (!thwart) {
  243. foreachship(sq) {
  244. if (sq->file->dir && meleeing(sq, sp))
  245. unboard(sq, sp, 0);
  246. unboard(sp, sq, 0);
  247. }
  248. unboard(sp, sp, 1);
  249. } else if (thwart == 2)
  250. unboard(sp, sp, 1);
  251. }
  252. }
  253. void
  254. compcombat(void)
  255. {
  256. int n;
  257. struct ship *sp;
  258. struct ship *closest;
  259. int crew[3], men = 0, target, temp;
  260. int r, guns, ready, load, car;
  261. int index, rakehim, sternrake;
  262. int shootat, hit;
  263. foreachship(sp) {
  264. if (sp->file->captain[0] || sp->file->dir == 0)
  265. continue;
  266. crew[0] = sp->specs->crew1;
  267. crew[1] = sp->specs->crew2;
  268. crew[2] = sp->specs->crew3;
  269. for (n = 0; n < 3; n++) {
  270. if (sp->file->OBP[n].turnsent)
  271. men += sp->file->OBP[n].mensent;
  272. }
  273. for (n = 0; n < 3; n++) {
  274. if (sp->file->DBP[n].turnsent)
  275. men += sp->file->DBP[n].mensent;
  276. }
  277. if (men){
  278. crew[0] = men/100 ? 0 : crew[0] != 0;
  279. crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
  280. crew[2] = men%10 ? 0 : crew[2] != 0;
  281. }
  282. for (r = 0; r < 2; r++) {
  283. if (!crew[2])
  284. continue;
  285. if (sp->file->struck)
  286. continue;
  287. if (r) {
  288. ready = sp->file->readyR;
  289. guns = sp->specs->gunR;
  290. car = sp->specs->carR;
  291. } else {
  292. ready = sp->file->readyL;
  293. guns = sp->specs->gunL;
  294. car = sp->specs->carL;
  295. }
  296. if (!guns && !car)
  297. continue;
  298. if ((ready & R_LOADED) == 0)
  299. continue;
  300. closest = closestenemy(sp, r ? 'r' : 'l', 0);
  301. if (closest == 0)
  302. continue;
  303. if (range(closest, sp) > range(sp, closestenemy(sp, r ? 'r' : 'l', 1)))
  304. continue;
  305. if (closest->file->struck)
  306. continue;
  307. target = range(sp, closest);
  308. if (target > 10)
  309. continue;
  310. if (!guns && target >= 3)
  311. continue;
  312. load = L_ROUND;
  313. if (target == 1 && sp->file->loadwith == L_GRAPE)
  314. load = L_GRAPE;
  315. if (target <= 3 && closest->file->FS)
  316. load = L_CHAIN;
  317. if (target == 1 && load != L_GRAPE)
  318. load = L_DOUBLE;
  319. if (load > L_CHAIN && target < 6)
  320. shootat = HULL;
  321. else
  322. shootat = RIGGING;
  323. rakehim = gunsbear(sp, closest)
  324. && !gunsbear(closest, sp);
  325. temp = portside(closest, sp, 1)
  326. - closest->file->dir + 1;
  327. if (temp < 1)
  328. temp += 8;
  329. if (temp > 8)
  330. temp -= 8;
  331. sternrake = temp > 4 && temp < 6;
  332. index = guns;
  333. if (target < 3)
  334. index += car;
  335. index = (index - 1) / 3;
  336. index = index > 8 ? 8 : index;
  337. if (!rakehim)
  338. hit = HDT[index][target-1];
  339. else
  340. hit = HDTrake[index][target-1];
  341. if (rakehim && sternrake)
  342. hit++;
  343. hit += QUAL[index][capship(sp)->specs->qual - 1];
  344. for (n = 0; n < 3 && sp->file->captured == 0; n++)
  345. if (!crew[n]) {
  346. if (index <= 5)
  347. hit--;
  348. else
  349. hit -= 2;
  350. }
  351. if (ready & R_INITIAL) {
  352. if (!r)
  353. sp->file->readyL &= ~R_INITIAL;
  354. else
  355. sp->file->readyR &= ~R_INITIAL;
  356. if (index <= 3)
  357. hit++;
  358. else
  359. hit += 2;
  360. }
  361. if (sp->file->captured != 0) {
  362. if (index <= 1)
  363. hit--;
  364. else
  365. hit -= 2;
  366. }
  367. hit += AMMO[index][load - 1];
  368. temp = sp->specs->class;
  369. if ((temp >= 5 || temp == 1) && windspeed == 5)
  370. hit--;
  371. if (windspeed == 6 && temp == 4)
  372. hit -= 2;
  373. if (windspeed == 6 && temp <= 3)
  374. hit--;
  375. if (hit >= 0) {
  376. if (load != L_GRAPE)
  377. hit = hit > 10 ? 10 : hit;
  378. table(sp, closest, shootat, load, hit, dieroll());
  379. }
  380. }
  381. }
  382. }
  383. int
  384. next(void)
  385. {
  386. if (++turn % 55 == 0) {
  387. if (alive)
  388. alive = 0;
  389. else
  390. people = 0;
  391. }
  392. if (people <= 0 || windspeed == 7) {
  393. struct ship *s;
  394. struct ship *bestship = NULL;
  395. float net, best = 0.0;
  396. foreachship(s) {
  397. if (*s->file->captain)
  398. continue;
  399. net = (float)s->file->points / s->specs->pts;
  400. if (net > best) {
  401. best = net;
  402. bestship = s;
  403. }
  404. }
  405. if (best > 0.0) {
  406. char *tp = getenv("WOTD");
  407. const char *p;
  408. if (tp == 0)
  409. p = "Driver";
  410. else {
  411. *tp = toupper((unsigned char)*tp);
  412. p = tp;
  413. }
  414. strlcpy(bestship->file->captain, p,
  415. sizeof bestship->file->captain);
  416. logger(bestship);
  417. }
  418. return -1;
  419. }
  420. Write(W_TURN, SHIP(0), turn, 0, 0, 0);
  421. if (turn % 7 == 0 && (dieroll() >= cc->windchange || !windspeed)) {
  422. switch (dieroll()) {
  423. case 1:
  424. winddir = 1;
  425. break;
  426. case 2:
  427. break;
  428. case 3:
  429. winddir++;
  430. break;
  431. case 4:
  432. winddir--;
  433. break;
  434. case 5:
  435. winddir += 2;
  436. break;
  437. case 6:
  438. winddir -= 2;
  439. break;
  440. }
  441. if (winddir > 8)
  442. winddir -= 8;
  443. if (winddir < 1)
  444. winddir += 8;
  445. if (windspeed)
  446. switch (dieroll()) {
  447. case 1:
  448. case 2:
  449. windspeed--;
  450. break;
  451. case 5:
  452. case 6:
  453. windspeed++;
  454. break;
  455. }
  456. else
  457. windspeed++;
  458. Write(W_WIND, SHIP(0), winddir, windspeed, 0, 0);
  459. }
  460. return 0;
  461. }