1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
14 /**
15  * @file
16  * Map processing functions.
17  */
18 
19 #include "client.h"
20 
21 #include <assert.h>
22 #include <stdbool.h>
23 
24 #include "external.h"
25 #include "mapdata.h"
26 
27 /**
28  * Position of a player on the map, relative to the coordinates received
29  * after a 'newmap' command. These are kept to for reporting to client scripts.
30  */
31 PlayerPosition script_pos;
32 
33 /**
34  * Size of virtual map.
35  */
36 #define FOG_MAP_SIZE 512
37 
38 /**
39  * After shifting the virtual map: new minimum distance of the view area to the
40  * new virtual map border.
41  */
42 #define FOG_BORDER_MIN 128
43 
44 /**
45  * Maximum size of a big face image in tiles. Larger faces will be clipped top/left.
46  */
47 #define MAX_FACE_SIZE 16
48 
49 /* Max it can currently be.  Important right now because
50  * animation has to look at everything that may be viewable,
51  * and reducing this size basically reduces processing it needs
52  * to do by 75% (64^2 vs 33^2)
53  */
54 #define CURRENT_MAX_VIEW    33
55 
56 /**
57  * The struct BigCell describes a tile *outside* the view area. head contains
58  * the head (as sent by the server), tail contains the expanded big face. tail
59  * is *not* set for the head cell, that is (for example) a big face with size
60  * 2x3 occupies exactly 6 entries: 1 head and 5 tails.
61  *
62  * next and prev for a doubly linked list of all currently active entries.
63  * Unused entries are set to NULL.
64  *
65  * x, y, and layer contain the position of the cell in the bigfaces[] array.
66  * This information allows to find the corresponding bigfaces[] cell when
67  * iterating through the next pointers.
68  */
69 struct BigCell {
70     struct BigCell *next;
71     struct BigCell *prev;
72 
73     struct MapCellLayer head;
74     struct MapCellTailLayer tail;
75 
76     guint16 x, y;
77     guint8 layer;
78 };
79 
80 int global_offset_x = 0;
81 int global_offset_y = 0;
82 int want_offset_x = 0;
83 int want_offset_y = 0;
84 
85 static void recenter_virtual_map_view(int diff_x, int diff_y);
86 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h);
87 
88 
89 static int width;   //< width of current map view
90 static int height;  //< height of current map view
91 
92 
93 /**
94  * Contains the head of a list of all currently active big faces outside the
95  * view area. All entries are part of bigfaces[].
96  */
97 static struct BigCell *bigfaces_head;
98 
99 /**
100  * The variable bigfaces[] contains information about big faces (faces with a
101  * width or height >1). The viewable area bigfaces[0..width-1][0..height-1] is
102  * unused.
103  */
104 static struct BigCell bigfaces[MAX_VIEW][MAX_VIEW][MAXLAYERS];
105 
106 static struct Map the_map;
107 
108 /**
109  * Clear cells the_map.cells[x][y..y+len_y-1].
110  */
clear_cells(int x,int y,int len_y)111 static void clear_cells(int x, int y, int len_y) {
112     int clear_cells_i, j;
113     memset(mapdata_cell(x, y), 0, sizeof(struct MapCell)*len_y);
114 
115     for (clear_cells_i = 0; clear_cells_i < (len_y); clear_cells_i++) {
116         struct MapCell *cell = mapdata_cell(x, y+clear_cells_i);
117         for (j=0; j < MAXLAYERS; j++) {
118             cell->heads[j].size_x = 1;
119             cell->heads[j].size_y = 1;
120         }
121     }
122 }
123 
124 /**
125  * Get the stored map cell at the given map coordinate.
126  */
mapdata_cell(const int x,const int y)127 inline struct MapCell *mapdata_cell(const int x, const int y) {
128     return &the_map._cells[x][y];
129 }
130 
131 /**
132  * Determine whether the map data contains the given cell.
133  */
mapdata_contains(int x,int y)134 bool mapdata_contains(int x, int y) {
135     if (x < 0 || y < 0 || the_map.width <= x || the_map.height <= y) {
136         return false;
137     }
138 
139     return true;
140 }
141 
mapdata_can_smooth(int x,int y,int layer)142 bool mapdata_can_smooth(int x, int y, int layer) {
143     return (mapdata_cell(x, y)->heads[layer].face == 0 && layer > 0) ||
144             mapdata_cell(x, y)->smooth[layer];
145 }
146 
147 /**
148  * Determine the size of the internal fog-of-war map.
149  */
mapdata_size(int * x,int * y)150 void mapdata_size(int *x, int *y) {
151     if (x != NULL) {
152         *x = the_map.width;
153     }
154 
155     if (y != NULL) {
156         *y = the_map.height;
157     }
158 }
159 
160 /**
161  * Update darkness information. This function is called whenever a map1a
162  * command from the server was received.
163  *
164  * x and y are absolute coordinates into the_map.cells[].
165  *
166  * darkness is the new darkness value.
167  */
set_darkness(int x,int y,int darkness)168 static void set_darkness(int x, int y, int darkness)
169 {
170     mapdata_cell(x, y)->have_darkness = 1;
171     if (mapdata_cell(x, y)->darkness == darkness) {
172         return;
173     }
174 
175     mapdata_cell(x, y)->darkness = darkness;
176     mapdata_cell(x, y)->need_update = 1;
177 
178     /* pretty ugly - since the light code with pngximage uses neighboring
179      * spaces to adjust the darkness, we now need to let the neighbors know
180      * they should update their darkness now.
181      */
182     if (use_config[CONFIG_DISPLAYMODE] == CFG_DM_SDL
183             && (use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL
184                 ||  use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL_BEST)) {
185         if (x > 1) {
186             mapdata_cell(x-1, y)->need_update = 1;
187         }
188         if (y > 1) {
189             mapdata_cell(x, y-1)->need_update = 1;
190         }
191         if (x < width-1) {
192             mapdata_cell(x+1, y)->need_update = 1;
193         }
194         if (y < height-1) {
195             mapdata_cell(x, y+1)->need_update = 1;
196         }
197     }
198 }
199 
mark_resmooth(int x,int y,int layer)200 static void mark_resmooth(int x, int y, int layer)
201 {
202     int sdx,sdy;
203     if (mapdata_cell(x, y)->smooth[layer]>1) {
204         for (sdx=-1; sdx<2; sdx++)
205             for (sdy=-1; sdy<2; sdy++)
206                 if ( (sdx || sdy) /* ignore (0,0) */
207                         &&  ( (x+sdx >0) && (x+sdx < the_map.width) &&  /* only inside map */
208                               (y+sdy >0) && (y+sdy < the_map.height) ) ) {
209                     mapdata_cell(x+sdx, y+sdy)->need_resmooth=1;
210                 }
211     }
212 }
213 /**
214  * Clear a face from the_map.cells[].
215  *
216  * x, y, and layer are the coordinates of the head and layer relative to
217  * pl_pos.
218  *
219  * w and h give the width and height of the face to clear.
220  */
expand_clear_face(int x,int y,int w,int h,int layer)221 static void expand_clear_face(int x, int y, int w, int h, int layer)
222 {
223     int dx, dy;
224     struct MapCell *cell;
225 
226     assert(0 <= x && x < the_map.width);
227     assert(0 <= y && y < the_map.height);
228     assert(1 <= w && w <= MAX_FACE_SIZE);
229     assert(1 <= h && h <= MAX_FACE_SIZE);
230 
231     assert(0 <= x-w+1 && x-w+1 < the_map.width);
232     assert(0 <= y-h+1 && y-h+1 < the_map.height);
233 
234     cell = mapdata_cell(x, y);
235 
236     for (dx = 0; dx < w; dx++) {
237         for (dy = !dx; dy < h; dy++) {
238             struct MapCellTailLayer *tail = &mapdata_cell(x-dx, y-dy)->tails[layer];
239             assert(0 <= x-dx && x-dx < the_map.width);
240             assert(0 <= y-dy && y-dy < the_map.height);
241             assert(0 <= layer && layer < MAXLAYERS);
242 
243             /* Do not clear faces that already have been overwritten by another
244              * face.
245              */
246             if (tail->face == cell->heads[layer].face
247                     && tail->size_x == dx
248                     && tail->size_y == dy) {
249                 tail->face = 0;
250                 tail->size_x = 0;
251                 tail->size_y = 0;
252                 mapdata_cell(x-dx, y-dy)->need_update = 1;
253             }
254             mark_resmooth(x-dx,y-dy,layer);
255         }
256     }
257 
258     cell->heads[layer].face = 0;
259     cell->heads[layer].animation = 0;
260     cell->heads[layer].animation_speed = 0;
261     cell->heads[layer].animation_left = 0;
262     cell->heads[layer].animation_phase = 0;
263     cell->heads[layer].size_x = 1;
264     cell->heads[layer].size_y = 1;
265     cell->need_update = 1;
266     cell->need_resmooth = 1;
267     mark_resmooth(x,y,layer);
268 }
269 
270 /**
271  * Clear a face from the_map.cells[].
272  *
273  * x, y, and layer are the coordinates of the head and layer relative to
274  * pl_pos.
275  */
expand_clear_face_from_layer(int x,int y,int layer)276 static void expand_clear_face_from_layer(int x, int y, int layer)
277 {
278     const struct MapCellLayer *cell;
279 
280     assert(0 <= x && x < the_map.width);
281     assert(0 <= y && y < the_map.height);
282     assert(0 <= layer && layer < MAXLAYERS);
283 
284     cell = &mapdata_cell(x, y)->heads[layer];
285     if (cell->size_x && cell->size_y) {
286         expand_clear_face(x, y, cell->size_x, cell->size_y, layer);
287     }
288 }
289 
290 /**
291  * Update a face into the_map.cells[].
292  *
293  * x, y, and layer are the coordinates and layer of the head relative to
294  * pl_pos.
295  *
296  * face is the new face to set.
297  * if clear is set, clear this face.  If not set, don't clear.  the reason
298  * clear may not be set is because this is an animation update - animations
299  * must all be the same size, so when we set the data for the space,
300  * we will just overwrite the old data.  Problem with clearing is that
301  * clobbers the animation data.
302  */
expand_set_face(int x,int y,int layer,gint16 face,int clear)303 static void expand_set_face(int x, int y, int layer, gint16 face, int clear)
304 {
305     struct MapCell *cell;
306     int dx, dy;
307     guint8 w, h;
308 
309     assert(0 <= x && x < the_map.width);
310     assert(0 <= y && y < the_map.height);
311     assert(0 <= layer && layer < MAXLAYERS);
312 
313     cell = mapdata_cell(x, y);
314 
315     if (clear) {
316         expand_clear_face_from_layer(x, y, layer);
317     }
318 
319     mapdata_get_image_size(face, &w, &h);
320     assert(1 <= w && w <= MAX_FACE_SIZE);
321     assert(1 <= h && h <= MAX_FACE_SIZE);
322     cell->heads[layer].face = face;
323     cell->heads[layer].size_x = w;
324     cell->heads[layer].size_y = h;
325     cell->need_update=1;
326     mark_resmooth(x,y,layer);
327 
328     for (dx = 0; dx < w; dx++) {
329         for (dy = !dx; dy < h; dy++) {
330             struct MapCellTailLayer *tail = &mapdata_cell(x-dx, y-dy)->tails[layer];
331             assert(0 <= x-dx && x-dx < the_map.width);
332             assert(0 <= y-dy && y-dy < the_map.height);
333             assert(0 <= layer && layer < MAXLAYERS);
334 
335             tail->face = face;
336             tail->size_x = dx;
337             tail->size_y = dy;
338             mapdata_cell(x-dx, y-dy)->need_update = 1;
339             mark_resmooth(x-dx,y-dy,layer);
340         }
341     }
342 }
343 
344 /**
345  * Clear a face from bigfaces[].
346  *
347  * x, y, and layer are the coordinates and layer of the head relative to
348  * pl_pos.
349  *
350  * w and h give the width and height of the face to clear.
351  *
352  * If set_need_update is set, all affected tiles are marked as "need_update".
353  */
expand_clear_bigface(int x,int y,int w,int h,int layer,int set_need_update)354 static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update)
355 {
356     int dx, dy;
357     struct MapCellLayer *head;
358 
359     assert(0 <= x && x < MAX_VIEW);
360     assert(0 <= y && y < MAX_VIEW);
361     assert(1 <= w && w <= MAX_FACE_SIZE);
362     assert(1 <= h && h <= MAX_FACE_SIZE);
363 
364     head = &bigfaces[x][y][layer].head;
365 
366     for (dx = 0; dx < w && dx <= x; dx++) {
367         for (dy = !dx; dy < h && dy <= y; dy++) {
368             struct MapCellTailLayer *tail = &bigfaces[x-dx][y-dy][layer].tail;
369             assert(0 <= x-dx && x-dx < MAX_VIEW);
370             assert(0 <= y-dy && y-dy < MAX_VIEW);
371             assert(0 <= layer && layer < MAXLAYERS);
372 
373             /* Do not clear faces that already have been overwritten by another
374              * face.
375              */
376             if (tail->face == head->face
377                     && tail->size_x == dx
378                     && tail->size_y == dy) {
379                 tail->face = 0;
380                 tail->size_x = 0;
381                 tail->size_y = 0;
382 
383                 if (0 <= x-dx && x-dx < width
384                         && 0 <= y-dy && y-dy < height) {
385                     assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < the_map.width);
386                     assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < the_map.height);
387                     if (set_need_update) {
388                         mapdata_cell(pl_pos.x+x-dx, pl_pos.y+y-dy)->need_update = 1;
389                     }
390                 }
391             }
392         }
393     }
394 
395     head->face = 0;
396     head->size_x = 1;
397     head->size_y = 1;
398 }
399 
400 /**
401  * Clear a face from bigfaces[].
402  *
403  * x, y, and layer are the coordinates and layer of the head relative to
404  * pl_pos.
405  *
406  * If set_need_update is set, all affected tiles are marked as "need_update".
407  */
expand_clear_bigface_from_layer(int x,int y,int layer,int set_need_update)408 static void expand_clear_bigface_from_layer(int x, int y, int layer, int set_need_update)
409 {
410     struct BigCell *headcell;
411     const struct MapCellLayer *head;
412 
413     assert(0 <= x && x < MAX_VIEW);
414     assert(0 <= y && y < MAX_VIEW);
415     assert(0 <= layer && layer < MAXLAYERS);
416 
417     headcell = &bigfaces[x][y][layer];
418     head = &headcell->head;
419     if (head->face != 0) {
420         assert(headcell->prev != NULL || headcell == bigfaces_head);
421 
422         /* remove from bigfaces_head list */
423         if (headcell->prev != NULL) {
424             headcell->prev->next = headcell->next;
425         }
426         if (headcell->next != NULL) {
427             headcell->next->prev = headcell->prev;
428         }
429         if (bigfaces_head == headcell) {
430             assert(headcell->prev == NULL);
431             bigfaces_head = headcell->next;
432         } else {
433             assert(headcell->prev != NULL);
434         }
435         headcell->prev = NULL;
436         headcell->next = NULL;
437 
438         expand_clear_bigface(x, y, head->size_x, head->size_y, layer, set_need_update);
439     } else {
440         assert(headcell->prev == NULL && headcell != bigfaces_head);
441         assert(head->size_x == 1);
442         assert(head->size_y == 1);
443     }
444 }
445 
446 /**
447  * Update a face into bigfaces[].
448  *
449  * x, y, and layer are the coordinates and layer of the head relative to
450  * pl_pos.
451  *
452  * face is the new face to set.
453  */
expand_set_bigface(int x,int y,int layer,gint16 face,int clear)454 static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear)
455 {
456     struct BigCell *headcell;
457     struct MapCellLayer *head;
458     int dx, dy;
459     guint8 w, h;
460 
461     assert(0 <= x && x < MAX_VIEW);
462     assert(0 <= y && y < MAX_VIEW);
463     assert(0 <= layer && layer < MAXLAYERS);
464 
465     headcell = &bigfaces[x][y][layer];
466     head = &headcell->head;
467     if (clear) {
468         expand_clear_bigface_from_layer(x, y, layer, 1);
469     }
470 
471     /* add to bigfaces_head list */
472     if (face != 0) {
473         assert(headcell->prev == NULL);
474         assert(headcell->next == NULL);
475         assert(headcell != bigfaces_head);
476         if (bigfaces_head != NULL) {
477             assert(bigfaces_head->prev == NULL);
478             bigfaces_head->prev = headcell;
479         }
480         headcell->next = bigfaces_head;
481         bigfaces_head = headcell;
482     }
483 
484     mapdata_get_image_size(face, &w, &h);
485     assert(1 <= w && w <= MAX_FACE_SIZE);
486     assert(1 <= h && h <= MAX_FACE_SIZE);
487     head->face = face;
488     head->size_x = w;
489     head->size_y = h;
490 
491     for (dx = 0; dx < w && dx <= x; dx++) {
492         for (dy = !dx; dy < h && dy <= y; dy++) {
493             struct MapCellTailLayer *tail = &bigfaces[x-dx][y-dy][layer].tail;
494             assert(0 <= x-dx && x-dx < MAX_VIEW);
495             assert(0 <= y-dy && y-dy < MAX_VIEW);
496             assert(0 <= layer && layer < MAXLAYERS);
497 
498             tail->face = face;
499             tail->size_x = dx;
500             tail->size_y = dy;
501 
502             if (0 <= x-dx && x-dx < width
503                     && 0 <= y-dy && y-dy < height) {
504                 assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < the_map.width);
505                 assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < the_map.height);
506                 mapdata_cell(pl_pos.x+x-dx, pl_pos.y+y-dy)->need_update = 1;
507             }
508         }
509     }
510 }
511 
512 /**
513  * Mark a face as "need_update".
514  *
515  * x and y are the coordinates of the head relative to pl_pos.
516  *
517  * w and h is the size of the face.
518  */
expand_need_update(int x,int y,int w,int h)519 static void expand_need_update(int x, int y, int w, int h)
520 {
521     int dx, dy;
522 
523     assert(0 <= x && x < the_map.width);
524     assert(0 <= y && y < the_map.height);
525     assert(1 <= w && w <= MAX_FACE_SIZE);
526     assert(1 <= h && h <= MAX_FACE_SIZE);
527 
528     assert(0 <= x-w+1 && x-w+1 < the_map.width);
529     assert(0 <= y-h+1 && y-h+1 < the_map.height);
530 
531     for (dx = 0; dx < w; dx++) {
532         for (dy = 0; dy < h; dy++) {
533             struct MapCell *cell = mapdata_cell(x-dx, y-dy);
534             assert(0 <= x-dx && x-dx < the_map.width);
535             assert(0 <= y-dy && y-dy < the_map.height);
536             cell->need_update = 1;
537         }
538     }
539 }
540 
541 /**
542  * Mark a face as "need_update".
543  *
544  * x, y, and layer are the coordinates and layer of the head relative to
545  * pl_pos.
546  */
expand_need_update_from_layer(int x,int y,int layer)547 static void expand_need_update_from_layer(int x, int y, int layer)
548 {
549     struct MapCellLayer *head;
550 
551     assert(0 <= x && x < the_map.width);
552     assert(0 <= y && y < the_map.height);
553     assert(0 <= layer && layer < MAXLAYERS);
554 
555     head = &mapdata_cell(x, y)->heads[layer];
556     if (head->face != 0) {
557         expand_need_update(x, y, head->size_x, head->size_y);
558     } else {
559         assert(head->size_x == 1);
560         assert(head->size_y == 1);
561     }
562 }
563 
564 /**
565  * Allocate and set up pointers for a map, with cells represented as a C-style
566  * multi-dimensional array.
567  */
mapdata_alloc(struct Map * const map,const int width,const int height)568 static void mapdata_alloc(struct Map* const map, const int width, const int height) {
569     map->_cells = (struct MapCell **)g_new(struct MapCell, width * (height + 1));
570     g_assert(map->_cells != NULL); // g_new() always succeeds
571     map->width = width;
572     map->height = height;
573 
574     /* Skip past the first row of pointers to rows and assign the
575      * start of the actual map data
576      */
577     map->_cells[0] = (struct MapCell *)((char *)map->_cells+(sizeof(struct MapCell *)*map->width));
578 
579     /* Finish assigning the beginning of each row relative to the
580      * first row assigned above
581      */
582     for (int i = 0; i < map->width; i++) {
583         map->_cells[i] = map->_cells[0]+i*map->height;
584     }
585 }
586 
mapdata_init(void)587 static void mapdata_init(void)
588 {
589     int x, y;
590     int i;
591 
592     mapdata_alloc(&the_map, FOG_MAP_SIZE, FOG_MAP_SIZE);
593 
594     width = 0;
595     height = 0;
596     pl_pos.x = the_map.width/2-width/2;
597     pl_pos.y = the_map.height/2-height/2;
598 
599     for (x = 0; x < the_map.width; x++) {
600         clear_cells(x, 0, the_map.height);
601     }
602 
603     for (y = 0; y < MAX_VIEW; y++) {
604         for (x = 0; x < MAX_VIEW; x++) {
605             for (i = 0; i < MAXLAYERS; i++) {
606                 bigfaces[x][y][i].next = NULL;
607                 bigfaces[x][y][i].prev = NULL;
608                 bigfaces[x][y][i].head.face = 0;
609                 bigfaces[x][y][i].head.size_x = 1;
610                 bigfaces[x][y][i].head.size_y = 1;
611                 bigfaces[x][y][i].tail.face = 0;
612                 bigfaces[x][y][i].tail.size_x = 0;
613                 bigfaces[x][y][i].tail.size_y = 0;
614                 bigfaces[x][y][i].x = x;
615                 bigfaces[x][y][i].y = y;
616                 bigfaces[x][y][i].layer = i;
617             }
618         }
619     }
620     bigfaces_head = NULL;
621 
622     global_offset_x = 0;
623     global_offset_y = 0;
624     want_offset_x = 0;
625     want_offset_y = 0;
626 }
627 
mapdata_free(void)628 void mapdata_free(void) {
629     if (the_map._cells != NULL) {
630         g_free(the_map._cells);
631         the_map._cells = NULL;
632     }
633 }
634 
mapdata_set_size(int viewx,int viewy)635 void mapdata_set_size(int viewx, int viewy)
636 {
637     mapdata_free();
638     mapdata_init();
639 
640     width = viewx;
641     height = viewy;
642     pl_pos.x = the_map.width/2-width/2;
643     pl_pos.y = the_map.height/2-height/2;
644 }
645 
mapdata_is_inside(int x,int y)646 int mapdata_is_inside(int x, int y)
647 {
648     return(x >= 0 && x < width && y >= 0 && y < height);
649 }
650 
651 /* mapdate_clear_space() is used by Map2Cmd()
652  * Basically, server has told us there is nothing on
653  * this space.  So clear it.
654  */
mapdata_clear_space(int x,int y)655 void mapdata_clear_space(int x, int y)
656 {
657     int px, py;
658     int i;
659 
660     assert(0 <= x && x < MAX_VIEW);
661     assert(0 <= y && y < MAX_VIEW);
662 
663     px = pl_pos.x+x;
664     py = pl_pos.y+y;
665     assert(0 <= px && px < the_map.width);
666     assert(0 <= py && py < the_map.height);
667 
668     if (x < width && y < height) {
669         /* tile is visible */
670 
671         /* visible tile is now blank ==> do not clear but mark as cleared */
672         if (!mapdata_cell(px, py)->cleared) {
673             mapdata_cell(px, py)->cleared = 1;
674             mapdata_cell(px, py)->need_update = 1;
675 
676             for (i=0; i < MAXLAYERS; i++)
677                 if (mapdata_cell(px, py)->heads[i].face) {
678                     expand_need_update_from_layer(px, py, i);
679                 }
680         }
681     } else {
682         /* tile is invisible (outside view area, i.e. big face update) */
683 
684         for (i = 0; i < MAXLAYERS; i++) {
685             expand_set_bigface(x, y, i, 0, TRUE);
686         }
687     }
688 }
689 
690 
691 /* With map2, we basically process a piece of data at a time.  Thus,
692  * for each piece, we don't know what the final state of the space
693  * will be.  So once Map2Cmd() has processed all the information for
694  * a space, it calls mapdata_set_check_space() which can see if
695  * the space is cleared or other inconsistencies.
696  */
mapdata_set_check_space(int x,int y)697 void mapdata_set_check_space(int x, int y)
698 {
699     int px, py;
700     int is_blank;
701     int i;
702     struct MapCell *cell;
703 
704     assert(0 <= x && x < MAX_VIEW);
705     assert(0 <= y && y < MAX_VIEW);
706 
707     px = pl_pos.x+x;
708     py = pl_pos.y+y;
709 
710     assert(0 <= px && px < the_map.width);
711     assert(0 <= py && py < the_map.height);
712 
713 
714     is_blank=1;
715     cell = mapdata_cell(px, py);
716     for (i=0; i < MAXLAYERS; i++) {
717         if (cell->heads[i].face>0 || cell->tails[i].face>0) {
718             is_blank=0;
719             break;
720         }
721     }
722 
723     if (cell->have_darkness) {
724         is_blank=0;
725     }
726 
727     /* We only care if this space needs to be blanked out */
728     if (!is_blank) {
729         return;
730     }
731 
732     if (x < width && y < height) {
733         /* tile is visible */
734 
735         /* visible tile is now blank ==> do not clear but mark as cleared */
736         if (!mapdata_cell(px, py)->cleared) {
737             mapdata_cell(px, py)->cleared = 1;
738             mapdata_cell(px, py)->need_update = 1;
739 
740             for (i=0; i < MAXLAYERS; i++) {
741                 expand_need_update_from_layer(px, py, i);
742             }
743         }
744     }
745 }
746 
747 
748 
749 /* This just sets the darkness for a space.
750  * Used by Map2Cmd()
751  */
mapdata_set_darkness(int x,int y,int darkness)752 void mapdata_set_darkness(int x, int y, int darkness)
753 {
754     int px, py;
755 
756     assert(0 <= x && x < MAX_VIEW);
757     assert(0 <= y && y < MAX_VIEW);
758 
759     px = pl_pos.x+x;
760     py = pl_pos.y+y;
761     assert(0 <= px && px < the_map.width);
762     assert(0 <= py && py < the_map.height);
763 
764     /* Ignore darkness information for tile outside the viewable area: if
765      * such a tile becomes visible again, it is either "fog of war" (and
766      * darkness information is ignored) or it will be updated (including
767      * the darkness information).
768      */
769     if (darkness != -1 && x < width && y < height) {
770         set_darkness(px, py, 255-darkness);
771     }
772 }
773 
774 /* Sets smooth information for layer */
mapdata_set_smooth(int x,int y,guint8 smooth,int layer)775 void mapdata_set_smooth(int x, int y, guint8 smooth, int layer)
776 {
777     static int dx[8]= {0,1,1,1,0,-1,-1,-1};
778     static int dy[8]= {-1,-1,0,1,1,1,0,-1};
779     int rx, ry, px, py, i;
780 
781     assert(0 <= x && x < MAX_VIEW);
782     assert(0 <= y && y < MAX_VIEW);
783 
784     px = pl_pos.x+x;
785     py = pl_pos.y+y;
786     assert(0 <= px && px < the_map.width);
787     assert(0 <= py && py < the_map.height);
788 
789     if (mapdata_cell(px, py)->smooth[layer] != smooth) {
790         for (i=0; i<8; i++) {
791             rx=px+dx[i];
792             ry=py+dy[i];
793             if ( (rx<0) || (ry<0) || (the_map.width<=rx) || (the_map.height<=ry)) {
794                 continue;
795             }
796             mapdata_cell(rx, ry)->need_resmooth=1;
797         }
798         mapdata_cell(px, py)->need_resmooth=1;
799         mapdata_cell(px, py)->smooth[layer] = smooth;
800     }
801 }
802 
803 /* If old cell data is set and is to be cleared, clear it.
804  * This used to be in mapdata_set_face_layer(), however it needs to be
805  * called here, earlier in the Map2Cmd() because otherwise darkness
806  * doesn't work went sent before the layer data when that square was
807  * going to be cleared. This is used by the Map2Cmd()
808  */
mapdata_clear_old(int x,int y)809 void mapdata_clear_old(int x, int y)
810 {
811     int px, py;
812     int i;
813 
814     assert(0 <= x && x < MAX_VIEW);
815     assert(0 <= y && y < MAX_VIEW);
816 
817     px = pl_pos.x+x;
818     py = pl_pos.y+y;
819     assert(0 <= px && px < the_map.width);
820     assert(0 <= py && py < the_map.height);
821 
822     if (x < width && y < height)
823         if (mapdata_cell(px, py)->cleared) {
824             for (i=0; i < MAXLAYERS; i++) {
825                 expand_clear_face_from_layer(px, py, i);
826             }
827 
828             mapdata_cell(px, py)->darkness = 0;
829             mapdata_cell(px, py)->have_darkness = 0;
830         }
831 }
832 
833 /* This is vaguely related to the mapdata_set_face() above, but rather
834  * than take all the faces, takes 1 face and the layer this face is
835  * on.  This is used by the Map2Cmd()
836  */
mapdata_set_face_layer(int x,int y,gint16 face,int layer)837 void mapdata_set_face_layer(int x, int y, gint16 face, int layer)
838 {
839     int px, py;
840 
841     assert(0 <= x && x < MAX_VIEW);
842     assert(0 <= y && y < MAX_VIEW);
843 
844     px = pl_pos.x+x;
845     py = pl_pos.y+y;
846     assert(0 <= px && px < the_map.width);
847     assert(0 <= py && py < the_map.height);
848 
849     if (x < width && y < height) {
850         mapdata_cell(px, py)->need_update = 1;
851         if (face >0) {
852             expand_set_face(px, py, layer, face, TRUE);
853         } else {
854             expand_clear_face_from_layer(px, py, layer);
855         }
856 
857         mapdata_cell(px, py)->cleared = 0;
858     } else {
859         expand_set_bigface(x, y, layer, face, TRUE);
860     }
861 }
862 
863 
864 /* This is vaguely related to the mapdata_set_face() above, but rather
865  * than take all the faces, takes 1 face and the layer this face is
866  * on.  This is used by the Map2Cmd()
867  */
mapdata_set_anim_layer(int x,int y,guint16 anim,guint8 anim_speed,int layer)868 void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer)
869 {
870     int px, py;
871     int i, face, animation, phase, speed_left;
872 
873     assert(0 <= x && x < MAX_VIEW);
874     assert(0 <= y && y < MAX_VIEW);
875 
876     px = pl_pos.x+x;
877     py = pl_pos.y+y;
878     assert(0 <= px && px < the_map.width);
879     assert(0 <= py && py < the_map.height);
880 
881     animation = anim & ANIM_MASK;
882     face = 0;
883 
884     /* Random animation is pretty easy */
885     if ((anim & ANIM_FLAGS_MASK) == ANIM_RANDOM) {
886         const guint8 num_animations = animations[animation].num_animations;
887         if (num_animations == 0) {
888             LOG(LOG_WARNING, "mapdata_set_anim_layer",
889                 "animating object with zero animations");
890             return;
891         }
892         phase = g_random_int() % num_animations;
893         face = animations[animation].faces[phase];
894         speed_left = anim_speed % g_random_int();
895     } else if ((anim & ANIM_FLAGS_MASK) == ANIM_SYNC) {
896         animations[animation].speed = anim_speed;
897         phase = animations[animation].phase;
898         speed_left = animations[animation].speed_left;
899         face = animations[animation].faces[phase];
900     }
901 
902     if (x < width && y < height) {
903         mapdata_cell(px, py)->need_update = 1;
904         if (mapdata_cell(px, py)->cleared) {
905             for (i=0; i < MAXLAYERS; i++) {
906                 expand_clear_face_from_layer(px, py, i);
907             }
908 
909             mapdata_cell(px, py)->darkness = 0;
910             mapdata_cell(px, py)->have_darkness = 0;
911         }
912         if (face >0) {
913             expand_set_face(px, py, layer, face, TRUE);
914             mapdata_cell(px, py)->heads[layer].animation = animation;
915             mapdata_cell(px, py)->heads[layer].animation_phase = phase;
916             mapdata_cell(px, py)->heads[layer].animation_speed = anim_speed;
917             mapdata_cell(px, py)->heads[layer].animation_left = speed_left;
918         } else {
919             expand_clear_face_from_layer(px, py, layer);
920         }
921 
922         mapdata_cell(px, py)->cleared = 0;
923 
924     } else {
925         expand_set_bigface(x, y, layer, face, TRUE);
926     }
927 }
928 
929 
mapdata_scroll(int dx,int dy)930 void mapdata_scroll(int dx, int dy)
931 {
932     script_pos.x += dx;
933     script_pos.y += dy;
934     int x, y;
935 
936     recenter_virtual_map_view(dx, dy);
937 
938     if (want_config[CONFIG_MAPSCROLL] && display_mapscroll(dx, dy)) {
939         struct BigCell *cell;
940 
941         /* Mark all tiles as "need_update" that are overlapped by a big face
942          * from outside the view area.
943          */
944         for (cell = bigfaces_head; cell != NULL; cell = cell->next) {
945             for (x = 0; x < cell->head.size_x; x++) {
946                 for (y = !x; y < cell->head.size_y; y++) {
947                     if (0 <= cell->x-x && cell->x-x < width
948                             && 0 <= cell->y-y && cell->y-y < height) {
949                         mapdata_cell(pl_pos.x+cell->x-x, pl_pos.y+cell->y-y)->need_update = 1;
950                     }
951                 }
952             }
953         }
954     } else {
955         /* Emulate map scrolling by redrawing all tiles. */
956         for (x = 0; x < width; x++) {
957             for (y = 0; y < height; y++) {
958                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->need_update = 1;
959             }
960         }
961     }
962 
963     pl_pos.x += dx;
964     pl_pos.y += dy;
965 
966     /* clear all newly visible tiles */
967     if (dx > 0) {
968         for (y = 0; y < height; y++) {
969             for (x = width-dx; x < width; x++) {
970                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->cleared = 1;
971                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->need_update = 1;
972             }
973         }
974     } else {
975         for (y = 0; y < height; y++) {
976             for (x = 0; x < -dx; x++) {
977                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->cleared = 1;
978                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->need_update = 1;
979             }
980         }
981     }
982 
983     if (dy > 0) {
984         for (x = 0; x < width; x++) {
985             for (y = height-dy; y < height; y++) {
986                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->cleared = 1;
987                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->need_update = 1;
988             }
989         }
990     } else {
991         for (x = 0; x < width; x++) {
992             for (y = 0; y < -dy; y++) {
993                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->cleared = 1;
994                 mapdata_cell(pl_pos.x+x, pl_pos.y+y)->need_update = 1;
995             }
996         }
997     }
998 
999     /* Remove all big faces outside the view area. */
1000     while (bigfaces_head != NULL) {
1001         expand_clear_bigface_from_layer(bigfaces_head->x, bigfaces_head->y, bigfaces_head->layer, 0);
1002     }
1003 }
1004 
mapdata_newmap(void)1005 void mapdata_newmap(void)
1006 {
1007     script_pos.x = 0;
1008     script_pos.y = 0;
1009     int x, y;
1010 
1011     global_offset_x = 0;
1012     global_offset_y = 0;
1013     want_offset_x = 0;
1014     want_offset_y = 0;
1015 
1016     // Clear past predictions.
1017     memset(csocket.dir, -1, sizeof(csocket.dir));
1018 
1019     /* Clear the_map.cells[]. */
1020     for (x = 0; x < the_map.width; x++) {
1021         clear_cells(x, 0, the_map.height);
1022         for (y = 0; y < the_map.height; y++) {
1023             mapdata_cell(x, y)->need_update = 1;
1024         }
1025     }
1026 
1027     /* Clear bigfaces[]. */
1028     while (bigfaces_head != NULL) {
1029         expand_clear_bigface_from_layer(bigfaces_head->x, bigfaces_head->y, bigfaces_head->layer, 0);
1030     }
1031 }
1032 
1033 /**
1034  * Check if the given map tile is a valid slot in the map array.
1035  */
mapdata_has_tile(int x,int y,int layer)1036 static bool mapdata_has_tile(int x, int y, int layer) {
1037     if (0 <= x && x < width && 0 <= y && y < height) {
1038         if (0 <= layer && layer < MAXLAYERS) {
1039             return true;
1040         }
1041     }
1042 
1043     return false;
1044 }
1045 
1046 /**
1047  * Return the face number of a single-square pixmap at the given map tile.
1048  * @param x X-coordinate of tile on-screen
1049  * @param y Y-coordinate of tile on-screen
1050  * @param layer
1051  * @return Pixmap face number, or zero if the tile does not exist
1052  */
mapdata_face(int x,int y,int layer)1053 gint16 mapdata_face(int x, int y, int layer) {
1054     if (!mapdata_has_tile(x, y, layer)) {
1055         return 0;
1056     }
1057 
1058     return mapdata_cell(pl_pos.x+x, pl_pos.y+y)->heads[layer].face;
1059 }
1060 
mapdata_face_info(int mx,int my,int layer,int * dx,int * dy)1061 gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy) {
1062     struct MapCellLayer *head = &mapdata_cell(mx, my)->heads[layer];
1063     struct MapCellTailLayer *tail = &mapdata_cell(mx, my)->tails[layer];
1064     if (head->face != 0) {
1065         const int width = head->size_x, height = head->size_y;
1066         *dx = 1 - width, *dy = 1 - height;
1067         return head->face;
1068     } else if (tail->face != 0) {
1069         struct MapCellLayer *head_ptr = &mapdata_cell(mx + tail->size_x, my + tail->size_y)->heads[layer];
1070         const int width = head_ptr->size_x, height = head_ptr->size_y;
1071         *dx = tail->size_x - width + 1, *dy = tail->size_y - height + 1;
1072         return tail->face;
1073     } else {
1074         return 0;
1075     }
1076 }
1077 
1078 /**
1079  * Return the face number of a multi-square pixmap at the given map tile.
1080  * @param x X-coordinate of tile on-screen
1081  * @param y Y-coordinate of tile on-screen
1082  * @param layer
1083  * @param ww
1084  * @param hh
1085  * @return Pixmap face number, or zero if the tile does not exist
1086  */
mapdata_bigface(int x,int y,int layer,int * ww,int * hh)1087 gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh) {
1088     gint16 result;
1089 
1090     if (!mapdata_has_tile(x, y, layer)) {
1091         return 0;
1092     }
1093 
1094     result = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face;
1095     if (result != 0) {
1096         int clear_bigface;
1097         int dx = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].size_x;
1098         int dy = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].size_y;
1099         int w = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->heads[layer].size_x;
1100         int h = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->heads[layer].size_y;
1101         assert(1 <= w && w <= MAX_FACE_SIZE);
1102         assert(1 <= h && h <= MAX_FACE_SIZE);
1103         assert(0 <= dx && dx < w);
1104         assert(0 <= dy && dy < h);
1105 
1106         /* Now check if we are about to display an obsolete big face: such a
1107          * face has a cleared ("fog of war") head but the current tile is not
1108          * fog of war. Since the server would have sent an appropriate head
1109          * tile if it was already valid, just clear the big face and do not
1110          * return it.
1111          */
1112         if (mapdata_cell(pl_pos.x+x, pl_pos.y+y)->cleared) {
1113             /* Current face is a "fog of war" tile ==> do not clear
1114              * old information.
1115              */
1116             clear_bigface = 0;
1117         } else {
1118             if (x+dx < width && y+dy < height) {
1119                 /* Clear face if current tile is valid but the
1120                  * head is marked as cleared.
1121                  */
1122                 clear_bigface = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->cleared;
1123             } else {
1124                 /* Clear face if current tile is valid but the
1125                  * head is not set.
1126                  */
1127                 clear_bigface = bigfaces[x+dx][y+dy][layer].head.face == 0;
1128             }
1129         }
1130 
1131         if (!clear_bigface) {
1132             *ww = w-1-dx;
1133             *hh = h-1-dy;
1134             return(result);
1135         }
1136 
1137         assert(mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face == result);
1138         expand_clear_face_from_layer(pl_pos.x+x+dx, pl_pos.y+y+dy, layer);
1139         assert(mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face == 0);
1140     }
1141 
1142     result = bigfaces[x][y][layer].tail.face;
1143     if (result != 0) {
1144         int dx = bigfaces[x][y][layer].tail.size_x;
1145         int dy = bigfaces[x][y][layer].tail.size_y;
1146         int w = bigfaces[x+dx][y+dy][layer].head.size_x;
1147         int h = bigfaces[x+dx][y+dy][layer].head.size_y;
1148         assert(0 <= dx && dx < w);
1149         assert(0 <= dy && dy < h);
1150         *ww = w-1-dx;
1151         *hh = h-1-dy;
1152         return(result);
1153     }
1154 
1155     *ww = 1;
1156     *hh = 1;
1157     return(0);
1158 }
1159 
1160 /* This is used by the opengl logic.
1161  * Basically the opengl code draws the the entire image,
1162  * and doesn't care if if portions are off the edge
1163  * (opengl takes care of that).  So basically, this
1164  * function returns only if the head for a space is set,
1165  * otherwise, returns 0 - we don't care about the tails
1166  * or other details really.
1167  */
mapdata_bigface_head(int x,int y,int layer,int * ww,int * hh)1168 gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh) {
1169     gint16 result;
1170 
1171     if (!mapdata_has_tile(x, y, layer)) {
1172         return 0;
1173     }
1174 
1175     result = bigfaces[x][y][layer].head.face;
1176     if (result != 0) {
1177         int w = bigfaces[x][y][layer].head.size_x;
1178         int h = bigfaces[x][y][layer].head.size_y;
1179         *ww = w;
1180         *hh = h;
1181         return(result);
1182     }
1183 
1184     *ww = 1;
1185     *hh = 1;
1186     return(0);
1187 }
1188 
1189 /**
1190  * Check if current map position is out of bounds if shifted by (dx, dy). If
1191  * so, shift the virtual map so that the map view is within bounds again.
1192  *
1193  * Assures that [pl_pos.x-MAX_FACE_SIZE..pl_pos.x+MAX_VIEW+1] is within the
1194  * bounds of the virtual map area. This covers the area a map1a command may
1195  * affect plus a one tile border.
1196  */
recenter_virtual_map_view(int diff_x,int diff_y)1197 static void recenter_virtual_map_view(int diff_x, int diff_y)
1198 {
1199     int new_x, new_y;
1200     int shift_x, shift_y;
1201     int src_x, src_y;
1202     int dst_x, dst_y;
1203     int len_x, len_y;
1204     int sx;
1205     int dx;
1206     int i;
1207 
1208     /* shift player position in virtual map */
1209     new_x = pl_pos.x+diff_x;
1210     new_y = pl_pos.y+diff_y;
1211 
1212     /* determine neccessary amount to shift */
1213 
1214     /* if(new_x < 1) is not possible: a big face may reach up to
1215      * (MAX_FACE_SIZE-1) tiles to the left of pl_pos. Therefore maintain a
1216      * border of at least MAX_FACE_SIZE to the left of the virtual map
1217      * edge.
1218      */
1219     if (new_x < MAX_FACE_SIZE) {
1220         shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1221         /* This yields: new_x+shift_x == FOG_BORDER_MIN+MAX_FACE_SIZE,
1222          * i.e. left border is FOG_BORDER_MIN+MAX_FACE_SIZE after
1223          * shifting.
1224          */
1225     } else if (new_x+MAX_VIEW > the_map.width) {
1226         shift_x = the_map.width-FOG_BORDER_MIN-MAX_VIEW-new_x;
1227         /* This yields: new_x+shift_x ==
1228          * the_map.width-FOG_BODER_MIN-MAX_VIEW, i.e. right border is
1229          * FOGBORDER_MIN after shifting.
1230          */
1231     } else {
1232         shift_x = 0;
1233     }
1234 
1235     /* Same as above but for y. */
1236     if (new_y < MAX_FACE_SIZE) {
1237         shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1238     } else if (new_y+MAX_VIEW > the_map.height) {
1239         shift_y = the_map.height-FOG_BORDER_MIN-MAX_VIEW-new_y;
1240     } else {
1241         shift_y = 0;
1242     }
1243 
1244     /* No shift neccessary? ==> nothing to do. */
1245     if (shift_x == 0 && shift_y == 0) {
1246         return;
1247     }
1248 
1249     /* If shifting at all: maintain a border size of FOG_BORDER_MIN to all
1250      * directions. For example: if pl_pos=30/MAX_FACE_SIZE, and map_scroll is
1251      * 0/-1: shift pl_pos to FOG_BORDER_MIN+1/FOG_BORDER_MIN+1, not to
1252      * 30/FOG_BORDER_MIN+1.
1253      */
1254     if (shift_x == 0) {
1255         if (new_x < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1256             shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1257         } else if (new_x+MAX_VIEW+FOG_BORDER_MIN > the_map.width) {
1258             shift_x = the_map.width-FOG_BORDER_MIN-MAX_VIEW-new_x;
1259         }
1260     }
1261     if (shift_y == 0) {
1262         if (new_y < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1263             shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1264         } else if (new_y+MAX_VIEW+FOG_BORDER_MIN > the_map.height) {
1265             shift_y = the_map.height-FOG_BORDER_MIN-MAX_VIEW-new_y;
1266         }
1267     }
1268 
1269     /* Shift for more than virtual map size? ==> clear whole virtual map
1270      * and recenter.
1271      */
1272     if (shift_x <= -the_map.width || shift_x >= the_map.width
1273             || shift_y <= -the_map.height || shift_y >= the_map.height) {
1274         for (dx = 0; dx < the_map.width; dx++) {
1275             clear_cells(dx, 0, the_map.height);
1276         }
1277 
1278         pl_pos.x = the_map.width/2-width/2;
1279         pl_pos.y = the_map.height/2-height/2;
1280         return;
1281     }
1282 
1283     /* Move player position. */
1284     pl_pos.x += shift_x;
1285     pl_pos.y += shift_y;
1286 
1287     /* Actually shift the virtual map by shift_x/shift_y */
1288     if (shift_x < 0) {
1289         src_x = -shift_x;
1290         dst_x = 0;
1291         len_x = the_map.width+shift_x;
1292     } else {
1293         src_x = 0;
1294         dst_x = shift_x;
1295         len_x = the_map.width-shift_x;
1296     }
1297 
1298     if (shift_y < 0) {
1299         src_y = -shift_y;
1300         dst_y = 0;
1301         len_y = the_map.height+shift_y;
1302     } else {
1303         src_y = 0;
1304         dst_y = shift_y;
1305         len_y = the_map.height-shift_y;
1306     }
1307 
1308     if (shift_x < 0) {
1309         for (sx = src_x, dx = dst_x, i = 0; i < len_x; sx++, dx++, i++) {
1310             /* srcx!=dstx ==> can use memcpy since source and
1311              * destination to not overlap.
1312              */
1313             memcpy(mapdata_cell(dx, dst_y), mapdata_cell(sx, src_y), len_y*sizeof(struct MapCell));
1314         }
1315     } else if (shift_x > 0) {
1316         for (sx = src_x+len_x-1, dx = dst_x+len_x-1, i = 0; i < len_x; sx--, dx--, i++) {
1317             /* srcx!=dstx ==> can use memcpy since source and
1318              * destination to not overlap.
1319              */
1320             memcpy(mapdata_cell(dx, dst_y), mapdata_cell(sx, src_y), len_y*sizeof(struct MapCell));
1321         }
1322     } else {
1323         assert(src_x == dst_x);
1324         for (dx = src_x, i = 0; i < len_x; dx++, i++) {
1325             /* srcx==dstx ==> use memmove since source and
1326              * destination probably do overlap.
1327              */
1328             memmove(mapdata_cell(dx, dst_y), mapdata_cell(dx, src_y), len_y*sizeof(struct MapCell));
1329         }
1330     }
1331 
1332     /* Clear newly opened area */
1333     for (dx = 0; dx < dst_x; dx++) {
1334         clear_cells(dx, 0, the_map.height);
1335     }
1336     for (dx = dst_x+len_x; dx < the_map.width; dx++) {
1337         clear_cells(dx, 0, the_map.height);
1338     }
1339     if (shift_y > 0) {
1340         for (dx = 0; dx < len_x; dx++) {
1341             clear_cells(dx+dst_x, 0, shift_y);
1342         }
1343     } else if (shift_y < 0) {
1344         for (dx = 0; dx < len_x; dx++) {
1345             clear_cells(dx+dst_x, the_map.height+shift_y, -shift_y);
1346         }
1347     }
1348 }
1349 
1350 /**
1351  * Return the size of a face in tiles. The returned size is at between 1 and
1352  * MAX_FACE_SIZE (inclusive).
1353  */
mapdata_get_image_size(int face,guint8 * w,guint8 * h)1354 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
1355 {
1356     get_map_image_size(face, w, h);
1357     if (*w < 1) {
1358         *w = 1;
1359     }
1360     if (*h < 1) {
1361         *h = 1;
1362     }
1363     if (*w > MAX_FACE_SIZE) {
1364         *w = MAX_FACE_SIZE;
1365     }
1366     if (*h > MAX_FACE_SIZE) {
1367         *h = MAX_FACE_SIZE;
1368     }
1369 }
1370 
1371 /* This basically goes through all the map spaces and does the necessary
1372  * animation.
1373  */
mapdata_animation(void)1374 void mapdata_animation(void)
1375 {
1376     int x, y, layer, face;
1377     struct MapCellLayer *cell;
1378 
1379 
1380     /* For synchronized animations, what we do is set the initial values
1381      * in the mapdata to the fields in the animations[] array.  In this way,
1382      * the code below the iterates the spaces doesn't need to do anything
1383      * special.  But we have to update the animations[] array here to
1384      * keep in sync.
1385      */
1386     for (x=0; x < MAXANIM; x++) {
1387         if (animations[x].speed) {
1388             animations[x].speed_left++;
1389             if (animations[x].speed_left >= animations[x].speed) {
1390                 animations[x].speed_left=0;
1391                 animations[x].phase++;
1392                 if (animations[x].phase >= animations[x].num_animations) {
1393                     animations[x].phase=0;
1394                 }
1395             }
1396         }
1397     }
1398 
1399     for (x=0; x < CURRENT_MAX_VIEW; x++) {
1400         for (y=0; y < CURRENT_MAX_VIEW; y++) {
1401             struct MapCell *map_space = mapdata_cell(pl_pos.x + x, pl_pos.y + y);
1402 
1403             /* Short cut some processing here.  It makes sense to me
1404              * not to animate stuff out of view
1405              */
1406             if (map_space->cleared) {
1407                 continue;
1408             }
1409 
1410             for (layer=0; layer<MAXLAYERS; layer++) {
1411                 /* Using the cell structure just makes life easier here */
1412                 cell = &map_space->heads[layer];
1413 
1414                 if (cell->animation) {
1415                     cell->animation_left++;
1416                     if (cell->animation_left >= cell->animation_speed) {
1417                         cell->animation_left=0;
1418                         cell->animation_phase++;
1419                         if (cell->animation_phase >= animations[cell->animation].num_animations) {
1420                             cell->animation_phase=0;
1421                         }
1422                         face = animations[cell->animation].faces[cell->animation_phase];
1423 
1424                         /* I don't think we send any to the client, but it is possible
1425                          * for animations to have blank faces.
1426                          */
1427                         if (face >0) {
1428                             expand_set_face(pl_pos.x + x, pl_pos.y + y, layer, face, FALSE);
1429                         } else {
1430                             expand_clear_face_from_layer(pl_pos.x + x, pl_pos.y + y , layer);
1431                         }
1432                     }
1433                 }
1434                 cell = &bigfaces[x][y][layer].head;
1435                 if (cell->animation) {
1436                     cell->animation_left++;
1437                     if (cell->animation_left >= cell->animation_speed) {
1438                         cell->animation_left=0;
1439                         cell->animation_phase++;
1440                         if (cell->animation_phase >= animations[cell->animation].num_animations) {
1441                             cell->animation_phase=0;
1442                         }
1443                         face = animations[cell->animation].faces[cell->animation_phase];
1444 
1445                         /* I don't think we send any to the client, but it is possible
1446                          * for animations to have blank faces.
1447                          */
1448                         expand_set_bigface(x, y, layer, face, FALSE);
1449                     }
1450                 }
1451             }
1452         }
1453     }
1454 }
1455