ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/disease.C
Revision: 1.52
Committed: Tue Sep 1 20:56:05 2009 UTC (14 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_80
Changes since 1.51: +2 -2 lines
Log Message:
*** empty log message ***

File Contents

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