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