nrelease - fix/improve livecd
[dragonfly.git] / games / sail / dr_2.c
1 /*      $NetBSD: dr_2.c,v 1.27 2019/02/03 10:48:46 mrg 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_2.c      8.1 (Berkeley) 5/31/93";
36 #else
37 __RCSID("$NetBSD: dr_2.c,v 1.27 2019/02/03 10:48:46 mrg Exp $");
38 #endif
39 #endif /* not lint */
40
41 #include <stdbool.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include "extern.h"
46 #include "driver.h"
47
48 #define couldwin(f,t) (f->specs->crew2 > t->specs->crew2 * 1.5)
49
50 static int str_end(const char *);
51 static int score(struct ship *, struct ship *, char *, size_t, int);
52 static void move_ship(struct ship *, const char *, unsigned char *,
53                       short *, short *, int *);
54 static void try(struct ship *f, struct ship *t,
55                 char *command, size_t commandmax, char *temp, size_t tempmax,
56                 int ma, int ta, bool af, int vma, int dir, int *high,
57                 int rakeme);
58 static void rmend(char *);
59
60 const int dtab[] = {0,1,1,2,3,4,4,5};   /* diagonal distances in x==y */
61
62 void
63 thinkofgrapples(void)
64 {
65         struct ship *sp, *sq;
66         bool friendly;
67
68         foreachship(sp) {
69                 if (sp->file->captain[0] || sp->file->dir == 0)
70                         continue;
71                 foreachship(sq) {
72                         friendly = sp->nationality == capship(sq)->nationality;
73                         if (!friendly) {
74                                 if (sp->file->struck || sp->file->captured != 0)
75                                         continue;
76                                 if (range(sp, sq) != 1)
77                                         continue;
78                                 if (grappled2(sp, sq)) {
79                                         if (is_toughmelee(sp, sq, 0, 0))
80                                                 ungrap(sp, sq);
81                                         else
82                                                 grap(sp, sq);
83                                 } else if (couldwin(sp, sq)) {
84                                         grap(sp, sq);
85                                         sp->file->loadwith = L_GRAPE;
86                                 }
87                         } else
88                                 ungrap(sp, sq);
89                 }
90         }
91 }
92
93 void
94 checkup(void)
95 {
96         struct ship *sp, *sq;
97         char explode, sink;
98
99         foreachship(sp) {
100                 if (sp->file->dir == 0)
101                         continue;
102                 explode = sp->file->explode;
103                 sink = sp->file->sink;
104                 if (explode != 1 && sink != 1)
105                         continue;
106                 if (dieroll() < 5)
107                         continue;
108                 if (sink == 1) {
109                         send_sink(sp, 2);
110                 } else {
111                         send_explode(sp, 2);
112                 }
113                 send_dir(sp, 0);
114                 if (snagged(sp))
115                         foreachship(sq)
116                                 cleansnag(sp, sq, 1);
117                 if (sink != 1) {
118                         makemsg(sp, "exploding!");
119                         foreachship(sq) {
120                                 if (sp != sq && sq->file->dir &&
121                                     range(sp, sq) < 4)
122                                         table(sp, sq, RIGGING, L_EXPLODE,
123                                               sp->specs->guns/13, 6);
124                         }
125                 } else {
126                         makemsg(sp, "sinking!");
127                 }
128         }
129 }
130
131 void
132 prizecheck(void)
133 {
134         struct ship *sp;
135
136         foreachship(sp) {
137                 if (sp->file->captured == 0)
138                         continue;
139                 if (sp->file->struck || sp->file->dir == 0)
140                         continue;
141                 if (sp->specs->crew1 + sp->specs->crew2 + sp->specs->crew3 >
142                     sp->file->pcrew * 6) {
143                         send_signal(sp, "prize crew overthrown");
144                         send_points(sp->file->captured,
145                               sp->file->captured->file->points
146                                 - 2 * sp->specs->pts);
147                         send_captured(sp, -1);
148                 }
149         }
150 }
151
152 static int
153 str_end(const char *str)
154 {
155         const char *p;
156
157         for (p = str; *p; p++)
158                 ;
159         return p == str ? 0 : p[-1];
160 }
161
162 void
163 closeon(struct ship *from, struct ship *to, char *command, size_t commandmax,
164         int ta, int ma, bool af)
165 {
166         int high;
167         char temp[10];
168
169         temp[0] = command[0] = '\0';
170         high = -30000;
171         try(from, to, command, commandmax, temp, sizeof(temp),
172             ma, ta, af, ma, from->file->dir, &high, 0);
173 }
174
175 static int
176 score(struct ship *ship, struct ship *to, char *movement, size_t movementmax,
177       int onlytemp)
178 {
179         int drift;
180         int row, col, dir, total, ran;
181         struct File *fp = ship->file;
182
183         if ((dir = fp->dir) == 0)
184                 return 0;
185         row = fp->row;
186         col = fp->col;
187         drift = fp->drift;
188         move_ship(ship, movement, &fp->dir, &fp->row, &fp->col, &drift);
189         if (!*movement)
190                 strlcpy(movement, "d", movementmax);
191
192         ran = range(ship, to);
193         total = -50 * ran;
194         if (ran < 4 && gunsbear(ship, to))
195                 total += 60;
196         if ((ran = portside(ship, to, 1) - fp->dir) == 4 || ran == -4)
197                 total = -30000;
198
199         if (!onlytemp) {
200                 fp->row = row;
201                 fp->col = col;
202                 fp->dir = dir;
203         }
204         return total;
205 }
206
207 static void
208 move_ship(struct ship *ship, const char *p, unsigned char *dir,
209           short *row, short *col, int *drift)
210 {
211         int dist;
212         char moved = 0;
213
214         for (; *p; p++) {
215                 switch (*p) {
216                 case 'r':
217                         if (++*dir == 9)
218                                 *dir = 1;
219                         break;
220                 case 'l':
221                         if (--*dir == 0)
222                                 *dir = 8;
223                         break;
224                 case '1': case '2': case '3': case '4':
225                 case '5': case '6': case '7':
226                         moved++;
227                         if (*dir % 2 == 0)
228                                 dist = dtab[*p - '0'];
229                         else
230                                 dist = *p - '0';
231                         *row -= dr[*dir] * dist;
232                         *col -= dc[*dir] * dist;
233                         break;
234                 }
235         }
236         if (!moved) {
237                 if (windspeed != 0 && ++*drift > 2) {
238                         if ((ship->specs->class >= 3 && !snagged(ship))
239                             || (turn & 1) == 0) {
240                                 *row -= dr[winddir];
241                                 *col -= dc[winddir];
242                         }
243                 }
244         } else
245                 *drift = 0;
246 }
247
248 static void
249 try(struct ship *f, struct ship *t,
250     char *command, size_t commandmax,
251     char *temp, size_t tempmax,
252     int ma, int ta, bool af, int vma, int dir, int *high, int rakeme)
253 {
254         int new, n;
255         char st[11];
256 #define rakeyou (gunsbear(f, t) && !gunsbear(t, f))
257
258         if ((n = str_end(temp)) < '1' || n > '9')
259                 for (n = 1; vma - n >= 0; n++) {
260                         snprintf(st, sizeof(st), "%d", n);
261                         strlcat(temp, st, tempmax);
262                         new = score(f, t, temp, tempmax, rakeme);
263                         if (new > *high && (!rakeme || rakeyou)) {
264                                 *high = new;
265                                 strlcpy(command, temp, commandmax);
266                         }
267                         try(f, t, command, commandmax, temp, tempmax,
268                             ma-n, ta, af, vma-n,
269                             dir, high, rakeme);
270                         rmend(temp);
271                 }
272         if ((ma > 0 && ta > 0 && (n = str_end(temp)) != 'l' && n != 'r') ||
273             !strlen(temp)) {
274                 strlcat(temp, "r", tempmax);
275                 new = score(f, t, temp, tempmax, rakeme);
276                 if (new > *high && (!rakeme ||
277                                     (gunsbear(f, t) && !gunsbear(t, f)))) {
278                         *high = new;
279                         strlcpy(command, temp, commandmax);
280                 }
281                 try(f, t, command, commandmax, temp, tempmax,
282                     ma-1, ta-1, af,
283                     min(ma-1, maxmove(f, (dir == 8 ? 1 : dir+1), 0)),
284                     (dir == 8 ? 1 : dir+1), high, rakeme);
285                 rmend(temp);
286         }
287         if ((ma > 0 && ta > 0 && (n = str_end(temp)) != 'l' && n != 'r') ||
288             !strlen(temp)) {
289                 strlcat(temp, "l", tempmax);
290                 new = score(f, t, temp, tempmax, rakeme);
291                 if (new > *high && (!rakeme ||
292                                     (gunsbear(f, t) && !gunsbear(t, f)))) {
293                         *high = new;
294                         strlcpy(command, temp, commandmax);
295                 }
296                 try(f, t, command, commandmax, temp, tempmax,
297                     ma-1, ta-1, af,
298                     (min(ma-1,maxmove(f, (dir-1 ? dir-1 : 8), 0))),
299                     (dir-1 ? dir -1 : 8), high, rakeme);
300                 rmend(temp);
301         }
302 }
303
304 static void
305 rmend(char *str)
306 {
307         char *p;
308
309         for (p = str; *p; p++)
310                 ;
311         if (p != str)
312                 *--p = 0;
313 }