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