mapgen.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*
  2. mapgen.c
  3. tile <ascii> <mapto> <top> <right> <bottom> <left>
  4. ":"<mapline>
  5. num := <hexnum> | <decnum> | <asciinum>
  6. asciinum := "'" <char>
  7. hexnum := "$" <hexdigit> { <hexdigit> }
  8. decnum := <decdigit> { <decdigit> }
  9. decdigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
  10. hexdigit := "a" | "b" | "c" | "d" | "e" | "f" | "A" | "B" | "C" | "D" | "E" | "F" | <decdigit>
  11. The value 0 for "top", "right", "bottom" or "left" means match any.
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <stdint.h>
  16. #include <string.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <unistd.h>
  20. struct tile_struct
  21. {
  22. int ascii;
  23. int map_to;
  24. int condition[4];
  25. };
  26. #define TILE_MAX 4096
  27. struct tile_struct tile_list[TILE_MAX];
  28. int tile_cnt = 0;
  29. #define MAP_SIZE_X 1024
  30. #define MAP_SIZE_Y 1024
  31. #define MAP_LINE_MAX 4096
  32. uint8_t map[MAP_SIZE_Y][MAP_SIZE_X];
  33. uint8_t map2[MAP_SIZE_Y][MAP_SIZE_X];
  34. int map_curr_line = 0;
  35. char map_name[MAP_LINE_MAX];
  36. long map_width = 0;
  37. long map_height = 0;
  38. FILE *map_fp;
  39. char map_line[MAP_LINE_MAX];
  40. static void skip_space(const char **s)
  41. {
  42. for(;;)
  43. {
  44. if ( **s == '#' )
  45. {
  46. while( **s != '\0' )
  47. (*s)++;
  48. break;
  49. }
  50. if ( **s == '\0' )
  51. break;
  52. if ( **s > ' ' )
  53. break;
  54. (*s)++;
  55. }
  56. }
  57. static long get_dec(const char **s)
  58. {
  59. long v = 0;
  60. for(;;)
  61. {
  62. if ( (**s) >= '0' && (**s) <= '9' )
  63. {
  64. v*=10;
  65. v+= (**s)-'0';
  66. (*s)++;
  67. }
  68. else
  69. {
  70. break;
  71. }
  72. }
  73. skip_space(s);
  74. return v;
  75. }
  76. static long get_hex(const char **s)
  77. {
  78. long v = 0;
  79. for(;;)
  80. {
  81. if ( (**s) >= '0' && (**s) <= '9' )
  82. {
  83. v*=16;
  84. v+= (**s)-'0';
  85. (*s)++;
  86. }
  87. else if ( (**s) >= 'a' && (**s) <= 'f' )
  88. {
  89. v*=16;
  90. v+= (**s)-'a'+10;
  91. (*s)++;
  92. }
  93. else if ( (**s) >= 'A' && (**s) <= 'F' )
  94. {
  95. v*=16;
  96. v+= (**s)-'A'+10;
  97. (*s)++;
  98. }
  99. else
  100. {
  101. break;
  102. }
  103. }
  104. skip_space(s);
  105. return v;
  106. }
  107. static long get_ascii(const char **s)
  108. {
  109. long v = 0;
  110. v = **s;
  111. (*s)++;
  112. skip_space(s);
  113. return v;
  114. }
  115. static long get_num(const char **s)
  116. {
  117. if ( (**s) == '$' )
  118. {
  119. (*s)++;
  120. return get_hex(s);
  121. }
  122. if ( (**s) == '\'' )
  123. {
  124. (*s)++;
  125. return get_ascii(s);
  126. }
  127. return get_dec(s);
  128. }
  129. static const char *get_identifier(const char **s)
  130. {
  131. static char buf[MAP_LINE_MAX];
  132. int c;
  133. int i = 0;
  134. buf[0] = '\0';
  135. for(;;)
  136. {
  137. c = **s;
  138. if ( c < 'A' )
  139. break;
  140. if ( i >= MAP_LINE_MAX-2 )
  141. break;
  142. buf[i++] = c;
  143. buf[i] = '\0';
  144. (*s)++;
  145. }
  146. skip_space(s);
  147. return buf;
  148. }
  149. /*============================================*/
  150. int get_tile_idx_by_ascii(int ascii)
  151. {
  152. int i;
  153. for( i = 0; i < tile_cnt; i++ )
  154. {
  155. if ( tile_list[i].ascii == ascii )
  156. return i;
  157. }
  158. return -1;
  159. }
  160. /* map a tile from map[][] to map2[][] */
  161. /* called by map_all_tile */
  162. int map_tile(int x, int y)
  163. {
  164. int ascii, i, j;
  165. int cond[4];
  166. int is_condition_match;
  167. //int is_simple_match;
  168. int condition_match_cnt;
  169. int condition_match_max;
  170. int i_best;
  171. /* get the ascii version */
  172. ascii = map[y][x];
  173. cond[0] = 32;
  174. cond[1] = 32;
  175. cond[2] = 32;
  176. cond[3] = 32;
  177. if ( y > 0 ) cond[0] = map[y-1][x];
  178. if ( x+1 < map_width ) cond[1] = map[y][x+1];
  179. if ( y+1 < map_height ) cond[2] = map[y+1][x];
  180. if ( x > 0 ) cond[3] = map[y][x-1];
  181. /* find matching tile */
  182. condition_match_max = -1;
  183. i_best = -1;
  184. for( i = 0; i < tile_cnt; i++ )
  185. {
  186. if ( tile_list[i].ascii == ascii )
  187. {
  188. is_condition_match = 1;
  189. //is_simple_match = 1;
  190. condition_match_cnt = 0;
  191. for( j = 0; j < 4; j++ )
  192. {
  193. if ( tile_list[i].condition[j] != 0 )
  194. {
  195. //is_simple_match = 0;
  196. if ( tile_list[i].condition[j] != cond[j] )
  197. {
  198. is_condition_match = 0;
  199. }
  200. else
  201. {
  202. condition_match_cnt++;
  203. }
  204. }
  205. }
  206. if ( is_condition_match )
  207. {
  208. if ( condition_match_max < condition_match_cnt )
  209. {
  210. condition_match_max = condition_match_cnt;
  211. i_best = i;
  212. }
  213. }
  214. }
  215. }
  216. if ( i_best < 0 )
  217. {
  218. printf("no tile mapping found for '%c' (x=%d, y=%d)\n", ascii, x, y);
  219. return 0;
  220. }
  221. //printf("tile mapping '%c' --> $%02x (x=%d, y=%d)\n", ascii, tile_list[i_best].map_to, x, y);
  222. map2[y][x] = tile_list[i_best].map_to;
  223. return 1;
  224. }
  225. int map_all_tiles(void)
  226. {
  227. int x, y;
  228. for( y = 0; y < map_height; y++ )
  229. for( x = 0; x < map_width; x++ )
  230. if ( map_tile(x,y) == 0 )
  231. return 0;
  232. return 1;
  233. }
  234. void clear_map(void)
  235. {
  236. int x, y;
  237. for( y = 0; y < MAP_SIZE_Y; y++ )
  238. for( x = 0; x < MAP_SIZE_X; x++ )
  239. map[y][x] =32;
  240. map_curr_line = 0;
  241. }
  242. void write_map(const char *filename)
  243. {
  244. int x, y;
  245. FILE *fp;
  246. fp = fopen(filename, "w");
  247. for( y = 0; y < map_height; y++ )
  248. {
  249. fprintf(fp, " \"");
  250. for( x = 0; x < map_width; x++ )
  251. {
  252. fprintf(fp, "\\x%02x", map2[y][x]);
  253. }
  254. fprintf(fp, "\"");
  255. if ( y+1 < map_height )
  256. fprintf(fp, ",");
  257. fprintf(fp, "\n");
  258. }
  259. fclose(fp);
  260. }
  261. int map_read_tile(const char **s)
  262. {
  263. long ascii;
  264. int idx, i;
  265. ascii = get_num(s);
  266. if ( tile_cnt >= TILE_MAX )
  267. {
  268. printf("max number of tiles reached\n");
  269. return 0;
  270. }
  271. idx = tile_cnt;
  272. tile_list[idx].ascii = ascii;
  273. tile_cnt++;
  274. tile_list[idx].map_to = get_num(s);
  275. for( i = 0; i < 4; i++ )
  276. {
  277. tile_list[idx].condition[i] = get_num(s);
  278. }
  279. //printf("[%d] tile %c: ", idx, (int)ascii);
  280. //printf("map to $%02x\n", tile_list[idx].map_to);
  281. return 1;
  282. }
  283. int map_read_row(const char **s)
  284. {
  285. int x = 0;
  286. //printf("line %d\n", map_curr_line);
  287. while ( **s >= ' ' )
  288. {
  289. if ( x > map_width )
  290. {
  291. printf("map '%s': Row '%d' too long\n", map_name, map_curr_line);
  292. return 0;
  293. }
  294. //printf("%d ", **s);
  295. map[map_curr_line][x] = **s;
  296. (*s)++;
  297. x++;
  298. }
  299. map_curr_line++;
  300. return 1;
  301. }
  302. int map_read_map_cmd(const char **s)
  303. {
  304. /* get new map */
  305. strcpy(map_name, get_identifier(s));
  306. map_width = get_num(s);
  307. map_height = get_num(s);
  308. printf("map '%s' (%ld x %ld)\n", map_name, map_width, map_height);
  309. clear_map();
  310. return 1;
  311. }
  312. int map_read_line(const char **s)
  313. {
  314. const char *id;
  315. skip_space(s);
  316. if ( **s == '#' ) /* comment (hmm handled by skip_space) */
  317. return 1;
  318. if ( **s == '\0' ) /* empty line */
  319. return 1;
  320. if ( **s == ':' )
  321. {
  322. (*s)++;
  323. return map_read_row(s);
  324. }
  325. id = get_identifier(s);
  326. if ( strcmp(id, "tile") == 0 )
  327. {
  328. return map_read_tile(s);
  329. }
  330. else if ( strcmp(id, "map") == 0 )
  331. {
  332. return map_read_map_cmd(s);
  333. }
  334. else if ( strcmp(id, "endmap") == 0 )
  335. {
  336. /* write existing map */
  337. if ( map_width > 0 && map_height > 0 )
  338. {
  339. if ( map_all_tiles() )
  340. write_map("gm.c");
  341. }
  342. return 1;
  343. }
  344. else
  345. {
  346. printf("line %d: unkown command '%s'\n", map_curr_line, id);
  347. }
  348. return 1;
  349. }
  350. int map_read_fp(void)
  351. {
  352. const char *s;
  353. for(;;)
  354. {
  355. if ( fgets(map_line, MAP_LINE_MAX, map_fp) == NULL )
  356. break;
  357. s = &(map_line[0]);
  358. if ( map_read_line(&s) == 0 )
  359. return 0;
  360. }
  361. return 1;
  362. }
  363. int map_read_filename(const char *name)
  364. {
  365. map_fp = fopen(name, "r");
  366. if ( map_fp == NULL )
  367. return 0;
  368. printf("file '%s'\n", name);
  369. if ( map_read_fp() == 0 )
  370. return fclose(map_fp), 0;
  371. fclose(map_fp);
  372. return 1;
  373. }
  374. int main(void)
  375. {
  376. clear_map();
  377. map_read_filename("gm.map");
  378. }