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