- /* 
- SDLPoP, a port/conversion of the DOS game Prince of Persia. 
- Copyright (C) 2013-2018  Dávid Nagy 
-   
- This program is free software: you can redistribute it and/or modify 
- it under the terms of the GNU General Public License as published by 
- the Free Software Foundation, either version 3 of the License, or 
- (at your option) any later version. 
-   
- This program is distributed in the hope that it will be useful, 
- but WITHOUT ANY WARRANTY; without even the implied warranty of 
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- GNU General Public License for more details. 
-   
- You should have received a copy of the GNU General Public License 
- along with this program.  If not, see <http://www.gnu.org/licenses/>. 
-   
- The authors of this program may be contacted at http://forum.princed.org 
- */ 
-   
- #include "common.h" 
-   
- // seg007:0000 
- void __pascal far process_trobs() { 
-         word need_delete; 
-         word index; 
-         word new_index; 
-         need_delete = 0; 
-         if (trobs_count == 0) return; 
-         for (index = 0; index < trobs_count; ++index) { 
-                 trob = trobs[index]; 
-                 animate_tile(); 
-                 trobs[index].type = trob.type; 
-                 if (trob.type < 0) { 
-                         need_delete = 1; 
-                 } 
-         } 
-         if (need_delete) { 
-                 for (index = new_index = 0; index < trobs_count; ++index) { 
-                         if (trobs[index].type >= 0) { 
-                                 trobs[new_index++] = trobs[index]; 
-                         } 
-                 } 
-                 trobs_count = new_index; 
-         } 
- } 
-   
- // seg007:00AF 
- void __pascal far animate_tile() { 
-         get_room_address(trob.room); 
-         switch (get_curr_tile(trob.tilepos)) { 
-                 case tiles_19_torch: 
-                 case tiles_30_torch_with_debris: 
-                         animate_torch(); 
-                 break; 
-                 case tiles_6_closer: 
-                 case tiles_15_opener: 
-                         animate_button(); 
-                 break; 
-                 case tiles_2_spike: 
-                         animate_spike(); 
-                 break; 
-                 case tiles_11_loose: 
-                         animate_loose(); 
-                 break; 
-                 case tiles_0_empty: 
-                         animate_empty(); 
-                 break; 
-                 case tiles_18_chomper: 
-                         animate_chomper(); 
-                 break; 
-                 case tiles_4_gate: 
-                         animate_door(); 
-                 break; 
-                 case tiles_16_level_door_left: 
-                         animate_leveldoor(); 
-                 break; 
-                 case tiles_10_potion: 
-                         animate_potion(); 
-                 break; 
-                 case tiles_22_sword: 
-                         animate_sword(); 
-                 break; 
-                 default: 
-                         trob.type = -1; 
-                 break; 
-         } 
-         curr_room_modif[trob.tilepos] = curr_modifier; 
- } 
-   
- // seg007:0166 
- short __pascal far is_trob_in_drawn_room() { 
-         if (trob.room != drawn_room) { 
-                 trob.type = -1; 
-                 return 0; 
-         } else { 
-                 return 1; 
-         } 
- } 
-   
- // seg007:017E 
- void __pascal far set_redraw_anim_right() { 
-         set_redraw_anim(get_trob_right_pos_in_drawn_room(), 1); 
- } 
-   
- // seg007:018C 
- void __pascal far set_redraw_anim_curr() { 
-         set_redraw_anim(get_trob_pos_in_drawn_room(), 1); 
- } 
-   
- // seg007:019A 
- void __pascal far redraw_at_trob() { 
-         word tilepos; 
-         redraw_height = 63; 
-         tilepos = get_trob_pos_in_drawn_room(); 
-         set_redraw_full(tilepos, 1); 
-         set_wipe(tilepos, 1); 
- } 
-   
- // seg007:01C5 
- void __pascal far redraw_21h() { 
-         redraw_height = 0x21; 
-         redraw_tile_height(); 
- } 
-   
- // seg007:01D0 
- void __pascal far redraw_11h() { 
-         redraw_height = 0x11; 
-         redraw_tile_height(); 
- } 
-   
- // seg007:01DB 
- void __pascal far redraw_20h() { 
-         redraw_height = 0x20; 
-         redraw_tile_height(); 
- } 
-   
- // seg007:01E6 
- void __pascal far draw_trob() { 
-         word var_2; 
-         var_2 = get_trob_right_pos_in_drawn_room(); 
-         set_redraw_anim(var_2, 1); 
-         set_redraw_fore(var_2, 1); 
-         set_redraw_anim(get_trob_right_above_pos_in_drawn_room(), 1); 
- } 
-   
- // seg007:0218 
- void __pascal far redraw_tile_height() { 
-         short tilepos; 
-         tilepos = get_trob_pos_in_drawn_room(); 
-         set_redraw_full(tilepos, 1); 
-         set_wipe(tilepos, 1); 
-         tilepos = get_trob_right_pos_in_drawn_room(); 
-         set_redraw_full(tilepos, 1); 
-         set_wipe(tilepos, 1); 
- } 
-   
- // seg007:0258 
- short __pascal far get_trob_pos_in_drawn_room() { 
-         short tilepos; 
-         tilepos = trob.tilepos; 
-         if (trob.room == room_A) { 
-                 if (tilepos >= 20 && tilepos < 30) { 
-                         // 20..29 -> -1..-10 
-                         tilepos = 19 - tilepos; 
-                 } else { 
-                         tilepos = 30; 
-                 } 
-         } else { 
-                 if (trob.room != drawn_room) { 
-                         tilepos = 30; 
-                 } 
-         } 
-         return tilepos; 
- } 
-   
- // seg007:029D 
- short __pascal far get_trob_right_pos_in_drawn_room() { 
-         word tilepos; 
-         tilepos = trob.tilepos; 
-         if (trob.room == drawn_room) { 
-                 if (tilepos % 10 != 9) { 
-                         ++tilepos; 
-                 } else { 
-                         tilepos = 30; 
-                 } 
-         } else if (trob.room == room_L) { 
-                 if (tilepos % 10 == 9) { 
-                         tilepos -= 9; 
-                 } else { 
-                         tilepos = 30; 
-                 } 
-         } else if (trob.room == room_A) { 
-                 if (tilepos >= 20 && tilepos < 29) { 
-                         // 20..28 -> -2..-10 
-                         tilepos = 18 - tilepos; 
-                 } else { 
-                         tilepos = 30; 
-                 } 
-         } else if (trob.room == room_AL && tilepos == 29) { 
-                 tilepos = -1; 
-         } else { 
-                 tilepos = 30; 
-         } 
-         return tilepos; 
- } 
-   
- // seg007:032C 
- short __pascal far get_trob_right_above_pos_in_drawn_room() { 
-         word tilepos; 
-         tilepos = trob.tilepos; 
-         if (trob.room == drawn_room) { 
-                 if (tilepos % 10 != 9) { 
-                         if (tilepos < 10) { 
-                                 // 0..8 -> -2..-10 
-                                 tilepos = -(tilepos + 2); 
-                         } else { 
-                                 tilepos -= 9; 
-                         } 
-                 } else { 
-                         tilepos = 30; 
-                 } 
-         } else if (trob.room == room_L) { 
-                 if (tilepos == 9) { 
-                         tilepos = -1; 
-                 } else { 
-                         if (tilepos % 10 == 9) { 
-                                 tilepos -= 19; 
-                         } else { 
-                                 tilepos = 30; 
-                         } 
-                 } 
-         } else if (trob.room == room_B) { 
-                 if (tilepos < 9) { 
-                         tilepos += 21; 
-                 } else { 
-                         tilepos = 30; 
-                 } 
-         } else if (trob.room == room_BL && tilepos == 9) { 
-                 tilepos = 20; 
-         } else { 
-                 tilepos = 30; 
-         } 
-         return tilepos; 
- } 
-   
- // seg007:03CF 
- void __pascal far animate_torch() { 
-         if (is_trob_in_drawn_room()) { 
-                 curr_modifier = get_torch_frame(curr_modifier); 
-                 set_redraw_anim_right(); 
-         } 
- } 
-   
- // seg007:03E9 
- void __pascal far animate_potion() { 
-         word type; 
-         if (trob.type >= 0 && is_trob_in_drawn_room()) { 
-                 type = curr_modifier & 0xF8; 
-                 curr_modifier = bubble_next_frame(curr_modifier & 0x07) | type; 
-                 set_redraw_anim_curr(); 
-         } 
- } 
-   
- // seg007:0425 
- void __pascal far animate_sword() { 
-         if (is_trob_in_drawn_room()) { 
-                 --curr_modifier; 
-                 if (curr_modifier == 0) { 
-                         curr_modifier = (prandom(255) & 0x3F) + 0x28; 
-                 } 
-                 set_redraw_anim_curr(); 
-         } 
- } 
-   
- // seg007:0448 
- void __pascal far animate_chomper() { 
-         word blood; 
-         word frame; 
-         if (trob.type >= 0) { 
-                 blood = curr_modifier & 0x80; 
-                 frame = (curr_modifier & 0x7F) + 1; 
-                 if (frame > 15) { 
-                         frame = 1; 
-                 } 
-                 curr_modifier = blood | frame; 
-                 if (frame == 2) { 
-                         play_sound(sound_47_chomper); // chomper 
-                 } 
-                 // If either: 
-                 // - Kid left this room 
-                 // - Kid left this row 
-                 // - Kid died but not in this chomper 
-                 // and chomper is past frame 6 
-                 // then stop. 
-                 if ((trob.room != drawn_room || trob.tilepos / 10 != Kid.curr_row || 
-                         (Kid.alive >= 0 && blood == 0)) && (curr_modifier & 0x7F) >= 6 
-                 ) { 
-                         trob.type = -1; 
-                 } 
-         } 
-         if ((curr_modifier & 0x7F) < 6) { 
-                 redraw_at_trob(); 
-         } 
- } 
-   
- // seg007:04D3 
- void __pascal far animate_spike() { 
-         if (trob.type >= 0) { 
-                 // 0xFF means a disabled spike. 
-                 if (curr_modifier == 0xFF) return; 
-                 if (curr_modifier & 0x80) { 
-                         --curr_modifier; 
-                         if (curr_modifier & 0x7F) return; 
-                         curr_modifier = 6; 
-                 } else { 
-                         ++curr_modifier; 
-                         if (curr_modifier == 5) { 
-                                 curr_modifier = 0x8F; 
-                         } else if (curr_modifier == 9) { 
-                                 curr_modifier = 0; 
-                                 trob.type = -1; 
-                         } 
-                 } 
-         } 
-         redraw_21h(); 
- } 
-   
- // data:27B2 
- const byte gate_close_speeds[] = {0, 0, 0, 20, 40, 60, 80, 100, 120}; 
- // data:27C0 
- const byte door_delta[] = {-1, 4, 4}; 
- // seg007:0522 
- void __pascal far animate_door() { 
- /* 
- Possible values of anim_type: 
- 0: closing 
- 1: open 
- 2: permanent open 
- 3,4,5,6,7,8: fast closing with speeds 20,40,60,80,100,120 /4 pixel/frame 
- */ 
-         sbyte anim_type; 
-         anim_type = trob.type; 
-         if (anim_type >= 0) { 
-                 if (anim_type >= 3) { 
-                         // closing fast 
-                         if (anim_type < 8) { 
-                                 ++anim_type; 
-                                 trob.type = anim_type; 
-                         } 
-                         short new_mod = curr_modifier - gate_close_speeds[anim_type]; 
-                         curr_modifier = new_mod; 
-                         //if ((sbyte)curr_modifier < 0) { 
-                         if (new_mod < 0) { 
-                         //if ((curr_modifier -= gate_close_speeds[anim_type]) < 0) { 
-                                 curr_modifier = 0; 
-                                 trob.type = -1; 
-                                 play_sound(sound_6_gate_closing_fast); // gate closing fast 
-                         } 
-                 } else { 
-                         if (curr_modifier != 0xFF) { 
-                                 // 0xFF means permanently open. 
-                                 curr_modifier += door_delta[anim_type]; 
-                                 if (anim_type == 0) { 
-                                         // closing 
-                                         if (curr_modifier != 0) { 
-                                                 if (curr_modifier < 188) { 
-                                                         if ((curr_modifier & 3) == 3) { 
-                                                                 play_door_sound_if_visible(sound_4_gate_closing); // gate closing 
-                                                         } 
-                                                 } 
-                                         } else { 
-                                                 gate_stop(); 
-                                         } 
-                                 } else { 
-                                         // opening 
-                                         if (curr_modifier < 188) { 
-                                                 if ((curr_modifier & 7) == 0) { 
-                                                         play_sound(sound_5_gate_opening); // gate opening 
-                                                 } 
-                                         } else { 
-                                                 // stop 
-                                                 if (anim_type < 2) { 
-                                                         // after regular open 
-                                                         curr_modifier = 238; 
-                                                         trob.type = 0; // closing 
-                                                         play_sound(sound_7_gate_stop); // gate stop (after opening) 
-                                                 } else { 
-                                                         // after permanent open 
-                                                         curr_modifier = 0xFF; // keep open 
-                                                         gate_stop(); 
-                                                 } 
-                                         } 
-                                 } 
-                         } else { 
-                                 gate_stop(); 
-                         } 
-                 } 
-         } 
-         draw_trob(); 
- } 
-   
- // seg007:05E3 
- void __pascal far gate_stop() { 
-         trob.type = -1; 
-         play_door_sound_if_visible(sound_7_gate_stop); // gate stop (after closing) 
- } 
-   
- // data:27B8 
- const byte leveldoor_close_speeds[] = {0, 5, 17, 99, 0}; 
- // seg007:05F1 
- void __pascal far animate_leveldoor() { 
- /* 
- Possible values of trob_type: 
- 0: open 
- 1: open (with button) 
- 2: open 
- 3,4,5,6: fast closing with speeds 0,5,17,99 pixel/frame 
- */ 
-         word trob_type; 
-         trob_type = trob.type; 
-         if (trob.type >= 0) { 
-                 if (trob_type >= 3) { 
-                         // closing 
-                         ++trob.type; 
-                         curr_modifier -= leveldoor_close_speeds[trob.type - 3]; 
-                         if ((sbyte)curr_modifier < 0) { 
-                                 curr_modifier = 0; 
-                                 trob.type = -1; 
-                                 play_sound(sound_14_leveldoor_closing); // level door closing 
-                         } else { 
-                                 if (trob.type == 4 && 
-                                         (sound_flags & sfDigi) 
-                                 ) { 
-                                         sound_interruptible[sound_15_leveldoor_sliding] = 1; 
-                                         play_sound(sound_15_leveldoor_sliding); // level door sliding (closing) 
-                                 } 
-                         } 
-                 } else { 
-                         // opening 
-                         ++curr_modifier; 
-                         if (curr_modifier >= 43) { 
-                                 trob.type = -1; 
- #ifdef FIX_FEATHER_INTERRUPTED_BY_LEVELDOOR 
-                                 if (!(fix_feather_interrupted_by_leveldoor && is_feather_fall)) 
- #endif 
-                                 stop_sounds(); 
-                                 if (leveldoor_open == 0 || leveldoor_open == 2) { 
-                                         leveldoor_open = 1; 
-                                         if (current_level == 4) { 
-                                                 // Special event: place mirror 
-                                                 get_tile(4, 4, 0); 
-                                                 curr_room_tiles[curr_tilepos] = tiles_13_mirror; 
-                                         } 
-                                 } 
-                         } else { 
-                                 sound_interruptible[15] = 0; 
-                                 play_sound(sound_15_leveldoor_sliding); // level door sliding (opening) 
-                         } 
-                 } 
-         } 
-         set_redraw_anim_right(); 
- } 
-   
- // seg007:06AD 
- short __pascal far bubble_next_frame(short curr) { 
-         short next; 
-         next = curr + 1; 
-         if (next >= 8) next = 1; 
-         return next; 
- } 
-   
- // seg007:06CD 
- short __pascal far get_torch_frame(short curr) { 
-         short next; 
-         next = prandom(255); 
-         if (next != curr) { 
-                 if (next < 9) { 
-                         return next; 
-                 } else { 
-                         next = curr; 
-                 } 
-         } 
-         ++next; 
-         if (next >= 9) next = 0; 
-         return next; 
- } 
-   
- // seg007:070A 
- void __pascal far set_redraw_anim(short tilepos, byte frames) { 
-         if (tilepos < 30) { 
-                 if (tilepos < 0) { 
-                         ++tilepos; 
-                         redraw_frames_above[-tilepos] = frames; 
-                         // or simply: ~tilepos 
-                 } else { 
-                         redraw_frames_anim[tilepos] = frames; 
-                 } 
-         } 
- } 
-   
- // seg007:0738 
- void __pascal far set_redraw2(short tilepos, byte frames) { 
-         if (tilepos < 30) { 
-                 if (tilepos < 0) { 
-                         // trying to draw a mob at a negative tilepos, in the range -1 .. -10 
-                         // used e.g. when the kid is climbing up to the room above 
-                         // however, loose tiles falling out of the room end up with a negative tilepos {-2 .. -11} ! 
-                         tilepos = (-tilepos) - 1; 
-                         if (tilepos > 9) tilepos = 9; // prevent array index out of bounds! 
-                         redraw_frames_above[tilepos] = frames; 
-                 } else { 
-                         redraw_frames2[tilepos] = frames; 
-                 } 
-         } 
- } 
-   
- // seg007:0766 
- void __pascal far set_redraw_floor_overlay(short tilepos, byte frames) { 
-         if (tilepos < 30) { 
-                 if (tilepos < 0) { 
-                         ++tilepos; 
-                         redraw_frames_above[-tilepos] = frames; 
-                         // or simply: ~tilepos 
-                 } else { 
-                         redraw_frames_floor_overlay[tilepos] = frames; 
-                 } 
-         } 
- } 
-   
- // seg007:0794 
- void __pascal far set_redraw_full(short tilepos, byte frames) { 
-         if (tilepos < 30) { 
-                 if (tilepos < 0) { 
-                         ++tilepos; 
-                         redraw_frames_above[-tilepos] = frames; 
-                         // or simply: ~tilepos 
-                 } else { 
-                         redraw_frames_full[tilepos] = frames; 
-                 } 
-         } 
- } 
-   
- // seg007:07C2 
- void __pascal far set_redraw_fore(short tilepos, byte frames) { 
-         if (tilepos < 30 && tilepos >= 0) { 
-                 redraw_frames_fore[tilepos] = frames; 
-         } 
- } 
-   
- // seg007:07DF 
- void __pascal far set_wipe(short tilepos, byte frames) { 
-         if (tilepos < 30 && tilepos >= 0) { 
-                 if (wipe_frames[tilepos] != 0) { 
-                         redraw_height = MAX(wipe_heights[tilepos], redraw_height); 
-                 } 
-                 wipe_heights[tilepos] = redraw_height; 
-                 wipe_frames[tilepos] = frames; 
-         } 
- } 
-   
- // seg007:081E 
- void __pascal far start_anim_torch(short room,short tilepos) { 
-         curr_room_modif[tilepos] = prandom(8); 
-         add_trob(room, tilepos, 1); 
- } 
-   
- // seg007:0847 
- void __pascal far start_anim_potion(short room,short tilepos) { 
-         curr_room_modif[tilepos] &= 0xF8; 
-         curr_room_modif[tilepos] |= prandom(6) + 1; 
-         add_trob(room, tilepos, 1); 
- } 
-   
- // seg007:087C 
- void __pascal far start_anim_sword(short room,short tilepos) { 
-         curr_room_modif[tilepos] = prandom(0xFF) & 0x1F; 
-         add_trob(room, tilepos, 1); 
- } 
-   
- // seg007:08A7 
- void __pascal far start_anim_chomper(short room,short tilepos, byte modifier) { 
-         short old_modifier; 
-         old_modifier = curr_room_modif[tilepos]; 
-         if (old_modifier == 0 || old_modifier >= 6) { 
-                 curr_room_modif[tilepos] = modifier; 
-                 add_trob(room, tilepos, 1); 
-         } 
- } 
-   
- // seg007:08E3 
- void __pascal far start_anim_spike(short room,short tilepos) { 
-         sbyte old_modifier; 
-         old_modifier = curr_room_modif[tilepos]; 
-         if (old_modifier <= 0) { 
-                 if (old_modifier == 0) { 
-                         add_trob(room, tilepos, 1); 
-                         play_sound(sound_49_spikes); // spikes 
-                 } else { 
-                         // 0xFF means a disabled spike. 
-                         if (old_modifier != (sbyte)0xFF) { 
-                                 curr_room_modif[tilepos] = 0x8F; 
-                         } 
-                 } 
-         } 
- } 
-   
- // seg007:092C 
- short __pascal far trigger_gate(short room,short tilepos,short button_type) { 
-         byte modifier; 
-         modifier = curr_room_modif[tilepos]; 
-         if (button_type == tiles_15_opener) { 
-                 // If the gate is permanently open, don't to anything. 
-                 if (modifier == 0xFF) return -1; 
-                 if (modifier >= 188) { // if it's already open 
-                         curr_room_modif[tilepos] = 238; // keep it open for a while 
-                         return -1; 
-                 } 
-                 curr_room_modif[tilepos] = (modifier + 3) & 0xFC; 
-                 return 1; // regular open 
-         } else if (button_type == tiles_14_debris) { 
-                 // If it's not fully open: 
-                 if (modifier < 188) return 2; // permanent open 
-                 curr_room_modif[tilepos] = 0xFF; // keep open 
-                 return -1; 
-         } else { 
-                 if (modifier != 0) { 
-                         return 3; // close fast 
-                 } else { 
-                         // already closed 
-                         return -1; 
-                 } 
-         } 
- } 
-   
- // seg007:0999 
- short __pascal far trigger_1(short target_type,short room,short tilepos,short button_type) { 
-         short result; 
-         result = -1; 
-         if (target_type == tiles_4_gate) { 
-                 result = trigger_gate(room, tilepos, button_type); 
-         } else if (target_type == tiles_16_level_door_left) { 
-                 if (curr_room_modif[tilepos] != 0) { 
-                         result = -1; 
-                 } else { 
-                         result = 1; 
-                 } 
-         } else if (allow_triggering_any_tile) { //allow_triggering_any_tile hack 
-                 result = 1; 
-         } 
-         return result; 
- } 
-   
- // seg007:09E5 
- void __pascal far do_trigger_list(short index,short button_type) { 
-         word room; 
-         word tilepos; 
-         byte target_type; 
-         sbyte trigger_result; 
- //      while (doorlink1_ad[index] != -1) { // these can't be equal! 
-         while (1) {  // Same as the above but just a little faster and no compiler warning. 
-                 room = get_doorlink_room(index); 
-                 get_room_address(room); 
-                 tilepos = get_doorlink_tile(index); 
-                 target_type = curr_room_tiles[tilepos] & 0x1F; 
-                 trigger_result = trigger_1(target_type, room, tilepos, button_type); 
-                 if (trigger_result >= 0) { 
-                         add_trob(room, tilepos, trigger_result); 
-                 } 
-                 if (get_doorlink_next(index++) == 0) break; 
-         } 
- } 
-   
- // seg007:0A5A 
- void __pascal far add_trob(byte room,byte tilepos,sbyte type) { 
-         short found; 
-         if (trobs_count >= 30) { 
-                 show_dialog("Trobs Overflow"); 
-                 return /*0*/; // added 
-         } 
-         trob.room = room; 
-         trob.tilepos = tilepos; 
-         trob.type = type; 
-         found = find_trob(); 
-         if (found == -1) { 
-                 // add new 
-                 if (trobs_count == 30) return; 
-                 trobs[trobs_count++] = trob; 
-         } else { 
-                 // change existing 
-                 trobs[found].type = trob.type; 
-         } 
- } 
-   
- // seg007:0ACA 
- short __pascal far find_trob() { 
-         short index; 
-         for (index = 0; index < trobs_count; ++index) { 
-                 if (trobs[index].tilepos == trob.tilepos && 
-                         trobs[index].room == trob.room) return index; 
-         } 
-         return -1; 
- } 
-   
- // seg007:0B0A 
- void __pascal far clear_tile_wipes() { 
-         memset_near(redraw_frames_full, 0, sizeof(redraw_frames_full)); 
-         memset_near(wipe_frames, 0, sizeof(wipe_frames)); 
-         memset_near(wipe_heights, 0, sizeof(wipe_heights)); 
-         memset_near(redraw_frames_anim, 0, sizeof(redraw_frames_anim)); 
-         memset_near(redraw_frames_fore, 0, sizeof(redraw_frames_fore)); 
-         memset_near(redraw_frames2, 0, sizeof(redraw_frames2)); 
-         memset_near(redraw_frames_floor_overlay, 0, sizeof(redraw_frames_floor_overlay)); 
-         memset_near(tile_object_redraw, 0, sizeof(tile_object_redraw)); 
-         memset_near(redraw_frames_above, 0, sizeof(redraw_frames_above)); 
- } 
-   
- // seg007:0BB6 
- short __pascal far get_doorlink_timer(short index) { 
-         return doorlink2_ad[index] & 0x1F; 
- } 
-   
- // seg007:0BCD 
- short __pascal far set_doorlink_timer(short index,byte value) { 
-         doorlink2_ad[index] &= 0xE0; 
-         doorlink2_ad[index] |= value & 0x1F; 
-         return doorlink2_ad[index]; 
- } 
-   
- // seg007:0BF2 
- short __pascal far get_doorlink_tile(short index) { 
-         return doorlink1_ad[index] & 0x1F; 
- } 
-   
- // seg007:0C09 
- short __pascal far get_doorlink_next(short index) { 
-         return !(doorlink1_ad[index] & 0x80); 
- } 
-   
- // seg007:0C26 
- short __pascal far get_doorlink_room(short index) { 
-         return 
-                 ((doorlink1_ad[index] & 0x60) >> 5) + 
-                 ((doorlink2_ad[index] & 0xE0) >> 3); 
- } 
-   
- // seg007:0C53 
- void __pascal far trigger_button(int playsound,int button_type,int modifier) { 
-         sbyte link_timer; 
-         get_curr_tile(curr_tilepos); 
-         if (button_type == 0) { 
-                 // 0 means currently selected 
-                 button_type = curr_tile; 
-         } 
-         if (modifier == -1) { 
-                 // -1 means currently selected 
-                 modifier = curr_modifier; 
-         } 
-         link_timer = get_doorlink_timer(modifier); 
-         // is the event jammed? 
-         if (link_timer != 0x1F) { 
-                 set_doorlink_timer(modifier, 5); 
-                 if (link_timer < 2) { 
-                         add_trob(curr_room, curr_tilepos, 1); 
-                         redraw_11h(); 
-                         is_guard_notice = 1; 
-                         if (playsound) { 
-                                 play_sound(sound_3_button_pressed); // button pressed 
-                         } 
-                 } 
-                 do_trigger_list(modifier, button_type); 
-         } 
- } 
-   
- // seg007:0CD9 
- void __pascal far died_on_button() { 
-         word button_type; 
-         word modifier; 
-         button_type = get_curr_tile(curr_tilepos); 
-         modifier = curr_modifier; 
-         if (curr_tile == tiles_15_opener) { 
-                 curr_room_tiles[curr_tilepos] = tiles_1_floor; 
-                 curr_room_modif[curr_tilepos] = 0; 
-                 button_type = tiles_14_debris; // force permanent open 
-         } else { 
-                 curr_room_tiles[curr_tilepos] = tiles_5_stuck; 
-         } 
-         trigger_button(1, button_type, modifier); 
- } 
-   
- // seg007:0D3A 
- void __pascal far animate_button() { 
-         word var_2; 
-         if (trob.type >= 0) { 
-                 set_doorlink_timer(curr_modifier, var_2 = get_doorlink_timer(curr_modifier) - 1); 
-                 if (var_2 < 2) { 
-                         trob.type = -1; 
-                         redraw_11h(); 
-                 } 
-         } 
- } 
-   
- // seg007:0D72 
- void __pascal far start_level_door(short room,short tilepos) { 
-         curr_room_modif[tilepos] = 43; // start fully open 
-         add_trob(room, tilepos, 3); 
- } 
-   
- // seg007:0D93 
- void __pascal far animate_empty() { 
-         trob.type = -1; 
-         redraw_20h(); 
- } 
-   
- // data:2284 
- const word y_loose_land[] = {2, 65, 128, 191, 254}; 
- // seg007:0D9D 
- void __pascal far animate_loose() { 
-         word room; 
-         word row; 
-         word tilepos; 
-         short anim_type; 
-         anim_type = trob.type; 
-         if (anim_type >= 0) { 
-                 ++curr_modifier; 
-                 if (curr_modifier & 0x80) { 
-                         // just shaking 
-                         // don't shake on level 13 
-                         if (current_level == 13) return; 
-                         if (curr_modifier >= 0x84) { 
-                                 curr_modifier = 0; 
-                                 trob.type = -1; 
-                         } 
-                         loose_shake(!curr_modifier); 
-                 } else { 
-                         // something is on the floor 
-                         // should it fall already? 
-                         if (curr_modifier >= 11) { 
-                                 curr_modifier = remove_loose(room = trob.room, tilepos = trob.tilepos); 
-                                 trob.type = -1; 
-                                 curmob.xh = (tilepos % 10) << 2; 
-                                 row = tilepos / 10; 
-                                 curmob.y = y_loose_land[row + 1]; 
-                                 curmob.room = room; 
-                                 curmob.speed = 0; 
-                                 curmob.type = 0; 
-                                 curmob.row = row; 
-                                 add_mob(); 
-                         } else { 
-                                 loose_shake(0); 
-                         } 
-                 } 
-         } 
-         redraw_20h(); 
- } 
-   
- // data:2734 
- const byte loose_sound[] = {0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}; 
- // seg007:0E55 
- void __pascal far loose_shake(int arg_0) { 
-         word sound_id; 
-         if (arg_0 || loose_sound[curr_modifier & 0x7F]) { 
-                 do { 
-                         // Sounds 20,21,22: loose floor shaking 
-                         sound_id = prandom(2) + sound_20_loose_shake_1; 
-                 } while(sound_id == last_loose_sound); 
-                 if (sound_flags & sfDigi) { 
-                         last_loose_sound = sound_id; 
-                         // random sample rate (10500..11500) 
-                         //sound_pointers[sound_id]->samplerate = prandom(1000) + 10500; 
-                 } 
-                 play_sound(sound_id); 
-         } 
- } 
-   
- // seg007:0EB8 
- int __pascal far remove_loose(int room, int tilepos) { 
-         curr_room_tiles[tilepos] = tiles_0_empty; 
-         // note: the level type is used to determine the modifier of the empty space left behind 
-         return tbl_level_type[current_level]; 
- } 
-   
- // seg007:0ED5 
- void __pascal far make_loose_fall(byte modifier) { 
-         // is it a "solid" loose floor? 
-         if ((curr_room_tiles[curr_tilepos] & 0x20) == 0) { 
-                 if ((sbyte)curr_room_modif[curr_tilepos] <= 0) { 
-                         curr_room_modif[curr_tilepos] = modifier; 
-                         add_trob(curr_room, curr_tilepos, 0); 
-                         redraw_20h(); 
-                 } 
-         } 
- } 
-   
- // seg007:0F13 
- void __pascal far start_chompers() { 
-         short timing; 
-         short modifier; 
-         short tilepos; 
-         short column; 
-         timing = 15; 
-         if ((byte)Char.curr_row < 3) { 
-                 get_room_address(Char.room); 
-                 for (column = 0, tilepos = tbl_line[Char.curr_row]; 
-                         column < 10; ++column, ++tilepos 
-                 ){ 
-                         if (get_curr_tile(tilepos) == tiles_18_chomper) { 
-                                 modifier = curr_modifier & 0x7F; 
-                                 if (modifier == 0 || modifier >= 6) { 
-                                         start_anim_chomper(Char.room, tilepos, timing | (curr_modifier & 0x80)); 
-                                         timing = next_chomper_timing(timing); 
-                                 } 
-                         } 
-                 } 
-         } 
- } 
-   
- // seg007:0F9A 
- int __pascal far next_chomper_timing(byte timing) { 
-         // 15,12,9,6,13,10,7,14,11,8,repeat 
-         timing -= 3; 
-         if (timing < 6) { 
-                 timing += 10; 
-         } 
-         return timing; 
- } 
-   
- // seg007:0FB4 
- void __pascal far loose_make_shake() { 
-         if (curr_room_modif[curr_tilepos] == 0 && current_level != 13) { 
-                 curr_room_modif[curr_tilepos] = 0x80; 
-                 add_trob(curr_room, curr_tilepos, 1); 
-         } 
- } 
-   
- // seg007:0FE0 
- void __pascal far do_knock(int room,int tile_row) { 
-         short tile_col; 
-         for (tile_col = 0; tile_col < 10; ++tile_col) { 
-                 if (get_tile(room, tile_col, tile_row) == tiles_11_loose) { 
-                         loose_make_shake(); 
-                 } 
-         } 
- } 
-   
- // seg007:1010 
- void __pascal far add_mob() { 
-         if (mobs_count >= 14) { 
-                 show_dialog("Mobs Overflow"); 
-                 return /*0*/; // added 
-         } 
-         mobs[mobs_count++] = curmob; 
- } 
-   
- // seg007:1041 
- short __pascal far get_curr_tile(short tilepos) { 
-         curr_modifier = curr_room_modif[tilepos]; 
-         return curr_tile = curr_room_tiles[tilepos] & 0x1F; 
- } 
-   
- // data:43DC 
- word curmob_index; 
-   
- // seg007:1063 
- void __pascal far do_mobs() { 
-         short n_mobs; 
-         short index; 
-         short new_index; 
-         n_mobs = mobs_count; 
-         for (curmob_index = 0; n_mobs > curmob_index; ++curmob_index) { 
-                 curmob = mobs[curmob_index]; 
-                 move_mob(); 
-                 check_loose_fall_on_kid(); 
-                 mobs[curmob_index] = curmob; 
-         } 
-         new_index = 0; 
-         for (index = 0; index < mobs_count; ++index) { 
-                 if (mobs[index].speed != -1) { 
-                         mobs[new_index++] = mobs[index]; 
-                 } 
-         } 
-         mobs_count = new_index; 
- } 
-   
- // seg007:110F 
- void __pascal far move_mob() { 
-         if (curmob.type == 0) { 
-                 move_loose(); 
-         } 
-         if (curmob.speed <= 0) { 
-                 ++curmob.speed; 
-         } 
- } 
-   
- // data:227A 
- const short y_something[] = {-1, 62, 125, 188, 25}; 
- // data:594A 
- word curr_tile_temp; 
- // seg007:1126 
- void __pascal far move_loose() { 
-         if (curmob.speed < 0) return; 
-         if (curmob.speed < 29) curmob.speed += 3; 
-         curmob.y += curmob.speed; 
-         if (curmob.room == 0) { 
-                 if (curmob.y < 210) { 
-                         return; 
-                 } else { 
-                         curmob.speed = -2; 
-                         return; 
-                 } 
-         } 
-         if (curmob.y < 226 && y_something[curmob.row + 1] <= curmob.y) { 
-                 // fell into a different row 
-                 curr_tile_temp = get_tile(curmob.room, curmob.xh >> 2, curmob.row); 
-                 if (curr_tile_temp == tiles_11_loose) { 
-                         loose_fall(); 
-                 } 
-                 if (curr_tile_temp == tiles_0_empty || 
-                         curr_tile_temp == tiles_11_loose 
-                 ) { 
-                         mob_down_a_row(); 
-                         return; 
-                 } 
-                 play_sound(sound_2_tile_crashing); // tile crashing 
-                 do_knock(curmob.room, curmob.row); 
-                 curmob.y = y_something[curmob.row + 1]; 
-                 curmob.speed = -2; 
-                 loose_land(); 
-         } 
- } 
-   
- // seg007:11E8 
- void __pascal far loose_land() { 
-         short button_type; 
-         short tiletype; 
-         button_type = 0; 
-         tiletype = get_tile(curmob.room, curmob.xh >> 2, curmob.row); 
-         switch (tiletype) { 
-                 case tiles_15_opener: 
-                         curr_room_tiles[curr_tilepos] = tiles_14_debris; 
-                         button_type = tiles_14_debris; 
-                 // fallthrough! 
-                 case tiles_6_closer: 
-                         trigger_button(1, button_type, -1); 
-                         tiletype = get_tile(curmob.room, curmob.xh >> 2, curmob.row); 
-                 // fallthrough! 
-                 case tiles_1_floor: 
-                 case tiles_2_spike: 
-                 case tiles_10_potion: 
-                 case tiles_19_torch: 
-                 case tiles_30_torch_with_debris: 
-                         if (tiletype == tiles_19_torch || 
-                                 tiletype == tiles_30_torch_with_debris 
-                         ) { 
-                                 curr_room_tiles[curr_tilepos] = tiles_30_torch_with_debris; 
-                         } else { 
-                                 curr_room_tiles[curr_tilepos] = tiles_14_debris; 
-                         } 
-                         redraw_at_cur_mob(); 
-                         if (tile_col != 0) { 
-                                 set_redraw_full(curr_tilepos - 1, 1); 
-                         } 
-         } 
- } 
-   
- // seg007:12CB 
- void __pascal far loose_fall() { 
-         curr_room_modif[curr_tilepos] = remove_loose(curr_room, curr_tilepos); 
-         curmob.speed >>= 1; 
-         mobs[curmob_index] = curmob; 
-         curmob.y += 6; 
-         mob_down_a_row(); 
-         add_mob(); 
-         curmob = mobs[curmob_index]; 
-         redraw_at_cur_mob(); 
- } 
-   
- // seg007:132C 
- void __pascal far redraw_at_cur_mob() { 
-         if (curmob.room == drawn_room) { 
-                 redraw_height = 0x20; 
-                 set_redraw_full(curr_tilepos, 1); 
-                 set_wipe(curr_tilepos, 1); 
-                 // Redraw tile to the right only if it's in the same room. 
-                 if ((curr_tilepos % 10) + 1 < 10) { // changed 
-                         set_redraw_full(curr_tilepos + 1, 1); 
-                         set_wipe(curr_tilepos + 1, 1); 
-                 } 
-         } 
- } 
-   
- // seg007:1387 
- void __pascal far mob_down_a_row() { 
-         ++curmob.row; 
-         if (curmob.row >= 3) { 
-                 curmob.y -= 192; 
-                 curmob.row = 0; 
-                 curmob.room = level.roomlinks[curmob.room - 1].down; 
-         } 
- } 
-   
- // seg007:13AE 
- void __pascal far draw_mobs() { 
-         short index; 
-         for (index = 0; index < mobs_count; ++index) { 
-                 curmob = mobs[index]; 
-                 draw_mob(); 
-         } 
- } 
-   
- // seg007:13E5 
- void __pascal far draw_mob() { 
-         short tile_row; 
-         short ypos; 
-         short top_row; 
-         short tilepos; 
-         short tile_col; 
-         ypos = curmob.y; 
-         if (curmob.room == drawn_room) { 
-                 if (curmob.y >= 210) return; 
-         } else if (curmob.room == room_B) { 
-                 if (ABS(ypos) >= 18) return; 
-                 curmob.y += 192; 
-                 ypos = curmob.y; 
-         } else if (curmob.room == room_A) { 
-                 if (curmob.y < 174) return; 
-                 ypos = curmob.y - 189; 
-         } else { 
-                 return; 
-         } 
-         tile_col = curmob.xh >> 2; 
-         tile_row = y_to_row_mod4(ypos); 
-         obj_tilepos = get_tilepos_nominus(tile_col, tile_row); 
-         ++tile_col; 
-         tilepos = get_tilepos(tile_col, tile_row); 
-         set_redraw2(tilepos, 1); 
-         set_redraw_fore(tilepos, 1); 
-         top_row = y_to_row_mod4(ypos - 18); 
-         if (top_row != tile_row) { 
-                 tilepos = get_tilepos(tile_col, top_row); 
-                 set_redraw2(tilepos, 1); 
-                 set_redraw_fore(tilepos, 1); 
-         } 
-         add_mob_to_objtable(ypos); 
- } 
-   
- // seg007:14DE 
- void __pascal far add_mob_to_objtable(int ypos) { 
-         word index; 
-         objtable_type* curr_obj; 
-         index = objtable_count++; 
-         curr_obj = &objtable[index]; 
-         curr_obj->obj_type = curmob.type | 0x80; 
-         curr_obj->xh = curmob.xh; 
-         curr_obj->xl = 0; 
-         curr_obj->y = ypos; 
-         curr_obj->chtab_id = id_chtab_6_environment; 
-         curr_obj->id = 10; 
-         curr_obj->clip.top = 0; 
-         curr_obj->clip.left = 0; 
-         curr_obj->clip.right = 40; 
-         mark_obj_tile_redraw(index); 
- } 
-   
- // seg007:153E 
- void __pascal far sub_9A8E() { 
-         // This function is not used. 
-         method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_top, &rect_top, 0); 
- } 
-   
- // seg007:1556 
- int __pascal far is_spike_harmful() { 
-         sbyte modifier; 
-         modifier = curr_room_modif[curr_tilepos]; 
-         if (modifier == 0 || modifier == -1) { 
-                 return 0; 
-         } else if (modifier < 0) { 
-                 return 1; 
-         } else if (modifier < 5) { 
-                 return 2; 
-         } else { 
-                 return 0; 
-         } 
- } 
-   
- // seg007:1591 
- void __pascal far check_loose_fall_on_kid() { 
-         loadkid(); 
-         if (Char.room == curmob.room && 
-                 Char.curr_col == curmob.xh >> 2 && 
-                 curmob.y < Char.y && 
-                 Char.y - 30 < curmob.y 
-         ) { 
-                 fell_on_your_head(); 
-                 savekid(); 
-         } 
- } 
-   
- // seg007:15D3 
- void __pascal far fell_on_your_head() { 
-         short frame; 
-         short action; 
-         frame = Char.frame; 
-         action = Char.action; 
-         // loose floors hurt you in frames 5..14 (running) only on level 13 
-         if ( 
-                 (current_level == 13 || (frame < frame_5_start_run || frame >= 15)) && 
-                 (action < actions_2_hang_climb || action == actions_7_turn) 
-         ) { 
-                 Char.y = y_land[Char.curr_row + 1]; 
-                 if (take_hp(1)) { 
-                         seqtbl_offset_char(seq_22_crushed); // dead (because of loose floor) 
-                         if (frame == frame_177_spiked) { // spiked 
-                                 Char.x = char_dx_forward(-12); 
-                         } 
-                 } else { 
-                         if (frame != frame_109_crouch) { // crouching 
-                                 if (get_tile_behind_char() == 0) { 
-                                         Char.x = char_dx_forward(-2); 
-                                 } 
-                                 seqtbl_offset_char(seq_52_loose_floor_fell_on_kid); // loose floor fell on Kid 
-                         } 
-                 } 
-         } 
- } 
-   
- // seg007:1669 
- void __pascal far play_door_sound_if_visible(int sound_id) { 
-         word has_sound; 
-         word tilepos; 
-         word gate_room; 
-         tilepos = trob.tilepos; 
-         gate_room = trob.room; 
-         has_sound = 0; 
-   
- #ifdef FIX_GATE_SOUNDS 
-         sbyte has_sound_condition; 
-         if (fix_gate_sounds) 
-                 has_sound_condition =   (gate_room == room_L && tilepos % 10 == 9) || 
-                                         (gate_room == drawn_room && tilepos % 10 != 9); 
-         else 
-                 has_sound_condition =  gate_room == room_L ? tilepos % 10 == 9 : 
-                                       (gate_room == drawn_room && tilepos % 10 != 9); 
-         #define GATE_SOUND_CONDITION has_sound_condition 
- #else 
-         #define GATE_SOUND_CONDITION gate_room == room_L ? tilepos % 10 == 9 :          \ 
-                                     (gate_room == drawn_room && tilepos % 10 != 9) 
- #endif 
-         // Special event: sound of closing gates 
-         if ((current_level == 3 && gate_room == 2) || GATE_SOUND_CONDITION) { 
-                 has_sound = 1; 
-         } 
-         if (has_sound) { 
-                 play_sound(sound_id); 
-         } 
- } 
-