| 904 | }; |
| 905 | |
| 906 | void timeout_terrain_changes(int duration, bool force) |
| 907 | { |
| 908 | if (!duration && !force) |
| 909 | return; |
| 910 | |
| 911 | int num_seen[NUM_TERRAIN_CHANGE_TYPES] = {0}; |
| 912 | vector<terrain_change_reversion> revert; |
| 913 | |
| 914 | for (map_marker *mark : env.markers.get_all(MAT_TERRAIN_CHANGE)) |
| 915 | { |
| 916 | map_terrain_change_marker *marker = |
| 917 | dynamic_cast<map_terrain_change_marker*>(mark); |
| 918 | |
| 919 | if (marker->duration != INFINITE_DURATION) |
| 920 | marker->duration -= duration; |
| 921 | |
| 922 | if (marker->change_type == TERRAIN_CHANGE_DOOR_SEAL |
| 923 | && !feat_is_sealed(env.grid(marker->pos))) |
| 924 | { |
| 925 | // TODO: could this be done inside `revert_terrain_change`? The |
| 926 | // two things to test are corrupting sealed doors, and destroying |
| 927 | // sealed doors. See 7aedcd24e1be3ed58fef9542786c1a194e4c07d0 and |
| 928 | // 6c286a4f22bcba4cfcb36053eb066367874be752. |
| 929 | if (marker->duration <= 0) |
| 930 | env.markers.remove(marker); // deletes `marker` |
| 931 | continue; |
| 932 | } |
| 933 | |
| 934 | if ((marker->change_type == TERRAIN_CHANGE_BOG |
| 935 | || marker->change_type == TERRAIN_CHANGE_BINDING_SIGIL) |
| 936 | && !you.see_cell(marker->pos)) |
| 937 | { |
| 938 | marker->duration = 0; |
| 939 | } |
| 940 | |
| 941 | actor* src = actor_by_mid(marker->mon_num); |
| 942 | if (marker->duration <= 0 |
| 943 | || (marker->mon_num != 0 |
| 944 | && (!src || !src->alive() |
| 945 | || (src->is_monster() && src->as_monster()->pacified())))) |
| 946 | { |
| 947 | if (you.see_cell(marker->pos)) |
| 948 | num_seen[marker->change_type]++; |
| 949 | revert.push_back({marker->pos, marker->change_type, you.see_cell(marker->pos)}); |
| 950 | } |
| 951 | } |
| 952 | // finally, revert the changes and delete the markers |
| 953 | |
| 954 | // Sort terrain expiration from near to far, from the player's perspective |
| 955 | // (which results in more intuitive behavior when pushing the player out of walls). |
| 956 | sort(revert.begin(), revert.end(), [](const terrain_change_reversion& a, |
| 957 | const terrain_change_reversion& b) |
| 958 | { |
| 959 | return grid_distance(you.pos(), a.pos) < grid_distance(you.pos(), b.pos); |
| 960 | }); |
| 961 | |
| 962 | for (const auto &m_pos : revert) |
| 963 | { |
no test coverage detected