14 #include "mon-stuff.h"
21 #include "tiledef-dngn.h"
22 #include "tilemcache.h"
28 void tile_new_level(bool first_time
, bool init_unseen
)
30 tiles
.clear_minimap();
32 for (unsigned int x
= 0; x
< GXM
; x
++)
33 for (unsigned int y
= 0; y
< GYM
; y
++)
34 tiles
.update_minimap(coord_def(x
, y
));
39 if (!player_in_mappable_area() || init_unseen
)
41 for (unsigned int x
= 0; x
< GXM
; x
++)
42 for (unsigned int y
= 0; y
< GYM
; y
++)
44 env
.tile_bk_fg
[x
][y
] = 0;
45 env
.tile_bk_bg
[x
][y
] = TILE_DNGN_UNSEEN
;
49 // Fix up stair markers. The travel information isn't hooked up
50 // until after we change levels. So, look through all of the stairs
51 // on this level and check if they still need the stair flag.
52 for (unsigned int x
= 0; x
< GXM
; x
++)
53 for (unsigned int y
= 0; y
< GYM
; y
++)
55 unsigned int tile
= env
.tile_bk_bg
[x
][y
];
56 if (!(tile
& TILE_FLAG_NEW_STAIR
))
58 if (!is_unknown_stair(coord_def(x
,y
)))
59 env
.tile_bk_bg
[x
][y
] &= ~TILE_FLAG_NEW_STAIR
;
63 void tile_init_default_flavour()
65 tile_default_flv(you
.level_type
, you
.where_are_you
, env
.tile_default
);
68 void tile_default_flv(level_area_type lev
, branch_type br
, tile_flavour
&flv
)
70 flv
.wall
= TILE_WALL_NORMAL
;
71 flv
.floor
= TILE_FLOOR_NORMAL
;
74 if (lev
== LEVEL_PANDEMONIUM
)
76 flv
.floor
= TILE_FLOOR_TOMB
;
80 case 0: flv
.wall
= TILE_WALL_ZOT_BLUE
; break;
81 case 1: flv
.wall
= TILE_WALL_ZOT_RED
; break;
82 case 2: flv
.wall
= TILE_WALL_ZOT_MAGENTA
; break;
83 case 3: flv
.wall
= TILE_WALL_ZOT_GREEN
; break;
84 case 4: flv
.wall
= TILE_WALL_ZOT_CYAN
; break;
85 case 5: flv
.wall
= TILE_WALL_ZOT_YELLOW
; break;
86 case 6: flv
.wall
= TILE_WALL_ZOT_WHITE
; break;
90 flv
.wall
= TILE_WALL_FLESH
;
92 flv
.floor
= TILE_FLOOR_NERVES
;
96 else if (lev
== LEVEL_ABYSS
)
98 flv
.floor
= TILE_FLOOR_NERVES
;
102 case 0: flv
.wall
= TILE_WALL_HIVE
; break;
103 case 1: flv
.wall
= TILE_WALL_PEBBLE_RED
; break;
104 case 2: flv
.wall
= TILE_WALL_SLIME
; break;
105 case 3: flv
.wall
= TILE_WALL_ICE
; break;
106 case 4: flv
.wall
= TILE_WALL_HALL
; break;
107 case 5: flv
.wall
= TILE_WALL_UNDEAD
; break;
111 else if (lev
== LEVEL_LABYRINTH
)
113 flv
.wall
= TILE_WALL_UNDEAD
;
114 flv
.floor
= TILE_FLOOR_TOMB
;
117 else if (lev
== LEVEL_PORTAL_VAULT
)
119 // These should be handled in the respective lua files.
120 flv
.wall
= TILE_WALL_NORMAL
;
121 flv
.floor
= TILE_FLOOR_NORMAL
;
127 case BRANCH_MAIN_DUNGEON
:
128 flv
.wall
= TILE_WALL_NORMAL
;
129 flv
.floor
= TILE_FLOOR_NORMAL
;
133 flv
.wall
= TILE_WALL_HIVE
;
134 flv
.floor
= TILE_FLOOR_HIVE
;
138 flv
.wall
= TILE_WALL_VAULT
;
139 flv
.floor
= TILE_FLOOR_VAULT
;
142 case BRANCH_ECUMENICAL_TEMPLE
:
143 flv
.wall
= TILE_WALL_VINES
;
144 flv
.floor
= TILE_FLOOR_VINES
;
147 case BRANCH_DWARVEN_HALL
:
148 case BRANCH_ELVEN_HALLS
:
149 case BRANCH_HALL_OF_BLADES
:
150 flv
.wall
= TILE_WALL_HALL
;
151 flv
.floor
= TILE_FLOOR_HALL
;
154 case BRANCH_TARTARUS
:
156 case BRANCH_VESTIBULE_OF_HELL
:
157 flv
.wall
= TILE_WALL_UNDEAD
;
158 flv
.floor
= TILE_FLOOR_TOMB
;
162 flv
.wall
= TILE_WALL_TOMB
;
163 flv
.floor
= TILE_FLOOR_TOMB
;
167 flv
.wall
= TILE_WALL_ZOT_CYAN
;
168 flv
.floor
= TILE_FLOOR_TOMB
;
172 flv
.wall
= TILE_WALL_ZOT_RED
;
173 flv
.floor
= TILE_FLOOR_ROUGH_RED
;
177 flv
.wall
= TILE_WALL_ICE
;
178 flv
.floor
= TILE_FLOOR_ICE
;
181 case BRANCH_ORCISH_MINES
:
182 flv
.wall
= TILE_WALL_ORC
;
183 flv
.floor
= TILE_FLOOR_ORC
;
188 case BRANCH_SPIDER_NEST
:
189 flv
.wall
= TILE_WALL_LAIR
;
190 flv
.floor
= TILE_FLOOR_LAIR
;
193 case BRANCH_SLIME_PITS
:
194 flv
.wall
= TILE_WALL_SLIME
;
195 flv
.floor
= TILE_FLOOR_SLIME
;
198 case BRANCH_SNAKE_PIT
:
199 flv
.wall
= TILE_WALL_SNAKE
;
200 flv
.floor
= TILE_FLOOR_SNAKE
;
204 flv
.wall
= TILE_WALL_SWAMP
;
205 flv
.floor
= TILE_FLOOR_SWAMP
;
209 flv
.wall
= TILE_WALL_YELLOW_ROCK
;
210 flv
.floor
= TILE_FLOOR_SAND_STONE
;
213 case BRANCH_HALL_OF_ZOT
:
214 flv
.wall
= TILE_WALL_ZOT_YELLOW
;
215 flv
.floor
= TILE_FLOOR_TOMB
;
223 void tile_clear_flavour()
225 for (rectangle_iterator
ri(0); ri
; ++ri
)
227 env
.tile_flv(*ri
).floor
= 0;
228 env
.tile_flv(*ri
).wall
= 0;
229 env
.tile_flv(*ri
).feat
= 0;
230 env
.tile_flv(*ri
).special
= 0;
234 // For floors and walls that have not already been set to a particular tile,
235 // set them to a random instance of the default floor and wall tileset.
236 void tile_init_flavour()
238 for (rectangle_iterator
ri(0); ri
; ++ri
)
239 tile_init_flavour(*ri
);
242 static tileidx_t
_pick_random_dngn_tile(tileidx_t idx
, int value
= -1)
244 ASSERT(idx
>= 0 && idx
< TILE_DNGN_MAX
);
245 const int count
= tile_dngn_count(idx
);
249 const int total
= tile_dngn_probs(idx
+ count
- 1);
250 const int rand
= (value
== -1 ? random2(total
) : value
% total
);
252 for (int i
= 0; i
< count
; ++i
)
254 tileidx_t curr
= idx
+ i
;
255 if (rand
< tile_dngn_probs(curr
))
262 void tile_init_flavour(const coord_def
&gc
)
267 if (!env
.tile_flv(gc
).floor
)
269 tileidx_t floor_base
= env
.tile_default
.floor
;
270 int colour
= env
.grid_colours(gc
);
272 floor_base
= tile_dngn_coloured(floor_base
, colour
);
273 env
.tile_flv(gc
).floor
= _pick_random_dngn_tile(floor_base
);
276 if (!env
.tile_flv(gc
).wall
)
278 tileidx_t wall_base
= env
.tile_default
.wall
;
279 int colour
= env
.grid_colours(gc
);
281 wall_base
= tile_dngn_coloured(wall_base
, colour
);
282 env
.tile_flv(gc
).wall
= _pick_random_dngn_tile(wall_base
);
285 if (feat_is_door(grd(gc
)))
287 // Check for horizontal gates.
289 const coord_def
left(gc
.x
- 1, gc
.y
);
290 const coord_def
right(gc
.x
+ 1, gc
.y
);
292 bool door_left
= (grd(left
) == grd(gc
));
293 bool door_right
= (grd(right
) == grd(gc
));
295 if (door_left
|| door_right
)
298 if (door_left
&& door_right
)
299 target
= TILE_DNGN_GATE_CLOSED_MIDDLE
;
301 target
= TILE_DNGN_GATE_CLOSED_RIGHT
;
303 target
= TILE_DNGN_GATE_CLOSED_LEFT
;
305 // NOTE: This requires that closed gates and open gates
306 // are positioned in the tile set relative to their
308 env
.tile_flv(gc
).special
= target
- TILE_DNGN_CLOSED_DOOR
;
311 env
.tile_flv(gc
).special
= 0;
313 else if (feat_is_secret_door(grd(gc
)))
314 env
.tile_flv(gc
).special
= 0;
315 else if (!env
.tile_flv(gc
).special
)
316 env
.tile_flv(gc
).special
= random2(256);
332 static int _jitter(SpecialIdx i
)
334 return (i
+ random_range(-1, 1) + 8) % 8;
337 static bool _adjacent_target(dungeon_feature_type target
, int x
, int y
)
339 for (adjacent_iterator
ai(coord_def(x
, y
), false); ai
; ++ai
)
341 if (!map_bounds(*ai
))
343 if (grd(*ai
) == target
)
350 void tile_floor_halo(dungeon_feature_type target
, tileidx_t tile
)
352 for (int x
= 0; x
< GXM
; x
++)
354 for (int y
= 0; y
< GYM
; y
++)
356 if (grd
[x
][y
] < DNGN_FLOOR_MIN
)
358 if (!_adjacent_target(target
, x
, y
))
361 bool l_flr
= (x
> 0 && grd
[x
-1][y
] >= DNGN_FLOOR_MIN
);
362 bool r_flr
= (x
< GXM
- 1 && grd
[x
+1][y
] >= DNGN_FLOOR_MIN
);
363 bool u_flr
= (y
> 0 && grd
[x
][y
-1] >= DNGN_FLOOR_MIN
);
364 bool d_flr
= (y
< GYM
- 1 && grd
[x
][y
+1] >= DNGN_FLOOR_MIN
);
366 bool l_target
= _adjacent_target(target
, x
-1, y
);
367 bool r_target
= _adjacent_target(target
, x
+1, y
);
368 bool u_target
= _adjacent_target(target
, x
, y
-1);
369 bool d_target
= _adjacent_target(target
, x
, y
+1);
371 // The special tiles contains part floor and part special, so
372 // if there are adjacent floor or special tiles, we should
373 // do our best to "connect" them appropriately. If there are
374 // are other tiles there (walls, doors, whatever...) then it
376 bool l_nrm
= (l_flr
&& !l_target
);
377 bool r_nrm
= (r_flr
&& !r_target
);
378 bool u_nrm
= (u_flr
&& !u_target
);
379 bool d_nrm
= (d_flr
&& !d_target
);
381 bool l_spc
= (l_flr
&& l_target
);
382 bool r_spc
= (r_flr
&& r_target
);
383 bool u_spc
= (u_flr
&& u_target
);
384 bool d_spc
= (d_flr
&& d_target
);
386 if (l_nrm
&& r_nrm
|| u_nrm
&& d_nrm
)
388 // Not much to do here...
389 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_FULL
;
394 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NW
;
396 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SW
;
397 else if (u_spc
&& d_spc
)
398 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_W
;
399 else if (u_spc
&& r_spc
)
400 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SW
;
401 else if (d_spc
&& r_spc
)
402 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NW
;
405 env
.tile_flv
[x
][y
].floor
= tile
+ (coinflip() ?
406 SPECIAL_W
: SPECIAL_SW
);
410 env
.tile_flv
[x
][y
].floor
= tile
+ (coinflip() ?
411 SPECIAL_W
: SPECIAL_NW
);
414 env
.tile_flv
[x
][y
].floor
= tile
+ _jitter(SPECIAL_W
);
419 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NE
;
421 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SE
;
422 else if (u_spc
&& d_spc
)
423 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_E
;
424 else if (u_spc
&& l_spc
)
425 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SE
;
426 else if (d_spc
&& l_spc
)
427 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NE
;
429 env
.tile_flv
[x
][y
].floor
= tile
+ (coinflip() ?
430 SPECIAL_E
: SPECIAL_SE
);
432 env
.tile_flv
[x
][y
].floor
= tile
+ (coinflip() ?
433 SPECIAL_E
: SPECIAL_NE
);
435 env
.tile_flv
[x
][y
].floor
= tile
+ _jitter(SPECIAL_E
);
440 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_N
;
441 else if (r_spc
&& d_spc
)
442 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NW
;
443 else if (l_spc
&& d_spc
)
444 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NE
;
447 env
.tile_flv
[x
][y
].floor
= tile
+ (coinflip() ?
448 SPECIAL_N
: SPECIAL_NW
);
452 env
.tile_flv
[x
][y
].floor
= tile
+ (coinflip() ?
453 SPECIAL_N
: SPECIAL_NE
);
456 env
.tile_flv
[x
][y
].floor
= tile
+ _jitter(SPECIAL_N
);
461 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_S
;
462 else if (r_spc
&& u_spc
)
463 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SW
;
464 else if (l_spc
&& u_spc
)
465 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SE
;
468 env
.tile_flv
[x
][y
].floor
= tile
+ (coinflip() ?
469 SPECIAL_S
: SPECIAL_SW
);
473 env
.tile_flv
[x
][y
].floor
= tile
+ (coinflip() ?
474 SPECIAL_S
: SPECIAL_SE
);
477 env
.tile_flv
[x
][y
].floor
= tile
+ _jitter(SPECIAL_S
);
479 else if (u_spc
&& d_spc
)
481 // We know this value is already initialised and
482 // is necessarily in bounds.
483 tileidx_t t
= env
.tile_flv
[x
][y
-1].floor
- tile
;
484 if (t
== SPECIAL_NE
|| t
== SPECIAL_E
)
485 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_E
;
486 else if (t
== SPECIAL_NW
|| t
== SPECIAL_W
)
487 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_W
;
489 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_FULL
;
491 else if (r_spc
&& l_spc
)
493 // We know this value is already initialised and
494 // is necessarily in bounds.
495 tileidx_t t
= env
.tile_flv
[x
-1][y
].floor
- tile
;
496 if (t
== SPECIAL_NW
|| t
== SPECIAL_N
)
497 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_N
;
498 else if (t
== SPECIAL_SW
|| t
== SPECIAL_S
)
499 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_S
;
501 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_FULL
;
503 else if (u_spc
&& l_spc
)
505 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SE
;
507 else if (u_spc
&& r_spc
)
509 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SW
;
511 else if (d_spc
&& l_spc
)
513 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NE
;
515 else if (d_spc
&& r_spc
)
517 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NW
;
521 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_FULL
;
526 // Second pass for clean up. The only bad part about the above
527 // algorithm is that it could turn a block of floor like this:
533 // (KEY: N = normal floor, # = special floor)
535 // Into these flavours:
538 // 3-6, not important
540 // Generally the tiles don't fit with a north to the right or left
541 // of a south tile. What we really want to do is to separate the
542 // two regions, by making 1 a SPECIAL_SE and 2 a SPECIAL_NW tile.
543 for (int y
= 0; y
< GYM
- 1; ++y
)
544 for (int x
= 0; x
< GXM
- 1; ++x
)
546 int this_spc
= env
.tile_flv
[x
][y
].floor
- tile
;
547 if (this_spc
< 0 || this_spc
> 8)
550 if (this_spc
!= SPECIAL_N
&& this_spc
!= SPECIAL_S
551 && this_spc
!= SPECIAL_E
&& this_spc
!= SPECIAL_W
)
556 int right_spc
= x
< GXM
- 1 ? env
.tile_flv
[x
+1][y
].floor
- tile
558 int down_spc
= y
< GYM
- 1 ? env
.tile_flv
[x
][y
+1].floor
- tile
561 if (this_spc
== SPECIAL_N
&& right_spc
== SPECIAL_S
)
563 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NE
;
564 env
.tile_flv
[x
+1][y
].floor
= tile
+ SPECIAL_SW
;
566 else if (this_spc
== SPECIAL_S
&& right_spc
== SPECIAL_N
)
568 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SE
;
569 env
.tile_flv
[x
+1][y
].floor
= tile
+ SPECIAL_NW
;
571 else if (this_spc
== SPECIAL_E
&& down_spc
== SPECIAL_W
)
573 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_SE
;
574 env
.tile_flv
[x
][y
+1].floor
= tile
+ SPECIAL_NW
;
576 else if (this_spc
== SPECIAL_W
&& down_spc
== SPECIAL_E
)
578 env
.tile_flv
[x
][y
].floor
= tile
+ SPECIAL_NE
;
579 env
.tile_flv
[x
][y
+1].floor
= tile
+ SPECIAL_SW
;
584 void tile_draw_floor()
586 for (int cy
= 0; cy
< env
.tile_fg
.height(); cy
++)
587 for (int cx
= 0; cx
< env
.tile_fg
.width(); cx
++)
589 const coord_def
ep(cx
, cy
);
590 const coord_def gc
= show2grid(ep
);
592 tileidx_t bg
= TILE_DNGN_UNSEEN
| tileidx_unseen_flag(gc
);
594 if (you
.see_cell(gc
))
596 bg
= tileidx_feature(gc
);
598 dungeon_feature_type feat
= grid_appearance(gc
);
599 if (feat
== DNGN_DETECTED_SECRET_DOOR
)
600 bg
|= TILE_FLAG_WAS_SECRET
;
601 else if (is_unknown_stair(gc
))
602 bg
|= TILE_FLAG_NEW_STAIR
;
607 env
.tile_bg(ep
) = bg
;
612 // Called from item() in view.cc
613 void tile_place_item(const coord_def
&gc
, const item_def
&item
)
618 tileidx_t t
= tileidx_item(item
);
619 if (item
.link
!= NON_ITEM
)
620 t
|= TILE_FLAG_S_UNDER
;
624 if (item_needs_autopickup(item
))
625 env
.tile_bg(gc
) |= TILE_FLAG_CURSOR3
;
628 // Called from item() in view.cc
629 void tile_place_item_marker(const coord_def
&gc
, const item_def
&item
)
631 env
.tile_fg(gc
) |= TILE_FLAG_S_UNDER
;
633 if (item_needs_autopickup(item
))
634 env
.tile_bg(gc
) |= TILE_FLAG_CURSOR3
;
637 // Called from show_def::_update_monster() in show.cc
638 void tile_place_monster(const coord_def
&gc
, const monster
* mon
)
643 const coord_def ep
= grid2show(gc
);
645 tileidx_t t
= tileidx_monster(mon
);
646 tileidx_t t0
= t
& TILE_FLAG_MASK
;
647 tileidx_t flag
= t
& (~TILE_FLAG_MASK
);
649 if (mons_is_item_mimic(mon
->type
))
651 if (mons_is_unknown_mimic(mon
))
653 // If necessary add item brand.
654 if (you
.visible_igrd(gc
) != NON_ITEM
)
655 t
|= TILE_FLAG_S_UNDER
;
657 if (item_needs_autopickup(get_mimic_item(mon
)))
658 env
.tile_bg(ep
) |= TILE_FLAG_CURSOR3
;
661 else if (mons_is_stationary(mon
) && mon
->type
!= MONS_TRAINING_DUMMY
)
663 // If necessary add item brand.
664 if (you
.visible_igrd(gc
) != NON_ITEM
)
665 t
|= TILE_FLAG_S_UNDER
;
669 tileidx_t mcache_idx
= mcache
.register_monster(mon
);
670 t
= flag
| (mcache_idx
? mcache_idx
: t0
);
676 if (!mon
->visible_to(&you
)
677 || mons_is_lurking(mon
)
678 || mons_is_unknown_mimic(mon
)
679 || mons_class_flag(mon
->type
, M_NO_EXP_GAIN
))
684 const tag_pref pref
= Options
.tile_tag_pref
;
685 if (pref
== TAGPREF_NONE
)
687 else if (pref
== TAGPREF_TUTORIAL
)
689 const int kills
= you
.kills
->num_kills(mon
);
692 if (!mon
->is_named() && kills
> limit
)
695 else if (!mon
->is_named())
698 if (pref
!= TAGPREF_NAMED
&& mon
->friendly())
701 // HACK. Large-tile monsters don't interact well with name tags.
702 if (mon
->type
== MONS_PANDEMONIUM_DEMON
703 || mon
->type
== MONS_LERNAEAN_HYDRA
)
707 tiles
.add_text_tag(TAG_NAMED_MONSTER
, mon
);
710 void tile_place_cloud(const coord_def
&gc
, const cloud_struct
&cl
)
712 const coord_def ep
= grid2show(gc
);
713 if (env
.tile_fg(ep
) != 0)
716 const monster
* mon
= monster_at(gc
);
717 bool disturbance
= false;
719 if (mon
&& !mon
->visible_to(&you
) && you
.see_cell(gc
)
720 && is_opaque_cloud(env
.cgrid(gc
))
721 && !mon
->is_insubstantial())
726 // In the Shoals, ink is handled differently. (jpeg)
727 // I'm not sure it is even possible anywhere else, but just to be safe...
728 if (cl
.type
!= CLOUD_INK
|| !player_in_branch(BRANCH_SHOALS
))
729 env
.tile_fg(ep
) = tileidx_cloud(cl
, disturbance
);
732 unsigned int num_tile_rays
= 0;
738 FixedVector
<tile_ray
, 30> tile_ray_vec
;
740 void tile_place_ray(const coord_def
&gc
, bool in_range
)
742 // Record rays for later. The curses version just applies
743 // rays directly to the screen. The tiles version doesn't have
744 // (nor want) such direct access. So, it batches up all of the
745 // rays and applies them in viewwindow(...).
746 if (num_tile_rays
< tile_ray_vec
.size() - 1)
748 tile_ray_vec
[num_tile_rays
].in_range
= in_range
;
749 tile_ray_vec
[num_tile_rays
++].ep
= grid2show(gc
);
753 void tile_draw_rays(bool reset_count
)
755 for (unsigned int i
= 0; i
< num_tile_rays
; i
++)
757 tileidx_t flag
= tile_ray_vec
[i
].in_range
? TILE_FLAG_RAY
759 env
.tile_bg(tile_ray_vec
[i
].ep
) |= flag
;
766 void tile_wizmap_terrain(const coord_def
&gc
)
768 env
.tile_bk_bg(gc
) = tileidx_feature(gc
);
771 // Updates the "flavour" of tiles that are animated.
772 // Unfortunately, these are all hard-coded for now.
773 void tile_apply_animations(tileidx_t bg
, tile_flavour
*flv
)
775 tileidx_t bg_idx
= bg
& TILE_FLAG_MASK
;
776 if (bg_idx
>= TILE_DNGN_LAVA
&& bg_idx
< TILE_BLOOD
)
778 flv
->special
= random2(256);
780 else if (bg_idx
== TILE_DNGN_PORTAL_WIZARD_LAB
781 || bg_idx
== TILE_DNGN_ALTAR_CHEIBRIADOS
)
783 flv
->special
= (flv
->special
+ 1) % tile_dngn_count(bg_idx
);
785 else if (bg_idx
== TILE_WALL_NORMAL
786 && flv
->wall
>= TILE_WALL_BRICK_TORCH_START
787 && flv
->wall
<= TILE_WALL_BRICK_TORCH_END
)
790 if (flv
->wall
> TILE_WALL_BRICK_TORCH_END
)
791 flv
->wall
= TILE_WALL_BRICK_TORCH_START
;
795 static bool _suppress_blood(const coord_def pos
)
797 if (!you
.see_cell(pos
))
800 const dungeon_feature_type feat
= grd(pos
);
801 if (feat
== DNGN_TREE
|| feat
== DNGN_SWAMP_TREE
)
804 if (feat
>= DNGN_FOUNTAIN_BLUE
&& feat
<= DNGN_PERMADRY_FOUNTAIN
)
807 if (feat_is_altar(feat
))
810 if (feat_stair_direction(feat
) != CMD_NO_CMD
)
813 if (feat
== DNGN_TEMP_PORTAL
)
816 const trap_def
*trap
= find_trap(pos
);
817 if (trap
&& trap
->type
== TRAP_SHAFT
&& trap
->is_known())
823 static bool _suppress_blood(tileidx_t bg_idx
)
825 return (bg_idx
>= TILE_WALL_BRICK_TORCH_START
826 && bg_idx
<= TILE_WALL_BRICK_TORCH_END
);
829 // Specifically for vault-overwritten doors. We have three "sets" of tiles that
830 // can be dealt with. The tile sets should be 2, 3, 8 and 9 respectively. They
833 // 3. Detected, closed, open.
834 // 8. Closed, open, gate left closed, gate middle closed, gate right closed,
835 // gate left open, gate middle open, gate right open.
836 // 9. Detected, closed, open, gate left closed, gate middle closed, gate right
837 // closed, gate left open, gate middle open, gate right open.
838 static int _get_door_offset(tileidx_t base_tile
, bool opened
= false,
839 bool detected
= false, int gateway_type
= 0)
841 int count
= tile_dngn_count(base_tile
);
845 // The location of the default "closed" tile.
851 return ((opened
) ? 1: 0);
860 // But is BASE_TILE for others.
864 // It's located at BASE_TILE+1 for tile sets with detected doors
868 // Passed a non-door tile base, pig out now.
869 die("non-door tile");
872 // If we've reached this point, we're dealing with a gate.
873 // Don't believe gateways deal differently with detection.
877 if (!opened
&& !detected
&& gateway_type
== 0)
880 return offset
+ gateway_type
;
883 static inline void _apply_variations(const tile_flavour
&flv
, tileidx_t
*bg
,
886 tileidx_t orig
= (*bg
) & TILE_FLAG_MASK
;
887 tileidx_t flag
= (*bg
) & (~TILE_FLAG_MASK
);
889 // TODO enne - expose this as an option, so ziggurat can use it too.
890 // Alternatively, allow the stone type to be set.
892 // Hack: Swap rock/stone in crypt and tomb, because there are
894 if ((you
.where_are_you
== BRANCH_CRYPT
|| you
.where_are_you
== BRANCH_TOMB
)
895 && orig
== TILE_DNGN_STONE_WALL
)
897 orig
= TILE_WALL_NORMAL
;
900 if (orig
== TILE_FLOOR_NORMAL
)
902 else if (orig
== TILE_WALL_NORMAL
)
904 else if (orig
== TILE_DNGN_CLOSED_DOOR
|| orig
== TILE_DNGN_OPEN_DOOR
)
906 tileidx_t override
= flv
.feat
;
907 // Setting an override on a door specifically for undetected secret
908 // doors causes issues if there are a number of variants for that tile.
909 // In these instances, append "last_tile" and have the tile specifier
910 // for the door in question on its own line, and it should bypass any
911 // asserts or weird visual issues. Somewhat hackish. The following code
912 // assumes that if there is an override on a door location and that
913 // has no variations, that the override is not actually a door tile but
914 // the aforementioned secret door thing. {due}
915 if (override
&& tile_dngn_count(override
) > 1)
917 // XXX: This doesn't deal properly with detected doors.
918 bool opened
= (orig
== TILE_DNGN_OPEN_DOOR
);
919 int offset
= _get_door_offset(override
, opened
, false, flv
.special
);
920 *bg
= override
+ offset
;
923 *bg
= orig
+ std::min((int)flv
.special
, 3);
925 if (feature_mimic_at(gc
))
927 dungeon_feature_type feat
= get_mimic_feat(monster_at(gc
));
928 if (feat
== DNGN_CLOSED_DOOR
)
932 else if (orig
== TILE_DNGN_PORTAL_WIZARD_LAB
933 || orig
== TILE_DNGN_ALTAR_CHEIBRIADOS
)
935 *bg
= orig
+ flv
.special
% tile_dngn_count(orig
);
937 else if (orig
< TILE_DNGN_MAX
)
939 *bg
= _pick_random_dngn_tile(orig
, flv
.special
);
945 // If the top tile is a corpse, don't draw blood underneath.
946 static bool _top_item_is_corpse(const coord_def
&gc
)
951 const int item_idx
= igrd(gc
);
953 if (item_idx
== NON_ITEM
)
956 item_def
& item
= mitm
[item_idx
];
957 return (item
.base_type
== OBJ_CORPSES
958 && item
.sub_type
== CORPSE_BODY
);
961 void tile_apply_properties(const coord_def
&gc
, packed_cell
&cell
)
965 if (is_exclude_root(gc
))
966 cell
.bg
|= TILE_FLAG_EXCL_CTR
;
968 cell
.bg
|= TILE_FLAG_TRAV_EXCL
;
974 _apply_variations(env
.tile_flv(gc
), &cell
.bg
, gc
);
976 bool print_blood
= true;
979 monster
* mon
= monster_at(gc
);
980 if (you
.see_cell(gc
) && mon
)
982 if (!mons_class_flag(mon
->type
, M_NO_EXP_GAIN
)
983 && (!mons_is_mimic(mon
->type
)
984 || testbits(mon
->flags
, MF_KNOWN_MIMIC
)))
986 cell
.is_haloed
= true;
992 cell
.is_haloed
= false;
994 if (print_blood
&& (_suppress_blood(gc
)
995 || _suppress_blood((cell
.bg
) & TILE_FLAG_MASK
)))
1000 // Mold has the same restrictions as blood
1001 // but mold takes precendence over blood.
1005 cell
.is_moldy
= true;
1006 else if (is_bloodcovered(gc
) && !_top_item_is_corpse(gc
))
1007 cell
.is_bloody
= true;
1010 const dungeon_feature_type feat
= grd(gc
);
1011 if (feat_is_water(feat
) || feat
== DNGN_LAVA
)
1012 cell
.bg
|= TILE_FLAG_WATER
;
1014 if (is_sanctuary(gc
))
1015 cell
.is_sanctuary
= true;
1018 cell
.is_silenced
= true;
1020 if (grd(gc
) == DNGN_SWAMP_TREE
)
1021 cell
.swamp_tree_water
= true;
1024 void tile_clear_map(const coord_def
& gc
)
1026 env
.tile_bk_fg(gc
) = 0;
1027 tiles
.update_minimap(gc
);
1030 void tile_forget_map(const coord_def
&gc
)
1032 env
.tile_bk_fg(gc
) = 0;
1033 env
.tile_bk_bg(gc
) = 0;
1034 tiles
.update_minimap(gc
);