]> git.pond.sub.org Git - empserver/blob - src/lib/subs/snxtsct.c
Update copyright notice.
[empserver] / src / lib / subs / snxtsct.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2004, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program 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 2 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, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  snxtsct.c: Arrange sector selection using either distance or area
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1989
32  */
33
34 #include "misc.h"
35 #include "player.h"
36 #include "var.h"
37 #include "xy.h"
38 #include "sect.h"
39 #include "nsc.h"
40 #include "file.h"
41 #include "com.h"
42 #include "prototypes.h"
43 #include "optlist.h"
44
45 /*
46  * setup the nstr_sect structure for sector selection.
47  * can select on either NS_ALL, NS_AREA, or NS_RANGE
48  * iterate thru the "condarg" string looking
49  * for arguments to compile into the nstr.
50  */
51 int
52 snxtsct(register struct nstr_sect *np, s_char *str)
53 {
54     struct range range;
55     coord cx, cy;
56     int dist, n;
57     s_char buf[1024];
58     struct range wr;
59
60     if (str == 0 || *str == 0) {
61         if ((str = getstring("(sects)? ", buf)) == 0)
62             return 0;
63     }
64     wr.lx = -WORLD_X / 2;
65     wr.ly = -WORLD_Y / 2;
66     wr.hx = WORLD_X / 2;
67     wr.hy = WORLD_Y / 2;
68     wr.width = wr.height = 0;
69     switch (sarg_type(str)) {
70     case NS_AREA:
71         if (!sarg_area(str, &range))
72             return 0;
73         snxtsct_area(np, &range);
74         break;
75     case NS_DIST:
76         if (!sarg_range(str, &cx, &cy, &dist))
77             return 0;
78         snxtsct_dist(np, cx, cy, dist);
79         break;
80     case NS_ALL:
81         /* fake "all" by doing a world-sized area query */
82         snxtsct_area(np, &wr);
83         break;
84     default:
85         return 0;
86     }
87     if (player->condarg == 0)
88         return 1;
89     n = nstr_comp(np->cond, sizeof(np->cond) / sizeof(*np->cond),
90                   EF_SECTOR, player->condarg);
91     np->ncond = n >= 0 ? n : 0;
92     return n >= 0;
93 }
94
95 void
96 snxtsct_all(struct nstr_sect *np)
97 {
98     struct range worldrange;
99
100     worldrange.lx = -WORLD_X / 2;
101     worldrange.ly = -WORLD_Y / 2;
102     worldrange.hx = WORLD_X / 2;
103     worldrange.hy = WORLD_Y / 2;
104     worldrange.width = worldrange.height = 0;
105     snxtsct_area(np, &worldrange);
106 }
107
108 void
109 snxtsct_area(register struct nstr_sect *np, struct range *range)
110 {
111     memset(np, 0, sizeof(*np));
112     np->range = *range;
113     np->ncond = 0;
114     np->type = NS_AREA;
115     np->read = ef_read;
116     np->x = np->range.lx - 1;
117     np->y = np->range.ly;
118     np->dx = -1;
119     np->dy = 0;
120     xysize_range(&np->range);
121     ef_zapcache(EF_SECTOR);
122 }
123
124 void
125 snxtsct_rewind(struct nstr_sect *np)
126 {
127     np->x = np->range.lx - 1;
128     np->y = np->range.ly;
129     np->dx = -1;
130     np->dy = 0;
131     np->id = -1;
132     ef_zapcache(EF_SECTOR);
133 }
134
135 void
136 snxtsct_dist(register struct nstr_sect *np, coord cx, coord cy, int dist)
137 {
138     memset(np, 0, sizeof(*np));
139     xydist_range(cx, cy, dist, &np->range);
140     np->cx = cx;
141     np->cy = cy;
142     np->ncond = 0;
143     np->dist = dist;
144     np->type = NS_DIST;
145     np->read = ef_read;
146     np->x = np->range.lx - 1;
147     np->y = np->range.ly;
148     np->dx = -1;
149     np->dy = 0;
150 #if 0
151     /* This function is now done elsewhere. */
152     /* It was not doing the right thing when the world was small */
153     xysize_range(&np->range);
154 #endif
155     ef_zapcache(EF_SECTOR);
156 }
157
158 void
159 xysize_range(register struct range *rp)
160 {
161     if (rp->lx >= rp->hx)
162         rp->width = WORLD_X + rp->hx - rp->lx;
163     else
164         rp->width = rp->hx - rp->lx;
165 #ifndef HAY
166     /* This is a necessary check for small, hitech worlds. */
167     if (rp->width > WORLD_X)
168         rp->width = WORLD_X;
169 #endif
170     if (rp->ly >= rp->hy)
171         rp->height = WORLD_Y + rp->hy - rp->ly;
172     else
173         rp->height = rp->hy - rp->ly;
174 #ifndef HAY
175     /* This is a necessary check for small, hitech worlds. */
176     if (rp->height > WORLD_Y)
177         rp->height = WORLD_Y;
178 #endif
179 }
180
181 /* This is called also called in snxtitem.c */
182 void
183 xydist_range(coord x, coord y, register int dist, struct range *rp)
184 {
185     if (dist < WORLD_X / 4) {
186         rp->lx = xnorm((coord)(x - 2 * dist));
187         rp->hx = xnorm((coord)(x + 2 * dist) + 1);
188         rp->width = 4 * dist + 1;
189     } else {
190         /* Range is larger than the world */
191         /* Make sure we get lx in the right place. */
192         rp->lx = xnorm((coord)(x - WORLD_X / 2));
193         rp->hx = xnorm((coord)(rp->lx + WORLD_X - 1));
194         rp->width = WORLD_X;
195     }
196
197     if (dist < WORLD_Y / 2) {
198         rp->ly = ynorm((coord)(y - dist));
199         rp->hy = ynorm((coord)(y + dist) + 1);
200         rp->height = 2 * dist + 1;
201     } else {
202         /* Range is larger than the world */
203         rp->ly = ynorm((coord)(y - WORLD_Y / 2));
204         rp->hy = ynorm((coord)(rp->ly + WORLD_Y - 1));
205         rp->height = WORLD_Y;
206     }
207 }