1 /* NetHack 3.6 lev_main.c $NHDT-Date: 1448074107 2015/11/21 02:48:27 $ $NHDT-Branch: master $:$NHDT-Revision: 1.43 $ */
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
*variable_definitions
= 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", 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 */
646 struct opvar
*ov
= New(struct opvar
);
647 set_opvar_int(ov
, VA_NEXT(la
, long) );
648 add_opcode(sp
, SPO_PUSH
, ov
);
651 case 'c': /* coordinate */
653 struct opvar
*ov
= New(struct opvar
);
654 set_opvar_coord(ov
, VA_NEXT(la
, long) );
655 add_opcode(sp
, SPO_PUSH
, ov
);
658 case 'r': /* region */
660 struct opvar
*ov
= New(struct opvar
);
661 set_opvar_region(ov
, VA_NEXT(la
, long) );
662 add_opcode(sp
, SPO_PUSH
, ov
);
665 case 'm': /* mapchar */
667 struct opvar
*ov
= New(struct opvar
);
668 set_opvar_mapchar(ov
, VA_NEXT(la
, long) );
669 add_opcode(sp
, SPO_PUSH
, ov
);
672 case 'M': /* monster */
674 struct opvar
*ov
= New(struct opvar
);
675 set_opvar_monst(ov
, VA_NEXT(la
, long) );
676 add_opcode(sp
, SPO_PUSH
, ov
);
679 case 'O': /* object */
681 struct opvar
*ov
= New(struct opvar
);
682 set_opvar_obj(ov
, VA_NEXT(la
, long) );
683 add_opcode(sp
, SPO_PUSH
, ov
);
686 case 's': /* string */
688 struct opvar
*ov
= New(struct opvar
);
689 set_opvar_str(ov
, VA_NEXT(lp
, const char *) );
690 add_opcode(sp
, SPO_PUSH
, ov
);
693 case 'v': /* variable */
695 struct opvar
*ov
= New(struct opvar
);
696 set_opvar_var(ov
, VA_NEXT(lp
, const char *) );
697 add_opcode(sp
, SPO_PUSH
, ov
);
700 case 'o': /* opcode */
702 long i
= VA_NEXT(la
, int);
703 if (i
< 0 || i
>= MAX_SP_OPCODES
)
704 lc_pline("add_opvars: unknown opcode '%ld'.", i
);
705 add_opcode(sp
, i
, NULL
);
709 lc_pline("add_opvars: illegal format character '%c'.", *p
);
719 allow_break_statements
++;
723 break_stmt_end(splev
)
726 struct lc_breakdef
*tmp
= break_list
;
727 struct lc_breakdef
*prv
= NULL
;
730 if (tmp
->break_depth
== allow_break_statements
) {
731 struct lc_breakdef
*nxt
= tmp
->next
;
732 set_opvar_int(tmp
->breakpoint
,
733 splev
->n_opcodes
- tmp
->breakpoint
->vardata
.l
- 1);
746 allow_break_statements
--;
750 break_stmt_new(splev
, i
)
754 struct lc_breakdef
*tmp
= New(struct lc_breakdef
);
756 tmp
->breakpoint
= New(struct opvar
);
757 tmp
->break_depth
= allow_break_statements
;
758 tmp
->next
= break_list
;
760 set_opvar_int(tmp
->breakpoint
, i
);
761 add_opcode(splev
, SPO_PUSH
, tmp
->breakpoint
);
762 add_opcode(splev
, SPO_JMP
, NULL
);
766 funcdef_new(addr
, name
)
770 struct lc_funcdefs
*f
= New(struct lc_funcdefs
);
773 lc_error("Could not alloc function definition for '%s'.", name
);
778 f
->name
= strdup(name
);
782 f
->code
.opcodes
= NULL
;
783 f
->code
.n_opcodes
= 0;
788 funcdef_free_all(fchain
)
789 struct lc_funcdefs
*fchain
;
791 struct lc_funcdefs
*tmp
= fchain
;
792 struct lc_funcdefs
*nxt
;
793 struct lc_funcdefs_parm
*tmpparam
;
798 while (tmp
->params
) {
799 tmpparam
= tmp
->params
->next
;
800 Free(tmp
->params
->name
);
801 tmp
->params
= tmpparam
;
803 /* FIXME: free tmp->code */
810 funcdef_paramtypes(f
)
811 struct lc_funcdefs
*f
;
814 struct lc_funcdefs_parm
*fp
= f
->params
;
815 char *tmp
= (char *) alloc((f
->n_params
) + 1);
820 tmp
[i
++] = fp
->parmtype
;
828 funcdef_defined(f
, name
, casesense
)
829 struct lc_funcdefs
*f
;
835 if (!strcmp(name
, f
->name
))
838 if (!case_insensitive_comp(name
, f
->name
))
847 vardef_new(typ
, name
)
851 struct lc_vardefs
*f
= New(struct lc_vardefs
);
854 lc_error("Could not alloc variable definition for '%s'.", name
);
859 f
->name
= strdup(name
);
865 vardef_free_all(fchain
)
866 struct lc_vardefs
*fchain
;
868 struct lc_vardefs
*tmp
= fchain
;
869 struct lc_vardefs
*nxt
;
872 if (be_verbose
&& (tmp
->n_used
== 0))
873 lc_warning("Unused variable '%s'", tmp
->name
);
882 vardef_defined(f
, name
, casesense
)
883 struct lc_vardefs
*f
;
889 if (!strcmp(name
, f
->name
))
892 if (!case_insensitive_comp(name
, f
->name
))
905 static char buf
[2][128];
906 const char *n
= NULL
;
907 int is_array
= (spovar
& SPOVAR_ARRAY
);
909 spovar
&= ~SPOVAR_ARRAY
;
912 lc_error("spovar2str(%ld)", spovar
);
920 case SPOVAR_VARIABLE
:
940 togl
= ((togl
+ 1) % 2);
942 Sprintf(buf
[togl
], "%s%s", n
, (is_array
? " array" : ""));
947 vardef_used(vd
, varname
)
948 struct lc_vardefs
*vd
;
951 struct lc_vardefs
*tmp
;
953 if ((tmp
= vardef_defined(vd
, varname
, 1)) != 0)
958 check_vardef_type(vd
, varname
, vartype
)
959 struct lc_vardefs
*vd
;
963 struct lc_vardefs
*tmp
;
965 if ((tmp
= vardef_defined(vd
, varname
, 1)) != 0) {
966 if (tmp
->var_type
!= vartype
)
967 lc_error("Trying to use variable '%s' as %s, when it is %s.",
968 varname
, spovar2str(vartype
), spovar2str(tmp
->var_type
));
970 lc_error("Variable '%s' not defined.", varname
);
974 add_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 redefine variable '%s' as %s, when it is %s.",
984 varname
, spovar2str(vartype
), spovar2str(tmp
->var_type
));
986 tmp
= vardef_new(vartype
, varname
);
994 reverse_jmp_opcode(opcode
)
1011 lc_error("Cannot reverse comparison jmp opcode %d.", opcode
);
1016 /* basically copied from src/sp_lev.c */
1022 struct opvar
*tmpov
= (struct opvar
*) alloc(sizeof(struct opvar
));
1024 if (!tmpov
) { /* lint suppression */
1027 /* not possible; alloc() never returns Null */
1028 panic("could not alloc opvar struct");
1031 return (struct opvar
*) 0;
1033 switch (ov
->spovartyp
) {
1036 case SPOVAR_MAPCHAR
:
1040 tmpov
->spovartyp
= ov
->spovartyp
;
1041 tmpov
->vardata
.l
= ov
->vardata
.l
;
1043 case SPOVAR_VARIABLE
:
1044 case SPOVAR_STRING
: {
1045 int len
= strlen(ov
->vardata
.str
);
1046 tmpov
->spovartyp
= ov
->spovartyp
;
1047 tmpov
->vardata
.str
= (char *) alloc(len
+ 1);
1048 (void) memcpy((genericptr_t
) tmpov
->vardata
.str
,
1049 (genericptr_t
) ov
->vardata
.str
, len
);
1050 tmpov
->vardata
.str
[len
] = '\0';
1053 lc_error("Unknown opvar_clone value type (%d)!", ov
->spovartyp
);
1058 return (struct opvar
*) 0;
1062 splev_add_from(splev
, from_splev
)
1068 if (splev
&& from_splev
)
1069 for (i
= 0; i
< from_splev
->n_opcodes
; i
++)
1070 add_opcode(splev
, from_splev
->opcodes
[i
].opcode
,
1071 opvar_clone(from_splev
->opcodes
[i
].opdat
));
1075 start_level_def(splev
, ldfname
)
1079 struct lc_funcdefs
*f
;
1081 if (index(ldfname
, '.'))
1082 lc_error("Invalid dot ('.') in level name '%s'.", ldfname
);
1083 if ((int) strlen(ldfname
) > 14)
1084 lc_error("Level names limited to 14 characters ('%s').", ldfname
);
1085 f
= function_definitions
;
1090 *splev
= (sp_lev
*) alloc(sizeof(sp_lev
));
1091 (*splev
)->n_opcodes
= 0;
1092 (*splev
)->opcodes
= NULL
;
1094 vardef_free_all(variable_definitions
);
1095 variable_definitions
= NULL
;
1099 * Find the type of floor, knowing its char representation.
1108 val
= what_map_char(c
);
1109 if (val
== INVALID_TYPE
) {
1111 yywarning("Invalid fill character in MAZE declaration");
1117 * Find the type of a room in the table, knowing its name.
1126 for (i
= 0; room_types
[i
].name
; i
++)
1127 if (!strcmp(s
, room_types
[i
].name
))
1128 return ((int) room_types
[i
].type
);
1133 * Find the type of a trap in the table, knowing its name.
1142 for (i
= 0; trap_types
[i
].name
; i
++)
1143 if (!strcmp(s
, trap_types
[i
].name
))
1144 return trap_types
[i
].type
;
1149 * Find the index of a monster in the table, knowing its name.
1152 get_monster_id(s
, c
)
1156 register int i
, class;
1159 class = c
? def_char_to_monclass(c
) : 0;
1160 if (class == MAXMCLASSES
)
1163 for (i
= LOW_PM
; i
< NUMMONS
; i
++)
1164 if (!class || class == mons
[i
].mlet
)
1165 if (!strcmp(s
, mons
[i
].mname
))
1167 /* didn't find it; lets try case insensitive search */
1168 for (i
= LOW_PM
; i
< NUMMONS
; i
++)
1169 if (!class || class == mons
[i
].mlet
)
1170 if (!case_insensitive_comp(s
, mons
[i
].mname
)) {
1172 lc_warning("Monster type \"%s\" matches \"%s\".", s
,
1180 * Find the index of an object in the table, knowing its name.
1188 const char *objname
;
1191 class = (c
> 0) ? def_char_to_objclass(c
) : 0;
1192 if (class == MAXOCLASSES
)
1195 for (i
= class ? bases
[class] : 0; i
< NUM_OBJECTS
; i
++) {
1196 if (class && objects
[i
].oc_class
!= class)
1198 objname
= obj_descr
[i
].oc_name
;
1199 if (objname
&& !strcmp(s
, objname
))
1202 for (i
= class ? bases
[class] : 0; i
< NUM_OBJECTS
; i
++) {
1203 if (class && objects
[i
].oc_class
!= class)
1205 objname
= obj_descr
[i
].oc_name
;
1206 if (objname
&& !case_insensitive_comp(s
, objname
)) {
1208 lc_warning("Object type \"%s\" matches \"%s\".", s
, objname
);
1218 int i
, class, prev_class
;
1221 for (i
= 0; i
< NUM_OBJECTS
; i
++) {
1222 class = objects
[i
].oc_class
;
1223 if (class != prev_class
) {
1231 * Is the character 'c' a valid monster class ?
1234 check_monster_char(c
)
1237 return (def_char_to_monclass(c
) != MAXMCLASSES
);
1241 * Is the character 'c' a valid object class ?
1244 check_object_char(c
)
1247 return (def_char_to_objclass(c
) != MAXOCLASSES
);
1251 * Convert .des map letter into floor type.
1274 return (CROSSWALL
); /* hack: boundary location */
1300 return (IRONBARS
); /* Fe = iron */
1302 return (MAX_TYPE
); /* "see-through" */
1304 return (INVALID_TYPE
);
1308 add_opcode(sp
, opc
, dat
)
1313 long nop
= sp
->n_opcodes
;
1316 if ((opc
< 0) || (opc
>= MAX_SP_OPCODES
))
1317 lc_error("Unknown opcode '%d'", opc
);
1319 tmp
= (_opcode
*) alloc(sizeof(_opcode
) * (nop
+ 1));
1320 if (!tmp
) { /* lint suppression */
1323 /* not possible; alloc() never returns Null */
1324 lc_error("Could not alloc opcode space");
1329 if (sp
->opcodes
&& nop
) {
1330 (void) memcpy(tmp
, sp
->opcodes
, sizeof(_opcode
) * nop
);
1335 sp
->opcodes
[nop
].opcode
= opc
;
1336 sp
->opcodes
[nop
].opdat
= dat
;
1342 * Yep! LEX gives us the map in a raw mode.
1343 * Just analyze it here.
1350 register int i
, len
;
1351 register char *s1
, *s2
;
1354 char *tmpmap
[MAP_Y_LIM
+1];
1358 /* First, strip out digits 0-9 (line numbering) */
1359 for (s1
= s2
= map
; *s1
; s1
++)
1360 if (*s1
< '0' || *s1
> '9')
1364 /* Second, find the max width of the map */
1367 s2
= index(s1
, '\n');
1369 len
= (int) (s2
- s1
);
1372 len
= (int) strlen(s1
);
1379 /* Then parse it now */
1380 while (map
&& *map
) {
1381 if (max_hig
> MAP_Y_LIM
)
1383 tmpmap
[max_hig
] = (char *) alloc(max_len
);
1384 s1
= index(map
, '\n');
1386 len
= (int) (s1
- map
);
1389 len
= (int) strlen(map
);
1392 for (i
= 0; i
< len
; i
++)
1393 if ((tmpmap
[max_hig
][i
] = what_map_char(map
[i
]))
1395 lc_warning("Invalid character '%c' @ (%d, %d) - replacing "
1397 map
[i
], max_hig
, i
);
1398 tmpmap
[max_hig
][i
] = STONE
;
1401 tmpmap
[max_hig
][i
++] = STONE
;
1406 /* Memorize boundaries */
1408 max_x_map
= max_len
- 1;
1409 max_y_map
= max_hig
- 1;
1411 if (max_len
> MAP_X_LIM
|| max_hig
> MAP_Y_LIM
) {
1412 lc_error("Map too large at (%d x %d), max is (%d x %d)", max_len
,
1413 max_hig
, MAP_X_LIM
, MAP_Y_LIM
);
1416 mbuf
= (char *) alloc(((max_hig
- 1) * max_len
) + (max_len
- 1) + 2);
1417 for (dy
= 0; dy
< max_hig
; dy
++)
1418 for (dx
= 0; dx
< max_len
; dx
++)
1419 mbuf
[(dy
* max_len
) + dx
] = (tmpmap
[dy
][dx
] + 1);
1421 mbuf
[((max_hig
- 1) * max_len
) + (max_len
- 1) + 1] = '\0';
1423 add_opvars(sp
, "siio", VA_PASS4(mbuf
, max_hig
, max_len
, SPO_MAP
));
1425 for (dy
= 0; dy
< max_hig
; dy
++)
1431 * Output some info common to all special levels.
1434 write_common_data(fd
)
1437 static struct version_info version_data
= {
1438 VERSION_NUMBER
, VERSION_FEATURES
, VERSION_SANITY1
, VERSION_SANITY2
,
1442 Write(fd
, &version_data
, sizeof version_data
);
1447 * Here we write the sp_lev structure in the specified file (fd).
1448 * Also, we have to free the memory allocated via alloc().
1451 write_maze(fd
, maze
)
1457 if (!write_common_data(fd
))
1460 Write(fd
, &(maze
->n_opcodes
), sizeof(maze
->n_opcodes
));
1462 for (i
= 0; i
< maze
->n_opcodes
; i
++) {
1463 _opcode tmpo
= maze
->opcodes
[i
];
1465 Write(fd
, &(tmpo
.opcode
), sizeof(tmpo
.opcode
));
1467 if (tmpo
.opcode
< SPO_NULL
|| tmpo
.opcode
>= MAX_SP_OPCODES
)
1468 panic("write_maze: unknown opcode (%d).", tmpo
.opcode
);
1470 if (tmpo
.opcode
== SPO_PUSH
) {
1471 genericptr_t opdat
= tmpo
.opdat
;
1473 struct opvar
*ov
= (struct opvar
*) opdat
;
1475 Write(fd
, &(ov
->spovartyp
), sizeof(ov
->spovartyp
));
1476 switch (ov
->spovartyp
) {
1481 case SPOVAR_MAPCHAR
:
1485 Write(fd
, &(ov
->vardata
.l
), sizeof(ov
->vardata
.l
));
1487 case SPOVAR_VARIABLE
:
1489 if (ov
->vardata
.str
)
1490 size
= strlen(ov
->vardata
.str
);
1493 Write(fd
, &size
, sizeof(size
));
1495 Write(fd
, ov
->vardata
.str
, size
);
1496 Free(ov
->vardata
.str
);
1500 panic("write_maze: unknown data type (%d).",
1504 panic("write_maze: PUSH with no data.");
1507 genericptr_t opdat
= tmpo
.opdat
;
1509 panic("write_maze: opcode (%d) has data.", tmpo
.opcode
);
1514 /* clear the struct for next user */
1515 Free(maze
->opcodes
);
1516 maze
->opcodes
= NULL
;
1517 /*(void) memset((genericptr_t) &maze->init_lev, 0, sizeof
1518 * maze->init_lev);*/
1524 * Open and write maze or rooms file, based on which pointer is non-null.
1525 * Return TRUE on success, FALSE on failure.
1528 write_level_file(filename
, lvl
)
1537 Strcat(lbuf
, PREFIX
);
1539 Strcat(lbuf
, filename
);
1540 Strcat(lbuf
, LEV_EXT
);
1542 #if defined(MAC) && (defined(__SC__) || defined(__MRC__))
1543 fout
= open(lbuf
, O_WRONLY
| O_CREAT
| O_BINARY
);
1545 fout
= open(lbuf
, O_WRONLY
| O_CREAT
| O_BINARY
, OMASK
);
1551 panic("write_level_file");
1554 fprintf(stdout
, "File: '%s', opcodes: %ld\n", lbuf
, lvl
->n_opcodes
);
1556 if (!write_maze(fout
, lvl
))
1565 case_insensitive_comp(s1
, s2
)
1571 for (;; s1
++, s2
++) {
1578 if (u1
== '\0' || u1
!= u2
)
1584 #ifdef STRICT_REF_DEF
1586 * Any globals declared in hack.h and descendents which aren't defined
1587 * in the modules linked into lev_comp should be defined here. These
1588 * definitions can be dummies: their sizes shouldn't matter as long as
1589 * as their types are correct; actual values are irrelevant.
1591 #define ARBITRARY_SIZE 1
1593 struct attribs attrmax
, attrmin
;
1595 const char *configfile
;
1596 char lock
[ARBITRARY_SIZE
];
1597 char SAVEF
[ARBITRARY_SIZE
];
1599 char SAVEP
[ARBITRARY_SIZE
];
1602 struct tc_lcl_data tc_lcl_data
;
1605 const char *hilites
[CLR_MAX
];
1607 char NEARDATA
*hilites
[CLR_MAX
];
1611 const char *traps
[TRAPNUM
];
1613 #ifdef HANGUPHANDLING
1616 struct window_procs windowprocs
;
1618 #ifdef DEFINE_OSPEED
1621 #endif /* STRICT_REF_DEF */