/* * Determine if a given grid may be "tunneled" */ static bool do_cmd_tunnel_test(int y, int x) { /* Must have knowledge */ if (!(cave->info[y][x] & (CAVE_MARK))) { /* Message */ msg("You see nothing there."); /* Nope */ return (FALSE); } /* Must be a wall/door/etc */ if (cave_ispassable(cave, y, x)) { /* Message */ msg("You see nothing there to tunnel."); /* Nope */ return (FALSE); } /* Okay */ return (TRUE); }
/* * Hack -- quick debugging hook */ static void do_cmd_wiz_hack_ben(void) { int py = p_ptr->py; int px = p_ptr->px; int i, y, x; struct keypress kp; for (i = 0; i < MONSTER_FLOW_DEPTH; ++i) { /* Update map */ for (y = Term->offset_y; y < Term->offset_y + SCREEN_HGT; y++) { for (x = Term->offset_x; x < Term->offset_x + SCREEN_WID; x++) { byte a = TERM_RED; if (!cave_in_bounds_fully(cave, y, x)) continue; /* Display proper cost */ if (cave->cost[y][x] != i) continue; /* Reliability in yellow */ if (cave->when[y][x] == cave->when[py][px]) a = TERM_YELLOW; /* Display player/floors/walls */ if ((y == py) && (x == px)) print_rel(L'@', a, y, x); else if (cave_ispassable(cave, y, x)) print_rel(L'*', a, y, x); else print_rel(L'#', a, y, x); } } /* Prompt */ prt(format("Depth %d: ", i), 0, 0); /* Get key */ kp = inkey(); if (kp.code == ESCAPE) break; /* Redraw map */ prt_map(); } /* Done */ prt("", 0, 0); /* Redraw map */ prt_map(); }
/* * Determine if a given grid may be "walked" */ static bool do_cmd_walk_test(int y, int x) { int m_idx = cave->m_idx[y][x]; struct monster *m_ptr = cave_monster(cave, m_idx); /* Allow attack on visible monsters if unafraid */ if (m_idx > 0 && m_ptr->ml && !is_mimicking(m_ptr)) { /* Handle player fear */ if (check_state(p_ptr, OF_AFRAID, p_ptr->state.flags)) { /* Extract monster name (or "it") */ char m_name[80]; monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_DEFAULT); /* Message */ msgt(MSG_AFRAID, "You are too afraid to attack %s!", m_name); /* Nope */ return (FALSE); } return (TRUE); } /* If we don't know the grid, allow attempts to walk into it */ if (!(cave->info[y][x] & CAVE_MARK)) return TRUE; /* Require open space */ if (!cave_ispassable(cave, y, x)) { /* Rubble */ if (cave_isrubble(cave, y, x)) msgt(MSG_HITWALL, "There is a pile of rubble in the way!"); /* Door */ else if (cave_iscloseddoor(cave, y, x)) return TRUE; /* Wall */ else msgt(MSG_HITWALL, "There is a wall in the way!"); /* Cancel repeat */ disturb(p_ptr, 0, 0); /* Nope */ return (FALSE); } /* Okay */ return (TRUE); }
/* * Tunnel through wall. Assumes valid location. * * Note that it is impossible to "extend" rooms past their * outer walls (which are actually part of the room). * * Attempting to do so will produce floor grids which are not part * of the room, and whose "illumination" status do not change with * the rest of the room. */ static bool twall(int y, int x) { /* Paranoia -- Require a wall or door or some such */ if (cave_ispassable(cave, y, x)) return (FALSE); /* Sound */ sound(MSG_DIG); /* Forget the wall */ cave->info[y][x] &= ~(CAVE_MARK); /* Remove the feature */ cave_tunnel_wall(cave, y, x); /* Update the visuals */ p_ptr->update |= (PU_UPDATE_VIEW | PU_MONSTERS); /* Fully update the flow */ p_ptr->update |= (PU_FORGET_FLOW | PU_UPDATE_FLOW); /* Result */ return (TRUE); }
/** * Draw a visible path over the squares between (x1,y1) and (x2,y2). * * The path consists of "*", which are white except where there is a * monster, object or feature in the grid. * * This routine has (at least) three weaknesses: * - remembered objects/walls which are no longer present are not shown, * - squares which (e.g.) the player has walked through in the dark are * treated as unknown space. * - walls which appear strange due to hallucination aren't treated correctly. * * The first two result from information being lost from the dungeon arrays, * which requires changes elsewhere */ static int draw_path(u16b path_n, u16b *path_g, wchar_t *c, int *a, int y1, int x1) { int i; bool on_screen; /* No path, so do nothing. */ if (path_n < 1) return 0; /* The starting square is never drawn, but notice if it is being * displayed. In theory, it could be the last such square. */ on_screen = panel_contains(y1, x1); /* Draw the path. */ for (i = 0; i < path_n; i++) { byte colour; /* Find the co-ordinates on the level. */ int y = GRID_Y(path_g[i]); int x = GRID_X(path_g[i]); /* * As path[] is a straight line and the screen is oblong, * there is only section of path[] on-screen. * If the square being drawn is visible, this is part of it. * If none of it has been drawn, continue until some of it * is found or the last square is reached. * If some of it has been drawn, finish now as there are no * more visible squares to draw. */ if (panel_contains(y,x)) on_screen = TRUE; else if (on_screen) break; else continue; /* Find the position on-screen */ move_cursor_relative(y,x); /* This square is being overwritten, so save the original. */ Term_what(Term->scr->cx, Term->scr->cy, a+i, c+i); /* Choose a colour. */ if (cave->m_idx[y][x] && cave_monster_at(cave, y, x)->ml) { /* Visible monsters are red. */ monster_type *m_ptr = cave_monster_at(cave, y, x); /* Mimics act as objects */ if (rf_has(m_ptr->race->flags, RF_UNAWARE)) colour = TERM_YELLOW; else colour = TERM_L_RED; } else if (cave->o_idx[y][x] && object_byid(cave->o_idx[y][x])->marked) /* Known objects are yellow. */ colour = TERM_YELLOW; else if (!cave_ispassable(cave, y,x) && ((cave->info[y][x] & (CAVE_MARK)) || player_can_see_bold(y,x))) /* Known walls are blue. */ colour = TERM_BLUE; else if (!(cave->info[y][x] & (CAVE_MARK)) && !player_can_see_bold(y,x)) /* Unknown squares are grey. */ colour = TERM_L_DARK; else /* Unoccupied squares are white. */ colour = TERM_WHITE; /* Draw the path segment */ (void)Term_addch(colour, L'*'); } return i; }
/** * This is a helper function used by do_cmd_throw and do_cmd_fire. * * It abstracts out the projectile path, display code, identify and clean up * logic, while using the 'attack' parameter to do work particular to each * kind of attack. */ static void ranged_helper(int item, int dir, int range, int shots, ranged_attack attack) { /* Get the ammo */ object_type *o_ptr = object_from_item_idx(item); int i, j; byte missile_attr = object_attr(o_ptr); wchar_t missile_char; object_type object_type_body; object_type *i_ptr = &object_type_body; char o_name[80]; int path_n; u16b path_g[256]; int msec = op_ptr->delay_factor; /* Start at the player */ int x = p_ptr->px; int y = p_ptr->py; /* Predict the "target" location */ s16b ty = y + 99 * ddy[dir]; s16b tx = x + 99 * ddx[dir]; bool hit_target = FALSE; missile_char = object_char(o_ptr); /* Check for target validity */ if ((dir == 5) && target_okay()) { int taim; char msg[80]; target_get(&tx, &ty); taim = distance(y, x, ty, tx); if (taim > range) { sprintf (msg, "Target out of range by %d squares. Fire anyway? ", taim - range); if (!get_check(msg)) return; } } /* Sound */ sound(MSG_SHOOT); object_notice_on_firing(o_ptr); /* Describe the object */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_FULL | ODESC_SINGULAR); /* Actually "fire" the object -- Take a partial turn */ p_ptr->energy_use = (100 / shots); /* Calculate the path */ path_n = project_path(path_g, range, y, x, ty, tx, 0); /* Hack -- Handle stuff */ handle_stuff(p_ptr); /* Start at the player */ x = p_ptr->px; y = p_ptr->py; /* Project along the path */ for (i = 0; i < path_n; ++i) { int ny = GRID_Y(path_g[i]); int nx = GRID_X(path_g[i]); /* Hack -- Stop before hitting walls */ if (!cave_ispassable(cave, ny, nx)) break; /* Advance */ x = nx; y = ny; /* Only do visuals if the player can "see" the missile */ if (player_can_see_bold(y, x)) { print_rel(missile_char, missile_attr, y, x); move_cursor_relative(y, x); Term_fresh(); if (p_ptr->redraw) redraw_stuff(p_ptr); Term_xtra(TERM_XTRA_DELAY, msec); cave_light_spot(cave, y, x); Term_fresh(); if (p_ptr->redraw) redraw_stuff(p_ptr); } else { /* Delay anyway for consistency */ Term_xtra(TERM_XTRA_DELAY, msec); } /* Handle monster */ if (cave->m_idx[y][x] > 0) break; } /* Try the attack on the monster at (x, y) if any */ if (cave->m_idx[y][x] > 0) { monster_type *m_ptr = cave_monster_at(cave, y, x); int visible = m_ptr->ml; bool fear = FALSE; char m_name[80]; const char *note_dies = monster_is_unusual(m_ptr->race) ? " is destroyed." : " dies."; struct attack_result result = attack(o_ptr, y, x); int dmg = result.dmg; u32b msg_type = result.msg_type; const char *hit_verb = result.hit_verb; if (result.success) { hit_target = TRUE; /* Get "the monster" or "it" */ monster_desc(m_name, sizeof(m_name), m_ptr, 0); object_notice_attack_plusses(o_ptr); /* Learn by use for other equipped items */ wieldeds_notice_to_hit_on_attack(); /* No negative damage; change verb if no damage done */ if (dmg <= 0) { dmg = 0; msg_type = MSG_MISS; hit_verb = "fail to harm"; } if (!visible) { /* Invisible monster */ msgt(MSG_SHOOT_HIT, "The %s finds a mark.", o_name); } else { for (i = 0; i < (int)N_ELEMENTS(ranged_hit_types); i++) { const char *dmg_text = ""; if (msg_type != ranged_hit_types[i].msg) continue; if (OPT(show_damage)) dmg_text = format(" (%d)", dmg); if (ranged_hit_types[i].text) msgt(msg_type, "Your %s %s %s%s. %s", o_name, hit_verb, m_name, dmg_text, ranged_hit_types[i].text); else msgt(msg_type, "Your %s %s %s%s.", o_name, hit_verb, m_name, dmg_text); } /* Track this monster */ if (m_ptr->ml) monster_race_track(m_ptr->race); if (m_ptr->ml) health_track(p_ptr, m_ptr); } /* Hit the monster, check for death */ if (!mon_take_hit(m_ptr, dmg, &fear, note_dies)) { message_pain(m_ptr, dmg); if (fear && m_ptr->ml) add_monster_message(m_name, m_ptr, MON_MSG_FLEE_IN_TERROR, TRUE); } } } /* Obtain a local object */ object_copy(i_ptr, o_ptr); object_split(i_ptr, o_ptr, 1); /* See if the ammunition broke or not */ j = breakage_chance(i_ptr, hit_target); /* Drop (or break) near that location */ drop_near(cave, i_ptr, j, y, x, TRUE); if (item >= 0) { /* The ammo is from the inventory */ inven_item_increase(item, -1); inven_item_describe(item); inven_item_optimize(item); } else { /* The ammo is from the floor */ floor_item_increase(0 - item, -1); floor_item_optimize(0 - item); } }
/* * Query the dungeon */ static void do_cmd_wiz_query(void) { int py = p_ptr->py; int px = p_ptr->px; int y, x; struct keypress cmd; u16b mask = 0x00; /* Get a "debug command" */ if (!get_com("Debug Command Query: ", &cmd)) return; /* Extract a flag */ switch (cmd.code) { case '0': mask = (1 << 0); break; case '1': mask = (1 << 1); break; case '2': mask = (1 << 2); break; case '3': mask = (1 << 3); break; case '4': mask = (1 << 4); break; case '5': mask = (1 << 5); break; case '6': mask = (1 << 6); break; case '7': mask = (1 << 7); break; case 'm': mask |= (CAVE_MARK); break; case 'g': mask |= (CAVE_GLOW); break; case 'r': mask |= (CAVE_ROOM); break; case 'i': mask |= (CAVE_VAULT); break; case 's': mask |= (CAVE_SEEN); break; case 'v': mask |= (CAVE_VIEW); break; case 't': mask |= (CAVE_WASSEEN); break; case 'w': mask |= (CAVE_WALL); break; } /* Scan map */ for (y = Term->offset_y; y < Term->offset_y + SCREEN_HGT; y++) { for (x = Term->offset_x; x < Term->offset_x + SCREEN_WID; x++) { byte a = TERM_RED; if (!cave_in_bounds_fully(cave, y, x)) continue; /* Given mask, show only those grids */ if (mask && !(cave->info[y][x] & mask)) continue; /* Given no mask, show unknown grids */ if (!mask && (cave->info[y][x] & (CAVE_MARK))) continue; /* Color */ if (cave_ispassable(cave, y, x)) a = TERM_YELLOW; /* Display player/floors/walls */ if ((y == py) && (x == px)) print_rel(L'@', a, y, x); else if (cave_ispassable(cave, y, x)) print_rel(L'*', a, y, x); else print_rel(L'#', a, y, x); } } Term_redraw(); /* Get keypress */ msg("Press any key."); inkey_ex(); message_flush(); /* Redraw map */ prt_map(); }