ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/disease.C
Revision: 1.12
Committed: Wed Dec 20 09:14:22 2006 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.11: +1 -1 lines
Log Message:
- minor cleanups
- minor optimisations (in_player vs. is_player_inv)
- added P_PLAYER map flag
- some (dead) concept code

File Contents

# User Rev Content
1 elmex 1.1 /*
2     CrossFire, A Multiplayer game for X-windows
3    
4     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5     Copyright (C) 1992 Frank Tore Johansen
6    
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 root 1.5 The authors can be reached via e-mail to <crossfire@schmorp.de>
22 elmex 1.1 */
23    
24     /* This file contains all the code implementing diseases,
25     except for odds and ends in attack.c and in
26 root 1.2 living.c*/
27 elmex 1.1
28    
29    
30     /*
31    
32     For DISEASES:
33     Stat Property Definition
34    
35     attacktype Attack effects Attacktype of the disease. usu. AT_GODPOWER.
36     other_arch Creation object created and dropped when symptom moved.
37     title Message When the "disease" "infects" something, it will
38     print "title victim!!!" to the player who owns
39 root 1.2 the "disease".
40 elmex 1.1 wc+ Infectiousness How well the plague spreads person-to-person
41     magic+ Range range of infection
42     Stats* Disability What stats are reduced by the disease (str con...)
43     maxhp+ Persistence How long the disease can last OUTSIDE the host.
44     value TimeLeft Counter for persistence
45     dam^ Damage How much damage it does (%?).
46     maxgrace+ Duration How long before the disease is naturally cured.
47     food DurCount Counter for Duration
48    
49     speed Speed How often the disease moves.
50     last_sp^ Lethargy Percentage of max speed--10 = 10% speed.
51    
52     maxsp^ Mana deplete Saps mana.
53     ac^ Progressiveness How the diseases increases in severity.
54     last_eat*^ Deplete food saps food if negative
55     last_heal GrantImmunity If nonzero, disease does NOT grant immunity
56     when it runs out
57    
58     exp experience experience awarded when plague cured
59     hp*^ ReduceRegen reduces regeneration of disease-bearer
60     sp*^ ReduceSpRegen reduces spellpoint regeneration
61    
62     name Name Name of the plague
63     msg message What the plague says when it strikes.
64     race those affected species/race the plague strikes (* = everything)
65     level Plague Level General description of the plague's deadliness
66     armour Attenuation reduction in wc per generation of disease.
67     This builds in a self-limiting factor.
68    
69    
70     Explanations:
71     * means this # should be negative to cause adverse effect.
72     + means that this effect is modulated in spells by ldur
73     ^ means that this effect is modulated in spells by ldam
74    
75     attacktype is the attacktype used by the disease to smite "dam" damage with.
76    
77     wc/127 is the chance of someone in range catching it.
78    
79     magic is the range at which infection may occur. If negative, the range is
80     NOT level dependent.
81    
82     Stats are stat modifications. These should typically be negative.
83    
84     maxhp is how long the disease will persist if the host dies and "drops" it,
85     in "disease moves", i.e., moves of the disease. If negative, permanent.
86    
87    
88     value is the counter for maxhp, it starts at maxhp and drops...
89    
90     dam if positive, it is straight damage. if negative, a %-age.
91    
92     maxgrace how long in "disease moves" the disease lasts in the host, if negative,
93     permanent until cured.
94    
95     food if negative, disease is permanent. otherwise, decreases at <speed>,
96     disease goes away at food=0, set to "maxgrace" on infection.
97    
98     speed is the speed of the disease, how fast "disease moves" occur.
99    
100     last_sp is the lethargy imposed on the player by the disease. A lethargy
101     of "1" reduces the players speed to 1% of its normal value.
102    
103     maxsp how much mana is sapped per "disease move". if negative, a %-age is
104     taken.
105    
106     ac every "disease move" the severity of the symptoms are increased by
107     ac/100. (severity = 1 + (accumlated_progression)/100)
108    
109     last_eat increases food usage if negative.
110    
111    
112    
113     For SYMPTOMS:
114    
115     Stats modify stats
116     hp modify regen
117     value progression counter (multiplier = value/100)
118     food modify food use (from last_eat in DISEASE)
119     maxsp suck mana ( as noted for DISEASE)
120     last_sp Lethargy
121     msg What to say
122     speed speed of movement, from DISEASE
123    
124    
125     */
126    
127    
128     #include <global.h>
129     #include <object.h>
130     #include <living.h>
131     #ifndef __CEXTRACT__
132 root 1.4 # include <sproto.h>
133 elmex 1.1 #endif
134     #include <spells.h>
135     #include <sounds.h>
136     #include <skills.h>
137    
138     /* IMPLEMENTATION NOTES
139 root 1.2
140     Diseases may be contageous. They are objects which exist in a player's
141 elmex 1.1 inventory. They themselves do nothing, except modify Symptoms, or
142     spread to other live objects. Symptoms are what actually damage the player:
143     these are their own object. */
144    
145     /* check if victim is susceptible to disease. */
146 root 1.4 static int
147     is_susceptible_to_disease (object *victim, object *disease)
148 elmex 1.1 {
149 root 1.4 if (!QUERY_FLAG (victim, FLAG_ALIVE))
150     return 0;
151 elmex 1.1
152 root 1.4 if (strstr (disease->race, "*") && !QUERY_FLAG (victim, FLAG_UNDEAD))
153     return 1;
154 elmex 1.1
155 root 1.4 if ((disease->race == undead_name) && QUERY_FLAG (victim, FLAG_UNDEAD))
156     return 1;
157 elmex 1.1
158 root 1.4 if ((victim->race && strstr (disease->race, victim->race)) || strstr (disease->race, victim->name))
159     return 1;
160    
161     return 0;
162 elmex 1.1 }
163    
164 root 1.4 int
165     move_disease (object *disease)
166     {
167     /* first task is to determine if the disease is inside or outside of someone.
168     * If outside, we decrement 'value' until we're gone.
169     */
170    
171     if (disease->env == NULL)
172     { /* we're outside of someone */
173     if (disease->stats.maxhp > 0)
174     disease->value--;
175 root 1.9
176 root 1.4 if (disease->value == 0)
177     {
178 root 1.9 disease->destroy ();
179 root 1.4 return 1;
180 root 1.2 }
181 root 1.4 }
182     else
183     {
184     /* if we're inside a person, have the disease run its course */
185     /* negative foods denote "perpetual" diseases. */
186     if (disease->stats.food > 0)
187     {
188     disease->stats.food--;
189 root 1.9
190 root 1.4 if (disease->stats.food == 0)
191     {
192     remove_symptoms (disease); /* remove the symptoms of this disease */
193     grant_immunity (disease);
194 root 1.9 disease->destroy ();
195 root 1.4 return 1;
196 root 1.2 }
197     }
198 elmex 1.1 }
199 root 1.9
200 root 1.4 /* check to see if we infect others */
201     check_infection (disease);
202 elmex 1.1
203 root 1.4 /* impose or modify the symptoms of the disease */
204     if (disease->env && is_susceptible_to_disease (disease->env, disease))
205     do_symptoms (disease);
206 elmex 1.1
207 root 1.4 return 0;
208 elmex 1.1 }
209    
210     /* remove any symptoms of disease
211     * Modified by MSW 2003-03-28 do try to find all the symptom the
212     * player may have - I think through some odd interactoins with
213     * disease level and player level and whatnot, a player could get
214     * more than one symtpom to a disease.
215     */
216 root 1.4
217     int
218     remove_symptoms (object *disease)
219     {
220     object *symptom, *victim = NULL;
221    
222     while ((symptom = find_symptom (disease)) != NULL)
223     {
224     if (!victim)
225     victim = symptom->env;
226 root 1.9
227     symptom->destroy ();
228 root 1.4 }
229 root 1.9
230 root 1.4 if (victim)
231     fix_player (victim);
232     return 0;
233 elmex 1.1 }
234    
235     /* argument is a disease */
236 root 1.4 object *
237     find_symptom (object *disease)
238     {
239 elmex 1.1 object *walk;
240    
241     /* check the inventory for symptoms */
242 root 1.4 for (walk = disease->env->inv; walk; walk = walk->below)
243     if (!strcmp (walk->name, disease->name) && walk->type == SYMPTOM)
244     return walk;
245 elmex 1.1 return NULL;
246     }
247 root 1.4
248 elmex 1.1 /* searches around for more victims to infect */
249 root 1.4 int
250     check_infection (object *disease)
251     {
252     int x, y, range, mflags;
253 root 1.6 maptile *map, *map2;
254 root 1.4 object *tmp;
255    
256     range = abs (disease->magic);
257 root 1.7
258 root 1.4 if (disease->env)
259     {
260 root 1.7 x = disease->env->x;
261     y = disease->env->y;
262 root 1.4 map = disease->env->map;
263     }
264     else
265     {
266 root 1.7 x = disease->x;
267     y = disease->y;
268 root 1.4 map = disease->map;
269     }
270    
271 root 1.7 if (!map)
272 root 1.4 return 0;
273 root 1.7
274     for (int i = x - range; i <= x + range; i++)
275     for (int j = y - range; j <= y + range; j++)
276     {
277     sint16 i2, j2;
278     mflags = get_map_flags (map, &map2, i, j, &i2, &j2);
279    
280     if (!(mflags & P_OUT_OF_MAP) && (mflags & P_IS_ALIVE))
281 root 1.12 for (tmp = GET_MAP_OB (map2, i2, j2); tmp; tmp = tmp->above)
282 root 1.7 infect_object (tmp, disease, 0);
283     }
284    
285 root 1.4 return 1;
286 elmex 1.1 }
287    
288    
289     /* check to see if an object is infectable:
290     * objects with immunity aren't infectable.
291     * objects already infected aren't infectable.
292     * dead objects aren't infectable.
293     * undead objects are infectible only if specifically named.
294     */
295 root 1.4 int
296     infect_object (object *victim, object *disease, int force)
297     {
298     object *tmp;
299     object *new_disease;
300 elmex 1.1
301 root 1.4 /* don't infect inanimate objects */
302     if (!QUERY_FLAG (victim, FLAG_MONSTER) && !(victim->type == PLAYER))
303     return 0;
304    
305     /* check and see if victim can catch disease: diseases
306     * are specific
307     */
308     if (!is_susceptible_to_disease (victim, disease))
309     return 0;
310    
311     /* roll the dice on infection before doing the inventory check! */
312     if (!force && (random_roll (0, 126, victim, PREFER_HIGH) >= disease->stats.wc))
313     return 0;
314 elmex 1.1
315 root 1.4 /* do an immunity check */
316     if (victim->head)
317     tmp = victim->head->inv;
318     else
319     tmp = victim->inv;
320    
321     /* There used to (IMO) be a flaw in the below - it used to be the case
322     * that if level check was done for both immunity and disease. This could
323     * result in a person with multiple afflictions of the same disease
324     * (eg, level 1 cold, level 2 cold, level 3 cold, etc), as long as
325     * they were cast in that same order. Instead, change it so that
326     * if you diseased, you can't get diseased more.
327     */
328    
329     for ( /* tmp initialized in if, above */ ; tmp; tmp = tmp->below)
330     {
331     if (tmp->type == SIGN && !strcmp (tmp->name, disease->name) && tmp->level >= disease->level)
332     return 0; /*Immune! */
333     else if (tmp->type == DISEASE && !strcmp (tmp->name, disease->name))
334     return 0; /* already diseased */
335     }
336    
337     /* If we've gotten this far, go ahead and infect the victim. */
338 root 1.10 new_disease = disease->clone ();
339 root 1.4 new_disease->stats.food = disease->stats.maxgrace;
340     new_disease->value = disease->stats.maxhp;
341     new_disease->stats.wc -= disease->last_grace; /* self-limiting factor */
342    
343     /* Unfortunately, set_owner does the wrong thing to the skills pointers
344     * resulting in exp going into the owners *current* chosen skill.
345     */
346    
347 root 1.11 if (disease->owner)
348 root 1.4 {
349 root 1.11 new_disease->set_owner (disease->owner);
350 root 1.4
351     /* Only need to update skill if different */
352     if (new_disease->skill != disease->skill)
353     new_disease->skill = disease->skill;
354     }
355     else
356     { /* for diseases which are passed by hitting, set owner and praying skill */
357     if (disease->env && disease->env->type == PLAYER)
358     {
359     object *player = disease->env;
360    
361 root 1.11 new_disease->set_owner (player);
362 root 1.4
363     /* the skill pointer for these diseases should already be set up -
364     * hardcoding in 'praying' is not the right approach.
365     */
366 root 1.2 }
367 elmex 1.1 }
368    
369 root 1.4 insert_ob_in_ob (new_disease, victim);
370     /* This appears to be a horrible case of overloading 'NO_PASS'
371     * for meaning in the diseases.
372     */
373     new_disease->move_block = 0;
374     if (new_disease->owner && new_disease->owner->type == PLAYER)
375     {
376     char buf[128];
377    
378     /* if the disease has a title, it has a special infection message
379     * This messages is printed in the form MESSAGE victim
380     */
381     if (new_disease->title)
382     sprintf (buf, "%s %s!!", &disease->title, &victim->name);
383     else
384     sprintf (buf, "You infect %s with your disease, %s!", &victim->name, &new_disease->name);
385    
386     if (victim->type == PLAYER)
387     new_draw_info (NDI_UNIQUE | NDI_RED, 0, new_disease->owner, buf);
388     else
389     new_draw_info (0, 4, new_disease->owner, buf);
390 elmex 1.1 }
391 root 1.4 if (victim->type == PLAYER)
392     new_draw_info (NDI_UNIQUE | NDI_RED, 0, victim, "You suddenly feel ill.");
393 elmex 1.1
394 root 1.4 return 1;
395 elmex 1.1
396     }
397    
398    
399    
400     /* this function monitors the symptoms caused by the disease (if any),
401     causes symptoms, and modifies existing symptoms in the case of
402     existing diseases. */
403    
404 root 1.4 int
405     do_symptoms (object *disease)
406     {
407     object *symptom;
408     object *victim;
409     object *tmp;
410    
411     victim = disease->env;
412    
413     /* This is a quick hack - for whatever reason, disease->env will point
414     * back to disease, causing endless loops. Why this happens really needs
415     * to be found, but this should at least prevent the infinite loops.
416     */
417    
418     if (victim == NULL || victim == disease)
419     return 0; /* no-one to inflict symptoms on */
420    
421     symptom = find_symptom (disease);
422     if (symptom == NULL)
423     {
424     /* no symptom? need to generate one! */
425     object *new_symptom;
426    
427     /* first check and see if the carrier of the disease is immune. If so, no symptoms! */
428     if (!is_susceptible_to_disease (victim, disease))
429     return 0;
430    
431     /* check for an actual immunity */
432     /* do an immunity check */
433     if (victim->head)
434     tmp = victim->head->inv;
435     else
436     tmp = victim->inv;
437    
438     for ( /* tmp initialized in if, above */ ; tmp; tmp = tmp->below)
439     {
440     if (tmp->type == SIGN) /* possibly an immunity, or diseased */
441     if (!strcmp (tmp->name, disease->name) && tmp->level >= disease->level)
442     return 0; /*Immune! */
443 root 1.2 }
444    
445 root 1.4 new_symptom = get_archetype (ARCH_SYMPTOM);
446    
447     /* Something special done with dam. We want diseases to be more
448     * random in what they'll kill, so we'll make the damage they
449     * do random, note, this has a weird effect with progressive diseases.
450     */
451     if (disease->stats.dam != 0)
452     {
453     int dam = disease->stats.dam;
454    
455     /* reduce the damage, on average, 50%, and making things random. */
456    
457     dam = random_roll (1, FABS (dam), victim, PREFER_LOW);
458     if (disease->stats.dam < 0)
459     dam = -dam;
460     new_symptom->stats.dam = dam;
461 root 1.2 }
462 elmex 1.1
463 root 1.4
464     new_symptom->stats.maxsp = disease->stats.maxsp;
465     new_symptom->stats.food = new_symptom->stats.maxgrace;
466    
467     new_symptom->name = new_symptom->name_pl = disease->name;
468    
469     new_symptom->level = disease->level;
470     new_symptom->speed = disease->speed;
471     new_symptom->value = 0;
472     new_symptom->stats.Str = disease->stats.Str;
473     new_symptom->stats.Dex = disease->stats.Dex;
474     new_symptom->stats.Con = disease->stats.Con;
475     new_symptom->stats.Wis = disease->stats.Wis;
476     new_symptom->stats.Int = disease->stats.Int;
477     new_symptom->stats.Pow = disease->stats.Pow;
478     new_symptom->stats.Cha = disease->stats.Cha;
479     new_symptom->stats.sp = disease->stats.sp;
480     new_symptom->stats.food = disease->last_eat;
481     new_symptom->stats.maxsp = disease->stats.maxsp;
482     new_symptom->last_sp = disease->last_sp;
483     new_symptom->stats.exp = 0;
484     new_symptom->stats.hp = disease->stats.hp;
485     new_symptom->msg = disease->msg;
486     new_symptom->attacktype = disease->attacktype;
487     new_symptom->other_arch = disease->other_arch;
488    
489 root 1.11 new_symptom->set_owner (disease->owner);
490 root 1.4
491     if (new_symptom->skill != disease->skill)
492     new_symptom->skill = disease->skill;
493    
494     new_symptom->move_block = 0;
495     insert_ob_in_ob (new_symptom, victim);
496     return 1;
497     }
498    
499     /* now deal with progressing diseases: we increase the debility
500     * caused by the symptoms.
501     */
502    
503     if (disease->stats.ac != 0)
504     {
505     float scale;
506    
507     symptom->value += disease->stats.ac;
508     scale = 1.0 + symptom->value / 100.0;
509     /* now rescale all the debilities */
510     symptom->stats.Str = (int) (scale * disease->stats.Str);
511     symptom->stats.Dex = (int) (scale * disease->stats.Dex);
512     symptom->stats.Con = (int) (scale * disease->stats.Con);
513     symptom->stats.Wis = (int) (scale * disease->stats.Wis);
514     symptom->stats.Int = (int) (scale * disease->stats.Int);
515     symptom->stats.Pow = (int) (scale * disease->stats.Pow);
516     symptom->stats.Cha = (int) (scale * disease->stats.Cha);
517     symptom->stats.dam = (int) (scale * disease->stats.dam);
518     symptom->stats.sp = (int) (scale * disease->stats.sp);
519     symptom->stats.food = (int) (scale * disease->last_eat);
520     symptom->stats.maxsp = (int) (scale * disease->stats.maxsp);
521     symptom->last_sp = (int) (scale * disease->last_sp);
522     symptom->stats.exp = 0;
523     symptom->stats.hp = (int) (scale * disease->stats.hp);
524     symptom->msg = disease->msg;
525     symptom->attacktype = disease->attacktype;
526     symptom->other_arch = disease->other_arch;
527 elmex 1.1 }
528 root 1.4 SET_FLAG (symptom, FLAG_APPLIED);
529     fix_player (victim);
530     return 1;
531 elmex 1.1 }
532    
533    
534     /* grants immunity to plagues we've seen before. */
535 root 1.4 int
536     grant_immunity (object *disease)
537     {
538     object *immunity;
539 elmex 1.1 object *walk;
540 root 1.4
541 elmex 1.1 /* Don't give immunity to this disease if last_heal is set. */
542 root 1.4 if (disease->last_heal)
543     return 0;
544 elmex 1.1 /* first, search for an immunity of the same name */
545 root 1.4 for (walk = disease->env->inv; walk; walk = walk->below)
546     {
547     if (walk->type == 98 && !strcmp (disease->name, walk->name))
548     {
549     walk->level = disease->level;
550     return 1; /* just update the existing immunity. */
551     }
552     }
553     immunity = get_archetype ("immunity");
554 root 1.3 immunity->name = disease->name;
555 elmex 1.1 immunity->level = disease->level;
556     immunity->move_block = 0;
557 root 1.4 insert_ob_in_ob (immunity, disease->env);
558 elmex 1.1 return 1;
559    
560     }
561    
562    
563     /* make the symptom do the nasty things it does */
564    
565 root 1.4 int
566     move_symptom (object *symptom)
567     {
568     object *victim = symptom->env;
569     object *new_ob;
570     int sp_reduce;
571    
572     if (victim == NULL || victim->map == NULL)
573     { /* outside a monster/player, die immediately */
574 root 1.9 symptom->destroy ();
575 root 1.4 return 0;
576     }
577    
578     if (symptom->stats.dam > 0)
579     hit_player (victim, symptom->stats.dam, symptom, symptom->attacktype, 1);
580     else
581     hit_player (victim, (int) MAX (1, -victim->stats.maxhp * symptom->stats.dam / 100.0), symptom, symptom->attacktype, 1);
582    
583     if (symptom->stats.maxsp > 0)
584     sp_reduce = symptom->stats.maxsp;
585     else
586     sp_reduce = (int) MAX (1, victim->stats.maxsp * symptom->stats.maxsp / 100.0);
587     victim->stats.sp = MAX (0, victim->stats.sp - sp_reduce);
588    
589     /* create the symptom "other arch" object and drop it here
590     * under every part of the monster
591     * The victim may well have died.
592     */
593 elmex 1.1
594 root 1.4 if (victim->map == NULL)
595     return 0;
596     if (symptom->other_arch)
597     {
598     object *tmp;
599    
600     tmp = victim;
601     if (tmp->head != NULL)
602     tmp = tmp->head;
603     for ( /*tmp initialized above */ ; tmp != NULL; tmp = tmp->more)
604     {
605     new_ob = arch_to_object (symptom->other_arch);
606     new_ob->x = tmp->x;
607     new_ob->y = tmp->y;
608     new_ob->map = victim->map;
609     insert_ob_in_map (new_ob, victim->map, victim, 0);
610 root 1.2 }
611 elmex 1.1 }
612 root 1.4 new_draw_info (NDI_UNIQUE | NDI_RED, 0, victim, symptom->msg);
613    
614     return 1;
615 elmex 1.1 }
616    
617    
618     /* possibly infect due to direct physical contact
619     i.e., AT_PHYSICAL-- called from "hit_player_attacktype" */
620    
621 root 1.4 int
622     check_physically_infect (object *victim, object *hitter)
623     {
624 elmex 1.1 object *walk;
625 root 1.4
626 elmex 1.1 /* search for diseases, give every disease a chance to infect */
627 root 1.4 for (walk = hitter->inv; walk != NULL; walk = walk->below)
628     if (walk->type == DISEASE)
629     infect_object (victim, walk, 0);
630 elmex 1.1 return 1;
631     }
632    
633     /* find a disease in someone*/
634 root 1.4 object *
635     find_disease (object *victim)
636     {
637 elmex 1.1 object *walk;
638 root 1.4
639     for (walk = victim->inv; walk; walk = walk->below)
640     if (walk->type == DISEASE)
641     return walk;
642 elmex 1.1 return NULL;
643     }
644 root 1.4
645 elmex 1.1 /* do the cure disease stuff, from the spell "cure disease" */
646    
647 root 1.4 int
648     cure_disease (object *sufferer, object *caster)
649     {
650     object *disease, *next;
651     int casting_level;
652     int cure = 0;
653    
654     if (caster)
655     casting_level = caster->level;
656     else
657     casting_level = 1000; /* if null caster, CURE all. */
658    
659     for (disease = sufferer->inv; disease; disease = next)
660     {
661     next = disease->below;
662    
663     if (disease->type == DISEASE)
664     { /* attempt to cure this disease */
665     /* If caster lvel is higher than disease level, cure chance
666     * is automatic. If lower, then the chance is basically
667     * 1 in level_diff - if there is a 5 level difference, chance
668     * is 1 in 5.
669     */
670     if ((casting_level >= disease->level) || (!(random_roll (0, (disease->level - casting_level - 1), caster, PREFER_LOW))))
671     {
672    
673     remove_symptoms (disease);
674     cure = 1;
675 root 1.9
676 root 1.4 if (caster)
677     change_exp (caster, disease->stats.exp, caster->chosen_skill ? &caster->chosen_skill->skill : (const char *) 0, 0);
678 root 1.9
679     disease->destroy ();
680 root 1.2 }
681     }
682 elmex 1.1 }
683 root 1.4 if (cure)
684     {
685     /* Only draw these messages once */
686     if (caster)
687     new_draw_info_format (NDI_UNIQUE, 0, caster, "You cure a disease!");
688     new_draw_info (NDI_UNIQUE, 0, sufferer, "You no longer feel diseased.");
689 elmex 1.1 }
690     return 1;
691     }
692    
693     /* reduces disease progression: reduce_symptoms
694     * return true if we actually reduce a disease.
695     */
696    
697 root 1.4 int
698     reduce_symptoms (object *sufferer, int reduction)
699     {
700     object *walk;
701     int success = 0;
702    
703     for (walk = sufferer->inv; walk; walk = walk->below)
704     {
705     if (walk->type == SYMPTOM)
706     {
707     if (walk->value > 0)
708     {
709     success = 1;
710     walk->value = MAX (0, walk->value - 2 * reduction);
711     /* give the disease time to modify this symptom,
712     * and reduce its severity. */
713     walk->speed_left = 0;
714 root 1.2 }
715 root 1.4 }
716 elmex 1.1 }
717 root 1.4 if (success)
718     new_draw_info (NDI_UNIQUE, 0, sufferer, "Your illness seems less severe.");
719     return success;
720 elmex 1.1 }