]> git.pond.sub.org Git - empserver/blob - src/lib/common/xy.c
150828a20eab038261d4b0c092a8d12362b8f050
[empserver] / src / lib / common / xy.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2011, 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-2011
32  */
33
34 #include <config.h>
35
36 #include <errno.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include "file.h"
40 #include "misc.h"
41 #include "nat.h"
42 #include "optlist.h"
43 #include "prototypes.h"
44 #include "sect.h"
45 #include "xy.h"
46
47 /*
48  * return pointer to a string containing the x,y
49  * coords as desired by a particular target country.
50  */
51 char *
52 xyas(coord x, coord y, natid country)
53 {
54     struct natstr *np;
55
56     np = getnatp(country);
57     return prbuf("%d,%d", xrel(np, x), yrel(np, y));
58 }
59
60 char *
61 ownxy(struct sctstr *sp)
62 {
63     return xyas(sp->sct_x, sp->sct_y, sp->sct_own);
64 }
65
66 coord
67 xrel(struct natstr *np, coord absx)
68 {
69     coord x;
70
71     x = XNORM(absx - np->nat_xorg);
72     if (x >= WORLD_X / 2)
73         x -= WORLD_X;
74     return x;
75 }
76
77 coord
78 yrel(struct natstr *np, coord absy)
79 {
80     coord y;
81
82     y = YNORM(absy - np->nat_yorg);
83     if (y >= WORLD_Y / 2)
84         y -= WORLD_Y;
85     return y;
86 }
87
88 void
89 xyrelrange(struct natstr *np, struct range *src, struct range *dst)
90 {
91     dst->lx = xrel(np, src->lx);
92     dst->hx = xrel(np, src->hx);
93     dst->ly = yrel(np, src->ly);
94     dst->hy = yrel(np, src->hy);
95     dst->width = src->width;
96     dst->height = src->height;
97 }
98
99 void
100 xyabsrange(struct natstr *np, struct range *src, struct range *dst)
101 {
102     dst->lx = xabs(np, src->lx);
103     dst->hx = xabs(np, src->hx);
104     dst->ly = yabs(np, src->ly);
105     dst->hy = yabs(np, src->hy);
106     dst->width = src->width;
107     dst->height = src->height;
108 }
109
110 void
111 xysize_range(struct range *rp)
112 {
113     if (rp->lx > rp->hx)
114         rp->width = WORLD_X + rp->hx + 1 - rp->lx;
115     else
116         rp->width = rp->hx + 1 - rp->lx;
117     if (CANT_HAPPEN(rp->width > WORLD_X))
118         rp->width = WORLD_X;
119     if (rp->ly > rp->hy)
120         rp->height = WORLD_Y + rp->hy + 1 - rp->ly;
121     else
122         rp->height = rp->hy + 1 - rp->ly;
123     if (CANT_HAPPEN(rp->height > WORLD_Y))
124         rp->height = WORLD_Y;
125 }
126
127 void
128 xydist_range(coord x, coord y, int dist, struct range *rp)
129 {
130     if (4 * dist + 1 < WORLD_X) {
131         rp->lx = xnorm(x - 2 * dist);
132         rp->hx = xnorm(x + 2 * dist);
133         rp->width = 4 * dist + 1;
134     } else {
135         rp->lx = xnorm(x - WORLD_X / 2);
136         rp->hx = xnorm(rp->lx + WORLD_X - 1);
137         rp->width = WORLD_X;
138     }
139
140     if (2 * dist + 1 < WORLD_Y) {
141         rp->ly = ynorm(y - dist);
142         rp->hy = ynorm(y + dist);
143         rp->height = 2 * dist + 1;
144     } else {
145         rp->ly = ynorm(y - WORLD_Y / 2);
146         rp->hy = ynorm(rp->ly + WORLD_Y - 1);
147         rp->height = WORLD_Y;
148     }
149 }
150
151 /*
152  * Convert initial part of STR to normalized x-coordinate.
153  * Return -1 on error.  This works, as normalized coordinates are
154  * non-negative.
155  * Assign pointer to first character after the coordinate to *END,
156  * unless END is a null pointer.
157  */
158 coord
159 strtox(char *str, char **end)
160 {
161     long l;
162
163     errno = 0;
164     l = strtol(str, end, 10);
165     if (*end == str || errno != 0)
166         return -1;
167     return XNORM(l);
168 }
169
170 /*
171  * Convert initial part of STR to normalized y-coordinate.
172  * Return -1 on error.  This works, as normalized coordinates are
173  * non-negative.
174  * Assign pointer to first character after the coordinate to *END,
175  * unless END is a null pointer.
176  */
177 coord
178 strtoy(char *str, char **end)
179 {
180     long l;
181
182     errno = 0;
183     l = strtol(str, end, 10);
184     if (*end == str || errno != 0)
185         return -1;
186     return YNORM(l);
187 }
188
189 coord
190 xabs(struct natstr *np, coord relx)
191 {
192     relx += np->nat_xorg;
193     return XNORM(relx);
194 }
195
196 coord
197 yabs(struct natstr *np, coord rely)
198 {
199     rely += np->nat_yorg;
200     return YNORM(rely);
201 }
202
203 int
204 sctoff(coord x, coord y)
205 {
206     if (CANT_HAPPEN((x + y) & 1))
207         return -1;
208     return XYOFFSET(XNORM(x), YNORM(y));
209 }
210
211 coord
212 xnorm(coord x)
213 {
214     return XNORM(x);
215 }
216
217 coord
218 ynorm(coord y)
219 {
220     return YNORM(y);
221 }
222
223 int
224 xyinrange(coord x, coord y, struct range *rp)
225 {
226     if (rp->lx <= rp->hx) {
227         /* xrange doesn't wrap */
228         if (x < rp->lx || x > rp->hx)
229             return 0;
230     } else {
231         if (x < rp->lx && x > rp->hx)
232             return 0;
233     }
234     if (rp->ly <= rp->hy) {
235         /* yrange doesn't wrap */
236         if (y < rp->ly || y > rp->hy)
237             return 0;
238     } else {
239         if (y < rp->ly && y > rp->hy)
240             return 0;
241     }
242     return 1;
243 }
244
245
246 char *
247 prbuf(char *format, ...)
248 {
249     static int nbuf = -1;
250     static char buf[20][1024];
251     va_list ap;
252
253     if (++nbuf > 19)
254         nbuf = 0;
255
256     va_start(ap, format);
257     (void)vsprintf(buf[nbuf], format, ap);
258     va_end(ap);
259
260     return buf[nbuf];
261 }