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