(linenum→info "unix/slp.c:2238")

bsd-games/2.17/sail/dr_3.c

    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: }
Syntax (Markdown)