Esempio n. 1
0
void
draw_multi_rooms (void)
{
  int x, y;

  mr_map_rooms ();

  if (anim_cycle == 0) {
    generate_wall_colors_for_room (0, room0_wall_color);
  }

  if (em == PALACE && vm == VGA
      && (has_mr_view_changed ()
          || em != mr.last.em
          || vm != mr.last.vm))
    generate_wall_colors ();

  if (has_mr_view_changed ()) {
    generate_stars ();
    generate_mirrors_reflex ();
  }

  if (mouse_pos.room != mr.last.mouse_pos.room
      || mouse_pos.floor != mr.last.mouse_pos.floor
      || mouse_pos.place != mr.last.mouse_pos.place) {
    if (is_valid_pos (&mouse_pos))
      update_cache_pos (&mouse_pos, em, vm);
    if (is_valid_pos (&mr.last.mouse_pos))
      update_cache_pos (&mr.last.mouse_pos, em, vm);
  }

  if (anim_cycle == 0
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue) {
    update_room0_cache (em, vm);
  }

  if (anim_cycle == 0
      || has_mr_view_changed ()
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue
      || level.number != mr.last.level) {
    update_cache (em, vm);
  }

  size_t i;
  for (i = 0; i < changed_pos_nmemb; i++) {
    /* printf ("%i,%i,%i\n", changed_pos[i].room, changed_pos[i].floor, changed_pos[i].place); */
    update_cache_pos (&changed_pos[i], em, vm);
  }
  destroy_array ((void **) &changed_pos, &changed_pos_nmemb);

  clear_bitmap (screen, BLACK);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_background (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  if (! no_room_drawing) draw_bitmap (cache, screen, 0, 0, 0);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_foreground (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  if (mr.select_cycles > 0) {
    al_hold_bitmap_drawing (false);

    int x0 = ORIGINAL_WIDTH * mr.x;
    int y0 = ROOM_HEIGHT * mr.y + 3;
    int x1 = x0 + ORIGINAL_WIDTH;
    int y1 = y0 + ROOM_HEIGHT;
    draw_rectangle (screen, x0, y0, x1, y1, RED, 1);

    mr.select_cycles--;
  }

  mr.dx = mr.dy = -1;

  mr_update_last_settings ();
}
Esempio n. 2
0
void
update_cache_pos (struct pos *p, enum em em, enum vm vm)
{
  static bool recursive = false;

  int x, y;

  int room_view_bkp = room_view;

  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 pa; prel (p, &pa, -1, +0);
  struct pos pal; prel (p, &pal, -1, -1);
  struct pos par; prel (p, &par, -1, +1);

  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;

        int cx, cy, cw, ch;
        switch (con (p)->fg) {
        default:
          cx = PLACE_WIDTH * p->place;
          cy = PLACE_HEIGHT * p->floor - 10;
          cw = 2 * PLACE_WIDTH;
          ch = PLACE_HEIGHT + 3 + 10;
          break;
        }

        set_target_bitmap (mr.cell[x][y].cache);
        al_set_clipping_rectangle (cx, cy, cw, ch);
        al_clear_to_color (TRANSPARENT_COLOR);

        con_caching = true;

        draw_conbg (mr.cell[x][y].cache, &pbl, em, vm);
        draw_conbg (mr.cell[x][y].cache, &pb, em, vm);
        draw_conbg (mr.cell[x][y].cache, &pbr, em, vm);

        draw_conbg (mr.cell[x][y].cache, &pl, em, vm);
        draw_conbg (mr.cell[x][y].cache, p, em, vm);
        draw_conbg (mr.cell[x][y].cache, &pr, em, vm);

        draw_conbg (mr.cell[x][y].cache, &pal, em, vm);
        draw_conbg (mr.cell[x][y].cache, &pa, em, vm);
        draw_conbg (mr.cell[x][y].cache, &par, em, vm);

        draw_confg_right (mr.cell[x][y].cache, &pbl, em, vm, true);
        draw_confg_right (mr.cell[x][y].cache, &pb, em, vm, true);
        draw_confg_right (mr.cell[x][y].cache, &pl, em, vm, false);

        draw_confg (mr.cell[x][y].cache, p, em, vm, true);

        draw_confg_right (mr.cell[x][y].cache, &pal, em, vm, true);
        draw_confg (mr.cell[x][y].cache, &pa, em, vm, true);
        draw_confg_base (mr.cell[x][y].cache, &par, em, vm);
        draw_confg_left (mr.cell[x][y].cache, &par, em, vm, false);

        al_reset_clipping_rectangle ();
        al_hold_bitmap_drawing (false);
        con_caching = false;
      }

  /* printf ("%i,%i,%i\n", p->room, p->floor, p->place); */

  if (! recursive && p->place == -1) {
    struct pos p0;
    p0.room = roomd (p->room, LEFT);
    p0.floor = p->floor;
    p0.place = PLACES - 1;
    recursive = true;
    update_cache_pos (&p0, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == -1) {
    struct pos p0;
    p0.room = roomd (p->room, ABOVE);
    p0.floor = FLOORS - 1;
    p0.place = p->place;
    recursive = true;
    update_cache_pos (&p0, em, vm);
    recursive = false;
  }

  if (! recursive && p->place == PLACES - 1) {
    struct pos p0;
    p0.room = roomd (p->room, RIGHT);
    p0.floor = p->floor;
    p0.place = -1;
    recursive = true;
    update_cache_pos (&p0, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == FLOORS - 1) {
    struct pos p0;
    p0.room = roomd (p->room, BELOW);
    p0.floor = -1;
    p0.place = p->place;
    recursive = true;
    update_cache_pos (&p0, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == -1 && p->place == -1) {
    struct pos p0;
    p0.room = roomd (p->room, ABOVE);
    p0.room = roomd (p0.room, LEFT);
    p0.floor = FLOORS - 1;
    p0.place = PLACES - 1;
    recursive = true;
    update_cache_pos (&p0, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == -1 && p->place == PLACES - 1) {
    struct pos p0;
    p0.room = roomd (p->room, ABOVE);
    p0.room = roomd (p0.room, RIGHT);
    p0.floor = FLOORS - 1;
    p0.place = -1;
    recursive = true;
    update_cache_pos (&p0, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == FLOORS - 1 && p->place == -1) {
    struct pos p0;
    p0.room = roomd (p->room, LEFT);
    p0.room = roomd (p0.room, BELOW);
    p0.floor = -1;
    p0.place = PLACES - 1;
    recursive = true;
    update_cache_pos (&p0, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == FLOORS - 1 && p->place == PLACES - 1) {
    struct pos p0;
    p0.room = roomd (p->room, BELOW);
    p0.room = roomd (p0.room, RIGHT);
    p0.floor = -1;
    p0.place = -1;
    recursive = true;
    update_cache_pos (&p0, em, vm);
    recursive = false;
  }

  /* if (! recursive) printf ("----------------------------\n"); */

  room_view = room_view_bkp;
}
Esempio n. 3
0
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"); */
}
Esempio n. 4
0
void
draw_multi_rooms (void)
{
  int x, y;

  mr_set_origin (mr.room, mr.x, mr.y);

  bool mr_view_changed = has_mr_view_changed ();

  if (mr_view_changed) force_full_redraw = true;

  if (anim_cycle == 0) {
    generate_wall_colors_for_room (0, room0_wall_color);
  }

  if (em == PALACE && vm == VGA
      && (mr_view_changed
          || em != mr.last.em
          || vm != mr.last.vm))
    generate_wall_colors ();

  if (mr_view_changed)
    generate_stars ();

  if (mouse_pos.room != mr.last.mouse_pos.room
      || mouse_pos.floor != mr.last.mouse_pos.floor
      || mouse_pos.place != mr.last.mouse_pos.place) {
    if (is_valid_pos (&mouse_pos))
      update_cache_pos (&mouse_pos, CHPOS_MOUSE_SELECT, em, vm);
    if (is_valid_pos (&mr.last.mouse_pos))
      update_cache_pos (&mr.last.mouse_pos, CHPOS_MOUSE_DESELECT, em, vm);
  }

  if (anim_cycle == 0
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue) {
    update_room0_cache (em, vm);
    force_full_redraw = true;
  }

  if (anim_cycle == 0
      || mr_view_changed
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue
      || global_level.number != mr.last.level) {
    update_cache (em, vm);
  }

  size_t i;
  for (i = 0; i < changed_pos_nmemb; i++)
    update_cache_pos (&changed_pos[i].p, changed_pos[i].reason, em, vm);
  destroy_array ((void **) &changed_pos, &changed_pos_nmemb);

  for (i = 0; i < changed_room_nmemb; i++)
    update_cache_room (changed_room[i], em, vm);
  destroy_array ((void **) &changed_room, &changed_room_nmemb);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      clear_bitmap (mr.cell[x][y].screen, (mr.flicker > 0 && mr.flicker % 2)
                    ? mr.color : BLACK);

      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_background (mr.cell[x][y].screen,
                                mr.cell[x][y].room);
    }

  if (mr.flicker > 0) mr.flicker--;

  struct mr_room_list l;
  mr_get_room_list (&l);

  int xm, ym;
  if (! no_room_drawing)
    for (i = 0; i < l.nmemb; i++) {
      mr_coord (l.room[i], -1, &xm, &ym);
      for (y = mr.h - 1; y >= 0; y--)
        for (x = 0; x < mr.w; x++)
          if (mr.cell[x][y].room == l.room[i])
            draw_bitmap (mr.cell[xm][ym].cache,
                         mr.cell[x][y].screen, 0, 0, 0);
    }

  mr_destroy_room_list (&l);

  /* if (! no_room_drawing) */
  /*   for (y = mr.h - 1; y >= 0; y--) */
  /*     for (x = 0; x < mr.w; x++) */
  /*       if (mr.cell[x][y].room) */
  /*         draw_bitmap (mr.cell[x][y].cache, mr.cell[x][y].screen, 0, 0, 0); */

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_foreground (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  /* if (mr.select_cycles > 0) { */
  /*   int t = max_int (mr.w, mr.h); */
  /*   draw_rectangle (mr.cell[mr.x][mr.y].screen, 0, 3, */
  /*                   ORIGINAL_WIDTH - t, */
  /*                   3 + ROOM_HEIGHT - t, RED, t); */
  /*   mr.select_cycles--; */
  /* } */

  mr_update_last_settings ();
}
Esempio n. 5
0
void
draw_multi_rooms (void)
{
  int x, y;

  mr_set_origin (mr.room, mr.x, mr.y);

  bool mr_full_update = has_mr_view_changed ()
    || mr.full_update;

  if (mr_full_update) {
    mr_busy ();
    force_full_redraw = true;
  }

  if (anim_cycle == 0) {
    generate_wall_colors_for_room (0, room0_wall_color);
  }

  if (em == PALACE && vm == VGA
      && (mr_full_update
          || em != mr.last.em
          || vm != mr.last.vm))
    generate_wall_colors ();

  if (mouse_pos.room != mr.last.mouse_pos.room
      || mouse_pos.floor != mr.last.mouse_pos.floor
      || mouse_pos.place != mr.last.mouse_pos.place) {
    if (is_valid_pos (&mouse_pos))
      register_changed_pos (&mouse_pos);

    if (is_valid_pos (&mr.last.mouse_pos))
      register_changed_pos (&mr.last.mouse_pos);
  }

  if (anim_cycle == 0
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue) {
    update_room0_cache (em, vm);
    force_full_redraw = true;
  }

  size_t i;

  if (anim_cycle == 0
      || mr_full_update
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue
      || global_level.n != mr.last.level) {
    update_cache (em, vm);
  } else {
    bool depedv =
      ((em == DUNGEON && vm == VGA)
       || (em == DUNGEON && vm == EGA)
       || (em == PALACE && vm == EGA));

    /* optmize changed pos list */
    optimize_changed_pos ();

    /* update cache pos */
    for (i = 0; i < changed_pos_nmemb; i++) {
      update_cache_pos (&changed_pos[i], em, vm);
      struct pos pl; prel (&changed_pos[i], &pl, +0, -1);
      if (depedv && fake (&pl) == WALL)
        update_cache_pos (&pl, em, vm);
    }

    /* update cache room */
    for (i = 0; i < changed_room_nmemb; i++)
      update_cache_room (changed_room[i], em, vm);

    /* kept together so update_cache_pos and update_cache_room can
       access each other's arrays */
    destroy_array ((void **) &changed_pos, &changed_pos_nmemb);
    destroy_array ((void **) &changed_room, &changed_room_nmemb);
  }

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      clear_bitmap (mr.cell[x][y].screen, (mr.flicker > 0 && mr.flicker % 2)
                    ? mr.color : BLACK);

      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_background (mr.cell[x][y].screen,
                                mr.cell[x][y].room);
    }

  if (mr.flicker > 0) mr.flicker--;

  struct mr_room_list l;
  mr_get_room_list (&l);

  int xm, ym;
  if (! no_room_drawing)
    for (i = 0; i < l.nmemb; i++) {
      mr_coord (l.room[i], -1, &xm, &ym);
      for (y = mr.h - 1; y >= 0; y--)
        for (x = 0; x < mr.w; x++)
          if (mr.cell[x][y].room == l.room[i])
            draw_bitmap (mr.cell[xm][ym].cache,
                         mr.cell[x][y].screen, 0, 0, 0);
    }

  mr_destroy_room_list (&l);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_foreground (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  mr_update_last_settings ();
}