1 /*
2  * XPilot NG, a multiplayer space war game.
3  *
4  * Copyright (C) 2000-2004 by
5  *
6  *      Uoti Urpala          <uau@users.sourceforge.net>
7  *      Kristian S�derblom   <kps@users.sourceforge.net>
8  *
9  * Copyright (C) 1991-2001 by
10  *
11  *      Bj�rn Stabell        <bjoern@xpilot.org>
12  *      Ken Ronny Schouten   <ken@xpilot.org>
13  *      Bert Gijsbers        <bert@xpilot.org>
14  *      Dick Balaska         <dick@xpilot.org>
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  */
30 
31 #ifndef	MAP_H
32 #define	MAP_H
33 
34 #ifndef TYPES_H
35 # include "types.h"
36 #endif
37 #ifndef RULES_H
38 # include "rules.h"
39 #endif
40 #ifndef ITEM_H
41 # include "item.h"
42 #endif
43 
44 #define SPACE			0
45 #define BASE			1
46 #define FILLED			2
47 #define REC_LU			3
48 #define REC_LD			4
49 #define REC_RU			5
50 #define REC_RD			6
51 #define FUEL			7
52 #define CANNON			8
53 #define CHECK			9
54 #define POS_GRAV		10
55 #define NEG_GRAV		11
56 #define CWISE_GRAV		12
57 #define ACWISE_GRAV		13
58 #define WORMHOLE		14
59 #define TREASURE		15
60 #define TARGET			16
61 #define ITEM_CONCENTRATOR	17
62 #define DECOR_FILLED		18
63 #define DECOR_LU		19
64 #define DECOR_LD		20
65 #define DECOR_RU		21
66 #define DECOR_RD		22
67 #define UP_GRAV			23
68 #define DOWN_GRAV		24
69 #define RIGHT_GRAV		25
70 #define LEFT_GRAV		26
71 #define FRICTION		27
72 #define ASTEROID_CONCENTRATOR	28
73 #define BASE_ATTRACTOR		127
74 
75 #define DIR_RIGHT		0
76 #define DIR_UP			(RES/4)
77 #define DIR_LEFT		(RES/2)
78 #define DIR_DOWN		(3*RES/4)
79 
80 typedef struct world world_t;
81 extern world_t		World, *world;
82 
83 typedef struct fuel {
84     clpos_t	pos;
85     double	fuel;
86     uint32_t	conn_mask;
87     long	last_change;
88     int		team;
89 } fuel_t;
90 
91 typedef struct grav {
92     clpos_t	pos;
93     double	force;
94     int		type;
95 } grav_t;
96 
97 typedef struct base {
98     clpos_t	pos;
99     int		dir;
100     int		ind;
101     int		team;
102     int		order;
103     int		initial_items[NUM_ITEMS];
104 } base_t;
105 
106 typedef struct cannon {
107     clpos_t	pos;
108     int		dir;
109     uint32_t	conn_mask;
110     long	last_change;
111     int		item[NUM_ITEMS];
112     int		tractor_target_id;
113     bool	tractor_is_pressor;
114     int		team;
115     long	used;
116     double	dead_ticks;
117     double	damaged;
118     double	tractor_count;
119     double	emergency_shield_left;
120     double	phasing_left;
121     int		group;
122     double	score;
123     short	id;
124     short	smartness;
125     float	shot_speed;
126     int		initial_items[NUM_ITEMS];
127 } cannon_t;
128 
129 typedef struct check {
130     clpos_t	pos;
131 } check_t;
132 
133 typedef struct item {
134     double	prob;		/* Probability [0..1] for item to appear */
135     int		max;		/* Max on world at a given time */
136     int		num;		/* Number active right now */
137     int		chance;		/* Chance [0..127] for this item to appear */
138     double	cannonprob;	/* Relative probability for item to appear */
139     int		min_per_pack;	/* minimum number of elements per item. */
140     int		max_per_pack;	/* maximum number of elements per item. */
141     int		initial;	/* initial number of elements per player. */
142     int		cannon_initial;	/* initial number of elements per cannon. */
143     int		limit;		/* max number of elements per player/cannon. */
144 } item_t;
145 
146 typedef struct asteroid {
147     double	prob;		/* Probability [0..1] for asteroid to appear */
148     int		max;		/* Max on world at a given time */
149     int		num;		/* Number active right now */
150     int		chance;		/* Chance [0..127] for asteroid to appear */
151 } asteroid_t;
152 
153 typedef enum {
154     WORM_NORMAL,
155     WORM_IN,
156     WORM_OUT,
157     WORM_FIXED
158 } wormtype_t;
159 
160 typedef struct wormhole {
161     clpos_t	pos;
162     int		lastdest;	/* last destination wormhole */
163     double	countdown;	/* >0 warp to lastdest else random */
164     wormtype_t	type;
165     int		lastID;
166     int		lastblock;	/* block it occluded */
167     int		group;
168 } wormhole_t;
169 
170 typedef struct treasure {
171     clpos_t	pos;
172     bool	have;		/* true if this treasure has ball in it */
173     int		team;		/* team of this treasure */
174     int 	destroyed;	/* how often this treasure destroyed */
175     bool	empty;		/* true if this treasure never had a ball */
176     int		ball_style;	/* polystyle to use for color */
177 } treasure_t;
178 
179 typedef struct target {
180     clpos_t	pos;
181     int		team;
182     double	dead_ticks;
183     double	damage;
184     uint32_t	conn_mask;
185     uint32_t 	update_mask;
186     long	last_change;
187     int		group;
188 } target_t;
189 
190 typedef struct team {
191     int		NumMembers;		/* Number of current members */
192     int		NumRobots;		/* Number of robot players */
193     int		NumBases;		/* Number of bases owned */
194     int		NumTreasures;		/* Number of treasures owned */
195     int		NumEmptyTreasures;	/* Number of empty treasures owned */
196     int		TreasuresDestroyed;	/* Number of destroyed treasures */
197     int		TreasuresLeft;		/* Number of treasures left */
198     int		SwapperId;		/* Player swapping to this full team */
199 } team_t;
200 
201 typedef struct item_concentrator {
202     clpos_t	pos;
203 } item_concentrator_t;
204 
205 typedef struct asteroid_concentrator {
206     clpos_t	pos;
207 } asteroid_concentrator_t;
208 
209 typedef struct friction_area {
210     clpos_t	pos;
211     double	friction_setting;	/* Setting from map */
212     double	friction;		/* Changes with gameSpeed */
213     int		group;
214 } friction_area_t;
215 
216 #define MAX_PLAYER_ECMS		8	/* Maximum simultaneous per player */
217 typedef struct {
218     double	size;
219     clpos_t	pos;
220     int		id;
221 } ecm_t;
222 
223 /*
224  * Transporter info.
225  */
226 typedef struct {
227     clpos_t	pos;
228     int		victim_id;
229     int		id;
230     double	count;
231 } transporter_t;
232 
233 
234 extern bool is_polygon_map;
235 
236 struct world {
237     int		x, y;		/* Size of world in blocks, rounded up */
238     int		bwidth_floor;	/* Width of world in blocks, rounded down */
239     int		bheight_floor;	/* Height of world in blocks, rounded down */
240     double	diagonal;	/* Diagonal length in blocks */
241     int		width, height;	/* Size of world in pixels (optimization) */
242     int		cwidth, cheight;/* Size of world in clicks */
243     double	hypotenuse;	/* Diagonal length in pixels (optimization) */
244     rules_t	*rules;
245     char	name[MAX_CHARS];
246     char	author[MAX_CHARS];
247     char	dataURL[MAX_CHARS];
248 
249     u_byte	**block;	/* type of item in each block */
250     vector_t	**gravity;
251     item_t	items[NUM_ITEMS];
252     asteroid_t	asteroids;
253     team_t	teams[MAX_TEAMS];
254 
255     int		NumTeamBases;	/* How many 'different' teams are allowed */
256 
257     arraylist_t	*asteroidConcs;
258     arraylist_t	*bases;
259     arraylist_t	*cannons;
260     arraylist_t	*ecms;
261     arraylist_t	*fuels;
262     arraylist_t	*frictionAreas;
263     arraylist_t	*gravs;
264     arraylist_t	*itemConcs;
265     arraylist_t	*targets;
266     arraylist_t	*transporters;
267     arraylist_t	*treasures;
268     arraylist_t	*wormholes;
269 
270     int		NumChecks, MaxChecks;
271     check_t	*checks;
272 
273     bool	have_options;
274 };
275 
World_set_block(blkpos_t blk,int type)276 static inline void World_set_block(blkpos_t blk, int type)
277 {
278     assert (! (blk.bx < 0 || blk.bx >= world->x
279 	       || blk.by < 0 || blk.by >= world->y));
280     world->block[blk.bx][blk.by] = type;
281 }
282 
World_get_block(blkpos_t blk)283 static inline int World_get_block(blkpos_t blk)
284 {
285     assert (! (blk.bx < 0 || blk.bx >= world->x
286 	       || blk.by < 0 || blk.by >= world->y));
287     return world->block[blk.bx][blk.by];
288 }
289 
World_contains_clpos(clpos_t pos)290 static inline bool World_contains_clpos(clpos_t pos)
291 {
292     if (pos.cx < 0 || pos.cx >= world->cwidth)
293 	return false;
294     if (pos.cy < 0 || pos.cy >= world->cheight)
295 	return false;
296     return true;
297 }
298 
World_get_random_clpos(void)299 static inline clpos_t World_get_random_clpos(void)
300 {
301     clpos_t pos;
302 
303     pos.cx = (int)(rfrac() * world->cwidth);
304     pos.cy = (int)(rfrac() * world->cheight);
305 
306     return pos;
307 }
308 
World_wrap_xclick(int cx)309 static inline int World_wrap_xclick(int cx)
310 {
311     while (cx < 0)
312 	cx += world->cwidth;
313     while (cx >= world->cwidth)
314 	cx -= world->cwidth;
315 
316     return cx;
317 }
318 
World_wrap_yclick(int cy)319 static inline int World_wrap_yclick(int cy)
320 {
321     while (cy < 0)
322 	cy += world->cheight;
323     while (cy >= world->cheight)
324 	cy -= world->cheight;
325 
326     return cy;
327 }
328 
World_wrap_clpos(clpos_t pos)329 static inline clpos_t World_wrap_clpos(clpos_t pos)
330 {
331     pos.cx = World_wrap_xclick(pos.cx);
332     pos.cy = World_wrap_yclick(pos.cy);
333 
334     return pos;
335 }
336 
337 
338 /*
339  * Two inline function for edge wrap of x and y coordinates measured
340  * in clicks.
341  *
342  * Note that even when wrap play is off, ships will wrap around the map
343  * if there is not walls that hinder it.
344  */
WRAP_XCLICK(int cx)345 static inline int WRAP_XCLICK(int cx)
346 {
347     return World_wrap_xclick(cx);
348 }
349 
WRAP_YCLICK(int cy)350 static inline int WRAP_YCLICK(int cy)
351 {
352     return World_wrap_yclick(cy);
353 }
354 
355 
356 /*
357  * Two macros for edge wrap of differences in position.
358  * If the absolute value of a difference is bigger than
359  * half the map size then it is wrapped.
360  */
361 #define WRAP_DCX(dcx)	\
362 	(BIT(world->rules->mode, WRAP_PLAY) \
363 	    ? ((dcx) < - (world->cwidth >> 1) \
364 		? (dcx) + world->cwidth \
365 		: ((dcx) > (world->cwidth >> 1) \
366 		    ? (dcx) - world->cwidth \
367 		    : (dcx))) \
368 	    : (dcx))
369 
370 #define WRAP_DCY(dcy)	\
371 	(BIT(world->rules->mode, WRAP_PLAY) \
372 	    ? ((dcy) < - (world->cheight >> 1) \
373 		? (dcy) + world->cheight \
374 		: ((dcy) > (world->cheight >> 1) \
375 		    ? (dcy) - world->cheight \
376 		    : (dcy))) \
377 	    : (dcy))
378 
379 #define TWRAP_XCLICK(x_) \
380      ((x_) > 0 ? (x_) % world->cwidth : \
381       ((x_) % world->cwidth + world->cwidth))
382 
383 #define TWRAP_YCLICK(y_) \
384      ((y_) > 0 ? (y_) % world->cheight : \
385       ((y_) % world->cheight + world->cheight))
386 
387 
388 #define CENTER_XCLICK(X) \
389         (((X) < -(world->cwidth >> 1)) ? \
390              (X) + world->cwidth : \
391              (((X) >= (world->cwidth >> 1)) ? \
392                  (X) - world->cwidth : \
393                  (X)))
394 
395 #define CENTER_YCLICK(X) \
396         (((X) < -(world->cheight >> 1)) ? \
397 	     (X) + world->cheight : \
398 	     (((X) >= (world->cheight >> 1)) ? \
399 	         (X) - world->cheight : \
400 	         (X)))
401 
402 
403 
404 #define Num_asteroidConcs()	Arraylist_get_num_elements(world->asteroidConcs)
405 #define Num_bases()		Arraylist_get_num_elements(world->bases)
406 #define Num_cannons()		Arraylist_get_num_elements(world->cannons)
407 #define Num_ecms()		Arraylist_get_num_elements(world->ecms)
408 #define Num_frictionAreas()	Arraylist_get_num_elements(world->frictionAreas)
409 #define Num_fuels()		Arraylist_get_num_elements(world->fuels)
410 #define Num_gravs()		Arraylist_get_num_elements(world->gravs)
411 #define Num_itemConcs()	Arraylist_get_num_elements(world->itemConcs)
412 #define Num_targets()		Arraylist_get_num_elements(world->targets)
413 #define Num_transporters()	Arraylist_get_num_elements(world->transporters)
414 #define Num_treasures()	Arraylist_get_num_elements(world->treasures)
415 #define Num_wormholes()	Arraylist_get_num_elements(world->wormholes)
416 
417 #define AsteroidConc_by_index(i) \
418 	((asteroid_concentrator_t *)Arraylist_get(world->asteroidConcs, (i)))
419 #define Base_by_index(i)	((base_t *)Arraylist_get(world->bases, (i)))
420 #define Cannon_by_index(i)	((cannon_t *)Arraylist_get(world->cannons, (i)))
421 #define Ecm_by_index(i)	((ecm_t *)Arraylist_get(world->ecms, (i)))
422 #define FrictionArea_by_index(i) \
423 	((friction_area_t *)Arraylist_get(world->frictionAreas, (i)))
424 #define Fuel_by_index(i)	((fuel_t *)Arraylist_get(world->fuels, (i)))
425 #define Grav_by_index(i)	((grav_t *)Arraylist_get(world->gravs, (i)))
426 #define ItemConc_by_index(i) \
427 	((item_concentrator_t *)Arraylist_get(world->itemConcs, (i)))
428 #define Target_by_index(i)	((target_t *)Arraylist_get(world->targets, (i)))
429 #define Treasure_by_index(i)	((treasure_t *)Arraylist_get(world->treasures, (i)))
430 #define Wormhole_by_index(i)	((wormhole_t *)Arraylist_get(world->wormholes, (i)))
431 #define Transporter_by_index(i) \
432 	((transporter_t *)Arraylist_get(world->transporters, (i)))
433 
434 
Check_by_index(int ind)435 static inline check_t *Check_by_index(int ind)
436 {
437     if (ind >= 0 && ind < world->NumChecks)
438 	return &world->checks[ind];
439     return NULL;
440 }
441 
442 /*
443  * Here the index is the team number.
444  */
Team_by_index(int ind)445 static inline team_t *Team_by_index(int ind)
446 {
447     if (ind >= 0 && ind < MAX_TEAMS)
448 	return &world->teams[ind];
449     return NULL;
450 }
451 
452 #endif
453