xref: /original-bsd/games/sail/misc.c (revision 0842ddeb)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)misc.c	8.2 (Berkeley) 04/28/95";
10 #endif /* not lint */
11 
12 #include "extern.h"
13 #include "pathnames.h"
14 
15 #define distance(x,y) (abs(x) >= abs(y) ? abs(x) + abs(y)/2 : abs(y) + abs(x)/2)
16 
17 /* XXX */
18 range(from, to)
19 struct ship *from, *to;
20 {
21 	register bow1r, bow1c, bow2r, bow2c;
22 	int stern1r, stern1c, stern2c, stern2r;
23 	register int bb, bs, sb, ss, result;
24 
25 	if (!to->file->dir)
26 		return -1;
27 	stern1r = bow1r = from->file->row;
28 	stern1c = bow1c = from->file->col;
29 	stern2r = bow2r = to->file->row;
30 	stern2c = bow2c = to->file->col;
31 	result = bb = distance(bow2r - bow1r, bow2c - bow1c);
32 	if (bb < 5) {
33 		stern2r += dr[to->file->dir];
34 		stern2c += dc[to->file->dir];
35 		stern1r += dr[from->file->dir];
36 		stern1c += dc[from->file->dir];
37 		bs = distance((bow2r - stern1r), (bow2c - stern1c));
38 		sb = distance((bow1r - stern2r), (bow1c - stern2c));
39 		ss = distance((stern2r - stern1r) ,(stern2c - stern1c));
40 		result = min(bb, min(bs, min(sb, ss)));
41 	}
42 	return result;
43 }
44 
45 struct ship *
46 closestenemy(from, side, anyship)
47 register struct ship *from;
48 char side, anyship;
49 {
50 	register struct ship *sp;
51 	register char a;
52 	int olddist = 30000, dist;
53 	struct ship *closest = 0;
54 
55 	a = capship(from)->nationality;
56 	foreachship(sp) {
57 		if (sp == from)
58 			continue;
59 		if (sp->file->dir == 0)
60 			continue;
61 		if (a == capship(sp)->nationality && !anyship)
62 			continue;
63 		if (side && gunsbear(from, sp) != side)
64 			continue;
65 		dist = range(from, sp);
66 		if (dist < olddist) {
67 			closest = sp;
68 			olddist = dist;
69 		}
70 	}
71 	return closest;
72 }
73 
74 angle(dr, dc)
75 register dr, dc;
76 {
77 	register i;
78 
79 	if (dc >= 0 && dr > 0)
80 		i = 0;
81 	else if (dr <= 0 && dc > 0)
82 		i = 2;
83 	else if (dc <= 0 && dr < 0)
84 		i = 4;
85 	else
86 		i = 6;
87 	dr = abs(dr);
88 	dc = abs(dc);
89 	if ((i == 0 || i == 4) && dc * 2.4 > dr) {
90 		i++;
91 		if (dc > dr * 2.4)
92 			i++;
93 	} else if ((i == 2 || i == 6) && dr * 2.4 > dc) {
94 		i++;
95 		if (dr > dc * 2.4)
96 			i++;
97 	}
98 	return i % 8 + 1;
99 }
100 
101 gunsbear(from, to)		/* checks for target bow or stern */
102 register struct ship *from, *to;
103 {
104 	int Dr, Dc, i;
105 	register ang;
106 
107 	Dr = from->file->row - to->file->row;
108 	Dc = to->file->col - from->file->col;
109 	for (i = 2; i; i--) {
110 		if ((ang = angle(Dr, Dc) - from->file->dir + 1) < 1)
111 			ang += 8;
112 		if (ang >= 2 && ang <= 4)
113 			return 'r';
114 		if (ang >= 6 && ang <= 7)
115 			return 'l';
116 		Dr += dr[to->file->dir];
117 		Dc += dc[to->file->dir];
118 	}
119 	return 0;
120 }
121 
122 portside(from, on, quick)
123 register struct ship *from, *on;
124 int quick;			/* returns true if fromship is */
125 {				/* shooting at onship's starboard side */
126 	register ang;
127 	register Dr, Dc;
128 
129 	Dr = from->file->row - on->file->row;
130 	Dc = on->file->col - from->file->col;
131 	if (quick == -1) {
132 		Dr += dr[on->file->dir];
133 		Dc += dc[on->file->dir];
134 	}
135 	ang = angle(Dr, Dc);
136 	if (quick != 0)
137 		return ang;
138 	ang = (ang + 4 - on->file->dir - 1) % 8 + 1;
139 	return ang < 5;
140 }
141 
142 colours(sp)
143 register struct ship *sp;
144 {
145 	register char flag;
146 
147 	if (sp->file->struck)
148 		flag = '!';
149 	if (sp->file->explode)
150 		flag = '#';
151 	if (sp->file->sink)
152 		flag = '~';
153 	if (sp->file->struck)
154 		return flag;
155 	flag = *countryname[capship(sp)->nationality];
156 	return sp->file->FS ? flag : tolower(flag);
157 }
158 
159 #include <sys/file.h>
160 log(s)
161 register struct ship *s;
162 {
163 	FILE *fp;
164 	int persons;
165 	int n;
166 	struct logs log[NLOG];
167 	float net;
168 	register struct logs *lp;
169 
170 	if ((fp = fopen(_PATH_LOGFILE, "r+")) == NULL)
171 		return;
172 #ifdef LOCK_EX
173 	if (flock(fileno(fp), LOCK_EX) < 0)
174 		return;
175 #endif
176 	net = (float)s->file->points / s->specs->pts;
177 	persons = getw(fp);
178 	n = fread((char *)log, sizeof(struct logs), NLOG, fp);
179 	for (lp = &log[n]; lp < &log[NLOG]; lp++)
180 		lp->l_name[0] = lp->l_uid = lp->l_shipnum
181 			= lp->l_gamenum = lp->l_netpoints = 0;
182 	rewind(fp);
183 	if (persons < 0)
184 		(void) putw(1, fp);
185 	else
186 		(void) putw(persons + 1, fp);
187 	for (lp = log; lp < &log[NLOG]; lp++)
188 		if (net > (float)lp->l_netpoints
189 		    / scene[lp->l_gamenum].ship[lp->l_shipnum].specs->pts) {
190 			(void) fwrite((char *)log,
191 				sizeof (struct logs), lp - log, fp);
192 			(void) strcpy(log[NLOG-1].l_name, s->file->captain);
193 			log[NLOG-1].l_uid = getuid();
194 			log[NLOG-1].l_shipnum = s->file->index;
195 			log[NLOG-1].l_gamenum = game;
196 			log[NLOG-1].l_netpoints = s->file->points;
197 			(void) fwrite((char *)&log[NLOG-1],
198 				sizeof (struct logs), 1, fp);
199 			(void) fwrite((char *)lp,
200 				sizeof (struct logs), &log[NLOG-1] - lp, fp);
201 			break;
202 		}
203 #ifdef LOCK_EX
204 	(void) flock(fileno(fp), LOCK_UN);
205 #endif
206 	(void) fclose(fp);
207 }
208