]> git.pond.sub.org Git - empserver/blob - src/lib/common/xy.c
Update copyright notice
[empserver] / src / lib / common / xy.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2017, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  xy.c: x-y related conversion routines
28  *
29  *  Known contributors to this file:
30  *     Dave Pare, 1989
31  *     Markus Armbruster, 2004-2013
32  */
33
34 #include <config.h>
35
36 #include <errno.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include "misc.h"
40 #include "nat.h"
41 #include "optlist.h"
42 #include "prototypes.h"
43 #include "sect.h"
44 #include "xy.h"
45
46 /*
47  * return pointer to a string containing the x,y
48  * coords as desired by a particular target country.
49  */
50 char *
51 xyas(coord x, coord y, natid country)
52 {
53     struct natstr *np;
54
55     np = getnatp(country);
56     return prbuf("%d,%d", xrel(np, x), yrel(np, y));
57 }
58
59 char *
60 ownxy(struct sctstr *sp)
61 {
62     return xyas(sp->sct_x, sp->sct_y, sp->sct_own);
63 }
64
65 coord
66 xrel(struct natstr *np, coord absx)
67 {
68     coord x;
69
70     x = XNORM(absx - np->nat_xorg);
71     if (x >= WORLD_X / 2)
72         x -= WORLD_X;
73     return x;
74 }
75
76 coord
77 yrel(struct natstr *np, coord absy)
78 {
79     coord y;
80
81     y = YNORM(absy - np->nat_yorg);
82     if (y >= WORLD_Y / 2)
83         y -= WORLD_Y;
84     return y;
85 }
86
87 void
88 xyrelrange(struct natstr *np, struct range *src, struct range *dst)
89 {
90     dst->lx = xrel(np, src->lx);
91     dst->hx = xrel(np, src->hx);
92     dst->ly = yrel(np, src->ly);
93     dst->hy = yrel(np, src->hy);
94     dst->width = src->width;
95     dst->height = src->height;
96 }
97
98 void
99 xyabsrange(struct natstr *np, struct range *src, struct range *dst)
100 {
101     dst->lx = xabs(np, src->lx);
102     dst->hx = xabs(np, src->hx);
103     dst->ly = yabs(np, src->ly);
104     dst->hy = yabs(np, src->hy);
105     dst->width = src->width;
106     dst->height = src->height;
107 }
108
109 void
110 xysize_range(struct range *rp)
111 {
112     if (rp->lx > rp->hx)
113         rp->width = WORLD_X + rp->hx + 1 - rp->lx;
114     else
115         rp->width = rp->hx + 1 - rp->lx;
116     if (CANT_HAPPEN(rp->width > WORLD_X))
117         rp->width = WORLD_X;
118     if (rp->ly > rp->hy)
119         rp->height = WORLD_Y + rp->hy + 1 - rp->ly;
120     else
121         rp->height = rp->hy + 1 - rp->ly;
122     if (CANT_HAPPEN(rp->height > WORLD_Y))
123         rp->height = WORLD_Y;
124 }
125
126 void
127 xydist_range(coord x, coord y, int dist, struct range *rp)
128 {
129     if (4 * dist + 1 < WORLD_X) {
130         rp->lx = xnorm(x - 2 * dist);
131         rp->hx = xnorm(x + 2 * dist);
132         rp->width = 4 * dist + 1;
133     } else {
134         rp->lx = xnorm(x - WORLD_X / 2);
135         rp->hx = xnorm(rp->lx + WORLD_X - 1);
136         rp->width = WORLD_X;
137     }
138
139     if (2 * dist + 1 < WORLD_Y) {
140         rp->ly = ynorm(y - dist);
141         rp->hy = ynorm(y + dist);
142         rp->height = 2 * dist + 1;
143     } else {
144         rp->ly = ynorm(y - WORLD_Y / 2);
145         rp->hy = ynorm(rp->ly + WORLD_Y - 1);
146         rp->height = WORLD_Y;
147     }
148 }
149
150 /*
151  * Convert initial part of @str to normalized x-coordinate.
152  * Return -1 on error.  This works, as normalized coordinates are
153  * non-negative.
154  * Assign pointer to first character after the coordinate to *@end,
155  * unless @end is a null pointer.
156  */
157 coord
158 strtox(char *str, char **end)
159 {
160     long l;
161
162     errno = 0;
163     l = strtol(str, end, 10);
164     if (*end == str || errno != 0)
165         return -1;
166     return XNORM(l);
167 }
168
169 /*
170  * Convert initial part of @str to normalized y-coordinate.
171  * Return -1 on error.  This works, as normalized coordinates are
172  * non-negative.
173  * Assign pointer to first character after the coordinate to *@end,
174  * unless @end is a null pointer.
175  */
176 coord
177 strtoy(char *str, char **end)
178 {
179     long l;
180
181     errno = 0;
182     l = strtol(str, end, 10);
183     if (*end == str || errno != 0)
184         return -1;
185     return YNORM(l);
186 }
187
188 coord
189 xabs(struct natstr *np, coord relx)
190 {
191     relx += np->nat_xorg;
192     return XNORM(relx);
193 }
194
195 coord
196 yabs(struct natstr *np, coord rely)
197 {
198     rely += np->nat_yorg;
199     return YNORM(rely);
200 }
201
202 int
203 sctoff(coord x, coord y)
204 {
205     if (CANT_HAPPEN((x + y) & 1))
206         return -1;
207     return XYOFFSET(XNORM(x), YNORM(y));
208 }
209
210 void sctoff2xy(coord *x, coord *y, int off)
211 {
212     *y = off * 2 / WORLD_X;
213     *x = off * 2 % WORLD_X + *y % 2;
214 }
215
216 coord
217 xnorm(coord x)
218 {
219     return XNORM(x);
220 }
221
222 coord
223 ynorm(coord y)
224 {
225     return YNORM(y);
226 }
227
228 int
229 xyinrange(coord x, coord y, struct range *rp)
230 {
231     if (rp->lx <= rp->hx) {
232         /* xrange doesn't wrap */
233         if (x < rp->lx || x > rp->hx)
234             return 0;
235     } else {
236         if (x < rp->lx && x > rp->hx)
237             return 0;
238     }
239     if (rp->ly <= rp->hy) {
240         /* yrange doesn't wrap */
241         if (y < rp->ly || y > rp->hy)
242             return 0;
243     } else {
244         if (y < rp->ly && y > rp->hy)
245             return 0;
246     }
247     return 1;
248 }
249
250
251 char *
252 prbuf(char *format, ...)
253 {
254     static int nbuf = -1;
255     static char buf[20][1024];
256     va_list ap;
257
258     if (++nbuf > 19)
259         nbuf = 0;
260
261     va_start(ap, format);
262     (void)vsprintf(buf[nbuf], format, ap);
263     va_end(ap);
264
265     return buf[nbuf];
266 }