/* NetHack may be freely redistributed. See license for details. */ /* Copyright (c) Jaakko Peltonen, 2000 */ /* Copyright (c) Daniel Thaler, 2005 */ #include "vultures_win.h" #include "vultures_map.h" #include "vultures_gfl.h" #include "vultures_gametiles.h" #include "vultures_gra.h" #include "vultures_sdl.h" #include "vultures_main.h" #include "vultures_tile.h" #include "vultures_txt.h" #include "vultures_opt.h" #include "epri.h" /* lookat isn't in the nethack headers, but we use it here ... */ extern struct permonst * lookat(int, int, char *, char *); extern short glyph2tile[]; #define CMD_TRAVEL (char)0x90 #define META(c) (0x80 | (c)) /* the only other cmaps beside furniture that have significant height and * therefore need to be drawn as part of the second pass with the furniture. */ #define V_EXTRA_FURNITURE(typ) ((typ) == DOOR || \ (typ) == DBWALL || \ (typ) == IRONBARS || \ (typ) == TREE) /* minimap tile types */ enum { V_MMTILE_NONE, V_MMTILE_FLOOR, V_MMTILE_STAIRS, V_MMTILE_DOOR, V_MMTILE_YOU, V_MMTILE_PET, V_MMTILE_MONSTER, V_MMTILE_MAX }; /*---------------------------- * global variables *---------------------------- */ int vultures_view_x, vultures_view_y; /* Centre of displayed map area */ /* Map window contents, as Vulture's tile IDs */ static int ** vultures_map_glyph = NULL; /* real glyph representation of map */ static int ** vultures_map_back = NULL; /* background (floors, walls, pools, moats, ...) */ static int ** vultures_map_furniture = NULL; /* furniture (stairs, altars, fountains, ...) */ static int ** vultures_map_trap = NULL; /* traps */ static int ** vultures_map_obj = NULL; /* topmost object */ static int ** vultures_map_specialeff = NULL; /* special effects: zap, engulf, explode */ static int ** vultures_map_mon = NULL; /* monster tile ID */ static unsigned int ** vultures_map_specialattr = NULL; /* special attributes, we use them to highlight the pet */ static unsigned char ** vultures_map_deco = NULL; /* positions of murals and carpets */ static int vultures_map_swallow = V_TILE_NONE; /* the engulf tile, if any */ static SDL_Surface * vultures_map_symbols[V_MAX_MAP_SYMBOLS]; /* Map parchment symbols */ static char ** vultures_minimap_syms = NULL; static int * vultures_tilemap_special; static int * vultures_tilemap_engulf; /* pointer to full height, half height or transparent walltile array */ struct walls * walltiles = NULL; /* Map window contents, as Vulture's tiles */ static struct walls ** vultures_maptile_wall = NULL; /* Custom (combination) wall style for each square */ static struct fedges ** vultures_maptile_floor_edge = NULL; /* Custom floor edge style for each square */ static char ** vultures_map_tile_is_dark = NULL; static char ** vultures_room_indices = NULL; /* packed room numbers and deco ids */ static int vultures_map_clip_tl_x = 999999; static int vultures_map_clip_tl_y = 999999; static int vultures_map_clip_br_x = 0; static int vultures_map_clip_br_y = 0; int vultures_map_draw_msecs = 0; int vultures_map_draw_lastmove = 0; /*---------------------------- * pre-declared functions *---------------------------- */ static void vultures_init_floor_decors(int num_decors); static int vultures_get_floor_tile(int tile, int y, int x); static void vultures_get_floor_edges(int y, int x); static int vultures_get_room_index(int x, int y); static int vultures_get_wall_decor(int floortype, int wally, int wallx, int floory, int floorx); static int vultures_get_floor_decor(int floorstyle, int floory, int floorx); static void vultures_clear_floor_edges(int y, int x); static void vultures_get_wall_tiles(int y, int x); static int vultures_monster_to_tile(int mon_id, XCHAR_P x, XCHAR_P y); static char vultures_mappos_to_dirkey(point mappos); static void vultures_clear_walls(int y, int x); static void vultures_build_tilemap(void); static int vultures_remap_tile_id(int tile_id); /*---------------------------- * function implementations *---------------------------- */ /* Ordering of functions: * 1) initializer and destructor * - vultures_init_map * - vultures_destroy_map * * 2) drawing * - vultures_draw_level * - vultures_draw_map * - vultures_draw_minimap * - vultures_map_force_redraw * * 3) setting map data * - vultures_clear_map * - vultures_print_glyph * - vultures_clear_walls * - vultures_clear_floor_edges * * 4) Computing map data * - vultures_init_floor_decors * - vultures_get_wall_tiles * - vultures_get_floor_tile * - vultures_get_floor_edges * - vultures_get_room_index * - vultures_get_wall_decor * - vultures_get_floor_decor * * 5) Interface functions for windowing * - vultures_map_square_description * - vultures_mouse_to_map * - vultures_map_to_mouse * - vultures_get_map_action * - vultures_get_map_contextmenu * - vultures_perform_map_action * - vultures_get_map_cursor * * 6) misc utility functions * - vultures_object_to_tile * - vultures_monster_to_tile * - vultures_mappos_to_dirkey * - vultures_build_tilemap * - vultures_remap_tile_id */ /***************************************************************************** * 1) Initializer and destructor *****************************************************************************/ int vultures_init_map(void) { int i, j; SDL_Surface * image; /* select wall style */ switch (vultures_opts.wall_style) { case V_WALL_DISPLAY_STYLE_FULL: walltiles = (struct walls*)walls_full; break; case V_WALL_DISPLAY_STYLE_HALF_HEIGHT: walltiles = (struct walls*)walls_half; break; default: walltiles = (struct walls*)walls_half; break; } /* Initialize map */ vultures_map_glyph = malloc(V_MAP_HEIGHT * sizeof(int *)); vultures_map_back = malloc(V_MAP_HEIGHT * sizeof(int *)); vultures_map_obj = malloc(V_MAP_HEIGHT * sizeof(int *)); vultures_map_trap = malloc(V_MAP_HEIGHT * sizeof(int *)); vultures_map_furniture = malloc(V_MAP_HEIGHT * sizeof(int *)); vultures_map_specialeff = malloc(V_MAP_HEIGHT * sizeof(int *)); vultures_map_mon = malloc(V_MAP_HEIGHT * sizeof(int *)); vultures_map_specialattr = malloc(V_MAP_HEIGHT * sizeof(unsigned int**)); vultures_map_deco = malloc(V_MAP_HEIGHT * sizeof(unsigned char *)); vultures_maptile_wall = malloc(V_MAP_HEIGHT*sizeof(struct walls *)); vultures_maptile_floor_edge = malloc(V_MAP_HEIGHT*sizeof(struct fedges *)); vultures_map_tile_is_dark = malloc(V_MAP_HEIGHT*sizeof(char *)); vultures_room_indices = malloc(V_MAP_HEIGHT*sizeof(char *)); vultures_minimap_syms = malloc(V_MAP_HEIGHT*sizeof(char *)); if ((!vultures_map_back) || (!vultures_map_obj) || (!vultures_map_trap) || (!vultures_map_glyph) || (!vultures_map_furniture) || (!vultures_map_mon) || (!vultures_map_specialeff) || (!vultures_maptile_wall) || (!vultures_maptile_floor_edge) || (!vultures_map_deco) || (!vultures_map_specialattr) || (!vultures_room_indices)) vultures_bail("Out of memory"); for (i = 0; i < V_MAP_HEIGHT; i++) { vultures_map_glyph[i] = malloc(V_MAP_WIDTH * sizeof(int)); vultures_map_back[i] = malloc(V_MAP_WIDTH * sizeof(int)); vultures_map_obj[i] = malloc(V_MAP_WIDTH * sizeof(int)); vultures_map_trap[i] = malloc(V_MAP_WIDTH * sizeof(int)); vultures_map_furniture[i] = malloc(V_MAP_WIDTH * sizeof(int)); vultures_map_specialeff[i] = malloc(V_MAP_WIDTH * sizeof(int)); vultures_map_mon[i] = malloc(V_MAP_WIDTH * sizeof(int)); vultures_map_specialattr[i] = malloc(V_MAP_WIDTH * sizeof(unsigned int)); vultures_map_deco[i] = malloc(V_MAP_WIDTH * sizeof(unsigned char)); vultures_maptile_wall[i] = malloc(V_MAP_WIDTH*sizeof(struct walls)); vultures_maptile_floor_edge[i] = malloc(V_MAP_WIDTH*sizeof(struct fedges)); vultures_map_tile_is_dark[i] = malloc(V_MAP_WIDTH*sizeof(char)); vultures_room_indices[i] = malloc(V_MAP_WIDTH*sizeof(char)); vultures_minimap_syms[i] = malloc(V_MAP_WIDTH*sizeof(char)); if ((!vultures_map_back[i]) || (!vultures_map_obj[i]) || (!vultures_map_trap[i]) || (!vultures_map_furniture[i]) || (!vultures_map_mon[i]) || (!vultures_map_specialeff[i]) || (!vultures_maptile_wall[i]) || (!vultures_maptile_floor_edge[i]) || (!vultures_map_deco[i]) || (!vultures_map_specialattr[i]) || (!vultures_room_indices[i])) vultures_bail("Out of memory"); for (j = 0; j < V_MAP_WIDTH; j++) { vultures_map_glyph[i][j] = NO_GLYPH; vultures_map_back[i][j] = V_TILE_UNMAPPED_AREA; vultures_map_obj[i][j] = V_TILE_NONE; vultures_map_trap[i][j] = V_TILE_NONE; vultures_map_furniture[i][j] = V_TILE_NONE; vultures_map_specialeff[i][j] = V_TILE_NONE; vultures_map_mon[i][j] = V_TILE_NONE; vultures_map_specialattr[i][j] = 0; vultures_map_deco[i][j] = 0; vultures_room_indices[i][j] = 0; vultures_map_tile_is_dark[i][j] = 2; vultures_clear_walls(i,j); vultures_minimap_syms[i][j] = 0; } } vultures_view_x = V_MAP_WIDTH/2; vultures_view_y = V_MAP_HEIGHT/2; /* Load map symbols */ image = vultures_load_graphic(NULL, V_FILENAME_MAP_SYMBOLS); if (image == NULL) return 0; else { for (i = 0; i < V_MAX_MAP_SYMBOLS; i++) vultures_map_symbols[i] = vultures_get_img_src( (i%40)*VULTURES_MAP_SYMBOL_WIDTH, (i/40)*VULTURES_MAP_SYMBOL_HEIGHT, (i%40)*VULTURES_MAP_SYMBOL_WIDTH + (VULTURES_MAP_SYMBOL_WIDTH - 1), (i/40)*VULTURES_MAP_SYMBOL_HEIGHT+ (VULTURES_MAP_SYMBOL_HEIGHT - 1), image); SDL_FreeSurface(image); } /* build vultures_tilemap_special and vultures_tilemap_engulf */ vultures_build_tilemap(); return 1; } void vultures_destroy_map(void) { int i; for (i = 0; i < V_MAP_HEIGHT; i++) { free (vultures_map_glyph[i]); free (vultures_map_back[i]); free (vultures_map_obj[i]); free (vultures_map_trap[i]); free (vultures_map_furniture[i]); free (vultures_map_specialeff[i]); free (vultures_map_mon[i]); free (vultures_map_specialattr[i]); free (vultures_map_deco[i]); free (vultures_maptile_wall[i]); free (vultures_maptile_floor_edge[i]); free (vultures_map_tile_is_dark[i]); free (vultures_room_indices[i]); free(vultures_minimap_syms[i]); } free (vultures_map_glyph); free (vultures_map_back); free (vultures_map_obj); free (vultures_map_trap); free (vultures_map_furniture); free (vultures_map_specialeff); free (vultures_map_mon); free (vultures_map_specialattr); free (vultures_map_deco); free (vultures_maptile_wall); free (vultures_maptile_floor_edge); free (vultures_map_tile_is_dark); free (vultures_room_indices); free (vultures_minimap_syms); /* free the map symbols */ for (i = 0; i < V_MAX_MAP_SYMBOLS; i++) SDL_FreeSurface(vultures_map_symbols[i]); /* free nethack to vultures translation tables */ free (vultures_tilemap_special); free (vultures_tilemap_engulf); } /***************************************************************************** * 2) Drawing *****************************************************************************/ int vultures_draw_level(struct window * win) { int i, j, dir_idx; vultures_tile * cur_tile; int x, y; int tile_id; int map_tr_x, map_tr_y, __i, __j, diff, sum; int map_centre_x = win->w / 2; int map_centre_y = win->h / 2; unsigned long startticks = SDL_GetTicks(); static int cur_dlevel = -1; static int prev_cx = -1; static int prev_cy = -1; if (cur_dlevel != u.uz.dlevel) { vultures_init_floor_decors(10); cur_dlevel = u.uz.dlevel; } if (prev_cx != vultures_view_x || prev_cy != vultures_view_y || vultures_map_swallow != V_TILE_NONE) { vultures_map_clip_tl_x = win->abs_x; vultures_map_clip_tl_y = win->abs_y; vultures_map_clip_br_x = win->abs_x + win->w; vultures_map_clip_br_y = win->abs_y + win->h; } else { vultures_map_clip_tl_x = vultures_map_clip_tl_x >= 0 ? vultures_map_clip_tl_x : 0; vultures_map_clip_tl_y = vultures_map_clip_tl_y >= 0 ? vultures_map_clip_tl_y : 0; vultures_map_clip_br_x = (vultures_map_clip_br_x < win->abs_x + win->w) ? vultures_map_clip_br_x : win->abs_x + win->w - 1; vultures_map_clip_br_y = (vultures_map_clip_br_y < win->abs_y + win->h) ? vultures_map_clip_br_y : win->abs_y + win->h - 1; } if (vultures_map_clip_tl_x >= win->w + win->abs_x || vultures_map_clip_tl_y >= win->h + win->abs_y) /* nothing changed onscreen */ return 1; prev_cx = vultures_view_x; prev_cy = vultures_view_y; /* Only draw on map area */ vultures_set_draw_region(vultures_map_clip_tl_x, vultures_map_clip_tl_y, vultures_map_clip_br_x, vultures_map_clip_br_y); /* If swallowed draw ONLY the engulf tile and the player! */ if (u.uswallow && vultures_map_swallow != V_TILE_NONE) { /* Clear map area */ SDL_FillRect(vultures_screen, NULL, CLR32_BLACK); x = map_centre_x + V_MAP_XMOD*(u.ux - u.uy + vultures_view_y - vultures_view_x); y = map_centre_y + V_MAP_YMOD*(u.ux + u.uy - vultures_view_y - vultures_view_x); /* engulf tile */ vultures_put_tile(x, y, vultures_map_swallow); /* player */ vultures_put_tile(x, y, vultures_map_mon[u.uy][u.ux]); vultures_invalidate_region(vultures_map_clip_tl_x, vultures_map_clip_tl_y, vultures_map_clip_br_x - vultures_map_clip_tl_x, vultures_map_clip_br_y - vultures_map_clip_tl_y); return 1; } else vultures_map_swallow = V_TILE_NONE; /* coords of the top right corner */ map_tr_x = (-V_MAP_YMOD * (map_centre_x + 50) + V_MAP_XMOD * (map_centre_y + 50) + V_MAP_XMOD * V_MAP_YMOD) / (2 * V_MAP_XMOD * V_MAP_YMOD); map_tr_y = (V_MAP_YMOD * (map_centre_x + 50) + V_MAP_XMOD * (map_centre_y + 50) + V_MAP_XMOD * V_MAP_YMOD) / (2 * V_MAP_XMOD * V_MAP_YMOD); /* without the +-1 small corners within the viewport are not drawn */ diff = map_tr_x - map_tr_y - 1; sum = map_tr_x + map_tr_y + 1; for (__i = - map_tr_y; __i <= map_tr_y; __i++) { i = vultures_view_y + __i; for (__j = diff + __i; __j + __i <= sum; __j++) { j = vultures_view_x + __j; x = map_centre_x + V_MAP_XMOD*(__j - __i); y = map_centre_y + V_MAP_YMOD*(__j + __i); if (j < 1 || j >= V_MAP_WIDTH || i < 0 || i >= V_MAP_HEIGHT) { vultures_put_tile(x, y, V_TILE_OFF_MAP); continue; } /* Draw Vulture's tiles, in order: pass 1 1. Floor 2. Floor edges pass 2 1. North & west walls 2. Furniture 3. Traps 4. Objects 5. Monsters 6. Effects 7. South & east walls */ /* 0. init walls and floor edges for this tile*/ if (vultures_map_back[i][j] == V_TILE_WALL_GENERIC || vultures_map_back[i][j] == V_TILE_UNMAPPED_AREA) vultures_get_wall_tiles(i, j); else /* certain events (amnesia or a secret door being discovered) * require us to clear walls again. since we cannot check for those cases * we simply clear walls whenever we don't set any... */ vultures_clear_walls(i, j); if (vultures_map_back[i][j] == V_TILE_FLOOR_WATER || vultures_map_back[i][j] == V_TILE_FLOOR_ICE || vultures_map_back[i][j] == V_TILE_FLOOR_LAVA || vultures_map_back[i][j] == V_TILE_FLOOR_AIR) /* these tiles get edges */ vultures_get_floor_edges(i, j); else /* everything else doesn't. However we can't just assume a tile that doesn't need egdes doesn't have any: * pools may be dried out by fireballs, and suddenly we have a pit with edges :( * Therefore we always clear them explicitly */ vultures_clear_floor_edges(i ,j); /* 2. Floor */ tile_id = vultures_map_back[i][j]; if ((tile_id >= V_TILE_FLOOR_COBBLESTONE) && (tile_id <= V_TILE_FLOOR_DARK)) tile_id = vultures_get_floor_tile(tile_id, i, j) + vultures_map_tile_is_dark[i][j] * GAMETILECOUNT; else if (tile_id == V_TILE_WALL_GENERIC) tile_id = V_TILE_UNMAPPED_AREA; vultures_put_tile(x, y, tile_id); /* shortcut for unmapped case */ if (tile_id == V_TILE_UNMAPPED_AREA) continue; /* 3. Floor edges */ for (dir_idx = 0; dir_idx < 12; dir_idx++) vultures_put_tile(x, y, vultures_maptile_floor_edge[i][j].dir[dir_idx]); } } for (__i = - map_tr_y; __i <= map_tr_y; __i++) { i = vultures_view_y + __i; if (i < 0 || i >= V_MAP_HEIGHT) continue; for (__j = diff + __i; __j + __i <= sum; __j++) { j = vultures_view_x + __j; if (j < 1 || j >= V_MAP_WIDTH) continue; /* Find position of tile centre */ x = map_centre_x + V_MAP_XMOD*(__j - __i); y = map_centre_y + V_MAP_YMOD*(__j + __i); /* 1. West and north walls */ if (j > 1) vultures_put_tile(x, y, vultures_maptile_wall[i][j].west + vultures_map_tile_is_dark[i][j-1] * GAMETILECOUNT); if (i > 1) vultures_put_tile(x, y, vultures_maptile_wall[i][j].north + vultures_map_tile_is_dark[i-1][j] * GAMETILECOUNT); /* shortcut for unmapped case */ if (vultures_map_back[i][j] != V_TILE_UNMAPPED_AREA || vultures_map_obj[i][j] != V_TILE_NONE) { /* 2. Furniture*/ vultures_put_tile(x, y, vultures_map_furniture[i][j]); /* 3. Traps */ vultures_put_tile(x, y, vultures_map_trap[i][j]); /* 4. Objects */ vultures_put_tile(x, y, vultures_map_obj[i][j]); /* 5. Monsters */ if ((cur_tile = vultures_get_tile(vultures_map_mon[i][j])) != NULL) { vultures_put_tile(x, y, vultures_map_mon[i][j]); if (iflags.hilite_pet && (vultures_map_specialattr[i][j] & MG_PET)) vultures_put_img(x + cur_tile->xmod, y + cur_tile->ymod - 10, vultures_get_tile(V_TILE_HILITE_PET)->graphic); } /* 6. Effects */ vultures_put_tile(x, y, vultures_map_specialeff[i][j]); } /* 7. South & East walls */ if (i < V_MAP_HEIGHT - 1) vultures_put_tile(x, y, vultures_maptile_wall[i][j].south + vultures_map_tile_is_dark[i+1][j] * GAMETILECOUNT); if (j < V_MAP_WIDTH - 1) vultures_put_tile(x, y, vultures_maptile_wall[i][j].east + vultures_map_tile_is_dark[i][j+1] * GAMETILECOUNT); } } /* Restore drawing region */ vultures_set_draw_region(0, 0, vultures_screen->w-1, vultures_screen->h-1); vultures_invalidate_region(vultures_map_clip_tl_x, vultures_map_clip_tl_y, vultures_map_clip_br_x - vultures_map_clip_tl_x, vultures_map_clip_br_y - vultures_map_clip_tl_y); vultures_map_clip_tl_x = 999999; vultures_map_clip_tl_y = 999999; vultures_map_clip_br_x = 0; vultures_map_clip_br_y = 0; vultures_flip_tile_arrays(); vultures_map_draw_msecs = SDL_GetTicks() - startticks; vultures_map_draw_lastmove = moves; return 1; } int vultures_draw_map(struct window * win) { int map_x, map_y; int i, j; struct window * txt = win->first_child; /* Draw parchment */ vultures_put_img(win->abs_x, win->abs_y, win->pd.image); /* Draw the level name */ #ifdef VULTURESCLAW describe_level(txt->caption, TRUE); #else if (!describe_level(txt->caption)) sprintf(txt->caption, "%s, level %d ", dungeons[u.uz.dnum].dname, depth(&u.uz)); #endif txt->x = (win->w - vultures_text_length(V_FONT_HEADLINE, txt->caption)) / 2; txt->abs_x = win->abs_x + txt->x; txt->abs_y = win->abs_y + txt->y; vultures_put_text_shadow(V_FONT_HEADLINE, txt->caption, vultures_screen, txt->abs_x, txt->abs_y, CLR32_BROWN, CLR32_BLACK_A50); /* Find upper left corner of map on parchment */ map_x = win->abs_x + 39; map_y = win->abs_y + 91; /* Draw map on parchment, and create hotspots */ for (i = 0; i < V_MAP_HEIGHT; i++) for (j = 1; j < V_MAP_WIDTH; j++) { if (vultures_map_glyph[i][j] != NO_GLYPH && (vultures_map_glyph[i][j] != cmap_to_glyph(S_stone) || (level.locations[j][i].seenv && vultures_map_tile_is_dark[i][j] == 2))) { vultures_put_img( map_x+VULTURES_MAP_SYMBOL_WIDTH*j, map_y+VULTURES_MAP_SYMBOL_HEIGHT*i, vultures_map_symbols[glyph2tile[vultures_map_glyph[i][j]]]); } } vultures_invalidate_region(win->abs_x, win->abs_y, win->w, win->h); return 0; } int vultures_draw_minimap(struct window * win) { int map_x, map_y, sym; Uint32 * pixels; SDL_Rect destrect = {0, 0, 3, 2}; Uint32 minimap_colors[V_MMTILE_MAX] = {CLR32_BLACK, V_COLOR_MINI_FLOOR, V_COLOR_MINI_STAIRS, V_COLOR_MINI_DOOR, V_COLOR_MINI_YOU, CLR32_GREEN, CLR32_RED}; if (!win->pd.image) return 0; if (win->background) vultures_put_img(win->abs_x, win->abs_y, win->background); for (map_y = 0; map_y < V_MAP_HEIGHT; map_y++) { for (map_x = 1; map_x < V_MAP_WIDTH; map_x++) { /* translate the contents of the map into a minimap symbol color */ switch(vultures_map_back[map_y][map_x]) { case V_TILE_WALL_GENERIC: case V_TILE_UNMAPPED_AREA: sym = V_MMTILE_NONE; break; default: sym = V_MMTILE_FLOOR; break; } switch(vultures_map_furniture[map_y][map_x]) { case V_TILE_STAIRS_UP: case V_TILE_STAIRS_DOWN: sym = V_MMTILE_STAIRS; break; case V_TILE_VDOOR_WOOD_OPEN: case V_TILE_VDOOR_WOOD_CLOSED: case V_TILE_HDOOR_WOOD_OPEN: case V_TILE_HDOOR_WOOD_CLOSED: case V_TILE_VODBRIDGE: case V_TILE_HODBRIDGE: case V_TILE_VCDBRIDGE: case V_TILE_HCDBRIDGE: sym = V_MMTILE_DOOR; break; } if (vultures_map_trap[map_y][map_x] == V_TILE_MAGIC_PORTAL) sym = V_MMTILE_STAIRS; if (vultures_map_mon[map_y][map_x] != V_TILE_NONE) { if (vultures_map_specialattr[map_y][map_x] & MG_PET) sym = V_MMTILE_PET; else sym = V_MMTILE_MONSTER; } if ((map_y == u.uy) && (map_x == u.ux)) sym = V_MMTILE_YOU; /* draw symbols that changed onto the "minimap surface" */ if (sym != vultures_minimap_syms[map_y][map_x]) { vultures_minimap_syms[map_y][map_x] = sym; destrect.x = 40 + 2*map_x - 2*map_y; destrect.y = map_x + map_y; pixels = win->pd.image->pixels + win->pd.image->pitch * (destrect.y+6) + (destrect.x+6) * 4; /* A minimap symbol has this shape: _ C _ * C C C * where "_" is transparent and "C" is a colored pixel */ /* row 1: */ /* pixels[0] = transparent -> dont write */ pixels[1] = minimap_colors[sym]; /* pixels[2] = transparent -> dont write */ /* row 2 */ pixels = win->pd.image->pixels + win->pd.image->pitch * (destrect.y+7) + (destrect.x+6) * 4; pixels[0] = minimap_colors[sym]; pixels[1] = minimap_colors[sym]; pixels[2] = minimap_colors[sym]; } } } vultures_put_img(win->abs_x, win->abs_y, win->pd.image); vultures_invalidate_region(win->abs_x, win->abs_y, win->w, win->h); return 0; } void vultures_map_force_redraw(void) { struct window * win = vultures_get_window(0); win->need_redraw = 1; vultures_map_clip_tl_x = 0; vultures_map_clip_tl_y = 0; vultures_map_clip_br_x = win->w; vultures_map_clip_br_y = win->h; } /***************************************************************************** * 3) Setting map data *****************************************************************************/ void vultures_clear_map() { int i, j; for (i = 0; i < V_MAP_HEIGHT; i++) for (j = 0; j < V_MAP_WIDTH; j++) { vultures_map_tile_is_dark[i][j] = 2; /* ideally this is what we'd do to clear background: * vultures_map_back[i][j] = V_TILE_UNMAPPED_AREA; * unfortunately doing so breaks dark tiles in rooms... */ vultures_print_glyph(0, j, i, cmap_to_glyph(S_stone)); vultures_map_trap[i][j] = V_TILE_NONE; vultures_map_furniture[i][j] = V_TILE_NONE; vultures_map_obj[i][j] = V_TILE_NONE; vultures_map_mon[i][j] = V_TILE_NONE; vultures_map_specialeff[i][j] = V_TILE_NONE; vultures_map_specialattr[i][j] = 0; vultures_map_glyph[i][j] = cmap_to_glyph(S_stone); vultures_clear_floor_edges(i, j); vultures_clear_walls(i, j); } } static void vultures_set_map_data(int ** data_array, int x, int y, int newval, int force) { int pixel_x, pixel_y; int tl_x, tl_y, br_x, br_y; int oldval = vultures_remap_tile_id(data_array[y][x]); int tmp_newval = vultures_remap_tile_id(newval); struct window * map = vultures_get_window(0); if (data_array[y][x] != newval || force) { data_array[y][x] = newval; pixel_x = (map->w / 2) + V_MAP_XMOD*(x - y + vultures_view_y - vultures_view_x); pixel_y = (map->h / 2) + V_MAP_YMOD*(x + y - vultures_view_y - vultures_view_x); if (data_array != vultures_map_back) { tl_x = (vultures_gametiles[tmp_newval].hs_x < vultures_gametiles[oldval].hs_x) ? vultures_gametiles[tmp_newval].hs_x : vultures_gametiles[oldval].hs_x; tl_x += pixel_x; tl_y = (vultures_gametiles[tmp_newval].hs_y < vultures_gametiles[oldval].hs_y) ? vultures_gametiles[tmp_newval].hs_y : vultures_gametiles[oldval].hs_y; tl_y += pixel_y; br_x = pixel_x + V_MAX_TILE_XOFFS; br_y = pixel_y + V_MAX_TILE_YOFFS; if (data_array == vultures_map_mon) /* allow for the heart icon on pets */ tl_y -= 10; } else { /* floor tiles tend to be placeholders until we reach draw_level, so we do this manually */ tl_x = pixel_x - 56; tl_y = pixel_y - 100; /* 100 pixels accounts for possible walls, too */ br_x = pixel_x + 56; br_y = pixel_y + 22; } vultures_map_clip_tl_x = (vultures_map_clip_tl_x < tl_x) ? vultures_map_clip_tl_x : tl_x; vultures_map_clip_tl_y = (vultures_map_clip_tl_y < tl_y) ? vultures_map_clip_tl_y : tl_y; vultures_map_clip_br_x = (vultures_map_clip_br_x > br_x) ? vultures_map_clip_br_x : br_x; vultures_map_clip_br_y = (vultures_map_clip_br_y > br_y) ? vultures_map_clip_br_y : br_y; } } void vultures_print_glyph(winid window, XCHAR_P x, XCHAR_P y, int glyph) { struct obj *obj; struct trap *trap; int character, colour; int memglyph; /* if we're blind, we also need to print what we remember under us */ if (!cansee(x,y) && x == u.ux && y == u.uy) { #ifdef DISPLAY_LAYERS memglyph = memory_glyph(x,y); #else memglyph = level.locations[x][y].glyph; #endif if (glyph != memglyph) vultures_print_glyph(window, x, y, memglyph); } int map_mon = vultures_map_mon[y][x]; int map_obj = vultures_map_obj[y][x]; int map_trap = vultures_map_trap[y][x]; int map_back = vultures_map_back[y][x]; int map_special = V_TILE_NONE; int map_furniture = vultures_map_furniture[y][x]; int darkness = vultures_map_tile_is_dark[y][x]; vultures_map_glyph[y][x]=glyph; /* check wether we are swallowed, if so, return, because nothing but the swallow graphic will be drawn anyway */ if (glyph_is_swallow(glyph)) { /* we only SET vultures_map_swallow here; we expect vultures_draw_level to reset it */ vultures_map_swallow = vultures_tilemap_engulf[(glyph-GLYPH_SWALLOW_OFF) >> 3]; return; } /* Nethack will only show us one glyph per position. We need up to 4 "things" per mapsquare: * monsters, objects, traps & furniture, floor & walls. * Therefore we rely on the glyph only for monsters (which are never covered) and magical vision * where we can't just display eg the object a telepathically seen monster is standing on, * because that would be cheating. */ if (cansee(x,y)) { /* various special effects, these occur only during the player's turn and should be * layered on top of everything else */ if (glyph >= GLYPH_ZAP_OFF && glyph < GLYPH_WARNING_OFF) map_special = vultures_tilemap_special[S_vbeam + ((glyph - GLYPH_ZAP_OFF) & 0x03)]; else if (glyph >= GLYPH_EXPLODE_OFF && glyph < GLYPH_ZAP_OFF) map_special = EXPTILEOFFSET + (glyph - GLYPH_EXPLODE_OFF); else if (glyph_to_cmap(glyph) >= S_digbeam && glyph_to_cmap(glyph) <= S_ss4) /* digbeam, camera flash, boomerang, magic resistance: these are not floor tiles ... */ map_special = vultures_tilemap_special[glyph_to_cmap(glyph)]; /* We rely on the glyph for monsters, as they are never covered by anything * at the start of the turn and dealing with them manually is ugly */ if (glyph_is_monster(glyph)) { /* we need special attributes, so that we can highlight the pet */ mapglyph(glyph, &character, &colour, &vultures_map_specialattr[y][x], x, y); map_mon = vultures_monster_to_tile(glyph_to_mon(glyph), x, y); } /* however they may be temporarily obscured by magic effects... */ else if (map_special == V_TILE_NONE) map_mon = V_TILE_NONE; /* visible objects that are not covered by lava */ if ((obj = vobj_at(x,y)) && !covers_objects(x,y)) { /* glyph_to_obj(obj_to_glyph(foo)) looks like nonsense, but is actually an elegant * way of handling hallucination, especially the complicated matter of hallucinated * corpses... */ map_obj = vultures_object_to_tile(glyph_to_obj(obj_to_glyph( obj)), x, y); } /* just to make things interesting, the above does not handle thrown/kicked objects... */ else if (glyph_is_object(glyph)) { map_obj = vultures_object_to_tile(glyph_to_obj(glyph), x, y); } else map_obj = V_TILE_NONE; /* traps that are not covered by lava and have been seen */ if ((trap = t_at(x,y)) && !covers_traps(x,y) && trap->tseen) { /* what_trap handles hallucination */ map_trap = vultures_tilemap_special[what_trap(trap->ttyp) + S_arrow_trap - 1]; } else map_trap = V_TILE_NONE; /* handle furniture: altars, stairs,... * furniture is separated out from walls and floors, so that it can be used on any * type of floor, rather than producing a discolored blob*/ if (glyph_to_cmap(glyph) >= S_upstair && glyph_to_cmap(glyph) <= S_fountain) { /* this is a mimic pretending to be part of the dungeon */ map_furniture = vultures_tilemap_special[glyph_to_cmap(glyph)]; map_back = V_TILE_FLOOR_COBBLESTONE; } else if (IS_FURNITURE(level.locations[x][y].typ)) { map_furniture = vultures_tilemap_special[glyph_to_cmap(back_to_glyph(x,y))]; /* furniture is only found in rooms, so set the background type */ map_back = V_TILE_FLOOR_COBBLESTONE; } else if (glyph_to_cmap(glyph) >= S_ndoor && glyph_to_cmap(glyph) <= S_tree) { /* this is a mimic pretending to be part of the dungeon */ map_furniture = vultures_tilemap_special[glyph_to_cmap(glyph)]; map_back = V_TILE_FLOOR_ROUGH; } else if (V_EXTRA_FURNITURE(level.locations[x][y].typ)) { /* this stuff is not furniture, but we need to draw it at the same time, * so we pack it in with the furniture ...*/ map_furniture = vultures_tilemap_special[glyph_to_cmap(back_to_glyph(x,y))]; map_back = V_TILE_FLOOR_ROUGH; } else { map_furniture = V_TILE_NONE; map_back = vultures_tilemap_special[glyph_to_cmap(back_to_glyph(x,y))]; if (map_special == V_TILE_NONE && glyph_to_cmap(glyph) == S_cloud && back_to_glyph(x,y) != glyph) map_special = V_TILE_STINKING_CLOUD; } /* physically seen tiles cannot be dark */ vultures_map_tile_is_dark[y][x] = 0; } /* location seen via some form of magical vision OR * when a save is restored*/ else { /* if we can see a monster here, it will be re-shown explicitly */ map_mon = V_TILE_NONE; /* need to clear special effect explicitly here: * if we just got blinded by lightnig, the beam will remain onscreen otherwise */ map_special = V_TILE_NONE; /* monsters */ if (glyph_is_monster(glyph)) { mapglyph(glyph, &character, &colour, &vultures_map_specialattr[y][x], x, y); map_mon = vultures_monster_to_tile(glyph_to_mon(glyph), x, y); /* if seen telepathically in an unexplored area, it might not have a floor */ if (map_back == V_TILE_UNMAPPED_AREA && level.locations[x][y].typ != STONE) map_back = V_TILE_FLOOR_NOT_VISIBLE; } /* handle invisible monsters */ else if (glyph_is_invisible(glyph)) { mapglyph(glyph, &character, &colour, &vultures_map_specialattr[y][x], x, y); map_mon = V_TILE_INVISIBLE_MONSTER; } /* handle monsters you are warned of */ else if (glyph_is_warning(glyph)) { map_mon = V_TILE_WARNLEV_1 + glyph_to_warning(glyph); if (map_back == V_TILE_UNMAPPED_AREA && level.locations[x][y].typ != STONE) map_back = V_TILE_FLOOR_NOT_VISIBLE; } /* same as above, for objects */ else if (glyph_is_object(glyph)) { map_obj = vultures_object_to_tile(glyph_to_obj(glyph), x, y); if (map_back == V_TILE_UNMAPPED_AREA && level.locations[x][y].typ != STONE) map_back = V_TILE_FLOOR_NOT_VISIBLE; } /* traps are not seen magically (I think?), so this only triggers when loading a level */ else if (glyph_is_trap(glyph)) { map_trap = vultures_tilemap_special[glyph_to_cmap(glyph)]; if (map_back == V_TILE_UNMAPPED_AREA) map_back = V_TILE_FLOOR_NOT_VISIBLE; } else if (glyph_is_cmap(glyph)) { /* Nethack shows us the cmaps, therefore there are no traps or objects here */ map_obj = V_TILE_NONE; map_trap = V_TILE_NONE; /* IS_FURNITURE() may be true while the cmap is S_stone for dark rooms */ if (IS_FURNITURE(level.locations[x][y].typ) && glyph_to_cmap(glyph) != S_stone) { map_furniture = vultures_tilemap_special[glyph_to_cmap(glyph)]; map_back = V_TILE_FLOOR_COBBLESTONE; } else if (V_EXTRA_FURNITURE(level.locations[x][y].typ) && glyph_to_cmap(glyph) != S_stone) { /* V_EXTRA_FURNITURE = doors, drawbridges, iron bars * that stuff is not furniture, but we need to draw it at the same time, * so we pack it in with the furniture ...*/ map_furniture = vultures_tilemap_special[glyph_to_cmap(back_to_glyph(x,y))]; map_back = V_TILE_FLOOR_ROUGH; } else { map_furniture = V_TILE_NONE; map_back = vultures_tilemap_special[glyph_to_cmap(glyph)]; } } /* When a save is restored, we are shown a number of glyphs for objects, traps, etc * whose background we actually know and can display, even though we can't physically see it*/ if (level.locations[x][y].seenv != 0 && map_back == V_TILE_FLOOR_NOT_VISIBLE) { if (IS_FURNITURE(level.locations[x][y].typ)) { map_furniture = vultures_tilemap_special[glyph_to_cmap(back_to_glyph(x,y))]; /* furniture is only found in rooms, so set the background type */ map_back = V_TILE_FLOOR_COBBLESTONE; } else if (V_EXTRA_FURNITURE(level.locations[x][y].typ)) { /* this stuff is not furniture, but we need to draw it at the same time, * so we pack it in with the furniture ...*/ map_furniture = vultures_tilemap_special[glyph_to_cmap(back_to_glyph(x,y))]; map_back = V_TILE_FLOOR_ROUGH; } else { map_furniture = V_TILE_NONE; map_back = vultures_tilemap_special[glyph_to_cmap(back_to_glyph(x,y))]; } } /* handle unlit room tiles; until now we were assuming them to be lit; whereas tiles * converted via vultures_tilemap_special are currently V_TILE_NONE */ if ( ((!level.locations[x][y].waslit) && map_back == V_TILE_FLOOR_COBBLESTONE) || (level.locations[x][y].typ == ROOM && map_back == V_TILE_UNMAPPED_AREA && level.locations[x][y].seenv)) { map_back = V_TILE_FLOOR_COBBLESTONE; vultures_map_tile_is_dark[y][x] = 2; } else vultures_map_tile_is_dark[y][x] = 1; } /* if the lightlevel changed, we need to force the tile to be updated */ int force_update = (darkness != vultures_map_tile_is_dark[y][x]); /* fix drawbriges, so they don't start in the middle of the moat when they're open */ /* horizontal drawbridges */ if (level.locations[x][y].typ == 22 && level.locations[x-1][y].typ == DRAWBRIDGE_DOWN && level.locations[x-1][y].seenv) { map_furniture = V_TILE_HODBRIDGE; switch (level.locations[x][y].drawbridgemask & DB_UNDER) { case DB_MOAT: vultures_set_map_data(vultures_map_back, x-1, y, vultures_tilemap_special[S_pool], force_update); break; case DB_LAVA: vultures_set_map_data(vultures_map_back, x-1, y, vultures_tilemap_special[S_lava], force_update); break; case DB_ICE: vultures_set_map_data(vultures_map_back, x-1, y, vultures_tilemap_special[S_ice], force_update); break; case DB_FLOOR: vultures_set_map_data(vultures_map_back, x-1, y, vultures_tilemap_special[S_room], force_update); break; } } /* vertical drawbridges */ if (level.locations[x][y].typ == 22 && level.locations[x][y-1].typ == DRAWBRIDGE_DOWN && level.locations[x][y-1].seenv) { map_furniture = V_TILE_VODBRIDGE; switch (level.locations[x][y].drawbridgemask & DB_UNDER) { case DB_MOAT: vultures_set_map_data(vultures_map_back, x, y-1, vultures_tilemap_special[S_pool], force_update); break; case DB_LAVA: vultures_set_map_data(vultures_map_back, x, y-1, vultures_tilemap_special[S_lava], force_update); break; case DB_ICE: vultures_set_map_data(vultures_map_back, x, y-1, vultures_tilemap_special[S_ice], force_update); break; case DB_FLOOR: vultures_set_map_data(vultures_map_back, x, y-1, vultures_tilemap_special[S_room], force_update); break; } } /* write new map data */ vultures_set_map_data(vultures_map_mon, x, y, map_mon, force_update); vultures_set_map_data(vultures_map_obj, x, y, map_obj, force_update); vultures_set_map_data(vultures_map_trap, x, y, map_trap, force_update); vultures_set_map_data(vultures_map_specialeff, x, y, map_special, force_update); vultures_set_map_data(vultures_map_furniture, x, y, map_furniture, force_update); vultures_set_map_data(vultures_map_back, x, y, map_back, force_update); } static void vultures_clear_walls(int y, int x) { vultures_maptile_wall[y][x].west = V_TILE_NONE; vultures_maptile_wall[y][x].north = V_TILE_NONE; vultures_maptile_wall[y][x].east = V_TILE_NONE; vultures_maptile_wall[y][x].south = V_TILE_NONE; } static void vultures_clear_floor_edges(int y, int x) { int i; for (i = 0; i < 12; i++) vultures_maptile_floor_edge[y][x].dir[i] = V_TILE_NONE; } /***************************************************************************** * 4) Computing map data *****************************************************************************/ static void vultures_init_floor_decors(int num_decors) { int i, j, k; int lx, ly; if (!nroom) return; /* the level doesn't have distinct rooms, so do nothing */ /* after putting a decor in room roomno, we calculate (roomno + 5) modulo nroom. * (nroom is the global containing the number of rooms on the level) */ int roomno = 0; /* when roomno wraps we also add wrapadd, to ensure that a different bunch of rooms gets the next few decorations * this will distibute decorations seemingly at random but repeatably throughout the level * (rooms are sorted from left to right, so a step of 1 would leave most decorations on the left side)*/ int wrapadd = (nroom % 5) ? 0 : 1; /* if placing a decor fails, try at most retries other rooms */ int retries; /* did we manage to place the deco? */ int placed; int old_deco, old_deco2; int deco_height; int deco_width; int xoffset, yoffset; int current_deco = V_FLOOR_CARPET; /* reset the room indices and map decor arrays */ for (i = 0; i < V_MAP_HEIGHT; i++) { memset(vultures_room_indices[i], 0, V_MAP_WIDTH); memset(vultures_map_deco[i], 0, V_MAP_WIDTH); } /* init room indices */ for (i = 0; i < nroom; i++) for (j = rooms[i].ly; j <= rooms[i].hy; j++) memset(&vultures_room_indices[j][rooms[i].lx], (i+1), (rooms[i].hx-rooms[i].lx+1)); /* do no more if we're on the rogue level or in the mines, because decors there look dumb */ #ifdef REINCARNATION if (Is_rogue_level(&u.uz)) return; #endif s_level * lev; if (In_mines(&u.uz) && ((lev = Is_special(&u.uz)) == 0 || !lev->flags.town)) return; for (i = 0; i < num_decors; i++) { retries = nroom; placed = 0; switch (roomno % 3) { case 0: current_deco = V_FLOOR_CARPET; break; case 1: current_deco = V_FLOOR_MURAL; break; case 2: current_deco = V_FLOOR_MURAL2; break; } deco_width = floorstyles[current_deco].x; deco_height = floorstyles[current_deco].y; while (retries-- && !placed) { lx = rooms[roomno].lx; ly = rooms[roomno].ly; while (ly <= rooms[roomno].hy && (old_deco = (vultures_map_deco[ly][lx] >> 4)) != 0) { while (lx <= rooms[roomno].hx && (old_deco2 = (vultures_map_deco[ly][lx] >> 4)) != 0) lx += floorstyles[old_deco2-1].x; ly += floorstyles[old_deco-1].y; lx = rooms[roomno].lx; } if ((rooms[roomno].hx - lx + 1) >= deco_width && (rooms[roomno].hy - ly + 1) >= deco_height) { placed = 1; for (j=0; j nroom) roomno = (roomno % nroom) + wrapadd; } /* centre the decorations in the rooms, as the previous code always plces them in the top corner*/ for (i = 0; i < nroom; i++) { lx = rooms[i].lx; ly = rooms[i].ly; while (vultures_map_deco[ly][lx] != 0 && lx <= rooms[i].hx) lx++; deco_width = lx - rooms[i].lx; lx = rooms[i].lx; while (vultures_map_deco[ly][lx] != 0 && ly <= rooms[i].hy) ly++; deco_height = ly - rooms[i].ly; xoffset = (int)((rooms[i].lx + rooms[i].hx + 1)/2.0 - deco_width/2.0); yoffset = (int)((rooms[i].ly + rooms[i].hy + 1)/2.0 - deco_height/2.0); for (j = deco_height-1; j >= 0; j--) for (k = deco_width-1; k >= 0; k--) vultures_map_deco[yoffset + j][xoffset + k] = vultures_map_deco[rooms[i].ly + j][rooms[i].lx + k]; for (j = rooms[i].ly; j < yoffset; j++) memset(&vultures_map_deco[j][rooms[i].lx], 0, (rooms[i].hx-rooms[i].lx+1)); for (j = rooms[i].ly; j <= rooms[i].hy; j++) memset(&vultures_map_deco[j][rooms[i].lx], 0, (xoffset - rooms[i].lx)); } } static void vultures_get_wall_tiles(int y, int x) { int style; if (!level.locations[x][y].seenv) return; /* x - 1: west wall */ if (x > 0 && vultures_map_back[y][x - 1] != V_TILE_WALL_GENERIC && vultures_map_back[y][x - 1] != V_TILE_UNMAPPED_AREA) { style = vultures_get_wall_decor(vultures_map_back[y][x - 1], y, x, y, x-1); vultures_maptile_wall[y][x].west = walltiles[style].west; } else vultures_maptile_wall[y][x].west = V_TILE_NONE; /* y - 1: north wall */ if (y > 0 && vultures_map_back[y - 1][x] != V_TILE_WALL_GENERIC && vultures_map_back[y - 1][x] != V_TILE_UNMAPPED_AREA) { style = vultures_get_wall_decor(vultures_map_back[y - 1][x], y, x, y - 1, x); vultures_maptile_wall[y][x].north = walltiles[style].north; } else vultures_maptile_wall[y][x].north = V_TILE_NONE; /* x + 1: east wall */ if (x < V_MAP_WIDTH - 1 && vultures_map_back[y][x + 1] != V_TILE_WALL_GENERIC && vultures_map_back[y][x + 1] != V_TILE_UNMAPPED_AREA) { style = vultures_get_wall_decor(vultures_map_back[y][x + 1], y, x, y, x + 1); vultures_maptile_wall[y][x].east = walltiles[style].east; } else vultures_maptile_wall[y][x].east = V_TILE_NONE; /* y + 1: south wall */ if (y < V_MAP_HEIGHT - 1 && vultures_map_back[y + 1][x] != V_TILE_WALL_GENERIC && vultures_map_back[y + 1][x] != V_TILE_UNMAPPED_AREA) { style = vultures_get_wall_decor(vultures_map_back[y + 1][x], y, x, y + 1, x); vultures_maptile_wall[y][x].south = walltiles[style].south; } else vultures_maptile_wall[y][x].south = V_TILE_NONE; } static int vultures_get_floor_tile(int tile, int y, int x) { int style; int deco_pos; unsigned char deco = vultures_map_deco[y][x]; if (deco && tile == V_TILE_FLOOR_COBBLESTONE) { style = (deco >> 4) - 1; deco_pos = (int)(deco & 0x0F); return floorstyles[style].array[deco_pos]; } style = vultures_get_floor_decor(tile, y, x); deco_pos = floorstyles[style].x * (y % floorstyles[style].y) + (x % floorstyles[style].x); return floorstyles[style].array[deco_pos]; } static void vultures_get_floor_edges(int y, int x) { int i; int tile = vultures_map_back[y][x]; int style = V_FLOOR_EDGE_COBBLESTONE; point s_delta[4] = {{-1,0}, {0,-1}, {1,0}, {0,1}}; point d_delta[4] = {{-1,1}, {-1,-1}, {1,-1}, {1,1}}; /* Default: no floor edges around tile */ vultures_clear_floor_edges(y, x); /* straight sections */ for (i = 0; i < 4; i++) { if (x > 0 && x < V_MAP_WIDTH-s_delta[i].x && y > 0 && y < V_MAP_HEIGHT-s_delta[i].y && tile != vultures_map_back[y+s_delta[i].y][x+s_delta[i].x] && (tile + vultures_map_back[y+s_delta[i].y][x+s_delta[i].x]) != (V_TILE_FLOOR_WATER + V_TILE_FLOOR_ICE)) /* this prevents borders between water and ice*/ vultures_maptile_floor_edge[y][x].dir[i] = flooredges[style].dir[i]; } /* "inward pointing" corners */ for (i = 4; i < 8; i++) { if ((vultures_maptile_floor_edge[y][x].dir[(i+3)%4] != V_TILE_NONE) && (vultures_maptile_floor_edge[y][x].dir[i%4]) != V_TILE_NONE) vultures_maptile_floor_edge[y][x].dir[i] = flooredges[style].dir[i]; } /* "outward pointing" corners */ for (i = 8; i < 12; i++) { if ((vultures_maptile_floor_edge[y][x].dir[(i+3)%4] == V_TILE_NONE) && (vultures_maptile_floor_edge[y][x].dir[i%4] == V_TILE_NONE) && x > 0 && x < V_MAP_WIDTH - 1 && y > 0 && y < V_MAP_HEIGHT - 1 && tile != vultures_map_back[y+d_delta[i%4].y][x+d_delta[i%4].x] && (tile + vultures_map_back[y+d_delta[i%4].y][x+d_delta[i%4].x]) != (V_TILE_FLOOR_WATER + V_TILE_FLOOR_ICE)) vultures_maptile_floor_edge[y][x].dir[i] = flooredges[style].dir[i]; } /* for (i = 0; i < 12; i++) if (!vultures_maptile_floor_edge[y][x].dir[i]) vultures_maptile_floor_edge[y][x].dir[i] = V_TILE_NONE;*/ } /* get room index is only used to semi-randomly select room decorations * therefore the number we return can be as bogus as we want, so long as * it's consistently the same. Using the current depth will provide a bit of * variety on the maze levels...*/ static int vultures_get_room_index(int x, int y) { int rindex; if (nroom == 0) /* maze levels */ return u.uz.dlevel; if (In_mines(&u.uz)) /* The mines are a patchwork dungeon otherwise :( */ return (u.uz.dlevel + nroom); /* cleverly prevent a repetitive sequence :P */ rindex = vultures_room_indices[y][x]; if (!rindex) return (u.uz.dlevel + nroom); return rindex; } /* * Convert wall tile index (ie. wall type) to an associated decoration style. */ static int vultures_get_wall_decor( int floortype, int wally, int wallx, int floory, int floorx ) { int roomid; #if defined(VULTURESEYE) || (defined(VULTURESCLAW) && defined(REINCARNATION)) if (Is_rogue_level(&u.uz)) return V_WALL_LIGHT; #endif switch (floortype) { case V_TILE_FLOOR_ROUGH: case V_TILE_FLOOR_ROUGH_LIT: return V_WALL_ROUGH; case V_TILE_FLOOR_NOT_VISIBLE: case V_TILE_FLOOR_COBBLESTONE: { roomid = vultures_get_room_index(floorx, floory); switch(roomid % 4) { case 0: return V_WALL_STUCCO; case 1: return V_WALL_BRICK + ((wally*wallx+wally+wallx)%5); case 2: return V_WALL_VINE_COVERED; case 3: return V_WALL_MARBLE; } } default: return V_WALL_BRICK; } } /* * Convert floor tile index (ie. floor type) to an associated decoration style. */ static int vultures_get_floor_decor( int floorstyle, int floory, int floorx ) { int roomid; #if defined(VULTURESEYE) || (defined(VULTURESCLAW) && defined(REINCARNATION)) if (Is_rogue_level(&u.uz)) return V_FLOOR_DARK; #endif switch (floorstyle) { case V_TILE_FLOOR_ROUGH: return V_FLOOR_ROUGH; case V_TILE_FLOOR_ROUGH_LIT: return V_FLOOR_ROUGH_LIT; case V_TILE_FLOOR_COBBLESTONE: { roomid = vultures_get_room_index(floorx, floory); switch(roomid % 4) { case 0: return V_FLOOR_CERAMIC; case 1: return V_FLOOR_COBBLESTONE; case 2: return V_FLOOR_MOSS_COVERED; case 3: return V_FLOOR_MARBLE; } } case V_TILE_FLOOR_WATER: return V_FLOOR_WATER; case V_TILE_FLOOR_ICE: return V_FLOOR_ICE; case V_TILE_FLOOR_AIR: return V_FLOOR_AIR; case V_TILE_FLOOR_LAVA: return V_FLOOR_LAVA; case V_TILE_FLOOR_DARK: return V_FLOOR_DARK; default: return V_FLOOR_COBBLESTONE; } } /***************************************************************************** * 5) Interface functions for windowing *****************************************************************************/ char * vultures_map_square_description(point target, int include_seen) { struct permonst *pm; char *out_str, look_buf[BUFSZ]; char temp_buf[BUFSZ], coybuf[QBUFSZ]; char monbuf[BUFSZ]; struct monst *mtmp = (struct monst *) 0; const char *firstmatch; int n_objs; struct obj * obj; if ((target.x < 1) || (target.x >= V_MAP_WIDTH) || (target.y < 0) || (target.y >= V_MAP_HEIGHT)) return NULL; /* All of monsters, objects, traps and furniture get descriptions */ if ((vultures_map_mon[target.y][target.x] != V_TILE_NONE)) { out_str = malloc(BUFSZ); out_str[0] = '\0'; look_buf[0] = '\0'; monbuf[0] = '\0'; pm = lookat(target.x, target.y, look_buf, monbuf); firstmatch = look_buf; if (*firstmatch) { mtmp = m_at(target.x, target.y); Sprintf(temp_buf, "%s", (pm == &mons[PM_COYOTE]) ? coyotename(mtmp,coybuf) : firstmatch); strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1); } if (include_seen) { if (monbuf[0]) { sprintf(temp_buf, " [seen: %s]", monbuf); strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1); } } return out_str; } else if (vultures_map_obj[target.y][target.x] != V_TILE_NONE) { out_str = malloc(BUFSZ); look_buf[0] = '\0'; monbuf[0] = '\0'; lookat(target.x, target.y, look_buf, monbuf); n_objs = 0; obj = level.objects[target.x][target.y]; while(obj) { n_objs++; obj = obj->nexthere; } if (n_objs > 1) snprintf(out_str, BUFSZ, "%s (+%d other object%s)", look_buf, n_objs - 1, (n_objs > 2) ? "s" : ""); else strncpy(out_str, look_buf, BUFSZ); return out_str; } else if ((vultures_map_trap[target.y][target.x] != V_TILE_NONE) || (vultures_map_furniture[target.y][target.x] != V_TILE_NONE)) { out_str = malloc(BUFSZ); lookat(target.x, target.y, out_str, monbuf); return out_str; } return NULL; } point vultures_mouse_to_map(point mouse) { point mappos, px_offset; struct window * map = vultures_get_window(0); px_offset.x = mouse.x - (map->w / 2) + (vultures_view_x - vultures_view_y) * V_MAP_XMOD; px_offset.y = mouse.y - (map->h / 2) + (vultures_view_x+vultures_view_y)*V_MAP_YMOD; mappos.x = ( V_MAP_YMOD * px_offset.x + V_MAP_XMOD * px_offset.y + V_MAP_XMOD*V_MAP_YMOD)/(2*V_MAP_XMOD*V_MAP_YMOD); mappos.y = (-V_MAP_YMOD * px_offset.x + V_MAP_XMOD * px_offset.y + V_MAP_XMOD*V_MAP_YMOD)/(2*V_MAP_XMOD*V_MAP_YMOD); return mappos; } point vultures_map_to_mouse(point mappos) { struct window * map = vultures_get_window(WIN_MAP); int map_centre_x = map->w / 2; int map_centre_y = map->h / 2; point mouse; mouse.x = map_centre_x + V_MAP_XMOD*(mappos.x - mappos.y + vultures_view_y - vultures_view_x); mouse.y = map_centre_y + V_MAP_YMOD*(mappos.x + mappos.y - vultures_view_y - vultures_view_x); /* FIXME Why does this happen sometimes ? */ if ( mouse.x < 0 ) mouse.x = 0; if ( mouse.y < 0 ) mouse.y = 0; return mouse; } int vultures_get_map_action(point mappos) { int mapglyph_offset; /* Off-map squares have no default action */ if ((mappos.x < 1) || (mappos.x >= V_MAP_WIDTH) || (mappos.y < 0) || (mappos.y >= V_MAP_HEIGHT)) return 0; /* Target is at least 2 squares away */ if ((abs(u.ux-mappos.x) >= 2) || (abs(u.uy-mappos.y) >= 2)) return V_ACTION_TRAVEL; /* Monster on target square */ if (vultures_map_mon[mappos.y][mappos.x] != V_TILE_NONE && (u.ux != mappos.x || u.uy != mappos.y)) return V_ACTION_MOVE_HERE; /* Object on target square */ if (vultures_map_obj[mappos.y][mappos.x] != V_TILE_NONE && u.ux == mappos.x && u.uy == mappos.y) { mapglyph_offset = vultures_map_obj[mappos.y][mappos.x]; switch(mapglyph_offset - OBJTILEOFFSET) { case LARGE_BOX: case ICE_BOX: case CHEST: return V_ACTION_LOOT; default: return V_ACTION_PICK_UP; } } /* map feature on target square */ if (vultures_map_furniture[mappos.y][mappos.x] != V_TILE_NONE) { if ((u.ux == mappos.x) && (u.uy == mappos.y)) switch (vultures_map_furniture[mappos.y][mappos.x]) { case V_TILE_STAIRS_DOWN: case V_TILE_LADDER_DOWN: return V_ACTION_GO_DOWN; case V_TILE_STAIRS_UP: case V_TILE_LADDER_UP: return V_ACTION_GO_UP; case V_TILE_FOUNTAIN: return V_ACTION_DRINK; } else switch (vultures_map_furniture[mappos.y][mappos.x]) { case V_TILE_VDOOR_WOOD_CLOSED: case V_TILE_HDOOR_WOOD_CLOSED: return V_ACTION_OPEN_DOOR; } } /* default action for your own square */ if (u.ux == mappos.x && u.uy == mappos.y) return V_ACTION_SEARCH; /* default action for adjacent squares (nonadjacent squares were handled further up)*/ /* if the square contains an object and there is no monster ther, use trvel after all * to suppress the messegebox listing the objects */ if (vultures_map_obj[mappos.y][mappos.x] && !level.monsters[mappos.x][mappos.y]) return V_ACTION_TRAVEL; if (u.ux != mappos.x || u.uy != mappos.y) return V_ACTION_MOVE_HERE; return 0; } int vultures_get_map_contextmenu(point mappos) { struct window * menu; int mapglyph_offset; int result; /* Dropdown commands are shown only for valid squares */ if ((mappos. x < 1) || (mappos. x >= V_MAP_WIDTH) || (mappos. y < 0) || (mappos. y >= V_MAP_HEIGHT)) return(0); /* Construct a context-sensitive drop-down menu */ menu = vultures_create_window_internal(0, NULL, V_WINTYPE_DROPDOWN); if ((u.ux == mappos. x) && (u.uy == mappos. y)) { /* Add personal options: */ vultures_add_context_action(menu, V_ACTION_ENGRAVE, "Engrave"); vultures_add_context_action(menu, V_ACTION_LOOK_AROUND, "Look around"); vultures_add_context_action(menu, V_ACTION_MONSTER_ABILITY, "Monster ability"); if (*u.ushops) vultures_add_context_action(menu, V_ACTION_PAY_BILL, "Pay bill"); vultures_add_context_action(menu, V_ACTION_PRAY, "Pray"); vultures_add_context_action(menu, V_ACTION_REST, "Rest"); vultures_add_context_action(menu, V_ACTION_SEARCH, "Search"); vultures_add_context_action(menu, V_ACTION_SIT, "Sit"); /* do a minimum check to leave turn undead out for those who _definitely_ can't do it */ #ifdef VULTURESEYE if (Role_if(PM_PRIEST) || Role_if(PM_KNIGHT) || #else /* VULTURESCLAW */ if (tech_known(T_TURN_UNDEAD) || #endif objects[SPE_TURN_UNDEAD].oc_name_known) vultures_add_context_action(menu, V_ACTION_TURN_UNDEAD, "Turn undead"); vultures_add_context_action(menu, V_ACTION_WIPE_FACE, "Wipe face"); } /* monster options */ else if (vultures_map_mon[mappos. y][mappos. x] != V_TILE_NONE) if ((abs(u.ux-mappos. x) <= 1) && (abs(u.uy-mappos. y) <= 1)) { vultures_add_context_action(menu, V_ACTION_CHAT, "Chat"); vultures_add_context_action(menu, V_ACTION_NAMEMON, "Name"); } /* Add object options: */ if (vultures_map_obj[mappos. y][mappos. x] != V_TILE_NONE && (abs(u.ux-mappos. x) <= 1 && abs(u.uy-mappos. y) <= 1)) { mapglyph_offset = vultures_map_obj[mappos. y][mappos. x]; switch(mapglyph_offset - OBJTILEOFFSET) { case LARGE_BOX: case ICE_BOX: case CHEST: if ((u.ux == mappos. x) && (u.uy == mappos. y)) { vultures_add_context_action(menu, V_ACTION_FORCE_LOCK, "Force lock"); vultures_add_context_action(menu, V_ACTION_LOOT, "Loot"); vultures_add_context_action(menu, V_ACTION_PICK_UP, "Pick up"); } vultures_add_context_action(menu, V_ACTION_UNTRAP, "Untrap"); break; case SACK: case OILSKIN_SACK: case BAG_OF_HOLDING: case BAG_OF_TRICKS: case (V_TILE_UNIDENTIFIED_BAG + OBJTILEOFFSET): if ((u.ux == mappos. x) && (u.uy == mappos. y)) { vultures_add_context_action(menu, V_ACTION_LOOT, "Loot"); vultures_add_context_action(menu, V_ACTION_PICK_UP, "Pick up"); } break; default: if ((u.ux == mappos. x) && (u.uy == mappos. y)) vultures_add_context_action(menu, V_ACTION_PICK_UP, "Pick up"); break; } } /* Add location options: */ if (vultures_map_furniture[mappos. y][mappos. x] != V_TILE_NONE && abs(u.ux-mappos. x) <= 1 && abs(u.uy-mappos. y) <= 1) { switch(vultures_map_furniture[mappos. y][mappos. x]) { case V_TILE_STAIRS_DOWN: case V_TILE_LADDER_DOWN: if ((u.ux == mappos. x) && (u.uy == mappos. y)) vultures_add_context_action(menu, V_ACTION_GO_DOWN, "Go down"); break; case V_TILE_STAIRS_UP: case V_TILE_LADDER_UP: if ((u.ux == mappos. x) && (u.uy == mappos. y)) vultures_add_context_action(menu, V_ACTION_GO_UP, "Go up"); break; case V_TILE_FOUNTAIN: if ((u.ux == mappos. x) && (u.uy == mappos. y)) vultures_add_context_action(menu, V_ACTION_DRINK, "Drink"); break; case V_TILE_VDOOR_WOOD_OPEN: case V_TILE_HDOOR_WOOD_OPEN: if ((u.ux != mappos. x) || (u.uy != mappos. y)) { vultures_add_context_action(menu, V_ACTION_CLOSE_DOOR, "Close door"); vultures_add_context_action(menu, V_ACTION_UNTRAP, "Untrap"); vultures_add_context_action(menu, V_ACTION_KICK, "Kick"); } break; case V_TILE_VDOOR_WOOD_CLOSED: case V_TILE_HDOOR_WOOD_CLOSED: if ((u.ux != mappos. x) || (u.uy != mappos. y)) { vultures_add_context_action(menu, V_ACTION_OPEN_DOOR, "Open door"); vultures_add_context_action(menu, V_ACTION_UNTRAP, "Untrap"); vultures_add_context_action(menu, V_ACTION_KICK, "Kick"); } break; case V_TILE_ALTAR: if ((u.ux == mappos. x) && (u.uy == mappos. y)) vultures_add_context_action(menu, V_ACTION_OFFER, "Offer"); else vultures_add_context_action(menu, V_ACTION_KICK, "Kick"); break; default: if ((u.ux != mappos. x) || (u.uy != mappos. y)) vultures_add_context_action(menu, V_ACTION_KICK, "Kick"); break; } } if (vultures_map_trap[mappos. y][mappos. x] != V_TILE_NONE) { vultures_add_context_action(menu, V_ACTION_UNTRAP, "Untrap"); if ((u.ux != mappos. x) || (u.uy != mappos. y)) if ((abs(u.ux-mappos. x) <= 1) && (abs(u.uy-mappos. y) <= 1)) vultures_add_context_action(menu, V_ACTION_MOVE_HERE, "Enter trap"); } if (vultures_map_back[mappos. y][mappos. x] != V_TILE_NONE) { if ((u.ux != mappos. x) || (u.uy != mappos. y)) vultures_add_context_action(menu, V_ACTION_TRAVEL, "Move here"); vultures_add_context_action(menu, V_ACTION_WHATS_THIS, "What's this?"); } vultures_layout_dropdown(menu); vultures_event_dispatcher(&result, V_RESPOND_INT, menu); vultures_destroy_window_internal(menu); return result; } int vultures_perform_map_action(int action_id, point mappos) { switch (action_id) { case V_ACTION_TRAVEL: u.tx = mappos.x; u.ty = mappos.y; return CMD_TRAVEL; case V_ACTION_MOVE_HERE: return vultures_mappos_to_dirkey(mappos); case V_ACTION_LOOT: return 'l'; case V_ACTION_PICK_UP: return ','; case V_ACTION_GO_DOWN: return '>'; case V_ACTION_GO_UP: return '<'; case V_ACTION_DRINK: return 'q'; case V_ACTION_SEARCH: return 's'; case V_ACTION_ENGRAVE: return 'E'; case V_ACTION_LOOK_AROUND: return ':'; case V_ACTION_PAY_BILL: return 'p'; case V_ACTION_OFFER: return META('o'); case V_ACTION_PRAY: return META('p'); case V_ACTION_REST: return '.'; case V_ACTION_SIT: return META('s'); case V_ACTION_TURN_UNDEAD: return META('t'); case V_ACTION_WIPE_FACE: return META('w'); case V_ACTION_FORCE_LOCK: return META('f'); case V_ACTION_MONSTER_ABILITY: return META('m'); case V_ACTION_KICK: vultures_eventstack_add(vultures_mappos_to_dirkey(mappos),-1,-1, V_RESPOND_CHARACTER); return 'k'; case V_ACTION_OPEN_DOOR: vultures_eventstack_add(vultures_mappos_to_dirkey(mappos),-1,-1, V_RESPOND_CHARACTER); return 'o'; case V_ACTION_UNTRAP: vultures_eventstack_add(vultures_mappos_to_dirkey(mappos),-1,-1, V_RESPOND_CHARACTER); return META('u'); case V_ACTION_CLOSE_DOOR: vultures_eventstack_add(vultures_mappos_to_dirkey(mappos),-1,-1, V_RESPOND_CHARACTER); return 'c'; case V_ACTION_WHATS_THIS: /* events get stored on a STACK, so calls to eventstack add * need to be done in revers order */ vultures_whatis_singleshot = 1; /* select the mapsquare */ vultures_eventstack_add(0, mappos.x, mappos.y, V_RESPOND_POSKEY); /* yes, we _really do_ want more info */ vultures_eventstack_add('y', -1, -1, V_RESPOND_CHARACTER); return '/'; case V_ACTION_CHAT: vultures_eventstack_add(vultures_mappos_to_dirkey(mappos),-1,-1, V_RESPOND_CHARACTER); return META('c'); case V_ACTION_NAMEMON: vultures_eventstack_add(0, mappos.x, mappos.y, V_RESPOND_POSKEY); return 'C'; default: break; } return 0; } int vultures_get_map_cursor(point mappos) { if ((mappos.x < 1) || (mappos.x >= V_MAP_WIDTH) || (mappos.y < 0) || (mappos.y >= V_MAP_HEIGHT)) return V_CURSOR_TARGET_INVALID; if (vultures_whatis_active) return V_CURSOR_TARGET_HELP; if (vultures_map_mon[mappos.y][mappos.x] != V_TILE_NONE && ((mappos.x != u.ux) || (mappos.y != u.uy))) return V_CURSOR_TARGET_RED; if (vultures_map_obj[mappos.y][mappos.x] != V_TILE_NONE) return V_CURSOR_TARGET_RED; if (vultures_map_back[mappos.y][mappos.x] != V_TILE_NONE) /* valid visible location */ { /* Closed doors get an 'open door' cursor */ if ((vultures_map_furniture[mappos.y][mappos.x] == V_TILE_VDOOR_WOOD_CLOSED) || (vultures_map_furniture[mappos.y][mappos.x] == V_TILE_HDOOR_WOOD_CLOSED)) return V_CURSOR_OPENDOOR; /* Stairs and ladders get a 'stairs' cursor */ if ((vultures_map_furniture[mappos.y][mappos.x] == V_TILE_STAIRS_UP) || (vultures_map_furniture[mappos.y][mappos.x] == V_TILE_STAIRS_DOWN) || (vultures_map_furniture[mappos.y][mappos.x] == V_TILE_LADDER_UP) || (vultures_map_furniture[mappos.y][mappos.x] == V_TILE_LADDER_DOWN)) return V_CURSOR_STAIRS; /* Fountains get a 'goblet' cursor */ if (vultures_map_furniture[mappos.y][mappos.x] == V_TILE_FOUNTAIN) return V_CURSOR_GOBLET; if (vultures_map_back[mappos.y][mappos.x] != V_TILE_WALL_GENERIC) return V_CURSOR_TARGET_GREEN; } return V_CURSOR_TARGET_INVALID; } /***************************************************************************** * 6) misc utility functions *****************************************************************************/ int vultures_object_to_tile(int obj_id, int x, int y) { struct obj *obj; int tile; static int lastfigurine = PM_KNIGHT; static int laststatue = PM_KNIGHT; if (obj_id < 0 || obj_id > NUM_OBJECTS) /* we get *seriously weird* input for hallucinated corpses */ obj_id = CORPSE; if (x >= 0) obj = level.objects[x][y]; else obj = invent; while (obj && !(obj->otyp == obj_id && (x >= 0 || obj->invlet == y))) obj = (x >= 0) ? obj->nexthere : obj->nobj; if (obj && Blind && !obj->dknown) { switch (obj->oclass) { case AMULET_CLASS: return OBJECT_TO_VTILE(AMULET_OF_ESP); case POTION_CLASS: return OBJECT_TO_VTILE(POT_WATER); case SCROLL_CLASS: return OBJECT_TO_VTILE(SCR_BLANK_PAPER); case WAND_CLASS: return OBJECT_TO_VTILE(WAN_NOTHING); case SPBOOK_CLASS: return OBJECT_TO_VTILE(SPE_BLANK_PAPER); case RING_CLASS: return OBJECT_TO_VTILE(RIN_ADORNMENT); case GEM_CLASS: if (objects[obj_id].oc_material == MINERAL) return OBJECT_TO_VTILE(ROCK); else return OBJECT_TO_VTILE(GEM_BLUE_GLASS); } } if (obj_id == STATUE || obj_id == FIGURINE) { if (obj_id == FIGURINE) { tile = lastfigurine; if (obj) { tile = obj->corpsenm; lastfigurine = tile; } tile = FIGURINE_TO_VTILE(tile); } else /* obj_id == STATUE */ { tile = laststatue; if (obj) { tile = obj->corpsenm; laststatue = tile; } tile = STATUE_TO_VTILE(tile); } return tile; } if (!objects[obj_id].oc_name_known) { switch (obj_id) { case SACK: case OILSKIN_SACK: case BAG_OF_TRICKS: case BAG_OF_HOLDING: return V_TILE_UNIDENTIFIED_BAG; case LOADSTONE: case LUCKSTONE: case FLINT: case TOUCHSTONE: #ifdef HEALTHSTONE /* only in SlashEM */ case HEALTHSTONE: #endif #ifdef WHETSTONE /* only in SlashEM */ case WHETSTONE: #endif return V_TILE_STONE; case OIL_LAMP: case MAGIC_LAMP: return OBJECT_TO_VTILE(OIL_LAMP); case TIN_WHISTLE: case MAGIC_WHISTLE: return OBJECT_TO_VTILE(TIN_WHISTLE); case DILITHIUM_CRYSTAL: case DIAMOND: case RUBY: case JACINTH: case SAPPHIRE: case BLACK_OPAL: case EMERALD: case TURQUOISE: case CITRINE: case AQUAMARINE: case AMBER: case TOPAZ: case JET: case OPAL: case CHRYSOBERYL: case GARNET: case AMETHYST: case JASPER: case FLUORITE: case OBSIDIAN: case AGATE: case JADE: switch (objects[obj_id].oc_color) { case CLR_RED: tile = GEM_RED_GLASS; break; case CLR_BLACK: tile = GEM_BLACK_GLASS; break; case CLR_GREEN: tile = GEM_GREEN_GLASS; break; case CLR_BROWN: tile = GEM_BROWN_GLASS; break; case CLR_MAGENTA: tile = GEM_VIOLET_GLASS; break; case CLR_ORANGE: tile = GEM_ORANGE_GLASS; break; case CLR_YELLOW: tile = GEM_YELLOW_GLASS; break; case CLR_WHITE: tile = GEM_WHITE_GLASS; break; case CLR_BLUE: tile = GEM_BLUE_GLASS; break; default: tile = GEM_BLACK_GLASS; break; } return OBJECT_TO_VTILE(tile); } } return OBJECT_TO_VTILE(obj_id); } static int vultures_monster_to_tile(int mon_id, XCHAR_P x, XCHAR_P y) { if (Invis && u.ux == x && u.uy == y) return V_TILE_PLAYER_INVIS; #if defined(VULTURESEYE) || (defined(VULTURESCLAW) && defined(REINCARNATION)) if (Is_rogue_level(&u.uz)) { switch (mon_id) { case PM_COUATL : case PM_ALEAX : case PM_ANGEL : case PM_KI_RIN : case PM_ARCHON : return V_TILE_ROGUE_LEVEL_A; case PM_GIANT_BAT : case PM_RAVEN : case PM_VAMPIRE_BAT : case PM_BAT : return V_TILE_ROGUE_LEVEL_B; case PM_PLAINS_CENTAUR : case PM_FOREST_CENTAUR : case PM_MOUNTAIN_CENTAUR : return V_TILE_ROGUE_LEVEL_C; case PM_DOG: case PM_BABY_GRAY_DRAGON : case PM_BABY_SILVER_DRAGON : case PM_BABY_RED_DRAGON : case PM_BABY_WHITE_DRAGON : case PM_BABY_ORANGE_DRAGON : case PM_BABY_BLACK_DRAGON : case PM_BABY_BLUE_DRAGON : case PM_BABY_GREEN_DRAGON : case PM_BABY_YELLOW_DRAGON : case PM_GRAY_DRAGON : case PM_SILVER_DRAGON : case PM_RED_DRAGON : case PM_WHITE_DRAGON : case PM_ORANGE_DRAGON : case PM_BLACK_DRAGON : case PM_BLUE_DRAGON : case PM_GREEN_DRAGON : case PM_YELLOW_DRAGON : return V_TILE_ROGUE_LEVEL_D; case PM_STALKER : case PM_AIR_ELEMENTAL : case PM_FIRE_ELEMENTAL: case PM_EARTH_ELEMENTAL : case PM_WATER_ELEMENTAL : return V_TILE_ROGUE_LEVEL_E; case PM_LICHEN : case PM_BROWN_MOLD : case PM_YELLOW_MOLD : case PM_GREEN_MOLD : case PM_RED_MOLD : case PM_SHRIEKER : case PM_VIOLET_FUNGUS : return V_TILE_ROGUE_LEVEL_F; case PM_GNOME : case PM_GNOME_LORD : case PM_GNOMISH_WIZARD : case PM_GNOME_KING : return V_TILE_ROGUE_LEVEL_G; case PM_GIANT : case PM_STONE_GIANT : case PM_HILL_GIANT : case PM_FIRE_GIANT : case PM_FROST_GIANT : case PM_STORM_GIANT : case PM_ETTIN : case PM_TITAN : case PM_MINOTAUR : return V_TILE_ROGUE_LEVEL_H; case 999990 : //None return V_TILE_ROGUE_LEVEL_I; case PM_JABBERWOCK : return V_TILE_ROGUE_LEVEL_J; case PM_KEYSTONE_KOP : case PM_KOP_SERGEANT : case PM_KOP_LIEUTENANT : case PM_KOP_KAPTAIN : return V_TILE_ROGUE_LEVEL_K; case PM_LICH : case PM_DEMILICH : case PM_MASTER_LICH : case PM_ARCH_LICH : return V_TILE_ROGUE_LEVEL_L; case PM_KOBOLD_MUMMY : case PM_GNOME_MUMMY : case PM_ORC_MUMMY : case PM_DWARF_MUMMY : case PM_ELF_MUMMY : case PM_HUMAN_MUMMY : case PM_ETTIN_MUMMY : case PM_GIANT_MUMMY : return V_TILE_ROGUE_LEVEL_M; case PM_RED_NAGA_HATCHLING : case PM_BLACK_NAGA_HATCHLING : case PM_GOLDEN_NAGA_HATCHLING : case PM_GUARDIAN_NAGA_HATCHLING : case PM_RED_NAGA : case PM_BLACK_NAGA : case PM_GOLDEN_NAGA : case PM_GUARDIAN_NAGA : return V_TILE_ROGUE_LEVEL_N; case PM_OGRE : case PM_OGRE_LORD : case PM_OGRE_KING : return V_TILE_ROGUE_LEVEL_O; case PM_GRAY_OOZE : case PM_BROWN_PUDDING : case PM_BLACK_PUDDING : case PM_GREEN_SLIME : return V_TILE_ROGUE_LEVEL_P; case PM_QUANTUM_MECHANIC : return V_TILE_ROGUE_LEVEL_Q; case PM_RUST_MONSTER : case PM_DISENCHANTER : return V_TILE_ROGUE_LEVEL_R; case PM_GARTER_SNAKE : case PM_SNAKE : case PM_WATER_MOCCASIN : case PM_PIT_VIPER : case PM_PYTHON : case PM_COBRA : return V_TILE_ROGUE_LEVEL_S; case PM_TROLL : case PM_ICE_TROLL : case PM_ROCK_TROLL : case PM_WATER_TROLL : case PM_OLOG_HAI : return V_TILE_ROGUE_LEVEL_T; case PM_UMBER_HULK : return V_TILE_ROGUE_LEVEL_U; case PM_VAMPIRE : case PM_VAMPIRE_LORD : return V_TILE_ROGUE_LEVEL_V; case PM_BARROW_WIGHT : case PM_WRAITH : case PM_NAZGUL : return V_TILE_ROGUE_LEVEL_W; case PM_XORN : return V_TILE_ROGUE_LEVEL_X; case PM_MONKEY : case PM_APE : case PM_OWLBEAR : case PM_YETI : case PM_CARNIVOROUS_APE : case PM_SASQUATCH : return V_TILE_ROGUE_LEVEL_Y; case PM_GHOUL: case PM_KOBOLD_ZOMBIE : case PM_GNOME_ZOMBIE : case PM_ORC_ZOMBIE : case PM_DWARF_ZOMBIE : case PM_ELF_ZOMBIE : case PM_HUMAN_ZOMBIE : case PM_ETTIN_ZOMBIE : case PM_GIANT_ZOMBIE : return V_TILE_ROGUE_LEVEL_Z; default: { if ((mon_id >= 0) && (mon_id < NUMMONS)) return MONSTER_TO_VTILE(mon_id); else return V_TILE_NONE; } } } #endif if (mon_id == PM_ALEAX) return MONSTER_TO_VTILE(u.umonnum); if (mon_id == PM_ALIGNED_PRIEST) { register struct monst *mtmp = m_at(x, y); switch (EPRI(mtmp)->shralign) { case A_LAWFUL: return V_TILE_LAWFUL_PRIEST; case A_CHAOTIC: return V_TILE_CHAOTIC_PRIEST; case A_NEUTRAL: return V_TILE_NEUTRAL_PRIEST; default: return V_TILE_UNALIGNED_PRIEST; } } if ((mon_id >= 0) && (mon_id < NUMMONS)) return MONSTER_TO_VTILE(mon_id); return V_TILE_NONE; } static char vultures_mappos_to_dirkey(point mappos) { if (mappos.y == u.uy + 1) { if (mappos.x == u.ux - 1) return '1'; if (mappos.x == u.ux) return '2'; if (mappos.x == u.ux + 1) return '3'; } else if (mappos.y == u.uy) { if (mappos.x == u.ux - 1) return '4'; if (mappos.x == u.ux) return '.'; if (mappos.x == u.ux + 1) return '6'; } else if (mappos.y == u.uy - 1) { if (mappos.x == u.ux - 1) return '7'; if (mappos.x == u.ux) return '8'; if (mappos.x == u.ux + 1) return '9'; } /* the caller should make sure we don't get here */ return 0; } static void vultures_build_tilemap(void) { int i; vultures_tilemap_special = malloc(MAXPCHARS*sizeof(int)); vultures_tilemap_engulf = malloc(NUMMONS*sizeof(int)); for (i = 0; i < NUMMONS; i++) vultures_tilemap_engulf[i] = V_TILE_NONE; vultures_tilemap_engulf[PM_OCHRE_JELLY] = V_TILE_ENGULF_OCHRE_JELLY; vultures_tilemap_engulf[PM_LURKER_ABOVE] = V_TILE_ENGULF_LURKER_ABOVE; vultures_tilemap_engulf[PM_TRAPPER] = V_TILE_ENGULF_TRAPPER; vultures_tilemap_engulf[PM_PURPLE_WORM] = V_TILE_ENGULF_PURPLE_WORM; vultures_tilemap_engulf[PM_DUST_VORTEX] = V_TILE_ENGULF_DUST_VORTEX; vultures_tilemap_engulf[PM_ICE_VORTEX] = V_TILE_ENGULF_ICE_VORTEX; vultures_tilemap_engulf[PM_ENERGY_VORTEX] = V_TILE_ENGULF_ENERGY_VORTEX; vultures_tilemap_engulf[PM_STEAM_VORTEX] = V_TILE_ENGULF_STEAM_VORTEX; vultures_tilemap_engulf[PM_FIRE_VORTEX] = V_TILE_ENGULF_FIRE_VORTEX; vultures_tilemap_engulf[PM_FOG_CLOUD] = V_TILE_ENGULF_FOG_CLOUD; vultures_tilemap_engulf[PM_AIR_ELEMENTAL] = V_TILE_ENGULF_AIR_ELEMENTAL; vultures_tilemap_engulf[PM_JUIBLEX] = V_TILE_ENGULF_JUIBLEX; vultures_tilemap_special[S_stone] = V_TILE_UNMAPPED_AREA; vultures_tilemap_special[S_vwall] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_hwall] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_tlcorn] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_trcorn] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_blcorn] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_brcorn] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_crwall] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_tuwall] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_tdwall] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_tlwall] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_trwall] = V_TILE_WALL_GENERIC; vultures_tilemap_special[S_ndoor] = V_TILE_DOOR_WOOD_BROKEN; vultures_tilemap_special[S_vodoor] = V_TILE_VDOOR_WOOD_OPEN; vultures_tilemap_special[S_hodoor] = V_TILE_HDOOR_WOOD_OPEN; vultures_tilemap_special[S_vcdoor] = V_TILE_VDOOR_WOOD_CLOSED; vultures_tilemap_special[S_hcdoor] = V_TILE_HDOOR_WOOD_CLOSED; vultures_tilemap_special[S_room] = V_TILE_FLOOR_COBBLESTONE; vultures_tilemap_special[S_corr] = V_TILE_FLOOR_ROUGH; vultures_tilemap_special[S_upstair] = V_TILE_STAIRS_UP; vultures_tilemap_special[S_dnstair] = V_TILE_STAIRS_DOWN; vultures_tilemap_special[S_fountain] = V_TILE_FOUNTAIN; vultures_tilemap_special[S_altar] = V_TILE_ALTAR; vultures_tilemap_special[S_teleportation_trap] = V_TILE_TRAP_TELEPORTER; vultures_tilemap_special[S_tree] = V_TILE_TREE; vultures_tilemap_special[S_cloud] = V_TILE_CLOUD; vultures_tilemap_special[S_air] = V_TILE_FLOOR_AIR; vultures_tilemap_special[S_grave] = V_TILE_GRAVE; vultures_tilemap_special[S_sink] = V_TILE_SINK; vultures_tilemap_special[S_bear_trap] = V_TILE_TRAP_BEAR; vultures_tilemap_special[S_rust_trap] = V_TILE_TRAP_WATER; vultures_tilemap_special[S_pit] = V_TILE_TRAP_PIT; vultures_tilemap_special[S_hole] = V_TILE_TRAP_PIT; vultures_tilemap_special[S_trap_door] = V_TILE_TRAP_DOOR; vultures_tilemap_special[S_water] = V_TILE_FLOOR_WATER; vultures_tilemap_special[S_pool] = V_TILE_FLOOR_WATER; vultures_tilemap_special[S_ice] = V_TILE_FLOOR_ICE; vultures_tilemap_special[S_lava] = V_TILE_FLOOR_LAVA; vultures_tilemap_special[S_throne] = V_TILE_THRONE; vultures_tilemap_special[S_bars] = V_TILE_BARS; vultures_tilemap_special[S_upladder] = V_TILE_LADDER_UP; vultures_tilemap_special[S_dnladder] = V_TILE_LADDER_DOWN; vultures_tilemap_special[S_arrow_trap] = V_TILE_TRAP_ARROW; vultures_tilemap_special[S_rolling_boulder_trap] = V_TILE_ROLLING_BOULDER_TRAP; vultures_tilemap_special[S_sleeping_gas_trap] = V_TILE_GAS_TRAP; vultures_tilemap_special[S_fire_trap] = V_TILE_TRAP_FIRE; vultures_tilemap_special[S_web] = V_TILE_WEB_TRAP; vultures_tilemap_special[S_statue_trap] = OBJECT_TO_VTILE(STATUE); vultures_tilemap_special[S_anti_magic_trap] = V_TILE_TRAP_ANTI_MAGIC; vultures_tilemap_special[S_polymorph_trap] = V_TILE_TRAP_POLYMORPH; vultures_tilemap_special[S_vbeam] = V_TILE_ZAP_VERTICAL; vultures_tilemap_special[S_hbeam] = V_TILE_ZAP_HORIZONTAL; vultures_tilemap_special[S_lslant] = V_TILE_ZAP_SLANT_LEFT; vultures_tilemap_special[S_rslant] = V_TILE_ZAP_SLANT_RIGHT; vultures_tilemap_special[S_litcorr] = V_TILE_FLOOR_ROUGH_LIT; vultures_tilemap_special[S_ss1] = V_TILE_RESIST_SPELL_1; vultures_tilemap_special[S_ss2] = V_TILE_RESIST_SPELL_2; vultures_tilemap_special[S_ss3] = V_TILE_RESIST_SPELL_3; vultures_tilemap_special[S_ss4] = V_TILE_RESIST_SPELL_4; vultures_tilemap_special[S_dart_trap] = V_TILE_DART_TRAP; vultures_tilemap_special[S_falling_rock_trap] = V_TILE_FALLING_ROCK_TRAP; vultures_tilemap_special[S_squeaky_board] = V_TILE_SQUEAKY_BOARD; vultures_tilemap_special[S_land_mine] = V_TILE_LAND_MINE; vultures_tilemap_special[S_magic_portal] = V_TILE_MAGIC_PORTAL; vultures_tilemap_special[S_spiked_pit] = V_TILE_SPIKED_PIT; vultures_tilemap_special[S_hole] = V_TILE_HOLE; vultures_tilemap_special[S_level_teleporter] = V_TILE_LEVEL_TELEPORTER; vultures_tilemap_special[S_magic_trap] = V_TILE_MAGIC_TRAP; vultures_tilemap_special[S_digbeam] = V_TILE_DIGBEAM; vultures_tilemap_special[S_flashbeam] = V_TILE_FLASHBEAM; vultures_tilemap_special[S_boomleft] = V_TILE_BOOMLEFT; vultures_tilemap_special[S_boomright] = V_TILE_BOOMRIGHT; vultures_tilemap_special[S_hcdbridge] = V_TILE_HCDBRIDGE; vultures_tilemap_special[S_vcdbridge] = V_TILE_VCDBRIDGE; vultures_tilemap_special[S_hodbridge] = V_TILE_HODBRIDGE; vultures_tilemap_special[S_vodbridge] = V_TILE_VODBRIDGE; #ifdef VULTURESCLAW vultures_tilemap_special[S_toilet] = V_TILE_TOILET; #endif } static int vultures_remap_tile_id(int tile_id) { if (tile_id == V_TILE_PLAYER_INVIS) tile_id = MONSTER_TO_VTILE(u.umonnum); if (tile_id < NUM_OBJECTS) tile_id = objects[tile_id].oc_descr_idx; /* if the tile is merely a pointer to another tile we modify the tile_id */ if (!vultures_gametiles[tile_id].data_len && vultures_gametiles[tile_id].ptr != -1) { tile_id = vultures_gametiles[tile_id].ptr; } return tile_id; }