void close_door (struct level *l, int e) { struct pos *p; struct door *d; struct level_door *ld; do { p = &l->event[e].p; switch (con (p)->fg) { case DOOR: d = door_at_pos (p); if (! d) continue; d->action = ABRUPTLY_CLOSE_DOOR; break; case LEVEL_DOOR: ld = level_door_at_pos (p); if (! ld) continue; ld->action = CLOSE_LEVEL_DOOR; break; default: break; } } while (l->event[e++].next); }
int door_grid_tip_y (struct pos *p) { struct coord c; int h = al_get_bitmap_height (dv_door_grid_tip); return door_grid_tip_coord (p, &c, door_at_pos (p)->i)->y + h - 1; }
void open_door (struct level *l, int e) { struct pos *p; struct door *d; struct level_door *ld; do { p = &l->event[e].p; switch (con (p)->fg) { case DOOR: d = door_at_pos (p); if (! d) continue; d->action = OPEN_DOOR; d->wait = DOOR_WAIT; break; case LEVEL_DOOR: ld = level_door_at_pos (p); if (! ld) continue; ld->action = OPEN_LEVEL_DOOR; break; default: break; } } while (l->event[e++].next); }
void register_door (struct pos *p) { assert (con (p)->fg == DOOR && door_at_pos (p) == NULL); struct door d; d.p = *p; d.i = con (p)->ext.step; d.action = NO_DOOR_ACTION; d.wait = DOOR_WAIT; d.noise = false; door = add_to_array (&d, 1, door, &door_nmemb, door_nmemb, sizeof (d)); qsort (door, door_nmemb, sizeof (d), compare_doors); }
void draw_door_fg (ALLEGRO_BITMAP *bitmap, struct pos *p, struct frame *f, enum em em, enum vm vm) { struct pos par, pr, pa; draw_floor_base (bitmap, p, em, vm); draw_door_pole (bitmap, p, em, vm); prel (p, &pr, +0, +1); prel (p, &pa, -1, +0); prel (p, &par, -1, +1); if (should_draw_door_grid (p, f)) { struct door *d = door_at_pos (p); draw_door_grid (bitmap, p, d->i, em, vm); draw_confg_right (bitmap, &pa, em, vm, true); draw_confg_base (bitmap, &par, em, vm); draw_confg_left (bitmap, &par, em, vm, true); draw_confg_fg (bitmap, &pr, em, vm, f); } }
static bool flow (struct anim *k) { struct coord nc; struct pos np, ptf, pbf; enum confg ctf; if (k->oaction != kid_couch) { k->i = -1; k->fall = k->collision = k->misstep = false; k->wait = 0; } if (k->uncouch_slowly) { k->wait = 36; k->uncouch_slowly = false; } if (k->oaction == kid_climb) k->i = 10; if (k->oaction == kid_couch_collision) k->collision = true, k->inertia = k->cinertia = 0; if (k->oaction == kid_fall) { k->fall = true; k->inertia = k->cinertia = 0; } /* if (k->i > 2 && k->hit_by_loose_floor) */ /* k->i = -1; */ /* unclimb */ int dir = (k->f.dir == LEFT) ? +1 : -1; ctf = survey (_tf, pos, &k->f, &nc, &ptf, &np)->fg; survey (_bf, pos, &k->f, &nc, &pbf, &np); struct pos ph; prel (&pbf, &ph, +1, dir); if (k->i == -1 && ! k->collision && ! k->fall && ! k->hit_by_loose_floor && k->item_pos.room == -1 && is_hangable_pos (&ph, k->f.dir) && dist_next_place (&k->f, _tf, pos, 0, true) <= 27 && ! (ctf == DOOR && k->f.dir == LEFT && door_at_pos (&ptf)->i > DOOR_CLIMB_LIMIT)) { pos2room (&ph, k->f.c.room, &k->hang_pos); kid_unclimb (k); return false; } if (k->i == 12) { k->hit_by_loose_floor = false; kid_normal (k); return false; } if (k->i == 2 && k->item_pos.room != -1 && ! k->collision && ! k->fall) { if (is_potion (&k->item_pos)) kid_drink (k); else if (is_sword (&k->item_pos)) kid_raise_sword (k); else { k->item_pos.room = -1; goto no_item; } return false; } no_item: if (k->i == 2 && k->key.down && k->cinertia == 0 && k->wait-- <= 0 && ((k->f.dir == LEFT && k->key.left) || (k->f.dir == RIGHT && k->key.right))) { k->i = 0; select_frame (k, kid_couch_frameset, 0); return true; } if (k->i != 2 || (! k->key.down && k->wait-- <= 0)) k->i++; if (k->i == 1 && k->wait > 0 && ((k->fall == true && k->hurt) || k->hit_by_loose_floor)) k->i = 2; select_frame (k, kid_couch_frameset, k->i); if (k->oaction == kid_climb) k->fo.dx += 7; if (k->i > 0 && k->i < 3) k->fo.dx -= k->cinertia; if (k->cinertia > 0) k->cinertia--; return true; }
void draw_door_right (ALLEGRO_BITMAP *bitmap, struct pos *p, enum em em, enum vm vm) { struct coord c; struct door *d = door_at_pos (p); if (! d) return; ALLEGRO_BITMAP *door_right = NULL, *door_top = NULL; switch (em) { case DUNGEON: switch (vm) { case CGA: door_right = dc_door_right; door_top = dc_door_top; break; case EGA: door_right = de_door_right; door_top = de_door_top; break; case VGA: door_right = dv_door_right; door_top = dv_door_top; break; } break; case PALACE: switch (vm) { case CGA: door_right = pc_door_right; door_top = pc_door_top; break; case EGA: door_right = pe_door_right; door_top = pe_door_top; break; case VGA: door_right = pv_door_right; door_top = pv_door_top; break; } break; } if (vm == VGA) { door_right = apply_hue_palette (door_right); door_top = apply_hue_palette (door_top); } if (hgc) { door_right = apply_palette (door_right, hgc_palette); door_top = apply_palette (door_top, hgc_palette); } if (peq (p, &mouse_pos)) { door_right = apply_palette (door_right, selection_palette); door_top = apply_palette (door_top, selection_palette); } draw_bitmapc (door_right, bitmap, door_right_coord (p, &c), 0); draw_bitmapc (door_top, bitmap, door_top_coord (p, &c), 0); draw_door_grid (bitmap, p, d->i, em, vm); }
void update_cache_pos (struct pos *p, enum changed_pos_reason reason, enum em em, enum vm vm) { static bool recursive = false, recursive_01 = false; int x, y; struct pos p0; p0 = *p; struct pos pbl; prel (p, &pbl, +1, -1); struct pos pb; prel (p, &pb, +1, +0); struct pos pbr; prel (p, &pbr, +1, +1); struct pos pl; prel (p, &pl, +0, -1); struct pos pr; prel (p, &pr, +0, +1); struct pos par; prel (p, &par, -1, +1); /* if (! recursive) */ /* printf ("%i,%i,%i,%i\n", p->room, p->floor, p->place, reason); */ for (y = mr.h - 1; y >= 0; y--) for (x = 0; x < mr.w; x++) if (p->room && mr.cell[x][y].room == p->room) { room_view = p->room; mr.dx = x; mr.dy = y; con_caching = true; struct rect r; struct door *d; switch (reason) { case CHPOS_NONE: break; case CHPOS_UNHIDE_FLOOR: case CHPOS_MOUSE_SELECT: case CHPOS_MOUSE_DESELECT: case CHPOS_CLOSE_LEVEL_DOOR: case CHPOS_CARPET_DESIGN: case CHPOS_WALL: draw_conbg (mr.cell[x][y].cache, p, em, vm, true); break; case CHPOS_SHAKE_LOOSE_FLOOR: case CHPOS_RELEASE_LOOSE_FLOOR: case CHPOS_PRESS_OPENER_FLOOR: case CHPOS_UNPRESS_OPENER_FLOOR: case CHPOS_PRESS_CLOSER_FLOOR: case CHPOS_UNPRESS_CLOSER_FLOOR: new_rect (&r, p->room, PLACE_WIDTH * p->place, PLACE_HEIGHT * p->floor + 49, 58, 17); clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR); if (con (&pbl)->fg == LEVEL_DOOR || con (&pbl)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pbl, em, vm, true); if (con (&pb)->fg == LEVEL_DOOR || con (&pb)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pb, em, vm, true); if (con (&pbr)->fg == LEVEL_DOOR || con (&pbr)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pbr, em, vm, true); draw_confg_top (mr.cell[x][y].cache, &pb, em, vm, true); draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true); draw_conbg (mr.cell[x][y].cache, p, em, vm, true); break; case CHPOS_LOOSE_FLOOR_FALL: case CHPOS_CHAIN_RELEASE_LOOSE_FLOOR: new_rect (&r, p->room, PLACE_WIDTH * p->place, PLACE_HEIGHT * p->floor + 49, 58, 17); clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR); if (con (&pbl)->fg == LEVEL_DOOR || con (&pbl)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pbl, em, vm, true); if (con (&pb)->fg == LEVEL_DOOR || con (&pb)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pb, em, vm, true); if (con (&pbr)->fg == LEVEL_DOOR || con (&pbr)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pbr, em, vm, true); draw_confg_top (mr.cell[x][y].cache, &pbl, em, vm, true); draw_confg_top (mr.cell[x][y].cache, &pb, em, vm, true); draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true); draw_conbg (mr.cell[x][y].cache, p, em, vm, true); draw_confg_base (mr.cell[x][y].cache, &pr, em, vm); draw_confg_left (mr.cell[x][y].cache, &pr, em, vm, true); break; case CHPOS_BREAK_LOOSE_FLOOR: case CHPOS_BREAK_OPENER_FLOOR: case CHPOS_BREAK_CLOSER_FLOOR: case CHPOS_BREAK_LEVEL_DOOR: new_rect (&r, p->room, PLACE_WIDTH * p->place, PLACE_HEIGHT * p->floor + 35, 57, 31); clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR); if (con (&pbl)->fg == LEVEL_DOOR || con (&pbl)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pbl, em, vm, true); if (con (&pb)->fg == LEVEL_DOOR || con (&pb)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pb, em, vm, true); if (con (&pbr)->fg == LEVEL_DOOR || con (&pbr)->bg == BALCONY) draw_conbg (mr.cell[x][y].cache, &pbr, em, vm, true); draw_confg_top (mr.cell[x][y].cache, &pb, em, vm, true); draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true); draw_conbg (mr.cell[x][y].cache, p, em, vm, true); break; case CHPOS_OPEN_DOOR: case CHPOS_CLOSE_DOOR: case CHPOS_ABRUPTLY_CLOSE_DOOR: d = door_at_pos (p); int ch = 18 + d->i + 1; new_rect (&r, p->room, PLACE_WIDTH * (p->place + 1), PLACE_HEIGHT * p->floor - 6, 24, ch); clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR); draw_conbg (mr.cell[x][y].cache, p, em, vm, true); if (ch > PLACE_HEIGHT - 3) draw_confg_top (mr.cell[x][y].cache, &pb, em, vm, true); break; case CHPOS_OPEN_LEVEL_DOOR: new_rect (&r, p->room, PLACE_WIDTH * p->place + 7, PLACE_HEIGHT * p->floor - 1, 48, 51); clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR); draw_conbg (mr.cell[x][y].cache, p, em, vm, true); break; case CHPOS_SPIKES: new_rect (&r, p->room, PLACE_WIDTH * p->place + 7, PLACE_HEIGHT * p->floor + 34, 40, 24); clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR); draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true); draw_conbg (mr.cell[x][y].cache, p, em, vm, true); break; case CHPOS_CHOPPER: new_rect (&r, p->room, PLACE_WIDTH * p->place, PLACE_HEIGHT * p->floor + 3, 27, 60); clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR); draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true); draw_conbg (mr.cell[x][y].cache, p, em, vm, true); break; default: new_rect (&r, p->room, PLACE_WIDTH * p->place - 1, PLACE_HEIGHT * p->floor - 17, 2 * PLACE_WIDTH + 1, PLACE_HEIGHT + 3 + 17); clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR); for (p0.floor = p->floor + 1; p0.floor >= p->floor - 1; p0.floor--) for (p0.place = p->place - 2; p0.place <= p->place + 1; p0.place++) draw_conbg (mr.cell[x][y].cache, &p0, em, vm, true); break; } con_caching = false; goto end; } end:; /* if (is_room_visible (p->room)) printf ("%i,%i,%i\n", p->room, p->floor, p->place); */ bool depedv = ((em == DUNGEON && vm == VGA) || (em == DUNGEON && vm == EGA) || (em == PALACE && vm == EGA)); if (! recursive_01 && depedv && con (&pl)->fg == WALL) { recursive_01 = true; update_cache_pos (&pl, CHPOS_WALL, em, vm); recursive_01 = false; } if (! recursive && p->place == -1) { p0.room = roomd (&global_level, p->room, LEFT); p0.floor = p->floor; p0.place = PLACES - 1; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->floor == -1) { p0.room = roomd (&global_level, p->room, ABOVE); p0.floor = FLOORS - 1; p0.place = p->place; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->floor == 0) { p0.room = roomd (&global_level, p->room, ABOVE); p0.floor = FLOORS; p0.place = p->place; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->place == PLACES - 1) { p0.room = roomd (&global_level, p->room, RIGHT); p0.floor = p->floor; p0.place = -1; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->floor == FLOORS - 1) { p0.room = roomd (&global_level, p->room, BELOW); p0.floor = -1; p0.place = p->place; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->floor == -1 && p->place == -1) { p0.room = roomd (&global_level, p->room, ABOVE); p0.room = roomd (&global_level, p0.room, LEFT); p0.floor = FLOORS - 1; p0.place = PLACES - 1; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->floor == 0 && p->place == PLACES - 1) { p0.room = roomd (&global_level, p->room, ABOVE); p0.room = roomd (&global_level, p0.room, RIGHT); p0.floor = FLOORS; p0.place = -1; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->floor == -1 && p->place == PLACES - 1) { p0.room = roomd (&global_level, p->room, ABOVE); p0.room = roomd (&global_level, p0.room, RIGHT); p0.floor = FLOORS - 1; p0.place = -1; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->floor == FLOORS - 1 && p->place == -1) { p0.room = roomd (&global_level, p->room, LEFT); p0.room = roomd (&global_level, p0.room, BELOW); p0.floor = -1; p0.place = PLACES - 1; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } if (! recursive && p->floor == FLOORS - 1 && p->place == PLACES - 1) { p0.room = roomd (&global_level, p->room, BELOW); p0.room = roomd (&global_level, p0.room, RIGHT); p0.floor = -1; p0.place = -1; recursive = true; update_cache_pos (&p0, reason, em, vm); recursive = false; } /* if (is_room_visible (p->room) && ! recursive) printf ("----------------------------\n"); */ }
bool is_safe_to_follow (struct anim *k0, struct anim *k1, enum dir dir) { /* not aware of enemy position */ if (! is_valid_pos (&k0->enemy_pos)) return false; struct pos p0, p, p1, pke, pk; survey (_m, pos, &k0->f, NULL, &p0, NULL); survey ((k0->f.dir == LEFT) ? _mr : _ml, pos, &k1->f, NULL, &p1, NULL); pos2room (&p1, p0.room, &p1); /* not reachable, to start with */ if (p0.room != p1.room) return false; if (p0.floor > p1.floor) return false; /* the character went down after the enemy */ if (p0.floor != k0->enemy_pos.floor) { /* enum dir odir = (dir == LEFT) ? RIGHT : LEFT; */ /* if (is_on_back (k0, k1) && is_seeing (k0, k1, odir) */ /* && p0.floor == p1.floor) return true; */ if (is_anim_seeing (k0, k1, LEFT) || is_anim_seeing (k0, k1, RIGHT)) return true; return false; } /* if falling the chasing is inevitable (necessary to prevent leave_fight_logic from forgeting enemy based on the facing direction of the is_in_range check) */ if (is_anim_fall (&k0->f)) return true; if (dir == LEFT) { if (! is_safe_at_left (&p0)) return false; if (! is_safe_at_right (&k0->enemy_pos, &k0->f)) return false; if (peqr (&k0->enemy_pos, &p0, +0, -1)) return true; prel (&p0, &pk, +0, -1); prel (&k0->enemy_pos, &pke, +0, +1); if (is_collidable_at_right (&pk, &k0->f)) return false; } else { if (! is_safe_at_right (&p0, &k0->f)) return false; if (! is_safe_at_left (&k0->enemy_pos)) return false; if (peqr (&k0->enemy_pos, &p0, +0, +1)) return true; prel (&p0, &pk, +0, +1); prel (&k0->enemy_pos, &pke, +0, -1); if (is_collidable_at_right (&p0, &k0->f)) return false; } /* enemy went down */ if (is_traversable (&k0->enemy_pos)) { prel (&k0->enemy_pos, &pke, +1, +0); if (is_traversable (&pke) || fg (&pke) == SPIKES_FLOOR) return false; int d = (dir == LEFT) ? -1 : +1; if (peq (&pk, &k0->enemy_pos)) return true; prel (&k0->enemy_pos, &pke, +0, -1 * d); } else if (peq (&p0, &k0->enemy_pos) && ! (is_anim_seeing (k0, k1, LEFT) || is_anim_seeing (k0, k1, RIGHT))) return false; first_confg (&pk, &pke, dangerous_cs, &p); if (is_valid_pos (&p)) return false; first_confg (&pk, &pke, door_cs, &p); if (! is_valid_pos (&p)) return true; else return door_at_pos (&p)->action == OPEN_DOOR || ! is_collidable_at_right (&p, &k0->f); }
bool is_safe_at_right (struct pos *p, struct frame *f) { return ! is_collidable_at_right (p, f) || (fg (p) == DOOR && door_at_pos (p)->action == OPEN_DOOR); }