| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- /*
- mapgen.c
-
- tile <ascii> <mapto> <top> <right> <bottom> <left>
- ":"<mapline>
- num := <hexnum> | <decnum> | <asciinum>
- asciinum := "'" <char>
- hexnum := "$" <hexdigit> { <hexdigit> }
- decnum := <decdigit> { <decdigit> }
- decdigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
- hexdigit := "a" | "b" | "c" | "d" | "e" | "f" | "A" | "B" | "C" | "D" | "E" | "F" | <decdigit>
- The value 0 for "top", "right", "bottom" or "left" means match any.
-
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- struct tile_struct
- {
- int ascii;
- int map_to;
- int condition[4];
- };
- #define TILE_MAX 4096
- struct tile_struct tile_list[TILE_MAX];
- int tile_cnt = 0;
- #define MAP_SIZE_X 1024
- #define MAP_SIZE_Y 1024
- #define MAP_LINE_MAX 4096
- uint8_t map[MAP_SIZE_Y][MAP_SIZE_X];
- uint8_t map2[MAP_SIZE_Y][MAP_SIZE_X];
- int map_curr_line = 0;
- char map_name[MAP_LINE_MAX];
- long map_width = 0;
- long map_height = 0;
- FILE *map_fp;
- char map_line[MAP_LINE_MAX];
- static void skip_space(const char **s)
- {
- for(;;)
- {
- if ( **s == '#' )
- {
- while( **s != '\0' )
- (*s)++;
- break;
- }
- if ( **s == '\0' )
- break;
- if ( **s > ' ' )
- break;
- (*s)++;
- }
- }
- static long get_dec(const char **s)
- {
- long v = 0;
- for(;;)
- {
- if ( (**s) >= '0' && (**s) <= '9' )
- {
- v*=10;
- v+= (**s)-'0';
- (*s)++;
- }
- else
- {
- break;
- }
- }
- skip_space(s);
- return v;
- }
- static long get_hex(const char **s)
- {
- long v = 0;
- for(;;)
- {
- if ( (**s) >= '0' && (**s) <= '9' )
- {
- v*=16;
- v+= (**s)-'0';
- (*s)++;
- }
- else if ( (**s) >= 'a' && (**s) <= 'f' )
- {
- v*=16;
- v+= (**s)-'a'+10;
- (*s)++;
- }
- else if ( (**s) >= 'A' && (**s) <= 'F' )
- {
- v*=16;
- v+= (**s)-'A'+10;
- (*s)++;
- }
- else
- {
- break;
- }
- }
- skip_space(s);
- return v;
- }
- static long get_ascii(const char **s)
- {
- long v = 0;
- v = **s;
- (*s)++;
- skip_space(s);
- return v;
- }
- static long get_num(const char **s)
- {
- if ( (**s) == '$' )
- {
- (*s)++;
- return get_hex(s);
- }
- if ( (**s) == '\'' )
- {
- (*s)++;
- return get_ascii(s);
- }
-
- return get_dec(s);
- }
- static const char *get_identifier(const char **s)
- {
- static char buf[MAP_LINE_MAX];
- int c;
- int i = 0;
- buf[0] = '\0';
- for(;;)
- {
- c = **s;
- if ( c < 'A' )
- break;
- if ( i >= MAP_LINE_MAX-2 )
- break;
- buf[i++] = c;
- buf[i] = '\0';
- (*s)++;
- }
- skip_space(s);
- return buf;
- }
- /*============================================*/
- int get_tile_idx_by_ascii(int ascii)
- {
- int i;
- for( i = 0; i < tile_cnt; i++ )
- {
- if ( tile_list[i].ascii == ascii )
- return i;
- }
- return -1;
- }
- /* map a tile from map[][] to map2[][] */
- /* called by map_all_tile */
- int map_tile(int x, int y)
- {
- int ascii, i, j;
- int cond[4];
- int is_condition_match;
- //int is_simple_match;
- int condition_match_cnt;
- int condition_match_max;
- int i_best;
-
- /* get the ascii version */
- ascii = map[y][x];
- cond[0] = 32;
- cond[1] = 32;
- cond[2] = 32;
- cond[3] = 32;
-
- if ( y > 0 ) cond[0] = map[y-1][x];
- if ( x+1 < map_width ) cond[1] = map[y][x+1];
- if ( y+1 < map_height ) cond[2] = map[y+1][x];
- if ( x > 0 ) cond[3] = map[y][x-1];
-
- /* find matching tile */
- condition_match_max = -1;
- i_best = -1;
- for( i = 0; i < tile_cnt; i++ )
- {
- if ( tile_list[i].ascii == ascii )
- {
- is_condition_match = 1;
- //is_simple_match = 1;
- condition_match_cnt = 0;
- for( j = 0; j < 4; j++ )
- {
- if ( tile_list[i].condition[j] != 0 )
- {
- //is_simple_match = 0;
- if ( tile_list[i].condition[j] != cond[j] )
- {
- is_condition_match = 0;
- }
- else
- {
- condition_match_cnt++;
- }
- }
- }
- if ( is_condition_match )
- {
- if ( condition_match_max < condition_match_cnt )
- {
- condition_match_max = condition_match_cnt;
- i_best = i;
- }
- }
- }
- }
- if ( i_best < 0 )
- {
- printf("no tile mapping found for '%c' (x=%d, y=%d)\n", ascii, x, y);
- return 0;
- }
- //printf("tile mapping '%c' --> $%02x (x=%d, y=%d)\n", ascii, tile_list[i_best].map_to, x, y);
- map2[y][x] = tile_list[i_best].map_to;
- return 1;
- }
- int map_all_tiles(void)
- {
- int x, y;
- for( y = 0; y < map_height; y++ )
- for( x = 0; x < map_width; x++ )
- if ( map_tile(x,y) == 0 )
- return 0;
- return 1;
- }
- void clear_map(void)
- {
- int x, y;
- for( y = 0; y < MAP_SIZE_Y; y++ )
- for( x = 0; x < MAP_SIZE_X; x++ )
- map[y][x] =32;
- map_curr_line = 0;
- }
- void write_map(const char *filename)
- {
- int x, y;
- FILE *fp;
- fp = fopen(filename, "w");
- for( y = 0; y < map_height; y++ )
- {
- fprintf(fp, " \"");
- for( x = 0; x < map_width; x++ )
- {
- fprintf(fp, "\\x%02x", map2[y][x]);
- }
- fprintf(fp, "\"");
- if ( y+1 < map_height )
- fprintf(fp, ",");
- fprintf(fp, "\n");
- }
- fclose(fp);
- }
- int map_read_tile(const char **s)
- {
- long ascii;
- int idx, i;
- ascii = get_num(s);
- if ( tile_cnt >= TILE_MAX )
- {
- printf("max number of tiles reached\n");
- return 0;
- }
- idx = tile_cnt;
- tile_list[idx].ascii = ascii;
- tile_cnt++;
-
- tile_list[idx].map_to = get_num(s);
- for( i = 0; i < 4; i++ )
- {
- tile_list[idx].condition[i] = get_num(s);
- }
-
- //printf("[%d] tile %c: ", idx, (int)ascii);
- //printf("map to $%02x\n", tile_list[idx].map_to);
-
- return 1;
- }
- int map_read_row(const char **s)
- {
- int x = 0;
- //printf("line %d\n", map_curr_line);
- while ( **s >= ' ' )
- {
- if ( x > map_width )
- {
- printf("map '%s': Row '%d' too long\n", map_name, map_curr_line);
- return 0;
- }
- //printf("%d ", **s);
- map[map_curr_line][x] = **s;
- (*s)++;
- x++;
-
- }
- map_curr_line++;
- return 1;
- }
- int map_read_map_cmd(const char **s)
- {
-
- /* get new map */
- strcpy(map_name, get_identifier(s));
- map_width = get_num(s);
- map_height = get_num(s);
- printf("map '%s' (%ld x %ld)\n", map_name, map_width, map_height);
- clear_map();
- return 1;
- }
- int map_read_line(const char **s)
- {
- const char *id;
- skip_space(s);
-
- if ( **s == '#' ) /* comment (hmm handled by skip_space) */
- return 1;
- if ( **s == '\0' ) /* empty line */
- return 1;
-
- if ( **s == ':' )
- {
- (*s)++;
- return map_read_row(s);
- }
-
- id = get_identifier(s);
- if ( strcmp(id, "tile") == 0 )
- {
- return map_read_tile(s);
- }
- else if ( strcmp(id, "map") == 0 )
- {
- return map_read_map_cmd(s);
- }
- else if ( strcmp(id, "endmap") == 0 )
- {
- /* write existing map */
- if ( map_width > 0 && map_height > 0 )
- {
- if ( map_all_tiles() )
- write_map("gm.c");
- }
- return 1;
- }
- else
- {
- printf("line %d: unkown command '%s'\n", map_curr_line, id);
- }
-
- return 1;
- }
- int map_read_fp(void)
- {
- const char *s;
- for(;;)
- {
- if ( fgets(map_line, MAP_LINE_MAX, map_fp) == NULL )
- break;
- s = &(map_line[0]);
- if ( map_read_line(&s) == 0 )
- return 0;
- }
- return 1;
- }
- int map_read_filename(const char *name)
- {
- map_fp = fopen(name, "r");
- if ( map_fp == NULL )
- return 0;
- printf("file '%s'\n", name);
- if ( map_read_fp() == 0 )
- return fclose(map_fp), 0;
- fclose(map_fp);
- return 1;
- }
- int main(void)
- {
- clear_map();
- map_read_filename("gm.map");
- }
|