NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / util / lev_comp.y
blob3be32dc6e34b344b353dd3811755bdfde9076f72
1 %{
2 /* aNetHack 0.0.1 lev_comp.y $ANH-Date: 1455746893 2016/02/17 22:08:13 $ $ANH-Branch: master $:$ANH-Revision: 1.21 $ */
3 /* Copyright (c) 1989 by Jean-Christophe Collet */
4 /* aNetHack may be freely redistributed. See license for details. */
6 /*
7 * This file contains the Level Compiler code
8 * It may handle special mazes & special room-levels
9 */
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.
20 #ifdef _AIX
21 #pragma alloca /* keep leading space! */
22 #endif
24 #define SPEC_LEV /* for USE_OLDARGS (sp_lev.h) */
25 #include "hack.h"
26 #include "sp_lev.h"
28 #define ERR (-1)
29 /* many types of things are put in chars for transference to aNetHack.
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
38 #define New(type) \
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);
48 int NDECL(yyparse);
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 *,
71 char *, int));
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 *,
78 char *, int));
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 *,
89 char *, long));
91 extern int FDECL(reverse_jmp_opcode, (int));
93 struct coord {
94 long x;
95 long y;
98 struct forloopdef {
99 char *varname;
100 long jmp_point;
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 or a variable) */
118 int is_inconstant_number = 0;
120 int in_switch_statement = 0;
121 static struct opvar *switch_check_jump = NULL;
122 static struct opvar *switch_default_case = NULL;
123 static struct opvar *switch_case_list[MAX_SWITCH_CASES];
124 static long switch_case_value[MAX_SWITCH_CASES];
125 int n_switch_case_list = 0;
127 int allow_break_statements = 0;
128 struct lc_breakdef *break_list = NULL;
130 extern struct lc_vardefs *variable_definitions;
133 struct lc_vardefs *function_tmp_var_defs = NULL;
134 extern struct lc_funcdefs *function_definitions;
135 struct lc_funcdefs *curr_function = NULL;
136 struct lc_funcdefs_parm * curr_function_param = NULL;
137 int in_function_definition = 0;
138 sp_lev *function_splev_backup = NULL;
140 extern int fatal_error;
141 extern int got_errors;
142 extern int line_number;
143 extern const char *fname;
145 extern char curr_token[512];
149 %union
151 long i;
152 char* map;
153 struct {
154 long room;
155 long wall;
156 long door;
157 } corpos;
158 struct {
159 long area;
160 long x1;
161 long y1;
162 long x2;
163 long y2;
164 } lregn;
165 struct {
166 long x;
167 long y;
168 } crd;
169 struct {
170 long ter;
171 long lit;
172 } terr;
173 struct {
174 long height;
175 long width;
176 } sze;
177 struct {
178 long die;
179 long num;
180 } dice;
181 struct {
182 long cfunc;
183 char *varstr;
184 } meth;
188 %token <i> CHAR INTEGER BOOLEAN PERCENT SPERCENT
189 %token <i> MINUS_INTEGER PLUS_INTEGER
190 %token <i> MAZE_GRID_ID SOLID_FILL_ID MINES_ID ROGUELEV_ID
191 %token <i> MESSAGE_ID MAZE_ID LEVEL_ID LEV_INIT_ID GEOMETRY_ID NOMAP_ID
192 %token <i> OBJECT_ID COBJECT_ID MONSTER_ID TRAP_ID DOOR_ID DRAWBRIDGE_ID
193 %token <i> object_ID monster_ID terrain_ID
194 %token <i> MAZEWALK_ID WALLIFY_ID REGION_ID FILLING IRREGULAR JOINED
195 %token <i> ALTAR_ID LADDER_ID STAIR_ID NON_DIGGABLE_ID NON_PASSWALL_ID ROOM_ID
196 %token <i> PORTAL_ID TELEPRT_ID BRANCH_ID LEV MINERALIZE_ID
197 %token <i> CORRIDOR_ID GOLD_ID ENGRAVING_ID FOUNTAIN_ID POOL_ID SINK_ID NONE
198 %token <i> RAND_CORRIDOR_ID DOOR_STATE LIGHT_STATE CURSE_TYPE ENGRAVING_TYPE
199 %token <i> DIRECTION RANDOM_TYPE RANDOM_TYPE_BRACKET A_REGISTER
200 %token <i> ALIGNMENT LEFT_OR_RIGHT CENTER TOP_OR_BOT ALTAR_TYPE UP_OR_DOWN
201 %token <i> SUBROOM_ID NAME_ID FLAGS_ID FLAG_TYPE MON_ATTITUDE MON_ALERTNESS
202 %token <i> MON_APPEARANCE ROOMDOOR_ID IF_ID ELSE_ID
203 %token <i> TERRAIN_ID HORIZ_OR_VERT REPLACE_TERRAIN_ID
204 %token <i> EXIT_ID SHUFFLE_ID
205 %token <i> QUANTITY_ID BURIED_ID LOOP_ID
206 %token <i> FOR_ID TO_ID
207 %token <i> SWITCH_ID CASE_ID BREAK_ID DEFAULT_ID
208 %token <i> ERODED_ID TRAPPED_STATE RECHARGED_ID INVIS_ID GREASED_ID
209 %token <i> FEMALE_ID CANCELLED_ID REVIVED_ID AVENGE_ID FLEEING_ID BLINDED_ID
210 %token <i> PARALYZED_ID STUNNED_ID CONFUSED_ID SEENTRAPS_ID ALL_ID
211 %token <i> MONTYPE_ID
212 %token <i> GRAVE_ID ERODEPROOF_ID
213 %token <i> FUNCTION_ID
214 %token <i> MSG_OUTPUT_TYPE
215 %token <i> COMPARE_TYPE
216 %token <i> UNKNOWN_TYPE
217 %token <i> rect_ID fillrect_ID line_ID randline_ID grow_ID selection_ID flood_ID
218 %token <i> rndcoord_ID circle_ID ellipse_ID filter_ID complement_ID
219 %token <i> gradient_ID GRADIENT_TYPE LIMITED HUMIDITY_TYPE
220 %token <i> ',' ':' '(' ')' '[' ']' '{' '}'
221 %token <map> STRING MAP_ID
222 %token <map> NQSTRING VARSTRING
223 %token <map> CFUNC CFUNC_INT CFUNC_STR CFUNC_COORD CFUNC_REGION
224 %token <map> VARSTRING_INT VARSTRING_INT_ARRAY
225 %token <map> VARSTRING_STRING VARSTRING_STRING_ARRAY
226 %token <map> VARSTRING_VAR VARSTRING_VAR_ARRAY
227 %token <map> VARSTRING_COORD VARSTRING_COORD_ARRAY
228 %token <map> VARSTRING_REGION VARSTRING_REGION_ARRAY
229 %token <map> VARSTRING_MAPCHAR VARSTRING_MAPCHAR_ARRAY
230 %token <map> VARSTRING_MONST VARSTRING_MONST_ARRAY
231 %token <map> VARSTRING_OBJ VARSTRING_OBJ_ARRAY
232 %token <map> VARSTRING_SEL VARSTRING_SEL_ARRAY
233 %token <meth> METHOD_INT METHOD_INT_ARRAY
234 %token <meth> METHOD_STRING METHOD_STRING_ARRAY
235 %token <meth> METHOD_VAR METHOD_VAR_ARRAY
236 %token <meth> METHOD_COORD METHOD_COORD_ARRAY
237 %token <meth> METHOD_REGION METHOD_REGION_ARRAY
238 %token <meth> METHOD_MAPCHAR METHOD_MAPCHAR_ARRAY
239 %token <meth> METHOD_MONST METHOD_MONST_ARRAY
240 %token <meth> METHOD_OBJ METHOD_OBJ_ARRAY
241 %token <meth> METHOD_SEL METHOD_SEL_ARRAY
242 %token <dice> DICE
243 %type <i> h_justif v_justif trap_name room_type door_state light_state
244 %type <i> alignment altar_type a_register roomfill door_pos
245 %type <i> alignment_prfx
246 %type <i> door_wall walled secret
247 %type <i> dir_list teleprt_detail
248 %type <i> object_infos object_info monster_infos monster_info
249 %type <i> levstatements stmt_block region_detail_end
250 %type <i> engraving_type flag_list roomregionflag roomregionflags optroomregionflags
251 %type <i> humidity_flags
252 %type <i> comparestmt encodecoord encoderegion mapchar
253 %type <i> seen_trap_mask
254 %type <i> encodemonster encodeobj encodeobj_list
255 %type <i> integer_list string_list encodecoord_list encoderegion_list mapchar_list encodemonster_list
256 %type <i> opt_percent opt_fillchar
257 %type <i> all_integers
258 %type <i> ter_selection ter_selection_x
259 %type <i> func_param_type
260 %type <i> objectid monsterid terrainid
261 %type <i> opt_coord_or_var opt_limited
262 %type <i> mazefiller
263 %type <map> level_def
264 %type <map> any_var any_var_array any_var_or_arr any_var_or_unk
265 %type <map> func_call_params_list func_call_param_list
266 %type <i> func_call_param_part
267 %type <corpos> corr_spec
268 %type <lregn> region lev_region
269 %type <crd> room_pos subroom_pos room_align
270 %type <sze> room_size
271 %type <terr> terrain_type
272 %left '+' '-'
273 %left '*' '/' '%'
274 %start file
277 file : /* nothing */
278 | levels
281 levels : level
282 | level levels
285 level : level_def flags levstatements
287 if (fatal_error > 0) {
288 (void) fprintf(stderr,
289 "%s: %d errors detected for level \"%s\". No output created!\n",
290 fname, fatal_error, $1);
291 fatal_error = 0;
292 got_errors++;
293 } else if (!got_errors) {
294 if (!write_level_file($1, splev)) {
295 lc_error("Can't write output file for '%s'!", $1);
296 exit(EXIT_FAILURE);
299 Free($1);
300 Free(splev);
301 splev = NULL;
302 vardef_free_all(variable_definitions);
303 variable_definitions = NULL;
307 level_def : LEVEL_ID ':' STRING
309 start_level_def(&splev, $3);
310 $$ = $3;
312 | MAZE_ID ':' STRING ',' mazefiller
314 start_level_def(&splev, $3);
315 if ($5 == -1) {
316 add_opvars(splev, "iiiiiiiio",
317 VA_PASS9(LVLINIT_MAZEGRID,HWALL,0,0,
318 0,0,0,0, SPO_INITLEVEL));
319 } else {
320 long bg = what_map_char((char) $5);
321 add_opvars(splev, "iiiiiiiio",
322 VA_PASS9(LVLINIT_SOLIDFILL, bg, 0,0,
323 0,0,0,0, SPO_INITLEVEL));
325 add_opvars(splev, "io",
326 VA_PASS2(MAZELEVEL, SPO_LEVEL_FLAGS));
327 max_x_map = COLNO-1;
328 max_y_map = ROWNO;
329 $$ = $3;
333 mazefiller : RANDOM_TYPE
335 $$ = -1;
337 | CHAR
339 $$ = what_map_char((char) $1);
343 lev_init : LEV_INIT_ID ':' SOLID_FILL_ID ',' terrain_type
345 long filling = $5.ter;
346 if (filling == INVALID_TYPE || filling >= MAX_TYPE)
347 lc_error("INIT_MAP: Invalid fill char type.");
348 add_opvars(splev, "iiiiiiiio",
349 LVLINIT_SOLIDFILL,filling,0,(long)$5.lit, 0,0,0,0, SPO_INITLEVEL);
350 max_x_map = COLNO-1;
351 max_y_map = ROWNO;
353 | LEV_INIT_ID ':' MAZE_GRID_ID ',' CHAR
355 long filling = what_map_char((char) $5);
356 if (filling == INVALID_TYPE || filling >= MAX_TYPE)
357 lc_error("INIT_MAP: Invalid fill char type.");
358 add_opvars(splev, "iiiiiiiio",
359 VA_PASS9(LVLINIT_MAZEGRID,filling,0,0,
360 0,0,0,0, SPO_INITLEVEL));
361 max_x_map = COLNO-1;
362 max_y_map = ROWNO;
364 | LEV_INIT_ID ':' ROGUELEV_ID
366 add_opvars(splev, "iiiiiiiio",
367 VA_PASS9(LVLINIT_ROGUE,0,0,0,
368 0,0,0,0, SPO_INITLEVEL));
370 | LEV_INIT_ID ':' MINES_ID ',' CHAR ',' CHAR ',' BOOLEAN ',' BOOLEAN ',' light_state ',' walled opt_fillchar
372 long fg = what_map_char((char) $5);
373 long bg = what_map_char((char) $7);
374 long smoothed = $9;
375 long joined = $11;
376 long lit = $13;
377 long walled = $15;
378 long filling = $16;
379 if (fg == INVALID_TYPE || fg >= MAX_TYPE)
380 lc_error("INIT_MAP: Invalid foreground type.");
381 if (bg == INVALID_TYPE || bg >= MAX_TYPE)
382 lc_error("INIT_MAP: Invalid background type.");
383 if (joined && fg != CORR && fg != ROOM)
384 lc_error("INIT_MAP: Invalid foreground type for joined map.");
386 if (filling == INVALID_TYPE)
387 lc_error("INIT_MAP: Invalid fill char type.");
389 add_opvars(splev, "iiiiiiiio",
390 VA_PASS9(LVLINIT_MINES,filling,walled,lit,
391 joined,smoothed,bg,fg,
392 SPO_INITLEVEL));
393 max_x_map = COLNO-1;
394 max_y_map = ROWNO;
398 opt_limited : /* nothing */
400 $$ = 0;
402 | ',' LIMITED
404 $$ = $2;
408 opt_coord_or_var : /* nothing */
410 add_opvars(splev, "o", VA_PASS1(SPO_COPY));
411 $$ = 0;
413 | ',' coord_or_var
415 $$ = 1;
419 opt_fillchar : /* nothing */
421 $$ = -1;
423 | ',' CHAR
425 $$ = what_map_char((char) $2);
430 walled : BOOLEAN
431 | RANDOM_TYPE
434 flags : /* nothing */
436 add_opvars(splev, "io", VA_PASS2(0, SPO_LEVEL_FLAGS));
438 | FLAGS_ID ':' flag_list
440 add_opvars(splev, "io", VA_PASS2($3, SPO_LEVEL_FLAGS));
444 flag_list : FLAG_TYPE ',' flag_list
446 $$ = ($1 | $3);
448 | FLAG_TYPE
450 $$ = $1;
454 levstatements : /* nothing */
456 $$ = 0;
458 | levstatement levstatements
460 $$ = 1 + $2;
464 stmt_block : '{' levstatements '}'
466 $$ = $2;
470 levstatement : message
471 | lev_init
472 | altar_detail
473 | grave_detail
474 | branch_region
475 | corridor
476 | variable_define
477 | shuffle_detail
478 | diggable_detail
479 | door_detail
480 | drawbridge_detail
481 | engraving_detail
482 | mineralize
483 | fountain_detail
484 | gold_detail
485 | switchstatement
486 | forstatement
487 | loopstatement
488 | ifstatement
489 | chancestatement
490 | exitstatement
491 | breakstatement
492 | function_define
493 | function_call
494 | ladder_detail
495 | map_definition
496 | mazewalk_detail
497 | monster_detail
498 | object_detail
499 | passwall_detail
500 | pool_detail
501 | portal_region
502 | random_corridors
503 | region_detail
504 | room_def
505 | subroom_def
506 | sink_detail
507 | terrain_detail
508 | replace_terrain_detail
509 | stair_detail
510 | stair_region
511 | teleprt_region
512 | trap_detail
513 | wallify_detail
516 any_var_array : VARSTRING_INT_ARRAY
517 | VARSTRING_STRING_ARRAY
518 | VARSTRING_VAR_ARRAY
519 | VARSTRING_COORD_ARRAY
520 | VARSTRING_REGION_ARRAY
521 | VARSTRING_MAPCHAR_ARRAY
522 | VARSTRING_MONST_ARRAY
523 | VARSTRING_OBJ_ARRAY
524 | VARSTRING_SEL_ARRAY
527 any_var : VARSTRING_INT
528 | VARSTRING_STRING
529 | VARSTRING_VAR
530 | VARSTRING_COORD
531 | VARSTRING_REGION
532 | VARSTRING_MAPCHAR
533 | VARSTRING_MONST
534 | VARSTRING_OBJ
535 | VARSTRING_SEL
538 any_var_or_arr : any_var_array
539 | any_var
540 | VARSTRING
543 any_var_or_unk : VARSTRING
544 | any_var
547 shuffle_detail : SHUFFLE_ID ':' any_var_array
549 struct lc_vardefs *vd;
550 if ((vd = vardef_defined(variable_definitions, $3, 1))) {
551 if (!(vd->var_type & SPOVAR_ARRAY))
552 lc_error("Trying to shuffle non-array variable '%s'", $3);
553 } else lc_error("Trying to shuffle undefined variable '%s'", $3);
554 add_opvars(splev, "so", VA_PASS2($3, SPO_SHUFFLE_ARRAY));
555 Free($3);
559 variable_define : any_var_or_arr '=' math_expr_var
561 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_INT);
562 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
563 Free($1);
565 | any_var_or_arr '=' selection_ID ':' ter_selection
567 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_SEL);
568 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
569 Free($1);
571 | any_var_or_arr '=' string_expr
573 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_STRING);
574 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
575 Free($1);
577 | any_var_or_arr '=' terrainid ':' mapchar_or_var
579 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_MAPCHAR);
580 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
581 Free($1);
583 | any_var_or_arr '=' monsterid ':' monster_or_var
585 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_MONST);
586 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
587 Free($1);
589 | any_var_or_arr '=' objectid ':' object_or_var
591 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_OBJ);
592 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
593 Free($1);
595 | any_var_or_arr '=' coord_or_var
597 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_COORD);
598 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
599 Free($1);
601 | any_var_or_arr '=' region_or_var
603 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_REGION);
604 add_opvars(splev, "iso", VA_PASS3(0, $1, SPO_VAR_INIT));
605 Free($1);
607 | any_var_or_arr '=' '{' integer_list '}'
609 long n_items = $4;
610 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_INT|SPOVAR_ARRAY);
611 add_opvars(splev, "iso",
612 VA_PASS3(n_items, $1, SPO_VAR_INIT));
613 Free($1);
615 | any_var_or_arr '=' '{' encodecoord_list '}'
617 long n_items = $4;
618 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_COORD|SPOVAR_ARRAY);
619 add_opvars(splev, "iso",
620 VA_PASS3(n_items, $1, SPO_VAR_INIT));
621 Free($1);
623 | any_var_or_arr '=' '{' encoderegion_list '}'
625 long n_items = $4;
626 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_REGION|SPOVAR_ARRAY);
627 add_opvars(splev, "iso",
628 VA_PASS3(n_items, $1, SPO_VAR_INIT));
629 Free($1);
631 | any_var_or_arr '=' terrainid ':' '{' mapchar_list '}'
633 long n_items = $6;
634 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_MAPCHAR|SPOVAR_ARRAY);
635 add_opvars(splev, "iso",
636 VA_PASS3(n_items, $1, SPO_VAR_INIT));
637 Free($1);
639 | any_var_or_arr '=' monsterid ':' '{' encodemonster_list '}'
641 long n_items = $6;
642 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_MONST|SPOVAR_ARRAY);
643 add_opvars(splev, "iso",
644 VA_PASS3(n_items, $1, SPO_VAR_INIT));
645 Free($1);
647 | any_var_or_arr '=' objectid ':' '{' encodeobj_list '}'
649 long n_items = $6;
650 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_OBJ|SPOVAR_ARRAY);
651 add_opvars(splev, "iso",
652 VA_PASS3(n_items, $1, SPO_VAR_INIT));
653 Free($1);
655 | any_var_or_arr '=' '{' string_list '}'
657 long n_items = $4;
658 variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_STRING|SPOVAR_ARRAY);
659 add_opvars(splev, "iso",
660 VA_PASS3(n_items, $1, SPO_VAR_INIT));
661 Free($1);
665 encodeobj_list : encodeobj
667 add_opvars(splev, "O", VA_PASS1($1));
668 $$ = 1;
670 | encodeobj_list ',' encodeobj
672 add_opvars(splev, "O", VA_PASS1($3));
673 $$ = 1 + $1;
677 encodemonster_list : encodemonster
679 add_opvars(splev, "M", VA_PASS1($1));
680 $$ = 1;
682 | encodemonster_list ',' encodemonster
684 add_opvars(splev, "M", VA_PASS1($3));
685 $$ = 1 + $1;
689 mapchar_list : mapchar
691 add_opvars(splev, "m", VA_PASS1($1));
692 $$ = 1;
694 | mapchar_list ',' mapchar
696 add_opvars(splev, "m", VA_PASS1($3));
697 $$ = 1 + $1;
701 encoderegion_list : encoderegion
703 $$ = 1;
705 | encoderegion_list ',' encoderegion
707 $$ = 1 + $1;
711 encodecoord_list : encodecoord
713 add_opvars(splev, "c", VA_PASS1($1));
714 $$ = 1;
716 | encodecoord_list ',' encodecoord
718 add_opvars(splev, "c", VA_PASS1($3));
719 $$ = 1 + $1;
723 integer_list : math_expr_var
725 $$ = 1;
727 | integer_list ',' math_expr_var
729 $$ = 1 + $1;
733 string_list : string_expr
735 $$ = 1;
737 | string_list ',' string_expr
739 $$ = 1 + $1;
743 function_define : FUNCTION_ID NQSTRING '('
745 struct lc_funcdefs *funcdef;
747 if (in_function_definition)
748 lc_error("Recursively defined functions not allowed (function %s).", $2);
750 in_function_definition++;
752 if (funcdef_defined(function_definitions, $2, 1))
753 lc_error("Function '%s' already defined once.", $2);
755 funcdef = funcdef_new(-1, $2);
756 funcdef->next = function_definitions;
757 function_definitions = funcdef;
758 function_splev_backup = splev;
759 splev = &(funcdef->code);
760 Free($2);
761 curr_function = funcdef;
762 function_tmp_var_defs = variable_definitions;
763 variable_definitions = NULL;
765 func_params_list ')'
767 /* nothing */
769 stmt_block
771 add_opvars(splev, "io", VA_PASS2(0, SPO_RETURN));
772 splev = function_splev_backup;
773 in_function_definition--;
774 curr_function = NULL;
775 vardef_free_all(variable_definitions);
776 variable_definitions = function_tmp_var_defs;
780 function_call : NQSTRING '(' func_call_params_list ')'
782 struct lc_funcdefs *tmpfunc;
783 tmpfunc = funcdef_defined(function_definitions, $1, 1);
784 if (tmpfunc) {
785 long l;
786 long nparams = strlen( $3 );
787 char *fparamstr = funcdef_paramtypes(tmpfunc);
788 if (strcmp($3, fparamstr)) {
789 char *tmps = strdup(decode_parm_str(fparamstr));
790 lc_error("Function '%s' requires params '%s', got '%s' instead.", $1, tmps, decode_parm_str($3));
791 Free(tmps);
793 Free(fparamstr);
794 Free($3);
795 if (!(tmpfunc->n_called)) {
796 /* we haven't called the function yet, so insert it in the code */
797 struct opvar *jmp = New(struct opvar);
798 set_opvar_int(jmp, splev->n_opcodes+1);
799 add_opcode(splev, SPO_PUSH, jmp);
800 add_opcode(splev, SPO_JMP, NULL); /* we must jump past it first, then CALL it, due to RETURN. */
802 tmpfunc->addr = splev->n_opcodes;
804 { /* init function parameter variables */
805 struct lc_funcdefs_parm *tfp = tmpfunc->params;
806 while (tfp) {
807 add_opvars(splev, "iso",
808 VA_PASS3(0, tfp->name,
809 SPO_VAR_INIT));
810 tfp = tfp->next;
814 splev_add_from(splev, &(tmpfunc->code));
815 set_opvar_int(jmp, splev->n_opcodes - jmp->vardata.l);
817 l = tmpfunc->addr - splev->n_opcodes - 2;
818 add_opvars(splev, "iio",
819 VA_PASS3(nparams, l, SPO_CALL));
820 tmpfunc->n_called++;
821 } else {
822 lc_error("Function '%s' not defined.", $1);
824 Free($1);
828 exitstatement : EXIT_ID
830 add_opcode(splev, SPO_EXIT, NULL);
834 opt_percent : /* nothing */
836 $$ = 100;
838 | PERCENT
840 $$ = $1;
844 comparestmt : PERCENT
846 /* val > rn2(100) */
847 add_opvars(splev, "iio",
848 VA_PASS3((long)$1, 100, SPO_RN2));
849 $$ = SPO_JG;
851 | '[' math_expr_var COMPARE_TYPE math_expr_var ']'
853 $$ = $3;
855 | '[' math_expr_var ']'
857 /* boolean, explicit foo != 0 */
858 add_opvars(splev, "i", VA_PASS1(0));
859 $$ = SPO_JNE;
863 switchstatement : SWITCH_ID
865 is_inconstant_number = 0;
867 '[' integer_or_var ']'
869 struct opvar *chkjmp;
870 if (in_switch_statement > 0)
871 lc_error("Cannot nest switch-statements.");
873 in_switch_statement++;
875 n_switch_case_list = 0;
876 switch_default_case = NULL;
878 if (!is_inconstant_number)
879 add_opvars(splev, "o", VA_PASS1(SPO_RN2));
880 is_inconstant_number = 0;
882 chkjmp = New(struct opvar);
883 set_opvar_int(chkjmp, splev->n_opcodes+1);
884 switch_check_jump = chkjmp;
885 add_opcode(splev, SPO_PUSH, chkjmp);
886 add_opcode(splev, SPO_JMP, NULL);
887 break_stmt_start();
889 '{' switchcases '}'
891 struct opvar *endjump = New(struct opvar);
892 int i;
894 set_opvar_int(endjump, splev->n_opcodes+1);
896 add_opcode(splev, SPO_PUSH, endjump);
897 add_opcode(splev, SPO_JMP, NULL);
899 set_opvar_int(switch_check_jump,
900 splev->n_opcodes - switch_check_jump->vardata.l);
902 for (i = 0; i < n_switch_case_list; i++) {
903 add_opvars(splev, "oio",
904 VA_PASS3(SPO_COPY,
905 switch_case_value[i], SPO_CMP));
906 set_opvar_int(switch_case_list[i],
907 switch_case_list[i]->vardata.l - splev->n_opcodes-1);
908 add_opcode(splev, SPO_PUSH, switch_case_list[i]);
909 add_opcode(splev, SPO_JE, NULL);
912 if (switch_default_case) {
913 set_opvar_int(switch_default_case,
914 switch_default_case->vardata.l - splev->n_opcodes-1);
915 add_opcode(splev, SPO_PUSH, switch_default_case);
916 add_opcode(splev, SPO_JMP, NULL);
919 set_opvar_int(endjump, splev->n_opcodes - endjump->vardata.l);
921 break_stmt_end(splev);
923 add_opcode(splev, SPO_POP, NULL); /* get rid of the value in stack */
924 in_switch_statement--;
930 switchcases : /* nothing */
931 | switchcase switchcases
934 switchcase : CASE_ID all_integers ':'
936 if (n_switch_case_list < MAX_SWITCH_CASES) {
937 struct opvar *tmppush = New(struct opvar);
938 set_opvar_int(tmppush, splev->n_opcodes);
939 switch_case_value[n_switch_case_list] = $2;
940 switch_case_list[n_switch_case_list++] = tmppush;
941 } else lc_error("Too many cases in a switch.");
943 levstatements
946 | DEFAULT_ID ':'
948 struct opvar *tmppush = New(struct opvar);
950 if (switch_default_case)
951 lc_error("Switch default case already used.");
953 set_opvar_int(tmppush, splev->n_opcodes);
954 switch_default_case = tmppush;
956 levstatements
961 breakstatement : BREAK_ID
963 if (!allow_break_statements)
964 lc_error("Cannot use BREAK outside a statement block.");
965 else {
966 break_stmt_new(splev, splev->n_opcodes);
971 for_to_span : '.' '.'
972 | TO_ID
975 forstmt_start : FOR_ID any_var_or_unk '=' math_expr_var for_to_span math_expr_var
977 char buf[256], buf2[256];
979 if (n_forloops >= MAX_NESTED_IFS) {
980 lc_error("FOR: Too deeply nested loops.");
981 n_forloops = MAX_NESTED_IFS - 1;
984 /* first, define a variable for the for-loop end value */
985 Sprintf(buf, "%s end", $2);
986 /* the value of which is already in stack (the 2nd math_expr) */
987 add_opvars(splev, "iso", VA_PASS3(0, buf, SPO_VAR_INIT));
989 variable_definitions = add_vardef_type(variable_definitions,
990 $2, SPOVAR_INT);
991 /* define the for-loop variable. value is in stack (1st math_expr) */
992 add_opvars(splev, "iso", VA_PASS3(0, $2, SPO_VAR_INIT));
994 /* calculate value for the loop "step" variable */
995 Sprintf(buf2, "%s step", $2);
996 /* end - start */
997 add_opvars(splev, "vvo",
998 VA_PASS3(buf, $2, SPO_MATH_SUB));
999 /* sign of that */
1000 add_opvars(splev, "o", VA_PASS1(SPO_MATH_SIGN));
1001 /* save the sign into the step var */
1002 add_opvars(splev, "iso",
1003 VA_PASS3(0, buf2, SPO_VAR_INIT));
1005 forloop_list[n_forloops].varname = strdup($2);
1006 forloop_list[n_forloops].jmp_point = splev->n_opcodes;
1008 n_forloops++;
1009 Free($2);
1013 forstatement : forstmt_start
1015 /* nothing */
1016 break_stmt_start();
1018 stmt_block
1020 char buf[256], buf2[256];
1022 n_forloops--;
1023 Sprintf(buf, "%s step", forloop_list[n_forloops].varname);
1024 Sprintf(buf2, "%s end", forloop_list[n_forloops].varname);
1025 /* compare for-loop var to end value */
1026 add_opvars(splev, "vvo",
1027 VA_PASS3(forloop_list[n_forloops].varname,
1028 buf2, SPO_CMP));
1029 /* var + step */
1030 add_opvars(splev, "vvo",
1031 VA_PASS3(buf, forloop_list[n_forloops].varname,
1032 SPO_MATH_ADD));
1033 /* for-loop var = (for-loop var + step) */
1034 add_opvars(splev, "iso",
1035 VA_PASS3(0, forloop_list[n_forloops].varname,
1036 SPO_VAR_INIT));
1037 /* jump back if compared values were not equal */
1038 add_opvars(splev, "io",
1039 VA_PASS2(
1040 forloop_list[n_forloops].jmp_point - splev->n_opcodes - 1,
1041 SPO_JNE));
1042 Free(forloop_list[n_forloops].varname);
1043 break_stmt_end(splev);
1047 loopstatement : LOOP_ID '[' integer_or_var ']'
1049 struct opvar *tmppush = New(struct opvar);
1051 if (n_if_list >= MAX_NESTED_IFS) {
1052 lc_error("LOOP: Too deeply nested conditionals.");
1053 n_if_list = MAX_NESTED_IFS - 1;
1055 set_opvar_int(tmppush, splev->n_opcodes);
1056 if_list[n_if_list++] = tmppush;
1058 add_opvars(splev, "o", VA_PASS1(SPO_DEC));
1059 break_stmt_start();
1061 stmt_block
1063 struct opvar *tmppush;
1065 add_opvars(splev, "oio", VA_PASS3(SPO_COPY, 0, SPO_CMP));
1067 tmppush = (struct opvar *) if_list[--n_if_list];
1068 set_opvar_int(tmppush, tmppush->vardata.l - splev->n_opcodes-1);
1069 add_opcode(splev, SPO_PUSH, tmppush);
1070 add_opcode(splev, SPO_JG, NULL);
1071 add_opcode(splev, SPO_POP, NULL); /* get rid of the count value in stack */
1072 break_stmt_end(splev);
1076 chancestatement : comparestmt ':'
1078 struct opvar *tmppush2 = New(struct opvar);
1080 if (n_if_list >= MAX_NESTED_IFS) {
1081 lc_error("IF: Too deeply nested conditionals.");
1082 n_if_list = MAX_NESTED_IFS - 1;
1085 add_opcode(splev, SPO_CMP, NULL);
1087 set_opvar_int(tmppush2, splev->n_opcodes+1);
1089 if_list[n_if_list++] = tmppush2;
1091 add_opcode(splev, SPO_PUSH, tmppush2);
1093 add_opcode(splev, reverse_jmp_opcode( $1 ), NULL);
1096 levstatement
1098 if (n_if_list > 0) {
1099 struct opvar *tmppush;
1100 tmppush = (struct opvar *) if_list[--n_if_list];
1101 set_opvar_int(tmppush, splev->n_opcodes - tmppush->vardata.l);
1102 } else lc_error("IF: Huh?! No start address?");
1106 ifstatement : IF_ID comparestmt
1108 struct opvar *tmppush2 = New(struct opvar);
1110 if (n_if_list >= MAX_NESTED_IFS) {
1111 lc_error("IF: Too deeply nested conditionals.");
1112 n_if_list = MAX_NESTED_IFS - 1;
1115 add_opcode(splev, SPO_CMP, NULL);
1117 set_opvar_int(tmppush2, splev->n_opcodes+1);
1119 if_list[n_if_list++] = tmppush2;
1121 add_opcode(splev, SPO_PUSH, tmppush2);
1123 add_opcode(splev, reverse_jmp_opcode( $2 ), NULL);
1126 if_ending
1128 /* do nothing */
1132 if_ending : stmt_block
1134 if (n_if_list > 0) {
1135 struct opvar *tmppush;
1136 tmppush = (struct opvar *) if_list[--n_if_list];
1137 set_opvar_int(tmppush, splev->n_opcodes - tmppush->vardata.l);
1138 } else lc_error("IF: Huh?! No start address?");
1140 | stmt_block
1142 if (n_if_list > 0) {
1143 struct opvar *tmppush = New(struct opvar);
1144 struct opvar *tmppush2;
1146 set_opvar_int(tmppush, splev->n_opcodes+1);
1147 add_opcode(splev, SPO_PUSH, tmppush);
1149 add_opcode(splev, SPO_JMP, NULL);
1151 tmppush2 = (struct opvar *) if_list[--n_if_list];
1153 set_opvar_int(tmppush2, splev->n_opcodes - tmppush2->vardata.l);
1154 if_list[n_if_list++] = tmppush;
1155 } else lc_error("IF: Huh?! No else-part address?");
1157 ELSE_ID stmt_block
1159 if (n_if_list > 0) {
1160 struct opvar *tmppush;
1161 tmppush = (struct opvar *) if_list[--n_if_list];
1162 set_opvar_int(tmppush, splev->n_opcodes - tmppush->vardata.l);
1163 } else lc_error("IF: Huh?! No end address?");
1167 message : MESSAGE_ID ':' string_expr
1169 add_opvars(splev, "o", VA_PASS1(SPO_MESSAGE));
1173 random_corridors: RAND_CORRIDOR_ID
1175 add_opvars(splev, "iiiiiio",
1176 VA_PASS7(-1, 0, -1, -1, -1, -1, SPO_CORRIDOR));
1178 | RAND_CORRIDOR_ID ':' all_integers
1180 add_opvars(splev, "iiiiiio",
1181 VA_PASS7(-1, $3, -1, -1, -1, -1, SPO_CORRIDOR));
1183 | RAND_CORRIDOR_ID ':' RANDOM_TYPE
1185 add_opvars(splev, "iiiiiio",
1186 VA_PASS7(-1, -1, -1, -1, -1, -1, SPO_CORRIDOR));
1190 corridor : CORRIDOR_ID ':' corr_spec ',' corr_spec
1192 add_opvars(splev, "iiiiiio",
1193 VA_PASS7($3.room, $3.door, $3.wall,
1194 $5.room, $5.door, $5.wall,
1195 SPO_CORRIDOR));
1197 | CORRIDOR_ID ':' corr_spec ',' all_integers
1199 add_opvars(splev, "iiiiiio",
1200 VA_PASS7($3.room, $3.door, $3.wall,
1201 -1, -1, (long)$5,
1202 SPO_CORRIDOR));
1206 corr_spec : '(' INTEGER ',' DIRECTION ',' door_pos ')'
1208 $$.room = $2;
1209 $$.wall = $4;
1210 $$.door = $6;
1214 room_begin : room_type opt_percent ',' light_state
1216 if (($2 < 100) && ($1 == OROOM))
1217 lc_error("Only typed rooms can have a chance.");
1218 else {
1219 add_opvars(splev, "iii",
1220 VA_PASS3((long)$1, (long)$2, (long)$4));
1225 subroom_def : SUBROOM_ID ':' room_begin ',' subroom_pos ',' room_size optroomregionflags
1227 long rflags = $8;
1229 if (rflags == -1) rflags = (1 << 0);
1230 add_opvars(splev, "iiiiiiio",
1231 VA_PASS8(rflags, ERR, ERR,
1232 $5.x, $5.y, $7.width, $7.height,
1233 SPO_SUBROOM));
1234 break_stmt_start();
1236 stmt_block
1238 break_stmt_end(splev);
1239 add_opcode(splev, SPO_ENDROOM, NULL);
1243 room_def : ROOM_ID ':' room_begin ',' room_pos ',' room_align ',' room_size optroomregionflags
1245 long rflags = $8;
1247 if (rflags == -1) rflags = (1 << 0);
1248 add_opvars(splev, "iiiiiiio",
1249 VA_PASS8(rflags,
1250 $7.x, $7.y, $5.x, $5.y,
1251 $9.width, $9.height, SPO_ROOM));
1252 break_stmt_start();
1254 stmt_block
1256 break_stmt_end(splev);
1257 add_opcode(splev, SPO_ENDROOM, NULL);
1261 roomfill : /* nothing */
1263 $$ = 1;
1265 | ',' BOOLEAN
1267 $$ = $2;
1271 room_pos : '(' INTEGER ',' INTEGER ')'
1273 if ( $2 < 1 || $2 > 5 ||
1274 $4 < 1 || $4 > 5 ) {
1275 lc_error("Room positions should be between 1-5: (%li,%li)!", $2, $4);
1276 } else {
1277 $$.x = $2;
1278 $$.y = $4;
1281 | RANDOM_TYPE
1283 $$.x = $$.y = ERR;
1287 subroom_pos : '(' INTEGER ',' INTEGER ')'
1289 if ( $2 < 0 || $4 < 0) {
1290 lc_error("Invalid subroom position (%li,%li)!", $2, $4);
1291 } else {
1292 $$.x = $2;
1293 $$.y = $4;
1296 | RANDOM_TYPE
1298 $$.x = $$.y = ERR;
1302 room_align : '(' h_justif ',' v_justif ')'
1304 $$.x = $2;
1305 $$.y = $4;
1307 | RANDOM_TYPE
1309 $$.x = $$.y = ERR;
1313 room_size : '(' INTEGER ',' INTEGER ')'
1315 $$.width = $2;
1316 $$.height = $4;
1318 | RANDOM_TYPE
1320 $$.height = $$.width = ERR;
1324 door_detail : ROOMDOOR_ID ':' secret ',' door_state ',' door_wall ',' door_pos
1326 /* ERR means random here */
1327 if ($7 == ERR && $9 != ERR) {
1328 lc_error("If the door wall is random, so must be its pos!");
1329 } else {
1330 add_opvars(splev, "iiiio",
1331 VA_PASS5((long)$9, (long)$5, (long)$3,
1332 (long)$7, SPO_ROOM_DOOR));
1335 | DOOR_ID ':' door_state ',' ter_selection
1337 add_opvars(splev, "io", VA_PASS2((long)$3, SPO_DOOR));
1341 secret : BOOLEAN
1342 | RANDOM_TYPE
1345 door_wall : dir_list
1346 | RANDOM_TYPE
1349 dir_list : DIRECTION
1351 $$ = $1;
1353 | DIRECTION '|' dir_list
1355 $$ = ($1 | $3);
1359 door_pos : INTEGER
1360 | RANDOM_TYPE
1363 map_definition : NOMAP_ID
1365 add_opvars(splev, "ciisiio",
1366 VA_PASS7(0, 0, 1, (char *)0, 0, 0, SPO_MAP));
1367 max_x_map = COLNO-1;
1368 max_y_map = ROWNO;
1370 | GEOMETRY_ID ':' h_justif ',' v_justif roomfill MAP_ID
1372 add_opvars(splev, "cii",
1373 VA_PASS3(SP_COORD_PACK(($3),($5)),
1374 1, (long)$6));
1375 scan_map($7, splev);
1376 Free($7);
1378 | GEOMETRY_ID ':' coord_or_var roomfill MAP_ID
1380 add_opvars(splev, "ii", VA_PASS2(2, (long)$4));
1381 scan_map($5, splev);
1382 Free($5);
1386 h_justif : LEFT_OR_RIGHT
1387 | CENTER
1390 v_justif : TOP_OR_BOT
1391 | CENTER
1394 monster_detail : MONSTER_ID ':' monster_desc
1396 add_opvars(splev, "io", VA_PASS2(0, SPO_MONSTER));
1398 | MONSTER_ID ':' monster_desc
1400 add_opvars(splev, "io", VA_PASS2(1, SPO_MONSTER));
1401 in_container_obj++;
1402 break_stmt_start();
1404 stmt_block
1406 break_stmt_end(splev);
1407 in_container_obj--;
1408 add_opvars(splev, "o", VA_PASS1(SPO_END_MONINVENT));
1412 monster_desc : monster_or_var ',' coord_or_var monster_infos
1414 /* nothing */
1418 monster_infos : /* nothing */
1420 struct opvar *stopit = New(struct opvar);
1421 set_opvar_int(stopit, SP_M_V_END);
1422 add_opcode(splev, SPO_PUSH, stopit);
1423 $$ = 0x0000;
1425 | monster_infos ',' monster_info
1427 if (( $1 & $3 ))
1428 lc_error("MONSTER extra info defined twice.");
1429 $$ = ( $1 | $3 );
1433 monster_info : string_expr
1435 add_opvars(splev, "i", VA_PASS1(SP_M_V_NAME));
1436 $$ = 0x0001;
1438 | MON_ATTITUDE
1440 add_opvars(splev, "ii",
1441 VA_PASS2((long)$<i>1, SP_M_V_PEACEFUL));
1442 $$ = 0x0002;
1444 | MON_ALERTNESS
1446 add_opvars(splev, "ii",
1447 VA_PASS2((long)$<i>1, SP_M_V_ASLEEP));
1448 $$ = 0x0004;
1450 | alignment_prfx
1452 add_opvars(splev, "ii",
1453 VA_PASS2((long)$1, SP_M_V_ALIGN));
1454 $$ = 0x0008;
1456 | MON_APPEARANCE string_expr
1458 add_opvars(splev, "ii",
1459 VA_PASS2((long)$<i>1, SP_M_V_APPEAR));
1460 $$ = 0x0010;
1462 | FEMALE_ID
1464 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_FEMALE));
1465 $$ = 0x0020;
1467 | INVIS_ID
1469 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_INVIS));
1470 $$ = 0x0040;
1472 | CANCELLED_ID
1474 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_CANCELLED));
1475 $$ = 0x0080;
1477 | REVIVED_ID
1479 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_REVIVED));
1480 $$ = 0x0100;
1482 | AVENGE_ID
1484 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_AVENGE));
1485 $$ = 0x0200;
1487 | FLEEING_ID ':' integer_or_var
1489 add_opvars(splev, "i", VA_PASS1(SP_M_V_FLEEING));
1490 $$ = 0x0400;
1492 | BLINDED_ID ':' integer_or_var
1494 add_opvars(splev, "i", VA_PASS1(SP_M_V_BLINDED));
1495 $$ = 0x0800;
1497 | PARALYZED_ID ':' integer_or_var
1499 add_opvars(splev, "i", VA_PASS1(SP_M_V_PARALYZED));
1500 $$ = 0x1000;
1502 | STUNNED_ID
1504 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_STUNNED));
1505 $$ = 0x2000;
1507 | CONFUSED_ID
1509 add_opvars(splev, "ii", VA_PASS2(1, SP_M_V_CONFUSED));
1510 $$ = 0x4000;
1512 | SEENTRAPS_ID ':' seen_trap_mask
1514 add_opvars(splev, "ii",
1515 VA_PASS2((long)$3, SP_M_V_SEENTRAPS));
1516 $$ = 0x8000;
1520 seen_trap_mask : STRING
1522 int token = get_trap_type($1);
1523 if (token == ERR || token == 0)
1524 lc_error("Unknown trap type '%s'!", $1);
1525 Free($1);
1526 $$ = (1L << (token - 1));
1528 | ALL_ID
1530 $$ = (long) ~0;
1532 | STRING '|' seen_trap_mask
1534 int token = get_trap_type($1);
1535 if (token == ERR || token == 0)
1536 lc_error("Unknown trap type '%s'!", $1);
1538 if ((1L << (token - 1)) & $3)
1539 lc_error("Monster seen_traps, trap '%s' listed twice.", $1);
1540 Free($1);
1541 $$ = ((1L << (token - 1)) | $3);
1545 object_detail : OBJECT_ID ':' object_desc
1547 long cnt = 0;
1548 if (in_container_obj) cnt |= SP_OBJ_CONTENT;
1549 add_opvars(splev, "io", VA_PASS2(cnt, SPO_OBJECT));
1551 | COBJECT_ID ':' object_desc
1553 long cnt = SP_OBJ_CONTAINER;
1554 if (in_container_obj) cnt |= SP_OBJ_CONTENT;
1555 add_opvars(splev, "io", VA_PASS2(cnt, SPO_OBJECT));
1556 in_container_obj++;
1557 break_stmt_start();
1559 stmt_block
1561 break_stmt_end(splev);
1562 in_container_obj--;
1563 add_opcode(splev, SPO_POP_CONTAINER, NULL);
1567 object_desc : object_or_var object_infos
1569 if (( $2 & 0x4000) && in_container_obj)
1570 lc_error("Object cannot have a coord when contained.");
1571 else if (!( $2 & 0x4000) && !in_container_obj)
1572 lc_error("Object needs a coord when not contained.");
1576 object_infos : /* nothing */
1578 struct opvar *stopit = New(struct opvar);
1579 set_opvar_int(stopit, SP_O_V_END);
1580 add_opcode(splev, SPO_PUSH, stopit);
1581 $$ = 0x00;
1583 | object_infos ',' object_info
1585 if (( $1 & $3 ))
1586 lc_error("OBJECT extra info '%s' defined twice.", curr_token);
1587 $$ = ( $1 | $3 );
1591 object_info : CURSE_TYPE
1593 add_opvars(splev, "ii",
1594 VA_PASS2((long)$1, SP_O_V_CURSE));
1595 $$ = 0x0001;
1597 | MONTYPE_ID ':' monster_or_var
1599 add_opvars(splev, "i", VA_PASS1(SP_O_V_CORPSENM));
1600 $$ = 0x0002;
1602 | all_ints_push
1604 add_opvars(splev, "i", VA_PASS1(SP_O_V_SPE));
1605 $$ = 0x0004;
1607 | NAME_ID ':' string_expr
1609 add_opvars(splev, "i", VA_PASS1(SP_O_V_NAME));
1610 $$ = 0x0008;
1612 | QUANTITY_ID ':' integer_or_var
1614 add_opvars(splev, "i", VA_PASS1(SP_O_V_QUAN));
1615 $$ = 0x0010;
1617 | BURIED_ID
1619 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_BURIED));
1620 $$ = 0x0020;
1622 | LIGHT_STATE
1624 add_opvars(splev, "ii", VA_PASS2((long)$1, SP_O_V_LIT));
1625 $$ = 0x0040;
1627 | ERODED_ID ':' integer_or_var
1629 add_opvars(splev, "i", VA_PASS1(SP_O_V_ERODED));
1630 $$ = 0x0080;
1632 | ERODEPROOF_ID
1634 add_opvars(splev, "ii", VA_PASS2(-1, SP_O_V_ERODED));
1635 $$ = 0x0080;
1637 | DOOR_STATE
1639 if ($1 == D_LOCKED) {
1640 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_LOCKED));
1641 $$ = 0x0100;
1642 } else if ($1 == D_BROKEN) {
1643 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_BROKEN));
1644 $$ = 0x0200;
1645 } else
1646 lc_error("DOOR state can only be locked or broken.");
1648 | TRAPPED_STATE
1650 add_opvars(splev, "ii", VA_PASS2($1, SP_O_V_TRAPPED));
1651 $$ = 0x0400;
1653 | RECHARGED_ID ':' integer_or_var
1655 add_opvars(splev, "i", VA_PASS1(SP_O_V_RECHARGED));
1656 $$ = 0x0800;
1658 | INVIS_ID
1660 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_INVIS));
1661 $$ = 0x1000;
1663 | GREASED_ID
1665 add_opvars(splev, "ii", VA_PASS2(1, SP_O_V_GREASED));
1666 $$ = 0x2000;
1668 | coord_or_var
1670 add_opvars(splev, "i", VA_PASS1(SP_O_V_COORD));
1671 $$ = 0x4000;
1675 trap_detail : TRAP_ID ':' trap_name ',' coord_or_var
1677 add_opvars(splev, "io", VA_PASS2((long)$3, SPO_TRAP));
1681 drawbridge_detail: DRAWBRIDGE_ID ':' coord_or_var ',' DIRECTION ',' door_state
1683 long dir, state = 0;
1685 /* convert dir from a DIRECTION to a DB_DIR */
1686 dir = $5;
1687 switch (dir) {
1688 case W_NORTH: dir = DB_NORTH; break;
1689 case W_SOUTH: dir = DB_SOUTH; break;
1690 case W_EAST: dir = DB_EAST; break;
1691 case W_WEST: dir = DB_WEST; break;
1692 default:
1693 lc_error("Invalid drawbridge direction.");
1694 break;
1697 if ( $7 == D_ISOPEN )
1698 state = 1;
1699 else if ( $7 == D_CLOSED )
1700 state = 0;
1701 else if ( $7 == -1 )
1702 state = -1;
1703 else
1704 lc_error("A drawbridge can only be open, closed or random!");
1705 add_opvars(splev, "iio",
1706 VA_PASS3(state, dir, SPO_DRAWBRIDGE));
1710 mazewalk_detail : MAZEWALK_ID ':' coord_or_var ',' DIRECTION
1712 add_opvars(splev, "iiio",
1713 VA_PASS4((long)$5, 1, 0, SPO_MAZEWALK));
1715 | MAZEWALK_ID ':' coord_or_var ',' DIRECTION ',' BOOLEAN opt_fillchar
1717 add_opvars(splev, "iiio",
1718 VA_PASS4((long)$5, (long)$<i>7,
1719 (long)$8, SPO_MAZEWALK));
1723 wallify_detail : WALLIFY_ID
1725 add_opvars(splev, "rio",
1726 VA_PASS3(SP_REGION_PACK(-1,-1,-1,-1),
1727 0, SPO_WALLIFY));
1729 | WALLIFY_ID ':' ter_selection
1731 add_opvars(splev, "io", VA_PASS2(1, SPO_WALLIFY));
1735 ladder_detail : LADDER_ID ':' coord_or_var ',' UP_OR_DOWN
1737 add_opvars(splev, "io",
1738 VA_PASS2((long)$<i>5, SPO_LADDER));
1742 stair_detail : STAIR_ID ':' coord_or_var ',' UP_OR_DOWN
1744 add_opvars(splev, "io",
1745 VA_PASS2((long)$<i>5, SPO_STAIR));
1749 stair_region : STAIR_ID ':' lev_region ',' lev_region ',' UP_OR_DOWN
1751 add_opvars(splev, "iiiii iiiii iiso",
1752 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
1753 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
1754 (long) (($7) ? LR_UPSTAIR : LR_DOWNSTAIR),
1755 0, (char *) 0, SPO_LEVREGION));
1759 portal_region : PORTAL_ID ':' lev_region ',' lev_region ',' STRING
1761 add_opvars(splev, "iiiii iiiii iiso",
1762 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
1763 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
1764 LR_PORTAL, 0, $7, SPO_LEVREGION));
1765 Free($7);
1769 teleprt_region : TELEPRT_ID ':' lev_region ',' lev_region teleprt_detail
1771 long rtyp = 0;
1772 switch($6) {
1773 case -1: rtyp = LR_TELE; break;
1774 case 0: rtyp = LR_DOWNTELE; break;
1775 case 1: rtyp = LR_UPTELE; break;
1777 add_opvars(splev, "iiiii iiiii iiso",
1778 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
1779 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
1780 rtyp, 0, (char *)0, SPO_LEVREGION));
1784 branch_region : BRANCH_ID ':' lev_region ',' lev_region
1786 add_opvars(splev, "iiiii iiiii iiso",
1787 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
1788 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
1789 (long) LR_BRANCH, 0,
1790 (char *) 0, SPO_LEVREGION));
1794 teleprt_detail : /* empty */
1796 $$ = -1;
1798 | ',' UP_OR_DOWN
1800 $$ = $2;
1804 fountain_detail : FOUNTAIN_ID ':' ter_selection
1806 add_opvars(splev, "o", VA_PASS1(SPO_FOUNTAIN));
1810 sink_detail : SINK_ID ':' ter_selection
1812 add_opvars(splev, "o", VA_PASS1(SPO_SINK));
1816 pool_detail : POOL_ID ':' ter_selection
1818 add_opvars(splev, "o", VA_PASS1(SPO_POOL));
1822 terrain_type : CHAR
1824 $$.lit = -2;
1825 $$.ter = what_map_char((char) $<i>1);
1827 | '(' CHAR ',' light_state ')'
1829 $$.lit = $4;
1830 $$.ter = what_map_char((char) $<i>2);
1834 replace_terrain_detail : REPLACE_TERRAIN_ID ':' region_or_var ',' mapchar_or_var ',' mapchar_or_var ',' SPERCENT
1836 add_opvars(splev, "io",
1837 VA_PASS2($9, SPO_REPLACETERRAIN));
1841 terrain_detail : TERRAIN_ID ':' ter_selection ',' mapchar_or_var
1843 add_opvars(splev, "o", VA_PASS1(SPO_TERRAIN));
1847 diggable_detail : NON_DIGGABLE_ID ':' region_or_var
1849 add_opvars(splev, "o", VA_PASS1(SPO_NON_DIGGABLE));
1853 passwall_detail : NON_PASSWALL_ID ':' region_or_var
1855 add_opvars(splev, "o", VA_PASS1(SPO_NON_PASSWALL));
1859 region_detail : REGION_ID ':' region_or_var ',' light_state ',' room_type optroomregionflags
1861 long irr;
1862 long rt = $7;
1863 long rflags = $8;
1865 if (rflags == -1) rflags = (1 << 0);
1866 if (!(rflags & 1)) rt += MAXRTYPE+1;
1867 irr = ((rflags & 2) != 0);
1868 add_opvars(splev, "iiio",
1869 VA_PASS4((long)$5, rt, rflags, SPO_REGION));
1870 $<i>$ = (irr || (rflags & 1) || rt != OROOM);
1871 break_stmt_start();
1873 region_detail_end
1875 break_stmt_end(splev);
1876 if ( $<i>9 ) {
1877 add_opcode(splev, SPO_ENDROOM, NULL);
1878 } else if ( $<i>10 )
1879 lc_error("Cannot use lev statements in non-permanent REGION");
1883 region_detail_end : /* nothing */
1885 $$ = 0;
1887 | stmt_block
1889 $$ = $1;
1893 altar_detail : ALTAR_ID ':' coord_or_var ',' alignment ',' altar_type
1895 add_opvars(splev, "iio",
1896 VA_PASS3((long)$7, (long)$5, SPO_ALTAR));
1900 grave_detail : GRAVE_ID ':' coord_or_var ',' string_expr
1902 add_opvars(splev, "io", VA_PASS2(2, SPO_GRAVE));
1904 | GRAVE_ID ':' coord_or_var ',' RANDOM_TYPE
1906 add_opvars(splev, "sio",
1907 VA_PASS3((char *)0, 1, SPO_GRAVE));
1909 | GRAVE_ID ':' coord_or_var
1911 add_opvars(splev, "sio",
1912 VA_PASS3((char *)0, 0, SPO_GRAVE));
1916 gold_detail : GOLD_ID ':' math_expr_var ',' coord_or_var
1918 add_opvars(splev, "o", VA_PASS1(SPO_GOLD));
1922 engraving_detail: ENGRAVING_ID ':' coord_or_var ',' engraving_type ',' string_expr
1924 add_opvars(splev, "io",
1925 VA_PASS2((long)$5, SPO_ENGRAVING));
1929 mineralize : MINERALIZE_ID ':' integer_or_var ',' integer_or_var ',' integer_or_var ',' integer_or_var
1931 add_opvars(splev, "o", VA_PASS1(SPO_MINERALIZE));
1933 | MINERALIZE_ID
1935 add_opvars(splev, "iiiio",
1936 VA_PASS5(-1L, -1L, -1L, -1L, SPO_MINERALIZE));
1940 trap_name : STRING
1942 int token = get_trap_type($1);
1943 if (token == ERR)
1944 lc_error("Unknown trap type '%s'!", $1);
1945 $$ = token;
1946 Free($1);
1948 | RANDOM_TYPE
1951 room_type : STRING
1953 int token = get_room_type($1);
1954 if (token == ERR) {
1955 lc_warning("Unknown room type \"%s\"! Making ordinary room...", $1);
1956 $$ = OROOM;
1957 } else
1958 $$ = token;
1959 Free($1);
1961 | RANDOM_TYPE
1964 optroomregionflags : /* empty */
1966 $$ = -1;
1968 | ',' roomregionflags
1970 $$ = $2;
1974 roomregionflags : roomregionflag
1976 $$ = $1;
1978 | roomregionflag ',' roomregionflags
1980 $$ = $1 | $3;
1984 /* 0 is the "default" here */
1985 roomregionflag : FILLING
1987 $$ = ($1 << 0);
1989 | IRREGULAR
1991 $$ = ($1 << 1);
1993 | JOINED
1995 $$ = ($1 << 2);
1999 door_state : DOOR_STATE
2000 | RANDOM_TYPE
2003 light_state : LIGHT_STATE
2004 | RANDOM_TYPE
2007 alignment : ALIGNMENT
2008 | a_register
2009 | RANDOM_TYPE
2011 $$ = - MAX_REGISTERS - 1;
2015 alignment_prfx : ALIGNMENT
2016 | a_register
2017 | A_REGISTER ':' RANDOM_TYPE
2019 $$ = - MAX_REGISTERS - 1;
2023 altar_type : ALTAR_TYPE
2024 | RANDOM_TYPE
2027 a_register : A_REGISTER '[' INTEGER ']'
2029 if ( $3 >= 3 )
2030 lc_error("Register Index overflow!");
2031 else
2032 $$ = - $3 - 1;
2036 string_or_var : STRING
2038 add_opvars(splev, "s", VA_PASS1($1));
2039 Free($1);
2041 | VARSTRING_STRING
2043 check_vardef_type(variable_definitions, $1, SPOVAR_STRING);
2044 vardef_used(variable_definitions, $1);
2045 add_opvars(splev, "v", VA_PASS1($1));
2046 Free($1);
2048 | VARSTRING_STRING_ARRAY '[' math_expr_var ']'
2050 check_vardef_type(variable_definitions, $1, SPOVAR_STRING|SPOVAR_ARRAY);
2051 vardef_used(variable_definitions, $1);
2052 add_opvars(splev, "v", VA_PASS1($1));
2053 Free($1);
2058 integer_or_var : math_expr_var
2060 /* nothing */
2064 coord_or_var : encodecoord
2066 add_opvars(splev, "c", VA_PASS1($1));
2068 | rndcoord_ID '(' ter_selection ')'
2070 add_opvars(splev, "o", VA_PASS1(SPO_SEL_RNDCOORD));
2072 | VARSTRING_COORD
2074 check_vardef_type(variable_definitions, $1, SPOVAR_COORD);
2075 vardef_used(variable_definitions, $1);
2076 add_opvars(splev, "v", VA_PASS1($1));
2077 Free($1);
2079 | VARSTRING_COORD_ARRAY '[' math_expr_var ']'
2081 check_vardef_type(variable_definitions, $1, SPOVAR_COORD|SPOVAR_ARRAY);
2082 vardef_used(variable_definitions, $1);
2083 add_opvars(splev, "v", VA_PASS1($1));
2084 Free($1);
2088 encodecoord : '(' INTEGER ',' INTEGER ')'
2090 if ($2 < 0 || $4 < 0 || $2 >= COLNO || $4 >= ROWNO)
2091 lc_error("Coordinates (%li,%li) out of map range!", $2, $4);
2092 $$ = SP_COORD_PACK($2, $4);
2094 | RANDOM_TYPE
2096 $$ = SP_COORD_PACK_RANDOM(0);
2098 | RANDOM_TYPE_BRACKET humidity_flags ']'
2100 $$ = SP_COORD_PACK_RANDOM( $2 );
2104 humidity_flags : HUMIDITY_TYPE
2106 $$ = $1;
2108 | HUMIDITY_TYPE ',' humidity_flags
2110 if (($1 & $3))
2111 lc_warning("Humidity flag used twice.");
2112 $$ = ($1 | $3);
2116 region_or_var : encoderegion
2118 /* nothing */
2120 | VARSTRING_REGION
2122 check_vardef_type(variable_definitions, $1, SPOVAR_REGION);
2123 vardef_used(variable_definitions, $1);
2124 add_opvars(splev, "v", VA_PASS1($1));
2125 Free($1);
2127 | VARSTRING_REGION_ARRAY '[' math_expr_var ']'
2129 check_vardef_type(variable_definitions, $1, SPOVAR_REGION|SPOVAR_ARRAY);
2130 vardef_used(variable_definitions, $1);
2131 add_opvars(splev, "v", VA_PASS1($1));
2132 Free($1);
2136 encoderegion : '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
2138 long r = SP_REGION_PACK($2, $4, $6, $8);
2139 if ( $2 > $6 || $4 > $8 )
2140 lc_error("Region start > end: (%li,%li,%li,%li)!", $2, $4, $6, $8);
2142 add_opvars(splev, "r", VA_PASS1(r));
2143 $$ = r;
2147 mapchar_or_var : mapchar
2149 add_opvars(splev, "m", VA_PASS1($1));
2151 | VARSTRING_MAPCHAR
2153 check_vardef_type(variable_definitions, $1, SPOVAR_MAPCHAR);
2154 vardef_used(variable_definitions, $1);
2155 add_opvars(splev, "v", VA_PASS1($1));
2156 Free($1);
2158 | VARSTRING_MAPCHAR_ARRAY '[' math_expr_var ']'
2160 check_vardef_type(variable_definitions, $1, SPOVAR_MAPCHAR|SPOVAR_ARRAY);
2161 vardef_used(variable_definitions, $1);
2162 add_opvars(splev, "v", VA_PASS1($1));
2163 Free($1);
2167 mapchar : CHAR
2169 if (what_map_char((char) $1) != INVALID_TYPE)
2170 $$ = SP_MAPCHAR_PACK(what_map_char((char) $1), -2);
2171 else {
2172 lc_error("Unknown map char type '%c'!", $1);
2173 $$ = SP_MAPCHAR_PACK(STONE, -2);
2176 | '(' CHAR ',' light_state ')'
2178 if (what_map_char((char) $2) != INVALID_TYPE)
2179 $$ = SP_MAPCHAR_PACK(what_map_char((char) $2), $4);
2180 else {
2181 lc_error("Unknown map char type '%c'!", $2);
2182 $$ = SP_MAPCHAR_PACK(STONE, $4);
2187 monster_or_var : encodemonster
2189 add_opvars(splev, "M", VA_PASS1($1));
2191 | VARSTRING_MONST
2193 check_vardef_type(variable_definitions, $1, SPOVAR_MONST);
2194 vardef_used(variable_definitions, $1);
2195 add_opvars(splev, "v", VA_PASS1($1));
2196 Free($1);
2198 | VARSTRING_MONST_ARRAY '[' math_expr_var ']'
2200 check_vardef_type(variable_definitions, $1, SPOVAR_MONST|SPOVAR_ARRAY);
2201 vardef_used(variable_definitions, $1);
2202 add_opvars(splev, "v", VA_PASS1($1));
2203 Free($1);
2207 encodemonster : STRING
2209 long m = get_monster_id($1, (char)0);
2210 if (m == ERR) {
2211 lc_error("Unknown monster \"%s\"!", $1);
2212 $$ = -1;
2213 } else
2214 $$ = SP_MONST_PACK(m,
2215 def_monsyms[(int) mons[m].mlet].sym);
2216 Free($1);
2218 | CHAR
2220 if (check_monster_char((char) $1))
2221 $$ = SP_MONST_PACK(-1, $1);
2222 else {
2223 lc_error("Unknown monster class '%c'!", $1);
2224 $$ = -1;
2227 | '(' CHAR ',' STRING ')'
2229 long m = get_monster_id($4, (char) $2);
2230 if (m == ERR) {
2231 lc_error("Unknown monster ('%c', \"%s\")!", $2, $4);
2232 $$ = -1;
2233 } else
2234 $$ = SP_MONST_PACK(m, $2);
2235 Free($4);
2237 | RANDOM_TYPE
2239 $$ = -1;
2243 object_or_var : encodeobj
2245 add_opvars(splev, "O", VA_PASS1($1));
2247 | VARSTRING_OBJ
2249 check_vardef_type(variable_definitions, $1, SPOVAR_OBJ);
2250 vardef_used(variable_definitions, $1);
2251 add_opvars(splev, "v", VA_PASS1($1));
2252 Free($1);
2254 | VARSTRING_OBJ_ARRAY '[' math_expr_var ']'
2256 check_vardef_type(variable_definitions, $1, SPOVAR_OBJ|SPOVAR_ARRAY);
2257 vardef_used(variable_definitions, $1);
2258 add_opvars(splev, "v", VA_PASS1($1));
2259 Free($1);
2263 encodeobj : STRING
2265 long m = get_object_id($1, (char)0);
2266 if (m == ERR) {
2267 lc_error("Unknown object \"%s\"!", $1);
2268 $$ = -1;
2269 } else
2270 $$ = SP_OBJ_PACK(m, 1); /* obj class != 0 to force generation of a specific item */
2271 Free($1);
2273 | CHAR
2275 if (check_object_char((char) $1))
2276 $$ = SP_OBJ_PACK(-1, $1);
2277 else {
2278 lc_error("Unknown object class '%c'!", $1);
2279 $$ = -1;
2282 | '(' CHAR ',' STRING ')'
2284 long m = get_object_id($4, (char) $2);
2285 if (m == ERR) {
2286 lc_error("Unknown object ('%c', \"%s\")!", $2, $4);
2287 $$ = -1;
2288 } else
2289 $$ = SP_OBJ_PACK(m, $2);
2290 Free($4);
2292 | RANDOM_TYPE
2294 $$ = -1;
2299 string_expr : string_or_var { }
2300 | string_expr '.' string_or_var
2302 add_opvars(splev, "o", VA_PASS1(SPO_MATH_ADD));
2306 math_expr_var : INTEGER
2308 add_opvars(splev, "i", VA_PASS1($1));
2310 | dice
2312 is_inconstant_number = 1;
2314 | '(' MINUS_INTEGER ')'
2316 add_opvars(splev, "i", VA_PASS1($2));
2318 | VARSTRING_INT
2320 check_vardef_type(variable_definitions, $1, SPOVAR_INT);
2321 vardef_used(variable_definitions, $1);
2322 add_opvars(splev, "v", VA_PASS1($1));
2323 Free($1);
2324 is_inconstant_number = 1;
2326 | VARSTRING_INT_ARRAY '[' math_expr_var ']'
2328 check_vardef_type(variable_definitions,
2329 $1, SPOVAR_INT|SPOVAR_ARRAY);
2330 vardef_used(variable_definitions, $1);
2331 add_opvars(splev, "v", VA_PASS1($1));
2332 Free($1);
2333 is_inconstant_number = 1;
2335 | math_expr_var '+' math_expr_var
2337 add_opvars(splev, "o", VA_PASS1(SPO_MATH_ADD));
2339 | math_expr_var '-' math_expr_var
2341 add_opvars(splev, "o", VA_PASS1(SPO_MATH_SUB));
2343 | math_expr_var '*' math_expr_var
2345 add_opvars(splev, "o", VA_PASS1(SPO_MATH_MUL));
2347 | math_expr_var '/' math_expr_var
2349 add_opvars(splev, "o", VA_PASS1(SPO_MATH_DIV));
2351 | math_expr_var '%' math_expr_var
2353 add_opvars(splev, "o", VA_PASS1(SPO_MATH_MOD));
2355 | '(' math_expr_var ')' { }
2358 func_param_type : CFUNC_INT
2360 if (!strcmp("int", $1) || !strcmp("integer", $1)) {
2361 $$ = (int)'i';
2362 } else
2363 lc_error("Unknown function parameter type '%s'", $1);
2365 | CFUNC_STR
2367 if (!strcmp("str", $1) || !strcmp("string", $1)) {
2368 $$ = (int)'s';
2369 } else
2370 lc_error("Unknown function parameter type '%s'", $1);
2374 func_param_part : any_var_or_arr ':' func_param_type
2376 struct lc_funcdefs_parm *tmp = New(struct lc_funcdefs_parm);
2378 if (!curr_function) {
2379 lc_error("Function parameters outside function definition.");
2380 } else if (!tmp) {
2381 lc_error("Could not alloc function params.");
2382 } else {
2383 long vt = SPOVAR_NULL;
2385 tmp->name = strdup($1);
2386 tmp->parmtype = (char) $3;
2387 tmp->next = curr_function->params;
2388 curr_function->params = tmp;
2389 curr_function->n_params++;
2390 switch (tmp->parmtype) {
2391 case 'i':
2392 vt = SPOVAR_INT;
2393 break;
2394 case 's':
2395 vt = SPOVAR_STRING;
2396 break;
2397 default:
2398 lc_error("Unknown func param conversion.");
2399 break;
2401 variable_definitions = add_vardef_type(
2402 variable_definitions,
2403 $1, vt);
2405 Free($1);
2409 func_param_list : func_param_part
2410 | func_param_list ',' func_param_part
2413 func_params_list : /* nothing */
2414 | func_param_list
2417 func_call_param_part : math_expr_var
2419 $$ = (int)'i';
2421 | string_expr
2423 $$ = (int)'s';
2428 func_call_param_list : func_call_param_part
2430 char tmpbuf[2];
2431 tmpbuf[0] = (char) $1;
2432 tmpbuf[1] = '\0';
2433 $$ = strdup(tmpbuf);
2435 | func_call_param_list ',' func_call_param_part
2437 long len = strlen( $1 );
2438 char *tmp = (char *) alloc(len + 2);
2439 sprintf(tmp, "%c%s", (char) $3, $1 );
2440 Free( $1 );
2441 $$ = tmp;
2445 func_call_params_list : /* nothing */
2447 $$ = strdup("");
2449 | func_call_param_list
2451 char *tmp = strdup( $1 );
2452 Free( $1 );
2453 $$ = tmp;
2457 ter_selection_x : coord_or_var
2459 add_opvars(splev, "o", VA_PASS1(SPO_SEL_POINT));
2461 | rect_ID region_or_var
2463 add_opvars(splev, "o", VA_PASS1(SPO_SEL_RECT));
2465 | fillrect_ID region_or_var
2467 add_opvars(splev, "o", VA_PASS1(SPO_SEL_FILLRECT));
2469 | line_ID coord_or_var ',' coord_or_var
2471 add_opvars(splev, "o", VA_PASS1(SPO_SEL_LINE));
2473 | randline_ID coord_or_var ',' coord_or_var ',' math_expr_var
2475 /* randline (x1,y1),(x2,y2), roughness */
2476 add_opvars(splev, "o", VA_PASS1(SPO_SEL_RNDLINE));
2478 | grow_ID '(' ter_selection ')'
2480 add_opvars(splev, "io", VA_PASS2(W_ANY, SPO_SEL_GROW));
2482 | grow_ID '(' dir_list ',' ter_selection ')'
2484 add_opvars(splev, "io", VA_PASS2($3, SPO_SEL_GROW));
2486 | filter_ID '(' SPERCENT ',' ter_selection ')'
2488 add_opvars(splev, "iio",
2489 VA_PASS3($3, SPOFILTER_PERCENT, SPO_SEL_FILTER));
2491 | filter_ID '(' ter_selection ',' ter_selection ')'
2493 add_opvars(splev, "io",
2494 VA_PASS2(SPOFILTER_SELECTION, SPO_SEL_FILTER));
2496 | filter_ID '(' mapchar_or_var ',' ter_selection ')'
2498 add_opvars(splev, "io",
2499 VA_PASS2(SPOFILTER_MAPCHAR, SPO_SEL_FILTER));
2501 | flood_ID coord_or_var
2503 add_opvars(splev, "o", VA_PASS1(SPO_SEL_FLOOD));
2505 | circle_ID '(' coord_or_var ',' math_expr_var ')'
2507 add_opvars(splev, "oio",
2508 VA_PASS3(SPO_COPY, 1, SPO_SEL_ELLIPSE));
2510 | circle_ID '(' coord_or_var ',' math_expr_var ',' FILLING ')'
2512 add_opvars(splev, "oio",
2513 VA_PASS3(SPO_COPY, $7, SPO_SEL_ELLIPSE));
2515 | ellipse_ID '(' coord_or_var ',' math_expr_var ',' math_expr_var ')'
2517 add_opvars(splev, "io", VA_PASS2(1, SPO_SEL_ELLIPSE));
2519 | ellipse_ID '(' coord_or_var ',' math_expr_var ',' math_expr_var ',' FILLING ')'
2521 add_opvars(splev, "io", VA_PASS2($9, SPO_SEL_ELLIPSE));
2523 | gradient_ID '(' GRADIENT_TYPE ',' '(' math_expr_var '-' math_expr_var opt_limited ')' ',' coord_or_var opt_coord_or_var ')'
2525 add_opvars(splev, "iio",
2526 VA_PASS3($9, $3, SPO_SEL_GRADIENT));
2528 | complement_ID ter_selection_x
2530 add_opvars(splev, "o", VA_PASS1(SPO_SEL_COMPLEMENT));
2532 | VARSTRING_SEL
2534 check_vardef_type(variable_definitions, $1, SPOVAR_SEL);
2535 vardef_used(variable_definitions, $1);
2536 add_opvars(splev, "v", VA_PASS1($1));
2537 Free($1);
2539 | '(' ter_selection ')'
2541 /* nothing */
2545 ter_selection : ter_selection_x
2547 /* nothing */
2549 | ter_selection_x '&' ter_selection
2551 add_opvars(splev, "o", VA_PASS1(SPO_SEL_ADD));
2555 dice : DICE
2557 add_opvars(splev, "iio",
2558 VA_PASS3($1.num, $1.die, SPO_DICE));
2562 all_integers : MINUS_INTEGER
2563 | PLUS_INTEGER
2564 | INTEGER
2567 all_ints_push : MINUS_INTEGER
2569 add_opvars(splev, "i", VA_PASS1($1));
2571 | PLUS_INTEGER
2573 add_opvars(splev, "i", VA_PASS1($1));
2575 | INTEGER
2577 add_opvars(splev, "i", VA_PASS1($1));
2579 | dice
2581 /* nothing */
2585 objectid : object_ID
2586 | OBJECT_ID
2589 monsterid : monster_ID
2590 | MONSTER_ID
2593 terrainid : terrain_ID
2594 | TERRAIN_ID
2597 engraving_type : ENGRAVING_TYPE
2598 | RANDOM_TYPE
2601 lev_region : region
2603 $$ = $1;
2605 | LEV '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
2607 if ($3 <= 0 || $3 >= COLNO)
2608 lc_error(
2609 "Region (%ld,%ld,%ld,%ld) out of level range (x1)!",
2610 $3, $5, $7, $9);
2611 else if ($5 < 0 || $5 >= ROWNO)
2612 lc_error(
2613 "Region (%ld,%ld,%ld,%ld) out of level range (y1)!",
2614 $3, $5, $7, $9);
2615 else if ($7 <= 0 || $7 >= COLNO)
2616 lc_error(
2617 "Region (%ld,%ld,%ld,%ld) out of level range (x2)!",
2618 $3, $5, $7, $9);
2619 else if ($9 < 0 || $9 >= ROWNO)
2620 lc_error(
2621 "Region (%ld,%ld,%ld,%ld) out of level range (y2)!",
2622 $3, $5, $7, $9);
2623 $$.x1 = $3;
2624 $$.y1 = $5;
2625 $$.x2 = $7;
2626 $$.y2 = $9;
2627 $$.area = 1;
2631 region : '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
2633 /* This series of if statements is a hack for MSC 5.1. It seems that its
2634 tiny little brain cannot compile if these are all one big if statement. */
2635 if ($2 < 0 || $2 > (int) max_x_map)
2636 lc_error(
2637 "Region (%ld,%ld,%ld,%ld) out of map range (x1)!",
2638 $2, $4, $6, $8);
2639 else if ($4 < 0 || $4 > (int) max_y_map)
2640 lc_error(
2641 "Region (%ld,%ld,%ld,%ld) out of map range (y1)!",
2642 $2, $4, $6, $8);
2643 else if ($6 < 0 || $6 > (int) max_x_map)
2644 lc_error(
2645 "Region (%ld,%ld,%ld,%ld) out of map range (x2)!",
2646 $2, $4, $6, $8);
2647 else if ($8 < 0 || $8 > (int) max_y_map)
2648 lc_error(
2649 "Region (%ld,%ld,%ld,%ld) out of map range (y2)!",
2650 $2, $4, $6, $8);
2651 $$.area = 0;
2652 $$.x1 = $2;
2653 $$.y1 = $4;
2654 $$.x2 = $6;
2655 $$.y2 = $8;
2662 /*lev_comp.y*/