1 /* $NetBSD: dr_3.c,v 1.15 2003/08/07 09:37:42 agc Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)dr_3.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 __RCSID("$NetBSD: dr_3.c,v 1.15 2003/08/07 09:37:42 agc Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include <stdlib.h> 42 #include <string.h> 43 #include "extern.h" 44 #include "driver.h" 45 46 static int stillmoving(int); 47 static int is_isolated(struct ship *); 48 static int push(struct ship *, struct ship *); 49 static void step(struct ship *, int, char *); 50 51 /* move all comp ships */ 52 void 53 moveall(void) 54 { 55 struct ship *sp, *sq; 56 int n; 57 int k, l; 58 int row[NSHIP], col[NSHIP], dir[NSHIP], drift[NSHIP]; 59 char moved[NSHIP]; 60 61 /* 62 * first try to create moves for OUR ships 63 */ 64 foreachship(sp) { 65 struct ship *closest; 66 int ma, ta; 67 char af; 68 69 if (sp->file->captain[0] || sp->file->dir == 0) 70 continue; 71 if (!sp->file->struck && windspeed && !snagged(sp) 72 && sp->specs->crew3) { 73 ta = maxturns(sp, &af); 74 ma = maxmove(sp, sp->file->dir, 0); 75 closest = closestenemy(sp, 0, 0); 76 if (closest == 0) 77 *sp->file->movebuf = '\0'; 78 else 79 closeon(sp, closest, sp->file->movebuf, 80 ta, ma, af); 81 } else 82 *sp->file->movebuf = '\0'; 83 } 84 /* 85 * Then execute the moves for ALL ships (dead ones too), 86 * checking for collisions and snags at each step. 87 * The old positions are saved in row[], col[], dir[]. 88 * At the end, we compare and write out the changes. 89 */ 90 n = 0; 91 foreachship(sp) { 92 if (snagged(sp)) 93 strcpy(sp->file->movebuf, "d"); 94 else 95 if (*sp->file->movebuf != 'd') 96 strcat(sp->file->movebuf, "d"); 97 row[n] = sp->file->row; 98 col[n] = sp->file->col; 99 dir[n] = sp->file->dir; 100 drift[n] = sp->file->drift; 101 moved[n] = 0; 102 n++; 103 } 104 /* 105 * Now resolve collisions. 106 * This is the tough part. 107 */ 108 for (k = 0; stillmoving(k); k++) { 109 /* 110 * Step once. 111 * And propagate the nulls at the end of sp->file->movebuf. 112 */ 113 n = 0; 114 foreachship(sp) { 115 if (!sp->file->movebuf[k]) 116 sp->file->movebuf[k+1] = '\0'; 117 else if (sp->file->dir) 118 step(sp, sp->file->movebuf[k], &moved[n]); 119 n++; 120 } 121 /* 122 * The real stuff. 123 */ 124 n = 0; 125 foreachship(sp) { 126 if (sp->file->dir == 0 || is_isolated(sp)) 127 goto cont1; 128 l = 0; 129 foreachship(sq) { 130 char snap = 0; 131 132 if (sp == sq) 133 goto cont2; 134 if (sq->file->dir == 0) 135 goto cont2; 136 if (!push(sp, sq)) 137 goto cont2; 138 if (snagged2(sp, sq) && range(sp, sq) > 1) 139 snap++; 140 if (!range(sp, sq) && !fouled2(sp, sq)) { 141 makesignal(sp, "collision with $$", sq); 142 if (dieroll() < 4) { 143 makesignal(sp, "fouled with $$", 144 sq); 145 Write(W_FOUL, sp, l, 0, 0, 0); 146 Write(W_FOUL, sq, n, 0, 0, 0); 147 } 148 snap++; 149 } 150 if (snap) { 151 sp->file->movebuf[k + 1] = 0; 152 sq->file->movebuf[k + 1] = 0; 153 sq->file->row = sp->file->row - 1; 154 if (sp->file->dir == 1 155 || sp->file->dir == 5) 156 sq->file->col = 157 sp->file->col - 1; 158 else 159 sq->file->col = sp->file->col; 160 sq->file->dir = sp->file->dir; 161 } 162 cont2: 163 l++; 164 } 165 cont1: 166 n++; 167 } 168 } 169 /* 170 * Clear old moves. And write out new pos. 171 */ 172 n = 0; 173 foreachship(sp) { 174 if (sp->file->dir != 0) { 175 *sp->file->movebuf = 0; 176 if (row[n] != sp->file->row) 177 Write(W_ROW, sp, sp->file->row, 0, 0, 0); 178 if (col[n] != sp->file->col) 179 Write(W_COL, sp, sp->file->col, 0, 0, 0); 180 if (dir[n] != sp->file->dir) 181 Write(W_DIR, sp, sp->file->dir, 0, 0, 0); 182 if (drift[n] != sp->file->drift) 183 Write(W_DRIFT, sp, sp->file->drift, 0, 0, 0); 184 } 185 n++; 186 } 187 } 188 189 static int 190 stillmoving(int k) 191 { 192 struct ship *sp; 193 194 foreachship(sp) 195 if (sp->file->movebuf[k]) 196 return 1; 197 return 0; 198 } 199 200 static int 201 is_isolated(struct ship *ship) 202 { 203 struct ship *sp; 204 205 foreachship(sp) { 206 if (ship != sp && range(ship, sp) <= 10) 207 return 0; 208 } 209 return 1; 210 } 211 212 static int 213 push(struct ship *from, struct ship *to) 214 { 215 int bs, sb; 216 217 sb = to->specs->guns; 218 bs = from->specs->guns; 219 if (sb > bs) 220 return 1; 221 if (sb < bs) 222 return 0; 223 return from < to; 224 } 225 226 static void 227 step(struct ship *sp, int com, char *moved) 228 { 229 int dist; 230 231 switch (com) { 232 case 'r': 233 if (++sp->file->dir == 9) 234 sp->file->dir = 1; 235 break; 236 case 'l': 237 if (--sp->file->dir == 0) 238 sp->file->dir = 8; 239 break; 240 case '0': case '1': case '2': case '3': 241 case '4': case '5': case '6': case '7': 242 if (sp->file->dir % 2 == 0) 243 dist = dtab[com - '0']; 244 else 245 dist = com - '0'; 246 sp->file->row -= dr[sp->file->dir] * dist; 247 sp->file->col -= dc[sp->file->dir] * dist; 248 *moved = 1; 249 break; 250 case 'b': 251 break; 252 case 'd': 253 if (!*moved) { 254 if (windspeed != 0 && ++sp->file->drift > 2 && 255 ((sp->specs->class >= 3 && !snagged(sp)) 256 || (turn & 1) == 0)) { 257 sp->file->row -= dr[winddir]; 258 sp->file->col -= dc[winddir]; 259 } 260 } else 261 sp->file->drift = 0; 262 break; 263 } 264 } 265 266 void 267 sendbp(struct ship *from, struct ship *to, int sections, int isdefense) 268 { 269 int n; 270 struct BP *bp; 271 272 bp = isdefense ? from->file->DBP : from->file->OBP; 273 for (n = 0; n < NBP && bp[n].turnsent; n++) 274 ; 275 if (n < NBP && sections) { 276 Write(isdefense ? W_DBP : W_OBP, from, 277 n, turn, to->file->index, sections); 278 if (isdefense) 279 makemsg(from, "repelling boarders"); 280 else 281 makesignal(from, "boarding the $$", to); 282 } 283 } 284 285 int 286 is_toughmelee(struct ship *ship, struct ship *to, int isdefense, int count) 287 { 288 struct BP *bp; 289 int obp = 0; 290 int n, OBP = 0, DBP = 0, dbp = 0; 291 int qual; 292 293 qual = ship->specs->qual; 294 bp = isdefense ? ship->file->DBP : ship->file->OBP; 295 for (n = 0; n < NBP; n++, bp++) { 296 if (bp->turnsent && (to == bp->toship || isdefense)) { 297 obp += bp->mensent / 100 298 ? ship->specs->crew1 * qual : 0; 299 obp += (bp->mensent % 100)/10 300 ? ship->specs->crew2 * qual : 0; 301 obp += bp->mensent % 10 302 ? ship->specs->crew3 * qual : 0; 303 } 304 } 305 if (count || isdefense) 306 return obp; 307 OBP = is_toughmelee(to, ship, 0, count + 1); 308 dbp = is_toughmelee(ship, to, 1, count + 1); 309 DBP = is_toughmelee(to, ship, 1, count + 1); 310 if (OBP > obp + 10 || OBP + DBP >= obp + dbp + 10) 311 return 1; 312 else 313 return 0; 314 } 315 316 void 317 reload(void) 318 { 319 struct ship *sp; 320 321 foreachship(sp) { 322 sp->file->loadwith = 0; 323 } 324 } 325 326 void 327 checksails(void) 328 { 329 struct ship *sp; 330 int rig, full; 331 struct ship *close; 332 333 foreachship(sp) { 334 if (sp->file->captain[0] != 0) 335 continue; 336 rig = sp->specs->rig1; 337 if (windspeed == 6 || (windspeed == 5 && sp->specs->class > 4)) 338 rig = 0; 339 if (rig && sp->specs->crew3) { 340 close = closestenemy(sp, 0, 0); 341 if (close != 0) { 342 if (range(sp, close) > 9) 343 full = 1; 344 else 345 full = 0; 346 } else 347 full = 0; 348 } else 349 full = 0; 350 if ((sp->file->FS != 0) != full) 351 Write(W_FS, sp, full, 0, 0, 0); 352 } 353 } 354