2 /* NetHack 3.6 lev_comp.y $NHDT-Date: 1543371691 2018/11/28 02:21:31 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.22 $ */
3 /* Copyright (c) 1989 by Jean-Christophe Collet */
4 /* NetHack may be freely redistributed. See license for details. */
7 * This file contains the Level Compiler code
8 * It may handle special mazes & special room-levels
11 /* In case we're using bison in AIX. This definition must be
12 * placed before any other C-language construct in the file
13 * excluding comments and preprocessor directives (thanks IBM
14 * for this wonderful feature...).
16 * Note: some cpps barf on this 'undefined control' (#pragma).
17 * Addition of the leading space seems to prevent barfage for now,
18 * and AIX will still see the directive.
21 #pragma alloca /* keep leading space! */
24 #define SPEC_LEV /* for USE_OLDARGS (sp_lev.h) */
29 /* many types of things are put in chars for transference to NetHack.
30 * since some systems will use signed chars, limit everybody to the
31 * same number for portability.
33 #define MAX_OF_TYPE 128
35 #define MAX_NESTED_IFS 20
36 #define MAX_SWITCH_CASES 20
39 (type *) memset((genericptr_t) alloc(sizeof (type)), 0, sizeof (type))
40 #define NewTab(type, size) (type **) alloc(sizeof (type *) * size)
41 #define Free(ptr) free((genericptr_t) ptr)
43 extern void VDECL(lc_error, (const char *, ...));
44 extern void VDECL(lc_warning, (const char *, ...));
45 extern void FDECL(yyerror, (const char *));
46 extern void FDECL(yywarning, (const char *));
47 extern int NDECL(yylex);
50 extern int FDECL(get_floor_type, (CHAR_P));
51 extern int FDECL(get_room_type, (char *));
52 extern int FDECL(get_trap_type, (char *));
53 extern int FDECL(get_monster_id, (char *,CHAR_P));
54 extern int FDECL(get_object_id, (char *,CHAR_P));
55 extern boolean FDECL(check_monster_char, (CHAR_P));
56 extern boolean FDECL(check_object_char, (CHAR_P));
57 extern char FDECL(what_map_char, (CHAR_P));
58 extern void FDECL(scan_map, (char *, sp_lev *));
59 extern void FDECL(add_opcode, (sp_lev *, int, genericptr_t));
60 extern genericptr_t FDECL(get_last_opcode_data1, (sp_lev *, int));
61 extern genericptr_t FDECL(get_last_opcode_data2, (sp_lev *, int, int));
62 extern boolean FDECL(check_subrooms, (sp_lev *));
63 extern boolean FDECL(write_level_file, (char *,sp_lev *));
64 extern struct opvar *FDECL(set_opvar_int, (struct opvar *, long));
65 extern void VDECL(add_opvars, (sp_lev *, const char *, ...));
66 extern void FDECL(start_level_def, (sp_lev * *, char *));
68 extern struct lc_funcdefs *FDECL(funcdef_new, (long,char *));
69 extern void FDECL(funcdef_free_all, (struct lc_funcdefs *));
70 extern struct lc_funcdefs *FDECL(funcdef_defined, (struct lc_funcdefs *,
72 extern char *FDECL(funcdef_paramtypes, (struct lc_funcdefs *));
73 extern char *FDECL(decode_parm_str, (char *));
75 extern struct lc_vardefs *FDECL(vardef_new, (long,char *));
76 extern void FDECL(vardef_free_all, (struct lc_vardefs *));
77 extern struct lc_vardefs *FDECL(vardef_defined, (struct lc_vardefs *,
80 extern void NDECL(break_stmt_start);
81 extern void FDECL(break_stmt_end, (sp_lev *));
82 extern void FDECL(break_stmt_new, (sp_lev *, long));
84 extern void FDECL(splev_add_from, (sp_lev *, sp_lev *));
86 extern void FDECL(check_vardef_type, (struct lc_vardefs *, char *, long));
87 extern void FDECL(vardef_used, (struct lc_vardefs *, char *));
88 extern struct lc_vardefs *FDECL(add_vardef_type, (struct lc_vardefs *,
91 extern int FDECL(reverse_jmp_opcode, (int));
102 static struct forloopdef forloop_list[MAX_NESTED_IFS];
103 static short n_forloops = 0;
106 sp_lev *splev = NULL;
108 static struct opvar *if_list[MAX_NESTED_IFS];
110 static short n_if_list = 0;
112 unsigned int max_x_map, max_y_map;
113 int obj_containment = 0;
115 int in_container_obj = 0;
117 /* integer value is possibly an inconstant value (eg. dice notation
119 int is_inconstant_number = 0;
121 int in_switch_statement = 0;
122 static struct opvar *switch_check_jump = NULL;
123 static struct opvar *switch_default_case = NULL;
124 static struct opvar *switch_case_list[MAX_SWITCH_CASES];
125 static long switch_case_value[MAX_SWITCH_CASES];
126 int n_switch_case_list = 0;
128 int allow_break_statements = 0;
129 struct lc_breakdef *break_list = NULL;
131 extern struct lc_vardefs *vardefs; /* variable definitions */
134 struct lc_vardefs *function_tmp_var_defs = NULL;
135 extern struct lc_funcdefs *function_definitions;
136 struct lc_funcdefs *curr_function = NULL;
137 struct lc_funcdefs_parm * curr_function_param = NULL;
138 int in_function_definition = 0;
139 sp_lev *function_splev_backup = NULL;
141 extern int fatal_error;
142 extern int got_errors;
143 extern int line_number;
144 extern const char *fname;
146 extern char curr_token[512];
189 %token <i> CHAR INTEGER BOOLEAN PERCENT SPERCENT
190 %token <i> MINUS_INTEGER PLUS_INTEGER
191 %token <i> MAZE_GRID_ID SOLID_FILL_ID MINES_ID ROGUELEV_ID
192 %token <i> MESSAGE_ID MAZE_ID LEVEL_ID LEV_INIT_ID GEOMETRY_ID NOMAP_ID
193 %token <i> OBJECT_ID COBJECT_ID MONSTER_ID TRAP_ID DOOR_ID DRAWBRIDGE_ID
194 %token <i> object_ID monster_ID terrain_ID
195 %token <i> MAZEWALK_ID WALLIFY_ID REGION_ID FILLING IRREGULAR JOINED
196 %token <i> ALTAR_ID LADDER_ID STAIR_ID NON_DIGGABLE_ID NON_PASSWALL_ID ROOM_ID
197 %token <i> PORTAL_ID TELEPRT_ID BRANCH_ID LEV MINERALIZE_ID
198 %token <i> CORRIDOR_ID GOLD_ID ENGRAVING_ID FOUNTAIN_ID POOL_ID SINK_ID NONE
199 %token <i> RAND_CORRIDOR_ID DOOR_STATE LIGHT_STATE CURSE_TYPE ENGRAVING_TYPE
200 %token <i> DIRECTION RANDOM_TYPE RANDOM_TYPE_BRACKET A_REGISTER
201 %token <i> ALIGNMENT LEFT_OR_RIGHT CENTER TOP_OR_BOT ALTAR_TYPE UP_OR_DOWN
202 %token <i> SUBROOM_ID NAME_ID FLAGS_ID FLAG_TYPE MON_ATTITUDE MON_ALERTNESS
203 %token <i> MON_APPEARANCE ROOMDOOR_ID IF_ID ELSE_ID
204 %token <i> TERRAIN_ID HORIZ_OR_VERT REPLACE_TERRAIN_ID
205 %token <i> EXIT_ID SHUFFLE_ID
206 %token <i> QUANTITY_ID BURIED_ID LOOP_ID
207 %token <i> FOR_ID TO_ID
208 %token <i> SWITCH_ID CASE_ID BREAK_ID DEFAULT_ID
209 %token <i> ERODED_ID TRAPPED_STATE RECHARGED_ID INVIS_ID GREASED_ID
210 %token <i> FEMALE_ID CANCELLED_ID REVIVED_ID AVENGE_ID FLEEING_ID BLINDED_ID
211 %token <i> PARALYZED_ID STUNNED_ID CONFUSED_ID SEENTRAPS_ID ALL_ID
212 %token <i> MONTYPE_ID
213 %token <i> GRAVE_ID ERODEPROOF_ID
214 %token <i> FUNCTION_ID
215 %token <i> MSG_OUTPUT_TYPE
216 %token <i> COMPARE_TYPE
217 %token <i> UNKNOWN_TYPE
218 %token <i> rect_ID fillrect_ID line_ID randline_ID grow_ID
219 %token <i> selection_ID flood_ID
220 %token <i> rndcoord_ID circle_ID ellipse_ID filter_ID complement_ID
221 %token <i> gradient_ID GRADIENT_TYPE LIMITED HUMIDITY_TYPE
222 %token <i> ',' ':' '(' ')' '[' ']' '{' '}'
223 %token <map> STRING MAP_ID
224 %token <map> NQSTRING VARSTRING
225 %token <map> CFUNC CFUNC_INT CFUNC_STR CFUNC_COORD CFUNC_REGION
226 %token <map> VARSTRING_INT VARSTRING_INT_ARRAY
227 %token <map> VARSTRING_STRING VARSTRING_STRING_ARRAY
228 %token <map> VARSTRING_VAR VARSTRING_VAR_ARRAY
229 %token <map> VARSTRING_COORD VARSTRING_COORD_ARRAY
230 %token <map> VARSTRING_REGION VARSTRING_REGION_ARRAY
231 %token <map> VARSTRING_MAPCHAR VARSTRING_MAPCHAR_ARRAY
232 %token <map> VARSTRING_MONST VARSTRING_MONST_ARRAY
233 %token <map> VARSTRING_OBJ VARSTRING_OBJ_ARRAY
234 %token <map> VARSTRING_SEL VARSTRING_SEL_ARRAY
235 %token <meth> METHOD_INT METHOD_INT_ARRAY
236 %token <meth> METHOD_STRING METHOD_STRING_ARRAY
237 %token <meth> METHOD_VAR METHOD_VAR_ARRAY
238 %token <meth> METHOD_COORD METHOD_COORD_ARRAY
239 %token <meth> METHOD_REGION METHOD_REGION_ARRAY
240 %token <meth> METHOD_MAPCHAR METHOD_MAPCHAR_ARRAY
241 %token <meth> METHOD_MONST METHOD_MONST_ARRAY
242 %token <meth> METHOD_OBJ METHOD_OBJ_ARRAY
243 %token <meth> METHOD_SEL METHOD_SEL_ARRAY
245 %type <i> h_justif v_justif trap_name room_type door_state light_state
246 %type <i> alignment altar_type a_register roomfill door_pos
247 %type <i> alignment_prfx
248 %type <i> door_wall walled secret
249 %type <i> dir_list teleprt_detail
250 %type <i> object_infos object_info monster_infos monster_info
251 %type <i> levstatements stmt_block region_detail_end
252 %type <i> engraving_type flag_list roomregionflag roomregionflags
253 %type <i> optroomregionflags
254 %type <i> humidity_flags
255 %type <i> comparestmt encodecoord encoderegion mapchar
256 %type <i> seen_trap_mask
257 %type <i> encodemonster encodeobj encodeobj_list
258 %type <i> integer_list string_list encodecoord_list encoderegion_list
259 %type <i> mapchar_list encodemonster_list
260 %type <i> opt_percent opt_fillchar
261 %type <i> all_integers
262 %type <i> ter_selection ter_selection_x
263 %type <i> func_param_type
264 %type <i> objectid monsterid terrainid
265 %type <i> opt_coord_or_var opt_limited
267 %type <map> level_def
268 %type <map> any_var any_var_array any_var_or_arr any_var_or_unk
269 %type <map> func_call_params_list func_call_param_list
270 %type <i> func_call_param_part
271 %type <corpos> corr_spec
272 %type <lregn> region lev_region
273 %type <crd> room_pos subroom_pos room_align
274 %type <sze> room_size
275 %type <terr> terrain_type
289 level : level_def flags levstatements
291 if (fatal_error > 0) {
292 (void) fprintf(stderr,
293 "%s: %d errors detected for level \"%s\". No output created!\n",
294 fname, fatal_error, $1);
297 } else if (!got_errors) {
298 if (!write_level_file($1, splev)) {
299 lc_error("Can't write output file for '%s'!",
307 vardef_free_all(vardefs);
312 level_def : LEVEL_ID ':' STRING
314 start_level_def(&splev, $3);
317 | MAZE_ID ':' STRING ',' mazefiller
319 start_level_def(&splev, $3);
321 add_opvars(splev, "iiiiiiiio",
322 VA_PASS9(LVLINIT_MAZEGRID, HWALL, 0,0,
323 0,0,0,0, SPO_INITLEVEL));
325 int bg = (int) what_map_char((char) $5);
327 add_opvars(splev, "iiiiiiiio",
328 VA_PASS9(LVLINIT_SOLIDFILL, bg, 0,0,
329 0,0,0,0, SPO_INITLEVEL));
331 add_opvars(splev, "io",
332 VA_PASS2(MAZELEVEL, SPO_LEVEL_FLAGS));
339 mazefiller : RANDOM_TYPE
345 $$ = what_map_char((char) $1);
349 lev_init : LEV_INIT_ID ':' SOLID_FILL_ID ',' terrain_type
351 int filling = (int) $5.ter;
353 if (filling == INVALID_TYPE || filling >= MAX_TYPE)
354 lc_error("INIT_MAP: Invalid fill char type.");
355 add_opvars(splev, "iiiiiiiio",
356 VA_PASS9(LVLINIT_SOLIDFILL, filling,
358 0,0,0,0, SPO_INITLEVEL));
362 | LEV_INIT_ID ':' MAZE_GRID_ID ',' CHAR
364 int filling = (int) what_map_char((char) $5);
366 if (filling == INVALID_TYPE || filling >= MAX_TYPE)
367 lc_error("INIT_MAP: Invalid fill char type.");
368 add_opvars(splev, "iiiiiiiio",
369 VA_PASS9(LVLINIT_MAZEGRID, filling, 0,0,
370 0,0,0,0, SPO_INITLEVEL));
374 | LEV_INIT_ID ':' ROGUELEV_ID
376 add_opvars(splev, "iiiiiiiio",
377 VA_PASS9(LVLINIT_ROGUE,0,0,0,
378 0,0,0,0, SPO_INITLEVEL));
380 | LEV_INIT_ID ':' MINES_ID ',' CHAR ',' CHAR ',' BOOLEAN ',' BOOLEAN ',' light_state ',' walled opt_fillchar
382 int fg = (int) what_map_char((char) $5),
383 bg = (int) what_map_char((char) $7);
384 int smoothed = (int) $9,
390 if (fg == INVALID_TYPE || fg >= MAX_TYPE)
391 lc_error("INIT_MAP: Invalid foreground type.");
392 if (bg == INVALID_TYPE || bg >= MAX_TYPE)
393 lc_error("INIT_MAP: Invalid background type.");
394 if (joined && fg != CORR && fg != ROOM)
395 lc_error("INIT_MAP: Invalid foreground type for joined map.");
397 if (filling == INVALID_TYPE)
398 lc_error("INIT_MAP: Invalid fill char type.");
400 add_opvars(splev, "iiiiiiiio",
401 VA_PASS9(LVLINIT_MINES, filling, walled, lit,
402 joined, smoothed, bg, fg,
409 opt_limited : /* nothing */
419 opt_coord_or_var : /* nothing */
421 add_opvars(splev, "o", VA_PASS1(SPO_COPY));
430 opt_fillchar : /* nothing */
436 $$ = what_map_char((char) $2);
445 flags : /* nothing */
447 add_opvars(splev, "io", VA_PASS2(0, SPO_LEVEL_FLAGS));
449 | FLAGS_ID ':' flag_list
451 add_opvars(splev, "io",
452 VA_PASS2((int) $3, SPO_LEVEL_FLAGS));
456 flag_list : FLAG_TYPE ',' flag_list
466 levstatements : /* nothing */
470 | levstatement levstatements
476 stmt_block : '{' levstatements '}'
482 levstatement : message
520 | replace_terrain_detail
528 any_var_array : VARSTRING_INT_ARRAY
529 | VARSTRING_STRING_ARRAY
530 | VARSTRING_VAR_ARRAY
531 | VARSTRING_COORD_ARRAY
532 | VARSTRING_REGION_ARRAY
533 | VARSTRING_MAPCHAR_ARRAY
534 | VARSTRING_MONST_ARRAY
535 | VARSTRING_OBJ_ARRAY
536 | VARSTRING_SEL_ARRAY
539 any_var : VARSTRING_INT
550 any_var_or_arr : any_var_array
555 any_var_or_unk : VARSTRING
559 shuffle_detail : SHUFFLE_ID ':' any_var_array
561 struct lc_vardefs *vd;
563 if ((vd = vardef_defined(vardefs, $3, 1))) {
564 if (!(vd->var_type & SPOVAR_ARRAY))
565 lc_error("Trying to shuffle non-array variable '%s'",
568 lc_error("Trying to shuffle undefined variable '%s'",
570 add_opvars(splev, "so", VA_PASS2($3, SPO_SHUFFLE_ARRAY));
575 variable_define : any_var_or_arr '=' math_expr_var
577 vardefs = add_vardef_type(vardefs, $1, SPOVAR_INT);
578 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
581 | any_var_or_arr '=' selection_ID ':' ter_selection
583 vardefs = add_vardef_type(vardefs, $1, SPOVAR_SEL);
584 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
587 | any_var_or_arr '=' string_expr
589 vardefs = add_vardef_type(vardefs, $1, SPOVAR_STRING);
590 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
593 | any_var_or_arr '=' terrainid ':' mapchar_or_var
595 vardefs = add_vardef_type(vardefs, $1, SPOVAR_MAPCHAR);
596 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
599 | any_var_or_arr '=' monsterid ':' monster_or_var
601 vardefs = add_vardef_type(vardefs, $1, SPOVAR_MONST);
602 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
605 | any_var_or_arr '=' objectid ':' object_or_var
607 vardefs = add_vardef_type(vardefs, $1, SPOVAR_OBJ);
608 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
611 | any_var_or_arr '=' coord_or_var
613 vardefs = add_vardef_type(vardefs, $1, SPOVAR_COORD);
614 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
617 | any_var_or_arr '=' region_or_var
619 vardefs = add_vardef_type(vardefs, $1, SPOVAR_REGION);
620 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
623 | any_var_or_arr '=' '{' integer_list '}'
625 int n_items = (int) $4;
627 vardefs = add_vardef_type(vardefs, $1,
628 SPOVAR_INT | SPOVAR_ARRAY);
629 add_opvars(splev, "iso",
630 VA_PASS3(n_items, $1, SPO_VAR_INIT));
633 | any_var_or_arr '=' '{' encodecoord_list '}'
635 int n_items = (int) $4;
637 vardefs = add_vardef_type(vardefs, $1,
638 SPOVAR_COORD | SPOVAR_ARRAY);
639 add_opvars(splev, "iso",
640 VA_PASS3(n_items, $1, SPO_VAR_INIT));
643 | any_var_or_arr '=' '{' encoderegion_list '}'
645 int n_items = (int) $4;
647 vardefs = add_vardef_type(vardefs, $1,
648 SPOVAR_REGION | SPOVAR_ARRAY);
649 add_opvars(splev, "iso",
650 VA_PASS3(n_items, $1, SPO_VAR_INIT));
653 | any_var_or_arr '=' terrainid ':' '{' mapchar_list '}'
655 int n_items = (int) $6;
657 vardefs = add_vardef_type(vardefs, $1,
658 SPOVAR_MAPCHAR | SPOVAR_ARRAY);
659 add_opvars(splev, "iso",
660 VA_PASS3(n_items, $1, SPO_VAR_INIT));
663 | any_var_or_arr '=' monsterid ':' '{' encodemonster_list '}'
665 int n_items = (int) $6;
667 vardefs = add_vardef_type(vardefs, $1,
668 SPOVAR_MONST | SPOVAR_ARRAY);
669 add_opvars(splev, "iso",
670 VA_PASS3(n_items, $1, SPO_VAR_INIT));
673 | any_var_or_arr '=' objectid ':' '{' encodeobj_list '}'
675 int n_items = (int) $6;
677 vardefs = add_vardef_type(vardefs, $1,
678 SPOVAR_OBJ | SPOVAR_ARRAY);
679 add_opvars(splev, "iso",
680 VA_PASS3(n_items, $1, SPO_VAR_INIT));
683 | any_var_or_arr '=' '{' string_list '}'
685 int n_items = (int) $4;
687 vardefs = add_vardef_type(vardefs, $1,
688 SPOVAR_STRING | SPOVAR_ARRAY);
689 add_opvars(splev, "iso",
690 VA_PASS3(n_items, $1, SPO_VAR_INIT));
695 encodeobj_list : encodeobj
697 add_opvars(splev, "O", VA_PASS1($1));
700 | encodeobj_list ',' encodeobj
702 add_opvars(splev, "O", VA_PASS1($3));
707 encodemonster_list : encodemonster
709 add_opvars(splev, "M", VA_PASS1($1));
712 | encodemonster_list ',' encodemonster
714 add_opvars(splev, "M", VA_PASS1($3));
719 mapchar_list : mapchar
721 add_opvars(splev, "m", VA_PASS1($1));
724 | mapchar_list ',' mapchar
726 add_opvars(splev, "m", VA_PASS1($3));
731 encoderegion_list : encoderegion
735 | encoderegion_list ',' encoderegion
741 encodecoord_list : encodecoord
743 add_opvars(splev, "c", VA_PASS1($1));
746 | encodecoord_list ',' encodecoord
748 add_opvars(splev, "c", VA_PASS1($3));
753 integer_list : math_expr_var
757 | integer_list ',' math_expr_var
763 string_list : string_expr
767 | string_list ',' string_expr
773 function_define : FUNCTION_ID NQSTRING '('
775 struct lc_funcdefs *funcdef;
777 if (in_function_definition)
778 lc_error("Recursively defined functions not allowed (function %s).", $2);
780 in_function_definition++;
782 if (funcdef_defined(function_definitions, $2, 1))
783 lc_error("Function '%s' already defined once.", $2);
785 funcdef = funcdef_new(-1, $2);
786 funcdef->next = function_definitions;
787 function_definitions = funcdef;
788 function_splev_backup = splev;
789 splev = &(funcdef->code);
791 curr_function = funcdef;
792 function_tmp_var_defs = vardefs;
801 add_opvars(splev, "io", VA_PASS2(0, SPO_RETURN));
802 splev = function_splev_backup;
803 in_function_definition--;
804 curr_function = NULL;
805 vardef_free_all(vardefs);
806 vardefs = function_tmp_var_defs;
810 function_call : NQSTRING '(' func_call_params_list ')'
812 struct lc_funcdefs *tmpfunc;
814 tmpfunc = funcdef_defined(function_definitions, $1, 1);
817 int nparams = (int) strlen($3);
818 char *fparamstr = funcdef_paramtypes(tmpfunc);
820 if (strcmp($3, fparamstr)) {
821 char *tmps = strdup(decode_parm_str(fparamstr));
823 lc_error("Function '%s' requires params '%s', got '%s' instead.",
824 $1, tmps, decode_parm_str($3));
829 if (!(tmpfunc->n_called)) {
830 /* we haven't called the function yet, so insert it in the code */
831 struct opvar *jmp = New(struct opvar);
833 set_opvar_int(jmp, splev->n_opcodes+1);
834 add_opcode(splev, SPO_PUSH, jmp);
835 /* we must jump past it first, then CALL it, due to RETURN. */
836 add_opcode(splev, SPO_JMP, NULL);
838 tmpfunc->addr = splev->n_opcodes;
840 { /* init function parameter variables */
841 struct lc_funcdefs_parm *tfp = tmpfunc->params;
843 add_opvars(splev, "iso",
844 VA_PASS3(0, tfp->name,
850 splev_add_from(splev, &(tmpfunc->code));
852 splev->n_opcodes - jmp->vardata.l);
854 l = (int) (tmpfunc->addr - splev->n_opcodes - 2);
855 add_opvars(splev, "iio",
856 VA_PASS3(nparams, l, SPO_CALL));
859 lc_error("Function '%s' not defined.", $1);
865 exitstatement : EXIT_ID
867 add_opcode(splev, SPO_EXIT, NULL);
871 opt_percent : /* nothing */
881 comparestmt : PERCENT
884 add_opvars(splev, "iio",
885 VA_PASS3((int) $1, 100, SPO_RN2));
888 | '[' math_expr_var COMPARE_TYPE math_expr_var ']'
892 | '[' math_expr_var ']'
894 /* boolean, explicit foo != 0 */
895 add_opvars(splev, "i", VA_PASS1(0));
900 switchstatement : SWITCH_ID
902 is_inconstant_number = 0;
904 '[' integer_or_var ']'
906 struct opvar *chkjmp;
908 if (in_switch_statement > 0)
909 lc_error("Cannot nest switch-statements.");
911 in_switch_statement++;
913 n_switch_case_list = 0;
914 switch_default_case = NULL;
916 if (!is_inconstant_number)
917 add_opvars(splev, "o", VA_PASS1(SPO_RN2));
918 is_inconstant_number = 0;
920 chkjmp = New(struct opvar);
921 set_opvar_int(chkjmp, splev->n_opcodes+1);
922 switch_check_jump = chkjmp;
923 add_opcode(splev, SPO_PUSH, chkjmp);
924 add_opcode(splev, SPO_JMP, NULL);
929 struct opvar *endjump = New(struct opvar);
932 set_opvar_int(endjump, splev->n_opcodes+1);
934 add_opcode(splev, SPO_PUSH, endjump);
935 add_opcode(splev, SPO_JMP, NULL);
937 set_opvar_int(switch_check_jump,
938 splev->n_opcodes - switch_check_jump->vardata.l);
940 for (i = 0; i < n_switch_case_list; i++) {
941 add_opvars(splev, "oio",
943 switch_case_value[i], SPO_CMP));
944 set_opvar_int(switch_case_list[i],
945 switch_case_list[i]->vardata.l - splev->n_opcodes-1);
946 add_opcode(splev, SPO_PUSH, switch_case_list[i]);
947 add_opcode(splev, SPO_JE, NULL);
950 if (switch_default_case) {
951 set_opvar_int(switch_default_case,
952 switch_default_case->vardata.l - splev->n_opcodes-1);
953 add_opcode(splev, SPO_PUSH, switch_default_case);
954 add_opcode(splev, SPO_JMP, NULL);
957 set_opvar_int(endjump, splev->n_opcodes - endjump->vardata.l);
959 break_stmt_end(splev);
961 add_opcode(splev, SPO_POP, NULL); /* get rid of the value in stack */
962 in_switch_statement--;
968 switchcases : /* nothing */
969 | switchcase switchcases
972 switchcase : CASE_ID all_integers ':'
974 if (n_switch_case_list < MAX_SWITCH_CASES) {
975 struct opvar *tmppush = New(struct opvar);
977 set_opvar_int(tmppush, splev->n_opcodes);
978 switch_case_value[n_switch_case_list] = $2;
979 switch_case_list[n_switch_case_list++] = tmppush;
980 } else lc_error("Too many cases in a switch.");
987 struct opvar *tmppush = New(struct opvar);
989 if (switch_default_case)
990 lc_error("Switch default case already used.");
992 set_opvar_int(tmppush, splev->n_opcodes);
993 switch_default_case = tmppush;
1000 breakstatement : BREAK_ID
1002 if (!allow_break_statements)
1003 lc_error("Cannot use BREAK outside a statement block.");
1005 break_stmt_new(splev, splev->n_opcodes);
1010 for_to_span : '.' '.'
1014 forstmt_start : FOR_ID any_var_or_unk '=' math_expr_var for_to_span math_expr_var
1016 char buf[256], buf2[256];
1018 if (n_forloops >= MAX_NESTED_IFS) {
1019 lc_error("FOR: Too deeply nested loops.");
1020 n_forloops = MAX_NESTED_IFS - 1;
1023 /* first, define a variable for the for-loop end value */
1024 Sprintf(buf, "%s end", $2);
1025 /* the value of which is already in stack (the 2nd math_expr) */
1026 add_opvars(splev, "iso", VA_PASS3(0, buf, SPO_VAR_INIT));
1028 vardefs = add_vardef_type(vardefs, $2, SPOVAR_INT);
1029 /* define the for-loop variable. value is in stack (1st math_expr) */
1030 add_opvars(splev, "iso", VA_PASS3(0, $2, SPO_VAR_INIT));
1032 /* calculate value for the loop "step" variable */
1033 Sprintf(buf2, "%s step", $2);
1035 add_opvars(splev, "vvo",
1036 VA_PASS3(buf, $2, SPO_MATH_SUB));
1038 add_opvars(splev, "o", VA_PASS1(SPO_MATH_SIGN));
1039 /* save the sign into the step var */
1040 add_opvars(splev, "iso",
1041 VA_PASS3(0, buf2, SPO_VAR_INIT));
1043 forloop_list[n_forloops].varname = strdup($2);
1044 forloop_list[n_forloops].jmp_point = splev->n_opcodes;
1051 forstatement : forstmt_start
1059 char buf[256], buf2[256];
1062 Sprintf(buf, "%s step", forloop_list[n_forloops].varname);
1063 Sprintf(buf2, "%s end", forloop_list[n_forloops].varname);
1064 /* compare for-loop var to end value */
1065 add_opvars(splev, "vvo",
1066 VA_PASS3(forloop_list[n_forloops].varname,
1069 add_opvars(splev, "vvo",
1070 VA_PASS3(buf, forloop_list[n_forloops].varname,
1072 /* for-loop var = (for-loop var + step) */
1073 add_opvars(splev, "iso",
1074 VA_PASS3(0, forloop_list[n_forloops].varname,
1076 /* jump back if compared values were not equal */
1077 l = (int) (forloop_list[n_forloops].jmp_point
1078 - splev->n_opcodes - 1);
1079 add_opvars(splev, "io", VA_PASS2(l, SPO_JNE));
1080 Free(forloop_list[n_forloops].varname);
1081 break_stmt_end(splev);
1085 loopstatement : LOOP_ID '[' integer_or_var ']'
1087 struct opvar *tmppush = New(struct opvar);
1089 if (n_if_list >= MAX_NESTED_IFS) {
1090 lc_error("LOOP: Too deeply nested conditionals.");
1091 n_if_list = MAX_NESTED_IFS - 1;
1093 set_opvar_int(tmppush, splev->n_opcodes);
1094 if_list[n_if_list++] = tmppush;
1096 add_opvars(splev, "o", VA_PASS1(SPO_DEC));
1101 struct opvar *tmppush;
1103 add_opvars(splev, "oio", VA_PASS3(SPO_COPY, 0, SPO_CMP));
1105 tmppush = (struct opvar *) if_list[--n_if_list];
1106 set_opvar_int(tmppush,
1107 tmppush->vardata.l - splev->n_opcodes-1);
1108 add_opcode(splev, SPO_PUSH, tmppush);
1109 add_opcode(splev, SPO_JG, NULL);
1110 add_opcode(splev, SPO_POP, NULL); /* discard count */
1111 break_stmt_end(splev);
1115 chancestatement : comparestmt ':'
1117 struct opvar *tmppush2 = New(struct opvar);
1119 if (n_if_list >= MAX_NESTED_IFS) {
1120 lc_error("IF: Too deeply nested conditionals.");
1121 n_if_list = MAX_NESTED_IFS - 1;
1124 add_opcode(splev, SPO_CMP, NULL);
1126 set_opvar_int(tmppush2, splev->n_opcodes+1);
1128 if_list[n_if_list++] = tmppush2;
1130 add_opcode(splev, SPO_PUSH, tmppush2);
1132 add_opcode(splev, reverse_jmp_opcode( $1 ), NULL);
1137 if (n_if_list > 0) {
1138 struct opvar *tmppush;
1140 tmppush = (struct opvar *) if_list[--n_if_list];
1141 set_opvar_int(tmppush,
1142 splev->n_opcodes - tmppush->vardata.l);
1143 } else lc_error("IF: Huh?! No start address?");
1147 ifstatement : IF_ID comparestmt
1149 struct opvar *tmppush2 = New(struct opvar);
1151 if (n_if_list >= MAX_NESTED_IFS) {
1152 lc_error("IF: Too deeply nested conditionals.");
1153 n_if_list = MAX_NESTED_IFS - 1;
1156 add_opcode(splev, SPO_CMP, NULL);
1158 set_opvar_int(tmppush2, splev->n_opcodes+1);
1160 if_list[n_if_list++] = tmppush2;
1162 add_opcode(splev, SPO_PUSH, tmppush2);
1164 add_opcode(splev, reverse_jmp_opcode( $2 ), NULL);
1173 if_ending : stmt_block
1175 if (n_if_list > 0) {
1176 struct opvar *tmppush;
1178 tmppush = (struct opvar *) if_list[--n_if_list];
1179 set_opvar_int(tmppush,
1180 splev->n_opcodes - tmppush->vardata.l);
1181 } else lc_error("IF: Huh?! No start address?");
1185 if (n_if_list > 0) {
1186 struct opvar *tmppush = New(struct opvar);
1187 struct opvar *tmppush2;
1189 set_opvar_int(tmppush, splev->n_opcodes+1);
1190 add_opcode(splev, SPO_PUSH, tmppush);
1192 add_opcode(splev, SPO_JMP, NULL);
1194 tmppush2 = (struct opvar *) if_list[--n_if_list];
1196 set_opvar_int(tmppush2,
1197 splev->n_opcodes - tmppush2->vardata.l);
1198 if_list[n_if_list++] = tmppush;
1199 } else lc_error("IF: Huh?! No else-part address?");
1203 if (n_if_list > 0) {
1204 struct opvar *tmppush;
1205 tmppush = (struct opvar *) if_list[--n_if_list];
1206 set_opvar_int(tmppush, splev->n_opcodes - tmppush->vardata.l);
1207 } else lc_error("IF: Huh?! No end address?");
1211 message : MESSAGE_ID ':' string_expr
1213 add_opvars(splev, "o", VA_PASS1(SPO_MESSAGE));
1217 random_corridors: RAND_CORRIDOR_ID
1219 add_opvars(splev, "iiiiiio",
1220 VA_PASS7(-1, 0, -1, -1, -1, -1, SPO_CORRIDOR));
1222 | RAND_CORRIDOR_ID ':' all_integers
1224 add_opvars(splev, "iiiiiio",
1225 VA_PASS7(-1, $3, -1, -1, -1, -1, SPO_CORRIDOR));
1227 | RAND_CORRIDOR_ID ':' RANDOM_TYPE
1229 add_opvars(splev, "iiiiiio",
1230 VA_PASS7(-1, -1, -1, -1, -1, -1, SPO_CORRIDOR));
1234 corridor : CORRIDOR_ID ':' corr_spec ',' corr_spec
1236 add_opvars(splev, "iiiiiio",
1237 VA_PASS7($3.room, $3.door, $3.wall,
1238 $5.room, $5.door, $5.wall,
1241 | CORRIDOR_ID ':' corr_spec ',' all_integers
1243 add_opvars(splev, "iiiiiio",
1244 VA_PASS7($3.room, $3.door, $3.wall,
1250 corr_spec : '(' INTEGER ',' DIRECTION ',' door_pos ')'
1258 room_begin : room_type opt_percent ',' light_state
1260 if (($2 < 100) && ($1 == OROOM))
1261 lc_error("Only typed rooms can have a chance.");
1263 add_opvars(splev, "iii",
1264 VA_PASS3((long)$1, (long)$2, (long)$4));
1269 subroom_def : SUBROOM_ID ':' room_begin ',' subroom_pos ',' room_size optroomregionflags
1273 if (rflags == -1) rflags = (1 << 0);
1274 add_opvars(splev, "iiiiiiio",
1275 VA_PASS8(rflags, ERR, ERR,
1276 $5.x, $5.y, $7.width, $7.height,
1282 break_stmt_end(splev);
1283 add_opcode(splev, SPO_ENDROOM, NULL);
1287 room_def : ROOM_ID ':' room_begin ',' room_pos ',' room_align ',' room_size optroomregionflags
1291 if (rflags == -1) rflags = (1 << 0);
1292 add_opvars(splev, "iiiiiiio",
1294 $7.x, $7.y, $5.x, $5.y,
1295 $9.width, $9.height, SPO_ROOM));
1300 break_stmt_end(splev);
1301 add_opcode(splev, SPO_ENDROOM, NULL);
1305 roomfill : /* nothing */
1315 room_pos : '(' INTEGER ',' INTEGER ')'
1317 if ( $2 < 1 || $2 > 5 ||
1318 $4 < 1 || $4 > 5 ) {
1319 lc_error("Room positions should be between 1-5: (%li,%li)!", $2, $4);
1331 subroom_pos : '(' INTEGER ',' INTEGER ')'
1333 if ( $2 < 0 || $4 < 0) {
1334 lc_error("Invalid subroom position (%li,%li)!", $2, $4);
1346 room_align : '(' h_justif ',' v_justif ')'
1357 room_size : '(' INTEGER ',' INTEGER ')'
1364 $$.height = $$.width = ERR;
1368 door_detail : ROOMDOOR_ID ':' secret ',' door_state ',' door_wall ',' door_pos
1370 /* ERR means random here */
1371 if ($7 == ERR && $9 != ERR) {
1372 lc_error("If the door wall is random, so must be its pos!");
1374 add_opvars(splev, "iiiio",
1375 VA_PASS5((long)$9, (long)$5, (long)$3,
1376 (long)$7, SPO_ROOM_DOOR));
1379 | DOOR_ID ':' door_state ',' ter_selection
1381 add_opvars(splev, "io", VA_PASS2((long)$3, SPO_DOOR));
1389 door_wall : dir_list
1393 dir_list : DIRECTION
1397 | DIRECTION '|' dir_list
1407 map_definition : NOMAP_ID
1409 add_opvars(splev, "ciisiio",
1410 VA_PASS7(0, 0, 1, (char *) 0, 0, 0, SPO_MAP));
1411 max_x_map = COLNO-1;
1414 | GEOMETRY_ID ':' h_justif ',' v_justif roomfill MAP_ID
1416 add_opvars(splev, "cii",
1417 VA_PASS3(SP_COORD_PACK(($3), ($5)),
1419 scan_map($7, splev);
1422 | GEOMETRY_ID ':' coord_or_var roomfill MAP_ID
1424 add_opvars(splev, "ii", VA_PASS2(2, (int) $4));
1425 scan_map($5, splev);
1430 h_justif : LEFT_OR_RIGHT
1434 v_justif : TOP_OR_BOT
1438 monster_detail : MONSTER_ID ':' monster_desc
1440 add_opvars(splev, "io", VA_PASS2(0, SPO_MONSTER));
1442 | MONSTER_ID ':' monster_desc
1444 add_opvars(splev, "io", VA_PASS2(1, SPO_MONSTER));
1450 break_stmt_end(splev);
1452 add_opvars(splev, "o", VA_PASS1(SPO_END_MONINVENT));
1456 monster_desc : monster_or_var ',' coord_or_var monster_infos
1462 monster_infos : /* nothing */
1464 struct opvar *stopit = New(struct opvar);
1466 set_opvar_int(stopit, SP_M_V_END);
1467 add_opcode(splev, SPO_PUSH, stopit);
1470 | monster_infos ',' monster_info
1473 lc_error("MONSTER extra info defined twice.");
1478 monster_info : string_expr
1480 add_opvars(splev, "i", VA_PASS1(SP_M_V_NAME));
1485 add_opvars(splev, "ii",
1486 VA_PASS2((int) $<i>1, SP_M_V_PEACEFUL));
1491 add_opvars(splev, "ii",
1492 VA_PASS2((int) $<i>1, SP_M_V_ASLEEP));
1497 add_opvars(splev, "ii",
1498 VA_PASS2((int) $1, SP_M_V_ALIGN));
1501 | MON_APPEARANCE string_expr
1503 add_opvars(splev, "ii",
1504 VA_PASS2((int) $<i>1, SP_M_V_APPEAR));
1509 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_FEMALE));
1514 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_INVIS));
1519 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_CANCELLED));
1524 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_REVIVED));
1529 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_AVENGE));
1532 | FLEEING_ID ':' integer_or_var
1534 add_opvars(splev, "i", VA_PASS1(SP_M_V_FLEEING));
1537 | BLINDED_ID ':' integer_or_var
1539 add_opvars(splev, "i", VA_PASS1(SP_M_V_BLINDED));
1542 | PARALYZED_ID ':' integer_or_var
1544 add_opvars(splev, "i", VA_PASS1(SP_M_V_PARALYZED));
1549 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_STUNNED));
1554 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_CONFUSED));
1557 | SEENTRAPS_ID ':' seen_trap_mask
1559 add_opvars(splev, "ii",
1560 VA_PASS2((int) $3, SP_M_V_SEENTRAPS));
1565 seen_trap_mask : STRING
1567 int token = get_trap_type($1);
1569 if (token == ERR || token == 0)
1570 lc_error("Unknown trap type '%s'!", $1);
1572 $$ = (1L << (token - 1));
1578 | STRING '|' seen_trap_mask
1580 int token = get_trap_type($1);
1581 if (token == ERR || token == 0)
1582 lc_error("Unknown trap type '%s'!", $1);
1584 if ((1L << (token - 1)) & $3)
1585 lc_error("Monster seen_traps, trap '%s' listed twice.", $1);
1587 $$ = ((1L << (token - 1)) | $3);
1591 object_detail : OBJECT_ID ':' object_desc
1595 if (in_container_obj)
1596 cnt |= SP_OBJ_CONTENT;
1597 add_opvars(splev, "io", VA_PASS2(cnt, SPO_OBJECT));
1599 | COBJECT_ID ':' object_desc
1601 int cnt = SP_OBJ_CONTAINER;
1603 if (in_container_obj)
1604 cnt |= SP_OBJ_CONTENT;
1605 add_opvars(splev, "io", VA_PASS2(cnt, SPO_OBJECT));
1611 break_stmt_end(splev);
1613 add_opcode(splev, SPO_POP_CONTAINER, NULL);
1617 object_desc : object_or_var object_infos
1619 if (( $2 & 0x4000) && in_container_obj)
1620 lc_error("Object cannot have a coord when contained.");
1621 else if (!( $2 & 0x4000) && !in_container_obj)
1622 lc_error("Object needs a coord when not contained.");
1626 object_infos : /* nothing */
1628 struct opvar *stopit = New(struct opvar);
1629 set_opvar_int(stopit, SP_O_V_END);
1630 add_opcode(splev, SPO_PUSH, stopit);
1633 | object_infos ',' object_info
1636 lc_error("OBJECT extra info '%s' defined twice.", curr_token);
1641 object_info : CURSE_TYPE
1643 add_opvars(splev, "ii",
1644 VA_PASS2((int) $1, SP_O_V_CURSE));
1647 | MONTYPE_ID ':' monster_or_var
1649 add_opvars(splev, "i", VA_PASS1(SP_O_V_CORPSENM));
1654 add_opvars(splev, "i", VA_PASS1(SP_O_V_SPE));
1657 | NAME_ID ':' string_expr
1659 add_opvars(splev, "i", VA_PASS1(SP_O_V_NAME));
1662 | QUANTITY_ID ':' integer_or_var
1664 add_opvars(splev, "i", VA_PASS1(SP_O_V_QUAN));
1669 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_BURIED));
1674 add_opvars(splev, "ii", VA_PASS2((int) $1, SP_O_V_LIT));
1677 | ERODED_ID ':' integer_or_var
1679 add_opvars(splev, "i", VA_PASS1(SP_O_V_ERODED));
1684 add_opvars(splev, "ii", VA_PASS2(-1, SP_O_V_ERODED));
1689 if ($1 == D_LOCKED) {
1690 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_LOCKED));
1692 } else if ($1 == D_BROKEN) {
1693 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_BROKEN));
1696 lc_error("DOOR state can only be locked or broken.");
1700 add_opvars(splev, "ii",
1701 VA_PASS2((int) $1, SP_O_V_TRAPPED));
1704 | RECHARGED_ID ':' integer_or_var
1706 add_opvars(splev, "i", VA_PASS1(SP_O_V_RECHARGED));
1711 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_INVIS));
1716 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_GREASED));
1721 add_opvars(splev, "i", VA_PASS1(SP_O_V_COORD));
1726 trap_detail : TRAP_ID ':' trap_name ',' coord_or_var
1728 add_opvars(splev, "io", VA_PASS2((int) $3, SPO_TRAP));
1732 drawbridge_detail: DRAWBRIDGE_ID ':' coord_or_var ',' DIRECTION ',' door_state
1734 long dir, state = 0;
1736 /* convert dir from a DIRECTION to a DB_DIR */
1739 case W_NORTH: dir = DB_NORTH; break;
1740 case W_SOUTH: dir = DB_SOUTH; break;
1741 case W_EAST: dir = DB_EAST; break;
1742 case W_WEST: dir = DB_WEST; break;
1744 lc_error("Invalid drawbridge direction.");
1748 if ( $7 == D_ISOPEN )
1750 else if ( $7 == D_CLOSED )
1752 else if ( $7 == -1 )
1755 lc_error("A drawbridge can only be open, closed or random!");
1756 add_opvars(splev, "iio",
1757 VA_PASS3(state, dir, SPO_DRAWBRIDGE));
1761 mazewalk_detail : MAZEWALK_ID ':' coord_or_var ',' DIRECTION
1763 add_opvars(splev, "iiio",
1764 VA_PASS4((int) $5, 1, 0, SPO_MAZEWALK));
1766 | MAZEWALK_ID ':' coord_or_var ',' DIRECTION ',' BOOLEAN opt_fillchar
1768 add_opvars(splev, "iiio",
1769 VA_PASS4((int) $5, (int) $<i>7,
1770 (int) $8, SPO_MAZEWALK));
1774 wallify_detail : WALLIFY_ID
1776 add_opvars(splev, "rio",
1777 VA_PASS3(SP_REGION_PACK(-1,-1,-1,-1),
1780 | WALLIFY_ID ':' ter_selection
1782 add_opvars(splev, "io", VA_PASS2(1, SPO_WALLIFY));
1786 ladder_detail : LADDER_ID ':' coord_or_var ',' UP_OR_DOWN
1788 add_opvars(splev, "io",
1789 VA_PASS2((int) $<i>5, SPO_LADDER));
1793 stair_detail : STAIR_ID ':' coord_or_var ',' UP_OR_DOWN
1795 add_opvars(splev, "io",
1796 VA_PASS2((int) $<i>5, SPO_STAIR));
1800 stair_region : STAIR_ID ':' lev_region ',' lev_region ',' UP_OR_DOWN
1802 add_opvars(splev, "iiiii iiiii iiso",
1803 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
1804 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
1805 (long) (($7) ? LR_UPSTAIR : LR_DOWNSTAIR),
1806 0, (char *) 0, SPO_LEVREGION));
1810 portal_region : PORTAL_ID ':' lev_region ',' lev_region ',' STRING
1812 add_opvars(splev, "iiiii iiiii iiso",
1813 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
1814 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
1815 LR_PORTAL, 0, $7, SPO_LEVREGION));
1820 teleprt_region : TELEPRT_ID ':' lev_region ',' lev_region teleprt_detail
1824 case -1: rtyp = LR_TELE; break;
1825 case 0: rtyp = LR_DOWNTELE; break;
1826 case 1: rtyp = LR_UPTELE; break;
1828 add_opvars(splev, "iiiii iiiii iiso",
1829 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
1830 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
1831 rtyp, 0, (char *)0, SPO_LEVREGION));
1835 branch_region : BRANCH_ID ':' lev_region ',' lev_region
1837 add_opvars(splev, "iiiii iiiii iiso",
1838 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
1839 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
1840 (long) LR_BRANCH, 0,
1841 (char *) 0, SPO_LEVREGION));
1845 teleprt_detail : /* empty */
1855 fountain_detail : FOUNTAIN_ID ':' ter_selection
1857 add_opvars(splev, "o", VA_PASS1(SPO_FOUNTAIN));
1861 sink_detail : SINK_ID ':' ter_selection
1863 add_opvars(splev, "o", VA_PASS1(SPO_SINK));
1867 pool_detail : POOL_ID ':' ter_selection
1869 add_opvars(splev, "o", VA_PASS1(SPO_POOL));
1876 $$.ter = what_map_char((char) $<i>1);
1878 | '(' CHAR ',' light_state ')'
1881 $$.ter = what_map_char((char) $<i>2);
1885 replace_terrain_detail : REPLACE_TERRAIN_ID ':' region_or_var ',' mapchar_or_var ',' mapchar_or_var ',' SPERCENT
1887 add_opvars(splev, "io",
1888 VA_PASS2($9, SPO_REPLACETERRAIN));
1892 terrain_detail : TERRAIN_ID ':' ter_selection ',' mapchar_or_var
1894 add_opvars(splev, "o", VA_PASS1(SPO_TERRAIN));
1898 diggable_detail : NON_DIGGABLE_ID ':' region_or_var
1900 add_opvars(splev, "o", VA_PASS1(SPO_NON_DIGGABLE));
1904 passwall_detail : NON_PASSWALL_ID ':' region_or_var
1906 add_opvars(splev, "o", VA_PASS1(SPO_NON_PASSWALL));
1910 region_detail : REGION_ID ':' region_or_var ',' light_state ',' room_type optroomregionflags
1916 if (rflags == -1) rflags = (1 << 0);
1917 if (!(rflags & 1)) rt += MAXRTYPE+1;
1918 irr = ((rflags & 2) != 0);
1919 add_opvars(splev, "iiio",
1920 VA_PASS4((long)$5, rt, rflags, SPO_REGION));
1921 $<i>$ = (irr || (rflags & 1) || rt != OROOM);
1926 break_stmt_end(splev);
1928 add_opcode(splev, SPO_ENDROOM, NULL);
1929 } else if ( $<i>10 )
1930 lc_error("Cannot use lev statements in non-permanent REGION");
1934 region_detail_end : /* nothing */
1944 altar_detail : ALTAR_ID ':' coord_or_var ',' alignment ',' altar_type
1946 add_opvars(splev, "iio",
1947 VA_PASS3((long)$7, (long)$5, SPO_ALTAR));
1951 grave_detail : GRAVE_ID ':' coord_or_var ',' string_expr
1953 add_opvars(splev, "io", VA_PASS2(2, SPO_GRAVE));
1955 | GRAVE_ID ':' coord_or_var ',' RANDOM_TYPE
1957 add_opvars(splev, "sio",
1958 VA_PASS3((char *)0, 1, SPO_GRAVE));
1960 | GRAVE_ID ':' coord_or_var
1962 add_opvars(splev, "sio",
1963 VA_PASS3((char *)0, 0, SPO_GRAVE));
1967 gold_detail : GOLD_ID ':' math_expr_var ',' coord_or_var
1969 add_opvars(splev, "o", VA_PASS1(SPO_GOLD));
1973 engraving_detail: ENGRAVING_ID ':' coord_or_var ',' engraving_type ',' string_expr
1975 add_opvars(splev, "io",
1976 VA_PASS2((long)$5, SPO_ENGRAVING));
1980 mineralize : MINERALIZE_ID ':' integer_or_var ',' integer_or_var ',' integer_or_var ',' integer_or_var
1982 add_opvars(splev, "o", VA_PASS1(SPO_MINERALIZE));
1986 add_opvars(splev, "iiiio",
1987 VA_PASS5(-1L, -1L, -1L, -1L, SPO_MINERALIZE));
1993 int token = get_trap_type($1);
1995 lc_error("Unknown trap type '%s'!", $1);
2004 int token = get_room_type($1);
2006 lc_warning("Unknown room type \"%s\"! Making ordinary room...", $1);
2015 optroomregionflags : /* empty */
2019 | ',' roomregionflags
2025 roomregionflags : roomregionflag
2029 | roomregionflag ',' roomregionflags
2035 /* 0 is the "default" here */
2036 roomregionflag : FILLING
2050 door_state : DOOR_STATE
2054 light_state : LIGHT_STATE
2058 alignment : ALIGNMENT
2062 $$ = - MAX_REGISTERS - 1;
2066 alignment_prfx : ALIGNMENT
2068 | A_REGISTER ':' RANDOM_TYPE
2070 $$ = - MAX_REGISTERS - 1;
2074 altar_type : ALTAR_TYPE
2078 a_register : A_REGISTER '[' INTEGER ']'
2081 lc_error("Register Index overflow!");
2087 string_or_var : STRING
2089 add_opvars(splev, "s", VA_PASS1($1));
2094 check_vardef_type(vardefs, $1, SPOVAR_STRING);
2095 vardef_used(vardefs, $1);
2096 add_opvars(splev, "v", VA_PASS1($1));
2099 | VARSTRING_STRING_ARRAY '[' math_expr_var ']'
2101 check_vardef_type(vardefs, $1,
2102 SPOVAR_STRING | SPOVAR_ARRAY);
2103 vardef_used(vardefs, $1);
2104 add_opvars(splev, "v", VA_PASS1($1));
2110 integer_or_var : math_expr_var
2116 coord_or_var : encodecoord
2118 add_opvars(splev, "c", VA_PASS1($1));
2120 | rndcoord_ID '(' ter_selection ')'
2122 add_opvars(splev, "o", VA_PASS1(SPO_SEL_RNDCOORD));
2126 check_vardef_type(vardefs, $1, SPOVAR_COORD);
2127 vardef_used(vardefs, $1);
2128 add_opvars(splev, "v", VA_PASS1($1));
2131 | VARSTRING_COORD_ARRAY '[' math_expr_var ']'
2133 check_vardef_type(vardefs, $1,
2134 SPOVAR_COORD | SPOVAR_ARRAY);
2135 vardef_used(vardefs, $1);
2136 add_opvars(splev, "v", VA_PASS1($1));
2141 encodecoord : '(' INTEGER ',' INTEGER ')'
2143 if ($2 < 0 || $4 < 0 || $2 >= COLNO || $4 >= ROWNO)
2144 lc_error("Coordinates (%li,%li) out of map range!",
2146 $$ = SP_COORD_PACK($2, $4);
2150 $$ = SP_COORD_PACK_RANDOM(0);
2152 | RANDOM_TYPE_BRACKET humidity_flags ']'
2154 $$ = SP_COORD_PACK_RANDOM($2);
2158 humidity_flags : HUMIDITY_TYPE
2162 | HUMIDITY_TYPE ',' humidity_flags
2165 lc_warning("Humidity flag used twice.");
2170 region_or_var : encoderegion
2176 check_vardef_type(vardefs, $1, SPOVAR_REGION);
2177 vardef_used(vardefs, $1);
2178 add_opvars(splev, "v", VA_PASS1($1));
2181 | VARSTRING_REGION_ARRAY '[' math_expr_var ']'
2183 check_vardef_type(vardefs, $1,
2184 SPOVAR_REGION | SPOVAR_ARRAY);
2185 vardef_used(vardefs, $1);
2186 add_opvars(splev, "v", VA_PASS1($1));
2191 encoderegion : '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
2193 long r = SP_REGION_PACK($2, $4, $6, $8);
2195 if ($2 > $6 || $4 > $8)
2196 lc_error("Region start > end: (%ld,%ld,%ld,%ld)!",
2199 add_opvars(splev, "r", VA_PASS1(r));
2204 mapchar_or_var : mapchar
2206 add_opvars(splev, "m", VA_PASS1($1));
2210 check_vardef_type(vardefs, $1, SPOVAR_MAPCHAR);
2211 vardef_used(vardefs, $1);
2212 add_opvars(splev, "v", VA_PASS1($1));
2215 | VARSTRING_MAPCHAR_ARRAY '[' math_expr_var ']'
2217 check_vardef_type(vardefs, $1,
2218 SPOVAR_MAPCHAR | SPOVAR_ARRAY);
2219 vardef_used(vardefs, $1);
2220 add_opvars(splev, "v", VA_PASS1($1));
2227 if (what_map_char((char) $1) != INVALID_TYPE)
2228 $$ = SP_MAPCHAR_PACK(what_map_char((char) $1), -2);
2230 lc_error("Unknown map char type '%c'!", $1);
2231 $$ = SP_MAPCHAR_PACK(STONE, -2);
2234 | '(' CHAR ',' light_state ')'
2236 if (what_map_char((char) $2) != INVALID_TYPE)
2237 $$ = SP_MAPCHAR_PACK(what_map_char((char) $2), $4);
2239 lc_error("Unknown map char type '%c'!", $2);
2240 $$ = SP_MAPCHAR_PACK(STONE, $4);
2245 monster_or_var : encodemonster
2247 add_opvars(splev, "M", VA_PASS1($1));
2251 check_vardef_type(vardefs, $1, SPOVAR_MONST);
2252 vardef_used(vardefs, $1);
2253 add_opvars(splev, "v", VA_PASS1($1));
2256 | VARSTRING_MONST_ARRAY '[' math_expr_var ']'
2258 check_vardef_type(vardefs, $1,
2259 SPOVAR_MONST | SPOVAR_ARRAY);
2260 vardef_used(vardefs, $1);
2261 add_opvars(splev, "v", VA_PASS1($1));
2266 encodemonster : STRING
2268 long m = get_monster_id($1, (char)0);
2270 lc_error("Unknown monster \"%s\"!", $1);
2273 $$ = SP_MONST_PACK(m,
2274 def_monsyms[(int) mons[m].mlet].sym);
2279 if (check_monster_char((char) $1))
2280 $$ = SP_MONST_PACK(-1, $1);
2282 lc_error("Unknown monster class '%c'!", $1);
2286 | '(' CHAR ',' STRING ')'
2288 long m = get_monster_id($4, (char) $2);
2290 lc_error("Unknown monster ('%c', \"%s\")!", $2, $4);
2293 $$ = SP_MONST_PACK(m, $2);
2302 object_or_var : encodeobj
2304 add_opvars(splev, "O", VA_PASS1($1));
2308 check_vardef_type(vardefs, $1, SPOVAR_OBJ);
2309 vardef_used(vardefs, $1);
2310 add_opvars(splev, "v", VA_PASS1($1));
2313 | VARSTRING_OBJ_ARRAY '[' math_expr_var ']'
2315 check_vardef_type(vardefs, $1,
2316 SPOVAR_OBJ | SPOVAR_ARRAY);
2317 vardef_used(vardefs, $1);
2318 add_opvars(splev, "v", VA_PASS1($1));
2325 long m = get_object_id($1, (char)0);
2327 lc_error("Unknown object \"%s\"!", $1);
2330 /* obj class != 0 to force generation of a specific item */
2331 $$ = SP_OBJ_PACK(m, 1);
2336 if (check_object_char((char) $1))
2337 $$ = SP_OBJ_PACK(-1, $1);
2339 lc_error("Unknown object class '%c'!", $1);
2343 | '(' CHAR ',' STRING ')'
2345 long m = get_object_id($4, (char) $2);
2347 lc_error("Unknown object ('%c', \"%s\")!", $2, $4);
2350 $$ = SP_OBJ_PACK(m, $2);
2360 string_expr : string_or_var { }
2361 | string_expr '.' string_or_var
2363 add_opvars(splev, "o", VA_PASS1(SPO_MATH_ADD));
2367 math_expr_var : INTEGER
2369 add_opvars(splev, "i", VA_PASS1($1));
2373 is_inconstant_number = 1;
2375 | '(' MINUS_INTEGER ')'
2377 add_opvars(splev, "i", VA_PASS1($2));
2381 check_vardef_type(vardefs, $1, SPOVAR_INT);
2382 vardef_used(vardefs, $1);
2383 add_opvars(splev, "v", VA_PASS1($1));
2385 is_inconstant_number = 1;
2387 | VARSTRING_INT_ARRAY '[' math_expr_var ']'
2389 check_vardef_type(vardefs, $1,
2390 SPOVAR_INT | SPOVAR_ARRAY);
2391 vardef_used(vardefs, $1);
2392 add_opvars(splev, "v", VA_PASS1($1));
2394 is_inconstant_number = 1;
2396 | math_expr_var '+' math_expr_var
2398 add_opvars(splev, "o", VA_PASS1(SPO_MATH_ADD));
2400 | math_expr_var '-' math_expr_var
2402 add_opvars(splev, "o", VA_PASS1(SPO_MATH_SUB));
2404 | math_expr_var '*' math_expr_var
2406 add_opvars(splev, "o", VA_PASS1(SPO_MATH_MUL));
2408 | math_expr_var '/' math_expr_var
2410 add_opvars(splev, "o", VA_PASS1(SPO_MATH_DIV));
2412 | math_expr_var '%' math_expr_var
2414 add_opvars(splev, "o", VA_PASS1(SPO_MATH_MOD));
2416 | '(' math_expr_var ')' { }
2419 func_param_type : CFUNC_INT
2421 if (!strcmp("int", $1) || !strcmp("integer", $1)) {
2424 lc_error("Unknown function parameter type '%s'", $1);
2428 if (!strcmp("str", $1) || !strcmp("string", $1)) {
2431 lc_error("Unknown function parameter type '%s'", $1);
2435 func_param_part : any_var_or_arr ':' func_param_type
2437 struct lc_funcdefs_parm *tmp = New(struct lc_funcdefs_parm);
2439 if (!curr_function) {
2440 lc_error("Function parameters outside function definition.");
2442 lc_error("Could not alloc function params.");
2444 long vt = SPOVAR_NULL;
2446 tmp->name = strdup($1);
2447 tmp->parmtype = (char) $3;
2448 tmp->next = curr_function->params;
2449 curr_function->params = tmp;
2450 curr_function->n_params++;
2451 switch (tmp->parmtype) {
2459 lc_error("Unknown func param conversion.");
2462 vardefs = add_vardef_type( vardefs, $1, vt);
2468 func_param_list : func_param_part
2469 | func_param_list ',' func_param_part
2472 func_params_list : /* nothing */
2476 func_call_param_part : math_expr_var
2487 func_call_param_list : func_call_param_part
2490 tmpbuf[0] = (char) $1;
2492 $$ = strdup(tmpbuf);
2494 | func_call_param_list ',' func_call_param_part
2496 long len = strlen( $1 );
2497 char *tmp = (char *) alloc(len + 2);
2498 sprintf(tmp, "%c%s", (char) $3, $1 );
2504 func_call_params_list : /* nothing */
2508 | func_call_param_list
2510 char *tmp = strdup( $1 );
2516 ter_selection_x : coord_or_var
2518 add_opvars(splev, "o", VA_PASS1(SPO_SEL_POINT));
2520 | rect_ID region_or_var
2522 add_opvars(splev, "o", VA_PASS1(SPO_SEL_RECT));
2524 | fillrect_ID region_or_var
2526 add_opvars(splev, "o", VA_PASS1(SPO_SEL_FILLRECT));
2528 | line_ID coord_or_var ',' coord_or_var
2530 add_opvars(splev, "o", VA_PASS1(SPO_SEL_LINE));
2532 | randline_ID coord_or_var ',' coord_or_var ',' math_expr_var
2534 /* randline (x1,y1),(x2,y2), roughness */
2535 add_opvars(splev, "o", VA_PASS1(SPO_SEL_RNDLINE));
2537 | grow_ID '(' ter_selection ')'
2539 add_opvars(splev, "io", VA_PASS2(W_ANY, SPO_SEL_GROW));
2541 | grow_ID '(' dir_list ',' ter_selection ')'
2543 add_opvars(splev, "io", VA_PASS2($3, SPO_SEL_GROW));
2545 | filter_ID '(' SPERCENT ',' ter_selection ')'
2547 add_opvars(splev, "iio",
2548 VA_PASS3($3, SPOFILTER_PERCENT, SPO_SEL_FILTER));
2550 | filter_ID '(' ter_selection ',' ter_selection ')'
2552 add_opvars(splev, "io",
2553 VA_PASS2(SPOFILTER_SELECTION, SPO_SEL_FILTER));
2555 | filter_ID '(' mapchar_or_var ',' ter_selection ')'
2557 add_opvars(splev, "io",
2558 VA_PASS2(SPOFILTER_MAPCHAR, SPO_SEL_FILTER));
2560 | flood_ID coord_or_var
2562 add_opvars(splev, "o", VA_PASS1(SPO_SEL_FLOOD));
2564 | circle_ID '(' coord_or_var ',' math_expr_var ')'
2566 add_opvars(splev, "oio",
2567 VA_PASS3(SPO_COPY, 1, SPO_SEL_ELLIPSE));
2569 | circle_ID '(' coord_or_var ',' math_expr_var ',' FILLING ')'
2571 add_opvars(splev, "oio",
2572 VA_PASS3(SPO_COPY, $7, SPO_SEL_ELLIPSE));
2574 | ellipse_ID '(' coord_or_var ',' math_expr_var ',' math_expr_var ')'
2576 add_opvars(splev, "io", VA_PASS2(1, SPO_SEL_ELLIPSE));
2578 | ellipse_ID '(' coord_or_var ',' math_expr_var ',' math_expr_var ',' FILLING ')'
2580 add_opvars(splev, "io", VA_PASS2($9, SPO_SEL_ELLIPSE));
2582 | gradient_ID '(' GRADIENT_TYPE ',' '(' math_expr_var '-' math_expr_var opt_limited ')' ',' coord_or_var opt_coord_or_var ')'
2584 add_opvars(splev, "iio",
2585 VA_PASS3($9, $3, SPO_SEL_GRADIENT));
2587 | complement_ID ter_selection_x
2589 add_opvars(splev, "o", VA_PASS1(SPO_SEL_COMPLEMENT));
2593 check_vardef_type(vardefs, $1, SPOVAR_SEL);
2594 vardef_used(vardefs, $1);
2595 add_opvars(splev, "v", VA_PASS1($1));
2598 | '(' ter_selection ')'
2604 ter_selection : ter_selection_x
2608 | ter_selection_x '&' ter_selection
2610 add_opvars(splev, "o", VA_PASS1(SPO_SEL_ADD));
2616 add_opvars(splev, "iio",
2617 VA_PASS3($1.num, $1.die, SPO_DICE));
2621 all_integers : MINUS_INTEGER
2626 all_ints_push : MINUS_INTEGER
2628 add_opvars(splev, "i", VA_PASS1($1));
2632 add_opvars(splev, "i", VA_PASS1($1));
2636 add_opvars(splev, "i", VA_PASS1($1));
2644 objectid : object_ID
2648 monsterid : monster_ID
2652 terrainid : terrain_ID
2656 engraving_type : ENGRAVING_TYPE
2664 | LEV '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
2666 if ($3 <= 0 || $3 >= COLNO)
2668 "Region (%ld,%ld,%ld,%ld) out of level range (x1)!",
2670 else if ($5 < 0 || $5 >= ROWNO)
2672 "Region (%ld,%ld,%ld,%ld) out of level range (y1)!",
2674 else if ($7 <= 0 || $7 >= COLNO)
2676 "Region (%ld,%ld,%ld,%ld) out of level range (x2)!",
2678 else if ($9 < 0 || $9 >= ROWNO)
2680 "Region (%ld,%ld,%ld,%ld) out of level range (y2)!",
2690 region : '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
2692 /* This series of if statements is a hack for MSC 5.1. It seems that its
2693 tiny little brain cannot compile if these are all one big if statement. */
2694 if ($2 < 0 || $2 > (int) max_x_map)
2696 "Region (%ld,%ld,%ld,%ld) out of map range (x1)!",
2698 else if ($4 < 0 || $4 > (int) max_y_map)
2700 "Region (%ld,%ld,%ld,%ld) out of map range (y1)!",
2702 else if ($6 < 0 || $6 > (int) max_x_map)
2704 "Region (%ld,%ld,%ld,%ld) out of map range (x2)!",
2706 else if ($8 < 0 || $8 > (int) max_y_map)
2708 "Region (%ld,%ld,%ld,%ld) out of map range (y2)!",