1 /* NetHack 3.6 sp_lev.h $NHDT-Date: 1544930819 2018/12/16 03:26:59 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.25 $ */ 2 /* Copyright (c) 1989 by Jean-Christophe Collet */ 3 /* NetHack may be freely redistributed. See license for details. */ 4 5 #ifndef SP_LEV_H 6 #define SP_LEV_H 7 8 /* wall directions */ 9 #define W_NORTH 1 10 #define W_SOUTH 2 11 #define W_EAST 4 12 #define W_WEST 8 13 #define W_ANY (W_NORTH | W_SOUTH | W_EAST | W_WEST) 14 15 /* MAP limits */ 16 #define MAP_X_LIM 76 17 #define MAP_Y_LIM 21 18 19 /* Per level flags */ 20 #define NOTELEPORT 0x00000001L 21 #define HARDFLOOR 0x00000002L 22 #define NOMMAP 0x00000004L 23 #define SHORTSIGHTED 0x00000008L 24 #define ARBOREAL 0x00000010L 25 #define MAZELEVEL 0x00000020L 26 #define PREMAPPED 0x00000040L /* premapped level & sokoban rules */ 27 #define SHROUD 0x00000080L 28 #define GRAVEYARD 0x00000100L 29 #define ICEDPOOLS 0x00000200L /* for ice locations: ICED_POOL vs ICED_MOAT \ 30 */ 31 #define SOLIDIFY 0x00000400L /* outer areas are nondiggable & nonpasswall */ 32 #define CORRMAZE 0x00000800L /* for maze levels only */ 33 #define CHECK_INACCESSIBLES 0x00001000L /* check for inaccessible areas and 34 generate ways to escape from them */ 35 36 /* different level layout initializers */ 37 enum lvlinit_types { 38 LVLINIT_NONE = 0, 39 LVLINIT_SOLIDFILL, 40 LVLINIT_MAZEGRID, 41 LVLINIT_MINES, 42 LVLINIT_ROGUE 43 }; 44 45 /* max. layers of object containment */ 46 #define MAX_CONTAINMENT 10 47 48 /* max. # of random registers */ 49 #define MAX_REGISTERS 10 50 51 /* max. nested depth of subrooms */ 52 #define MAX_NESTED_ROOMS 5 53 54 /* max. # of opcodes per special level */ 55 #define SPCODER_MAX_RUNTIME 65536 56 57 /* Opcodes for creating the level 58 * If you change these, also change opcodestr[] in util/lev_main.c 59 */ 60 enum opcode_defs { 61 SPO_NULL = 0, 62 SPO_MESSAGE, 63 SPO_MONSTER, 64 SPO_OBJECT, 65 SPO_ENGRAVING, 66 SPO_ROOM, 67 SPO_SUBROOM, 68 SPO_DOOR, 69 SPO_STAIR, 70 SPO_LADDER, 71 SPO_ALTAR, 72 SPO_FOUNTAIN, 73 SPO_SINK, 74 SPO_POOL, 75 SPO_TRAP, 76 SPO_GOLD, 77 SPO_CORRIDOR, 78 SPO_LEVREGION, 79 SPO_DRAWBRIDGE, 80 SPO_MAZEWALK, 81 SPO_NON_DIGGABLE, 82 SPO_NON_PASSWALL, 83 SPO_WALLIFY, 84 SPO_MAP, 85 SPO_ROOM_DOOR, 86 SPO_REGION, 87 SPO_MINERALIZE, 88 SPO_CMP, 89 SPO_JMP, 90 SPO_JL, 91 SPO_JLE, 92 SPO_JG, 93 SPO_JGE, 94 SPO_JE, 95 SPO_JNE, 96 SPO_TERRAIN, 97 SPO_REPLACETERRAIN, 98 SPO_EXIT, 99 SPO_ENDROOM, 100 SPO_POP_CONTAINER, 101 SPO_PUSH, 102 SPO_POP, 103 SPO_RN2, 104 SPO_DEC, 105 SPO_INC, 106 SPO_MATH_ADD, 107 SPO_MATH_SUB, 108 SPO_MATH_MUL, 109 SPO_MATH_DIV, 110 SPO_MATH_MOD, 111 SPO_MATH_SIGN, 112 SPO_COPY, 113 SPO_END_MONINVENT, 114 SPO_GRAVE, 115 SPO_FRAME_PUSH, 116 SPO_FRAME_POP, 117 SPO_CALL, 118 SPO_RETURN, 119 SPO_INITLEVEL, 120 SPO_LEVEL_FLAGS, 121 SPO_VAR_INIT, /* variable_name data */ 122 SPO_SHUFFLE_ARRAY, 123 SPO_DICE, 124 125 SPO_SEL_ADD, 126 SPO_SEL_POINT, 127 SPO_SEL_RECT, 128 SPO_SEL_FILLRECT, 129 SPO_SEL_LINE, 130 SPO_SEL_RNDLINE, 131 SPO_SEL_GROW, 132 SPO_SEL_FLOOD, 133 SPO_SEL_RNDCOORD, 134 SPO_SEL_ELLIPSE, 135 SPO_SEL_FILTER, 136 SPO_SEL_GRADIENT, 137 SPO_SEL_COMPLEMENT, 138 139 MAX_SP_OPCODES 140 }; 141 142 /* MONSTER and OBJECT can take a variable number of parameters, 143 * they also pop different # of values from the stack. So, 144 * first we pop a value that tells what the _next_ value will 145 * mean. 146 */ 147 /* MONSTER */ 148 enum sp_mon_var_flags { 149 SP_M_V_PEACEFUL = 0, 150 SP_M_V_ALIGN, 151 SP_M_V_ASLEEP, 152 SP_M_V_APPEAR, 153 SP_M_V_NAME, 154 SP_M_V_FEMALE, 155 SP_M_V_INVIS, 156 SP_M_V_CANCELLED, 157 SP_M_V_REVIVED, 158 SP_M_V_AVENGE, 159 SP_M_V_FLEEING, 160 SP_M_V_BLINDED, 161 SP_M_V_PARALYZED, 162 SP_M_V_STUNNED, 163 SP_M_V_CONFUSED, 164 SP_M_V_SEENTRAPS, 165 166 SP_M_V_END 167 }; 168 169 /* OBJECT */ 170 enum sp_obj_var_flags { 171 SP_O_V_SPE = 0, 172 SP_O_V_CURSE, 173 SP_O_V_CORPSENM, 174 SP_O_V_NAME, 175 SP_O_V_QUAN, 176 SP_O_V_BURIED, 177 SP_O_V_LIT, 178 SP_O_V_ERODED, 179 SP_O_V_LOCKED, 180 SP_O_V_TRAPPED, 181 SP_O_V_RECHARGED, 182 SP_O_V_INVIS, 183 SP_O_V_GREASED, 184 SP_O_V_BROKEN, 185 SP_O_V_COORD, 186 187 SP_O_V_END 188 }; 189 190 /* When creating objects, we need to know whether 191 * it's a container and/or contents. 192 */ 193 #define SP_OBJ_CONTENT 0x1 194 #define SP_OBJ_CONTAINER 0x2 195 196 /* SPO_FILTER types */ 197 #define SPOFILTER_PERCENT 0 198 #define SPOFILTER_SELECTION 1 199 #define SPOFILTER_MAPCHAR 2 200 201 /* gradient filter types */ 202 #define SEL_GRADIENT_RADIAL 0 203 #define SEL_GRADIENT_SQUARE 1 204 205 /* variable types */ 206 #define SPOVAR_NULL 0x00 207 #define SPOVAR_INT 0x01 /* l */ 208 #define SPOVAR_STRING 0x02 /* str */ 209 #define SPOVAR_VARIABLE 0x03 /* str (contains the variable name) */ 210 #define SPOVAR_COORD \ 211 0x04 /* coordinate, encoded in l; use SP_COORD_X() and SP_COORD_Y() */ 212 #define SPOVAR_REGION 0x05 /* region, encoded in l; use SP_REGION_X1() etc \ 213 */ 214 #define SPOVAR_MAPCHAR 0x06 /* map char, in l */ 215 #define SPOVAR_MONST \ 216 0x07 /* monster class & specific monster, encoded in l; use SP_MONST_... \ 217 */ 218 #define SPOVAR_OBJ \ 219 0x08 /* object class & specific object type, encoded in l; use \ 220 SP_OBJ_... */ 221 #define SPOVAR_SEL 0x09 /* selection. char[COLNO][ROWNO] in str */ 222 #define SPOVAR_ARRAY 0x40 /* used in splev_var & lc_vardefs, not in opvar */ 223 224 #define SP_COORD_IS_RANDOM 0x01000000L 225 /* Humidity flags for get_location() and friends, used with 226 * SP_COORD_PACK_RANDOM() */ 227 #define DRY 0x01 228 #define WET 0x02 229 #define HOT 0x04 230 #define SOLID 0x08 231 #define ANY_LOC 0x10 /* even outside the level */ 232 #define NO_LOC_WARN 0x20 /* no complaints and set x & y to -1, if no loc */ 233 #define SPACELOC 0x40 /* like DRY, but accepts furniture too */ 234 235 #define SP_COORD_X(l) (l & 0xff) 236 #define SP_COORD_Y(l) ((l >> 16) & 0xff) 237 #define SP_COORD_PACK(x, y) (((x) & 0xff) + (((y) & 0xff) << 16)) 238 #define SP_COORD_PACK_RANDOM(f) (SP_COORD_IS_RANDOM | (f)) 239 240 #define SP_REGION_X1(l) (l & 0xff) 241 #define SP_REGION_Y1(l) ((l >> 8) & 0xff) 242 #define SP_REGION_X2(l) ((l >> 16) & 0xff) 243 #define SP_REGION_Y2(l) ((l >> 24) & 0xff) 244 #define SP_REGION_PACK(x1, y1, x2, y2) \ 245 (((x1) & 0xff) + (((y1) & 0xff) << 8) + (((x2) & 0xff) << 16) \ 246 + (((y2) & 0xff) << 24)) 247 248 /* permonst index, object index, and lit value might be negative; 249 * add 10 to accept -1 through -9 while forcing non-negative for bit shift 250 */ 251 #define SP_MONST_CLASS(l) ((l) & 0xff) 252 #define SP_MONST_PM(l) ((((l) >> 8) & 0xffff) - 10) 253 #define SP_MONST_PACK(pm, cls) (((10 + (pm)) << 8) | ((cls) & 0xff)) 254 255 #define SP_OBJ_CLASS(l) ((l) & 0xff) 256 #define SP_OBJ_TYP(l) ((((l) >> 8) & 0xffff) - 10) 257 #define SP_OBJ_PACK(ob, cls) (((10 + (ob)) << 8) | ((cls) & 0xff)) 258 259 #define SP_MAPCHAR_TYP(l) ((l) & 0xff) 260 #define SP_MAPCHAR_LIT(l) ((((l) >> 8) & 0xffff) - 10) 261 #define SP_MAPCHAR_PACK(typ, lit) (((10 + (lit)) << 8) | ((typ) & 0xff)) 262 263 struct splev_var { 264 struct splev_var *next; 265 char *name; 266 xchar svtyp; /* SPOVAR_foo */ 267 union { 268 struct opvar *value; 269 struct opvar **arrayvalues; 270 } data; 271 long array_len; 272 }; 273 274 struct splevstack { 275 long depth; 276 long depth_alloc; 277 struct opvar **stackdata; 278 }; 279 280 struct sp_frame { 281 struct sp_frame *next; 282 struct splevstack *stack; 283 struct splev_var *variables; 284 long n_opcode; 285 }; 286 287 struct sp_coder { 288 struct splevstack *stack; 289 struct sp_frame *frame; 290 int premapped; 291 boolean solidify; 292 struct mkroom *croom; 293 struct mkroom *tmproomlist[MAX_NESTED_ROOMS + 1]; 294 boolean failed_room[MAX_NESTED_ROOMS + 1]; 295 int n_subroom; 296 boolean exit_script; 297 int lvl_is_joined; 298 boolean check_inaccessibles; 299 300 int opcode; /* current opcode */ 301 struct opvar *opdat; /* current push data (req. opcode == SPO_PUSH) */ 302 }; 303 304 /* special level coder CPU flags */ 305 #define SP_CPUFLAG_LT 1 306 #define SP_CPUFLAG_GT 2 307 #define SP_CPUFLAG_EQ 4 308 #define SP_CPUFLAG_ZERO 8 309 310 /* 311 * Structures manipulated by the special levels loader & compiler 312 */ 313 314 #define packed_coord long 315 typedef struct { 316 xchar is_random; 317 long getloc_flags; 318 int x, y; 319 } unpacked_coord; 320 321 typedef struct { 322 int cmp_what; 323 int cmp_val; 324 } opcmp; 325 326 typedef struct { 327 long jmp_target; 328 } opjmp; 329 330 typedef union str_or_len { 331 char *str; 332 int len; 333 } Str_or_Len; 334 335 typedef struct { 336 xchar init_style; /* one of LVLINIT_foo */ 337 long flags; 338 schar filling; 339 boolean init_present, padding; 340 char fg, bg; 341 boolean smoothed, joined; 342 xchar lit, walled; 343 boolean icedpools; 344 } lev_init; 345 346 typedef struct { 347 xchar wall, pos, secret, mask; 348 } room_door; 349 350 typedef struct { 351 packed_coord coord; 352 xchar x, y, type; 353 } spltrap; 354 355 typedef struct { 356 Str_or_Len name, appear_as; 357 short id; 358 aligntyp align; 359 packed_coord coord; 360 xchar x, y, class, appear; 361 schar peaceful, asleep; 362 short female, invis, cancelled, revived, avenge, fleeing, blinded, 363 paralyzed, stunned, confused; 364 long seentraps; 365 short has_invent; 366 } monster; 367 368 typedef struct { 369 Str_or_Len name; 370 int corpsenm; 371 short id, spe; 372 packed_coord coord; 373 xchar x, y, class, containment; 374 schar curse_state; 375 int quan; 376 short buried; 377 short lit; 378 short eroded, locked, trapped, recharged, invis, greased, broken; 379 } object; 380 381 typedef struct { 382 packed_coord coord; 383 xchar x, y; 384 aligntyp align; 385 xchar shrine; 386 } altar; 387 388 typedef struct { 389 xchar x1, y1, x2, y2; 390 xchar rtype, rlit, rirreg; 391 } region; 392 393 typedef struct { 394 xchar ter, tlit; 395 } terrain; 396 397 typedef struct { 398 xchar chance; 399 xchar x1, y1, x2, y2; 400 xchar fromter, toter, tolit; 401 } replaceterrain; 402 403 /* values for rtype are defined in dungeon.h */ 404 typedef struct { 405 struct { 406 xchar x1, y1, x2, y2; 407 } inarea; 408 struct { 409 xchar x1, y1, x2, y2; 410 } delarea; 411 boolean in_islev, del_islev; 412 xchar rtype, padding; 413 Str_or_Len rname; 414 } lev_region; 415 416 typedef struct { 417 struct { 418 xchar room; 419 xchar wall; 420 xchar door; 421 } src, dest; 422 } corridor; 423 424 typedef struct _room { 425 Str_or_Len name; 426 Str_or_Len parent; 427 xchar x, y, w, h; 428 xchar xalign, yalign; 429 xchar rtype, chance, rlit, filled, joined; 430 } room; 431 432 typedef struct { 433 schar zaligntyp; 434 schar keep_region; 435 schar halign, valign; 436 char xsize, ysize; 437 char **map; 438 } mazepart; 439 440 typedef struct { 441 int opcode; 442 struct opvar *opdat; 443 } _opcode; 444 445 typedef struct { 446 _opcode *opcodes; 447 long n_opcodes; 448 } sp_lev; 449 450 typedef struct { 451 xchar x, y, direction, count, lit; 452 char typ; 453 } spill; 454 455 /* only used by lev_comp */ 456 struct lc_funcdefs_parm { 457 char *name; 458 char parmtype; 459 struct lc_funcdefs_parm *next; 460 }; 461 462 struct lc_funcdefs { 463 struct lc_funcdefs *next; 464 char *name; 465 long addr; 466 sp_lev code; 467 long n_called; 468 struct lc_funcdefs_parm *params; 469 long n_params; 470 }; 471 472 struct lc_vardefs { 473 struct lc_vardefs *next; 474 char *name; 475 long var_type; /* SPOVAR_foo */ 476 long n_used; 477 }; 478 479 struct lc_breakdef { 480 struct lc_breakdef *next; 481 struct opvar *breakpoint; 482 int break_depth; 483 }; 484 485 /* 486 * Quick! Avert your eyes while you still have a chance! 487 */ 488 #ifdef SPEC_LEV 489 /* compiling lev_comp rather than nethack */ 490 /* clang format off */ 491 #ifdef USE_OLDARGS 492 #ifndef VA_TYPE 493 typedef const char *vA; 494 #define VA_TYPE 495 #endif 496 /* hack to avoid "warning: cast to 'vA' (aka 'const char *') from smaller 497 integer type 'int' [-Wint-to-pointer-cast]" */ 498 #define vA_(a) ((vA) (long) a) 499 #undef VA_ARGS /* redefine with the maximum number actually used */ 500 #undef VA_SHIFT /* ditto */ 501 #undef VA_PASS1 502 #define VA_ARGS \ 503 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, \ 504 arg12, arg13, arg14 505 /* Unlike in the core, lev_comp's VA_SHIFT should be completely safe, 506 because callers always pass all these arguments. */ 507 #define VA_SHIFT() \ 508 (arg1 = arg2, arg2 = arg3, arg3 = arg4, arg4 = arg5, arg5 = arg6, \ 509 arg6 = arg7, arg7 = arg8, arg8 = arg9, arg9 = arg10, arg10 = arg11, \ 510 arg11 = arg12, arg12 = arg13, arg13 = arg14, arg14 = 0) 511 /* standard NULL may be either (void *)0 or plain 0, both of 512 which would need to be explicitly cast to (char *) here */ 513 #define VA_PASS1(a1) \ 514 vA_(a1), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), \ 515 vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0) 516 #define VA_PASS2(a1,a2) \ 517 vA_(a1), vA_(a2), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), \ 518 vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0) 519 #define VA_PASS3(a1,a2,a3) \ 520 vA_(a1), vA_(a2), vA_(a3), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), \ 521 vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0) 522 #define VA_PASS4(a1,a2,a3,a4) \ 523 vA_(a1), vA_(a2), vA_(a3), vA_(a4), vA_(0), vA_(0), vA_(0), vA_(0), \ 524 vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0) 525 #define VA_PASS5(a1,a2,a3,a4,a5) \ 526 vA_(a1), vA_(a2), vA_(a3), vA_(a4), vA_(a5), vA_(0), vA_(0), vA_(0), \ 527 vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0) 528 #define VA_PASS7(a1,a2,a3,a4,a5,a6,a7) \ 529 vA_(a1), vA_(a2), vA_(a3), vA_(a4), vA_(a5), vA_(a6), vA_(a7), vA_(0), \ 530 vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0) 531 #define VA_PASS8(a1,a2,a3,a4,a5,a6,a7,a8) \ 532 vA_(a1), vA_(a2), vA_(a3), vA_(a4), vA_(a5), vA_(a6), vA_(a7), vA_(a8), \ 533 vA_(0), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0) 534 #define VA_PASS9(a1,a2,a3,a4,a5,a6,a7,a8,a9) \ 535 vA_(a1), vA_(a2), vA_(a3), vA_(a4), vA_(a5), vA_(a6), vA_(a7), vA_(a8), \ 536 vA_(a9), vA_(0), vA_(0), vA_(0), vA_(0), vA_(0) 537 #define VA_PASS14(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14) \ 538 vA_(a1), vA_(a2), vA_(a3), vA_(a4), vA_(a5), vA_(a6), vA_(a7), vA_(a8), \ 539 vA_(a9), vA_(a10), vA_(a11), vA_(a12), vA_(a13), vA_(a14) 540 #else /*!USE_OLDARGS*/ 541 /* USE_STDARG and USE_VARARGS don't need to pass dummy arguments 542 or cast real ones */ 543 #define VA_PASS1(a1) a1 544 #define VA_PASS2(a1,a2) a1, a2 545 #define VA_PASS3(a1,a2,a3) a1, a2, a3 546 #define VA_PASS4(a1,a2,a3,a4) a1, a2, a3, a4 547 #define VA_PASS5(a1,a2,a3,a4,a5) a1, a2, a3, a4, a5 548 #define VA_PASS7(a1,a2,a3,a4,a5,a6,a7) a1, a2, a3, a4, a5, a6, a7 549 #define VA_PASS8(a1,a2,a3,a4,a5,a6,a7,a8) a1, a2, a3, a4, a5, a6, a7, a8 550 #define VA_PASS9(a1,a2,a3,a4,a5,a6,a7,a8,a9) a1, a2, a3, a4, a5, a6, a7, a8, a9 551 #define VA_PASS14(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14) \ 552 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 553 #endif /*?USE_OLDARGS*/ 554 /* clang format on */ 555 /* You were warned to avert your eyes.... */ 556 #endif /*SPEC_LEV*/ 557 558 #endif /* SP_LEV_H */ 559