/* * $Id: map.bits.c,v 1.1.1.1 2005/01/11 21:18:07 kstevens Exp $ * * Author: Markus Stenberg <fingon@iki.fi> * * Copyright (c) 1996 Markus Stenberg * All rights reserved * * Created: Tue Oct 22 16:32:09 1996 fingon * Last modified: Fri Jun 12 23:10:43 1998 fingon * */ #include "mech.h" #include "create.h" #define CHELO(a,b,c,d) if ((tmp=fread(a,b,c,d)) != c) { fprintf (stderr, "Error loading mapdynamic for #%d - couldn't find enough entries! (found: %d, should: %d)\n", map->mynum, tmp, c); fflush(stderr); exit(1); } #define CHESA(a,b,c,d) if ((tmp=fwrite(a,b,c,d)) != c) { fprintf (stderr, "Error writing mapdynamic for #%d - couldn't find enough entries! (found: %d, should: %d)\n", map->mynum, tmp, c); fflush(stderr); exit(1); } #define realnum(x) ((x) / 4 + ((x) % 4 ? 1 : 0)) #define boffs(x) (2 * ((x) % 4)) #define boffsbit(x,n) ((1<<boffs(x))*n) #define btsetbit(arr,x,y,n) \ create_if_neccessary(arr,map,y);arr[y][realnum(x)] |= boffsbit(x,n) #define btunsetbit(arr,x,y,n) if (arr[y]) arr[y][realnum(x)] &= ~(boffsbit(x,n)) #define btissetbit(arr,x,y,n) (arr[y][realnum(x)] & boffsbit(x,n)) #define BIT_MINE 1 #define BIT_HANGAR 2 /* Main idea: By using 2 bits / hex in external array, we can _fast_ figure out if a certain hex has mines / hangars or not. Downside is keeping the table up to date. */ static void create_if_neccessary(unsigned char **foo, MAP * map, int y) { int xs = map->map_width; if (!foo[y]) Create(foo[y], unsigned char, realnum(xs)); } /* All the nasty bits on the map ;) */ void map_load_bits(FILE * f, MAP * map) { int xs = map->map_width; int ys = map->map_height; unsigned char **foo; int tmp, i; Create(foo, unsigned char *, ys); CHELO(foo, sizeof(unsigned char *), ys, f); for (i = 0; i < ys; i++) if (foo[i]) { Create(foo[i], unsigned char, realnum(xs)); CHELO(foo[i], sizeof(unsigned char), realnum(xs), f); } } void map_save_bits(FILE * f, MAP * map, mapobj * obj) { int tmp; int i, j, c, tc = 0; unsigned char **foo; int xs = map->map_width; int ys = map->map_height; unsigned char tmpb; #define outbyte(a) tmpb=(a);fwrite(&tmpb, 1, 1, f); foo = (unsigned char **) ((void *) obj->datai); /* First, we clean up our act */ for (i = 0; i < ys; i++) { c = 0; if (foo[i]) { for (j = 0; j < realnum(xs); j++) if (foo[i][j]) c++; if (!c) { free((void *) foo[i]); foo[i] = NULL; } else tc += c; } } if (!tc) { /* We don't want to save worthless shit */ /* On other hand, cleaning us out of memory would take too much trouble compared to the worth. Therefore, during next cleanup (reboot), this structure does a disappearance act. */ return; } outbyte(TYPE_BITS + 1); CHESA(foo, sizeof(unsigned char *), ys, f); for (i = 0; i < ys; i++) if (foo[i]) CHESA(foo[i], sizeof(unsigned char), realnum(xs), f); } /* Okay, now we got code to load / save the bits.. but what will we do with them? */ /* Nasty stuff starts here ;) */ static unsigned char **grab_us_an_array(MAP * map) { unsigned char **foo; mapobj foob; int ys = map->map_height; if (!map->mapobj[TYPE_BITS]) { Create(foo, unsigned char *, ys); foob.datai = (int) ((void *) foo); add_mapobj(map, &map->mapobj[TYPE_BITS], &foob, 0); } else foo = (unsigned char **) ((void *) map->mapobj[TYPE_BITS]->datai); return foo; } void set_hex_enterable(MAP * map, int x, int y) { unsigned char **foo; foo = grab_us_an_array(map); btsetbit(foo, x, y, BIT_HANGAR); } void set_hex_mine(MAP * map, int x, int y) { unsigned char **foo; foo = grab_us_an_array(map); btsetbit(foo, x, y, BIT_MINE); } void unset_hex_enterable(MAP * map, int x, int y) { unsigned char **foo; foo = grab_us_an_array(map); btunsetbit(foo, x, y, BIT_HANGAR); } void unset_hex_mine(MAP * map, int x, int y) { unsigned char **foo; foo = grab_us_an_array(map); btunsetbit(foo, x, y, BIT_MINE); } int is_mine_hex(MAP * map, int x, int y) { unsigned char **foo; if (!map) return 0; if (!map->mapobj[TYPE_BITS]) return 0; foo = grab_us_an_array(map); if (!foo[y]) return 0; return (btissetbit(foo, x, y, BIT_MINE)); } int is_hangar_hex(MAP * map, int x, int y) { unsigned char **foo; if (!map) return 0; if (!map->mapobj[TYPE_BITS]) return 0; foo = grab_us_an_array(map); if (!foo[y]) return 0; return (btissetbit(foo, x, y, BIT_HANGAR)); } void clear_hex_bits(MAP * map, int bits) { int xs = map->map_width; int ys = map->map_height; int i, j; unsigned char **foo; if (!map->mapobj[TYPE_BITS]) return; foo = grab_us_an_array(map); for (i = 0; i < ys; i++) if (foo[i]) for (j = 0; j < xs; j++) { switch (bits) { case 1: case 2: if (btissetbit(foo, j, i, bits)) btunsetbit(foo, j, i, bits); break; case 0: if (btissetbit(foo, j, i, 1)) btunsetbit(foo, j, i, 1); if (btissetbit(foo, j, i, 2)) btunsetbit(foo, j, i, 2); break; } } } int bit_size(MAP * map) { int xs = map->map_width; int ys = map->map_height; int i, s = 0; unsigned char **foo; if (!map->mapobj[TYPE_BITS]) return 0; foo = grab_us_an_array(map); for (i = 0; i < ys; i++) if (foo[i]) s += realnum(xs); return s; }