Changeset 590

Show
Ignore:
Timestamp:
09/29/07 16:23:35 (1 year ago)
Author:
takkaria
Message:

Have a go at making object descriptions more terse, as part of #399.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/obj-info.c

    r570 r590  
    2020#include "cmds.h" 
    2121 
    22  
    23 /* TRUE if a paragraph break should be output before next p_text_out() */ 
    24 static bool new_paragraph = FALSE; 
    25  
    26  
    27 static void p_text_out(cptr str) 
    28 
    29         if (new_paragraph) 
    30         { 
    31                 text_out("\n\n"); 
    32                 new_paragraph = FALSE; 
    33         } 
    34  
    35         text_out(str); 
    36 
    37  
    38  
    39 static void output_list(const char *list[], int num) 
    40 
    41         int i; 
    42         const char *conjunction = "and "; 
    43  
    44         if (num < 0) 
    45         { 
    46                 num = -num; 
    47                 conjunction = "or "; 
    48         } 
    49  
    50         for (i = 0; i < num; i++) 
    51         { 
    52         if (i) 
     22/* 
     23 * Describes a flag-name pair. 
     24 */ 
     25typedef struct 
     26
     27        u32b flag; 
     28        const char *name; 
     29} flag_type; 
     30 
     31 
     32 
     33/*** Utility code ***/ 
     34 
     35/* 
     36 * Given an array of strings, as so: 
     37 *  { "intelligence", "fish", "lens", "prime", "number" }, 
     38 * 
     39 * ... output a list like "intelligence, fish, lens, prime, number.\n". 
     40 */ 
     41static inline void info_out_list(const char *list[], size_t count) 
     42
     43        size_t i; 
     44 
     45        for (i = 0; i < count; i++) 
     46        { 
     47                text_out(list[i]); 
     48                if (i != (count - 1)) text_out(", "); 
     49        } 
     50 
     51        text_out(".\n"); 
     52
     53 
     54 
     55/* 
     56 * 
     57 */ 
     58size_t info_collect(const flag_type list[], size_t max, u32b flag, const char *recepticle[]) 
     59
     60        size_t i, count = 0; 
     61 
     62        for (i = 0; i < max; i++) 
     63        { 
     64                if (flag & list[i].flag) 
     65                        recepticle[count++] = list[i].name; 
     66        } 
     67 
     68        return count; 
     69
     70 
     71 
     72/*** Big fat data tables ***/ 
     73 
     74static const flag_type f1_pval[] = 
     75
     76        { TR1_STR,     "strength" }, 
     77        { TR1_INT,     "intelligence" }, 
     78        { TR1_WIS,     "wisdom" }, 
     79        { TR1_DEX,     "dexterity" }, 
     80        { TR1_CON,     "constitution" }, 
     81        { TR1_CHR,     "charisma" }, 
     82        { TR1_STEALTH, "stealth" }, 
     83        { TR1_SEARCH,  "searching" }, 
     84        { TR1_INFRA,   "infravision" }, 
     85        { TR1_TUNNEL,  "tunneling" }, 
     86        { TR1_SPEED,   "speed" }, 
     87        { TR1_BLOWS,   "attack speed" }, 
     88        { TR1_SHOTS,   "shooting speed" }, 
     89        { TR1_MIGHT,   "shooting power" }, 
     90}; 
     91 
     92static const flag_type f2_immunity[] = 
     93
     94        { TR2_IM_ACID, "acid" }, 
     95        { TR2_IM_ELEC, "lightning" }, 
     96        { TR2_IM_FIRE, "fire" }, 
     97        { TR2_IM_COLD, "cold" }, 
     98}; 
     99 
     100static const flag_type f2_resist[] = 
     101
     102        { TR2_RES_ACID,  "acid" }, 
     103        { TR2_RES_ELEC,  "lightning" }, 
     104        { TR2_RES_FIRE,  "fire" }, 
     105        { TR2_RES_COLD,  "cold" }, 
     106        { TR2_RES_POIS,  "poison" }, 
     107        { TR2_RES_FEAR,  "fear" }, 
     108        { TR2_RES_LITE,  "light" }, 
     109        { TR2_RES_DARK,  "dark" }, 
     110        { TR2_RES_BLIND, "blindness" }, 
     111        { TR2_RES_CONFU, "confusion" }, 
     112        { TR2_RES_SOUND, "sound" }, 
     113        { TR2_RES_SHARD, "shards" }, 
     114        { TR2_RES_NEXUS, "nexus"  }, 
     115        { TR2_RES_NETHR, "nether" }, 
     116        { TR2_RES_CHAOS, "chaos" }, 
     117        { TR2_RES_DISEN, "disenchantment" }, 
     118}; 
     119 
     120static const flag_type f3_ignore[] = 
     121
     122        { TR3_IGNORE_ACID, "acid" }, 
     123        { TR3_IGNORE_ELEC, "electricity" }, 
     124        { TR3_IGNORE_FIRE, "fire" }, 
     125        { TR3_IGNORE_COLD, "cold" }, 
     126}; 
     127 
     128static const flag_type f2_sustains[] = 
     129
     130        { TR2_SUST_STR, "strength" }, 
     131        { TR2_SUST_INT, "intelligence" }, 
     132        { TR2_SUST_WIS, "wisdom" }, 
     133        { TR2_SUST_DEX, "dexterity" }, 
     134        { TR2_SUST_CON, "constitution" }, 
     135        { TR2_SUST_CHR, "charisma" }, 
     136}; 
     137 
     138static const flag_type f3_misc[] = 
     139
     140        { TR3_BLESSED,     "Blessed by the gods" }, 
     141        { TR3_SLOW_DIGEST, "Slows your metabolism" }, 
     142        { TR3_FEATHER,     "Feather Falling" }, 
     143        { TR3_REGEN,       "Speeds regeneration" }, 
     144        { TR3_FREE_ACT,    "Prevents paralysis" }, 
     145        { TR3_HOLD_LIFE,   "Stops experience drain" }, 
     146        { TR3_TELEPATHY,   "Grants telepathy" }, 
     147        { TR3_SEE_INVIS,   "Grants the ability to see invisible things" }, 
     148        { TR3_AGGRAVATE,   "Aggravates creatures nearby" }, 
     149        { TR3_DRAIN_EXP,   "Drains experience" }, 
     150        { TR3_TELEPORT,    "Induces random teleportation" }, 
     151}; 
     152 
     153 
     154/*** Code that makes use of the data tables ***/ 
     155 
     156/* 
     157 * Describe stat modifications. 
     158 */ 
     159static bool describe_stats(u32b f1, int pval) 
     160
     161        cptr descs[N_ELEMENTS(f1_pval)]; 
     162        size_t count; 
     163 
     164        if (!pval) return FALSE; 
     165 
     166        count = info_collect(f1_pval, N_ELEMENTS(f1_pval), f1, descs); 
     167        if (!count) return FALSE; 
     168 
     169        text_out_c((pval > 0) ? TERM_L_GREEN : TERM_RED, "%+i ", pval); 
     170        info_out_list(descs, count); 
     171 
     172        return TRUE; 
     173
     174 
     175 
     176/* 
     177 * Describe immunities granted by an object. 
     178 */ 
     179static bool describe_immune(u32b f2) 
     180
     181        const char *descs[N_ELEMENTS(f2_resist)]; 
     182        size_t count; 
     183 
     184        bool prev = FALSE; 
     185 
     186        /* Immunities */ 
     187        count = info_collect(f2_immunity, N_ELEMENTS(f2_immunity), f2, descs); 
     188        if (count) 
     189        { 
     190                text_out("Provides immunity to "); 
     191                info_out_list(descs, count); 
     192                prev = TRUE; 
     193        } 
     194 
     195        /* Resistances */ 
     196        count = info_collect(f2_resist, N_ELEMENTS(f2_resist), f2, descs); 
     197        if (count) 
     198        { 
     199                text_out("Provides resistance to "); 
     200                info_out_list(descs, count); 
     201                prev = TRUE; 
     202        } 
     203 
     204        return prev; 
     205
     206 
     207 
     208/* 
     209 * Describe 'ignores' of an object. 
     210 */ 
     211static bool describe_ignores(u32b f3) 
     212
     213        const char *descs[N_ELEMENTS(f3_ignore)]; 
     214        size_t count = info_collect(f3_ignore, N_ELEMENTS(f3_ignore), f3, descs); 
     215 
     216        if (!count) return FALSE; 
     217 
     218        text_out("Cannot be harmed by "); 
     219        info_out_list(descs, count); 
     220 
     221        return TRUE; 
     222
     223 
     224 
     225/* 
     226 * Describe stat sustains. 
     227 */ 
     228static bool describe_sustains(u32b f2) 
     229
     230        const char *descs[N_ELEMENTS(f2_sustains)]; 
     231        size_t count = info_collect(f2_sustains, N_ELEMENTS(f2_sustains), f2, descs); 
     232 
     233        if (!count) return FALSE; 
     234 
     235        text_out("Sustains "); 
     236        info_out_list(descs, count); 
     237 
     238        return TRUE; 
     239
     240 
     241 
     242/* 
     243 * Describe miscellaneous powers. 
     244 */ 
     245static bool describe_misc_magic(u32b f3) 
     246
     247        size_t i; 
     248        bool printed = FALSE; 
     249 
     250        for (i = 0; i < N_ELEMENTS(f3_misc); i++) 
     251        { 
     252                if (f3 & f3_misc[i].flag) 
    53253                { 
    54                         if (num > 2) 
    55                                 text_out(", "); 
    56                         else 
    57                                 text_out(" "); 
    58  
    59                         if (i == num - 1) 
    60                                 text_out(conjunction); 
     254                        text_out("%s.\n", f3_misc[i].name); 
     255                        printed = TRUE; 
    61256                } 
    62  
    63                 text_out(list[i]); 
    64         } 
    65 
    66  
    67  
    68 static void output_desc_list(cptr intro, cptr list[], int n) 
    69 
    70         if (!n) return; 
    71  
    72         p_text_out(intro); 
    73         output_list(list, n); 
    74         text_out(".  "); 
    75 
    76  
    77  
    78  
    79 /* 
    80  * Describe stat modifications. 
    81  */ 
    82 static bool describe_stats(const object_type *o_ptr, u32b f1) 
    83 
    84         cptr descs[16]; 
    85         int cnt = 0; 
    86         bool prev = FALSE; 
    87  
    88         int pval = (o_ptr->pval > 0 ? o_ptr->pval : -o_ptr->pval); 
    89         const char *what = (o_ptr->pval > 0) ? "increases" : "decreases"; 
    90         byte col = (o_ptr->pval > 0) ? TERM_L_GREEN : TERM_RED; 
    91  
    92  
    93         /* No pval?  Forget it! */ 
    94         if (!o_ptr->pval) return FALSE; 
    95  
    96         /* Collect stat bonuses */ 
    97         cnt = 0; 
    98         if (f1 & (TR1_STR)) descs[cnt++] = stat_names_full[A_STR]; 
    99         if (f1 & (TR1_INT)) descs[cnt++] = stat_names_full[A_INT]; 
    100         if (f1 & (TR1_WIS)) descs[cnt++] = stat_names_full[A_WIS]; 
    101         if (f1 & (TR1_DEX)) descs[cnt++] = stat_names_full[A_DEX]; 
    102         if (f1 & (TR1_CON)) descs[cnt++] = stat_names_full[A_CON]; 
    103         if (f1 & (TR1_CHR)) descs[cnt++] = stat_names_full[A_CHR]; 
    104  
    105     /* Shorten to "all stats" if appropriate */ 
    106         if (cnt == A_MAX) 
    107         { 
    108                 p_text_out(format("It %s all your stats", what)); 
    109                 cnt = 0; 
    110                 prev = TRUE; 
    111         } 
    112  
    113         /* Collect secondry bonuses */ 
    114         if (f1 & (TR1_STEALTH)) descs[cnt++] = "stealth"; 
    115         if (f1 & (TR1_SEARCH))  descs[cnt++] = "searching"; 
    116         if (f1 & (TR1_INFRA))   descs[cnt++] = "infravision"; 
    117         if (f1 & (TR1_TUNNEL))  descs[cnt++] = "tunneling"; 
    118         if (f1 & (TR1_SPEED))   descs[cnt++] = "speed"; 
    119         if (f1 & (TR1_BLOWS))   descs[cnt++] = "attack speed"; 
    120         if (f1 & (TR1_SHOTS))   descs[cnt++] = "shooting speed"; 
    121         if (f1 & (TR1_MIGHT))   descs[cnt++] = "shooting power"; 
    122  
    123         if (cnt) 
    124         { 
    125                 if (prev) 
    126                         text_out(" and your "); 
    127                 else 
    128                         p_text_out(format("It %s your ", what)); 
    129  
    130                 /* Output list */ 
    131                 output_list(descs, cnt); 
    132                 prev = TRUE; 
    133         } 
    134  
    135         /* Output end */ 
    136         if (prev) 
    137         { 
    138                 text_out(" by "); 
    139                 text_out_c(col, "%i", pval); 
    140                 text_out(".  "); 
    141         } 
    142  
    143         return prev; 
    144 
     257        } 
     258 
     259        return printed; 
     260
     261 
     262 
     263 
     264 
     265 
     266 
     267 
     268 
     269 
     270 
    145271 
    146272/* 
     
    176302 
    177303 
     304 
    178305/* 
    179306 * Describe combat advantages. 
     
    201328                if (!object_known_p(o_ptr)) return FALSE; 
    202329 
    203                 p_text_out("It can be thrown at monsters with damaging effect.  "); 
     330                text_out("It can be thrown at creatures with damaging effect.\n"); 
    204331                return TRUE; 
    205332        } 
     
    224351                if (adj_str_hold[p_ptr->stat_ind[A_STR]] < o_ptr->weight / 10) 
    225352                { 
    226                         if (new_paragraph) { text_out("\n\n"); new_paragraph = FALSE; } 
    227                         text_out_c(TERM_L_RED, "You are too weak to use this weapon effectively!  "); 
     353                        text_out_c(TERM_L_RED, "You are too weak to use this weapon effectively!\n"); 
    228354                        blows = 1; 
    229355                } 
    230356         
    231             p_text_out("Using this weapon, in your current condition, you are able to score "); 
     357            text_out("With this weapon, you would currently get "); 
    232358            text_out_c(TERM_L_GREEN, format("%d ", blows)); 
    233359            if (blows > 1) 
     
    247373                xtra_dam += (dam * 2); 
    248374 
    249                 p_text_out("Fired from your current bow, this arrow will hit targets up to "); 
     375                text_out("Fired from your current missile launcher, this arrow will hit targets up to "); 
    250376                text_out_c(TERM_L_GREEN, format("%d", tdis * 10)); 
    251377                text_out(" feet away, inflicting an average damage of "); 
     
    274400                text_out_c(TERM_L_GREEN, "%d", dam / 10); 
    275401 
    276         text_out(" against normal creatures.  "); 
     402        text_out(" against normal creatures.\n"); 
     403 
     404        /* Note the impact flag */ 
     405        if (f3 & TR3_IMPACT) 
     406                text_out("Sometimes creates earthquakes on impact.\n"); 
    277407 
    278408        /* Add breakage chance */ 
    279409        if (ammo) 
    280410        { 
    281                 text_out("It has a "); 
    282411                text_out_c(TERM_L_GREEN, "%d%%", breakage_chance(o_ptr)); 
    283                 text_out(" chance of breaking upon contact."); 
     412                text_out(" chance of breaking upon contact.\n"); 
    284413        } 
    285414 
     
    289418 
    290419 
    291 /* 
    292  * Describe immunities granted by an object. 
    293  */ 
    294 static bool describe_immune(const object_type *o_ptr, u32b f2, u32b f3) 
    295 
    296         cptr vp[26]; 
    297         int vn; 
    298         bool prev = FALSE; 
    299  
    300         /* Unused parameter */ 
    301         (void)o_ptr; 
    302  
    303         /* Collect immunities */ 
    304         vn = 0; 
    305         if (f2 & (TR2_IM_ACID))  vp[vn++] = "acid"; 
    306         if (f2 & (TR2_IM_ELEC))  vp[vn++] = "lightning"; 
    307         if (f2 & (TR2_IM_FIRE))  vp[vn++] = "fire"; 
    308         if (f2 & (TR2_IM_COLD))  vp[vn++] = "cold"; 
    309         if (f3 & (TR3_FREE_ACT)) vp[vn++] = "paralysis"; 
    310  
    311         /* Describe immunities */ 
    312         if (vn) 
    313         { 
    314                 text_out("It provides immunity to "); 
    315  
    316                 output_list(vp, vn); 
    317                 prev = TRUE; 
    318         } 
    319  
    320         /* Collect resistances */ 
    321         vn = 0; 
    322         if ((f2 & (TR2_RES_ACID)) && !(f2 & (TR2_IM_ACID))) 
    323                 vp[vn++] = "acid"; 
    324         if ((f2 & (TR2_RES_ELEC)) && !(f2 & (TR2_IM_ELEC))) 
    325                 vp[vn++] = "lightning"; 
    326         if ((f2 & (TR2_RES_FIRE)) && !(f2 & (TR2_IM_FIRE))) 
    327                 vp[vn++] = "fire"; 
    328         if ((f2 & (TR2_RES_COLD)) && !(f2 & (TR2_IM_COLD))) 
    329                 vp[vn++] = "cold"; 
    330  
    331         if (f2 & (TR2_RES_POIS))  vp[vn++] = "poison"; 
    332         if (f2 & (TR2_RES_FEAR))  vp[vn++] = "fear"; 
    333         if (f2 & (TR2_RES_LITE))  vp[vn++] = "light"; 
    334         if (f2 & (TR2_RES_DARK))  vp[vn++] = "dark"; 
    335         if (f2 & (TR2_RES_BLIND)) vp[vn++] = "blindness"; 
    336         if (f2 & (TR2_RES_CONFU)) vp[vn++] = "confusion"; 
    337         if (f2 & (TR2_RES_SOUND)) vp[vn++] = "sound"; 
    338         if (f2 & (TR2_RES_SHARD)) vp[vn++] = "shards"; 
    339         if (f2 & (TR2_RES_NEXUS)) vp[vn++] = "nexus" ; 
    340         if (f2 & (TR2_RES_NETHR)) vp[vn++] = "nether"; 
    341         if (f2 & (TR2_RES_CHAOS)) vp[vn++] = "chaos"; 
    342         if (f2 & (TR2_RES_DISEN)) vp[vn++] = "disenchantment"; 
    343         if (f3 & (TR3_HOLD_LIFE)) vp[vn++] = "life draining"; 
    344  
    345         if (vn) 
    346         { 
    347                 if (prev) 
    348                         text_out(", and provides resistance to "); 
    349                 else 
    350                         p_text_out("It provides resistance to "); 
    351  
    352                 /* Output list */ 
    353                 output_list(vp, vn); 
    354                 prev = TRUE; 
    355         } 
    356  
    357         /* Parting words */ 
    358         if (prev) text_out(".  "); 
    359  
    360         return prev; 
    361 
    362  
    363  
    364 /* 
    365  * Describe 'ignores' of an object. 
    366  */ 
    367 static bool describe_ignores(const object_type *o_ptr, u32b f3) 
    368 
    369         cptr list[4]; 
    370         int n = 0; 
    371  
    372         /* Unused parameter */ 
    373         (void)o_ptr; 
    374  
    375         /* Collect the ignores */ 
    376         if (f3 & (TR3_IGNORE_ACID)) list[n++] = "acid"; 
    377         if (f3 & (TR3_IGNORE_ELEC)) list[n++] = "electricity"; 
    378         if (f3 & (TR3_IGNORE_FIRE)) list[n++] = "fire"; 
    379         if (f3 & (TR3_IGNORE_COLD)) list[n++] = "cold"; 
    380  
    381         /* Describe ignores */ 
    382         if (n == 4) 
    383                 p_text_out("It cannot be harmed by the elements.  "); 
    384         else 
    385                 output_desc_list("It cannot be harmed by ", list, -n); 
    386  
    387         return (n ? TRUE : FALSE); 
    388 
    389  
    390  
    391 /* 
    392  * Describe stat sustains. 
    393  */ 
    394 static bool describe_sustains(const object_type *o_ptr, u32b f2) 
    395 
    396         cptr list[A_MAX]; 
    397         int n = 0; 
    398  
    399         /* Unused parameter */ 
    400         (void)o_ptr; 
    401  
    402         /* Collect the sustains */ 
    403         if (f2 & (TR2_SUST_STR)) list[n++] = stat_names_full[A_STR]; 
    404         if (f2 & (TR2_SUST_INT)) list[n++] = stat_names_full[A_INT]; 
    405         if (f2 & (TR2_SUST_WIS)) list[n++] = stat_names_full[A_WIS]; 
    406         if (f2 & (TR2_SUST_DEX)) list[n++] = stat_names_full[A_DEX]; 
    407         if (f2 & (TR2_SUST_CON)) list[n++] = stat_names_full[A_CON]; 
    408         if (f2 & (TR2_SUST_CHR)) list[n++] = stat_names_full[A_CHR]; 
    409  
    410         /* Describe immunities */ 
    411         if (n == A_MAX) 
    412                 p_text_out("It sustains all your stats.  "); 
    413         else 
    414                 output_desc_list("It sustains your ", list, n); 
    415  
    416         /* We are done here */ 
    417         return (n ? TRUE : FALSE); 
    418 
    419  
    420  
    421 /* 
    422  * Describe miscellaneous powers such as see invisible, free action, 
    423  * permanent light, etc; also note curses and penalties. 
    424  */ 
    425 static bool describe_misc_magic(const object_type *o_ptr, u32b f3) 
    426 
    427         cptr good[6], bad[4]; 
    428         int gc = 0, bc = 0; 
    429         bool something = FALSE; 
    430  
    431         /* Describe lights */ 
    432         if (o_ptr->tval == TV_LITE || (f3 & TR3_LITE)) 
    433         { 
    434                 bool artifact = artifact_p(o_ptr); 
    435                 bool no_fuel = (f3 & TR3_NO_FUEL) ? TRUE : FALSE; 
    436                 int rad = 0; 
    437  
    438                 if (artifact) 
    439                         rad = 3; 
    440                 else if (o_ptr->tval == TV_LITE) 
    441                         rad = 2; 
    442  
    443                 if (f3 & TR3_LITE) rad++; 
    444  
    445                 p_text_out("It usually provides light of radius "); 
    446                 text_out_c(TERM_L_GREEN, format("%d", rad)); 
    447                 if (no_fuel && !artifact) 
    448                         text_out(", and never needs refuelling"); 
    449                 else if (o_ptr->tval == TV_LITE && o_ptr->sval == SV_LITE_TORCH) 
    450                         text_out(", though this is reduced when running of out fuel"); 
    451                 text_out(".  "); 
    452  
    453                 if (o_ptr->tval == TV_LITE) 
    454                 { 
    455                         const char *name = (o_ptr->sval == SV_LITE_TORCH) ? "torch" : "lantern"; 
    456                         int turns = (o_ptr->sval == SV_LITE_TORCH) ? FUEL_TORCH : FUEL_LAMP; 
    457  
    458                         text_out("It can refill another %s, up to %d turns of fuel.  ", name, turns); 
    459                 } 
    460  
    461                 something = TRUE; 
    462         } 
    463  
    464         /* Collect stuff which can't be categorized */ 
    465         if (f3 & (TR3_BLESSED))     good[gc++] = "is blessed by the gods"; 
    466         if (f3 & (TR3_IMPACT))      good[gc++] = "creates earthquakes on impact"; 
    467         if (f3 & (TR3_SLOW_DIGEST)) good[gc++] = "slows your metabolism"; 
    468         if (f3 & (TR3_FEATHER))     good[gc++] = "makes you fall like a feather"; 
    469         if (f3 & (TR3_REGEN))       good[gc++] = "speeds your regeneration"; 
    470  
    471         /* Describe */ 
    472         if (gc) 
    473         { 
    474                 output_desc_list("It ", good, gc); 
    475                 something = TRUE; 
    476         } 
    477  
    478  
    479         /* Collect granted powers */ 
    480         gc = 0; 
    481         if (f3 & (TR3_TELEPATHY)) good[gc++] = "the power of telepathy"; 
    482         if (f3 & (TR3_SEE_INVIS)) good[gc++] = "the ability to see invisible things"; 
    483  
    484         /* Collect penalties */ 
    485         if (f3 & (TR3_AGGRAVATE)) bad[bc++] = "aggravates creatures around you"; 
    486         if (f3 & (TR3_DRAIN_EXP)) bad[bc++] = "drains experience"; 
    487         if (f3 & (TR3_TELEPORT))  bad[bc++] = "induces random teleportation"; 
    488  
    489         /* Deal with cursed stuff */ 
    490         if (cursed_p(o_ptr)) 
    491         { 
    492                 if (f3 & (TR3_PERMA_CURSE)) bad[bc++] = "is permanently cursed"; 
    493                 else if (f3 & (TR3_HEAVY_CURSE)) bad[bc++] = "is heavily cursed"; 
    494                 else if (object_known_p(o_ptr)) bad[bc++] = "is cursed"; 
    495         } 
    496  
    497         /* Describe */ 
    498         if (gc) 
    499         { 
    500                 /* Output intro */ 
    501                 p_text_out("It grants you "); 
    502  
    503                 /* Output list */ 
    504                 output_list(good, gc); 
    505  
    506                 /* Output end (if needed) */ 
    507                 if (!bc) p_text_out(".  "); 
    508         } 
    509  
    510         if (bc) 
    511         { 
    512                 /* Output intro */ 
    513                 if (gc) p_text_out(", but it also "); 
    514                 else p_text_out("It "); 
    515  
    516                 /* Output list */ 
    517                 output_list(bad, bc); 
    518  
    519                 /* Output end */ 
    520                 p_text_out(".  "); 
    521         } 
    522  
    523         /* Return "something" */ 
    524         return (gc || bc) ? TRUE : FALSE; 
    525 
     420 
     421/* 
     422 * Describe things that look like lights. 
     423 */ 
     424static bool describe_light(const object_type *o_ptr, u32b f3) 
     425
     426        int rad = 0; 
     427 
     428        bool artifact = artifact_p(o_ptr); 
     429        bool no_fuel = (f3 & TR3_NO_FUEL) ? TRUE : FALSE; 
     430        bool is_lite = (o_ptr->tval == TV_LITE) ? TRUE : FALSE; 
     431 
     432        if ((o_ptr->tval != TV_LITE) && !(f3 & TR3_LITE)) 
     433                return FALSE; 
     434 
     435        /* Work out radius */ 
     436        if (artifact)      rad = 3; 
     437        else if (is_lite)  rad = 2; 
     438        if (f3 & TR3_LITE) rad++; 
     439 
     440        /* Describe here */ 
     441        text_out("Radius "); 
     442        text_out_c(TERM_L_GREEN, format("%d", rad)); 
     443        if (no_fuel && !artifact) 
     444                text_out(" light.  No fuel required."); 
     445        else if (is_lite && o_ptr->sval == SV_LITE_TORCH) 
     446                text_out(" light, reduced when running of out fuel"); 
     447        text_out("."); 
     448 
     449        if (is_lite) 
     450        { 
     451                const char *name = (o_ptr->sval == SV_LITE_TORCH) ? "torch" : "lantern"; 
     452                int turns = (o_ptr->sval == SV_LITE_TORCH) ? FUEL_TORCH : FUEL_LAMP; 
     453 
     454                text_out("  Can refill another %s, up to %d turns of fuel.", name, turns); 
     455        } 
     456 
     457        text_out("\n"); 
     458 
     459        return TRUE; 
     460
     461 
    526462 
    527463 
     
    563499        if (!desc) return FALSE; 
    564500 
    565         p_text_out("When "); 
     501        text_out("When "); 
    566502 
    567503        if (f3 & TR3_ACTIVATE) 
     
    614550 
    615551 
    616 /* 
    617  * Describe origin of an item 
    618  */ 
    619 static bool describe_origin(const object_type *o_ptr) 
    620 { 
    621         /* Abort now if undisplayable origin */ 
    622         if (o_ptr->origin == ORIGIN_NONE || 
    623             o_ptr->origin == ORIGIN_MIXED) 
    624                 return FALSE; 
    625  
    626         if (o_ptr->number > 1) 
    627                 p_text_out("They were "); 
    628         else 
    629                 p_text_out("It was "); 
    630  
    631         /* Display the right thing */ 
    632         switch (o_ptr->origin) 
    633         { 
    634                 case ORIGIN_BIRTH: 
    635                         text_out("an inheritance from your family"); 
    636                         break; 
    637  
    638                 case ORIGIN_STORE: 
    639                         text_out("bought in a store"); 
    640                         break; 
    641  
    642                 case ORIGIN_FLOOR: 
    643                         text_out("lying on the floor"); 
    644                         break; 
    645  
    646                 case ORIGIN_DROP: 
    647                 { 
    648                         const char *name = r_name + r_info[o_ptr->origin_xtra].name; 
    649                         bool unique = (r_info[o_ptr->origin_xtra].flags1 & RF1_UNIQUE) ? TRUE : FALSE; 
    650  
    651                         text_out("dropped by "); 
    652  
    653                         if (unique) 
    654                                 text_out("%s", name); 
    655                         else 
    656                                 text_out("%s%s", is_a_vowel(name[0]) ? "an " : "a ", name); 
    657  
    658                         break; 
    659                 } 
    660  
    661                 case ORIGIN_DROP_UNKNOWN: 
    662                         text_out("dropped by an unknown monster"); 
    663                         break; 
    664  
    665                 case ORIGIN_ACQUIRE: 
    666                         text_out("conjured forth by magic"); 
    667                         break; 
    668  
    669                 case ORIGIN_CHEAT: 
    670                         text_out("created by a debug option"); 
    671                         break; 
    672  
    673                 case ORIGIN_CHEST: 
    674                         text_out("found in a chest"); 
    675                         break; 
    676         } 
    677  
    678         if (o_ptr->origin_depth) 
    679         { 
    680                 text_out(" at a depth of %d feet (level %d)", 
    681                          o_ptr->origin_depth * 50, o_ptr->origin_depth); 
    682         } 
    683  
    684         text_out(".  "); 
    685         return TRUE; 
    686 } 
    687  
    688552 
    689553/* 
     
    701565                object_flags_known(o_ptr, &f1, &f2, &f3); 
    702566 
    703         /* Describe other bits */ 
    704         new_paragraph = TRUE; 
    705         if (describe_stats(o_ptr, f1)) something = TRUE; 
    706         if (describe_immune(o_ptr, f2, f3)) something = TRUE; 
    707         if (describe_sustains(o_ptr, f2)) something = TRUE; 
    708         if (describe_misc_magic(o_ptr, f3)) something = TRUE; 
     567 
     568        if (cursed_p(o_ptr)) 
     569        { 
     570                if (f3 & TR3_PERMA_CURSE) 
     571                        text_out_c(TERM_L_RED, "Permanently cursed.\n"); 
     572                else if (f3 & TR3_HEAVY_CURSE) 
     573                        text_out_c(TERM_L_RED, "Heavily cursed.\n"); 
     574                else if (object_known_p(o_ptr)) 
     575                        text_out_c(TERM_L_RED, "Cursed.\n"); 
     576        } 
     577 
     578        if (describe_stats(f1, o_ptr->pval)) something = TRUE; 
     579        if (describe_immune(f2)) something = TRUE; 
     580        if (describe_ignores(f3)) something = TRUE; 
     581        if (describe_sustains(f2)) something = TRUE; 
     582        if (describe_misc_magic(f3)) something = TRUE; 
     583 
     584        if (something) text_out("\n"); 
     585 
    709586        if (describe_activation(o_ptr, f3, full)) something = TRUE; 
    710         if (describe_ignores(o_ptr, f3)) something = TRUE; 
    711  
    712         /* We are done. */ 
     587        if (describe_light(o_ptr, f3)) something = TRUE; 
     588 
    713589        return something; 
    714590} 
     
    716592 
    717593/* 
    718  * Header for additional information when printing to screen. 
    719  * 
    720  * Return TRUE if an object description was displayed. 
     594 * Print name, origin, and descriptive text for a given object. 
    721595 */ 
    722596void object_info_header(const object_type *o_ptr) 
    723597{ 
    724         char *o_name; 
    725         int name_size = Term->wid; 
    726  
    727         /* Allocate memory to the size of the screen */ 
    728         o_name = C_RNEW(name_size, char); 
    729  
    730         /* Description */ 
    731         object_desc(o_name, name_size, o_ptr, TRUE, 3); 
    732  
    733         /* Print, in colour */ 
    734         text_out_c(TERM_YELLOW, format("%^s", o_name)); 
    735  
    736         /* Free up the memory */ 
    737         FREE(o_name); 
     598        char o_name[120]; 
     599 
     600        /* Object name */ 
     601        object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 3); 
     602        text_out_c(TERM_L_BLUE, "%^s\n", o_name); 
     603 
     604        /* Display the origin */ 
     605        switch (o_ptr->origin) 
     606        { 
     607                case ORIGIN_NONE: 
     608                case ORIGIN_MIXED: 
     609                        break; 
     610 
     611                case ORIGIN_BIRTH: 
     612                        text_out("(an inheritance from your family)\n"); 
     613                        break; 
     614 
     615                case ORIGIN_STORE: 
     616                        text_out("(bought in a store)\n"); 
     617                        break; 
     618 
     619                case ORIGIN_FLOOR: 
     620                        text_out("(lying on the floor at %d feet (level %d))\n", 
     621                         o_ptr->origin_depth * 50, o_ptr->origin_depth);                         
     622                        break; 
     623 
     624                case ORIGIN_DROP: 
     625                { 
     626                        const char *name = r_name + r_info[o_ptr->origin_xtra].name; 
     627                        bool unique = (r_info[o_ptr->origin_xtra].flags1 & RF1_UNIQUE) ? TRUE : FALSE; 
     628 
     629                        text_out("dropped by "); 
     630 
     631                        if (unique) 
     632                                text_out("%s", name); 
     633                        else 
     634                                text_out("%s%s", is_a_vowel(name[0]) ? "an " : "a ", name); 
     635 
     636                        text_out(" at %d feet (level %d))\n", 
     637                         o_ptr->origin_depth * 50, o_ptr->origin_depth);                         
     638 
     639                        break; 
     640                } 
     641 
     642                case ORIGIN_DROP_UNKNOWN: 
     643                        text_out("(dropped by an unknown monster)\n"); 
     644                        break; 
     645 
     646                case ORIGIN_ACQUIRE: 
     647                        text_out("(conjured forth by magic)\n"); 
     648                        break; 
     649 
     650                case ORIGIN_CHEAT: 
     651                        text_out("(created by debug option)\n"); 
     652                        break; 
     653 
     654                case ORIGIN_CHEST: 
     655                        text_out("(found in a chest at %d feet (level %d))\n", 
     656                         o_ptr->origin_depth * 50, o_ptr->origin_depth);                         
     657                        break; 
     658        } 
     659 
     660        text_out("\n"); 
    738661 
    739662        /* Display the known artifact description */ 
     
    741664            object_known_p(o_ptr) && a_info[o_ptr->name1].text) 
    742665        { 
     666                text_out(a_text + a_info[o_ptr->name1].text); 
    743667                text_out("\n\n"); 
    744                 text_out(a_text + a_info[o_ptr->name1].text); 
    745668        } 
    746669 
     
    752675                if (k_info[o_ptr->k_idx].text) 
    753676                { 
    754                         text_out("\n\n"); 
    755677                        text_out(k_text + k_info[o_ptr->k_idx].text); 
    756678                        did_desc = TRUE; 
     
    761683                { 
    762684                        if (did_desc) text_out("  "); 
    763                         else text_out("\n\n"); 
    764  
    765685                        text_out(e_text + e_info[o_ptr->name2].text); 
     686                        text_out("\n\n"); 
     687                } 
     688                else if (did_desc) 
     689                { 
     690                        text_out("\n\n"); 
    766691                } 
    767692        } 
     
    781706                o_ptr->pval) 
    782707        { 
    783                 p_text_out("It provides nourishment for about "); 
     708                text_out("Provides nourishment for about "); 
     709                text_out_c(TERM_L_GREEN, "%d", o_ptr->pval / 2); 
     710                text_out(" turns under normal conditions."); 
     711                has_info = TRUE; 
     712        } 
     713 
     714        if (!object_known_p(o_ptr)) 
     715        { 
     716                text_out("You do not know the full extent of this item's powers."); 
     717                has_info = TRUE; 
     718        } 
     719 
     720        /* Describe combat bits */ 
     721        if (describe_combat(o_ptr, FALSE)) has_info = TRUE; 
     722 
     723        return has_info; 
     724
     725 
     726bool object_info_full(const object_type *o_ptr) 
     727
     728        return object_info_out(o_ptr, TRUE); 
     729
     730 
     731bool object_info_store(const object_type *o_ptr) 
     732
     733        bool has_info = FALSE; 
     734 
     735        has_info = object_info_out(o_ptr, TRUE); 
     736 
     737        /* Describe boring bits */ 
     738        if ((o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION) && 
     739                o_ptr->pval) 
     740        { 
     741                text_out("Provides nourishment for about "); 
    784742                text_out_c(TERM_L_GREEN, "%d", o_ptr->pval / 2); 
    785743                text_out(" turns under normal conditions.  "); 
     
    787745        } 
    788746 
    789         new_paragraph = TRUE; 
    790         if (!object_known_p(o_ptr)) 
    791         { 
    792                 p_text_out("You do not know the full extent of this item's powers."); 
    793                 has_info = TRUE; 
    794         } 
    795  
    796         /* Describe combat bits */ 
    797         new_paragraph = TRUE; 
    798         if (describe_combat(o_ptr, FALSE)) has_info = TRUE; 
    799  
    800         new_paragraph = TRUE; 
    801         if (describe_origin(o_ptr)) has_info = TRUE; 
     747        if (describe_combat(o_ptr, TRUE)) has_info = TRUE; 
    802748 
    803749        return has_info; 
    804750} 
    805  
    806 bool object_info_full(const object_type *o_ptr) 
    807 { 
    808         return object_info_out(o_ptr, TRUE); 
    809 } 
    810  
    811 bool object_info_store(const object_type *o_ptr) 
    812 { 
    813         bool has_info = FALSE; 
    814  
    815         has_info = object_info_out(o_ptr, TRUE); 
    816  
    817         /* Describe boring bits */ 
    818         if ((o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION) && 
    819                 o_ptr->pval) 
    820         { 
    821                 p_text_out("It provides nourishment for about "); 
    822                 text_out_c(TERM_L_GREEN, "%d", o_ptr->pval / 2); 
    823                 text_out(" turns under normal conditions.  "); 
    824                 has_info = TRUE; 
    825         } 
    826  
    827         new_paragraph = TRUE; 
    828         if (describe_combat(o_ptr, TRUE)) has_info = TRUE; 
    829  
    830         return has_info; 
    831 }