Changeset 670

Show
Ignore:
Timestamp:
01/31/08 03:39:42 (10 months ago)
Author:
takkaria
Message:
  • Move ang_sort() & co into z-util.c. (not perfect, but better)
  • Split out targetting code into target.c for clarity (I expect to have to do some work on it soon)
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/Makefile.src

    r667 r670  
    9595        store.o \ 
    9696        tables.o \ 
     97        target.o \ 
    9798        trap.o \ 
    9899        ui.o \ 
  • trunk/src/externs.h

    r636 r670  
    233233extern byte item_tester_tval; 
    234234extern bool (*item_tester_hook)(const object_type*); 
    235 extern bool (*ang_sort_comp)(const void *u, const void *v, int a, int b); 
    236 extern void (*ang_sort_swap)(void *u, void *v, int a, int b); 
    237235extern bool (*get_mon_num_hook)(int r_idx); 
    238236extern bool (*get_obj_num_hook)(int k_idx); 
     
    552550extern void store_init(void); 
    553551 
     552/* target.c */ 
     553bool target_able(int m_idx); 
     554bool target_okay(void); 
     555void target_set_monster(int m_idx); 
     556void target_set_location(int y, int x); 
     557bool target_set_interactive(int mode); 
     558bool get_aim_dir(int *dp); 
     559 
    554560/* trap.c */ 
    555561extern void hit_trap(int y, int x); 
     
    649655bool change_panel(int dir); 
    650656void verify_panel(void); 
    651 void ang_sort_aux(void *u, void *v, int p, int q); 
    652 void ang_sort(void *u, void *v, int n); 
    653657int motion_dir(int y1, int x1, int y2, int x2); 
    654658int target_dir(char ch); 
    655 bool target_able(int m_idx); 
    656 bool target_okay(void); 
    657 void target_set_monster(int m_idx); 
    658 void target_set_location(int y, int x); 
    659 bool target_set_interactive(int mode); 
    660 bool get_aim_dir(int *dp); 
    661659bool get_rep_dir(int *dp); 
    662660bool confuse_dir(int *dp); 
  • trunk/src/variable.c

    r617 r670  
    726726 
    727727/* 
    728  * Current "comp" function for ang_sort() 
    729  */ 
    730 bool (*ang_sort_comp)(const void *u, const void *v, int a, int b); 
    731  
    732  
    733 /* 
    734  * Current "swap" function for ang_sort() 
    735  */ 
    736 void (*ang_sort_swap)(void *u, void *v, int a, int b); 
    737  
    738  
    739  
    740 /* 
    741728 * Hack -- function hook to restrict "get_mon_num_prep()" function 
    742729 */ 
  • trunk/src/xtra2.c

    r656 r670  
    17951795 
    17961796 
    1797  
    1798 /* 
    1799  * Monster health description 
    1800  */ 
    1801 static void look_mon_desc(char *buf, size_t max, int m_idx) 
    1802 { 
    1803         monster_type *m_ptr = &mon_list[m_idx]; 
    1804         monster_race *r_ptr = &r_info[m_ptr->r_idx]; 
    1805  
    1806         bool living = TRUE; 
    1807  
    1808  
    1809         /* Determine if the monster is "living" (vs "undead") */ 
    1810         if (r_ptr->flags3 & (RF3_UNDEAD)) living = FALSE; 
    1811         if (r_ptr->flags3 & (RF3_DEMON)) living = FALSE; 
    1812         if (strchr("Egv", r_ptr->d_char)) living = FALSE; 
    1813  
    1814  
    1815         /* Healthy monsters */ 
    1816         if (m_ptr->hp >= m_ptr->maxhp) 
    1817         { 
    1818                 /* No damage */ 
    1819                 my_strcpy(buf, (living ? "unhurt" : "undamaged"), max); 
    1820         } 
    1821         else 
    1822         { 
    1823                 /* Calculate a health "percentage" */ 
    1824                 int perc = 100L * m_ptr->hp / m_ptr->maxhp; 
    1825  
    1826                 if (perc >= 60) 
    1827                         my_strcpy(buf, (living ? "somewhat wounded" : "somewhat damaged"), max); 
    1828                 else if (perc >= 25) 
    1829                         my_strcpy(buf, (living ? "wounded" : "damaged"), max); 
    1830                 else if (perc >= 10) 
    1831                         my_strcpy(buf, (living ? "badly wounded" : "badly damaged"), max); 
    1832                 else 
    1833                         my_strcpy(buf, (living ? "almost dead" : "almost destroyed"), max); 
    1834         } 
    1835  
    1836         if (m_ptr->csleep) my_strcat(buf, ", asleep", max); 
    1837         if (m_ptr->confused) my_strcat(buf, ", confused", max); 
    1838         if (m_ptr->monfear) my_strcat(buf, ", afraid", max); 
    1839         if (m_ptr->stunned) my_strcat(buf, ", stunned", max); 
    1840 } 
    1841  
    1842  
    1843  
    1844 /* 
    1845  * Angband sorting algorithm -- quick sort in place 
    1846  * 
    1847  * Note that the details of the data we are sorting is hidden, 
    1848  * and we rely on the "ang_sort_comp()" and "ang_sort_swap()" 
    1849  * function hooks to interact with the data, which is given as 
    1850  * two pointers, and which may have any user-defined form. 
    1851  */ 
    1852 void ang_sort_aux(void *u, void *v, int p, int q) 
    1853 { 
    1854         int z, a, b; 
    1855  
    1856         /* Done sort */ 
    1857         if (p >= q) return; 
    1858  
    1859         /* Pivot */ 
    1860         z = p; 
    1861  
    1862         /* Begin */ 
    1863         a = p; 
    1864         b = q; 
    1865  
    1866         /* Partition */ 
    1867         while (TRUE) 
    1868         { 
    1869                 /* Slide i2 */ 
    1870                 while (!(*ang_sort_comp)(u, v, b, z)) b--; 
    1871  
    1872                 /* Slide i1 */ 
    1873                 while (!(*ang_sort_comp)(u, v, z, a)) a++; 
    1874  
    1875                 /* Done partition */ 
    1876                 if (a >= b) break; 
    1877  
    1878                 /* Swap */ 
    1879                 (*ang_sort_swap)(u, v, a, b); 
    1880  
    1881                 /* Advance */ 
    1882                 a++, b--; 
    1883         } 
    1884  
    1885         /* Recurse left side */ 
    1886         ang_sort_aux(u, v, p, b); 
    1887  
    1888         /* Recurse right side */ 
    1889         ang_sort_aux(u, v, b+1, q); 
    1890 } 
    1891  
    1892  
    1893 /* 
    1894  * Angband sorting algorithm -- quick sort in place 
    1895  * 
    1896  * Note that the details of the data we are sorting is hidden, 
    1897  * and we rely on the "ang_sort_comp()" and "ang_sort_swap()" 
    1898  * function hooks to interact with the data, which is given as 
    1899  * two pointers, and which may have any user-defined form. 
    1900  */ 
    1901 void ang_sort(void *u, void *v, int n) 
    1902 { 
    1903         /* Sort the array */ 
    1904         ang_sort_aux(u, v, 0, n-1); 
    1905 } 
    1906  
    1907  
    1908  
    1909  
    1910  
    1911 /*** Targetting Code ***/ 
    1912  
    1913  
    19141797/* 
    19151798 * Given a "source" and "target" location, extract a "direction", 
     
    20081891 
    20091892 
    2010 /* 
    2011  * Determine is a monster makes a reasonable target 
    2012  * 
    2013  * The concept of "targetting" was stolen from "Morgul" (?) 
    2014  * 
    2015  * The player can target any location, or any "target-able" monster. 
    2016  * 
    2017  * Currently, a monster is "target_able" if it is visible, and if 
    2018  * the player can hit it with a projection, and the player is not 
    2019  * hallucinating.  This allows use of "use closest target" macros. 
    2020  * 
    2021  * Future versions may restrict the ability to target "trappers" 
    2022  * and "mimics", but the semantics is a little bit weird. 
    2023  */ 
    2024 bool target_able(int m_idx) 
    2025 { 
    2026         int py = p_ptr->py; 
    2027         int px = p_ptr->px; 
    2028  
    2029         monster_type *m_ptr; 
    2030  
    2031         /* No monster */ 
    2032         if (m_idx <= 0) return (FALSE); 
    2033  
    2034         /* Get monster */ 
    2035         m_ptr = &mon_list[m_idx]; 
    2036  
    2037         /* Monster must be alive */ 
    2038         if (!m_ptr->r_idx) return (FALSE); 
    2039  
    2040         /* Monster must be visible */ 
    2041         if (!m_ptr->ml) return (FALSE); 
    2042  
    2043         /* Monster must be projectable */ 
    2044         if (!projectable(py, px, m_ptr->fy, m_ptr->fx)) return (FALSE); 
    2045  
    2046         /* Hack -- no targeting hallucinations */ 
    2047         if (p_ptr->timed[TMD_IMAGE]) return (FALSE); 
    2048  
    2049         /* Hack -- Never target trappers XXX XXX XXX */ 
    2050         /* if (CLEAR_ATTR && (CLEAR_CHAR)) return (FALSE); */ 
    2051  
    2052         /* Assume okay */ 
    2053         return (TRUE); 
    2054 } 
    2055  
    2056  
    2057  
    2058  
    2059 /* 
    2060  * Update (if necessary) and verify (if possible) the target. 
    2061  * 
    2062  * We return TRUE if the target is "okay" and FALSE otherwise. 
    2063  */ 
    2064 bool target_okay(void) 
    2065 { 
    2066         /* No target */ 
    2067         if (!p_ptr->target_set) return (FALSE); 
    2068  
    2069         /* Accept "location" targets */ 
    2070         if (p_ptr->target_who == 0) return (TRUE); 
    2071  
    2072         /* Check "monster" targets */ 
    2073         if (p_ptr->target_who > 0) 
    2074         { 
    2075                 int m_idx = p_ptr->target_who; 
    2076  
    2077                 /* Accept reasonable targets */ 
    2078                 if (target_able(m_idx)) 
    2079                 { 
    2080                         monster_type *m_ptr = &mon_list[m_idx]; 
    2081  
    2082                         /* Get the monster location */ 
    2083                         p_ptr->target_row = m_ptr->fy; 
    2084                         p_ptr->target_col = m_ptr->fx; 
    2085  
    2086                         /* Good target */ 
    2087                         return (TRUE); 
    2088                 } 
    2089         } 
    2090  
    2091         /* Assume no target */ 
    2092         return (FALSE); 
    2093 } 
    2094  
    2095  
    2096 /* 
    2097  * Set the target to a monster (or nobody) 
    2098  */ 
    2099 void target_set_monster(int m_idx) 
    2100 { 
    2101         /* Acceptable target */ 
    2102         if ((m_idx > 0) && target_able(m_idx)) 
    2103         { 
    2104                 monster_type *m_ptr = &mon_list[m_idx]; 
    2105  
    2106                 /* Save target info */ 
    2107                 p_ptr->target_set = TRUE; 
    2108                 p_ptr->target_who = m_idx; 
    2109                 p_ptr->target_row = m_ptr->fy; 
    2110                 p_ptr->target_col = m_ptr->fx; 
    2111         } 
    2112  
    2113         /* Clear target */ 
    2114         else 
    2115         { 
    2116                 /* Reset target info */ 
    2117                 p_ptr->target_set = FALSE; 
    2118                 p_ptr->target_who = 0; 
    2119                 p_ptr->target_row = 0; 
    2120                 p_ptr->target_col = 0; 
    2121         } 
    2122 } 
    2123  
    2124  
    2125 /* 
    2126  * Set the target to a location 
    2127  */ 
    2128 void target_set_location(int y, int x) 
    2129 { 
    2130         /* Legal target */ 
    2131         if (in_bounds_fully(y, x)) 
    2132         { 
    2133                 /* Save target info */ 
    2134                 p_ptr->target_set = TRUE; 
    2135                 p_ptr->target_who = 0; 
    2136                 p_ptr->target_row = y; 
    2137                 p_ptr->target_col = x; 
    2138         } 
    2139  
    2140         /* Clear target */ 
    2141         else 
    2142         { 
    2143                 /* Reset target info */ 
    2144                 p_ptr->target_set = FALSE; 
    2145                 p_ptr->target_who = 0; 
    2146                 p_ptr->target_row = 0; 
    2147                 p_ptr->target_col = 0; 
    2148         } 
    2149 } 
    2150  
    2151  
    2152 /* 
    2153  * Sorting hook -- comp function -- by "distance to player" 
    2154  * 
    2155  * We use "u" and "v" to point to arrays of "x" and "y" positions, 
    2156  * and sort the arrays by double-distance to the player. 
    2157  */ 
    2158 static bool ang_sort_comp_distance(const void *u, const void *v, int a, int b) 
    2159 { 
    2160         int py = p_ptr->py; 
    2161         int px = p_ptr->px; 
    2162  
    2163         byte *x = (byte*)(u); 
    2164         byte *y = (byte*)(v); 
    2165  
    2166         int da, db, kx, ky; 
    2167  
    2168         /* Absolute distance components */ 
    2169         kx = x[a]; kx -= px; kx = ABS(kx); 
    2170         ky = y[a]; ky -= py; ky = ABS(ky); 
    2171  
    2172         /* Approximate Double Distance to the first point */ 
    2173         da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx)); 
    2174  
    2175         /* Absolute distance components */ 
    2176         kx = x[b]; kx -= px; kx = ABS(kx); 
    2177         ky = y[b]; ky -= py; ky = ABS(ky); 
    2178  
    2179         /* Approximate Double Distance to the first point */ 
    2180         db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx)); 
    2181  
    2182         /* Compare the distances */ 
    2183         return (da <= db); 
    2184 } 
    2185  
    2186  
    2187 /* 
    2188  * Sorting hook -- swap function -- by "distance to player" 
    2189  * 
    2190  * We use "u" and "v" to point to arrays of "x" and "y" positions, 
    2191  * and sort the arrays by distance to the player. 
    2192  */ 
    2193 static void ang_sort_swap_distance(void *u, void *v, int a, int b) 
    2194 { 
    2195         byte *x = (byte*)(u); 
    2196         byte *y = (byte*)(v); 
    2197  
    2198         byte temp; 
    2199  
    2200         /* Swap "x" */ 
    2201         temp = x[a]; 
    2202         x[a] = x[b]; 
    2203         x[b] = temp; 
    2204  
    2205         /* Swap "y" */ 
    2206         temp = y[a]; 
    2207         y[a] = y[b]; 
    2208         y[b] = temp; 
    2209 } 
    2210  
    2211  
    2212  
    2213 /* 
    2214  * Hack -- help "select" a location (see below) 
    2215  */ 
    2216 static s16b target_pick(int y1, int x1, int dy, int dx) 
    2217 { 
    2218         int i, v; 
    2219  
    2220         int x2, y2, x3, y3, x4, y4; 
    2221  
    2222         int b_i = -1, b_v = 9999; 
    2223  
    2224  
    2225         /* Scan the locations */ 
    2226         for (i = 0; i < temp_n; i++) 
    2227         { 
    2228                 /* Point 2 */ 
    2229                 x2 = temp_x[i]; 
    2230                 y2 = temp_y[i]; 
    2231  
    2232                 /* Directed distance */ 
    2233                 x3 = (x2 - x1); 
    2234                 y3 = (y2 - y1); 
    2235  
    2236                 /* Verify quadrant */ 
    2237                 if (dx && (x3 * dx <= 0)) continue; 
    2238                 if (dy && (y3 * dy <= 0)) continue; 
    2239  
    2240                 /* Absolute distance */ 
    2241                 x4 = ABS(x3); 
    2242                 y4 = ABS(y3); 
    2243  
    2244                 /* Verify quadrant */ 
    2245                 if (dy && !dx && (x4 > y4)) continue; 
    2246                 if (dx && !dy && (y4 > x4)) continue; 
    2247  
    2248                 /* Approximate Double Distance */ 
    2249                 v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4)); 
    2250  
    2251                 /* Penalize location XXX XXX XXX */ 
    2252  
    2253                 /* Track best */ 
    2254                 if ((b_i >= 0) && (v >= b_v)) continue; 
    2255  
    2256                 /* Track best */ 
    2257                 b_i = i; b_v = v; 
    2258         } 
    2259  
    2260         /* Result */ 
    2261         return (b_i); 
    2262 } 
    2263  
    2264  
    2265 /* 
    2266  * Hack -- determine if a given location is "interesting" 
    2267  */ 
    2268 static bool target_set_interactive_accept(int y, int x) 
    2269 { 
    2270         object_type *o_ptr; 
    2271  
    2272  
    2273         /* Player grids are always interesting */ 
    2274         if (cave_m_idx[y][x] < 0) return (TRUE); 
    2275  
    2276  
    2277         /* Handle hallucination */ 
    2278         if (p_ptr->timed[TMD_IMAGE]) return (FALSE); 
    2279  
    2280  
    2281         /* Visible monsters */ 
    2282         if (cave_m_idx[y][x] > 0) 
    2283         { 
    2284                 monster_type *m_ptr = &mon_list[cave_m_idx[y][x]]; 
    2285  
    2286                 /* Visible monsters */ 
    2287                 if (m_ptr->ml) return (TRUE); 
    2288         } 
    2289  
    2290         /* Scan all objects in the grid */ 
    2291         for (o_ptr = get_first_object(y, x); o_ptr; o_ptr = get_next_object(o_ptr)) 
    2292         { 
    2293                 /* Memorized object */ 
    2294                 if (o_ptr->marked && !squelch_hide_item(o_ptr)) return (TRUE); 
    2295         } 
    2296  
    2297         /* Interesting memorized features */ 
    2298         if (cave_info[y][x] & (CAVE_MARK)) 
    2299         { 
    2300                 /* Notice glyphs */ 
    2301                 if (cave_feat[y][x] == FEAT_GLYPH) return (TRUE); 
    2302  
    2303                 /* Notice doors */ 
    2304                 if (cave_feat[y][x] == FEAT_OPEN) return (TRUE); 
    2305                 if (cave_feat[y][x] == FEAT_BROKEN) return (TRUE); 
    2306  
    2307                 /* Notice stairs */ 
    2308                 if (cave_feat[y][x] == FEAT_LESS) return (TRUE); 
    2309                 if (cave_feat[y][x] == FEAT_MORE) return (TRUE); 
    2310  
    2311                 /* Notice shops */ 
    2312                 if ((cave_feat[y][x] >= FEAT_SHOP_HEAD) && 
    2313                     (cave_feat[y][x] <= FEAT_SHOP_TAIL)) return (TRUE); 
    2314  
    2315                 /* Notice traps */ 
    2316                 if ((cave_feat[y][x] >= FEAT_TRAP_HEAD) && 
    2317                     (cave_feat[y][x] <= FEAT_TRAP_TAIL)) return (TRUE); 
    2318  
    2319                 /* Notice doors */ 
    2320                 if ((cave_feat[y][x] >= FEAT_DOOR_HEAD) && 
    2321                     (cave_feat[y][x] <= FEAT_DOOR_TAIL)) return (TRUE); 
    2322  
    2323                 /* Notice rubble */ 
    2324                 if (cave_feat[y][x] == FEAT_RUBBLE) return (TRUE); 
    2325  
    2326                 /* Notice veins with treasure */ 
    2327                 if (cave_feat[y][x] == FEAT_MAGMA_K) return (TRUE); 
    2328                 if (cave_feat[y][x] == FEAT_QUARTZ_K) return (TRUE); 
    2329         } 
    2330  
    2331         /* Nope */ 
    2332         return (FALSE); 
    2333 } 
    2334  
    2335  
    2336 /* 
    2337  * Prepare the "temp" array for "target_interactive_set" 
    2338  * 
    2339  * Return the number of target_able monsters in the set. 
    2340  */ 
    2341 static void target_set_interactive_prepare(int mode) 
    2342 { 
    2343         int y, x; 
    2344  
    2345         /* Reset "temp" array */ 
    2346         temp_n = 0; 
    2347  
    2348         /* Scan the current panel */ 
    2349         for (y = Term->offset_y; y < Term->offset_y + SCREEN_HGT; y++) 
    2350         { 
    2351                 for (x = Term->offset_x; x < Term->offset_x + SCREEN_WID; x++) 
    2352                 { 
    2353                         /* Check bounds */ 
    2354                         if (!in_bounds_fully(y, x)) continue; 
    2355  
    2356                         /* Require "interesting" contents */ 
    2357                         if (!target_set_interactive_accept(y, x)) continue; 
    2358  
    2359                         /* Special mode */ 
    2360                         if (mode & (TARGET_KILL)) 
    2361                         { 
    2362                                 /* Must contain a monster */ 
    2363                                 if (!(cave_m_idx[y][x] > 0)) continue; 
    2364  
    2365                                 /* Must be a targettable monster */ 
    2366                                 if (!target_able(cave_m_idx[y][x])) continue; 
    2367                         } 
    2368  
    2369                         /* Save the location */ 
    2370                         temp_x[temp_n] = x; 
    2371                         temp_y[temp_n] = y; 
    2372                         temp_n++; 
    2373                 } 
    2374         } 
    2375  
    2376         /* Set the sort hooks */ 
    2377         ang_sort_comp = ang_sort_comp_distance; 
    2378         ang_sort_swap = ang_sort_swap_distance; 
    2379  
    2380         /* Sort the positions */ 
    2381         ang_sort(temp_x, temp_y, temp_n); 
    2382 } 
    2383  
    2384  
    2385 /* 
    2386  * Examine a grid, return a keypress. 
    2387  * 
    2388  * The "mode" argument contains the "TARGET_LOOK" bit flag, which 
    2389  * indicates that the "space" key should scan through the contents 
    2390  * of the grid, instead of simply returning immediately.  This lets 
    2391  * the "look" command get complete information, without making the 
    2392  * "target" command annoying. 
    2393  * 
    2394  * The "info" argument contains the "commands" which should be shown 
    2395  * inside the "[xxx]" text.  This string must never be empty, or grids 
    2396  * containing monsters will be displayed with an extra comma. 
    2397  * 
    2398  * Note that if a monster is in the grid, we update both the monster 
    2399  * recall info and the health bar info to track that monster. 
    2400  * 
    2401  * This function correctly handles multiple objects per grid, and objects 
    2402  * and terrain features in the same grid, though the latter never happens. 
    2403  * 
    2404  * This function must handle blindness/hallucination. 
    2405  */ 
    2406 static ui_event_data target_set_interactive_aux(int y, int x, int mode, cptr info) 
    2407 { 
    2408         s16b this_o_idx = 0, next_o_idx = 0; 
    2409  
    2410         cptr s1, s2, s3; 
    2411  
    2412         bool boring; 
    2413  
    2414         bool floored; 
    2415  
    2416         int feat; 
    2417  
    2418         int floor_list[MAX_FLOOR_STACK]; 
    2419         int floor_num; 
    2420  
    2421         ui_event_data query; 
    2422  
    2423         char out_val[256]; 
    2424  
    2425  
    2426         /* Repeat forever */ 
    2427         while (1) 
    2428         { 
    2429                 /* Paranoia */ 
    2430                 query.key = ' '; 
    2431  
    2432                 /* Assume boring */ 
    2433                 boring = TRUE; 
    2434  
    2435                 /* Default */ 
    2436                 s1 = "You see "; 
    2437                 s2 = ""; 
    2438                 s3 = ""; 
    2439  
    2440  
    2441                 /* The player */ 
    2442                 if (cave_m_idx[y][x] < 0) 
    2443                 { 
    2444                         /* Description */ 
    2445                         s1 = "You are "; 
    2446  
    2447                         /* Preposition */ 
    2448                         s2 = "on "; 
    2449                 } 
    2450  
    2451  
    2452                 /* Hack -- hallucination */ 
    2453                 if (p_ptr->timed[TMD_IMAGE]) 
    2454                 { 
    2455                         cptr name = "something strange"; 
    2456  
    2457                         /* Display a message */ 
    2458                         if (p_ptr->wizard) 
    2459                         { 
    2460                                 strnfmt(out_val, sizeof(out_val), 
    2461                                         "%s%s%s%s [%s] (%d:%d)", s1, s2, s3, name, info, y, x); 
    2462                         } 
    2463                         else 
    2464                         { 
    2465                                 strnfmt(out_val, sizeof(out_val), 
    2466                                         "%s%s%s%s [%s]", s1, s2, s3, name, info); 
    2467                         } 
    2468  
    2469                         prt(out_val, 0, 0); 
    2470                         move_cursor_relative(y, x); 
    2471                         query = inkey_ex(); 
    2472  
    2473                         /* Stop on everything but "return" */ 
    2474                         if ((query.key != '\n') && (query.key != '\r')) break; 
    2475  
    2476                         /* Repeat forever */ 
    2477                         continue; 
    2478                 } 
    2479  
    2480  
    2481                 /* Actual monsters */ 
    2482                 if (cave_m_idx[y][x] > 0) 
    2483                 { 
    2484                         monster_type *m_ptr = &mon_list[cave_m_idx[y][x]]; 
    2485                         monster_race *r_ptr = &r_info[m_ptr->r_idx]; 
    2486  
    2487                         /* Visible */ 
    2488                         if (m_ptr->ml) 
    2489                         { 
    2490                                 bool recall = FALSE; 
    2491  
    2492                                 char m_name[80]; 
    2493  
    2494                                 /* Not boring */ 
    2495                                 boring = FALSE; 
    2496  
    2497                                 /* Get the monster name ("a kobold") */ 
    2498                                 monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_IND2); 
    2499  
    2500                                 /* Hack -- track this monster race */ 
    2501                                 monster_race_track(m_ptr->r_idx); 
    2502  
    2503                                 /* Hack -- health bar for this monster */ 
    2504                                 health_track(cave_m_idx[y][x]); 
    2505  
    2506                                 /* Hack -- handle stuff */ 
    2507                                 handle_stuff(); 
    2508  
    2509                                 /* Interact */ 
    2510                                 while (1) 
    2511                                 { 
    2512                                         /* Recall */ 
    2513                                         if (recall) 
    2514                                         { 
    2515                                                 /* Save screen */ 
    2516                                                 screen_save(); 
    2517  
    2518                                                 /* Recall on screen */ 
    2519                                                 screen_roff(m_ptr->r_idx); 
    2520  
    2521                                                 /* Hack -- Complete the prompt (again) */ 
    2522                                                 Term_addstr(-1, TERM_WHITE, format("  [r,%s]", info)); 
    2523  
    2524                                                 /* Command */ 
    2525                                                 query = inkey_ex(); 
    2526  
    2527                                                 /* Load screen */ 
    2528                                                 screen_load(); 
    2529                                         } 
    2530  
    2531                                         /* Normal */ 
    2532                                         else 
    2533                                         { 
    2534                                                 char buf[80]; 
    2535  
    2536                                                 /* Describe the monster */ 
    2537                                                 look_mon_desc(buf, sizeof(buf), cave_m_idx[y][x]); 
    2538  
    2539                                                 /* Describe, and prompt for recall */ 
    2540                                                 if (p_ptr->wizard) 
    2541                                                 { 
    2542                                                         strnfmt(out_val, sizeof(out_val), 
    2543                                                                 "%s%s%s%s (%s) [r,%s] (%d:%d)", 
    2544                                                             s1, s2, s3, m_name, buf, info, y, x); 
    2545                                                 } 
    2546                                                 else 
    2547                                                 { 
    2548                                                         strnfmt(out_val, sizeof(out_val), 
    2549                                                                 "%s%s%s%s (%s) [r,%s]", 
    2550                                                                 s1, s2, s3, m_name, buf, info); 
    2551                                                 } 
    2552  
    2553                                                 prt(out_val, 0, 0); 
    2554  
    2555                                                 /* Place cursor */ 
    2556                                                 move_cursor_relative(y, x); 
    2557  
    2558                                                 /* Command */ 
    2559                                                 query = inkey_ex(); 
    2560                                         } 
    2561  
    2562                                         /* Normal commands */ 
    2563                                         if (query.key != 'r') break; 
    2564  
    2565                                         /* Toggle recall */ 
    2566                                         recall = !recall; 
    2567                                 } 
    2568  
    2569                                 /* Stop on everything but "return"/"space" */ 
    2570                                 if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; 
    2571  
    2572                                 /* Sometimes stop at "space" key */ 
    2573                                 if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; 
    2574  
    2575                                 /* Change the intro */ 
    2576                                 s1 = "It is "; 
    2577  
    2578                                 /* Hack -- take account of gender */ 
    2579                                 if (r_ptr->flags1 & (RF1_FEMALE)) s1 = "She is "; 
    2580                                 else if (r_ptr->flags1 & (RF1_MALE)) s1 = "He is "; 
    2581  
    2582                                 /* Use a preposition */ 
    2583                                 s2 = "carrying "; 
    2584  
    2585                                 /* Scan all objects being carried */ 
    2586                                 for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx) 
    2587                                 { 
    2588                                         char o_name[80]; 
    2589  
    2590                                         object_type *o_ptr; 
    2591  
    2592                                         /* Get the object */ 
    2593                                         o_ptr = &o_list[this_o_idx]; 
    2594  
    2595                                         /* Get the next object */ 
    2596                                         next_o_idx = o_ptr->next_o_idx; 
    2597  
    2598                                         /* Obtain an object description */ 
    2599                                         object_desc(o_name, sizeof(o_name), o_ptr, TRUE, ODESC_FULL); 
    2600  
    2601                                         /* Describe the object */ 
    2602                                         if (p_ptr->wizard) 
    2603                                         { 
    2604                                                 strnfmt(out_val, sizeof(out_val), 
    2605                                                         "%s%s%s%s [%s] (%d:%d)", 
    2606                                                         s1, s2, s3, o_name, info, y, x); 
    2607                                         } 
    2608                                         else 
    2609                                         { 
    2610                                                 strnfmt(out_val, sizeof(out_val), 
    2611                                                         "%s%s%s%s [%s]", s1, s2, s3, o_name, info); 
    2612                                         } 
    2613  
    2614                                         prt(out_val, 0, 0); 
    2615                                         move_cursor_relative(y, x); 
    2616                                         query = inkey_ex(); 
    2617  
    2618                                         /* Stop on everything but "return"/"space" */ 
    2619                                         if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; 
    2620  
    2621                                         /* Sometimes stop at "space" key */ 
    2622                                         if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; 
    2623  
    2624                                         /* Change the intro */ 
    2625                                         s2 = "also carrying "; 
    2626                                 } 
    2627  
    2628                                 /* Double break */ 
    2629                                 if (this_o_idx) break; 
    2630  
    2631                                 /* Use a preposition */ 
    2632                                 s2 = "on "; 
    2633                         } 
    2634                 } 
    2635  
    2636  
    2637                 /* Assume not floored */ 
    2638                 floored = FALSE; 
    2639  
    2640                 floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), y, x, 0x02); 
    2641  
    2642                 /* Scan all marked objects in the grid */ 
    2643                 if ((floor_num > 0) && 
    2644                     (!(p_ptr->timed[TMD_BLIND]) || (y == p_ptr->py && x == p_ptr->px))) 
    2645                 { 
    2646                         /* Not boring */ 
    2647                         boring = FALSE; 
    2648  
    2649                         /* If there is more than one item... */ 
    2650                         if (floor_num > 1) while (1) 
    2651                         { 
    2652                                 floored = TRUE; 
    2653  
    2654                                 /* Describe the pile */ 
    2655                                 if (p_ptr->wizard) 
    2656                                 { 
    2657                                         strnfmt(out_val, sizeof(out_val), 
    2658                                                 "%s%s%sa pile of %d objects [r,%s] (%d:%d)", 
    2659                                                 s1, s2, s3, floor_num, info, y, x); 
    2660                                 } 
    2661                                 else 
    2662                                 { 
    2663                                         strnfmt(out_val, sizeof(out_val), 
    2664                                                 "%s%s%sa pile of %d objects [r,%s]", 
    2665                                                 s1, s2, s3, floor_num, info); 
    2666                                 } 
    2667  
    2668                                 prt(out_val, 0, 0); 
    2669                                 move_cursor_relative(y, x); 
    2670                                 query = inkey_ex(); 
    2671  
    2672                                 /* Display objects */ 
    2673                                 if (query.key == 'r') 
    2674                                 { 
    2675                                         /* Save screen */ 
    2676                                         screen_save(); 
    2677  
    2678                                         /* Display */ 
    2679                                         show_floor(floor_list, floor_num, TRUE); 
    2680  
    2681                                         /* Describe the pile */ 
    2682                                         prt(out_val, 0, 0); 
    2683                                         query = inkey_ex(); 
    2684  
    2685                                         /* Load screen */ 
    2686                                         screen_load(); 
    2687  
    2688                                         /* Continue on 'r' only */ 
    2689                                         if (query.key == 'r') continue; 
    2690                                 } 
    2691  
    2692                                 /* Done */ 
    2693                                 break; 
    2694                         } 
    2695                         /* Only one object to display */ 
    2696                         else 
    2697                         { 
    2698  
    2699                                 char o_name[80]; 
    2700  
    2701                                 /* Get the single object in the list */ 
    2702                                 object_type *o_ptr = &o_list[floor_list[0]]; 
    2703  
    2704                                 /* Not boring */ 
    2705                                 boring = FALSE; 
    2706  
    2707                                 /* Obtain an object description */ 
    2708                                 object_desc(o_name, sizeof(o_name), o_ptr, TRUE, ODESC_FULL); 
    2709  
    2710                                 /* Describe the object */ 
    2711                                 if (p_ptr->wizard) 
    2712                                 { 
    2713                                   &