1 /* NetHack 3.6 lev_main.c $NHDT-Date: 1543371692 2018/11/28 02:21:32 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.56 $ */
2 /* Copyright (c) 1989 by Jean-Christophe Collet */
3 /* NetHack may be freely redistributed. See license for details. */
6 * This file contains the main function for the parser
7 * and some useful functions needed by yacc
9 #define SPEC_LEV /* for USE_OLDARGS (sp_lev.h) and for MPW (macconf.h) */
21 #if defined(__SC__) || defined(__MRC__)
23 #define PREFIX ":dungeon:" /* place output files here */
24 #include <CursorCtl.h>
26 #if !defined(__MACH__)
27 #define PREFIX ":lib:" /* place output files here */
33 #define PREFIX "\\nethack\\dat\\"
40 #if defined(AMIGA) && defined(DLB)
41 #define PREFIX "NH:slib/"
47 #ifndef O_CREAT /* some older BSD systems do not define O_CREAT in <fcntl.h> \
51 #ifndef O_BINARY /* used for micros, no-op for others */
55 #if defined(MICRO) || defined(WIN32)
63 #define NewTab(type, size) (type **) alloc(sizeof(type *) * size)
66 free((genericptr_t)(ptr))
67 /* write() returns a signed value but its size argument is unsigned;
68 types might be int and unsigned or ssize_t and size_t; casting
69 to long should be safe for all permutations (even if size_t is
70 bigger, since the values involved won't be too big for long) */
71 #define Write(fd, item, size) \
72 if ((long) write(fd, (genericptr_t)(item), size) != (long) (size)) \
75 #if defined(__BORLANDC__) && !defined(_WIN32)
76 extern unsigned _stklen = STKSIZ;
80 extern int NDECL(yyparse);
81 extern void FDECL(init_yyin, (FILE *));
82 extern void FDECL(init_yyout, (FILE *));
84 int FDECL(main, (int, char **));
85 void FDECL(yyerror, (const char *));
86 void FDECL(yywarning, (const char *));
88 int FDECL(get_floor_type, (CHAR_P));
89 int FDECL(get_room_type, (char *));
90 int FDECL(get_trap_type, (char *));
91 int FDECL(get_monster_id, (char *, CHAR_P));
92 int FDECL(get_object_id, (char *, CHAR_P));
93 boolean FDECL(check_monster_char, (CHAR_P));
94 boolean FDECL(check_object_char, (CHAR_P));
95 char FDECL(what_map_char, (CHAR_P));
96 void FDECL(scan_map, (char *, sp_lev *));
97 boolean NDECL(check_subrooms);
98 boolean FDECL(write_level_file, (char *, sp_lev *));
100 struct lc_funcdefs *FDECL(funcdef_new, (long, char *));
101 void FDECL(funcdef_free_all, (struct lc_funcdefs *));
102 struct lc_funcdefs *FDECL(funcdef_defined,
103 (struct lc_funcdefs *, char *, int));
105 struct lc_vardefs *FDECL(vardef_new, (long, char *));
106 void FDECL(vardef_free_all, (struct lc_vardefs *));
107 struct lc_vardefs *FDECL(vardef_defined, (struct lc_vardefs *, char *, int));
109 void FDECL(splev_add_from, (sp_lev *, sp_lev *));
111 extern void NDECL(monst_init);
112 extern void NDECL(objects_init);
113 extern void NDECL(decl_init);
115 void FDECL(add_opcode, (sp_lev *, int, genericptr_t));
117 static boolean FDECL(write_common_data, (int));
118 static boolean FDECL(write_maze, (int, sp_lev *));
119 static void NDECL(init_obj_classes);
120 static int FDECL(case_insensitive_comp, (const char *, const char *));
122 void VDECL(lc_pline, (const char *, ...));
123 void VDECL(lc_error, (const char *, ...));
124 void VDECL(lc_warning, (const char *, ...));
125 char *FDECL(decode_parm_chr, (CHAR_P));
126 char *FDECL(decode_parm_str, (char *));
127 struct opvar *FDECL(set_opvar_int, (struct opvar *, long));
128 struct opvar *FDECL(set_opvar_coord, (struct opvar *, long));
129 struct opvar *FDECL(set_opvar_region, (struct opvar *, long));
130 struct opvar *FDECL(set_opvar_mapchar, (struct opvar *, long));
131 struct opvar *FDECL(set_opvar_monst, (struct opvar *, long));
132 struct opvar *FDECL(set_opvar_obj, (struct opvar *, long));
133 struct opvar *FDECL(set_opvar_str, (struct opvar *, const char *));
134 struct opvar *FDECL(set_opvar_var, (struct opvar *, const char *));
135 void VDECL(add_opvars, (sp_lev *, const char *, ...));
136 void NDECL(break_stmt_start);
137 void FDECL(break_stmt_end, (sp_lev *));
138 void FDECL(break_stmt_new, (sp_lev *, long));
139 char *FDECL(funcdef_paramtypes, (struct lc_funcdefs *));
140 const char *FDECL(spovar2str, (long));
141 void FDECL(vardef_used, (struct lc_vardefs *, char *));
142 void FDECL(check_vardef_type, (struct lc_vardefs *, char *, long));
143 struct lc_vardefs *FDECL(add_vardef_type,
144 (struct lc_vardefs *, char *, long));
145 int FDECL(reverse_jmp_opcode, (int));
146 struct opvar *FDECL(opvar_clone, (struct opvar *));
147 void FDECL(start_level_def, (sp_lev **, char *));
152 } trap_types[] = { { "arrow", ARROW_TRAP },
153 { "dart", DART_TRAP },
154 { "falling rock", ROCKTRAP },
155 { "board", SQKY_BOARD },
156 { "bear", BEAR_TRAP },
157 { "land mine", LANDMINE },
158 { "rolling boulder", ROLLING_BOULDER_TRAP },
159 { "sleep gas", SLP_GAS_TRAP },
160 { "rust", RUST_TRAP },
161 { "fire", FIRE_TRAP },
163 { "spiked pit", SPIKED_PIT },
165 { "trap door", TRAPDOOR },
166 { "teleport", TELEP_TRAP },
167 { "level teleport", LEVEL_TELEP },
168 { "magic portal", MAGIC_PORTAL },
170 { "statue", STATUE_TRAP },
171 { "magic", MAGIC_TRAP },
172 { "anti magic", ANTI_MAGIC },
173 { "polymorph", POLY_TRAP },
174 { "vibrating square", VIBRATING_SQUARE },
181 /* for historical reasons, room types are not contiguous numbers */
182 /* (type 1 is skipped) */
183 { "ordinary", OROOM },
187 { "beehive", BEEHIVE },
188 { "morgue", MORGUE },
189 { "barracks", BARRACKS },
191 { "delphi", DELPHI },
192 { "temple", TEMPLE },
193 { "anthole", ANTHOLE },
194 { "cocknest", COCKNEST },
195 { "leprehall", LEPREHALL },
196 { "shop", SHOPBASE },
197 { "armor shop", ARMORSHOP },
198 { "scroll shop", SCROLLSHOP },
199 { "potion shop", POTIONSHOP },
200 { "weapon shop", WEAPONSHOP },
201 { "food shop", FOODSHOP },
202 { "ring shop", RINGSHOP },
203 { "wand shop", WANDSHOP },
204 { "tool shop", TOOLSHOP },
205 { "book shop", BOOKSHOP },
206 { "health food shop", FODDERSHOP },
207 { "candle shop", CANDLESHOP },
211 const char *fname = "(stdin)";
215 int fname_counter = 1;
218 /* Flex 2.3 bug work around; not needed for 2.3.6 or later */
222 extern unsigned int max_x_map, max_y_map;
224 extern int nh_line_number;
226 extern int token_start_pos;
227 extern char curr_token[512];
229 struct lc_vardefs *vardefs = NULL;
230 struct lc_funcdefs *function_definitions = NULL;
232 extern int allow_break_statements;
233 extern struct lc_breakdef *break_list;
242 boolean errors_encountered = FALSE;
243 #if defined(MAC) && (defined(THINK_C) || defined(__MWERKS__))
244 static char *mac_argv[] = {
245 "lev_comp", /* dummy argv[0] */
246 ":dat:Arch.des", ":dat:Barb.des", ":dat:Caveman.des",
247 ":dat:Healer.des", ":dat:Knight.des", ":dat:Monk.des",
248 ":dat:Priest.des", ":dat:Ranger.des", ":dat:Rogue.des",
249 ":dat:Samurai.des", ":dat:Tourist.des", ":dat:Valkyrie.des",
250 ":dat:Wizard.des", ":dat:bigroom.des", ":dat:castle.des",
251 ":dat:endgame.des", ":dat:gehennom.des", ":dat:knox.des",
252 ":dat:medusa.des", ":dat:mines.des", ":dat:oracle.des",
253 ":dat:sokoban.des", ":dat:tower.des", ":dat:yendor.des"
256 argc = SIZE(mac_argv);
259 /* Note: these initializers don't do anything except guarantee that
260 * we're linked properly.
265 /* this one does something... */
269 if (argc == 1) { /* Read standard input */
272 if (fatal_error > 0) {
273 errors_encountered = TRUE;
275 } else { /* Otherwise every argument is a filename */
276 for (i = 1; i < argc; i++) {
278 if (!strcmp(fname, "-v")) {
282 fin = freopen(fname, "r", stdin);
284 lc_pline("Can't open \"%s\" for input.\n", VA_PASS1(fname));
286 errors_encountered = TRUE;
292 if (fatal_error > 0 || got_errors > 0) {
293 errors_encountered = TRUE;
299 exit(errors_encountered ? EXIT_FAILURE : EXIT_SUCCESS);
305 * Each time the parser detects an error, it uses this function.
306 * Here we take count of the errors. To continue farther than
307 * MAX_ERRORS wouldn't be reasonable.
308 * Assume that explicit calls from lev_comp.y have the 1st letter
309 * capitalized, to allow printing of the line containing the start of
310 * the current declaration, instead of the beginning of the next declaration.
316 char *e = ((char *) s + strlen(s) - 1);
318 (void) fprintf(stderr, "%s: line %d, pos %d: %s", fname, nh_line_number,
319 token_start_pos - (int) strlen(curr_token), s);
320 if (*e != '.' && *e != '!')
321 (void) fprintf(stderr, " at \"%s\"", curr_token);
322 (void) fprintf(stderr, "\n");
324 if (++fatal_error > MAX_ERRORS) {
325 (void) fprintf(stderr, "Too many errors, good bye!\n");
331 * Just display a warning (that is : a non fatal error)
337 (void) fprintf(stderr, "%s: line %d : WARNING : %s\n", fname,
342 * Stub needed for lex interface.
351 * lc_pline(): lev_comp version of pline(), stripped down version of
352 * core's pline(), with convoluted handling for variadic arguments to
353 * support <stdarg.h>, <varargs.h>, and neither of the above.
355 * Using state for message/warning/error mode simplifies calling interface.
357 #define LC_PLINE_MESSAGE 0
358 #define LC_PLINE_WARNING 1
359 #define LC_PLINE_ERROR 2
360 static int lc_pline_mode = LC_PLINE_MESSAGE;
362 #if defined(USE_STDARG) || defined(USE_VARARGS)
363 static void FDECL(lc_vpline, (const char *, va_list));
366 VA_DECL(const char *, line)
369 VA_INIT(line, char *);
370 lc_vpline(line, VA_ARGS);
376 lc_vpline(const char *line, va_list the_args)
379 lc_vpline(line, the_args)
384 #else /* USE_STDARG | USE_VARARG */
386 #define lc_vpline lc_pline
390 VA_DECL(const char *, line)
391 #endif /* USE_STDARG | USE_VARARG */
392 { /* opening brace for lc_vpline, nested block for USE_OLDARGS lc_pline */
394 char pbuf[3 * BUFSZ];
395 static char nomsg[] = "(no message)";
396 /* Do NOT use VA_START and VA_END in here... see above */
399 line = nomsg; /* shouldn't happen */
400 if (index(line, '%')) {
401 Vsprintf(pbuf, line, VA_ARGS);
402 pbuf[BUFSZ - 1] = '\0'; /* truncate if long */
405 switch (lc_pline_mode) {
409 case LC_PLINE_WARNING:
413 (void) fprintf(stderr, "%s\n", line);
416 lc_pline_mode = LC_PLINE_MESSAGE; /* reset to default */
418 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
419 VA_END(); /* closing brace ofr USE_OLDARGS's nested block */
426 VA_DECL(const char *, line)
429 VA_INIT(line, const char *);
430 lc_pline_mode = LC_PLINE_ERROR;
431 lc_vpline(line, VA_ARGS);
439 VA_DECL(const char *, line)
442 VA_INIT(line, const char *);
443 lc_pline_mode = LC_PLINE_WARNING;
444 lc_vpline(line, VA_ARGS);
457 Strcpy(buf, "unknown");
463 Strcpy(buf, "region");
472 Strcpy(buf, "coord");
475 Strcpy(buf, "nothing");
478 Strcpy(buf, "mapchar");
481 Strcpy(buf, "monster");
491 static char tmpbuf[1024];
496 Strcat(tmpbuf, decode_parm_chr(*p));
498 Strcat(tmpbuf, ", ");
505 set_opvar_int(ov, val)
510 ov->spovartyp = SPOVAR_INT;
517 set_opvar_coord(ov, val)
522 ov->spovartyp = SPOVAR_COORD;
529 set_opvar_region(ov, val)
534 ov->spovartyp = SPOVAR_REGION;
541 set_opvar_mapchar(ov, val)
546 ov->spovartyp = SPOVAR_MAPCHAR;
553 set_opvar_monst(ov, val)
558 ov->spovartyp = SPOVAR_MONST;
565 set_opvar_obj(ov, val)
570 ov->spovartyp = SPOVAR_OBJ;
577 set_opvar_str(ov, val)
582 ov->spovartyp = SPOVAR_STRING;
583 ov->vardata.str = (val) ? strdup(val) : NULL;
589 set_opvar_var(ov, val)
594 ov->spovartyp = SPOVAR_VARIABLE;
595 ov->vardata.str = (val) ? strdup(val) : NULL;
601 (type *) memset((genericptr_t) alloc(sizeof(type)), 0, sizeof(type))
603 #if defined(USE_STDARG) || defined(USE_VARARGS)
604 static void FDECL(vadd_opvars, (sp_lev *, const char *, va_list));
607 VA_DECL2(sp_lev *, sp, const char *, fmt)
610 VA_INIT(fmt, char *);
611 vadd_opvars(sp, fmt, VA_ARGS);
617 vadd_opvars(sp_lev *sp, const char *fmt, va_list the_args)
621 vadd_opvars(sp, fmt, the_args)
628 #else /* USE_STDARG | USE_VARARG */
630 #define vadd_opvars add_opvars
633 VA_DECL2(sp_lev *, sp, const char *, fmt)
634 #endif /* USE_STDARG | USE_VARARG */
638 /* Do NOT use VA_START and VA_END in here... see above */
640 for (p = fmt; *p != '\0'; p++) {
644 case 'i': /* integer (via plain 'int') */
646 struct opvar *ov = New(struct opvar);
648 set_opvar_int(ov, (long) VA_NEXT(la, int));
649 add_opcode(sp, SPO_PUSH, ov);
652 case 'l': /* integer (via 'long int') */
654 struct opvar *ov = New(struct opvar);
656 set_opvar_int(ov, VA_NEXT(la, long));
657 add_opcode(sp, SPO_PUSH, ov);
660 case 'c': /* coordinate */
662 struct opvar *ov = New(struct opvar);
663 set_opvar_coord(ov, VA_NEXT(la, long));
664 add_opcode(sp, SPO_PUSH, ov);
667 case 'r': /* region */
669 struct opvar *ov = New(struct opvar);
670 set_opvar_region(ov, VA_NEXT(la, long));
671 add_opcode(sp, SPO_PUSH, ov);
674 case 'm': /* mapchar */
676 struct opvar *ov = New(struct opvar);
677 set_opvar_mapchar(ov, VA_NEXT(la, long));
678 add_opcode(sp, SPO_PUSH, ov);
681 case 'M': /* monster */
683 struct opvar *ov = New(struct opvar);
684 set_opvar_monst(ov, VA_NEXT(la, long));
685 add_opcode(sp, SPO_PUSH, ov);
688 case 'O': /* object */
690 struct opvar *ov = New(struct opvar);
691 set_opvar_obj(ov, VA_NEXT(la, long));
692 add_opcode(sp, SPO_PUSH, ov);
695 case 's': /* string */
697 struct opvar *ov = New(struct opvar);
698 set_opvar_str(ov, VA_NEXT(lp, const char *));
699 add_opcode(sp, SPO_PUSH, ov);
702 case 'v': /* variable */
704 struct opvar *ov = New(struct opvar);
705 set_opvar_var(ov, VA_NEXT(lp, const char *));
706 add_opcode(sp, SPO_PUSH, ov);
709 case 'o': /* opcode */
711 long i = VA_NEXT(la, int);
712 if (i < 0 || i >= MAX_SP_OPCODES)
713 lc_pline("add_opvars: unknown opcode '%ld'.", VA_PASS1(i));
714 add_opcode(sp, i, NULL);
718 lc_pline("add_opvars: illegal format character '%ld'.",
719 VA_PASS1((long) *p));
724 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
725 /* provide closing brace for USE_OLDARGS nested block from VA_DECL2() */
733 allow_break_statements++;
737 break_stmt_end(splev)
740 struct lc_breakdef *tmp = break_list;
741 struct lc_breakdef *prv = NULL;
744 if (tmp->break_depth == allow_break_statements) {
745 struct lc_breakdef *nxt = tmp->next;
746 set_opvar_int(tmp->breakpoint,
747 splev->n_opcodes - tmp->breakpoint->vardata.l - 1);
760 allow_break_statements--;
764 break_stmt_new(splev, i)
768 struct lc_breakdef *tmp = New(struct lc_breakdef);
770 tmp->breakpoint = New(struct opvar);
771 tmp->break_depth = allow_break_statements;
772 tmp->next = break_list;
774 set_opvar_int(tmp->breakpoint, i);
775 add_opcode(splev, SPO_PUSH, tmp->breakpoint);
776 add_opcode(splev, SPO_JMP, NULL);
780 funcdef_new(addr, name)
784 struct lc_funcdefs *f = New(struct lc_funcdefs);
787 lc_error("Could not alloc function definition for '%s'.",
793 f->name = strdup(name);
797 f->code.opcodes = NULL;
798 f->code.n_opcodes = 0;
803 funcdef_free_all(fchain)
804 struct lc_funcdefs *fchain;
806 struct lc_funcdefs *tmp = fchain;
807 struct lc_funcdefs *nxt;
808 struct lc_funcdefs_parm *tmpparam;
813 while (tmp->params) {
814 tmpparam = tmp->params->next;
815 Free(tmp->params->name);
816 tmp->params = tmpparam;
818 /* FIXME: free tmp->code */
825 funcdef_paramtypes(f)
826 struct lc_funcdefs *f;
829 struct lc_funcdefs_parm *fp = f->params;
830 char *tmp = (char *) alloc((f->n_params) + 1);
835 tmp[i++] = fp->parmtype;
843 funcdef_defined(f, name, casesense)
844 struct lc_funcdefs *f;
850 if (!strcmp(name, f->name))
853 if (!case_insensitive_comp(name, f->name))
862 vardef_new(typ, name)
866 struct lc_vardefs *f = New(struct lc_vardefs);
869 lc_error("Could not alloc variable definition for '%s'.",
875 f->name = strdup(name);
881 vardef_free_all(fchain)
882 struct lc_vardefs *fchain;
884 struct lc_vardefs *tmp = fchain;
885 struct lc_vardefs *nxt;
888 if (be_verbose && (tmp->n_used == 0))
889 lc_warning("Unused variable '%s'", VA_PASS1(tmp->name));
898 vardef_defined(f, name, casesense)
899 struct lc_vardefs *f;
905 if (!strcmp(name, f->name))
908 if (!case_insensitive_comp(name, f->name))
921 static char buf[2][128];
922 const char *n = NULL;
923 int is_array = (spovar & SPOVAR_ARRAY);
925 spovar &= ~SPOVAR_ARRAY;
928 lc_error("spovar2str(%ld)", VA_PASS1(spovar));
936 case SPOVAR_VARIABLE:
956 togl = ((togl + 1) % 2);
958 Sprintf(buf[togl], "%s%s", n, (is_array ? " array" : ""));
963 vardef_used(vd, varname)
964 struct lc_vardefs *vd;
967 struct lc_vardefs *tmp;
969 if ((tmp = vardef_defined(vd, varname, 1)) != 0)
974 check_vardef_type(vd, varname, vartype)
975 struct lc_vardefs *vd;
979 struct lc_vardefs *tmp;
981 if ((tmp = vardef_defined(vd, varname, 1)) != 0) {
982 if (tmp->var_type != vartype)
983 lc_error("Trying to use variable '%s' as %s, when it is %s.",
986 spovar2str(tmp->var_type)));
988 lc_error("Variable '%s' not defined.", VA_PASS1(varname));
992 add_vardef_type(vd, varname, vartype)
993 struct lc_vardefs *vd;
997 struct lc_vardefs *tmp;
999 if ((tmp = vardef_defined(vd, varname, 1)) != 0) {
1000 if (tmp->var_type != vartype)
1001 lc_error("Trying to redefine variable '%s' as %s, when it is %s.",
1003 spovar2str(vartype),
1004 spovar2str(tmp->var_type)));
1006 tmp = vardef_new(vartype, varname);
1014 reverse_jmp_opcode(opcode)
1031 lc_error("Cannot reverse comparison jmp opcode %ld.",
1032 VA_PASS1((long) opcode));
1037 /* basically copied from src/sp_lev.c */
1043 struct opvar *tmpov = (struct opvar *) alloc(sizeof(struct opvar));
1045 if (!tmpov) { /* lint suppression */
1048 /* not possible; alloc() never returns Null */
1049 panic("could not alloc opvar struct");
1052 return (struct opvar *) 0;
1054 switch (ov->spovartyp) {
1057 case SPOVAR_MAPCHAR:
1061 tmpov->spovartyp = ov->spovartyp;
1062 tmpov->vardata.l = ov->vardata.l;
1064 case SPOVAR_VARIABLE:
1065 case SPOVAR_STRING: {
1066 int len = strlen(ov->vardata.str);
1067 tmpov->spovartyp = ov->spovartyp;
1068 tmpov->vardata.str = (char *) alloc(len + 1);
1069 (void) memcpy((genericptr_t) tmpov->vardata.str,
1070 (genericptr_t) ov->vardata.str, len);
1071 tmpov->vardata.str[len] = '\0';
1074 lc_error("Unknown opvar_clone value type (%ld)!",
1075 VA_PASS1((long) ov->spovartyp));
1080 return (struct opvar *) 0;
1084 splev_add_from(splev, from_splev)
1090 if (splev && from_splev)
1091 for (i = 0; i < from_splev->n_opcodes; i++)
1092 add_opcode(splev, from_splev->opcodes[i].opcode,
1093 opvar_clone(from_splev->opcodes[i].opdat));
1097 start_level_def(splev, ldfname)
1101 struct lc_funcdefs *f;
1103 if (index(ldfname, '.'))
1104 lc_error("Invalid dot ('.') in level name '%s'.", VA_PASS1(ldfname));
1105 if ((int) strlen(ldfname) > 14)
1106 lc_error("Level names limited to 14 characters ('%s').",
1108 f = function_definitions;
1113 *splev = (sp_lev *) alloc(sizeof(sp_lev));
1114 (*splev)->n_opcodes = 0;
1115 (*splev)->opcodes = NULL;
1117 vardef_free_all(vardefs);
1122 * Find the type of floor, knowing its char representation.
1131 val = what_map_char(c);
1132 if (val == INVALID_TYPE) {
1134 yywarning("Invalid fill character in MAZE declaration");
1140 * Find the type of a room in the table, knowing its name.
1149 for (i = 0; room_types[i].name; i++)
1150 if (!strcmp(s, room_types[i].name))
1151 return ((int) room_types[i].type);
1156 * Find the type of a trap in the table, knowing its name.
1165 for (i = 0; trap_types[i].name; i++)
1166 if (!strcmp(s, trap_types[i].name))
1167 return trap_types[i].type;
1172 * Find the index of a monster in the table, knowing its name.
1175 get_monster_id(s, c)
1179 register int i, class;
1182 class = c ? def_char_to_monclass(c) : 0;
1183 if (class == MAXMCLASSES)
1186 for (i = LOW_PM; i < NUMMONS; i++)
1187 if (!class || class == mons[i].mlet)
1188 if (!strcmp(s, mons[i].mname))
1190 /* didn't find it; lets try case insensitive search */
1191 for (i = LOW_PM; i < NUMMONS; i++)
1192 if (!class || class == mons[i].mlet)
1193 if (!case_insensitive_comp(s, mons[i].mname)) {
1195 lc_warning("Monster type \"%s\" matches \"%s\".",
1196 VA_PASS2(s, mons[i].mname));
1203 * Find the index of an object in the table, knowing its name.
1211 const char *objname;
1214 class = (c > 0) ? def_char_to_objclass(c) : 0;
1215 if (class == MAXOCLASSES)
1218 for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
1219 if (class && objects[i].oc_class != class)
1221 objname = obj_descr[i].oc_name;
1222 if (objname && !strcmp(s, objname))
1225 for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
1226 if (class && objects[i].oc_class != class)
1228 objname = obj_descr[i].oc_name;
1229 if (objname && !case_insensitive_comp(s, objname)) {
1231 lc_warning("Object type \"%s\" matches \"%s\".",
1232 VA_PASS2(s, objname));
1242 int i, class, prev_class;
1245 for (i = 0; i < NUM_OBJECTS; i++) {
1246 class = objects[i].oc_class;
1247 if (class != prev_class) {
1255 * Is the character 'c' a valid monster class ?
1258 check_monster_char(c)
1261 return (def_char_to_monclass(c) != MAXMCLASSES);
1265 * Is the character 'c' a valid object class ?
1268 check_object_char(c)
1271 return (def_char_to_objclass(c) != MAXOCLASSES);
1275 * Convert .des map letter into floor type.
1298 return (CROSSWALL); /* hack: boundary location */
1324 return (IRONBARS); /* Fe = iron */
1326 return (MAX_TYPE); /* "see-through" */
1328 return (INVALID_TYPE);
1332 add_opcode(sp, opc, dat)
1337 long nop = sp->n_opcodes;
1340 if ((opc < 0) || (opc >= MAX_SP_OPCODES))
1341 lc_error("Unknown opcode '%ld'", VA_PASS1((long) opc));
1343 tmp = (_opcode *) alloc(sizeof(_opcode) * (nop + 1));
1344 if (!tmp) { /* lint suppression */
1347 /* not possible; alloc() never returns Null */
1348 lc_error("%s", VA_PASS1("Could not alloc opcode space"));
1353 if (sp->opcodes && nop) {
1354 (void) memcpy(tmp, sp->opcodes, sizeof(_opcode) * nop);
1359 sp->opcodes[nop].opcode = opc;
1360 sp->opcodes[nop].opdat = dat;
1366 * Yep! LEX gives us the map in a raw mode.
1367 * Just analyze it here.
1374 register int i, len;
1375 register char *s1, *s2;
1378 char *tmpmap[MAP_Y_LIM+1];
1382 /* First, strip out digits 0-9 (line numbering) */
1383 for (s1 = s2 = map; *s1; s1++)
1384 if (*s1 < '0' || *s1 > '9')
1388 /* Second, find the max width of the map */
1391 s2 = index(s1, '\n');
1393 len = (int) (s2 - s1);
1396 len = (int) strlen(s1);
1403 /* Then parse it now */
1404 while (map && *map) {
1405 if (max_hig > MAP_Y_LIM)
1407 tmpmap[max_hig] = (char *) alloc(max_len);
1408 s1 = index(map, '\n');
1410 len = (int) (s1 - map);
1413 len = (int) strlen(map);
1416 for (i = 0; i < len; i++)
1417 if ((tmpmap[max_hig][i] = what_map_char(map[i]))
1420 "Invalid character '%ld' @ (%ld, %ld) - replacing with stone",
1421 VA_PASS3((long) map[i], (long) max_hig, (long) i));
1422 tmpmap[max_hig][i] = STONE;
1425 tmpmap[max_hig][i++] = STONE;
1430 /* Memorize boundaries */
1432 max_x_map = max_len - 1;
1433 max_y_map = max_hig - 1;
1435 if (max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) {
1436 lc_error("Map too large at (%ld x %ld), max is (%ld x %ld)",
1437 VA_PASS4((long) max_len, (long) max_hig,
1438 (long) MAP_X_LIM, (long) MAP_Y_LIM));
1441 mbuf = (char *) alloc(((max_hig - 1) * max_len) + (max_len - 1) + 2);
1442 for (dy = 0; dy < max_hig; dy++)
1443 for (dx = 0; dx < max_len; dx++)
1444 mbuf[(dy * max_len) + dx] = (tmpmap[dy][dx] + 1);
1446 mbuf[((max_hig - 1) * max_len) + (max_len - 1) + 1] = '\0';
1448 add_opvars(sp, "sllo", VA_PASS4(mbuf, (long) max_hig, (long) max_len,
1451 for (dy = 0; dy < max_hig; dy++)
1457 * Output some info common to all special levels.
1460 write_common_data(fd)
1463 static struct version_info version_data = {
1464 VERSION_NUMBER, VERSION_FEATURES, VERSION_SANITY1, VERSION_SANITY2,
1468 Write(fd, &version_data, sizeof version_data);
1473 * Here we write the sp_lev structure in the specified file (fd).
1474 * Also, we have to free the memory allocated via alloc().
1477 write_maze(fd, maze)
1483 if (!write_common_data(fd))
1486 Write(fd, &(maze->n_opcodes), sizeof(maze->n_opcodes));
1488 for (i = 0; i < maze->n_opcodes; i++) {
1489 _opcode tmpo = maze->opcodes[i];
1491 Write(fd, &(tmpo.opcode), sizeof(tmpo.opcode));
1493 if (tmpo.opcode < SPO_NULL || tmpo.opcode >= MAX_SP_OPCODES)
1494 panic("write_maze: unknown opcode (%d).", tmpo.opcode);
1496 if (tmpo.opcode == SPO_PUSH) {
1497 genericptr_t opdat = tmpo.opdat;
1499 struct opvar *ov = (struct opvar *) opdat;
1501 Write(fd, &(ov->spovartyp), sizeof(ov->spovartyp));
1502 switch (ov->spovartyp) {
1507 case SPOVAR_MAPCHAR:
1511 Write(fd, &(ov->vardata.l), sizeof(ov->vardata.l));
1513 case SPOVAR_VARIABLE:
1515 if (ov->vardata.str)
1516 size = strlen(ov->vardata.str);
1519 Write(fd, &size, sizeof(size));
1521 Write(fd, ov->vardata.str, size);
1522 Free(ov->vardata.str);
1526 panic("write_maze: unknown data type (%d).",
1530 panic("write_maze: PUSH with no data.");
1533 genericptr_t opdat = tmpo.opdat;
1535 panic("write_maze: opcode (%d) has data.", tmpo.opcode);
1540 /* clear the struct for next user */
1541 Free(maze->opcodes);
1542 maze->opcodes = NULL;
1543 /*(void) memset((genericptr_t) &maze->init_lev, 0, sizeof
1544 * maze->init_lev);*/
1550 * Open and write maze or rooms file, based on which pointer is non-null.
1551 * Return TRUE on success, FALSE on failure.
1554 write_level_file(filename, lvl)
1563 Strcat(lbuf, PREFIX);
1565 Strcat(lbuf, filename);
1566 Strcat(lbuf, LEV_EXT);
1568 #if defined(MAC) && (defined(__SC__) || defined(__MRC__))
1569 fout = open(lbuf, O_WRONLY | O_CREAT | O_BINARY);
1571 fout = open(lbuf, O_WRONLY | O_CREAT | O_BINARY, OMASK);
1577 panic("write_level_file");
1580 fprintf(stdout, "File: '%s', opcodes: %ld\n", lbuf, lvl->n_opcodes);
1582 if (!write_maze(fout, lvl))
1591 case_insensitive_comp(s1, s2)
1597 for (;; s1++, s2++) {
1604 if (u1 == '\0' || u1 != u2)
1610 #ifdef STRICT_REF_DEF
1612 * Any globals declared in hack.h and descendents which aren't defined
1613 * in the modules linked into lev_comp should be defined here. These
1614 * definitions can be dummies: their sizes shouldn't matter as long as
1615 * as their types are correct; actual values are irrelevant.
1617 #define ARBITRARY_SIZE 1
1619 struct attribs attrmax, attrmin;
1621 const char *configfile;
1622 char lock[ARBITRARY_SIZE];
1623 char SAVEF[ARBITRARY_SIZE];
1625 char SAVEP[ARBITRARY_SIZE];
1628 struct tc_lcl_data tc_lcl_data;
1631 const char *hilites[CLR_MAX];
1633 char NEARDATA *hilites[CLR_MAX];
1637 const char *traps[TRAPNUM];
1639 #ifdef HANGUPHANDLING
1642 struct window_procs windowprocs;
1644 #ifdef DEFINE_OSPEED
1647 #endif /* STRICT_REF_DEF */