1 #include "AppHdr.h"
2
3 #include "tilepick.h"
4
5 #include "artefact.h"
6 #include "art-enum.h"
7 #include "cloud.h"
8 #include "colour.h"
9 #include "coord.h"
10 #include "coordit.h"
11 #include "describe.h"
12 #include "debug.h"
13 #include "env.h"
14 #include "tile-env.h"
15 #include "files.h"
16 #include "item-name.h"
17 #include "item-prop.h"
18 #include "item-status-flag-type.h"
19 #include "level-state-type.h"
20 #include "libutil.h"
21 #include "mon-death.h"
22 #include "mon-tentacle.h"
23 #include "mon-util.h"
24 #include "options.h"
25 #include "player.h"
26 #include "shopping.h"
27 #include "state.h"
28 #include "stringutil.h"
29 #include "terrain.h"
30 #include "rltiles/tiledef-dngn.h"
31 #include "tile-flags.h"
32 #include "rltiles/tiledef-gui.h"
33 #include "rltiles/tiledef-icons.h"
34 #include "rltiles/tiledef-main.h"
35 #include "rltiles/tiledef-player.h"
36 #include "rltiles/tiledef-unrand.h"
37 #include "tag-version.h"
38 #include "tilemcache.h"
39 #include "tileview.h"
40 #include "transform.h"
41 #include "traps.h"
42 #include "viewgeom.h"
43
44 // This should not be changed.
45 COMPILE_CHECK(TILE_DNGN_UNSEEN == 0);
46
47 // NOTE: If one of the following asserts fail, it's because the corresponding
48 // enum in item-prop-enum.h was modified, but rltiles/dc-item.txt was not
49 // modified in parallel.
50
51 // These brands start with "normal" which there's no tile for, so subtract 1.
52 COMPILE_CHECK(NUM_REAL_SPECIAL_WEAPONS - 1
53 == TILE_BRAND_WEP_LAST - TILE_BRAND_WEP_FIRST + 1);
54 COMPILE_CHECK(NUM_REAL_SPECIAL_ARMOURS - 1
55 == TILE_BRAND_ARM_LAST - TILE_BRAND_ARM_FIRST + 1);
56
57 COMPILE_CHECK(NUM_RINGS == TILE_RING_ID_LAST - TILE_RING_ID_FIRST + 1);
58 COMPILE_CHECK(NUM_JEWELLERY - AMU_FIRST_AMULET
59 == TILE_AMU_ID_LAST - TILE_AMU_ID_FIRST + 1);
60 COMPILE_CHECK(NUM_SCROLLS == TILE_SCR_ID_LAST - TILE_SCR_ID_FIRST + 1);
61 COMPILE_CHECK(NUM_STAVES == TILE_STAFF_ID_LAST - TILE_STAFF_ID_FIRST + 1);
62 #if TAG_MAJOR_VERSION == 34
63 COMPILE_CHECK(NUM_RODS == TILE_ROD_ID_LAST - TILE_ROD_ID_FIRST + 1);
64 #endif
65 COMPILE_CHECK(NUM_WANDS == TILE_WAND_ID_LAST - TILE_WAND_ID_FIRST + 1);
66 COMPILE_CHECK(NUM_POTIONS == TILE_POT_ID_LAST - TILE_POT_ID_FIRST + 1);
67
get_tile_texture(tileidx_t idx)68 TextureID get_tile_texture(tileidx_t idx)
69 {
70 if (idx < TILE_FLOOR_MAX)
71 return TEX_FLOOR;
72 else if (idx < TILE_WALL_MAX)
73 return TEX_WALL;
74 else if (idx < TILE_FEAT_MAX)
75 return TEX_FEAT;
76 else if (idx < TILE_MAIN_MAX)
77 return TEX_DEFAULT;
78 else if (idx < TILEP_PLAYER_MAX)
79 return TEX_PLAYER;
80 else if (idx < TILEG_GUI_MAX)
81 return TEX_GUI;
82 else if (idx < TILEI_ICONS_MAX)
83 return TEX_ICONS;
84 else
85 die("Cannot get texture for bad tileidx %" PRIu64, idx);
86 }
87
tileidx_trap(trap_type type)88 tileidx_t tileidx_trap(trap_type type)
89 {
90 switch (type)
91 {
92 case TRAP_ARROW:
93 return TILE_DNGN_TRAP_ARROW;
94 case TRAP_SPEAR:
95 return TILE_DNGN_TRAP_SPEAR;
96 case TRAP_DISPERSAL:
97 return TILE_DNGN_TRAP_DISPERSAL;
98 case TRAP_TELEPORT:
99 return TILE_DNGN_TRAP_TELEPORT;
100 case TRAP_TELEPORT_PERMANENT:
101 return TILE_DNGN_TRAP_TELEPORT_PERMANENT;
102 case TRAP_ALARM:
103 return TILE_DNGN_TRAP_ALARM;
104 case TRAP_BLADE:
105 return TILE_DNGN_TRAP_BLADE;
106 case TRAP_BOLT:
107 return TILE_DNGN_TRAP_BOLT;
108 case TRAP_NET:
109 return TILE_DNGN_TRAP_NET;
110 case TRAP_ZOT:
111 return TILE_DNGN_TRAP_ZOT;
112 case TRAP_DART:
113 return TILE_DNGN_TRAP_DART;
114 case TRAP_SHAFT:
115 return TILE_DNGN_TRAP_SHAFT;
116 case TRAP_GOLUBRIA:
117 return TILE_DNGN_TRAP_GOLUBRIA;
118 case TRAP_PLATE:
119 return TILE_DNGN_TRAP_PLATE;
120 case TRAP_WEB:
121 return TILE_DNGN_TRAP_WEB;
122 default:
123 return TILE_DNGN_ERROR;
124 }
125 }
126
tileidx_shop(const shop_struct * shop)127 tileidx_t tileidx_shop(const shop_struct *shop)
128 {
129 if (!shop)
130 return TILE_DNGN_ERROR;
131
132 switch (shop->type)
133 {
134 case SHOP_WEAPON:
135 case SHOP_WEAPON_ANTIQUE:
136 return TILE_SHOP_WEAPONS;
137 case SHOP_ARMOUR:
138 case SHOP_ARMOUR_ANTIQUE:
139 return TILE_SHOP_ARMOUR;
140 case SHOP_JEWELLERY:
141 return TILE_SHOP_JEWELLERY;
142 #if TAG_MAJOR_VERSION == 34
143 case SHOP_EVOKABLES:
144 return TILE_SHOP_GADGETS;
145 case SHOP_FOOD:
146 return TILE_SHOP_FOOD;
147 #endif
148 case SHOP_BOOK:
149 return TILE_SHOP_BOOKS;
150 case SHOP_SCROLL:
151 return TILE_SHOP_SCROLLS;
152 case SHOP_DISTILLERY:
153 return TILE_SHOP_POTIONS;
154 case SHOP_GENERAL:
155 case SHOP_GENERAL_ANTIQUE:
156 return TILE_SHOP_GENERAL;
157 default:
158 return TILE_DNGN_ERROR;
159 }
160 }
161
tileidx_feature_base(dungeon_feature_type feat)162 tileidx_t tileidx_feature_base(dungeon_feature_type feat)
163 {
164 switch (feat)
165 {
166 case DNGN_UNSEEN:
167 return TILE_DNGN_UNSEEN;
168 case DNGN_ROCK_WALL:
169 return TILE_WALL_NORMAL;
170 case DNGN_PERMAROCK_WALL:
171 return TILE_WALL_PERMAROCK;
172 case DNGN_SLIMY_WALL:
173 return TILE_WALL_SLIME;
174 case DNGN_RUNED_DOOR:
175 return TILE_DNGN_RUNED_DOOR;
176 case DNGN_RUNED_CLEAR_DOOR:
177 return TILE_DNGN_RUNED_CLEAR_DOOR;
178 case DNGN_SEALED_DOOR:
179 return TILE_DNGN_SEALED_DOOR;
180 case DNGN_SEALED_CLEAR_DOOR:
181 return TILE_DNGN_SEALED_CLEAR_DOOR;
182 case DNGN_GRATE:
183 return TILE_DNGN_GRATE;
184 case DNGN_CLEAR_ROCK_WALL:
185 return TILE_DNGN_TRANSPARENT_WALL;
186 case DNGN_CLEAR_STONE_WALL:
187 return TILE_DNGN_TRANSPARENT_STONE;
188 case DNGN_CLEAR_PERMAROCK_WALL:
189 return TILE_WALL_PERMAROCK_CLEAR;
190 case DNGN_STONE_WALL:
191 return TILE_DNGN_STONE_WALL;
192 case DNGN_CLOSED_DOOR:
193 return TILE_DNGN_CLOSED_DOOR;
194 case DNGN_CLOSED_CLEAR_DOOR:
195 return TILE_DNGN_CLOSED_CLEAR_DOOR;
196 case DNGN_METAL_WALL:
197 return TILE_DNGN_METAL_WALL;
198 case DNGN_CRYSTAL_WALL:
199 return TILE_DNGN_CRYSTAL_WALL;
200 case DNGN_ORCISH_IDOL:
201 return TILE_DNGN_ORCISH_IDOL;
202 case DNGN_TREE:
203 return TILE_DNGN_TREE;
204 case DNGN_MANGROVE:
205 return TILE_DNGN_MANGROVE;
206 case DNGN_PETRIFIED_TREE:
207 return TILE_DNGN_PETRIFIED_TREE;
208 case DNGN_DEMONIC_TREE:
209 return TILE_DNGN_DEMONIC_TREE;
210 case DNGN_GRANITE_STATUE:
211 return TILE_DNGN_GRANITE_STATUE;
212 case DNGN_LAVA:
213 return TILE_DNGN_LAVA;
214 case DNGN_LAVA_SEA:
215 return TILE_DNGN_LAVA_SEA;
216 case DNGN_DEEP_WATER:
217 return TILE_DNGN_DEEP_WATER;
218 case DNGN_SHALLOW_WATER:
219 return TILE_DNGN_SHALLOW_WATER;
220 case DNGN_OPEN_SEA:
221 return TILE_DNGN_OPEN_SEA;
222 case DNGN_TOXIC_BOG:
223 return TILE_DNGN_TOXIC_BOG;
224 case DNGN_FLOOR:
225 return TILE_FLOOR_NORMAL;
226 case DNGN_ENDLESS_SALT:
227 return TILE_DNGN_ENDLESS_SALT;
228 case DNGN_ENTER_HELL:
229 if (player_in_hell())
230 return TILE_DNGN_RETURN_VESTIBULE;
231 return TILE_DNGN_ENTER_HELL;
232 case DNGN_OPEN_DOOR:
233 return TILE_DNGN_OPEN_DOOR;
234 case DNGN_OPEN_CLEAR_DOOR:
235 return TILE_DNGN_OPEN_CLEAR_DOOR;
236 #if TAG_MAJOR_VERSION == 34
237 case DNGN_TRAP_MECHANICAL:
238 return TILE_DNGN_TRAP_ARROW;
239 #endif
240 case DNGN_TRAP_ARROW:
241 return TILE_DNGN_TRAP_ARROW;
242 case DNGN_TRAP_SPEAR:
243 return TILE_DNGN_TRAP_SPEAR;
244 case DNGN_TRAP_BLADE:
245 return TILE_DNGN_TRAP_BLADE;
246 case DNGN_TRAP_DART:
247 return TILE_DNGN_TRAP_DART;
248 case DNGN_TRAP_BOLT:
249 return TILE_DNGN_TRAP_BOLT;
250 case DNGN_TRAP_NET:
251 return TILE_DNGN_TRAP_NET;
252 case DNGN_TRAP_PLATE:
253 return TILE_DNGN_TRAP_PLATE;
254 case DNGN_TRAP_DISPERSAL:
255 return TILE_DNGN_TRAP_DISPERSAL;
256 case DNGN_TRAP_TELEPORT:
257 return TILE_DNGN_TRAP_TELEPORT;
258 case DNGN_TRAP_TELEPORT_PERMANENT:
259 return TILE_DNGN_TRAP_TELEPORT_PERMANENT;
260 case DNGN_TRAP_ALARM:
261 return TILE_DNGN_TRAP_ALARM;
262 case DNGN_TRAP_ZOT:
263 return TILE_DNGN_TRAP_ZOT;
264 case DNGN_TRAP_SHAFT:
265 return TILE_DNGN_TRAP_SHAFT;
266 case DNGN_TRAP_WEB:
267 return TILE_DNGN_TRAP_WEB;
268 #if TAG_MAJOR_VERSION == 34
269 case DNGN_TELEPORTER:
270 return TILE_DNGN_TRAP_GOLUBRIA;
271 #endif
272 case DNGN_TRANSPORTER:
273 return TILE_DNGN_TRANSPORTER;
274 case DNGN_TRANSPORTER_LANDING:
275 return TILE_DNGN_TRANSPORTER_LANDING;
276 case DNGN_ENTER_SHOP:
277 return TILE_SHOP_GENERAL;
278 case DNGN_ABANDONED_SHOP:
279 return TILE_DNGN_ABANDONED_SHOP;
280 case DNGN_ENTER_GAUNTLET:
281 return TILE_DNGN_PORTAL_GAUNTLET;
282 case DNGN_STONE_STAIRS_DOWN_I:
283 case DNGN_STONE_STAIRS_DOWN_II:
284 case DNGN_STONE_STAIRS_DOWN_III:
285 return TILE_DNGN_STONE_STAIRS_DOWN;
286 case DNGN_ESCAPE_HATCH_DOWN:
287 return TILE_DNGN_ESCAPE_HATCH_DOWN;
288 case DNGN_SEALED_STAIRS_DOWN:
289 return TILE_DNGN_SEALED_STAIRS_DOWN;
290 case DNGN_STONE_STAIRS_UP_I:
291 case DNGN_STONE_STAIRS_UP_II:
292 case DNGN_STONE_STAIRS_UP_III:
293 return TILE_DNGN_STONE_STAIRS_UP;
294 case DNGN_EXIT_GAUNTLET:
295 case DNGN_ESCAPE_HATCH_UP:
296 return TILE_DNGN_ESCAPE_HATCH_UP;
297 case DNGN_SEALED_STAIRS_UP:
298 return TILE_DNGN_SEALED_STAIRS_UP;
299 case DNGN_EXIT_DUNGEON:
300 return TILE_DNGN_EXIT_DUNGEON;
301 case DNGN_ENTER_DIS:
302 return TILE_DNGN_ENTER_DIS;
303 case DNGN_ENTER_GEHENNA:
304 return TILE_DNGN_ENTER_GEHENNA;
305 case DNGN_ENTER_COCYTUS:
306 return TILE_DNGN_ENTER_COCYTUS;
307 case DNGN_ENTER_TARTARUS:
308 return TILE_DNGN_ENTER_TARTARUS;
309 case DNGN_ENTER_ABYSS:
310 case DNGN_EXIT_THROUGH_ABYSS:
311 return TILE_DNGN_ENTER_ABYSS;
312 case DNGN_ABYSSAL_STAIR:
313 return TILE_DNGN_ABYSSAL_STAIR;
314 case DNGN_EXIT_HELL:
315 return TILE_DNGN_RETURN_HELL;
316 case DNGN_EXIT_ABYSS:
317 return TILE_DNGN_EXIT_ABYSS;
318 case DNGN_STONE_ARCH:
319 if (player_in_branch(BRANCH_VESTIBULE))
320 return TILE_DNGN_STONE_ARCH_HELL;
321 return TILE_DNGN_STONE_ARCH;
322 case DNGN_ENTER_PANDEMONIUM:
323 return TILE_DNGN_ENTER_PANDEMONIUM;
324 case DNGN_TRANSIT_PANDEMONIUM:
325 return TILE_DNGN_TRANSIT_PANDEMONIUM;
326 case DNGN_EXIT_PANDEMONIUM:
327 return TILE_DNGN_EXIT_PANDEMONIUM;
328
329 // branch entry stairs
330 #if TAG_MAJOR_VERSION == 34
331 case DNGN_ENTER_DWARF:
332 case DNGN_ENTER_FOREST:
333 case DNGN_ENTER_BLADE:
334 return TILE_DNGN_ENTER;
335 #endif
336 case DNGN_ENTER_TEMPLE:
337 return TILE_DNGN_ENTER_TEMPLE;
338 case DNGN_ENTER_ORC:
339 return TILE_DNGN_ENTER_ORC;
340 case DNGN_ENTER_ELF:
341 return TILE_DNGN_ENTER_ELF;
342 case DNGN_ENTER_LAIR:
343 return TILE_DNGN_ENTER_LAIR;
344 case DNGN_ENTER_SNAKE:
345 return TILE_DNGN_ENTER_SNAKE;
346 case DNGN_ENTER_SWAMP:
347 return TILE_DNGN_ENTER_SWAMP;
348 case DNGN_ENTER_SPIDER:
349 return TILE_DNGN_ENTER_SPIDER;
350 case DNGN_ENTER_SHOALS:
351 return TILE_DNGN_ENTER_SHOALS;
352 case DNGN_ENTER_SLIME:
353 return TILE_DNGN_ENTER_SLIME;
354 case DNGN_ENTER_DEPTHS:
355 return TILE_DNGN_ENTER_DEPTHS;
356 case DNGN_ENTER_VAULTS:
357 return you.level_visited(level_id(BRANCH_VAULTS, 1)) ? TILE_DNGN_ENTER_VAULTS_OPEN
358 : TILE_DNGN_ENTER_VAULTS_CLOSED;
359 case DNGN_ENTER_CRYPT:
360 return TILE_DNGN_ENTER_CRYPT;
361 case DNGN_ENTER_TOMB:
362 return TILE_DNGN_ENTER_TOMB;
363 case DNGN_ENTER_ZOT:
364 return you.level_visited(level_id(BRANCH_ZOT, 1)) ? TILE_DNGN_ENTER_ZOT_OPEN
365 : TILE_DNGN_ENTER_ZOT_CLOSED;
366 case DNGN_ENTER_ZIGGURAT:
367 return TILE_DNGN_PORTAL_ZIGGURAT;
368 case DNGN_ENTER_BAZAAR:
369 return TILE_DNGN_PORTAL_BAZAAR;
370 case DNGN_ENTER_TROVE:
371 return TILE_DNGN_PORTAL_TROVE;
372 case DNGN_ENTER_SEWER:
373 return TILE_DNGN_PORTAL_SEWER;
374 case DNGN_ENTER_OSSUARY:
375 return TILE_DNGN_PORTAL_OSSUARY;
376 case DNGN_ENTER_BAILEY:
377 return TILE_DNGN_PORTAL_BAILEY;
378 case DNGN_ENTER_ICE_CAVE:
379 return TILE_DNGN_PORTAL_ICE_CAVE;
380 case DNGN_ENTER_VOLCANO:
381 return TILE_DNGN_PORTAL_VOLCANO;
382 case DNGN_ENTER_WIZLAB:
383 return TILE_DNGN_PORTAL_WIZARD_LAB;
384 case DNGN_ENTER_DESOLATION:
385 return TILE_DNGN_PORTAL_DESOLATION;
386
387 // branch exit stairs
388 #if TAG_MAJOR_VERSION == 34
389 case DNGN_EXIT_DWARF:
390 case DNGN_EXIT_FOREST:
391 case DNGN_EXIT_BLADE:
392 return TILE_DNGN_RETURN;
393 #endif
394 case DNGN_EXIT_TEMPLE:
395 return TILE_DNGN_EXIT_TEMPLE;
396 case DNGN_EXIT_ORC:
397 return TILE_DNGN_EXIT_ORC;
398 case DNGN_EXIT_ELF:
399 return TILE_DNGN_EXIT_ELF;
400 case DNGN_EXIT_LAIR:
401 return TILE_DNGN_EXIT_LAIR;
402 case DNGN_EXIT_SNAKE:
403 return TILE_DNGN_EXIT_SNAKE;
404 case DNGN_EXIT_SWAMP:
405 return TILE_DNGN_EXIT_SWAMP;
406 case DNGN_EXIT_SPIDER:
407 return TILE_DNGN_EXIT_SPIDER;
408 case DNGN_EXIT_SHOALS:
409 return TILE_DNGN_EXIT_SHOALS;
410 case DNGN_EXIT_SLIME:
411 return TILE_DNGN_EXIT_SLIME;
412 case DNGN_EXIT_DEPTHS:
413 return TILE_DNGN_RETURN_DEPTHS;
414 case DNGN_EXIT_VAULTS:
415 return TILE_DNGN_EXIT_VAULTS;
416 case DNGN_EXIT_CRYPT:
417 return TILE_DNGN_EXIT_CRYPT;
418 case DNGN_EXIT_TOMB:
419 return TILE_DNGN_EXIT_TOMB;
420 case DNGN_EXIT_ZOT:
421 return TILE_DNGN_RETURN_ZOT;
422
423 case DNGN_EXIT_ZIGGURAT:
424 case DNGN_EXIT_BAZAAR:
425 case DNGN_EXIT_TROVE:
426 case DNGN_EXIT_SEWER:
427 case DNGN_EXIT_OSSUARY:
428 case DNGN_EXIT_BAILEY:
429 case DNGN_EXIT_DESOLATION:
430 return TILE_DNGN_PORTAL;
431 case DNGN_EXIT_ICE_CAVE:
432 return TILE_DNGN_PORTAL_ICE_CAVE;
433 case DNGN_EXIT_VOLCANO:
434 return TILE_DNGN_EXIT_VOLCANO;
435 case DNGN_EXIT_WIZLAB:
436 return TILE_DNGN_PORTAL_WIZARD_LAB;
437
438 #if TAG_MAJOR_VERSION == 34
439 case DNGN_ENTER_PORTAL_VAULT:
440 case DNGN_EXIT_PORTAL_VAULT:
441 return TILE_DNGN_PORTAL;
442 #endif
443 case DNGN_EXPIRED_PORTAL:
444 return TILE_DNGN_PORTAL_EXPIRED;
445 case DNGN_MALIGN_GATEWAY:
446 return TILE_DNGN_STARRY_PORTAL;
447
448 // altars
449 case DNGN_ALTAR_ZIN:
450 return TILE_DNGN_ALTAR_ZIN;
451 case DNGN_ALTAR_SHINING_ONE:
452 return TILE_DNGN_ALTAR_SHINING_ONE;
453 case DNGN_ALTAR_KIKUBAAQUDGHA:
454 return TILE_DNGN_ALTAR_KIKUBAAQUDGHA;
455 case DNGN_ALTAR_YREDELEMNUL:
456 return TILE_DNGN_ALTAR_YREDELEMNUL;
457 case DNGN_ALTAR_XOM:
458 return TILE_DNGN_ALTAR_XOM;
459 case DNGN_ALTAR_VEHUMET:
460 return TILE_DNGN_ALTAR_VEHUMET;
461 case DNGN_ALTAR_OKAWARU:
462 return TILE_DNGN_ALTAR_OKAWARU;
463 case DNGN_ALTAR_MAKHLEB:
464 return TILE_DNGN_ALTAR_MAKHLEB;
465 case DNGN_ALTAR_SIF_MUNA:
466 return TILE_DNGN_ALTAR_SIF_MUNA;
467 case DNGN_ALTAR_TROG:
468 return TILE_DNGN_ALTAR_TROG;
469 case DNGN_ALTAR_NEMELEX_XOBEH:
470 return TILE_DNGN_ALTAR_NEMELEX_XOBEH;
471 case DNGN_ALTAR_ELYVILON:
472 return TILE_DNGN_ALTAR_ELYVILON;
473 case DNGN_ALTAR_LUGONU:
474 return TILE_DNGN_ALTAR_LUGONU;
475 case DNGN_ALTAR_BEOGH:
476 return TILE_DNGN_ALTAR_BEOGH;
477 case DNGN_ALTAR_JIYVA:
478 return TILE_DNGN_ALTAR_JIYVA;
479 case DNGN_ALTAR_FEDHAS:
480 return TILE_DNGN_ALTAR_FEDHAS;
481 case DNGN_ALTAR_CHEIBRIADOS:
482 return TILE_DNGN_ALTAR_CHEIBRIADOS;
483 case DNGN_ALTAR_ASHENZARI:
484 return TILE_DNGN_ALTAR_ASHENZARI;
485 case DNGN_ALTAR_DITHMENOS:
486 return TILE_DNGN_ALTAR_DITHMENOS;
487 case DNGN_ALTAR_GOZAG:
488 return TILE_DNGN_ALTAR_GOZAG;
489 case DNGN_ALTAR_QAZLAL:
490 return TILE_DNGN_ALTAR_QAZLAL;
491 case DNGN_ALTAR_RU:
492 return TILE_DNGN_ALTAR_RU;
493 #if TAG_MAJOR_VERSION == 34
494 case DNGN_ALTAR_PAKELLAS:
495 return TILE_DNGN_ALTAR_PAKELLAS;
496 #endif
497 case DNGN_ALTAR_USKAYAW:
498 return TILE_DNGN_ALTAR_USKAYAW;
499 case DNGN_ALTAR_HEPLIAKLQANA:
500 return TILE_DNGN_ALTAR_HEPLIAKLQANA;
501 case DNGN_ALTAR_WU_JIAN:
502 return TILE_DNGN_ALTAR_WU_JIAN;
503 case DNGN_ALTAR_ECUMENICAL:
504 return TILE_DNGN_ALTAR_ECUMENICAL;
505 case DNGN_FOUNTAIN_BLUE:
506 return TILE_DNGN_BLUE_FOUNTAIN;
507 case DNGN_FOUNTAIN_SPARKLING:
508 return TILE_DNGN_SPARKLING_FOUNTAIN;
509 case DNGN_FOUNTAIN_BLOOD:
510 return TILE_DNGN_BLOOD_FOUNTAIN;
511 case DNGN_DRY_FOUNTAIN:
512 return TILE_DNGN_DRY_FOUNTAIN;
513 case DNGN_PASSAGE_OF_GOLUBRIA:
514 return TILE_DNGN_TRAP_GOLUBRIA;
515 case DNGN_UNKNOWN_ALTAR:
516 return TILE_DNGN_UNKNOWN_ALTAR;
517 case DNGN_UNKNOWN_PORTAL:
518 return TILE_DNGN_UNKNOWN_PORTAL;
519 default:
520 return TILE_DNGN_ERROR;
521 }
522 }
523
is_door_tile(tileidx_t tile)524 bool is_door_tile(tileidx_t tile)
525 {
526 return tile >= TILE_DNGN_CLOSED_DOOR &&
527 tile < TILE_DNGN_STONE_ARCH;
528 }
529
tileidx_feature(const coord_def & gc)530 tileidx_t tileidx_feature(const coord_def &gc)
531 {
532 dungeon_feature_type feat = env.map_knowledge(gc).feat();
533
534 tileidx_t override = tile_env.flv(gc).feat;
535 bool can_override = !feat_is_door(feat)
536 && feat != DNGN_FLOOR
537 && feat != DNGN_UNSEEN
538 && feat != DNGN_PASSAGE_OF_GOLUBRIA
539 && feat != DNGN_MALIGN_GATEWAY;
540 if (override && can_override)
541 return override;
542
543 // Any grid-specific tiles.
544 switch (feat)
545 {
546 case DNGN_FLOOR:
547 if (env.level_state & LSTATE_SLIMY_WALL)
548 for (adjacent_iterator ai(gc); ai; ++ai)
549 if (env.map_knowledge(*ai).feat() == DNGN_SLIMY_WALL)
550 return TILE_FLOOR_SLIME_ACIDIC;
551
552 if (env.level_state & LSTATE_ICY_WALL)
553 {
554 for (adjacent_iterator ai(gc); ai; ++ai)
555 {
556 if (feat_is_wall(env.map_knowledge(*ai).feat())
557 && env.map_knowledge(*ai).flags & MAP_ICY)
558 {
559 return TILE_FLOOR_ICY;
560 }
561 }
562 }
563 // deliberate fall-through
564 case DNGN_ROCK_WALL:
565 case DNGN_STONE_WALL:
566 case DNGN_CRYSTAL_WALL:
567 case DNGN_PERMAROCK_WALL:
568 case DNGN_CLEAR_PERMAROCK_WALL:
569 {
570 unsigned colour = env.map_knowledge(gc).feat_colour();
571 if (colour == 0)
572 {
573 colour = feat == DNGN_FLOOR ? env.floor_colour :
574 feat == DNGN_ROCK_WALL ? env.rock_colour
575 : 0; // meh
576 }
577 if (colour >= ETC_FIRST)
578 {
579 tileidx_t idx = (feat == DNGN_FLOOR) ? tile_env.flv(gc).floor :
580 (feat == DNGN_ROCK_WALL) ? tile_env.flv(gc).wall
581 : tileidx_feature_base(feat);
582
583 #ifdef USE_TILE
584 if (feat == DNGN_STONE_WALL)
585 apply_variations(tile_env.flv(gc), &idx, gc);
586 #endif
587
588 tileidx_t base = tile_dngn_basetile(idx);
589 tileidx_t spec = idx - base;
590 unsigned rc = real_colour(colour, gc);
591 return tile_dngn_coloured(base, rc) + spec; // XXX
592 }
593 return tileidx_feature_base(feat);
594 }
595
596 #if TAG_MAJOR_VERSION == 34
597 // New trap-type-specific features are handled in default case.
598 case DNGN_TRAP_MECHANICAL:
599 case DNGN_TRAP_TELEPORT:
600 return tileidx_trap(env.map_knowledge(gc).trap());
601 #endif
602
603 case DNGN_TRAP_WEB:
604 {
605 /*
606 trap_type this_trap_type = get_trap_type(gc);
607 // There's room here to have different types of webs (acid? fire? ice? different strengths?)
608 if (this_trap_type==TRAP_WEB) {*/
609
610 // Determine web connectivity on all sides
611 const coord_def neigh[4] =
612 {
613 coord_def(gc.x, gc.y - 1),
614 coord_def(gc.x + 1, gc.y),
615 coord_def(gc.x, gc.y + 1),
616 coord_def(gc.x - 1, gc.y),
617 };
618 int solid = 0;
619 for (int i = 0; i < 4; i++)
620 if (feat_is_solid(env.map_knowledge(neigh[i]).feat())
621 || env.map_knowledge(neigh[i]).trap() == TRAP_WEB)
622 {
623 solid |= 1 << i;
624 }
625 if (solid)
626 return TILE_DNGN_TRAP_WEB_N - 1 + solid;
627 return TILE_DNGN_TRAP_WEB;
628 }
629 case DNGN_ENTER_SHOP:
630 return tileidx_shop(shop_at(gc));
631
632 case DNGN_DEEP_WATER:
633 if (env.map_knowledge(gc).feat_colour() == GREEN
634 || env.map_knowledge(gc).feat_colour() == LIGHTGREEN)
635 {
636 return TILE_DNGN_DEEP_WATER_MURKY;
637 }
638 else if (player_in_branch(BRANCH_SHOALS))
639 return TILE_SHOALS_DEEP_WATER;
640
641 return TILE_DNGN_DEEP_WATER;
642 case DNGN_SHALLOW_WATER:
643 {
644 tileidx_t t = TILE_DNGN_SHALLOW_WATER;
645 if (env.map_knowledge(gc).feat_colour() == GREEN
646 || env.map_knowledge(gc).feat_colour() == LIGHTGREEN)
647 {
648 t = TILE_DNGN_SHALLOW_WATER_MURKY;
649 }
650 else if (player_in_branch(BRANCH_SHOALS))
651 t = TILE_SHOALS_SHALLOW_WATER;
652
653 if (env.map_knowledge(gc).invisible_monster())
654 {
655 // Add disturbance to tile.
656 t += tile_dngn_count(t);
657 }
658
659 return t;
660 }
661 default:
662 return tileidx_feature_base(feat);
663 }
664 }
665
_mon_random(tileidx_t tile,int mon_id)666 static tileidx_t _mon_random(tileidx_t tile, int mon_id)
667 {
668 int count = tile_player_count(tile);
669 return tile + hash_with_seed(count, mon_id, you.frame_no);
670 }
671
672 #ifdef USE_TILE
_mons_is_kraken_tentacle(const int mtype)673 static bool _mons_is_kraken_tentacle(const int mtype)
674 {
675 return mtype == MONS_KRAKEN_TENTACLE
676 || mtype == MONS_KRAKEN_TENTACLE_SEGMENT;
677 }
678 #endif
679
tileidx_tentacle(const monster_info & mon)680 tileidx_t tileidx_tentacle(const monster_info& mon)
681 {
682 ASSERT(mons_is_tentacle_or_tentacle_segment(mon.type));
683
684 // If the tentacle is submerged, we shouldn't even get here.
685 ASSERT(!mon.is(MB_SUBMERGED));
686
687 // Get tentacle position.
688 const coord_def t_pos = mon.pos;
689 // No parent tentacle, or the connection to the head is unknown.
690 bool no_head_connect = !mon.props.exists("inwards");
691 coord_def h_pos = coord_def(); // head position
692 if (!no_head_connect)
693 {
694 // Get the parent tentacle's location.
695 h_pos = t_pos + mon.props["inwards"].get_coord();
696 }
697 if (no_head_connect && (mon.type == MONS_SNAPLASHER_VINE
698 || mon.type == MONS_SNAPLASHER_VINE_SEGMENT))
699 {
700 // Find an adjacent tree to pretend we're connected to.
701 for (adjacent_iterator ai(t_pos); ai; ++ai)
702 {
703 if (feat_is_tree(env.grid(*ai)))
704 {
705 h_pos = *ai;
706 no_head_connect = false;
707 break;
708 }
709 }
710 }
711
712 // Is there a connection to the given direction?
713 // (either through head or next)
714 bool north = false, east = false,
715 south = false, west = false,
716 north_east = false, south_east = false,
717 south_west = false, north_west = false;
718
719 if (!no_head_connect)
720 {
721 if (h_pos.x == t_pos.x)
722 {
723 if (h_pos.y < t_pos.y)
724 north = true;
725 else
726 south = true;
727 }
728 else if (h_pos.y == t_pos.y)
729 {
730 if (h_pos.x < t_pos.x)
731 west = true;
732 else
733 east = true;
734 }
735 else if (h_pos.x < t_pos.x)
736 {
737 if (h_pos.y < t_pos.y)
738 north_west = true;
739 else
740 south_west = true;
741 }
742 else if (h_pos.x > t_pos.x)
743 {
744 if (h_pos.y < t_pos.y)
745 north_east = true;
746 else
747 south_east = true;
748 }
749 }
750
751 // Tentacle only requires checking of head position.
752 if (mons_is_tentacle(mon.type))
753 {
754 if (no_head_connect)
755 {
756 tileidx_t tile;
757 switch (mon.type)
758 {
759 case MONS_KRAKEN_TENTACLE: tile = TILEP_MONS_KRAKEN_TENTACLE_WATER; break;
760 case MONS_STARSPAWN_TENTACLE: tile = TILEP_MONS_STARSPAWN_TENTACLE_S; break;
761 case MONS_ELDRITCH_TENTACLE: tile = TILEP_MONS_ELDRITCH_TENTACLE_PORTAL; break;
762 case MONS_SNAPLASHER_VINE: tile = TILEP_MONS_VINE_S; break;
763 default: die("bad tentacle type");
764 }
765
766 bool vary = !(mon.props.exists("fake") && mon.props["fake"].get_bool());
767 return vary ? _mon_random(tile, t_pos.y*GXM + t_pos.x) : tile;
768 }
769
770 // Different handling according to relative positions.
771 if (north)
772 return TILEP_MONS_KRAKEN_TENTACLE_N;
773 if (south)
774 return TILEP_MONS_KRAKEN_TENTACLE_S;
775 if (west)
776 return TILEP_MONS_KRAKEN_TENTACLE_W;
777 if (east)
778 return TILEP_MONS_KRAKEN_TENTACLE_E;
779 if (north_west)
780 return TILEP_MONS_KRAKEN_TENTACLE_NW;
781 if (south_west)
782 return TILEP_MONS_KRAKEN_TENTACLE_SW;
783 if (north_east)
784 return TILEP_MONS_KRAKEN_TENTACLE_NE;
785 if (south_east)
786 return TILEP_MONS_KRAKEN_TENTACLE_SE;
787 die("impossible kraken direction");
788 }
789 // Only tentacle segments from now on.
790 ASSERT(mons_is_tentacle_segment(mon.type));
791
792 // For segments, we also need the next segment (or end piece).
793 coord_def n_pos;
794 bool no_next_connect = !mon.props.exists("outwards");
795 if (!no_next_connect)
796 n_pos = t_pos + mon.props["outwards"].get_coord();
797
798 if (no_head_connect && no_next_connect)
799 {
800 // Both head and next are submerged.
801 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_WATER;
802 }
803
804 if (!no_next_connect)
805 {
806 if (n_pos.x == t_pos.x)
807 {
808 if (n_pos.y < t_pos.y)
809 north = true;
810 else
811 south = true;
812 }
813 else if (n_pos.y == t_pos.y)
814 {
815 if (n_pos.x < t_pos.x)
816 west = true;
817 else
818 east = true;
819 }
820 else if (n_pos.x < t_pos.x)
821 {
822 if (n_pos.y < t_pos.y)
823 north_west = true;
824 else
825 south_west = true;
826 }
827 else if (n_pos.x > t_pos.x)
828 {
829 if (n_pos.y < t_pos.y)
830 north_east = true;
831 else
832 south_east = true;
833 }
834 }
835
836 if (no_head_connect || no_next_connect)
837 {
838 // One segment end goes into water, the other
839 // into the direction of head or next.
840
841 if (north)
842 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N;
843 if (south)
844 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_S;
845 if (west)
846 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W;
847 if (east)
848 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E;
849 if (north_west)
850 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NW;
851 if (south_west)
852 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_SW;
853 if (north_east)
854 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NE;
855 if (south_east)
856 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_SE;
857 die("impossible kraken direction");
858 }
859
860 // Okay, neither head nor next are submerged.
861 // Compare all three positions.
862
863 // Straight lines first: Vertical.
864 if (north && south)
865 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N_S;
866 // Horizontal.
867 if (east && west)
868 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_W;
869 // Diagonals.
870 if (north_west && south_east)
871 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NW_SE;
872 if (north_east && south_west)
873 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NE_SW;
874
875 // Curved segments.
876 if (east && north)
877 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_N;
878 if (east && south)
879 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_S;
880 if (south && west)
881 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_S_W;
882 if (north && west)
883 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N_W;
884 if (north_east && north_west)
885 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NE_NW;
886 if (south_east && south_west)
887 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_SE_SW;
888 if (north_west && south_west)
889 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NW_SW;
890 if (north_east && south_east)
891 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NE_SE;
892
893 // Connect corners and edges.
894 if (north && south_west)
895 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N_SW;
896 if (north && south_east)
897 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N_SE;
898 if (south && north_west)
899 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_S_NW;
900 if (south && north_east)
901 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_S_NE;
902 if (west && north_east)
903 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W_NE;
904 if (west && south_east)
905 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W_SE;
906 if (east && north_west)
907 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_NW;
908 if (east && south_west)
909 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_SW;
910
911 // Connections at acute angles; can currently only happen for vines.
912 if (north && north_west)
913 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N_NW;
914 if (north && north_east)
915 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N_NE;
916 if (east && north_east)
917 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_NE;
918 if (east && south_east)
919 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_SE;
920 if (south && south_east)
921 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_S_SE;
922 if (south && south_west)
923 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_S_SW;
924 if (west && south_west)
925 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W_SW;
926 if (west && north_west)
927 return TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W_NW;
928
929 return TILEP_MONS_PROGRAM_BUG;
930 }
931
tileidx_out_of_bounds(int branch)932 tileidx_t tileidx_out_of_bounds(int branch)
933 {
934 if (branch == BRANCH_SHOALS)
935 return TILE_DNGN_OPEN_SEA | TILE_FLAG_UNSEEN;
936 else
937 return TILE_DNGN_UNSEEN | TILE_FLAG_UNSEEN;
938 }
939
940 #ifdef USE_TILE
tileidx_out_of_los(tileidx_t * fg,tileidx_t * bg,tileidx_t * cloud,const coord_def & gc)941 void tileidx_out_of_los(tileidx_t *fg, tileidx_t *bg, tileidx_t *cloud, const coord_def& gc)
942 {
943 // Player memory.
944 tileidx_t mem_fg = tile_env.bk_fg(gc);
945 tileidx_t mem_bg = tile_env.bk_bg(gc);
946 tileidx_t mem_cloud = tile_env.bk_cloud(gc);
947
948 // Detected info is just stored in map_knowledge and doesn't get
949 // written to what the player remembers. We'll feather that in here.
950
951 // save any rays, which will get overwritten by mapped terrain
952 auto rays = *bg & (TILE_FLAG_RAY_MULTI | TILE_FLAG_RAY_OOR | TILE_FLAG_RAY
953 | TILE_FLAG_LANDING);
954
955 const map_cell &cell = env.map_knowledge(gc);
956
957 // Override terrain for magic mapping.
958 if (!cell.seen() && env.map_knowledge(gc).mapped())
959 *bg = tileidx_feature_base(cell.feat());
960 else
961 *bg = mem_bg;
962 *bg |= tileidx_unseen_flag(gc);
963
964 // if out-of-los rays are getting shown that shouldn't be, the bug isn't
965 // here -- fix it in the targeter
966 *bg |= rays;
967
968 // Override foreground for monsters/items
969 if (env.map_knowledge(gc).detected_monster())
970 {
971 ASSERT(cell.monster() == MONS_SENSED);
972 *fg = tileidx_monster_base(cell.monsterinfo()->base_type, 0);
973 }
974 else if (env.map_knowledge(gc).detected_item())
975 *fg = tileidx_item(*cell.item());
976 else
977 *fg = mem_fg;
978
979 *cloud = mem_cloud;
980 }
981
_zombie_tile_to_spectral(const tileidx_t z_tile)982 static tileidx_t _zombie_tile_to_spectral(const tileidx_t z_tile)
983 {
984 switch (z_tile)
985 {
986 case TILEP_MONS_ZOMBIE_SMALL:
987 case TILEP_MONS_ZOMBIE_SPRIGGAN:
988 case TILEP_MONS_ZOMBIE_GOBLIN:
989 case TILEP_MONS_ZOMBIE_HOBGOBLIN:
990 case TILEP_MONS_ZOMBIE_GNOLL:
991 case TILEP_MONS_ZOMBIE_KOBOLD:
992 case TILEP_MONS_ZOMBIE_ORC:
993 case TILEP_MONS_ZOMBIE_HUMAN:
994 case TILEP_MONS_ZOMBIE_DRACONIAN:
995 case TILEP_MONS_ZOMBIE_ELF:
996 case TILEP_MONS_ZOMBIE_FAUN:
997 case TILEP_MONS_ZOMBIE_MERFOLK:
998 case TILEP_MONS_ZOMBIE_MINOTAUR:
999 case TILEP_MONS_ZOMBIE_MONKEY:
1000 return TILEP_MONS_SPECTRAL_SMALL;
1001 case TILEP_MONS_ZOMBIE_LARGE:
1002 case TILEP_MONS_ZOMBIE_OGRE:
1003 case TILEP_MONS_ZOMBIE_TROLL:
1004 case TILEP_MONS_ZOMBIE_JUGGERNAUT:
1005 case TILEP_MONS_ZOMBIE_UGLY_THING:
1006 return TILEP_MONS_SPECTRAL_LARGE;
1007 case TILEP_MONS_ZOMBIE_QUADRUPED_SMALL:
1008 case TILEP_MONS_ZOMBIE_RAT:
1009 case TILEP_MONS_ZOMBIE_QUOKKA:
1010 case TILEP_MONS_ZOMBIE_JACKAL:
1011 case TILEP_MONS_ZOMBIE_HOUND:
1012 case TILEP_MONS_ZOMBIE_CRAB:
1013 case TILEP_MONS_ZOMBIE_TURTLE:
1014 case TILEP_MONS_ZOMBIE_BEAR:
1015 return TILEP_MONS_SPECTRAL_QUADRUPED_SMALL;
1016 case TILEP_MONS_ZOMBIE_QUADRUPED_LARGE:
1017 case TILEP_MONS_ZOMBIE_ELEPHANT:
1018 case TILEP_MONS_ZOMBIE_YAK:
1019 case TILEP_MONS_ZOMBIE_QUADRUPED_WINGED:
1020 return TILEP_MONS_SPECTRAL_QUADRUPED_LARGE;
1021 case TILEP_MONS_ZOMBIE_FROG:
1022 return TILEP_MONS_SPECTRAL_FROG;
1023 case TILEP_MONS_ZOMBIE_BAT:
1024 case TILEP_MONS_ZOMBIE_BIRD: /* no bird spectral tile */
1025 case TILEP_MONS_ZOMBIE_HARPY:
1026 return TILEP_MONS_SPECTRAL_BAT;
1027 case TILEP_MONS_ZOMBIE_BEE:
1028 case TILEP_MONS_ZOMBIE_MELIAI:
1029 case TILEP_MONS_ZOMBIE_HORNET:
1030 return TILEP_MONS_SPECTRAL_BEE;
1031 case TILEP_MONS_ZOMBIE_BEETLE:
1032 case TILEP_MONS_ZOMBIE_ROACH:
1033 case TILEP_MONS_ZOMBIE_BUG:
1034 return TILEP_MONS_SPECTRAL_BUG;
1035 case TILEP_MONS_ZOMBIE_FISH:
1036 return TILEP_MONS_SPECTRAL_FISH;
1037 case TILEP_MONS_ZOMBIE_CENTAUR:
1038 case TILEP_MONS_ZOMBIE_YAKTAUR:
1039 return TILEP_MONS_SPECTRAL_CENTAUR;
1040 case TILEP_MONS_ZOMBIE_NAGA:
1041 case TILEP_MONS_ZOMBIE_GUARDIAN_SERPENT:
1042 case TILEP_MONS_ZOMBIE_SALAMANDER:
1043 return TILEP_MONS_SPECTRAL_NAGA;
1044 case TILEP_MONS_ZOMBIE_SNAKE:
1045 case TILEP_MONS_ZOMBIE_ADDER:
1046 case TILEP_MONS_ZOMBIE_WORM:
1047 case TILEP_MONS_ZOMBIE_LINDWURM:
1048 return TILEP_MONS_SPECTRAL_SNAKE;
1049 case TILEP_MONS_ZOMBIE_LIZARD:
1050 return TILEP_MONS_SPECTRAL_LIZARD;
1051 case TILEP_MONS_ZOMBIE_SCORPION:
1052 case TILEP_MONS_ZOMBIE_SPIDER_LARGE:
1053 case TILEP_MONS_ZOMBIE_SPIDER_SMALL:
1054 return TILEP_MONS_SPECTRAL_SPIDER;
1055 case TILEP_MONS_ZOMBIE_DRAGON:
1056 case TILEP_MONS_ZOMBIE_IRON_DRAGON:
1057 case TILEP_MONS_ZOMBIE_GOLDEN_DRAGON:
1058 case TILEP_MONS_ZOMBIE_QUICKSILVER_DRAGON:
1059 return TILEP_MONS_SPECTRAL_DRAGON;
1060 case TILEP_MONS_ZOMBIE_DRAKE:
1061 case TILEP_MONS_ZOMBIE_WYVERN:
1062 return TILEP_MONS_SPECTRAL_DRAKE;
1063 case TILEP_MONS_ZOMBIE_KRAKEN:
1064 return TILEP_MONS_SPECTRAL_KRAKEN;
1065 default:
1066 if (tile_player_basetile(z_tile) == TILEP_MONS_ZOMBIE_HYDRA)
1067 {
1068 return TILEP_MONS_SPECTRAL_HYDRA
1069 + (z_tile - TILEP_MONS_ZOMBIE_HYDRA);
1070 }
1071 }
1072 return TILEP_MONS_SPECTRAL_SMALL;
1073 }
1074
_zombie_tile_to_simulacrum(const tileidx_t z_tile)1075 static tileidx_t _zombie_tile_to_simulacrum(const tileidx_t z_tile)
1076 {
1077 switch (z_tile)
1078 {
1079 case TILEP_MONS_ZOMBIE_SMALL:
1080 case TILEP_MONS_ZOMBIE_SPRIGGAN:
1081 case TILEP_MONS_ZOMBIE_GOBLIN:
1082 case TILEP_MONS_ZOMBIE_HOBGOBLIN:
1083 case TILEP_MONS_ZOMBIE_GNOLL:
1084 case TILEP_MONS_ZOMBIE_KOBOLD:
1085 case TILEP_MONS_ZOMBIE_ORC:
1086 case TILEP_MONS_ZOMBIE_HUMAN:
1087 case TILEP_MONS_ZOMBIE_DRACONIAN:
1088 case TILEP_MONS_ZOMBIE_ELF:
1089 case TILEP_MONS_ZOMBIE_FAUN:
1090 case TILEP_MONS_ZOMBIE_MERFOLK:
1091 case TILEP_MONS_ZOMBIE_MINOTAUR:
1092 case TILEP_MONS_ZOMBIE_MONKEY:
1093 return TILEP_MONS_SIMULACRUM_SMALL;
1094 case TILEP_MONS_ZOMBIE_LARGE:
1095 case TILEP_MONS_ZOMBIE_OGRE:
1096 case TILEP_MONS_ZOMBIE_TROLL:
1097 case TILEP_MONS_ZOMBIE_JUGGERNAUT:
1098 case TILEP_MONS_ZOMBIE_UGLY_THING:
1099 return TILEP_MONS_SIMULACRUM_LARGE;
1100 case TILEP_MONS_ZOMBIE_QUADRUPED_SMALL:
1101 case TILEP_MONS_ZOMBIE_BEAR:
1102 case TILEP_MONS_ZOMBIE_RAT:
1103 case TILEP_MONS_ZOMBIE_QUOKKA:
1104 case TILEP_MONS_ZOMBIE_JACKAL:
1105 case TILEP_MONS_ZOMBIE_HOUND:
1106 case TILEP_MONS_ZOMBIE_CRAB:
1107 case TILEP_MONS_ZOMBIE_TURTLE:
1108 return TILEP_MONS_SIMULACRUM_QUADRUPED_SMALL;
1109 case TILEP_MONS_ZOMBIE_QUADRUPED_LARGE:
1110 case TILEP_MONS_ZOMBIE_FROG:
1111 case TILEP_MONS_ZOMBIE_ELEPHANT:
1112 case TILEP_MONS_ZOMBIE_YAK:
1113 case TILEP_MONS_ZOMBIE_QUADRUPED_WINGED:
1114 return TILEP_MONS_SIMULACRUM_QUADRUPED_LARGE;
1115 case TILEP_MONS_ZOMBIE_BAT:
1116 case TILEP_MONS_ZOMBIE_BIRD: /* no bird simulacrum tile */
1117 case TILEP_MONS_ZOMBIE_HARPY:
1118 return TILEP_MONS_SIMULACRUM_BAT;
1119 case TILEP_MONS_ZOMBIE_BEE:
1120 case TILEP_MONS_ZOMBIE_MELIAI:
1121 case TILEP_MONS_ZOMBIE_HORNET:
1122 return TILEP_MONS_SIMULACRUM_BEE;
1123 case TILEP_MONS_ZOMBIE_BEETLE:
1124 case TILEP_MONS_ZOMBIE_ROACH:
1125 case TILEP_MONS_ZOMBIE_BUG:
1126 return TILEP_MONS_SIMULACRUM_BUG;
1127 case TILEP_MONS_ZOMBIE_FISH:
1128 return TILEP_MONS_SIMULACRUM_FISH;
1129 case TILEP_MONS_ZOMBIE_CENTAUR:
1130 case TILEP_MONS_ZOMBIE_YAKTAUR:
1131 return TILEP_MONS_SIMULACRUM_CENTAUR;
1132 case TILEP_MONS_ZOMBIE_NAGA:
1133 case TILEP_MONS_ZOMBIE_GUARDIAN_SERPENT:
1134 case TILEP_MONS_ZOMBIE_SALAMANDER:
1135 return TILEP_MONS_SIMULACRUM_NAGA;
1136 case TILEP_MONS_ZOMBIE_SNAKE:
1137 case TILEP_MONS_ZOMBIE_ADDER:
1138 case TILEP_MONS_ZOMBIE_WORM:
1139 case TILEP_MONS_ZOMBIE_LINDWURM:
1140 return TILEP_MONS_SIMULACRUM_SNAKE;
1141 case TILEP_MONS_ZOMBIE_LIZARD:
1142 return TILEP_MONS_SIMULACRUM_LIZARD;
1143 case TILEP_MONS_ZOMBIE_SCORPION:
1144 case TILEP_MONS_ZOMBIE_SPIDER_LARGE:
1145 case TILEP_MONS_ZOMBIE_SPIDER_SMALL:
1146 return TILEP_MONS_SIMULACRUM_SPIDER;
1147 case TILEP_MONS_ZOMBIE_DRAGON:
1148 case TILEP_MONS_ZOMBIE_IRON_DRAGON:
1149 case TILEP_MONS_ZOMBIE_GOLDEN_DRAGON:
1150 case TILEP_MONS_ZOMBIE_QUICKSILVER_DRAGON:
1151 return TILEP_MONS_SIMULACRUM_DRAGON;
1152 case TILEP_MONS_ZOMBIE_DRAKE:
1153 case TILEP_MONS_ZOMBIE_WYVERN:
1154 return TILEP_MONS_SIMULACRUM_DRAKE;
1155 case TILEP_MONS_ZOMBIE_KRAKEN:
1156 return TILEP_MONS_SIMULACRUM_KRAKEN;
1157 default:
1158 if (tile_player_basetile(z_tile) == TILEP_MONS_ZOMBIE_HYDRA)
1159 {
1160 return TILEP_MONS_SIMULACRUM_HYDRA
1161 + (z_tile - TILEP_MONS_ZOMBIE_HYDRA);
1162 }
1163 }
1164 return TILEP_MONS_SIMULACRUM_SMALL;
1165 }
1166
_zombie_tile_to_skeleton(const tileidx_t z_tile)1167 static tileidx_t _zombie_tile_to_skeleton(const tileidx_t z_tile)
1168 {
1169 switch (z_tile)
1170 {
1171 case TILEP_MONS_ZOMBIE_SMALL:
1172 case TILEP_MONS_ZOMBIE_SPRIGGAN:
1173 case TILEP_MONS_ZOMBIE_GOBLIN:
1174 case TILEP_MONS_ZOMBIE_KOBOLD:
1175 case TILEP_MONS_ZOMBIE_MONKEY:
1176 return TILEP_MONS_SKELETON_SMALL;
1177 case TILEP_MONS_ZOMBIE_HOBGOBLIN:
1178 case TILEP_MONS_ZOMBIE_GNOLL:
1179 case TILEP_MONS_ZOMBIE_ORC:
1180 case TILEP_MONS_ZOMBIE_HUMAN:
1181 case TILEP_MONS_ZOMBIE_ELF:
1182 case TILEP_MONS_ZOMBIE_MERFOLK:
1183 case TILEP_MONS_ZOMBIE_MINOTAUR:
1184 case TILEP_MONS_ZOMBIE_FAUN:
1185 return TILEP_MONS_SKELETON_MEDIUM;
1186 case TILEP_MONS_ZOMBIE_TROLL:
1187 return TILEP_MONS_SKELETON_TROLL;
1188 case TILEP_MONS_ZOMBIE_LARGE:
1189 case TILEP_MONS_ZOMBIE_OGRE:
1190 case TILEP_MONS_ZOMBIE_JUGGERNAUT:
1191 return TILEP_MONS_SKELETON_LARGE;
1192 case TILEP_MONS_ZOMBIE_QUADRUPED_SMALL:
1193 case TILEP_MONS_ZOMBIE_RAT:
1194 case TILEP_MONS_ZOMBIE_QUOKKA:
1195 case TILEP_MONS_ZOMBIE_JACKAL:
1196 case TILEP_MONS_ZOMBIE_HOUND:
1197 case TILEP_MONS_ZOMBIE_BEETLE:
1198 case TILEP_MONS_ZOMBIE_ROACH:
1199 case TILEP_MONS_ZOMBIE_BEAR:
1200 case TILEP_MONS_ZOMBIE_BUG:
1201 return TILEP_MONS_SKELETON_QUADRUPED_SMALL;
1202 case TILEP_MONS_ZOMBIE_LIZARD:
1203 case TILEP_MONS_ZOMBIE_CRAB:
1204 return TILEP_MONS_SKELETON_LIZARD;
1205 case TILEP_MONS_ZOMBIE_TURTLE:
1206 return TILEP_MONS_SKELETON_TURTLE;
1207 case TILEP_MONS_ZOMBIE_QUADRUPED_LARGE:
1208 case TILEP_MONS_ZOMBIE_ELEPHANT:
1209 case TILEP_MONS_ZOMBIE_YAK:
1210 return TILEP_MONS_SKELETON_QUADRUPED_LARGE;
1211 case TILEP_MONS_ZOMBIE_FROG:
1212 return TILEP_MONS_SKELETON_FROG;
1213 case TILEP_MONS_ZOMBIE_QUADRUPED_WINGED:
1214 return TILEP_MONS_SKELETON_QUADRUPED_WINGED;
1215 case TILEP_MONS_ZOMBIE_BAT:
1216 return TILEP_MONS_SKELETON_BAT;
1217 case TILEP_MONS_ZOMBIE_HARPY:
1218 case TILEP_MONS_ZOMBIE_BIRD:
1219 return TILEP_MONS_SKELETON_BIRD;
1220 case TILEP_MONS_ZOMBIE_FISH:
1221 return TILEP_MONS_SKELETON_FISH;
1222 case TILEP_MONS_ZOMBIE_CENTAUR:
1223 case TILEP_MONS_ZOMBIE_YAKTAUR:
1224 return TILEP_MONS_SKELETON_CENTAUR;
1225 case TILEP_MONS_ZOMBIE_NAGA:
1226 case TILEP_MONS_ZOMBIE_GUARDIAN_SERPENT:
1227 case TILEP_MONS_ZOMBIE_SALAMANDER:
1228 return TILEP_MONS_SKELETON_NAGA;
1229 case TILEP_MONS_ZOMBIE_SNAKE:
1230 case TILEP_MONS_ZOMBIE_ADDER:
1231 case TILEP_MONS_ZOMBIE_WORM:
1232 case TILEP_MONS_ZOMBIE_LINDWURM:
1233 return TILEP_MONS_SKELETON_SNAKE;
1234 case TILEP_MONS_ZOMBIE_DRAGON:
1235 case TILEP_MONS_ZOMBIE_IRON_DRAGON:
1236 case TILEP_MONS_ZOMBIE_GOLDEN_DRAGON:
1237 case TILEP_MONS_ZOMBIE_QUICKSILVER_DRAGON:
1238 return TILEP_MONS_SKELETON_DRAGON;
1239 case TILEP_MONS_ZOMBIE_DRAKE:
1240 case TILEP_MONS_ZOMBIE_WYVERN:
1241 return TILEP_MONS_SKELETON_DRAKE;
1242 case TILEP_MONS_ZOMBIE_UGLY_THING:
1243 return TILEP_MONS_SKELETON_UGLY_THING;
1244 case TILEP_MONS_ZOMBIE_DRACONIAN:
1245 return TILEP_MONS_SKELETON_DRACONIAN;
1246 default:
1247 if (tile_player_basetile(z_tile) == TILEP_MONS_ZOMBIE_HYDRA)
1248 {
1249 return TILEP_MONS_SKELETON_HYDRA
1250 + (z_tile - TILEP_MONS_ZOMBIE_HYDRA);
1251 }
1252 }
1253 return TILEP_MONS_SKELETON_SMALL;
1254 }
1255
1256 /**
1257 * For a given monster, what tile is appropriate for that monster if it's a
1258 * zombie?
1259 *
1260 * If it's another kind of derived undead (e.g. a skeleton), the actual tile to
1261 * be used will be derived from the zombie tile we return here.
1262 *
1263 * @param mon The monster in question.
1264 * @return An appropriate zombie tile; e.g. TILEP_MONS_ZOMBIE_DRAGON.
1265 */
_mon_to_zombie_tile(const monster_info & mon)1266 static tileidx_t _mon_to_zombie_tile(const monster_info &mon)
1267 {
1268 const monster_type subtype = mon.base_type;
1269
1270 // hydras get special casing
1271
1272 if (subtype == MONS_LERNAEAN_HYDRA && mon.type == MONS_ZOMBIE)
1273 {
1274 // Step down the number of heads to get the appropriate tile:
1275 // for the last five heads, use tiles 1-5, for greater amounts
1276 // use the next tile for every 5 more heads.
1277 return tileidx_mon_clamp(TILEP_MONS_LERNAEAN_HYDRA_ZOMBIE,
1278 mon.number <= 5 ?
1279 mon.number - 1 :
1280 4 + (mon.number - 1)/5);
1281 }
1282 if (mons_genus(subtype) == MONS_HYDRA)
1283 return TILEP_MONS_ZOMBIE_HYDRA + min(mon.num_heads, 5) - 1;
1284
1285 // specific per-species zombies - use to override genuses
1286 static const map<monster_type, tileidx_t> species_tiles = {
1287 { MONS_JUGGERNAUT, TILEP_MONS_ZOMBIE_JUGGERNAUT },
1288 { MONS_ACID_DRAGON, TILEP_MONS_ZOMBIE_DRAKE },
1289 { MONS_STEAM_DRAGON, TILEP_MONS_ZOMBIE_DRAKE },
1290 { MONS_JACKAL, TILEP_MONS_ZOMBIE_JACKAL },
1291 { MONS_ADDER, TILEP_MONS_ZOMBIE_ADDER },
1292 { MONS_WOLF_SPIDER, TILEP_MONS_ZOMBIE_SPIDER_LARGE },
1293 { MONS_EMPEROR_SCORPION, TILEP_MONS_ZOMBIE_SPIDER_LARGE },
1294 { MONS_HOWLER_MONKEY, TILEP_MONS_ZOMBIE_MONKEY },
1295 { MONS_IRON_DRAGON, TILEP_MONS_ZOMBIE_IRON_DRAGON },
1296 { MONS_GOLDEN_DRAGON, TILEP_MONS_ZOMBIE_GOLDEN_DRAGON },
1297 { MONS_QUICKSILVER_DRAGON, TILEP_MONS_ZOMBIE_QUICKSILVER_DRAGON },
1298 { MONS_LINDWURM, TILEP_MONS_ZOMBIE_LINDWURM, },
1299 { MONS_MELIAI, TILEP_MONS_ZOMBIE_MELIAI, },
1300 { MONS_HORNET, TILEP_MONS_ZOMBIE_HORNET, },
1301 };
1302 // per-genus zombies - use by default
1303 static const map<monster_type, tileidx_t> genus_tiles = {
1304 { MONS_GOBLIN, TILEP_MONS_ZOMBIE_GOBLIN },
1305 { MONS_HOBGOBLIN, TILEP_MONS_ZOMBIE_HOBGOBLIN },
1306 { MONS_GNOLL, TILEP_MONS_ZOMBIE_GNOLL },
1307 { MONS_HUMAN, TILEP_MONS_ZOMBIE_HUMAN },
1308 { MONS_GHOUL, TILEP_MONS_ZOMBIE_HUMAN }, // for skel
1309 { MONS_KOBOLD, TILEP_MONS_ZOMBIE_KOBOLD },
1310 { MONS_ORC, TILEP_MONS_ZOMBIE_ORC },
1311 { MONS_TROLL, TILEP_MONS_ZOMBIE_TROLL },
1312 { MONS_OGRE, TILEP_MONS_ZOMBIE_OGRE },
1313 { MONS_HARPY, TILEP_MONS_ZOMBIE_HARPY },
1314 { MONS_DRACONIAN, TILEP_MONS_ZOMBIE_DRACONIAN },
1315 { MONS_DRAGON, TILEP_MONS_ZOMBIE_DRAGON },
1316 { MONS_WYVERN, TILEP_MONS_ZOMBIE_WYVERN },
1317 { MONS_DRAKE, TILEP_MONS_ZOMBIE_DRAKE },
1318 { MONS_GIANT_LIZARD, TILEP_MONS_ZOMBIE_LIZARD },
1319 { MONS_RAT, TILEP_MONS_ZOMBIE_RAT },
1320 { MONS_QUOKKA, TILEP_MONS_ZOMBIE_QUOKKA },
1321 { MONS_HOUND, TILEP_MONS_ZOMBIE_HOUND },
1322 { MONS_FROG, TILEP_MONS_ZOMBIE_FROG },
1323 { MONS_CRAB, TILEP_MONS_ZOMBIE_CRAB },
1324 { MONS_SNAPPING_TURTLE, TILEP_MONS_ZOMBIE_TURTLE },
1325 { MONS_WORM, TILEP_MONS_ZOMBIE_WORM },
1326 { MONS_GIANT_COCKROACH, TILEP_MONS_ZOMBIE_ROACH },
1327 { MONS_SCORPION, TILEP_MONS_ZOMBIE_SCORPION },
1328 { MONS_KRAKEN, TILEP_MONS_ZOMBIE_KRAKEN },
1329 { MONS_OCTOPODE, TILEP_MONS_ZOMBIE_OCTOPODE },
1330 { MONS_UGLY_THING, TILEP_MONS_ZOMBIE_UGLY_THING },
1331 { MONS_ELEPHANT, TILEP_MONS_ZOMBIE_ELEPHANT },
1332 { MONS_ELF, TILEP_MONS_ZOMBIE_ELF },
1333 { MONS_FAUN, TILEP_MONS_ZOMBIE_FAUN },
1334 { MONS_SATYR, TILEP_MONS_ZOMBIE_FAUN },
1335 { MONS_GUARDIAN_SERPENT, TILEP_MONS_ZOMBIE_GUARDIAN_SERPENT, },
1336 { MONS_MERFOLK, TILEP_MONS_ZOMBIE_MERFOLK, },
1337 { MONS_MINOTAUR, TILEP_MONS_ZOMBIE_MINOTAUR, },
1338 { MONS_SALAMANDER, TILEP_MONS_ZOMBIE_SALAMANDER, },
1339 { MONS_SPRIGGAN, TILEP_MONS_ZOMBIE_SPRIGGAN, },
1340 { MONS_YAKTAUR, TILEP_MONS_ZOMBIE_YAKTAUR, },
1341 { MONS_YAK, TILEP_MONS_ZOMBIE_YAK, },
1342 { MONS_BEAR, TILEP_MONS_ZOMBIE_BEAR, },
1343 };
1344
1345 struct shape_size_tiles
1346 {
1347 tileidx_t small; ///< Z_SMALL and default tile
1348 tileidx_t big; ///< Z_BIG tile
1349 };
1350 const shape_size_tiles GENERIC_ZOMBIES = { TILEP_MONS_ZOMBIE_SMALL,
1351 TILEP_MONS_ZOMBIE_LARGE };
1352 static const map<mon_body_shape, shape_size_tiles> shape_tiles = {
1353 { MON_SHAPE_CENTAUR, {TILEP_MONS_ZOMBIE_CENTAUR} },
1354 { MON_SHAPE_NAGA, {TILEP_MONS_ZOMBIE_NAGA} },
1355 { MON_SHAPE_QUADRUPED_WINGED, {TILEP_MONS_ZOMBIE_QUADRUPED_WINGED} },
1356 { MON_SHAPE_BAT, {TILEP_MONS_ZOMBIE_BAT} },
1357 { MON_SHAPE_BIRD, {TILEP_MONS_ZOMBIE_BIRD} },
1358 { MON_SHAPE_SNAKE, {TILEP_MONS_ZOMBIE_SNAKE} },
1359 { MON_SHAPE_SNAIL, {TILEP_MONS_ZOMBIE_SNAKE} },
1360 { MON_SHAPE_FISH, {TILEP_MONS_ZOMBIE_FISH} },
1361 { MON_SHAPE_INSECT, {TILEP_MONS_ZOMBIE_BUG} },
1362 { MON_SHAPE_CENTIPEDE, {TILEP_MONS_ZOMBIE_BUG} },
1363 { MON_SHAPE_INSECT_WINGED, {TILEP_MONS_ZOMBIE_BEE} },
1364 { MON_SHAPE_ARACHNID, {TILEP_MONS_ZOMBIE_SPIDER_SMALL} },
1365 { MON_SHAPE_QUADRUPED_TAILLESS, {TILEP_MONS_ZOMBIE_QUADRUPED_SMALL,
1366 TILEP_MONS_ZOMBIE_QUADRUPED_LARGE} },
1367 { MON_SHAPE_QUADRUPED, {TILEP_MONS_ZOMBIE_QUADRUPED_SMALL,
1368 TILEP_MONS_ZOMBIE_QUADRUPED_LARGE} },
1369 { MON_SHAPE_HUMANOID, GENERIC_ZOMBIES },
1370 { MON_SHAPE_HUMANOID_WINGED, GENERIC_ZOMBIES },
1371 { MON_SHAPE_HUMANOID_TAILED, GENERIC_ZOMBIES },
1372 { MON_SHAPE_HUMANOID_WINGED_TAILED, GENERIC_ZOMBIES },
1373 };
1374
1375 const tileidx_t *subtype_tile = map_find(species_tiles, subtype);
1376 if (subtype_tile)
1377 return *subtype_tile;
1378
1379 const tileidx_t *genus_tile = map_find(genus_tiles, mons_genus(subtype));
1380 if (genus_tile)
1381 return *genus_tile;
1382
1383 const int z_size = mons_zombie_size(subtype);
1384 const shape_size_tiles *shape_tile_pair
1385 = map_find(shape_tiles, get_mon_shape(subtype));
1386 if (shape_tile_pair)
1387 {
1388 if (z_size == Z_BIG && shape_tile_pair->big)
1389 return shape_tile_pair->big;
1390 return shape_tile_pair->small;
1391 }
1392
1393 return TILEP_ERROR;
1394 }
1395
1396 /// What tile should be used for a given derived undead monster?
_tileidx_monster_zombified(const monster_info & mon)1397 static tileidx_t _tileidx_monster_zombified(const monster_info& mon)
1398 {
1399 const tileidx_t zombie_tile = _mon_to_zombie_tile(mon);
1400 switch (mon.type)
1401 {
1402 case MONS_SKELETON:
1403 return _zombie_tile_to_skeleton(zombie_tile);
1404 case MONS_SPECTRAL_THING:
1405 return _zombie_tile_to_spectral(zombie_tile);
1406 case MONS_SIMULACRUM:
1407 return _zombie_tile_to_simulacrum(zombie_tile);
1408 default:
1409 return zombie_tile;
1410 }
1411 }
1412
1413 // Special case for *taurs which have a different tile
1414 // for when they have a bow.
_bow_offset(const monster_info & mon)1415 static bool _bow_offset(const monster_info& mon)
1416 {
1417 if (!mon.inv[MSLOT_WEAPON])
1418 return true;
1419
1420 switch (mon.inv[MSLOT_WEAPON]->sub_type)
1421 {
1422 case WPN_SHORTBOW:
1423 case WPN_LONGBOW:
1424 case WPN_ARBALEST:
1425 return false;
1426 default:
1427 return true;
1428 }
1429 }
1430 #endif
1431
_mon_mod(tileidx_t tile,int offset)1432 static tileidx_t _mon_mod(tileidx_t tile, int offset)
1433 {
1434 int count = tile_player_count(tile);
1435 return tile + offset % count;
1436 }
1437
tileidx_mon_clamp(tileidx_t tile,int offset)1438 tileidx_t tileidx_mon_clamp(tileidx_t tile, int offset)
1439 {
1440 int count = tile_player_count(tile);
1441 return tile + min(max(offset, 0), count - 1);
1442 }
1443
1444 #ifdef USE_TILE
1445 // actually, a triangle wave, but it's up to the actual tiles
_mon_sinus(tileidx_t tile)1446 static tileidx_t _mon_sinus(tileidx_t tile)
1447 {
1448 int count = tile_player_count(tile);
1449 ASSERT(count > 0);
1450 ASSERT(count > 1); // technically, staying put would work
1451 int n = you.frame_no % (2 * count - 2);
1452 return (n < count) ? (tile + n) : (tile + 2 * count - 2 - n);
1453 }
1454 #endif
1455
_mon_cycle(tileidx_t tile,int offset)1456 static tileidx_t _mon_cycle(tileidx_t tile, int offset)
1457 {
1458 int count = tile_player_count(tile);
1459 return tile + ((offset + you.frame_no) % count);
1460 }
1461
_modrng(int mod,tileidx_t first,tileidx_t last)1462 static tileidx_t _modrng(int mod, tileidx_t first, tileidx_t last)
1463 {
1464 return first + mod % (last - first + 1);
1465 }
1466
1467 // This function allows for getting a monster from "just" the type.
1468 // To avoid needless duplication of a cases in tileidx_monster, some
1469 // extra parameters that have reasonable defaults for monsters where
1470 // only the type is known are pushed here.
tileidx_monster_base(int type,int mon_id,bool in_water,int colour,int number,int tile_num_prop,bool vary)1471 tileidx_t tileidx_monster_base(int type, int mon_id, bool in_water, int colour,
1472 int number, int tile_num_prop, bool vary)
1473 {
1474 switch (type)
1475 {
1476 case MONS_UGLY_THING:
1477 case MONS_VERY_UGLY_THING:
1478 {
1479 const tileidx_t ugly_tile = (type == MONS_VERY_UGLY_THING) ?
1480 TILEP_MONS_VERY_UGLY_THING : TILEP_MONS_UGLY_THING;
1481 int colour_offset = ugly_thing_colour_offset(colour);
1482 return tileidx_mon_clamp(ugly_tile, colour_offset);
1483 }
1484
1485 case MONS_HYDRA:
1486 // Number of heads
1487 return tileidx_mon_clamp(TILEP_MONS_HYDRA, number - 1);
1488 case MONS_SLIME_CREATURE:
1489 case MONS_MERGED_SLIME_CREATURE:
1490 return tileidx_mon_clamp(TILEP_MONS_SLIME_CREATURE, number - 1);
1491 case MONS_LERNAEAN_HYDRA:
1492 // Step down the number of heads to get the appropriate tile:
1493 // For the last five heads, use tiles 1-5, for greater amounts
1494 // use the next tile for every 5 more heads.
1495 return tileidx_mon_clamp(TILEP_MONS_LERNAEAN_HYDRA,
1496 number <= 5 ?
1497 number - 1 : 4 + (number - 1)/5);
1498
1499 // draconian ('d')
1500 case MONS_TIAMAT:
1501 {
1502 int offset = 0;
1503 switch (colour)
1504 {
1505 case BLUE: offset = 0; break;
1506 case YELLOW: offset = 1; break;
1507 case GREEN: offset = 2; break;
1508 case LIGHTGREY: offset = 3; break;
1509 case LIGHTMAGENTA: offset = 4; break;
1510 case CYAN: offset = 5; break;
1511 case MAGENTA: offset = 6; break;
1512 case LIGHTRED: offset = 7; break;
1513 case WHITE: offset = 8; break;
1514 }
1515
1516 return TILEP_MONS_TIAMAT + offset;
1517 }
1518 }
1519
1520 const monster_type mtype = static_cast<monster_type>(type);
1521 const tileidx_t base_tile = get_mon_base_tile(mtype);
1522 const mon_type_tile_variation vary_type = vary ? get_mon_tile_variation(mtype) : TVARY_NONE;
1523 switch (vary_type)
1524 {
1525 case TVARY_NONE:
1526 return base_tile;
1527 case TVARY_MOD:
1528 return _mon_mod(base_tile, tile_num_prop);
1529 case TVARY_CYCLE:
1530 return _mon_cycle(base_tile, tile_num_prop);
1531 case TVARY_RANDOM:
1532 return _mon_random(base_tile, mon_id);
1533 case TVARY_WATER:
1534 return base_tile + (in_water ? 1 : 0);
1535 default:
1536 die("Unknown tile variation type %d for mon %d!", vary_type, mtype);
1537 }
1538 }
1539
1540 enum class main_dir
1541 {
1542 north = 0,
1543 east,
1544 south,
1545 west
1546 };
1547
1548 enum class tentacle_type
1549 {
1550 kraken = 0,
1551 eldritch = 1,
1552 starspawn = 2,
1553 vine = 3,
1554 zombie_kraken = 4,
1555 simulacrum_kraken = 5,
1556 spectral_kraken = 6,
1557 };
1558
1559 #ifdef USE_TILE
_add_tentacle_overlay(const coord_def pos,const main_dir dir,tentacle_type type)1560 static void _add_tentacle_overlay(const coord_def pos,
1561 const main_dir dir,
1562 tentacle_type type)
1563 {
1564 /* This adds the corner overlays; e.g. in the following situation:
1565 .#
1566 #.
1567 we need to add corners to the floor tiles since the tentacle
1568 will otherwise look weird. So when placing the upper tentacle
1569 tile, this function is called with dir main_dir::west, so the upper
1570 floor tile gets a corner in the south-east; and similarly,
1571 when placing the lower tentacle tile, we get called with dir
1572 main_dir::east to give the lower floor tile a NW overlay.
1573 */
1574 coord_def next = pos;
1575 switch (dir)
1576 {
1577 case main_dir::north: next += coord_def( 0, -1); break;
1578 case main_dir::east: next += coord_def( 1, 0); break;
1579 case main_dir::south: next += coord_def( 0, 1); break;
1580 case main_dir::west: next += coord_def(-1, 0); break;
1581 default:
1582 die("invalid direction");
1583 }
1584 if (!in_bounds(next))
1585 return;
1586
1587 const coord_def next_showpos(grid2show(next));
1588 if (!show_bounds(next_showpos))
1589 return;
1590
1591 tile_flags flag;
1592 switch (dir)
1593 {
1594 case main_dir::north: flag = TILE_FLAG_TENTACLE_SW; break;
1595 case main_dir::east: flag = TILE_FLAG_TENTACLE_NW; break;
1596 case main_dir::south: flag = TILE_FLAG_TENTACLE_NE; break;
1597 case main_dir::west: flag = TILE_FLAG_TENTACLE_SE; break;
1598 default: die("invalid direction");
1599 }
1600 tile_env.bg(next_showpos) |= flag;
1601
1602 switch (type)
1603 {
1604 case tentacle_type::eldritch: flag = TILE_FLAG_TENTACLE_ELDRITCH; break;
1605 case tentacle_type::starspawn: flag = TILE_FLAG_TENTACLE_STARSPAWN; break;
1606 case tentacle_type::vine: flag = TILE_FLAG_TENTACLE_VINE; break;
1607 case tentacle_type::zombie_kraken: flag = TILE_FLAG_TENTACLE_ZOMBIE_KRAKEN; break;
1608 case tentacle_type::simulacrum_kraken: flag = TILE_FLAG_TENTACLE_SIMULACRUM_KRAKEN; break;
1609 case tentacle_type::spectral_kraken: flag = TILE_FLAG_TENTACLE_SPECTRAL_KRAKEN; break;
1610 default: flag = TILE_FLAG_TENTACLE_KRAKEN;
1611 }
1612 tile_env.bg(next_showpos) |= flag;
1613 }
1614
_handle_tentacle_overlay(const coord_def pos,const tileidx_t tile,tentacle_type type)1615 static void _handle_tentacle_overlay(const coord_def pos,
1616 const tileidx_t tile,
1617 tentacle_type type)
1618 {
1619 switch (tile)
1620 {
1621 case TILEP_MONS_KRAKEN_TENTACLE_NW:
1622 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NW:
1623 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_S_NW:
1624 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_NW:
1625 _add_tentacle_overlay(pos, main_dir::north, type);
1626 break;
1627 case TILEP_MONS_KRAKEN_TENTACLE_NE:
1628 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NE:
1629 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_S_NE:
1630 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W_NE:
1631 _add_tentacle_overlay(pos, main_dir::east, type);
1632 break;
1633 case TILEP_MONS_KRAKEN_TENTACLE_SE:
1634 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_SE:
1635 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N_SE:
1636 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W_SE:
1637 _add_tentacle_overlay(pos, main_dir::south, type);
1638 break;
1639 case TILEP_MONS_KRAKEN_TENTACLE_SW:
1640 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_SW:
1641 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N_SW:
1642 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_E_SW:
1643 _add_tentacle_overlay(pos, main_dir::west, type);
1644 break;
1645 // diagonals
1646 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NW_SE:
1647 _add_tentacle_overlay(pos, main_dir::north, type);
1648 _add_tentacle_overlay(pos, main_dir::south, type);
1649 break;
1650 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NE_SW:
1651 _add_tentacle_overlay(pos, main_dir::east, type);
1652 _add_tentacle_overlay(pos, main_dir::west, type);
1653 break;
1654 // other
1655 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NE_NW:
1656 _add_tentacle_overlay(pos, main_dir::north, type);
1657 _add_tentacle_overlay(pos, main_dir::east, type);
1658 break;
1659 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NE_SE:
1660 _add_tentacle_overlay(pos, main_dir::east, type);
1661 _add_tentacle_overlay(pos, main_dir::south, type);
1662 break;
1663 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_SE_SW:
1664 _add_tentacle_overlay(pos, main_dir::south, type);
1665 _add_tentacle_overlay(pos, main_dir::west, type);
1666 break;
1667 case TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_NW_SW:
1668 _add_tentacle_overlay(pos, main_dir::north, type);
1669 _add_tentacle_overlay(pos, main_dir::west, type);
1670 break;
1671 }
1672 }
1673
_get_tentacle_type(const monster_info & mon)1674 static tentacle_type _get_tentacle_type(const monster_info& mon)
1675 {
1676 switch (mon.type)
1677 {
1678 case MONS_KRAKEN_TENTACLE:
1679 case MONS_KRAKEN_TENTACLE_SEGMENT:
1680 switch (mon.base_type)
1681 {
1682 case MONS_ZOMBIE:
1683 return tentacle_type::zombie_kraken;
1684 case MONS_SIMULACRUM:
1685 return tentacle_type::simulacrum_kraken;
1686 case MONS_SPECTRAL_THING:
1687 return tentacle_type::spectral_kraken;
1688 default:
1689 return tentacle_type::kraken;
1690 }
1691 case MONS_ELDRITCH_TENTACLE:
1692 case MONS_ELDRITCH_TENTACLE_SEGMENT:
1693 return tentacle_type::eldritch;
1694 case MONS_STARSPAWN_TENTACLE:
1695 case MONS_STARSPAWN_TENTACLE_SEGMENT:
1696 return tentacle_type::starspawn;
1697 case MONS_SNAPLASHER_VINE:
1698 case MONS_SNAPLASHER_VINE_SEGMENT:
1699 return tentacle_type::vine;
1700
1701 default:
1702 die("Invalid tentacle type!");
1703 return tentacle_type::kraken; // Silence a warning
1704 }
1705 }
1706
_tentacle_tile_not_flying(tileidx_t tile)1707 static bool _tentacle_tile_not_flying(tileidx_t tile)
1708 {
1709 // All tiles between these two enums feature tentacles
1710 // emerging from water.
1711 return tile >= TILEP_FIRST_TENTACLE_IN_WATER
1712 && tile <= TILEP_LAST_TENTACLE_IN_WATER
1713 || tile >= TILEP_FIRST_ZOMBIE_TENTACLE_IN_WATER
1714 && tile <= TILEP_LAST_ZOMBIE_TENTACLE_IN_WATER
1715 || tile >= TILEP_FIRST_SIMULACRUM_TENTACLE_IN_WATER
1716 && tile <= TILEP_LAST_SIMULACRUM_TENTACLE_IN_WATER
1717 || tile >= TILEP_FIRST_SPECTRAL_TENTACLE_IN_WATER
1718 && tile <= TILEP_LAST_SPECTRAL_TENTACLE_IN_WATER;
1719 }
1720
_tileidx_monster_no_props(const monster_info & mon)1721 static tileidx_t _tileidx_monster_no_props(const monster_info& mon)
1722 {
1723 const bool in_water = feat_is_water(env.map_knowledge(mon.pos).feat());
1724
1725 // Show only base class for detected monsters.
1726 if (mons_class_is_zombified(mon.type))
1727 return _tileidx_monster_zombified(mon);
1728
1729 if (mon.props.exists("monster_tile"))
1730 {
1731 tileidx_t t = mon.props["monster_tile"].get_short();
1732 if (t == TILEP_MONS_HELL_WIZARD)
1733 return _mon_sinus(t);
1734 return t;
1735 }
1736
1737 int tile_num = 0;
1738 if (mon.props.exists(TILE_NUM_KEY))
1739 tile_num = mon.props[TILE_NUM_KEY].get_short();
1740
1741 bool vary = !(mon.props.exists("fake") && mon.props["fake"].get_bool());
1742 const tileidx_t base = tileidx_monster_base(mon.type,
1743 mon.pos.y*GXM + mon.pos.x,
1744 in_water, mon.colour(true),
1745 mon.number, tile_num, vary);
1746
1747 switch (mon.type)
1748 {
1749 // use a different tile not using a standard ranged weapon.
1750 case MONS_CENTAUR:
1751 case MONS_CENTAUR_WARRIOR:
1752 case MONS_YAKTAUR:
1753 case MONS_YAKTAUR_CAPTAIN:
1754 return base + (_bow_offset(mon) ? 1 : 0);
1755
1756 case MONS_CEREBOV:
1757 return base + (mon.inv[MSLOT_WEAPON] ? 0 : 1);
1758
1759 case MONS_BALLISTOMYCETE:
1760 return base + (mon.is_active ? 1 : 0);
1761
1762 case MONS_DUVESSA:
1763 case MONS_DOWAN:
1764 return mon.props.exists(ELVEN_IS_ENERGIZED_KEY) ? base + 1 : base;
1765
1766 case MONS_ARACHNE:
1767 {
1768 // Arachne normally is drawn with her staff wielded two-handed,
1769 // but will use a regular stance if she picks up a shield
1770 // (enhancer staves are compatible with those).
1771 const item_def* weapon = mon.inv[MSLOT_WEAPON].get();
1772 if (!mon.inv[MSLOT_SHIELD] && weapon
1773 && (weapon->is_type(OBJ_STAVES, STAFF_POISON)
1774 || is_unrandom_artefact(*weapon, UNRAND_OLGREB)))
1775 {
1776 return base;
1777 }
1778 else
1779 return base + 1;
1780 }
1781
1782 case MONS_AGNES:
1783 {
1784 // For if Agnes loses her lajatang
1785 const item_def * const weapon = mon.inv[MSLOT_WEAPON].get();
1786 if (weapon && weapon->is_type(OBJ_WEAPONS, WPN_LAJATANG))
1787 return TILEP_MONS_AGNES;
1788 else
1789 return TILEP_MONS_AGNES_STAVELESS;
1790 }
1791
1792 case MONS_EDMUND:
1793 {
1794 // For if Edmund loses his weapon
1795 const item_def * const weapon = mon.inv[MSLOT_WEAPON].get();
1796 if (weapon && (weapon->is_type(OBJ_WEAPONS, WPN_DIRE_FLAIL)
1797 || weapon->is_type(OBJ_WEAPONS, WPN_FLAIL)))
1798 {
1799 return TILEP_MONS_EDMUND;
1800 }
1801 else
1802 return TILEP_MONS_EDMUND_WEAPONLESS;
1803 }
1804
1805 case MONS_ERICA:
1806 {
1807 // For if Erica loses her flaming scimitar
1808 const item_def * const weapon = mon.inv[MSLOT_WEAPON].get();
1809 if (weapon
1810 && weapon->is_type(OBJ_WEAPONS, WPN_SCIMITAR)
1811 && get_weapon_brand(*weapon) == SPWPN_FLAMING)
1812 {
1813 return TILEP_MONS_ERICA;
1814 }
1815 else
1816 return TILEP_MONS_ERICA_SWORDLESS;
1817 }
1818
1819 case MONS_BUSH:
1820 if (env.map_knowledge(mon.pos).cloud() == CLOUD_FIRE)
1821 return TILEP_MONS_BUSH_BURNING;
1822 return base;
1823
1824 case MONS_BOULDER_BEETLE:
1825 return mon.is(MB_ROLLING)
1826 ? _mon_random(TILEP_MONS_BOULDER_BEETLE_ROLLING, mon.number)
1827 : base;
1828
1829 case MONS_ANIMATED_ARMOUR:
1830 return base | TILE_FLAG_ANIM_OBJ;
1831
1832 case MONS_DANCING_WEAPON:
1833 {
1834 // Use item tile.
1835 const item_def& item = *mon.inv[MSLOT_WEAPON];
1836 return tileidx_item(item) | TILE_FLAG_ANIM_OBJ;
1837 }
1838
1839 case MONS_SPECTRAL_WEAPON:
1840 {
1841 // TODO: it would be good to show the TILE_FLAG_ANIM_OBJ icon with
1842 // these too, but most are oriented NW-SE and it looks bad
1843 if (!mon.inv[MSLOT_WEAPON])
1844 return TILEP_MONS_SPECTRAL_SBL;
1845
1846 // Tiles exist for each class of weapon.
1847 const item_def& item = *mon.inv[MSLOT_WEAPON];
1848 switch (item_attack_skill(item))
1849 {
1850 case SK_LONG_BLADES:
1851 return TILEP_MONS_SPECTRAL_LBL;
1852 case SK_AXES:
1853 return TILEP_MONS_SPECTRAL_AXE;
1854 case SK_POLEARMS:
1855 return TILEP_MONS_SPECTRAL_SPEAR;
1856 case SK_STAVES:
1857 return TILEP_MONS_SPECTRAL_STAFF;
1858 case SK_MACES_FLAILS:
1859 {
1860 const weapon_type wt = (weapon_type)item.sub_type;
1861 return (wt == WPN_WHIP || wt == WPN_FLAIL
1862 || wt == WPN_DIRE_FLAIL || wt == WPN_DEMON_WHIP
1863 || wt == WPN_SACRED_SCOURGE)
1864 ? TILEP_MONS_SPECTRAL_WHIP
1865 : TILEP_MONS_SPECTRAL_MACE;
1866 }
1867 default:
1868 return TILEP_MONS_SPECTRAL_SBL;
1869 }
1870 }
1871
1872 case MONS_KRAKEN_TENTACLE:
1873 case MONS_KRAKEN_TENTACLE_SEGMENT:
1874 case MONS_ELDRITCH_TENTACLE:
1875 case MONS_ELDRITCH_TENTACLE_SEGMENT:
1876 case MONS_STARSPAWN_TENTACLE:
1877 case MONS_STARSPAWN_TENTACLE_SEGMENT:
1878 case MONS_SNAPLASHER_VINE:
1879 case MONS_SNAPLASHER_VINE_SEGMENT:
1880 {
1881 tileidx_t tile = tileidx_tentacle(mon);
1882 _handle_tentacle_overlay(mon.pos, tile, _get_tentacle_type(mon));
1883
1884 if (!_mons_is_kraken_tentacle(mon.type)
1885 && tile >= TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N
1886 && (tile <= TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W_SE
1887 || tile <= TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_W_NW &&
1888 mon.type == MONS_SNAPLASHER_VINE_SEGMENT))
1889 {
1890 tile += TILEP_MONS_ELDRITCH_TENTACLE_PORTAL_N;
1891 tile -= TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N;
1892
1893 if (mon.type == MONS_STARSPAWN_TENTACLE
1894 || mon.type == MONS_STARSPAWN_TENTACLE_SEGMENT)
1895 {
1896 tile += TILEP_MONS_STARSPAWN_TENTACLE_N;
1897 tile -= TILEP_MONS_ELDRITCH_TENTACLE_N;
1898 }
1899 else if (mon.type == MONS_SNAPLASHER_VINE
1900 || mon.type == MONS_SNAPLASHER_VINE_SEGMENT)
1901 {
1902 tile += TILEP_MONS_VINE_N;
1903 tile -= TILEP_MONS_ELDRITCH_TENTACLE_N;
1904 }
1905 }
1906
1907 if (_mons_is_kraken_tentacle(mon.type) && mon.base_type == MONS_ZOMBIE)
1908 {
1909 tile += TILEP_MONS_KRAKEN_ZOMBIE_TENTACLE_SEGMENT_N;
1910 tile -= TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N;
1911 }
1912 if (_mons_is_kraken_tentacle(mon.type) && mon.base_type == MONS_SIMULACRUM)
1913 {
1914 tile += TILEP_MONS_KRAKEN_SIMULACRUM_TENTACLE_SEGMENT_N;
1915 tile -= TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N;
1916 }
1917 if (_mons_is_kraken_tentacle(mon.type) && mon.base_type == MONS_SPECTRAL_THING)
1918 {
1919 tile += TILEP_MONS_KRAKEN_SPECTRAL_TENTACLE_SEGMENT_N;
1920 tile -= TILEP_MONS_KRAKEN_TENTACLE_SEGMENT_N;
1921 }
1922
1923 return tile;
1924 }
1925
1926 case MONS_SENSED:
1927 {
1928 // Should be always out of LOS, though...
1929 if (base == TILEP_MONS_PROGRAM_BUG)
1930 return TILE_UNSEEN_MONSTER;
1931 return base;
1932 }
1933
1934 default:
1935 return base;
1936 }
1937 }
1938
tileidx_monster(const monster_info & mons)1939 tileidx_t tileidx_monster(const monster_info& mons)
1940 {
1941 tileidx_t ch = _tileidx_monster_no_props(mons);
1942
1943 if ((!mons.ground_level() && !_tentacle_tile_not_flying(ch)))
1944 ch |= TILE_FLAG_FLYING;
1945 if (mons.is(MB_CAUGHT))
1946 ch |= TILE_FLAG_NET;
1947 if (mons.is(MB_WEBBED))
1948 ch |= TILE_FLAG_WEB;
1949 if (mons.is(MB_POISONED))
1950 ch |= TILE_FLAG_POISON;
1951 else if (mons.is(MB_MORE_POISONED))
1952 ch |= TILE_FLAG_MORE_POISON;
1953 else if (mons.is(MB_MAX_POISONED))
1954 ch |= TILE_FLAG_MAX_POISON;
1955 if (mons.is(MB_BURNING))
1956 ch |= TILE_FLAG_STICKY_FLAME;
1957 if (mons.is(MB_INNER_FLAME))
1958 ch |= TILE_FLAG_INNER_FLAME;
1959 if (!mons.constrictor_name.empty())
1960 ch |= TILE_FLAG_CONSTRICTED;
1961 if (mons.is(MB_BERSERK))
1962 ch |= TILE_FLAG_BERSERK;
1963 if (mons.is(MB_GLOWING))
1964 ch |= TILE_FLAG_GLOWING;
1965 if (mons.is(MB_SLOWED))
1966 ch |= TILE_FLAG_SLOWED;
1967 if (mons.is(MB_MIRROR_DAMAGE))
1968 ch |= TILE_FLAG_PAIN_MIRROR;
1969 if (mons.is(MB_HASTED))
1970 ch |= TILE_FLAG_HASTED;
1971 if (mons.is(MB_STRONG))
1972 ch |= TILE_FLAG_MIGHT;
1973 if (mons.is(MB_PETRIFYING))
1974 ch |= TILE_FLAG_PETRIFYING;
1975 if (mons.is(MB_PETRIFIED))
1976 ch |= TILE_FLAG_PETRIFIED;
1977 if (mons.is(MB_BLIND))
1978 ch |= TILE_FLAG_BLIND;
1979 if (mons.is(MB_SUMMONED))
1980 ch |= TILE_FLAG_SUMMONED;
1981 if (mons.is(MB_PERM_SUMMON))
1982 ch |= TILE_FLAG_PERM_SUMMON;
1983 if (mons.is(MB_WORD_OF_RECALL))
1984 ch |= TILE_FLAG_RECALL;
1985 if (mons.is(MB_LIGHTLY_DRAINED) || mons.is(MB_HEAVILY_DRAINED))
1986 ch |= TILE_FLAG_DRAIN;
1987 if (mons.is(MB_IDEALISED))
1988 ch |= TILE_FLAG_IDEALISED;
1989 if (mons.is(MB_BOUND_SOUL))
1990 ch |= TILE_FLAG_BOUND_SOUL;
1991 if (mons.is(MB_INFESTATION))
1992 ch |= TILE_FLAG_INFESTED;
1993 if (mons.is(MB_CORROSION))
1994 ch |= TILE_FLAG_CORRODED;
1995 if (mons.is(MB_SWIFT))
1996 ch |= TILE_FLAG_SWIFT;
1997 if (mons.is(MB_VILE_CLUTCH))
1998 ch |= TILE_FLAG_VILE_CLUTCH;
1999 if (mons.is(MB_POSSESSABLE))
2000 ch |= TILE_FLAG_POSSESSABLE;
2001 if (mons.is(MB_WITHERING) || mons.is(MB_CRUMBLING))
2002 ch |= TILE_FLAG_SLOWLY_DYING;
2003
2004 if (mons.attitude == ATT_FRIENDLY)
2005 ch |= TILE_FLAG_PET;
2006 else if (mons.attitude == ATT_GOOD_NEUTRAL)
2007 ch |= TILE_FLAG_GD_NEUTRAL;
2008 else if (mons.neutral())
2009 ch |= TILE_FLAG_NEUTRAL;
2010 else
2011 switch (mons.threat)
2012 {
2013 case MTHRT_TRIVIAL:
2014 if (Options.tile_show_threat_levels.find("trivial") != string::npos)
2015 ch |= TILE_FLAG_TRIVIAL;
2016 break;
2017 case MTHRT_EASY:
2018 if (Options.tile_show_threat_levels.find("easy") != string::npos)
2019 ch |= TILE_FLAG_EASY;
2020 break;
2021 case MTHRT_TOUGH:
2022 if (Options.tile_show_threat_levels.find("tough") != string::npos)
2023 ch |= TILE_FLAG_TOUGH;
2024 break;
2025 case MTHRT_NASTY:
2026 if (Options.tile_show_threat_levels.find("nasty") != string::npos)
2027 ch |= TILE_FLAG_NASTY;
2028 break;
2029 default:
2030 break;
2031 }
2032
2033 if (mons.is(MB_FLEEING))
2034 ch |= TILE_FLAG_FLEEING;
2035 else if (mons.is(MB_STABBABLE) || mons.is(MB_SLEEPING)
2036 || mons.is(MB_DORMANT))
2037 {
2038 // XXX: should we have different tile flags for "stabbable" versus
2039 // "sleeping"?
2040 ch |= TILE_FLAG_STAB;
2041 }
2042 // Should petrify show the '?' symbol?
2043 else if (mons.is(MB_DISTRACTED) && !mons.is(MB_PETRIFYING)
2044 || mons.attitude == ATT_FRIENDLY && mons.is(MB_CONFUSED))
2045 {
2046 ch |= TILE_FLAG_MAY_STAB;
2047 }
2048
2049 mon_dam_level_type damage_level = mons.dam;
2050
2051 switch (damage_level)
2052 {
2053 case MDAM_DEAD:
2054 case MDAM_ALMOST_DEAD:
2055 ch |= TILE_FLAG_MDAM_ADEAD;
2056 break;
2057 case MDAM_SEVERELY_DAMAGED:
2058 ch |= TILE_FLAG_MDAM_SEV;
2059 break;
2060 case MDAM_HEAVILY_DAMAGED:
2061 ch |= TILE_FLAG_MDAM_HEAVY;
2062 break;
2063 case MDAM_MODERATELY_DAMAGED:
2064 ch |= TILE_FLAG_MDAM_MOD;
2065 break;
2066 case MDAM_LIGHTLY_DAMAGED:
2067 ch |= TILE_FLAG_MDAM_LIGHT;
2068 break;
2069 case MDAM_OKAY:
2070 default:
2071 // no flag for okay.
2072 break;
2073 }
2074
2075 #ifdef USE_TILE_LOCAL
2076 // handled on client side in WebTiles
2077 if (Options.tile_show_demon_tier)
2078 {
2079 #endif
2080 // FIXME: non-linear bits suck, should be a simple addition
2081 switch (mons_demon_tier(mons.type))
2082 {
2083 case 1:
2084 ch |= TILE_FLAG_DEMON_1;
2085 break;
2086 case 2:
2087 ch |= TILE_FLAG_DEMON_2;
2088 break;
2089 case 3:
2090 ch |= TILE_FLAG_DEMON_3;
2091 break;
2092 case 4:
2093 ch |= TILE_FLAG_DEMON_4;
2094 break;
2095 case 5:
2096 ch |= TILE_FLAG_DEMON_5;
2097 break;
2098 }
2099 #ifdef USE_TILE_LOCAL
2100 }
2101 #endif
2102
2103 return ch;
2104 }
2105 #endif
2106
tileidx_draco_base(monster_type draco)2107 static tileidx_t tileidx_draco_base(monster_type draco)
2108 {
2109 return TILEP_DRACO_BASE + (draco - MONS_DRACONIAN);
2110 }
2111
tileidx_draco_base(const monster_info & mon)2112 tileidx_t tileidx_draco_base(const monster_info& mon)
2113 {
2114 return tileidx_draco_base(mon.draco_or_demonspawn_subspecies());
2115 }
2116
tileidx_draco_job(const monster_info & mon)2117 tileidx_t tileidx_draco_job(const monster_info& mon)
2118 {
2119 if (mons_is_draconian_job(mon.type))
2120 return get_mon_base_tile(mon.type);
2121 return 0;
2122 }
2123
tileidx_demonspawn_base(const monster_info & mon)2124 tileidx_t tileidx_demonspawn_base(const monster_info& mon)
2125 {
2126 return get_mon_base_tile(mon.draco_or_demonspawn_subspecies());
2127 }
2128
tileidx_demonspawn_job(const monster_info & mon)2129 tileidx_t tileidx_demonspawn_job(const monster_info& mon)
2130 {
2131 if (mons_is_demonspawn_job(mon.type))
2132 return get_mon_base_tile(mon.type);
2133 return 0;
2134 }
2135
2136 #ifdef USE_TILE
2137 /**
2138 * Return the monster tile used for the player based on a monster type.
2139 *
2140 * When using the player species monster or a monster in general instead of an
2141 * explicit tile name, this function cleans up the tiles for certain monsters
2142 * where there's an alternate tile that's better than the base one for doll
2143 * purposes.
2144 * @returns The tile id of the tile that will be used.
2145 */
tileidx_player_mons()2146 tileidx_t tileidx_player_mons()
2147 {
2148 ASSERT(Options.tile_use_monster != MONS_0);
2149
2150 monster_type mons;
2151 if (Options.tile_player_tile)
2152 return Options.tile_player_tile;
2153
2154 if (Options.tile_use_monster == MONS_PLAYER)
2155 mons = player_mons(false);
2156 else
2157 mons = Options.tile_use_monster;
2158
2159 if (mons_is_base_draconian(mons))
2160 return tileidx_draco_base(mons);
2161
2162 switch (mons)
2163 {
2164 case MONS_CENTAUR: return TILEP_MONS_CENTAUR_MELEE;
2165 case MONS_CENTAUR_WARRIOR: return TILEP_MONS_CENTAUR_WARRIOR_MELEE;
2166 case MONS_YAKTAUR: return TILEP_MONS_YAKTAUR_MELEE;
2167 case MONS_YAKTAUR_CAPTAIN: return TILEP_MONS_YAKTAUR_CAPTAIN_MELEE;
2168 default: return tileidx_monster_base(mons, 0);
2169 }
2170 }
2171 #endif
2172
_tileidx_unrand_artefact(int idx)2173 static tileidx_t _tileidx_unrand_artefact(int idx)
2174 {
2175 const tileidx_t tile = unrandart_to_tile(idx);
2176 return tile ? tile : tileidx_t{TILE_TODO};
2177 }
2178
_tileidx_wyrmbane(int plus)2179 static tileidx_t _tileidx_wyrmbane(int plus)
2180 {
2181 if (plus < 10)
2182 return TILE_UNRAND_WYRMBANE;
2183 else if (plus < 12)
2184 return TILE_UNRAND_WYRMBANE1;
2185 else if (plus < 15)
2186 return TILE_UNRAND_WYRMBANE2;
2187 else if (plus < 18)
2188 return TILE_UNRAND_WYRMBANE3;
2189 else
2190 return TILE_UNRAND_WYRMBANE4;
2191 }
2192
_tileidx_weapon_base(const item_def & item)2193 static tileidx_t _tileidx_weapon_base(const item_def &item)
2194 {
2195 switch (item.sub_type)
2196 {
2197 case WPN_DAGGER: return TILE_WPN_DAGGER;
2198 case WPN_SHORT_SWORD: return TILE_WPN_SHORT_SWORD;
2199 case WPN_QUICK_BLADE: return TILE_WPN_QUICK_BLADE;
2200 case WPN_RAPIER: return TILE_WPN_RAPIER;
2201 case WPN_FALCHION: return TILE_WPN_FALCHION;
2202 case WPN_LONG_SWORD: return TILE_WPN_LONG_SWORD;
2203 case WPN_GREAT_SWORD: return TILE_WPN_GREAT_SWORD;
2204 case WPN_SCIMITAR: return TILE_WPN_SCIMITAR;
2205 case WPN_DOUBLE_SWORD: return TILE_WPN_DOUBLE_SWORD;
2206 case WPN_TRIPLE_SWORD: return TILE_WPN_TRIPLE_SWORD;
2207 case WPN_HAND_AXE: return TILE_WPN_HAND_AXE;
2208 case WPN_WAR_AXE: return TILE_WPN_WAR_AXE;
2209 case WPN_BROAD_AXE: return TILE_WPN_BROAD_AXE;
2210 case WPN_BATTLEAXE: return TILE_WPN_BATTLEAXE;
2211 case WPN_EXECUTIONERS_AXE: return TILE_WPN_EXECUTIONERS_AXE;
2212 #if TAG_MAJOR_VERSION == 34
2213 case WPN_BLOWGUN: return TILE_WPN_BLOWGUN;
2214 #endif
2215 case WPN_HUNTING_SLING: return TILE_WPN_HUNTING_SLING;
2216 case WPN_FUSTIBALUS: return TILE_WPN_FUSTIBALUS;
2217 case WPN_SHORTBOW: return TILE_WPN_SHORTBOW;
2218 case WPN_HAND_CROSSBOW: return TILE_WPN_HAND_CROSSBOW;
2219 case WPN_ARBALEST: return TILE_WPN_ARBALEST;
2220 case WPN_TRIPLE_CROSSBOW: return TILE_WPN_TRIPLE_CROSSBOW;
2221 case WPN_SPEAR: return TILE_WPN_SPEAR;
2222 case WPN_TRIDENT: return TILE_WPN_TRIDENT;
2223 case WPN_HALBERD: return TILE_WPN_HALBERD;
2224 case WPN_SCYTHE: return TILE_WPN_SCYTHE;
2225 case WPN_GLAIVE: return TILE_WPN_GLAIVE;
2226 #if TAG_MAJOR_VERSION == 34
2227 case WPN_STAFF: return TILE_WPN_STAFF;
2228 #endif
2229 case WPN_QUARTERSTAFF: return TILE_WPN_QUARTERSTAFF;
2230 case WPN_CLUB: return TILE_WPN_CLUB;
2231 case WPN_MACE: return TILE_WPN_MACE;
2232 case WPN_FLAIL: return TILE_WPN_FLAIL;
2233 case WPN_GREAT_MACE: return TILE_WPN_GREAT_MACE;
2234 case WPN_DIRE_FLAIL: return TILE_WPN_DIRE_FLAIL;
2235 case WPN_MORNINGSTAR: return TILE_WPN_MORNINGSTAR;
2236 case WPN_EVENINGSTAR: return TILE_WPN_EVENINGSTAR;
2237 case WPN_GIANT_CLUB: return TILE_WPN_GIANT_CLUB;
2238 case WPN_GIANT_SPIKED_CLUB: return TILE_WPN_GIANT_SPIKED_CLUB;
2239 case WPN_WHIP: return TILE_WPN_WHIP;
2240 case WPN_DEMON_BLADE: return TILE_WPN_DEMON_BLADE;
2241 case WPN_EUDEMON_BLADE: return TILE_WPN_BLESSED_BLADE;
2242 case WPN_DEMON_WHIP: return TILE_WPN_DEMON_WHIP;
2243 case WPN_SACRED_SCOURGE: return TILE_WPN_SACRED_SCOURGE;
2244 case WPN_DEMON_TRIDENT: return TILE_WPN_DEMON_TRIDENT;
2245 case WPN_TRISHULA: return TILE_WPN_TRISHULA;
2246 case WPN_LONGBOW: return TILE_WPN_LONGBOW;
2247 case WPN_LAJATANG: return TILE_WPN_LAJATANG;
2248 case WPN_BARDICHE: return TILE_WPN_BARDICHE;
2249 }
2250
2251 return TILE_ERROR;
2252 }
2253
_tileidx_weapon(const item_def & item)2254 static tileidx_t _tileidx_weapon(const item_def &item)
2255 {
2256 tileidx_t tile = _tileidx_weapon_base(item);
2257 return tileidx_enchant_equ(item, tile);
2258 }
2259
_tileidx_missile_base(const item_def & item)2260 static tileidx_t _tileidx_missile_base(const item_def &item)
2261 {
2262 int brand = item.brand;
2263 // 0 indicates no ego at all
2264
2265 switch (item.sub_type)
2266 {
2267 case MI_STONE: return TILE_MI_STONE;
2268 case MI_LARGE_ROCK: return TILE_MI_LARGE_ROCK;
2269 case MI_THROWING_NET: return TILE_MI_THROWING_NET;
2270 case MI_BOOMERANG:
2271 switch (brand)
2272 {
2273 default: return TILE_MI_BOOMERANG + 1;
2274 case 0: return TILE_MI_BOOMERANG;
2275 case SPMSL_SILVER: return TILE_MI_BOOMERANG_SILVER;
2276 }
2277
2278 case MI_DART:
2279 switch (brand)
2280 {
2281 default: return TILE_MI_DART + 1;
2282 case 0: return TILE_MI_DART;
2283 case SPMSL_POISONED: return TILE_MI_DART_POISONED;
2284 case SPMSL_CURARE: return TILE_MI_DART_CURARE;
2285 case SPMSL_BLINDING: return TILE_MI_DART_BLINDING;
2286 case SPMSL_FRENZY: return TILE_MI_DART_FRENZY;
2287 }
2288
2289 case MI_ARROW:
2290 switch (brand)
2291 {
2292 default: return TILE_MI_ARROW + 1;
2293 case 0: return TILE_MI_ARROW;
2294 #if TAG_MAJOR_VERSION == 34
2295 case SPMSL_STEEL: return TILE_MI_ARROW_STEEL;
2296 #endif
2297 case SPMSL_SILVER: return TILE_MI_ARROW_SILVER;
2298 }
2299
2300 case MI_BOLT:
2301 switch (brand)
2302 {
2303 default: return TILE_MI_BOLT + 1;
2304 case 0: return TILE_MI_BOLT;
2305 #if TAG_MAJOR_VERSION == 34
2306 case SPMSL_STEEL: return TILE_MI_BOLT_STEEL;
2307 #endif
2308 case SPMSL_SILVER: return TILE_MI_BOLT_SILVER;
2309 }
2310
2311 case MI_SLING_BULLET:
2312 switch (brand)
2313 {
2314 default: return TILE_MI_SLING_BULLET + 1;
2315 case 0: return TILE_MI_SLING_BULLET;
2316 #if TAG_MAJOR_VERSION == 34
2317 case SPMSL_STEEL: return TILE_MI_SLING_BULLET_STEEL;
2318 #endif
2319 case SPMSL_SILVER: return TILE_MI_SLING_BULLET_SILVER;
2320 }
2321
2322 case MI_JAVELIN:
2323 switch (brand)
2324 {
2325 default: return TILE_MI_JAVELIN + 1;
2326 case 0: return TILE_MI_JAVELIN;
2327 #if TAG_MAJOR_VERSION == 34
2328 case SPMSL_STEEL: return TILE_MI_JAVELIN_STEEL;
2329 #endif
2330 case SPMSL_SILVER: return TILE_MI_JAVELIN_SILVER;
2331 }
2332 }
2333
2334 return TILE_ERROR;
2335 }
2336
_tileidx_missile(const item_def & item)2337 static tileidx_t _tileidx_missile(const item_def &item)
2338 {
2339 int tile = _tileidx_missile_base(item);
2340 return tileidx_enchant_equ(item, tile);
2341 }
2342
_tileidx_armour_base(const item_def & item)2343 static tileidx_t _tileidx_armour_base(const item_def &item)
2344 {
2345 int type = item.sub_type;
2346 switch (type)
2347 {
2348 case ARM_ROBE:
2349 return TILE_ARM_ROBE;
2350
2351 case ARM_LEATHER_ARMOUR:
2352 return TILE_ARM_LEATHER_ARMOUR;
2353
2354 case ARM_RING_MAIL:
2355 return TILE_ARM_RING_MAIL;
2356
2357 case ARM_SCALE_MAIL:
2358 return TILE_ARM_SCALE_MAIL;
2359
2360 case ARM_CHAIN_MAIL:
2361 return TILE_ARM_CHAIN_MAIL;
2362
2363 case ARM_PLATE_ARMOUR:
2364 return TILE_ARM_PLATE_ARMOUR;
2365
2366 case ARM_CRYSTAL_PLATE_ARMOUR:
2367 return TILE_ARM_CRYSTAL_PLATE_ARMOUR;
2368
2369 case ARM_KITE_SHIELD:
2370 return TILE_ARM_KITE_SHIELD;
2371
2372 case ARM_CLOAK:
2373 return TILE_ARM_CLOAK;
2374
2375 case ARM_SCARF:
2376 return TILE_ARM_SCARF;
2377
2378 case ARM_HAT:
2379 return TILE_THELM_HAT;
2380
2381 #if TAG_MAJOR_VERSION == 34
2382 case ARM_CAP:
2383 return TILE_THELM_CAP;
2384 #endif
2385
2386 case ARM_HELMET:
2387 return TILE_THELM_HELM;
2388
2389 case ARM_GLOVES:
2390 return TILE_ARM_GLOVES;
2391
2392 case ARM_BOOTS:
2393 return TILE_ARM_BOOTS;
2394
2395 case ARM_BUCKLER:
2396 return TILE_ARM_BUCKLER;
2397
2398 case ARM_TOWER_SHIELD:
2399 return TILE_ARM_TOWER_SHIELD;
2400
2401 case ARM_BARDING:
2402 return TILE_ARM_BARDING;
2403
2404 case ARM_ANIMAL_SKIN:
2405 return TILE_ARM_ANIMAL_SKIN;
2406
2407 case ARM_TROLL_LEATHER_ARMOUR:
2408 return TILE_ARM_TROLL_LEATHER_ARMOUR;
2409
2410 case ARM_FIRE_DRAGON_ARMOUR:
2411 return TILE_ARM_FIRE_DRAGON_ARMOUR;
2412
2413 case ARM_ICE_DRAGON_ARMOUR:
2414 return TILE_ARM_ICE_DRAGON_ARMOUR;
2415
2416 case ARM_STEAM_DRAGON_ARMOUR:
2417 return TILE_ARM_STEAM_DRAGON_ARMOUR;
2418
2419 case ARM_ACID_DRAGON_ARMOUR:
2420 return TILE_ARM_ACID_DRAGON_ARMOUR;
2421
2422 case ARM_QUICKSILVER_DRAGON_ARMOUR:
2423 return TILE_ARM_QUICKSILVER_DRAGON_ARMOUR;
2424
2425 case ARM_STORM_DRAGON_ARMOUR:
2426 return TILE_ARM_STORM_DRAGON_ARMOUR;
2427
2428 case ARM_SHADOW_DRAGON_ARMOUR:
2429 return TILE_ARM_SHADOW_DRAGON_ARMOUR;
2430
2431 case ARM_GOLD_DRAGON_ARMOUR:
2432 return TILE_ARM_GOLD_DRAGON_ARMOUR;
2433
2434 case ARM_PEARL_DRAGON_ARMOUR:
2435 return TILE_ARM_PEARL_DRAGON_ARMOUR;
2436
2437 case ARM_SWAMP_DRAGON_ARMOUR:
2438 return TILE_ARM_SWAMP_DRAGON_ARMOUR;
2439 }
2440
2441 return TILE_ERROR;
2442 }
2443
_tileidx_armour(const item_def & item)2444 static tileidx_t _tileidx_armour(const item_def &item)
2445 {
2446 tileidx_t tile = _tileidx_armour_base(item);
2447 return tileidx_enchant_equ(item, tile);
2448 }
2449
2450 // Returns index of skeleton tiles.
2451 // Parameter item holds the skeleton.
_tileidx_bone(const item_def & item)2452 static tileidx_t _tileidx_bone(const item_def &item)
2453 {
2454 const monster_type mc = item.mon_type;
2455 const size_type st = get_monster_data(mc)->size;
2456 int cs = 0;
2457
2458 switch (st)
2459 {
2460 default:
2461 cs = 0; break;
2462 case SIZE_MEDIUM:
2463 cs = 1; break;
2464 case SIZE_LARGE:
2465 case SIZE_BIG:
2466 cs = 2; break;
2467 case SIZE_GIANT:
2468 cs = 3; break;
2469 }
2470
2471 switch (get_mon_shape(item.mon_type))
2472 {
2473 case MON_SHAPE_HUMANOID:
2474 case MON_SHAPE_HUMANOID_TAILED:
2475 case MON_SHAPE_HUMANOID_WINGED:
2476 case MON_SHAPE_HUMANOID_WINGED_TAILED:
2477 return TILE_FOOD_BONE_HUMANOID + cs;
2478 default:
2479 return TILE_FOOD_BONE + cs;
2480 }
2481 }
2482
2483 // Returns index of corpse tiles.
2484 // Parameter item holds the corpse.
_tileidx_corpse(const item_def & item)2485 static tileidx_t _tileidx_corpse(const item_def &item)
2486 {
2487 const int type = item.plus;
2488 const tileidx_t base = get_mon_base_corpse_tile((monster_type)type);
2489
2490 switch (type)
2491 {
2492 case MONS_KILLER_KLOWN:
2493 {
2494 const int count = tile_main_count(TILE_CORPSE_KILLER_KLOWN);
2495 return base + ui_random(count);
2496 }
2497
2498 case MONS_UGLY_THING:
2499 case MONS_VERY_UGLY_THING:
2500 {
2501 int colour_offset = ugly_thing_colour_offset(item.get_colour());
2502 if (colour_offset == -1)
2503 colour_offset = 0;
2504 return base + colour_offset;
2505 }
2506
2507 default:
2508 return base;
2509 }
2510 }
2511
_tileidx_uncollected_rune(const item_def & item)2512 static tileidx_t _tileidx_uncollected_rune(const item_def &item)
2513 {
2514 switch (item.sub_type)
2515 {
2516 // the hell runes:
2517 case RUNE_DIS: return TILE_UNCOLLECTED_RUNE_DIS;
2518 case RUNE_GEHENNA: return TILE_UNCOLLECTED_RUNE_GEHENNA;
2519 case RUNE_COCYTUS: return TILE_UNCOLLECTED_RUNE_COCYTUS;
2520 case RUNE_TARTARUS: return TILE_UNCOLLECTED_RUNE_TARTARUS;
2521
2522 // special pandemonium runes:
2523 case RUNE_MNOLEG: return TILE_UNCOLLECTED_RUNE_MNOLEG;
2524 case RUNE_LOM_LOBON: return TILE_UNCOLLECTED_RUNE_LOM_LOBON;
2525 case RUNE_CEREBOV: return TILE_UNCOLLECTED_RUNE_CEREBOV;
2526 case RUNE_GLOORX_VLOQ: return TILE_UNCOLLECTED_RUNE_GLOORX_VLOQ;
2527
2528 case RUNE_DEMONIC: return TILE_UNCOLLECTED_RUNE_DEMONIC;
2529 case RUNE_ABYSSAL: return TILE_UNCOLLECTED_RUNE_ABYSS;
2530
2531 case RUNE_SNAKE: return TILE_UNCOLLECTED_RUNE_SNAKE;
2532 case RUNE_SPIDER: return TILE_UNCOLLECTED_RUNE_SPIDER;
2533 case RUNE_SLIME: return TILE_UNCOLLECTED_RUNE_SLIME;
2534 case RUNE_VAULTS: return TILE_UNCOLLECTED_RUNE_VAULTS;
2535 case RUNE_TOMB: return TILE_UNCOLLECTED_RUNE_TOMB;
2536 case RUNE_SWAMP: return TILE_UNCOLLECTED_RUNE_SWAMP;
2537 case RUNE_SHOALS: return TILE_UNCOLLECTED_RUNE_SHOALS;
2538 case RUNE_ELF: return TILE_UNCOLLECTED_RUNE_ELVEN;
2539
2540 case RUNE_FOREST:
2541 default: return TILE_MISC_UNCOLLECTED_RUNE_OF_ZOT;
2542 }
2543 }
2544
_tileidx_rune(const item_def & item)2545 static tileidx_t _tileidx_rune(const item_def &item)
2546 {
2547 switch (item.sub_type)
2548 {
2549 // the hell runes:
2550 case RUNE_DIS: return TILE_RUNE_DIS;
2551 case RUNE_GEHENNA: return TILE_RUNE_GEHENNA;
2552 case RUNE_COCYTUS: return TILE_RUNE_COCYTUS;
2553 case RUNE_TARTARUS: return TILE_RUNE_TARTARUS;
2554
2555 // special pandemonium runes:
2556 case RUNE_MNOLEG: return TILE_RUNE_MNOLEG;
2557 case RUNE_LOM_LOBON: return TILE_RUNE_LOM_LOBON;
2558 case RUNE_CEREBOV: return TILE_RUNE_CEREBOV;
2559 case RUNE_GLOORX_VLOQ: return TILE_RUNE_GLOORX_VLOQ;
2560
2561 case RUNE_DEMONIC: return TILE_RUNE_DEMONIC
2562 + ((uint32_t)item.rnd) % tile_main_count(TILE_RUNE_DEMONIC);
2563 case RUNE_ABYSSAL: return TILE_RUNE_ABYSS;
2564
2565 case RUNE_SNAKE: return TILE_RUNE_SNAKE;
2566 case RUNE_SPIDER: return TILE_RUNE_SPIDER;
2567 case RUNE_SLIME: return TILE_RUNE_SLIME;
2568 case RUNE_VAULTS: return TILE_RUNE_VAULTS;
2569 case RUNE_TOMB: return TILE_RUNE_TOMB;
2570 case RUNE_SWAMP: return TILE_RUNE_SWAMP;
2571 case RUNE_SHOALS: return TILE_RUNE_SHOALS;
2572 case RUNE_ELF: return TILE_RUNE_ELVEN;
2573
2574 case RUNE_FOREST:
2575 default: return TILE_MISC_RUNE_OF_ZOT;
2576 }
2577 }
2578
_tileidx_misc(const item_def & item)2579 static tileidx_t _tileidx_misc(const item_def &item)
2580 {
2581 switch (item.sub_type)
2582 {
2583 #if TAG_MAJOR_VERSION == 34
2584 case MISC_BOTTLED_EFREET:
2585 return TILE_MISC_BOTTLED_EFREET;
2586
2587 case MISC_FAN_OF_GALES:
2588 return TILE_MISC_FAN_OF_GALES_INERT;
2589
2590 case MISC_LAMP_OF_FIRE:
2591 return TILE_MISC_LAMP_OF_FIRE_INERT;
2592
2593 case MISC_STONE_OF_TREMORS:
2594 return TILE_MISC_STONE_OF_TREMORS_INERT;
2595 #endif
2596
2597 case MISC_PHIAL_OF_FLOODS:
2598 return evoker_charges(item.sub_type) ? TILE_MISC_PHIAL_OF_FLOODS
2599 : TILE_MISC_PHIAL_OF_FLOODS_INERT;
2600
2601 case MISC_TIN_OF_TREMORSTONES:
2602 return TILE_MISC_TIN_OF_TREMORSTONES;
2603
2604 case MISC_CONDENSER_VANE:
2605 return evoker_charges(item.sub_type) ? TILE_MISC_CONDENSER_VANE
2606 : TILE_MISC_CONDENSER_VANE_INERT;
2607
2608 case MISC_XOMS_CHESSBOARD:
2609 return _modrng(item.rnd, TILE_MISC_CHESSPIECE_FIRST, TILE_MISC_CHESSPIECE_LAST);
2610
2611 #if TAG_MAJOR_VERSION == 34
2612 case MISC_BUGGY_LANTERN_OF_SHADOWS:
2613 return TILE_MISC_LANTERN_OF_SHADOWS;
2614 #endif
2615
2616 case MISC_HORN_OF_GERYON:
2617 return TILE_MISC_HORN_OF_GERYON;
2618
2619 case MISC_BOX_OF_BEASTS:
2620 return TILE_MISC_BOX_OF_BEASTS;
2621
2622 #if TAG_MAJOR_VERSION == 34
2623 case MISC_CRYSTAL_BALL_OF_ENERGY:
2624 return TILE_MISC_CRYSTAL_BALL_OF_ENERGY;
2625 #endif
2626
2627 case MISC_LIGHTNING_ROD:
2628 return evoker_charges(item.sub_type) ? TILE_MISC_LIGHTNING_ROD
2629 : TILE_MISC_LIGHTNING_ROD_INERT;
2630
2631 #if TAG_MAJOR_VERSION == 34
2632 case MISC_SACK_OF_SPIDERS:
2633 return TILE_MISC_SACK_OF_SPIDERS;
2634 #endif
2635
2636 // Default for summary menus
2637 case NUM_MISCELLANY:
2638 case MISC_PHANTOM_MIRROR:
2639 return TILE_MISC_PHANTOM_MIRROR;
2640
2641 case MISC_ZIGGURAT:
2642 return TILE_MISC_ZIGGURAT;
2643
2644 case MISC_QUAD_DAMAGE:
2645 return TILE_MISC_QUAD_DAMAGE;
2646 }
2647
2648 return TILE_ERROR;
2649 }
2650
_tileidx_gold(const item_def & item)2651 static tileidx_t _tileidx_gold(const item_def &item)
2652 {
2653 if (item.quantity >= 1 && item.quantity <= 10)
2654 return TILE_GOLD01 + item.quantity - 1;
2655 if (item.quantity < 20)
2656 return TILE_GOLD16;
2657 if (item.quantity < 30)
2658 return TILE_GOLD19;
2659 if (item.quantity < 100)
2660 return TILE_GOLD23;
2661 return TILE_GOLD25;
2662 }
2663
tileidx_item(const item_def & item)2664 tileidx_t tileidx_item(const item_def &item)
2665 {
2666 if (item.props.exists("item_tile"))
2667 return item.props["item_tile"].get_short();
2668
2669 const int clas = item.base_type;
2670 const int type = item.sub_type;
2671 const int subtype_rnd = item.subtype_rnd;
2672 const int rnd = item.rnd;
2673
2674 switch (clas)
2675 {
2676 case OBJ_WEAPONS:
2677 if (is_unrandom_artefact(item, UNRAND_WYRMBANE))
2678 return _tileidx_wyrmbane(item.plus);
2679 else if (is_unrandom_artefact(item))
2680 return _tileidx_unrand_artefact(find_unrandart_index(item));
2681 else
2682 return _tileidx_weapon(item);
2683
2684 case OBJ_MISSILES:
2685 return _tileidx_missile(item);
2686
2687 case OBJ_ARMOUR:
2688 if (is_unrandom_artefact(item))
2689 return _tileidx_unrand_artefact(find_unrandart_index(item));
2690 else
2691 return _tileidx_armour(item);
2692
2693 case OBJ_WANDS:
2694 if (item.flags & ISFLAG_KNOW_TYPE)
2695 return TILE_WAND_ID_FIRST + type;
2696 else
2697 return TILE_WAND_OFFSET + subtype_rnd % NDSC_WAND_PRI;
2698
2699 case OBJ_SCROLLS:
2700 if (item.flags & ISFLAG_KNOW_TYPE)
2701 return TILE_SCR_ID_FIRST + type;
2702 return TILE_SCROLL;
2703
2704 case OBJ_GOLD:
2705 return _tileidx_gold(item);
2706
2707 case OBJ_JEWELLERY:
2708 if (is_unrandom_artefact(item))
2709 return _tileidx_unrand_artefact(find_unrandart_index(item));
2710
2711 // rings
2712 if (!jewellery_is_amulet(item))
2713 {
2714 if (is_artefact(item))
2715 {
2716 const int offset = item.rnd
2717 % tile_main_count(TILE_RING_RANDART_OFFSET);
2718 return TILE_RING_RANDART_OFFSET + offset;
2719 }
2720
2721 if (item.flags & ISFLAG_KNOW_TYPE)
2722 {
2723 return TILE_RING_ID_FIRST + type - RING_FIRST_RING
2724 #if TAG_MAJOR_VERSION == 34
2725 + 1 // we have a save-compat ring tile before FIRST_RING
2726 #endif
2727 ;
2728 }
2729
2730 return TILE_RING_NORMAL_OFFSET + subtype_rnd % NDSC_JEWEL_PRI;
2731 }
2732
2733 // amulets
2734 if (is_artefact(item))
2735 {
2736 const int offset = item.rnd
2737 % tile_main_count(TILE_AMU_RANDART_OFFSET);
2738 return TILE_AMU_RANDART_OFFSET + offset;
2739 }
2740
2741 if (item.flags & ISFLAG_KNOW_TYPE)
2742 return TILE_AMU_ID_FIRST + type - AMU_FIRST_AMULET;
2743 return TILE_AMU_NORMAL_OFFSET + subtype_rnd % NDSC_JEWEL_PRI;
2744
2745 case OBJ_POTIONS:
2746 if (item.flags & ISFLAG_KNOW_TYPE)
2747 return TILE_POT_ID_FIRST + type;
2748 else
2749 return TILE_POTION_OFFSET + item.subtype_rnd % NDSC_POT_PRI;
2750
2751 case OBJ_BOOKS:
2752 if (is_random_artefact(item))
2753 {
2754 const int offset = rnd % tile_main_count(TILE_BOOK_RANDART_OFFSET);
2755 return TILE_BOOK_RANDART_OFFSET + offset;
2756 }
2757
2758 if (item.sub_type == BOOK_MANUAL)
2759 return TILE_BOOK_MANUAL + rnd % tile_main_count(TILE_BOOK_MANUAL);
2760
2761 return TILE_BOOK_OFFSET
2762 + rnd % tile_main_count(TILE_BOOK_OFFSET);
2763
2764 case OBJ_STAVES:
2765 if (item.flags & ISFLAG_KNOW_TYPE)
2766 return TILE_STAFF_ID_FIRST + type;
2767
2768 return TILE_STAFF_OFFSET
2769 + (subtype_rnd / NDSC_STAVE_PRI) % NDSC_STAVE_SEC;
2770
2771 #if TAG_MAJOR_VERSION == 34
2772 case OBJ_RODS:
2773 return TILE_ROD + item.rnd % tile_main_count(TILE_ROD);
2774 #endif
2775
2776 case OBJ_CORPSES:
2777 if (item.sub_type == CORPSE_SKELETON)
2778 return _tileidx_bone(item);
2779 else
2780 return _tileidx_corpse(item);
2781
2782 case OBJ_ORBS:
2783 if (item.quantity <= 0)
2784 return TILE_UNCOLLECTED_ORB;
2785 return TILE_ORB + ui_random(tile_main_count(TILE_ORB));
2786
2787 case OBJ_MISCELLANY:
2788 return _tileidx_misc(item);
2789
2790 case OBJ_RUNES:
2791 if (item.quantity <= 0)
2792 return _tileidx_uncollected_rune(item);
2793 return _tileidx_rune(item);
2794
2795 case OBJ_DETECTED:
2796 return TILE_UNSEEN_ITEM;
2797
2798 default:
2799 return TILE_ERROR;
2800 }
2801 }
2802
2803 // Determine Octant of missile direction
2804 // .---> X+
2805 // |
2806 // | 701
2807 // Y 6O2
2808 // + 543
2809 //
2810 // The octant boundary slope tan(pi/8)=sqrt(2)-1 = 0.414 is approximated by 2/5.
_tile_bolt_dir(int dx,int dy)2811 static int _tile_bolt_dir(int dx, int dy)
2812 {
2813 int ax = abs(dx);
2814 int ay = abs(dy);
2815
2816 if (5*ay < 2*ax)
2817 return (dx > 0) ? 2 : 6;
2818 else if (5*ax < 2*ay)
2819 return (dy > 0) ? 4 : 0;
2820 else if (dx > 0)
2821 return (dy > 0) ? 3 : 1;
2822 else
2823 return (dy > 0) ? 5: 7;
2824 }
2825
tileidx_item_throw(const item_def & item,int dx,int dy)2826 tileidx_t tileidx_item_throw(const item_def &item, int dx, int dy)
2827 {
2828 if (item.base_type == OBJ_MISSILES)
2829 {
2830 int ch = -1;
2831 int dir = _tile_bolt_dir(dx, dy);
2832
2833 // Thrown items with multiple directions
2834 switch (item.sub_type)
2835 {
2836 case MI_ARROW:
2837 ch = TILE_MI_ARROW0;
2838 break;
2839 case MI_BOLT:
2840 ch = TILE_MI_BOLT0;
2841 break;
2842 case MI_DART:
2843 ch = TILE_MI_DART0;
2844 break;
2845 case MI_JAVELIN:
2846 ch = TILE_MI_JAVELIN0;
2847 break;
2848 case MI_THROWING_NET:
2849 ch = TILE_MI_THROWING_NET0;
2850 break;
2851 default:
2852 break;
2853 }
2854 if (ch != -1)
2855 return ch + dir;
2856
2857 // Thrown items with a single direction
2858 switch (item.sub_type)
2859 {
2860 case MI_STONE:
2861 ch = TILE_MI_STONE0;
2862 break;
2863 case MI_SLING_BULLET:
2864 switch (item.brand)
2865 {
2866 default:
2867 ch = TILE_MI_SLING_BULLET0;
2868 break;
2869 #if TAG_MAJOR_VERSION == 34
2870 case SPMSL_STEEL:
2871 ch = TILE_MI_SLING_BULLET_STEEL0;
2872 break;
2873 #endif
2874 case SPMSL_SILVER:
2875 ch = TILE_MI_SLING_BULLET_SILVER0;
2876 break;
2877 }
2878 break;
2879 case MI_LARGE_ROCK:
2880 ch = TILE_MI_LARGE_ROCK0;
2881 break;
2882 case MI_THROWING_NET:
2883 ch = TILE_MI_THROWING_NET0;
2884 break;
2885 case MI_BOOMERANG:
2886 ch = TILE_MI_BOOMERANG0;
2887 default:
2888 break;
2889 }
2890 if (ch != -1)
2891 return tileidx_enchant_equ(item, ch);
2892 }
2893
2894 // If not a special case, just return the default tile.
2895 return tileidx_item(item);
2896 }
2897
2898 // For items with randomized descriptions, only the overlay label is
2899 // placed in the tile page. This function looks up what the base item
2900 // is based on the randomized description. It returns 0 if there is none.
tileidx_known_base_item(tileidx_t label)2901 tileidx_t tileidx_known_base_item(tileidx_t label)
2902 {
2903 if (label >= TILE_POT_ID_FIRST && label <= TILE_POT_ID_LAST)
2904 {
2905 int type = label - TILE_POT_ID_FIRST;
2906 int desc = you.item_description[IDESC_POTIONS][type] % NDSC_POT_PRI;
2907
2908 if (!get_ident_type(OBJ_POTIONS, type))
2909 return TILE_UNSEEN_POTION;
2910 else
2911 return TILE_POTION_OFFSET + desc;
2912 }
2913
2914 if (label >= TILE_RING_ID_FIRST && label <= TILE_RING_ID_LAST)
2915 {
2916 int type = label - TILE_RING_ID_FIRST + RING_FIRST_RING
2917 #if TAG_MAJOR_VERSION == 34
2918 - 1 // we have a save-compat ring tile before FIRST_RING
2919 #endif
2920 ;
2921 int desc = you.item_description[IDESC_RINGS][type] % NDSC_JEWEL_PRI;
2922
2923 if (!get_ident_type(OBJ_JEWELLERY, type))
2924 return TILE_UNSEEN_RING;
2925 else
2926 return TILE_RING_NORMAL_OFFSET + desc;
2927 }
2928
2929 if (label >= TILE_AMU_ID_FIRST && label <= TILE_AMU_ID_LAST)
2930 {
2931 int type = label - TILE_AMU_ID_FIRST + AMU_FIRST_AMULET;
2932 int desc = you.item_description[IDESC_RINGS][type] % NDSC_JEWEL_PRI;
2933
2934 if (!get_ident_type(OBJ_JEWELLERY, type))
2935 return TILE_UNSEEN_AMULET;
2936 else
2937 return TILE_AMU_NORMAL_OFFSET + desc;
2938 }
2939
2940 if (label >= TILE_SCR_ID_FIRST && label <= TILE_SCR_ID_LAST)
2941 return TILE_SCROLL;
2942
2943 if (label >= TILE_WAND_ID_FIRST && label <= TILE_WAND_ID_LAST)
2944 {
2945 int type = label - TILE_WAND_ID_FIRST;
2946 int desc = you.item_description[IDESC_WANDS][type] % NDSC_WAND_PRI;
2947
2948 if (!get_ident_type(OBJ_WANDS, type))
2949 return TILE_UNSEEN_WAND;
2950 else
2951 return TILE_WAND_OFFSET + desc;
2952 }
2953
2954 if (label >= TILE_STAFF_ID_FIRST && label <= TILE_STAFF_ID_LAST)
2955 {
2956 int type = label - TILE_STAFF_ID_FIRST;
2957 int desc = you.item_description[IDESC_STAVES][type];
2958 desc = (desc / NDSC_STAVE_PRI) % NDSC_STAVE_SEC;
2959
2960 if (!get_ident_type(OBJ_STAVES, type))
2961 return TILE_UNSEEN_STAFF;
2962 else
2963 return TILE_STAFF_OFFSET + desc;
2964 }
2965
2966 return 0;
2967 }
2968
tileidx_cloud(const cloud_info & cl)2969 tileidx_t tileidx_cloud(const cloud_info &cl)
2970 {
2971 const cloud_type type = cl.type;
2972 const int colour = cl.colour;
2973 const unsigned int dur = cl.duration;
2974
2975 tileidx_t ch = cl.tile;
2976
2977 if (ch == 0)
2978 {
2979 const cloud_tile_info &tile_info = cloud_type_tile_info(type);
2980
2981 switch (tile_info.variation)
2982 {
2983 case CTVARY_NONE:
2984 ch = tile_info.base;
2985 break;
2986 case CTVARY_DUR:
2987 ch = tile_info.base + min(dur,
2988 tile_main_count(tile_info.base) - 1);
2989 break;
2990 case CTVARY_RANDOM:
2991 ch = tile_info.base + hash_with_seed(
2992 tile_main_count(tile_info.base),
2993 cl.pos.y * GXM + cl.pos.x, you.frame_no);
2994 break;
2995 }
2996
2997 if (!ch || ch == TILE_ERROR)
2998 ch = TILE_CLOUD_GREY_SMOKE;
2999
3000 switch (type)
3001 {
3002 case CLOUD_MUTAGENIC:
3003 ch = (dur == 0 ? TILE_CLOUD_MUTAGENIC_0 :
3004 dur == 1 ? TILE_CLOUD_MUTAGENIC_1
3005 : TILE_CLOUD_MUTAGENIC_2);
3006 ch += ui_random(tile_main_count(ch));
3007 break;
3008
3009 case CLOUD_VORTEX:
3010 ch = get_vortex_phase(cl.pos) ? TILE_CLOUD_FREEZING_WINDS_0
3011 : TILE_CLOUD_FREEZING_WINDS_1;
3012 break;
3013
3014 default:
3015 break;
3016 }
3017 }
3018
3019 if (colour != -1)
3020 ch = tile_main_coloured(ch, colour);
3021
3022 return ch;
3023 }
3024
tileidx_bolt(const bolt & bolt)3025 tileidx_t tileidx_bolt(const bolt &bolt)
3026 {
3027 const int col = bolt.colour;
3028 const coord_def diff = bolt.target - bolt.source;
3029 const int dir = _tile_bolt_dir(diff.x, diff.y);
3030
3031 switch (col)
3032 {
3033 case WHITE:
3034 if (bolt.name == "crystal spear")
3035 return TILE_BOLT_CRYSTAL_SPEAR + dir;
3036 else if (bolt.name == "puff of frost")
3037 return TILE_BOLT_FROST;
3038 else if (bolt.name == "shard of ice")
3039 return TILE_BOLT_ICICLE + dir;
3040 else if (bolt.name == "searing ray")
3041 return TILE_BOLT_SEARING_RAY;
3042 break;
3043
3044 case LIGHTCYAN:
3045 if (bolt.name == "iron shot")
3046 return TILE_BOLT_IRON_SHOT + dir;
3047 else if (bolt.name == "zap")
3048 return TILE_BOLT_ZAP + dir % tile_main_count(TILE_BOLT_ZAP);
3049 break;
3050
3051 case RED:
3052 if (bolt.name == "puff of flame")
3053 return TILE_BOLT_FLAME;
3054 break;
3055
3056 case LIGHTRED:
3057 if (bolt.name.find("damnation") != string::npos)
3058 return TILE_BOLT_DAMNATION;
3059 break;
3060
3061 case LIGHTMAGENTA:
3062 if (bolt.name == "magic dart")
3063 return TILE_BOLT_MAGIC_DART;
3064 break;
3065
3066 case BROWN:
3067 if (bolt.name == "blast of sand")
3068 return TILE_BOLT_SANDBLAST;
3069 else if (bolt.name == "klown pie")
3070 return TILE_BOLT_PIE + dir;
3071 break;
3072
3073 case GREEN:
3074 if (bolt.name == "sting")
3075 return TILE_BOLT_POISON_ARROW + dir;
3076 break;
3077
3078 case LIGHTGREEN:
3079 if (bolt.name == "poison arrow")
3080 return TILE_BOLT_POISON_ARROW + dir;
3081 break;
3082
3083 case LIGHTGREY:
3084 if (bolt.name == "stone arrow")
3085 return TILE_BOLT_STONE_ARROW + dir;
3086 break;
3087
3088 case DARKGREY:
3089 if (bolt.name == "bolt of negative energy")
3090 return TILE_BOLT_DRAIN;
3091 break;
3092
3093 case MAGENTA:
3094 break;
3095
3096 case CYAN:
3097 if (bolt.name == "slug dart")
3098 return TILE_BOLT_STONE_ARROW + dir;
3099 break;
3100
3101 case ETC_MUTAGENIC:
3102 if (bolt.name == "irradiate" || bolt.name == "unravelling")
3103 return TILE_BOLT_IRRADIATE;
3104 break;
3105 }
3106
3107 return tileidx_zap(col);
3108 }
3109
vary_bolt_tile(tileidx_t tile,int dist)3110 tileidx_t vary_bolt_tile(tileidx_t tile, int dist)
3111 {
3112 switch (tile)
3113 {
3114 case TILE_BOLT_FROST:
3115 case TILE_BOLT_MAGIC_DART:
3116 case TILE_BOLT_SANDBLAST:
3117 case TILE_BOLT_STING:
3118 return tile + dist % tile_main_count(tile);
3119 case TILE_BOLT_FLAME:
3120 case TILE_BOLT_IRRADIATE:
3121 return tile + ui_random(tile_main_count(tile));
3122 case TILE_MI_BOOMERANG0:
3123 return tile + ui_random(4);
3124 default:
3125 return tile;
3126 }
3127 }
3128
tileidx_zap(int colour)3129 tileidx_t tileidx_zap(int colour)
3130 {
3131 switch (colour)
3132 {
3133 case ETC_HOLY:
3134 colour = YELLOW;
3135 break;
3136 default:
3137 colour = element_colour(colour);
3138 break;
3139 }
3140
3141 if (colour < 1)
3142 colour = 7;
3143 else if (colour > 8)
3144 colour -= 8;
3145
3146 return TILE_SYM_BOLT_OFS - 1 + colour;
3147 }
3148
tileidx_spell(spell_type spell)3149 tileidx_t tileidx_spell(spell_type spell)
3150 {
3151 if (spell == NUM_SPELLS)
3152 return TILEG_MEMORISE; // XXX: Hack!
3153 return get_spell_tile(spell);
3154 }
3155
3156 /**
3157 * Get the appropriate tile for the given skill @ the given training level.
3158 *
3159 * @param skill The skill in question; e.g. SK_FIGHTING.
3160 * @param train The training_status to render at; e.g. TRAINING_DISABLED.
3161 * @return An appropriate tile; e.g. TILEG_FIGHTING_OFF>
3162 */
tileidx_skill(skill_type skill,int train)3163 tileidx_t tileidx_skill(skill_type skill, int train)
3164 {
3165 tileidx_t ch;
3166 switch (skill)
3167 {
3168 case SK_FIGHTING: ch = TILEG_FIGHTING_ON; break;
3169 case SK_SHORT_BLADES: ch = TILEG_SHORT_BLADES_ON; break;
3170 case SK_LONG_BLADES: ch = TILEG_LONG_BLADES_ON; break;
3171 case SK_AXES: ch = TILEG_AXES_ON; break;
3172 case SK_MACES_FLAILS: ch = TILEG_MACES_FLAILS_ON; break;
3173 case SK_POLEARMS: ch = TILEG_POLEARMS_ON; break;
3174 case SK_STAVES: ch = TILEG_STAVES_ON; break;
3175 case SK_SLINGS: ch = TILEG_SLINGS_ON; break;
3176 case SK_BOWS: ch = TILEG_BOWS_ON; break;
3177 case SK_CROSSBOWS: ch = TILEG_CROSSBOWS_ON; break;
3178 case SK_THROWING: ch = TILEG_THROWING_ON; break;
3179 case SK_ARMOUR: ch = TILEG_ARMOUR_ON; break;
3180 case SK_DODGING: ch = TILEG_DODGING_ON; break;
3181 case SK_STEALTH: ch = TILEG_STEALTH_ON; break;
3182 case SK_SHIELDS: ch = TILEG_SHIELDS_ON; break;
3183 case SK_UNARMED_COMBAT:
3184 {
3185 const string hand = you.hand_name(false);
3186 if (hand == "hand")
3187 ch = TILEG_UNARMED_COMBAT_ON;
3188 else if (hand == "paw")
3189 ch = TILEG_UNARMED_COMBAT_PAW_ON;
3190 else if (hand == "tentacle")
3191 ch = TILEG_UNARMED_COMBAT_TENTACLE_ON;
3192 else
3193 ch = TILEG_UNARMED_COMBAT_CLAW_ON;
3194 }
3195 break;
3196 case SK_SPELLCASTING: ch = TILEG_SPELLCASTING_ON; break;
3197 case SK_CONJURATIONS: ch = TILEG_CONJURATIONS_ON; break;
3198 case SK_HEXES: ch = TILEG_HEXES_ON; break;
3199 case SK_SUMMONINGS: ch = TILEG_SUMMONINGS_ON; break;
3200 case SK_NECROMANCY:
3201 ch = you.religion == GOD_KIKUBAAQUDGHA ? TILEG_NECROMANCY_K_ON
3202 : TILEG_NECROMANCY_ON; break;
3203 case SK_TRANSLOCATIONS: ch = TILEG_TRANSLOCATIONS_ON; break;
3204 case SK_TRANSMUTATIONS: ch = TILEG_TRANSMUTATIONS_ON; break;
3205 case SK_FIRE_MAGIC: ch = TILEG_FIRE_MAGIC_ON; break;
3206 case SK_ICE_MAGIC: ch = TILEG_ICE_MAGIC_ON; break;
3207 case SK_AIR_MAGIC: ch = TILEG_AIR_MAGIC_ON; break;
3208 case SK_EARTH_MAGIC: ch = TILEG_EARTH_MAGIC_ON; break;
3209 case SK_POISON_MAGIC: ch = TILEG_POISON_MAGIC_ON; break;
3210 case SK_EVOCATIONS: ch = TILEG_EVOCATIONS_ON; break;
3211 case SK_INVOCATIONS:
3212 {
3213 switch (you.religion)
3214 {
3215 // Gods who use invo get a unique tile.
3216 case GOD_SHINING_ONE:
3217 ch = TILEG_INVOCATIONS_1_ON; break;
3218 case GOD_BEOGH:
3219 ch = TILEG_INVOCATIONS_B_ON; break;
3220 case GOD_CHEIBRIADOS:
3221 ch = TILEG_INVOCATIONS_C_ON; break;
3222 case GOD_DITHMENOS:
3223 ch = TILEG_INVOCATIONS_D_ON; break;
3224 case GOD_ELYVILON:
3225 ch = TILEG_INVOCATIONS_E_ON; break;
3226 case GOD_FEDHAS:
3227 ch = TILEG_INVOCATIONS_F_ON; break;
3228 case GOD_HEPLIAKLQANA:
3229 ch = TILEG_INVOCATIONS_H_ON; break;
3230 case GOD_LUGONU:
3231 ch = TILEG_INVOCATIONS_L_ON; break;
3232 case GOD_MAKHLEB:
3233 ch = TILEG_INVOCATIONS_M_ON; break;
3234 case GOD_NEMELEX_XOBEH:
3235 ch = TILEG_INVOCATIONS_N_ON; break;
3236 case GOD_OKAWARU:
3237 ch = TILEG_INVOCATIONS_O_ON; break;
3238 case GOD_QAZLAL:
3239 ch = TILEG_INVOCATIONS_Q_ON; break;
3240 case GOD_SIF_MUNA:
3241 ch = TILEG_INVOCATIONS_S_ON; break;
3242 case GOD_USKAYAW:
3243 ch = TILEG_INVOCATIONS_U_ON; break;
3244 case GOD_YREDELEMNUL:
3245 ch = TILEG_INVOCATIONS_Y_ON; break;
3246 case GOD_ZIN:
3247 ch = TILEG_INVOCATIONS_Z_ON; break;
3248 default:
3249 ch = TILEG_INVOCATIONS_ON;
3250 }
3251 }
3252 break;
3253 default: return TILEG_TODO;
3254 }
3255
3256 switch (train)
3257 {
3258 case TRAINING_DISABLED:
3259 return ch + TILEG_FIGHTING_OFF - TILEG_FIGHTING_ON;
3260 case TRAINING_INACTIVE:
3261 return ch + TILEG_FIGHTING_INACTIVE - TILEG_FIGHTING_ON;
3262 case TRAINING_ENABLED:
3263 return ch;
3264 case TRAINING_FOCUSED:
3265 return ch + TILEG_FIGHTING_FOCUS - TILEG_FIGHTING_ON;
3266 case TRAINING_MASTERED:
3267 return ch + TILEG_FIGHTING_MAX - TILEG_FIGHTING_ON;
3268 default:
3269 die("invalid skill tile type");
3270 }
3271
3272 }
3273
tileidx_command(const command_type cmd)3274 tileidx_t tileidx_command(const command_type cmd)
3275 {
3276 switch (cmd)
3277 {
3278 case CMD_REST:
3279 return TILEG_CMD_REST;
3280 case CMD_EXPLORE:
3281 return TILEG_CMD_EXPLORE;
3282 case CMD_INTERLEVEL_TRAVEL:
3283 return TILEG_CMD_INTERLEVEL_TRAVEL;
3284 case CMD_AUTOFIGHT:
3285 return TILEG_CMD_AUTOFIGHT;
3286 case CMD_WAIT:
3287 return TILEG_CMD_WAIT;
3288 case CMD_USE_ABILITY:
3289 return TILEG_CMD_USE_ABILITY;
3290 case CMD_SEARCH_STASHES:
3291 return TILEG_CMD_SEARCH_STASHES;
3292 case CMD_REPLAY_MESSAGES:
3293 return TILEG_CMD_REPLAY_MESSAGES;
3294 case CMD_RESISTS_SCREEN:
3295 return TILEG_CMD_RESISTS_SCREEN;
3296 case CMD_DISPLAY_OVERMAP:
3297 return TILEG_CMD_DISPLAY_OVERMAP;
3298 case CMD_DISPLAY_RELIGION:
3299 return TILEG_CMD_DISPLAY_RELIGION;
3300 case CMD_DISPLAY_MUTATIONS:
3301 return TILEG_CMD_DISPLAY_MUTATIONS;
3302 case CMD_MACRO_ADD: // this tile is a fairly generic + despite the name
3303 case CMD_MACRO_MENU:
3304 case CMD_DISPLAY_SKILLS:
3305 return TILEG_CMD_DISPLAY_SKILLS;
3306 case CMD_SHOW_CHARACTER_DUMP:
3307 case CMD_DISPLAY_CHARACTER_STATUS:
3308 return TILEG_CMD_DISPLAY_CHARACTER_STATUS;
3309 case CMD_DISPLAY_KNOWN_OBJECTS:
3310 return TILEG_CMD_KNOWN_ITEMS;
3311 case CMD_SAVE_GAME_NOW:
3312 case CMD_SAVE_GAME:
3313 return TILEG_CMD_SAVE_GAME_NOW;
3314 #ifdef USE_TILE
3315 case CMD_EDIT_PLAYER_TILE:
3316 return TILEG_CMD_EDIT_PLAYER_TILE;
3317 #endif
3318 case CMD_DISPLAY_COMMANDS:
3319 return TILEG_CMD_DISPLAY_COMMANDS;
3320 case CMD_LOOKUP_HELP:
3321 return TILEG_CMD_LOOKUP_HELP;
3322 case CMD_CHARACTER_DUMP:
3323 return TILEG_CMD_CHARACTER_DUMP;
3324 case CMD_DISPLAY_INVENTORY:
3325 return TILEG_CMD_DISPLAY_INVENTORY;
3326 case CMD_CAST_SPELL:
3327 return TILEG_CMD_CAST_SPELL;
3328 case CMD_MEMORISE_SPELL:
3329 return TILEG_CMD_MEMORISE_SPELL;
3330 case CMD_DROP:
3331 return TILEG_CMD_DROP;
3332 case CMD_DISPLAY_MAP:
3333 return TILEG_CMD_DISPLAY_MAP;
3334 case CMD_MAP_GOTO_TARGET:
3335 return TILEG_CMD_MAP_GOTO_TARGET;
3336 case CMD_MAP_NEXT_LEVEL:
3337 return TILEG_CMD_MAP_NEXT_LEVEL;
3338 case CMD_MAP_PREV_LEVEL:
3339 return TILEG_CMD_MAP_PREV_LEVEL;
3340 case CMD_MAP_GOTO_LEVEL:
3341 return TILEG_CMD_MAP_GOTO_LEVEL;
3342 case CMD_MAP_EXCLUDE_AREA:
3343 return TILEG_CMD_MAP_EXCLUDE_AREA;
3344 case CMD_MAP_FIND_EXCLUDED:
3345 return TILEG_CMD_MAP_FIND_EXCLUDED;
3346 case CMD_MAP_CLEAR_EXCLUDES:
3347 return TILEG_CMD_MAP_CLEAR_EXCLUDES;
3348 case CMD_MAP_ADD_WAYPOINT:
3349 return TILEG_CMD_MAP_ADD_WAYPOINT;
3350 case CMD_MAP_FIND_WAYPOINT:
3351 return TILEG_CMD_MAP_FIND_WAYPOINT;
3352 case CMD_MAP_FIND_UPSTAIR:
3353 return TILEG_CMD_MAP_FIND_UPSTAIR;
3354 case CMD_MAP_FIND_DOWNSTAIR:
3355 return TILEG_CMD_MAP_FIND_DOWNSTAIR;
3356 case CMD_MAP_FIND_YOU:
3357 return TILEG_CMD_MAP_FIND_YOU;
3358 case CMD_MAP_FIND_PORTAL:
3359 return TILEG_CMD_MAP_FIND_PORTAL;
3360 case CMD_MAP_FIND_TRAP:
3361 return TILEG_CMD_MAP_FIND_TRAP;
3362 case CMD_MAP_FIND_ALTAR:
3363 return TILEG_CMD_MAP_FIND_ALTAR;
3364 case CMD_MAP_FIND_STASH:
3365 return TILEG_CMD_MAP_FIND_STASH;
3366 case CMD_QUIT:
3367 return TILEG_SYMBOL_OF_TORMENT;
3368 case CMD_GAME_MENU:
3369 return TILEG_STARTUP_STONESOUP;
3370 #ifdef TOUCH_UI
3371 case CMD_SHOW_KEYBOARD:
3372 return TILEG_CMD_KEYBOARD;
3373 #endif
3374 default:
3375 return TILEG_TODO;
3376 }
3377 }
3378
tileidx_gametype(const game_type gtype)3379 tileidx_t tileidx_gametype(const game_type gtype)
3380 {
3381 switch (gtype)
3382 {
3383 case GAME_TYPE_NORMAL:
3384 case GAME_TYPE_CUSTOM_SEED:
3385 return TILEG_STARTUP_STONESOUP;
3386 case GAME_TYPE_TUTORIAL:
3387 return TILEG_STARTUP_TUTORIAL;
3388 case GAME_TYPE_HINTS:
3389 return TILEG_STARTUP_HINTS;
3390 case GAME_TYPE_SPRINT:
3391 return TILEG_STARTUP_SPRINT;
3392 case GAME_TYPE_INSTRUCTIONS:
3393 return TILEG_STARTUP_INSTRUCTIONS;
3394 case GAME_TYPE_ARENA:
3395 return TILEG_STARTUP_ARENA;
3396 case GAME_TYPE_HIGH_SCORES:
3397 return TILEG_STARTUP_HIGH_SCORES;
3398 default:
3399 return TILEG_ERROR;
3400 }
3401 }
3402
tileidx_ability(const ability_type ability)3403 tileidx_t tileidx_ability(const ability_type ability)
3404 {
3405 switch (ability)
3406 {
3407 // Innate abilities and (Demonspaw) mutations.
3408 case ABIL_SPIT_POISON:
3409 return TILEG_ABILITY_SPIT_POISON;
3410 case ABIL_BREATHE_FIRE:
3411 return TILEG_ABILITY_BREATHE_FIRE;
3412 case ABIL_BREATHE_FROST:
3413 return TILEG_ABILITY_BREATHE_FROST;
3414 case ABIL_BREATHE_POISON:
3415 return TILEG_ABILITY_BREATHE_POISON;
3416 case ABIL_BREATHE_LIGHTNING:
3417 return TILEG_ABILITY_BREATHE_LIGHTNING;
3418 case ABIL_BREATHE_POWER:
3419 return TILEG_ABILITY_BREATHE_ENERGY;
3420 case ABIL_BREATHE_STEAM:
3421 return TILEG_ABILITY_BREATHE_STEAM;
3422 case ABIL_BREATHE_MEPHITIC:
3423 return TILEG_ABILITY_BREATHE_MEPHITIC;
3424 case ABIL_BREATHE_ACID:
3425 return TILEG_ABILITY_BREATHE_ACID;
3426 #if TAG_MAJOR_VERSION == 34
3427 case ABIL_BLINK:
3428 return TILEG_ABILITY_BLINK;
3429 #endif
3430 case ABIL_HOP:
3431 return TILEG_ABILITY_HOP;
3432 case ABIL_ROLLING_CHARGE:
3433 return TILEG_ABILITY_ROLL;
3434 case ABIL_BLINKBOLT:
3435 return TILEG_ABILITY_BLINKBOLT;
3436
3437 // Others
3438 case ABIL_END_TRANSFORMATION:
3439 return TILEG_ABILITY_END_TRANSFORMATION;
3440 case ABIL_STOP_RECALL:
3441 return TILEG_ABILITY_STOP_RECALL;
3442
3443 // Species-specific abilities.
3444 // Demonspawn-only
3445 case ABIL_DAMNATION:
3446 return TILEG_ABILITY_HURL_DAMNATION;
3447 case ABIL_WORD_OF_CHAOS:
3448 return TILEG_ABILITY_WORD_OF_CHAOS;
3449 // Vampires
3450 case ABIL_TRAN_BAT:
3451 return TILEG_ABILITY_BAT_FORM;
3452 case ABIL_EXSANGUINATE:
3453 return TILEG_ABILITY_EXSANGUINATE;
3454 case ABIL_REVIVIFY:
3455 return TILEG_ABILITY_REVIVIFY;
3456 // Deep Dwarves
3457 case ABIL_HEAL_WOUNDS:
3458 return TILEG_ABILITY_HEAL_WOUNDS;
3459 // Formicids
3460 case ABIL_DIG:
3461 return TILEG_ABILITY_DIG;
3462 case ABIL_SHAFT_SELF:
3463 return TILEG_ABILITY_SHAFT_SELF;
3464
3465 // Evoking items.
3466 case ABIL_EVOKE_BERSERK:
3467 return TILEG_ABILITY_EVOKE_BERSERK;
3468 case ABIL_EVOKE_BLINK:
3469 return TILEG_ABILITY_BLINK;
3470 case ABIL_EVOKE_TURN_INVISIBLE:
3471 return TILEG_ABILITY_EVOKE_INVISIBILITY;
3472 case ABIL_EVOKE_THUNDER:
3473 return TILEG_ABILITY_EVOKE_THUNDER;
3474
3475 // Divine abilities
3476 // Zin
3477 case ABIL_ZIN_SUSTENANCE:
3478 return TILEG_TODO;
3479 case ABIL_ZIN_RECITE:
3480 return TILEG_ABILITY_ZIN_RECITE;
3481 case ABIL_ZIN_VITALISATION:
3482 return TILEG_ABILITY_ZIN_VITALISATION;
3483 case ABIL_ZIN_IMPRISON:
3484 return TILEG_ABILITY_ZIN_IMPRISON;
3485 case ABIL_ZIN_SANCTUARY:
3486 return TILEG_ABILITY_ZIN_SANCTUARY;
3487 case ABIL_ZIN_DONATE_GOLD:
3488 return TILEG_ABILITY_ZIN_DONATE_GOLD;
3489 // TSO
3490 case ABIL_TSO_DIVINE_SHIELD:
3491 return TILEG_ABILITY_TSO_DIVINE_SHIELD;
3492 case ABIL_TSO_CLEANSING_FLAME:
3493 return TILEG_ABILITY_TSO_CLEANSING_FLAME;
3494 case ABIL_TSO_SUMMON_DIVINE_WARRIOR:
3495 return TILEG_ABILITY_TSO_DIVINE_WARRIOR;
3496 case ABIL_TSO_BLESS_WEAPON:
3497 return TILEG_ABILITY_TSO_BLESS_WEAPON;
3498 // Kiku
3499 case ABIL_KIKU_RECEIVE_CORPSES:
3500 return TILEG_ABILITY_KIKU_RECEIVE_CORPSES;
3501 case ABIL_KIKU_TORMENT:
3502 return TILEG_ABILITY_KIKU_TORMENT;
3503 case ABIL_KIKU_BLESS_WEAPON:
3504 return TILEG_ABILITY_KIKU_BLESS_WEAPON;
3505 case ABIL_KIKU_GIFT_CAPSTONE_SPELLS:
3506 return TILEG_ABILITY_KIKU_NECRONOMICON;
3507 // Yredelemnul
3508 case ABIL_YRED_INJURY_MIRROR:
3509 return TILEG_ABILITY_YRED_INJURY_MIRROR;
3510 case ABIL_YRED_ANIMATE_REMAINS:
3511 return TILEG_ABILITY_YRED_ANIMATE_REMAINS;
3512 case ABIL_YRED_RECALL_UNDEAD_SLAVES:
3513 return TILEG_ABILITY_YRED_RECALL;
3514 case ABIL_YRED_ANIMATE_DEAD:
3515 return TILEG_ABILITY_YRED_ANIMATE_DEAD;
3516 case ABIL_YRED_DRAIN_LIFE:
3517 return TILEG_ABILITY_YRED_DRAIN_LIFE;
3518 case ABIL_YRED_ENSLAVE_SOUL:
3519 return TILEG_ABILITY_YRED_ENSLAVE_SOUL;
3520 // Xom, Vehumet = 90
3521 // Okawaru
3522 case ABIL_OKAWARU_HEROISM:
3523 return TILEG_ABILITY_OKAWARU_HEROISM;
3524 case ABIL_OKAWARU_FINESSE:
3525 return TILEG_ABILITY_OKAWARU_FINESSE;
3526 // Makhleb
3527 case ABIL_MAKHLEB_MINOR_DESTRUCTION:
3528 return TILEG_ABILITY_MAKHLEB_MINOR_DESTRUCTION;
3529 case ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB:
3530 return TILEG_ABILITY_MAKHLEB_LESSER_SERVANT;
3531 case ABIL_MAKHLEB_MAJOR_DESTRUCTION:
3532 return TILEG_ABILITY_MAKHLEB_MAJOR_DESTRUCTION;
3533 case ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB:
3534 return TILEG_ABILITY_MAKHLEB_GREATER_SERVANT;
3535 // Sif Muna
3536 case ABIL_SIF_MUNA_CHANNEL_ENERGY:
3537 return TILEG_ABILITY_SIF_MUNA_CHANNEL;
3538 case ABIL_SIF_MUNA_FORGET_SPELL:
3539 return TILEG_ABILITY_SIF_MUNA_AMNESIA;
3540 case ABIL_SIF_MUNA_DIVINE_EXEGESIS:
3541 return TILEG_ABILITY_SIF_MUNA_EXEGESIS;
3542 // Trog
3543 case ABIL_TROG_BERSERK:
3544 return TILEG_ABILITY_TROG_BERSERK;
3545 case ABIL_TROG_HAND:
3546 return TILEG_ABILITY_TROG_HAND;
3547 case ABIL_TROG_BROTHERS_IN_ARMS:
3548 return TILEG_ABILITY_TROG_BROTHERS_IN_ARMS;
3549 // Elyvilon
3550 case ABIL_ELYVILON_LIFESAVING:
3551 return TILEG_ABILITY_ELYVILON_DIVINE_PROTECTION;
3552 case ABIL_ELYVILON_LESSER_HEALING:
3553 return TILEG_ABILITY_ELYVILON_LESSER_HEALING;
3554 case ABIL_ELYVILON_PURIFICATION:
3555 return TILEG_ABILITY_ELYVILON_PURIFICATION;
3556 case ABIL_ELYVILON_GREATER_HEALING:
3557 return TILEG_ABILITY_ELYVILON_GREATER_HEALING;
3558 case ABIL_ELYVILON_HEAL_OTHER:
3559 return TILEG_ABILITY_ELYVILON_HEAL_OTHER;
3560 case ABIL_ELYVILON_DIVINE_VIGOUR:
3561 return TILEG_ABILITY_ELYVILON_DIVINE_VIGOUR;
3562 // Lugonu
3563 case ABIL_LUGONU_ABYSS_EXIT:
3564 return TILEG_ABILITY_LUGONU_EXIT_ABYSS;
3565 case ABIL_LUGONU_BEND_SPACE:
3566 return TILEG_ABILITY_LUGONU_BEND_SPACE;
3567 case ABIL_LUGONU_BANISH:
3568 return TILEG_ABILITY_LUGONU_BANISH;
3569 case ABIL_LUGONU_CORRUPT:
3570 return TILEG_ABILITY_LUGONU_CORRUPT;
3571 case ABIL_LUGONU_ABYSS_ENTER:
3572 return TILEG_ABILITY_LUGONU_ENTER_ABYSS;
3573 case ABIL_LUGONU_BLESS_WEAPON:
3574 return TILEG_ABILITY_LUGONU_BLESS_WEAPON;
3575 // Nemelex
3576 case ABIL_NEMELEX_TRIPLE_DRAW:
3577 return TILEG_ABILITY_NEMELEX_TRIPLE_DRAW;
3578 case ABIL_NEMELEX_DEAL_FOUR:
3579 return TILEG_ABILITY_NEMELEX_DEAL_FOUR;
3580 case ABIL_NEMELEX_STACK_FIVE:
3581 return TILEG_ABILITY_NEMELEX_STACK_FIVE;
3582 case ABIL_NEMELEX_DRAW_ESCAPE:
3583 return TILEG_ABILITY_NEMELEX_DRAW_ESCAPE;
3584 case ABIL_NEMELEX_DRAW_DESTRUCTION:
3585 return TILEG_ABILITY_NEMELEX_DRAW_DESTRUCTION;
3586 case ABIL_NEMELEX_DRAW_SUMMONING:
3587 return TILEG_ABILITY_NEMELEX_DRAW_SUMMONING;
3588 case ABIL_NEMELEX_DRAW_STACK:
3589 return TILEG_ABILITY_NEMELEX_DRAW_STACK;
3590 // Beogh
3591 case ABIL_BEOGH_GIFT_ITEM:
3592 return TILEG_ABILITY_BEOGH_GIFT_ITEM;
3593 case ABIL_BEOGH_SMITING:
3594 return TILEG_ABILITY_BEOGH_SMITE;
3595 case ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS:
3596 return TILEG_ABILITY_BEOGH_RECALL;
3597 case ABIL_CONVERT_TO_BEOGH:
3598 return TILEG_ABILITY_CONVERT_TO_BEOGH;
3599 case ABIL_BEOGH_RESURRECTION:
3600 return TILEG_ABILITY_BEOGH_RESURRECTION;
3601 // Jiyva
3602 case ABIL_JIYVA_CALL_JELLY:
3603 return TILEG_ABILITY_JIYVA_REQUEST_JELLY;
3604 case ABIL_JIYVA_SLIMIFY:
3605 return TILEG_ABILITY_JIYVA_SLIMIFY;
3606 case ABIL_JIYVA_CURE_BAD_MUTATION:
3607 return TILEG_ABILITY_JIYVA_CURE_BAD_MUTATIONS;
3608 // Fedhas
3609 case ABIL_FEDHAS_WALL_OF_BRIARS:
3610 return TILEG_ABILITY_FEDHAS_WALL_OF_BRIARS;
3611 case ABIL_FEDHAS_GROW_BALLISTOMYCETE:
3612 return TILEG_ABILITY_FEDHAS_GROW_BALLISTOMYCETE;
3613 case ABIL_FEDHAS_OVERGROW:
3614 return TILEG_ABILITY_FEDHAS_OVERGROW;
3615 case ABIL_FEDHAS_GROW_OKLOB:
3616 return TILEG_ABILITY_FEDHAS_GROW_OKLOB;
3617 // Cheibriados
3618 case ABIL_CHEIBRIADOS_TIME_STEP:
3619 return TILEG_ABILITY_CHEIBRIADOS_TIME_STEP;
3620 case ABIL_CHEIBRIADOS_TIME_BEND:
3621 return TILEG_ABILITY_CHEIBRIADOS_BEND_TIME;
3622 case ABIL_CHEIBRIADOS_SLOUCH:
3623 return TILEG_ABILITY_CHEIBRIADOS_SLOUCH;
3624 case ABIL_CHEIBRIADOS_DISTORTION:
3625 return TILEG_ABILITY_CHEIBRIADOS_TEMPORAL_DISTORTION;
3626 // Ashenzari
3627 case ABIL_ASHENZARI_CURSE:
3628 return TILEG_ABILITY_ASHENZARI_CURSE;
3629 case ABIL_ASHENZARI_UNCURSE:
3630 return TILEG_ABILITY_ASHENZARI_UNCURSE;
3631 // Dithmenos
3632 case ABIL_DITHMENOS_SHADOW_STEP:
3633 return TILEG_ABILITY_DITHMENOS_SHADOW_STEP;
3634 case ABIL_DITHMENOS_SHADOW_FORM:
3635 return TILEG_ABILITY_DITHMENOS_SHADOW_FORM;
3636 // Gozag
3637 case ABIL_GOZAG_POTION_PETITION:
3638 return TILEG_ABILITY_GOZAG_POTION_PETITION;
3639 case ABIL_GOZAG_CALL_MERCHANT:
3640 return TILEG_ABILITY_GOZAG_CALL_MERCHANT;
3641 case ABIL_GOZAG_BRIBE_BRANCH:
3642 return TILEG_ABILITY_GOZAG_BRIBE_BRANCH;
3643 // Qazlal
3644 case ABIL_QAZLAL_UPHEAVAL:
3645 return TILEG_ABILITY_QAZLAL_UPHEAVAL;
3646 case ABIL_QAZLAL_ELEMENTAL_FORCE:
3647 return TILEG_ABILITY_QAZLAL_ELEMENTAL_FORCE;
3648 case ABIL_QAZLAL_DISASTER_AREA:
3649 return TILEG_ABILITY_QAZLAL_DISASTER_AREA;
3650 // Ru
3651 case ABIL_RU_DRAW_OUT_POWER:
3652 return TILEG_ABILITY_RU_DRAW_OUT_POWER;
3653 case ABIL_RU_POWER_LEAP:
3654 return TILEG_ABILITY_RU_POWER_LEAP;
3655 case ABIL_RU_APOCALYPSE:
3656 return TILEG_ABILITY_RU_APOCALYPSE;
3657
3658 case ABIL_RU_SACRIFICE_PURITY:
3659 return TILEG_ABILITY_RU_SACRIFICE_PURITY;
3660 case ABIL_RU_SACRIFICE_WORDS:
3661 return TILEG_ABILITY_RU_SACRIFICE_WORDS;
3662 case ABIL_RU_SACRIFICE_DRINK:
3663 return TILEG_ABILITY_RU_SACRIFICE_DRINK;
3664 case ABIL_RU_SACRIFICE_ESSENCE:
3665 return TILEG_ABILITY_RU_SACRIFICE_ESSENCE;
3666 case ABIL_RU_SACRIFICE_HEALTH:
3667 return TILEG_ABILITY_RU_SACRIFICE_HEALTH;
3668 case ABIL_RU_SACRIFICE_STEALTH:
3669 return TILEG_ABILITY_RU_SACRIFICE_STEALTH;
3670 case ABIL_RU_SACRIFICE_ARTIFICE:
3671 return TILEG_ABILITY_RU_SACRIFICE_ARTIFICE;
3672 case ABIL_RU_SACRIFICE_LOVE:
3673 return TILEG_ABILITY_RU_SACRIFICE_LOVE;
3674 case ABIL_RU_SACRIFICE_COURAGE:
3675 return TILEG_ABILITY_RU_SACRIFICE_COURAGE;
3676 case ABIL_RU_SACRIFICE_ARCANA:
3677 return TILEG_ABILITY_RU_SACRIFICE_ARCANA;
3678 case ABIL_RU_SACRIFICE_NIMBLENESS:
3679 return TILEG_ABILITY_RU_SACRIFICE_NIMBLENESS;
3680 case ABIL_RU_SACRIFICE_DURABILITY:
3681 return TILEG_ABILITY_RU_SACRIFICE_DURABILITY;
3682 case ABIL_RU_SACRIFICE_HAND:
3683 return TILEG_ABILITY_RU_SACRIFICE_HAND;
3684 case ABIL_RU_SACRIFICE_EXPERIENCE:
3685 return TILEG_ABILITY_RU_SACRIFICE_EXPERIENCE;
3686 case ABIL_RU_SACRIFICE_SKILL:
3687 return TILEG_ABILITY_RU_SACRIFICE_SKILL;
3688 case ABIL_RU_SACRIFICE_EYE:
3689 return TILEG_ABILITY_RU_SACRIFICE_EYE;
3690 case ABIL_RU_SACRIFICE_RESISTANCE:
3691 return TILEG_ABILITY_RU_SACRIFICE_RESISTANCE;
3692 case ABIL_RU_REJECT_SACRIFICES:
3693 return TILEG_ABILITY_RU_REJECT_SACRIFICES;
3694 // Hepliaklqana
3695 case ABIL_HEPLIAKLQANA_RECALL:
3696 return TILEG_ABILITY_HEP_RECALL;
3697 case ABIL_HEPLIAKLQANA_IDEALISE:
3698 return TILEG_ABILITY_HEP_IDEALISE;
3699 case ABIL_HEPLIAKLQANA_TRANSFERENCE:
3700 return TILEG_ABILITY_HEP_TRANSFERENCE;
3701 case ABIL_HEPLIAKLQANA_IDENTITY:
3702 return TILEG_ABILITY_HEP_IDENTITY;
3703 case ABIL_HEPLIAKLQANA_TYPE_KNIGHT:
3704 return TILEG_ABILITY_HEP_KNIGHT;
3705 case ABIL_HEPLIAKLQANA_TYPE_BATTLEMAGE:
3706 return TILEG_ABILITY_HEP_BATTLEMAGE;
3707 case ABIL_HEPLIAKLQANA_TYPE_HEXER:
3708 return TILEG_ABILITY_HEP_HEXER;
3709 // usk
3710 case ABIL_USKAYAW_STOMP:
3711 return TILEG_ABILITY_USKAYAW_STOMP;
3712 case ABIL_USKAYAW_LINE_PASS:
3713 return TILEG_ABILITY_USKAYAW_LINE_PASS;
3714 case ABIL_USKAYAW_GRAND_FINALE:
3715 return TILEG_ABILITY_USKAYAW_GRAND_FINALE;
3716 // Wu Jian
3717 case ABIL_WU_JIAN_WALLJUMP:
3718 return TILEG_ABILITY_WU_JIAN_WALL_JUMP;
3719 case ABIL_WU_JIAN_SERPENTS_LASH:
3720 return TILEG_ABILITY_WU_JIAN_SERPENTS_LASH;
3721 case ABIL_WU_JIAN_HEAVENLY_STORM:
3722 return TILEG_ABILITY_WU_JIAN_HEAVENLY_STORM;
3723
3724 // General divine (pseudo) abilities.
3725 case ABIL_RENOUNCE_RELIGION:
3726 return TILEG_ABILITY_RENOUNCE_RELIGION;
3727
3728 default:
3729 return TILEG_ERROR;
3730 }
3731 }
3732
tileidx_branch(const branch_type br)3733 tileidx_t tileidx_branch(const branch_type br)
3734 {
3735 switch (br)
3736 {
3737 case BRANCH_DUNGEON:
3738 return TILE_DNGN_EXIT_DUNGEON;
3739 case BRANCH_TEMPLE:
3740 return TILE_DNGN_ENTER_TEMPLE;
3741 case BRANCH_ORC:
3742 return TILE_DNGN_ENTER_ORC;
3743 case BRANCH_ELF:
3744 return TILE_DNGN_ENTER_ELF;
3745 case BRANCH_LAIR:
3746 return TILE_DNGN_ENTER_LAIR;
3747 case BRANCH_SWAMP:
3748 return TILE_DNGN_ENTER_SWAMP;
3749 case BRANCH_SHOALS:
3750 return TILE_DNGN_ENTER_SHOALS;
3751 case BRANCH_SNAKE:
3752 return TILE_DNGN_ENTER_SNAKE;
3753 case BRANCH_SPIDER:
3754 return TILE_DNGN_ENTER_SPIDER;
3755 case BRANCH_SLIME:
3756 return TILE_DNGN_ENTER_SLIME;
3757 case BRANCH_VAULTS:
3758 return TILE_DNGN_ENTER_VAULTS_OPEN;
3759 case BRANCH_CRYPT:
3760 return TILE_DNGN_ENTER_CRYPT;
3761 case BRANCH_TOMB:
3762 return TILE_DNGN_ENTER_TOMB;
3763 case BRANCH_DEPTHS:
3764 return TILE_DNGN_ENTER_DEPTHS;
3765 case BRANCH_VESTIBULE:
3766 return TILE_DNGN_ENTER_HELL;
3767 case BRANCH_DIS:
3768 return TILE_DNGN_ENTER_DIS;
3769 case BRANCH_GEHENNA:
3770 return TILE_DNGN_ENTER_GEHENNA;
3771 case BRANCH_COCYTUS:
3772 return TILE_DNGN_ENTER_COCYTUS;
3773 case BRANCH_TARTARUS:
3774 return TILE_DNGN_ENTER_TARTARUS;
3775 case BRANCH_ZOT:
3776 return TILE_DNGN_ENTER_ZOT_OPEN;
3777 case BRANCH_ABYSS:
3778 return TILE_DNGN_ENTER_ABYSS;
3779 case BRANCH_PANDEMONIUM:
3780 return TILE_DNGN_ENTER_PANDEMONIUM;
3781 case BRANCH_ZIGGURAT:
3782 return TILE_DNGN_PORTAL_ZIGGURAT;
3783 case BRANCH_GAUNTLET:
3784 return TILE_DNGN_PORTAL_GAUNTLET;
3785 case BRANCH_BAZAAR:
3786 return TILE_DNGN_PORTAL_BAZAAR;
3787 case BRANCH_TROVE:
3788 return TILE_DNGN_PORTAL_TROVE;
3789 case BRANCH_SEWER:
3790 return TILE_DNGN_PORTAL_SEWER;
3791 case BRANCH_OSSUARY:
3792 return TILE_DNGN_PORTAL_OSSUARY;
3793 case BRANCH_BAILEY:
3794 return TILE_DNGN_PORTAL_BAILEY;
3795 case BRANCH_ICE_CAVE:
3796 return TILE_DNGN_PORTAL_ICE_CAVE;
3797 case BRANCH_VOLCANO:
3798 return TILE_DNGN_PORTAL_VOLCANO;
3799 case BRANCH_WIZLAB:
3800 return TILE_DNGN_PORTAL_WIZARD_LAB_7; /* I like this colour */
3801 case BRANCH_DESOLATION:
3802 return TILE_DNGN_PORTAL_DESOLATION;
3803
3804 default:
3805 return TILEG_ERROR;
3806 }
3807 }
3808
_tileidx_player_job_base(const job_type job)3809 static tileidx_t _tileidx_player_job_base(const job_type job)
3810 {
3811 switch (job)
3812 {
3813 case JOB_FIGHTER:
3814 return TILEG_JOB_FIGHTER;
3815 case JOB_WIZARD:
3816 return TILEG_JOB_WIZARD;
3817 case JOB_GLADIATOR:
3818 return TILEG_JOB_GLADIATOR;
3819 case JOB_NECROMANCER:
3820 return TILEG_JOB_NECROMANCER;
3821 case JOB_BRIGAND:
3822 return TILEG_JOB_BRIGAND;
3823 case JOB_BERSERKER:
3824 return TILEG_JOB_BERSERKER;
3825 case JOB_HUNTER:
3826 return TILEG_JOB_HUNTER;
3827 case JOB_CONJURER:
3828 return TILEG_JOB_CONJURER;
3829 case JOB_ENCHANTER:
3830 return TILEG_JOB_ENCHANTER;
3831 case JOB_FIRE_ELEMENTALIST:
3832 return TILEG_JOB_FIRE_ELEMENTALIST;
3833 case JOB_ICE_ELEMENTALIST:
3834 return TILEG_JOB_ICE_ELEMENTALIST;
3835 case JOB_SUMMONER:
3836 return TILEG_JOB_SUMMONER;
3837 case JOB_AIR_ELEMENTALIST:
3838 return TILEG_JOB_AIR_ELEMENTALIST;
3839 case JOB_EARTH_ELEMENTALIST:
3840 return TILEG_JOB_EARTH_ELEMENTALIST;
3841 case JOB_VENOM_MAGE:
3842 return TILEG_JOB_VENOM_MAGE;
3843 case JOB_CHAOS_KNIGHT:
3844 return TILEG_JOB_CHAOS_KNIGHT;
3845 case JOB_TRANSMUTER:
3846 return TILEG_JOB_TRANSMUTER;
3847 case JOB_MONK:
3848 return TILEG_JOB_MONK;
3849 case JOB_WARPER:
3850 return TILEG_JOB_WARPER;
3851 case JOB_WANDERER:
3852 return TILEG_JOB_WANDERER;
3853 case JOB_ARTIFICER:
3854 return TILEG_JOB_ARTIFICER;
3855 case JOB_DELVER:
3856 return TILEG_JOB_DELVER;
3857 case JOB_ARCANE_MARKSMAN:
3858 return TILEG_JOB_ARCANE_MARKSMAN;
3859 case JOB_ABYSSAL_KNIGHT:
3860 return TILEG_JOB_ABYSSAL_KNIGHT;
3861 default:
3862 return TILEG_ERROR;
3863 }
3864 }
3865
_tileidx_player_species_base(const species_type species)3866 static tileidx_t _tileidx_player_species_base(const species_type species)
3867 {
3868 switch (species)
3869 {
3870 case SP_HUMAN:
3871 return TILEG_SP_HUMAN;
3872 case SP_DEEP_ELF:
3873 return TILEG_SP_DEEP_ELF;
3874 case SP_HILL_ORC:
3875 return TILEG_SP_HILL_ORC;
3876 case SP_KOBOLD:
3877 return TILEG_SP_KOBOLD;
3878 case SP_MUMMY:
3879 return TILEG_SP_MUMMY;
3880 case SP_NAGA:
3881 return TILEG_SP_NAGA;
3882 case SP_OGRE:
3883 return TILEG_SP_OGRE;
3884 case SP_TROLL:
3885 return TILEG_SP_TROLL;
3886 case SP_BASE_DRACONIAN:
3887 return TILEG_SP_DRACONIAN;
3888 case SP_PALENTONGA:
3889 return TILEG_SP_PALENTONGA;
3890 case SP_DEMIGOD:
3891 return TILEG_SP_DEMIGOD;
3892 case SP_SPRIGGAN:
3893 return TILEG_SP_SPRIGGAN;
3894 case SP_MINOTAUR:
3895 return TILEG_SP_MINOTAUR;
3896 case SP_DEMONSPAWN:
3897 return TILEG_SP_DEMONSPAWN;
3898 case SP_GHOUL:
3899 return TILEG_SP_GHOUL;
3900 case SP_TENGU:
3901 return TILEG_SP_TENGU;
3902 case SP_MERFOLK:
3903 return TILEG_SP_MERFOLK;
3904 case SP_VAMPIRE:
3905 return TILEG_SP_VAMPIRE;
3906 case SP_DEEP_DWARF:
3907 return TILEG_SP_DEEP_DWARF;
3908 case SP_FELID:
3909 return TILEG_SP_FELID;
3910 case SP_OCTOPODE:
3911 return TILEG_SP_OCTOPODE;
3912 case SP_GARGOYLE:
3913 return TILEG_SP_GARGOYLE;
3914 case SP_FORMICID:
3915 return TILEG_SP_FORMICID;
3916 case SP_VINE_STALKER:
3917 return TILEG_SP_VINE_STALKER;
3918 case SP_BARACHI:
3919 return TILEG_SP_BARACHI;
3920 case SP_GNOLL:
3921 return TILEG_SP_GNOLL;
3922 case SP_DJINNI:
3923 return TILEG_SP_DJINNI;
3924 default:
3925 return TILEP_ERROR;
3926 }
3927 }
3928
tileidx_player_species(const species_type species,bool recommended)3929 tileidx_t tileidx_player_species(const species_type species, bool recommended)
3930 {
3931 tileidx_t off = recommended ? -TILEG_LAST_SPECIES+TILEG_LAST_RECOMMENDED_SPECIES: 0;
3932 return _tileidx_player_species_base(species) + off;
3933 }
3934
tileidx_player_job(const job_type job,bool recommended)3935 tileidx_t tileidx_player_job(const job_type job, bool recommended)
3936 {
3937 tileidx_t off = recommended ? -TILEG_LAST_JOB+TILEG_LAST_RECOMMENDED_JOB: 0;
3938 return _tileidx_player_job_base(job) + off;
3939 }
3940
tileidx_known_brand(const item_def & item)3941 tileidx_t tileidx_known_brand(const item_def &item)
3942 {
3943 if (!item_type_known(item))
3944 return 0;
3945
3946 if (item.base_type == OBJ_WEAPONS)
3947 {
3948 const int brand = get_weapon_brand(item);
3949 if (brand != SPWPN_NORMAL)
3950 return TILE_BRAND_WEP_FIRST + get_weapon_brand(item) - 1;
3951 }
3952 else if (item.base_type == OBJ_ARMOUR)
3953 {
3954 const int brand = get_armour_ego_type(item);
3955 if (brand != SPARM_NORMAL)
3956 return TILE_BRAND_ARM_FIRST + get_armour_ego_type(item) - 1;
3957 }
3958 else if (item.base_type == OBJ_MISSILES)
3959 {
3960 switch (get_ammo_brand(item))
3961 {
3962 #if TAG_MAJOR_VERSION == 34
3963 case SPMSL_FLAME:
3964 return TILE_BRAND_FLAME;
3965 case SPMSL_FROST:
3966 return TILE_BRAND_FROST;
3967 #endif
3968 case SPMSL_POISONED:
3969 return TILE_BRAND_POISONED;
3970 case SPMSL_CURARE:
3971 return TILE_BRAND_CURARE;
3972 #if TAG_MAJOR_VERSION == 34
3973 case SPMSL_RETURNING:
3974 return TILE_BRAND_RETURNING;
3975 #endif
3976 case SPMSL_CHAOS:
3977 return TILE_BRAND_CHAOS;
3978 #if TAG_MAJOR_VERSION == 34
3979 case SPMSL_PENETRATION:
3980 return TILE_BRAND_PENETRATION;
3981 #endif
3982 case SPMSL_DISPERSAL:
3983 return TILE_BRAND_DISPERSAL;
3984 case SPMSL_EXPLODING:
3985 return TILE_BRAND_EXPLOSION;
3986 #if TAG_MAJOR_VERSION == 34
3987 case SPMSL_CONFUSION:
3988 return TILE_BRAND_CONFUSION;
3989 case SPMSL_PARALYSIS:
3990 return TILE_BRAND_PARALYSIS;
3991 case SPMSL_SLOW:
3992 return TILE_BRAND_SLOWING;
3993 case SPMSL_SICKNESS:
3994 return TILE_BRAND_SICKNESS;
3995 case SPMSL_SLEEP:
3996 return TILE_BRAND_SLEEP;
3997 #endif
3998 case SPMSL_FRENZY:
3999 return TILE_BRAND_FRENZY;
4000 case SPMSL_BLINDING:
4001 return TILE_BRAND_BLINDING;
4002 default:
4003 break;
4004 }
4005 }
4006 #if TAG_MAJOR_VERSION == 34
4007 else if (item.base_type == OBJ_RODS)
4008 {
4009 // Technically not a brand, but still handled here
4010 return TILE_ROD_ID_FIRST + item.sub_type;
4011 }
4012 #endif
4013 return 0;
4014 }
4015
tileidx_corpse_brand(const item_def & item)4016 tileidx_t tileidx_corpse_brand(const item_def &item)
4017 {
4018 if (item.base_type != OBJ_CORPSES || item.sub_type != CORPSE_BODY)
4019 return 0;
4020
4021 return 0;
4022 }
4023
tileidx_unseen_flag(const coord_def & gc)4024 tileidx_t tileidx_unseen_flag(const coord_def &gc)
4025 {
4026 if (!map_bounds(gc))
4027 return TILE_FLAG_UNSEEN;
4028 else if (env.map_knowledge(gc).known()
4029 && !env.map_knowledge(gc).seen()
4030 || env.map_knowledge(gc).detected_item()
4031 || env.map_knowledge(gc).detected_monster()
4032 )
4033 {
4034 return TILE_FLAG_MM_UNSEEN;
4035 }
4036 else
4037 return TILE_FLAG_UNSEEN;
4038 }
4039
enchant_to_int(const item_def & item)4040 int enchant_to_int(const item_def &item)
4041 {
4042 if (is_random_artefact(item))
4043 return 4;
4044
4045 switch (item.flags & ISFLAG_COSMETIC_MASK)
4046 {
4047 default:
4048 return 0;
4049 case ISFLAG_EMBROIDERED_SHINY:
4050 return 1;
4051 case ISFLAG_RUNED:
4052 return 2;
4053 case ISFLAG_GLOWING:
4054 return 3;
4055 }
4056 }
4057
tileidx_enchant_equ(const item_def & item,tileidx_t tile,bool player)4058 tileidx_t tileidx_enchant_equ(const item_def &item, tileidx_t tile, bool player)
4059 {
4060 static const int etable[5][5] =
4061 {
4062 {0, 0, 0, 0, 0}, // all variants look the same
4063 {0, 1, 1, 1, 1}, // normal, ego/randart
4064 {0, 1, 1, 1, 2}, // normal, ego, randart
4065 {0, 1, 1, 2, 3}, // normal, ego (shiny/runed), ego (glowing), randart
4066 {0, 1, 2, 3, 4} // normal, shiny, runed, glowing, randart
4067 };
4068
4069 const int etype = enchant_to_int(item);
4070
4071 // XXX: only helmets, robes and boots have variants, but it would be nice
4072 // if this weren't hardcoded.
4073 if (tile == TILE_THELM_HELM)
4074 {
4075 switch (etype)
4076 {
4077 case 1:
4078 case 2:
4079 case 3:
4080 tile = _modrng(item.rnd, TILE_THELM_EGO_FIRST, TILE_THELM_EGO_LAST);
4081 break;
4082 case 4:
4083 tile = _modrng(item.rnd, TILE_THELM_ART_FIRST, TILE_THELM_ART_LAST);
4084 break;
4085 default:
4086 tile = _modrng(item.rnd, TILE_THELM_FIRST, TILE_THELM_LAST);
4087 }
4088 return tile;
4089 }
4090
4091 if (tile == TILE_ARM_ROBE)
4092 {
4093 switch (etype)
4094 {
4095 case 1:
4096 case 2:
4097 case 3:
4098 tile = _modrng(item.rnd, TILE_ARM_ROBE_EGO_FIRST, TILE_ARM_ROBE_EGO_LAST);
4099 break;
4100 case 4:
4101 tile = _modrng(item.rnd, TILE_ARM_ROBE_ART_FIRST, TILE_ARM_ROBE_ART_LAST);
4102 break;
4103 default:
4104 tile = _modrng(item.rnd, TILE_ARM_ROBE_FIRST, TILE_ARM_ROBE_LAST);
4105 }
4106 return tile;
4107 }
4108
4109 if (tile == TILE_ARM_BOOTS)
4110 {
4111 switch (etype)
4112 {
4113 case 1:
4114 case 2:
4115 case 3:
4116 tile = _modrng(item.rnd, TILE_ARM_BOOTS_EGO_FIRST, TILE_ARM_BOOTS_EGO_LAST);
4117 break;
4118 case 4:
4119 tile = _modrng(item.rnd, TILE_ARM_BOOTS_ART_FIRST, TILE_ARM_BOOTS_ART_LAST);
4120 break;
4121 default:
4122 tile = _modrng(item.rnd, TILE_ARM_BOOTS_FIRST, TILE_ARM_BOOTS_LAST);
4123 }
4124 return tile;
4125 }
4126
4127 int idx;
4128 if (player)
4129 idx = tile_player_count(tile) - 1;
4130 else
4131 idx = tile_main_count(tile) - 1;
4132 ASSERT(idx < 5);
4133
4134 tile += etable[idx][etype];
4135
4136 return tile;
4137 }
4138
4139 #ifdef USE_TILE
tile_debug_string(tileidx_t fg,tileidx_t bg,char prefix)4140 string tile_debug_string(tileidx_t fg, tileidx_t bg, char prefix)
4141 {
4142 tileidx_t fg_idx = fg & TILE_FLAG_MASK;
4143 tileidx_t bg_idx = bg & TILE_FLAG_MASK;
4144
4145 string fg_name;
4146 if (fg_idx < TILE_FLOOR_MAX)
4147 fg_name = tile_floor_name(fg_idx);
4148 else if (fg_idx < TILE_WALL_MAX)
4149 fg_name = tile_wall_name(fg_idx);
4150 else if (fg_idx < TILE_FEAT_MAX)
4151 fg_name = tile_feat_name(fg_idx);
4152 else if (fg_idx < TILE_DNGN_MAX)
4153 fg_name = tile_dngn_name(fg_idx);
4154 else if (fg_idx < TILE_MAIN_MAX)
4155 fg_name = tile_main_name(fg_idx);
4156 else if (fg_idx < TILEP_MCACHE_START)
4157 fg_name = (tile_player_name(fg_idx));
4158 else
4159 {
4160 fg_name = "mc:";
4161 mcache_entry *entry = mcache.get(fg_idx);
4162 if (entry)
4163 {
4164 tile_draw_info dinfo[mcache_entry::MAX_INFO_COUNT];
4165 unsigned int count = entry->info(&dinfo[0]);
4166 for (unsigned int i = 0; i < count; ++i)
4167 {
4168 tileidx_t mc_idx = dinfo[i].idx;
4169 if (mc_idx < TILE_MAIN_MAX)
4170 fg_name += tile_main_name(mc_idx);
4171 else if (mc_idx < TILEP_PLAYER_MAX)
4172 fg_name += tile_player_name(mc_idx);
4173 else
4174 fg_name += "[invalid index]";
4175
4176 if (i < count - 1)
4177 fg_name += ", ";
4178 }
4179 }
4180 else
4181 fg_name += "[not found]";
4182 }
4183
4184 string tile_string = make_stringf(
4185 "%cFG: %4" PRIu64" | 0x%8" PRIx64" (%s)\n"
4186 "%cBG: %4" PRIu64" | 0x%8" PRIx64" (%s)\n",
4187 prefix,
4188 fg_idx,
4189 fg & ~TILE_FLAG_MASK,
4190 fg_name.c_str(),
4191 prefix,
4192 bg_idx,
4193 bg & ~TILE_FLAG_MASK,
4194 tile_dngn_name(bg_idx));
4195
4196 return tile_string;
4197 }
4198 #endif
4199
bind_item_tile(item_def & item)4200 void bind_item_tile(item_def &item)
4201 {
4202 if (item.props.exists("item_tile_name"))
4203 {
4204 string tile = item.props["item_tile_name"].get_string();
4205 dprf("Binding non-worn item tile: \"%s\".", tile.c_str());
4206 tileidx_t index;
4207 if (!tile_main_index(tile.c_str(), &index))
4208 {
4209 // If invalid tile name, complain and discard the props.
4210 dprf("bad tile name: \"%s\".", tile.c_str());
4211 item.props.erase("item_tile_name");
4212 item.props.erase("item_tile");
4213 }
4214 else
4215 item.props["item_tile"] = short(index);
4216 }
4217
4218 if (item.props.exists("worn_tile_name"))
4219 {
4220 string tile = item.props["worn_tile_name"].get_string();
4221 dprf("Binding worn item tile: \"%s\".", tile.c_str());
4222 tileidx_t index;
4223 if (!tile_player_index(tile.c_str(), &index))
4224 {
4225 // If invalid tile name, complain and discard the props.
4226 dprf("bad tile name: \"%s\".", tile.c_str());
4227 item.props.erase("worn_tile_name");
4228 item.props.erase("worn_tile");
4229 }
4230 else
4231 item.props["worn_tile"] = short(index);
4232 }
4233 }
4234
tile_init_props(monster * mon)4235 void tile_init_props(monster* mon)
4236 {
4237 // Only monsters using mon_mod or mon_cycle need a tile_num.
4238 switch (mon->type)
4239 {
4240 case MONS_TOADSTOOL:
4241 case MONS_FUNGUS:
4242 case MONS_PLANT:
4243 case MONS_BUSH:
4244 case MONS_FIRE_VORTEX:
4245 case MONS_TWISTER:
4246 case MONS_SPATIAL_VORTEX:
4247 case MONS_SPATIAL_MAELSTROM:
4248 case MONS_ABOMINATION_SMALL:
4249 case MONS_ABOMINATION_LARGE:
4250 case MONS_BLOCK_OF_ICE:
4251 case MONS_BUTTERFLY:
4252 case MONS_HUMAN:
4253 case MONS_DEEP_ELF_ELEMENTALIST:
4254 break;
4255 default:
4256 return;
4257 }
4258
4259 // Already overridden or set.
4260 if (mon->props.exists("monster_tile") || mon->props.exists(TILE_NUM_KEY))
4261 return;
4262
4263 mon->props[TILE_NUM_KEY] = short(random2(256));
4264 }
4265