1 /* $NetBSD: dr_3.c,v 1.19 2009/03/14 22:52:52 dholland 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.19 2009/03/14 22:52:52 dholland 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 bool 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 == NULL) 77 *sp->file->movebuf = '\0'; 78 else 79 closeon(sp, closest, sp->file->movebuf, 80 sizeof(sp->file->movebuf), 81 ta, ma, af); 82 } else 83 *sp->file->movebuf = '\0'; 84 } 85 /* 86 * Then execute the moves for ALL ships (dead ones too), 87 * checking for collisions and snags at each step. 88 * The old positions are saved in row[], col[], dir[]. 89 * At the end, we compare and write out the changes. 90 */ 91 n = 0; 92 foreachship(sp) { 93 if (snagged(sp)) 94 strcpy(sp->file->movebuf, "d"); 95 else 96 if (*sp->file->movebuf != 'd') 97 strcat(sp->file->movebuf, "d"); 98 row[n] = sp->file->row; 99 col[n] = sp->file->col; 100 dir[n] = sp->file->dir; 101 drift[n] = sp->file->drift; 102 moved[n] = 0; 103 n++; 104 } 105 /* 106 * Now resolve collisions. 107 * This is the tough part. 108 */ 109 for (k = 0; stillmoving(k); k++) { 110 /* 111 * Step once. 112 * And propagate the nulls at the end of sp->file->movebuf. 113 */ 114 n = 0; 115 foreachship(sp) { 116 if (!sp->file->movebuf[k]) 117 sp->file->movebuf[k+1] = '\0'; 118 else if (sp->file->dir) 119 step(sp, sp->file->movebuf[k], &moved[n]); 120 n++; 121 } 122 /* 123 * The real stuff. 124 */ 125 n = 0; 126 foreachship(sp) { 127 if (sp->file->dir == 0 || is_isolated(sp)) 128 goto cont1; 129 l = 0; 130 foreachship(sq) { 131 char snap = 0; 132 133 if (sp == sq) 134 goto cont2; 135 if (sq->file->dir == 0) 136 goto cont2; 137 if (!push(sp, sq)) 138 goto cont2; 139 if (snagged2(sp, sq) && range(sp, sq) > 1) 140 snap++; 141 if (!range(sp, sq) && !fouled2(sp, sq)) { 142 makesignal(sp, "collision with $$", sq); 143 if (dieroll() < 4) { 144 makesignal(sp, "fouled with $$", 145 sq); 146 send_foul(sp, l); 147 send_foul(sq, n); 148 } 149 snap++; 150 } 151 if (snap) { 152 sp->file->movebuf[k + 1] = 0; 153 sq->file->movebuf[k + 1] = 0; 154 sq->file->row = sp->file->row - 1; 155 if (sp->file->dir == 1 156 || sp->file->dir == 5) 157 sq->file->col = 158 sp->file->col - 1; 159 else 160 sq->file->col = sp->file->col; 161 sq->file->dir = sp->file->dir; 162 } 163 cont2: 164 l++; 165 } 166 cont1: 167 n++; 168 } 169 } 170 /* 171 * Clear old moves. And write out new pos. 172 */ 173 n = 0; 174 foreachship(sp) { 175 if (sp->file->dir != 0) { 176 *sp->file->movebuf = 0; 177 if (row[n] != sp->file->row) 178 send_row(sp, sp->file->row); 179 if (col[n] != sp->file->col) 180 send_col(sp, sp->file->col); 181 if (dir[n] != sp->file->dir) 182 send_dir(sp, sp->file->dir); 183 if (drift[n] != sp->file->drift) 184 send_drift(sp, sp->file->drift); 185 } 186 n++; 187 } 188 } 189 190 static int 191 stillmoving(int k) 192 { 193 struct ship *sp; 194 195 foreachship(sp) 196 if (sp->file->movebuf[k]) 197 return 1; 198 return 0; 199 } 200 201 static int 202 is_isolated(struct ship *ship) 203 { 204 struct ship *sp; 205 206 foreachship(sp) { 207 if (ship != sp && range(ship, sp) <= 10) 208 return 0; 209 } 210 return 1; 211 } 212 213 static int 214 push(struct ship *from, struct ship *to) 215 { 216 int bs, sb; 217 218 sb = to->specs->guns; 219 bs = from->specs->guns; 220 if (sb > bs) 221 return 1; 222 if (sb < bs) 223 return 0; 224 return from < to; 225 } 226 227 static void 228 step(struct ship *sp, int com, char *moved) 229 { 230 int dist; 231 232 switch (com) { 233 case 'r': 234 if (++sp->file->dir == 9) 235 sp->file->dir = 1; 236 break; 237 case 'l': 238 if (--sp->file->dir == 0) 239 sp->file->dir = 8; 240 break; 241 case '0': case '1': case '2': case '3': 242 case '4': case '5': case '6': case '7': 243 if (sp->file->dir % 2 == 0) 244 dist = dtab[com - '0']; 245 else 246 dist = com - '0'; 247 sp->file->row -= dr[sp->file->dir] * dist; 248 sp->file->col -= dc[sp->file->dir] * dist; 249 *moved = 1; 250 break; 251 case 'b': 252 break; 253 case 'd': 254 if (!*moved) { 255 if (windspeed != 0 && ++sp->file->drift > 2 && 256 ((sp->specs->class >= 3 && !snagged(sp)) 257 || (turn & 1) == 0)) { 258 sp->file->row -= dr[winddir]; 259 sp->file->col -= dc[winddir]; 260 } 261 } else { 262 sp->file->drift = 0; 263 } 264 break; 265 } 266 } 267 268 void 269 sendbp(struct ship *from, struct ship *to, int sections, int isdefense) 270 { 271 int n; 272 struct BP *bp; 273 274 bp = isdefense ? from->file->DBP : from->file->OBP; 275 for (n = 0; n < NBP && bp[n].turnsent; n++) 276 ; 277 if (n < NBP && sections) { 278 if (isdefense) { 279 send_dbp(from, n, turn, to->file->index, sections); 280 } else { 281 send_obp(from, n, turn, to->file->index, sections); 282 } 283 if (isdefense) 284 makemsg(from, "repelling boarders"); 285 else 286 makesignal(from, "boarding the $$", to); 287 } 288 } 289 290 int 291 is_toughmelee(struct ship *ship, struct ship *to, int isdefense, int count) 292 { 293 struct BP *bp; 294 int obp = 0; 295 int n, OBP = 0, DBP = 0, dbp = 0; 296 int qual; 297 298 qual = ship->specs->qual; 299 bp = isdefense ? ship->file->DBP : ship->file->OBP; 300 for (n = 0; n < NBP; n++, bp++) { 301 if (bp->turnsent && (to == bp->toship || isdefense)) { 302 obp += bp->mensent / 100 303 ? ship->specs->crew1 * qual : 0; 304 obp += (bp->mensent % 100)/10 305 ? ship->specs->crew2 * qual : 0; 306 obp += bp->mensent % 10 307 ? ship->specs->crew3 * qual : 0; 308 } 309 } 310 if (count || isdefense) 311 return obp; 312 OBP = is_toughmelee(to, ship, 0, count + 1); 313 dbp = is_toughmelee(ship, to, 1, count + 1); 314 DBP = is_toughmelee(to, ship, 1, count + 1); 315 if (OBP > obp + 10 || OBP + DBP >= obp + dbp + 10) 316 return 1; 317 else 318 return 0; 319 } 320 321 void 322 reload(void) 323 { 324 struct ship *sp; 325 326 foreachship(sp) { 327 sp->file->loadwith = 0; 328 } 329 } 330 331 void 332 checksails(void) 333 { 334 struct ship *sp; 335 int rig, full; 336 struct ship *close; 337 338 foreachship(sp) { 339 if (sp->file->captain[0] != 0) 340 continue; 341 rig = sp->specs->rig1; 342 if (windspeed == 6 || (windspeed == 5 && sp->specs->class > 4)) 343 rig = 0; 344 if (rig && sp->specs->crew3) { 345 close = closestenemy(sp, 0, 0); 346 if (close != NULL) { 347 if (range(sp, close) > 9) 348 full = 1; 349 else 350 full = 0; 351 } else { 352 full = 0; 353 } 354 } else { 355 full = 0; 356 } 357 if ((sp->file->FS != 0) != full) 358 send_fs(sp, full); 359 } 360 } 361