/** * True if the player's current target is in LOS. */ bool target_sighted(void) { return target_okay() && panel_contains(target.grid.y, target.grid.x) && /* either the target is a grid and is visible, or it is a monster * that is visible */ ((!target.midx && square_isseen(cave, target.grid)) || (target.midx && monster_is_visible(cave_monster(cave, target.midx)))); }
/** * True if the player's current target is in LOS. */ bool target_sighted(void) { return target_okay() && panel_contains(target_y, target_x) && /* either the target is a grid and is visible, or it is a monster * that is visible */ ((!target_who && square_isseen(cave, target_y, target_x)) || (target_who && mflag_has(target_who->mflag, MFLAG_VISIBLE))); }
/** * Load the attr/char at each point along "path" which is on screen from * "a" and "c". This was saved in draw_path(). */ static void load_path(u16b path_n, u16b *path_g, wchar_t *c, int *a) { int i; for (i = 0; i < path_n; i++) { int y = GRID_Y(path_g[i]); int x = GRID_X(path_g[i]); if (!panel_contains(y, x)) continue; move_cursor_relative(y, x); Term_addch(a[i], c[i]); } Term_fresh(); }
/* * Load the attr/char at each point along "path" which is on screen from * "a" and "c". This was saved in draw_path(). */ static void load_path(u16b path_n, u16b *path_g, char *c, byte *a) { int i; for (i = 0; i < path_n; i++) { if (!panel_contains(GRID_Y(path_g[i]), GRID_X(path_g[i]))) continue; move_cursor_relative(GRID_Y(path_g[i]), GRID_X(path_g[i])); (void)Term_addch(a[i], c[i]); } (void)Term_fresh(); }
/* * 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, char *c, byte *a, int y1, int x1, int cur_tar_y, int cur_tar_x) { int i; bool on_screen; byte color_type; /* No path, so do nothing. */ if (path_n < 1) return (FALSE); /* 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++) { /* Find the co-ordinates on the level. */ int y = GRID_Y(path_g[i]); int x = GRID_X(path_g[i]); byte this_a; char this_c; /* * 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. */ /* Visible monsters are orange. */ if (cave_m_idx[y][x] && mon_list[cave_m_idx[y][x]].ml) { monster_type *m_ptr = &mon_list[cave_m_idx[y][x]]; /*mimics act as objects*/ if (m_ptr->mimic_k_idx) color_type = TERM_YELLOW; else color_type = TERM_ORANGE; } /* Known objects are yellow. */ else if (cave_o_idx[y][x] && o_list[cave_o_idx[y][x]].marked) { color_type = TERM_YELLOW; } /* Effects are green */ else if ((cave_x_idx[y][x] > 0) && (cave_info[y][x] & (CAVE_SEEN | CAVE_MARK))) { color_type = TERM_GREEN; } /* Known walls are blue. */ else if (!cave_project_bold(y,x) && ((cave_info[y][x] & (CAVE_MARK)) || player_can_see_bold(y,x))) { color_type = TERM_BLUE; } /* Unknown squares are grey. */ else if (!(cave_info[y][x] & (CAVE_MARK)) && !player_can_see_bold(y,x)) { color_type = TERM_L_DARK; } /* Unoccupied squares are white. */ else { color_type = TERM_WHITE; } /* ALways use red for the current target square */ if ((cur_tar_y == y) && (cur_tar_x == x)) color_type = TERM_RED; /* Get the character */ if (!use_graphics) { this_a = color_type; this_c = '*'; } /* Graphics are being used */ else { this_a = color_to_attr[TILE_BALL_INFO][color_type]; this_c = color_to_char[TILE_BALL_INFO][color_type]; } /* Visual effects -- Display */ print_rel(this_c, this_a, y, x); } return i; }
/** * 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; }
/** * 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, struct loc *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 = path_g[i].y; int x = path_g[i].x; struct monster *mon = square_monster(cave, y, x); struct object *obj = square_object(cave, y, x); /* * 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 (mon && mflag_has(mon->mflag, MFLAG_VISIBLE)) { /* Mimics act as objects */ if (rf_has(mon->race->flags, RF_UNAWARE)) colour = COLOUR_YELLOW; else /* Visible monsters are red. */ colour = COLOUR_L_RED; } else if (obj && obj->marked) /* Known objects are yellow. */ colour = COLOUR_YELLOW; else if ((!square_isprojectable(cave, y,x) && square_ismark(cave, y, x)) || square_isseen(cave, y, x)) /* Known walls are blue. */ colour = COLOUR_BLUE; else if (!square_ismark(cave, y, x) && !square_isseen(cave, y, x)) /* Unknown squares are grey. */ colour = COLOUR_L_DARK; else /* Unoccupied squares are white. */ colour = COLOUR_WHITE; /* Draw the path segment */ (void)Term_addch(colour, L'*'); } return i; }
/** * Builds a string describing a monster in some way. * * We can correctly describe monsters based on their visibility. * We can force all monsters to be treated as visible or invisible. * We can build nominatives, objectives, possessives, or reflexives. * We can selectively pronominalize hidden, visible, or all monsters. * We can use definite or indefinite descriptions for hidden monsters. * We can use definite or indefinite descriptions for visible monsters. * * Pronominalization involves the gender whenever possible and allowed, * so that by cleverly requesting pronominalization / visibility, you * can get messages like "You hit someone. She screams in agony!". * * Reflexives are acquired by requesting Objective plus Possessive. * * I am assuming that no monster name is more than 65 characters long, * so that "char desc[80];" is sufficiently large for any result, even * when the "offscreen" notation is added. * * Note that the "possessive" for certain unique monsters will look * really silly, as in "Morgoth, King of Darkness's". We should * perhaps add a flag to "remove" any "descriptives" in the name. * * Note that "offscreen" monsters will get a special "(offscreen)" * notation in their name if they are visible but offscreen. This * may look silly with possessives, as in "the rat's (offscreen)". * Perhaps the "offscreen" descriptor should be abbreviated. * * Mode Flags: * 0x01 --> Objective (or Reflexive) * 0x02 --> Possessive (or Reflexive) * 0x04 --> Use indefinites for hidden monsters ("something") * 0x08 --> Use indefinites for visible monsters ("a kobold") * 0x10 --> Pronominalize hidden monsters * 0x20 --> Pronominalize visible monsters * 0x40 --> Assume the monster is hidden * 0x80 --> Assume the monster is visible * 0x100 --> Capitalise monster name * * Useful Modes: * 0x00 --> Full nominative name ("the kobold") or "it" * 0x04 --> Full nominative name ("the kobold") or "something" * 0x80 --> Banishment resistance name ("the kobold") * 0x88 --> Killing name ("a kobold") * 0x22 --> Possessive, genderized if visable ("his") or "its" * 0x23 --> Reflexive, genderized if visable ("himself") or "itself" */ void monster_desc(char *desc, size_t max, const struct monster *mon, int mode) { const char *choice; bool seen, use_pronoun; assert(mon); /* Can we "see" it (forced, or not hidden + visible) */ seen = ((mode & (MDESC_SHOW)) || (!(mode & (MDESC_HIDE)) && mflag_has(mon->mflag, MFLAG_VISIBLE))); /* Sexed Pronouns (seen and forced, or unseen and allowed) */ use_pronoun = ((seen && (mode & (MDESC_PRO_VIS))) || (!seen && (mode & (MDESC_PRO_HID)))); /* First, try using pronouns, or describing hidden monsters */ if (!seen || use_pronoun) { /* an encoding of the monster "sex" */ int msex = 0x00; /* Extract the gender (if applicable) */ if (rf_has(mon->race->flags, RF_FEMALE)) msex = 0x20; else if (rf_has(mon->race->flags, RF_MALE)) msex = 0x10; /* Ignore the gender (if desired) */ if (!mon || !use_pronoun) msex = 0x00; /* Assume simple result */ choice = "it"; /* Brute force: split on the possibilities */ switch (msex + (mode & 0x07)) { /* Neuter, or unknown */ case 0x00: choice = "it"; break; case 0x01: choice = "it"; break; case 0x02: choice = "its"; break; case 0x03: choice = "itself"; break; case 0x04: choice = "something"; break; case 0x05: choice = "something"; break; case 0x06: choice = "something's"; break; case 0x07: choice = "itself"; break; /* Male (assume human if vague) */ case 0x10: choice = "he"; break; case 0x11: choice = "him"; break; case 0x12: choice = "his"; break; case 0x13: choice = "himself"; break; case 0x14: choice = "someone"; break; case 0x15: choice = "someone"; break; case 0x16: choice = "someone's"; break; case 0x17: choice = "himself"; break; /* Female (assume human if vague) */ case 0x20: choice = "she"; break; case 0x21: choice = "her"; break; case 0x22: choice = "her"; break; case 0x23: choice = "herself"; break; case 0x24: choice = "someone"; break; case 0x25: choice = "someone"; break; case 0x26: choice = "someone's"; break; case 0x27: choice = "herself"; break; } /* Copy the result */ my_strcpy(desc, choice, max); } else if ((mode & MDESC_POSS) && (mode & MDESC_OBJE)) { /* The monster is visible, so use its gender */ if (rf_has(mon->race->flags, RF_FEMALE)) my_strcpy(desc, "herself", max); else if (rf_has(mon->race->flags, RF_MALE)) my_strcpy(desc, "himself", max); else my_strcpy(desc, "itself", max); } else { /* Unique, indefinite or definite */ if (rf_has(mon->race->flags, RF_UNIQUE)) { /* Start with the name (thus nominative and objective) */ my_strcpy(desc, mon->race->name, max); } else if (mode & MDESC_IND_VIS) { /* XXX Check plurality for "some" */ /* Indefinite monsters need an indefinite article */ my_strcpy(desc, is_a_vowel(mon->race->name[0]) ? "an " : "a ", max); my_strcat(desc, mon->race->name, max); } else { /* Definite monsters need a definite article */ my_strcpy(desc, "the ", max); my_strcat(desc, mon->race->name, max); } /* Handle the Possessive as a special afterthought */ if (mode & MDESC_POSS) { /* XXX Check for trailing "s" */ /* Simply append "apostrophe" and "s" */ my_strcat(desc, "'s", max); } /* Mention "offscreen" monsters XXX XXX */ if (!panel_contains(mon->fy, mon->fx)) { /* Append special notation */ my_strcat(desc, " (offscreen)", max); } } if (mode & MDESC_CAPITAL) my_strcap(desc); }
static void _greater_whirlwind_attack_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Greater Ambush"); break; case SPELL_DESC: var_set_string(res, "Perform a massive ambush on nearby monsters."); break; case SPELL_CAST: { int i, x, y; cave_type *c_ptr; monster_type *m_ptr; /* cba d218l e3@7k f456j ghi */ typedef struct _offset_t { int dx; int dy; } _offset; static _offset offsets[] = { { 0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, { 0, 1}, { 1, 1}, { 1, 0}, { 1, -1}, { 1, -2}, { 0, -2}, {-1, -2}, {-2, -1}, {-2, 0}, {-2, 1}, {-1, 2}, { 0, 2}, { 1, 2}, { 2, 1}, { 2, 0}, { 2, -1}, { 0, 0}, /* sentinel */ }; for (i = 0;; i++) { _offset offset = offsets[i]; if (offset.dx == 0 && offset.dy == 0) break; y = py + offset.dy; x = px + offset.dx; if (!in_bounds(y, x)) continue; if (!projectable(py, px, y, x)) continue; c_ptr = &cave[y][x]; if (!c_ptr->m_idx) continue; m_ptr = &m_list[c_ptr->m_idx]; if (m_ptr->ml || cave_have_flag_bold(y, x, FF_PROJECT)) { int msec = delay_factor * delay_factor * delay_factor; if (panel_contains(y, x) && player_can_see_bold(y, x)) { char c = 0x30; byte a = TERM_WHITE; print_rel(c, a, y, x); move_cursor_relative(y, x); Term_fresh(); Term_xtra(TERM_XTRA_DELAY, msec); lite_spot(y, x); Term_fresh(); } else Term_xtra(TERM_XTRA_DELAY, msec); py_attack(y, x, 0); } } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }