xref: /openbsd/games/hack/hack.do_wear.c (revision a6445c1d)
1 /*	$OpenBSD: hack.do_wear.c,v 1.7 2009/10/27 23:59:25 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include "hack.h"
67 extern char *nomovemsg;
68 extern char quitchars[];
69 
70 static void off_msg(struct obj *);
71 static int  dorr(struct obj *);
72 static int  cursed(struct obj *);
73 
74 static void
75 off_msg(struct obj *otmp)
76 {
77 	pline("You were wearing %s.", doname(otmp));
78 }
79 
80 int
81 doremarm()
82 {
83 	struct obj *otmp;
84 	if(!uarm && !uarmh && !uarms && !uarmg) {
85 		pline("Not wearing any armor.");
86 		return(0);
87 	}
88 	otmp = (!uarmh && !uarms && !uarmg) ? uarm :
89 		(!uarms && !uarm && !uarmg) ? uarmh :
90 		(!uarmh && !uarm && !uarmg) ? uarms :
91 		(!uarmh && !uarm && !uarms) ? uarmg :
92 		getobj("[", "take off");
93 	if(!otmp) return(0);
94 	if(!(otmp->owornmask & (W_ARMOR - W_ARM2))) {
95 		pline("You can't take that off.");
96 		return(0);
97 	}
98 	if( otmp == uarmg && uwep && uwep->cursed ) {	/* myers@uwmacc */
99  pline("You seem not able to take off the gloves while holding your weapon.");
100 		return(0);
101 	}
102 	(void) armoroff(otmp);
103 	return(1);
104 }
105 
106 int
107 doremring()
108 {
109 	if(!uleft && !uright){
110 		pline("Not wearing any ring.");
111 		return(0);
112 	}
113 	if(!uleft)
114 		return(dorr(uright));
115 	if(!uright)
116 		return(dorr(uleft));
117 	if(uleft && uright) while(1) {
118 		char answer;
119 
120 		pline("What ring, Right or Left? [ rl?]");
121 		if(strchr(quitchars, (answer = readchar())))
122 			return(0);
123 		switch(answer) {
124 		case 'l':
125 		case 'L':
126 			return(dorr(uleft));
127 		case 'r':
128 		case 'R':
129 			return(dorr(uright));
130 		case '?':
131 			(void) doprring();
132 			/* might look at morc here %% */
133 		}
134 	}
135 	/* NOTREACHED */
136 	return(0);
137 }
138 
139 static int
140 dorr(struct obj *otmp)
141 {
142 	if(cursed(otmp)) return(0);
143 	ringoff(otmp);
144 	off_msg(otmp);
145 	return(1);
146 }
147 
148 static int
149 cursed(struct obj *otmp)
150 {
151 	if(otmp->cursed){
152 		pline("You can't. It appears to be cursed.");
153 		return(1);
154 	}
155 	return(0);
156 }
157 
158 int
159 armoroff(struct obj *otmp)
160 {
161 	int delay = -objects[otmp->otyp].oc_delay;
162 
163 	if(cursed(otmp)) return(0);
164 	setworn((struct obj *) 0, otmp->owornmask & W_ARMOR);
165 	if(delay) {
166 		nomul(delay);
167 		switch(otmp->otyp) {
168 		case HELMET:
169 			nomovemsg = "You finished taking off your helmet.";
170 			break;
171 		case PAIR_OF_GLOVES:
172 			nomovemsg = "You finished taking off your gloves";
173 			break;
174 		default:
175 			nomovemsg = "You finished taking off your suit.";
176 		}
177 	} else {
178 		off_msg(otmp);
179 	}
180 	return(1);
181 }
182 
183 int
184 doweararm()
185 {
186 	struct obj *otmp;
187 	int delay;
188 	int err = 0;
189 	long mask = 0;
190 
191 	otmp = getobj("[", "wear");
192 	if(!otmp) return(0);
193 	if(otmp->owornmask & W_ARMOR) {
194 		pline("You are already wearing that!");
195 		return(0);
196 	}
197 	if(otmp->otyp == HELMET){
198 		if(uarmh) {
199 			pline("You are already wearing a helmet.");
200 			err++;
201 		} else
202 			mask = W_ARMH;
203 	} else if(otmp->otyp == SHIELD){
204 		if(uarms) pline("You are already wearing a shield."), err++;
205 		if(uwep && uwep->otyp == TWO_HANDED_SWORD)
206 	pline("You cannot wear a shield and wield a two-handed sword."), err++;
207 		if(!err) mask = W_ARMS;
208 	} else if(otmp->otyp == PAIR_OF_GLOVES) {
209 		if(uarmg) {
210 			pline("You are already wearing gloves.");
211 			err++;
212 		} else
213 		if(uwep && uwep->cursed) {
214 			pline("You cannot wear gloves over your weapon.");
215 			err++;
216 		} else
217 			mask = W_ARMG;
218 	} else {
219 		if(uarm) {
220 			if(otmp->otyp != ELVEN_CLOAK || uarm2) {
221 				pline("You are already wearing some armor.");
222 				err++;
223 			}
224 		}
225 		if(!err) mask = W_ARM;
226 	}
227 	if(otmp == uwep && uwep->cursed) {
228 		if(!err++)
229 			pline("%s is welded to your hand.", Doname(uwep));
230 	}
231 	if(err) return(0);
232 	setworn(otmp, mask);
233 	if(otmp == uwep)
234 		setuwep((struct obj *) 0);
235 	delay = -objects[otmp->otyp].oc_delay;
236 	if(delay){
237 		nomul(delay);
238 		nomovemsg = "You finished your dressing manoeuvre.";
239 	}
240 	otmp->known = 1;
241 	return(1);
242 }
243 
244 int
245 dowearring()
246 {
247 	struct obj *otmp;
248 	long mask = 0;
249 	long oldprop;
250 
251 	if(uleft && uright){
252 		pline("There are no more ring-fingers to fill.");
253 		return(0);
254 	}
255 	otmp = getobj("=", "wear");
256 	if(!otmp) return(0);
257 	if(otmp->owornmask & W_RING) {
258 		pline("You are already wearing that!");
259 		return(0);
260 	}
261 	if(otmp == uleft || otmp == uright) {
262 		pline("You are already wearing that.");
263 		return(0);
264 	}
265 	if(otmp == uwep && uwep->cursed) {
266 		pline("%s is welded to your hand.", Doname(uwep));
267 		return(0);
268 	}
269 	if(uleft) mask = RIGHT_RING;
270 	else if(uright) mask = LEFT_RING;
271 	else do {
272 		char answer;
273 
274  		pline("What ring-finger, Right or Left? ");
275 		if(strchr(quitchars, (answer = readchar())))
276 			return(0);
277 		switch(answer){
278 		case 'l':
279 		case 'L':
280 			mask = LEFT_RING;
281 			break;
282 		case 'r':
283 		case 'R':
284 			mask = RIGHT_RING;
285 			break;
286 		}
287 	} while(!mask);
288 	setworn(otmp, mask);
289 	if(otmp == uwep)
290 		setuwep((struct obj *) 0);
291 	oldprop = u.uprops[PROP(otmp->otyp)].p_flgs;
292 	u.uprops[PROP(otmp->otyp)].p_flgs |= mask;
293 	switch(otmp->otyp){
294 	case RIN_LEVITATION:
295 		if(!oldprop) float_up();
296 		break;
297 	case RIN_PROTECTION_FROM_SHAPE_CHANGERS:
298 		rescham();
299 		break;
300 	case RIN_GAIN_STRENGTH:
301 		u.ustr += otmp->spe;
302 		u.ustrmax += otmp->spe;
303 		if(u.ustr > 118) u.ustr = 118;
304 		if(u.ustrmax > 118) u.ustrmax = 118;
305 		flags.botl = 1;
306 		break;
307 	case RIN_INCREASE_DAMAGE:
308 		u.udaminc += otmp->spe;
309 		break;
310 	}
311 	prinv(otmp);
312 	return(1);
313 }
314 
315 void
316 ringoff(struct obj *obj)
317 {
318 	long mask;
319 
320 	mask = obj->owornmask & W_RING;
321 	setworn((struct obj *) 0, obj->owornmask);
322 	if(!(u.uprops[PROP(obj->otyp)].p_flgs & mask))
323 		impossible("Strange... I didnt know you had that ring.");
324 	u.uprops[PROP(obj->otyp)].p_flgs &= ~mask;
325 	switch(obj->otyp) {
326 	case RIN_FIRE_RESISTANCE:
327 		/* Bad luck if the player is in hell... --jgm */
328 		if (!Fire_resistance && dlevel >= 30) {
329 			pline("The flames of Hell burn you to a crisp.");
330 			killer = "stupidity in hell";
331 			done("burned");
332 		}
333 		break;
334 	case RIN_LEVITATION:
335 		if(!Levitation) {	/* no longer floating */
336 			float_down();
337 		}
338 		break;
339 	case RIN_GAIN_STRENGTH:
340 		u.ustr -= obj->spe;
341 		u.ustrmax -= obj->spe;
342 		if(u.ustr > 118) u.ustr = 118;
343 		if(u.ustrmax > 118) u.ustrmax = 118;
344 		flags.botl = 1;
345 		break;
346 	case RIN_INCREASE_DAMAGE:
347 		u.udaminc -= obj->spe;
348 		break;
349 	}
350 }
351 
352 void
353 find_ac()
354 {
355 	int uac = 10;
356 
357 	if(uarm) uac -= ARM_BONUS(uarm);
358 	if(uarm2) uac -= ARM_BONUS(uarm2);
359 	if(uarmh) uac -= ARM_BONUS(uarmh);
360 	if(uarms) uac -= ARM_BONUS(uarms);
361 	if(uarmg) uac -= ARM_BONUS(uarmg);
362 	if(uleft && uleft->otyp == RIN_PROTECTION) uac -= uleft->spe;
363 	if(uright && uright->otyp == RIN_PROTECTION) uac -= uright->spe;
364 	if(uac != u.uac){
365 		u.uac = uac;
366 		flags.botl = 1;
367 	}
368 }
369 
370 void
371 glibr()
372 {
373 	struct obj *otmp;
374 	int xfl = 0;
375 
376 	if(!uarmg) if(uleft || uright) {
377 		/* Note: at present also cursed rings fall off */
378 		pline("Your %s off your fingers.",
379 			(uleft && uright) ? "rings slip" : "ring slips");
380 		xfl++;
381 		if((otmp = uleft) != Null(obj)){
382 			ringoff(uleft);
383 			dropx(otmp);
384 		}
385 		if((otmp = uright) != Null(obj)){
386 			ringoff(uright);
387 			dropx(otmp);
388 		}
389 	}
390 	if((otmp = uwep) != Null(obj)){
391 		/* Note: at present also cursed weapons fall */
392 		setuwep((struct obj *) 0);
393 		dropx(otmp);
394 		pline("Your weapon %sslips from your hands.",
395 			xfl ? "also " : "");
396 	}
397 }
398 
399 struct obj *
400 some_armor()
401 {
402 	struct obj *otmph = uarm;
403 
404 	if(uarmh && (!otmph || !rn2(4))) otmph = uarmh;
405 	if(uarmg && (!otmph || !rn2(4))) otmph = uarmg;
406 	if(uarms && (!otmph || !rn2(4))) otmph = uarms;
407 	return(otmph);
408 }
409 
410 void
411 corrode_armor()
412 {
413 	struct obj *otmph = some_armor();
414 
415 	if(otmph){
416 		if(otmph->rustfree ||
417 		   otmph->otyp == ELVEN_CLOAK ||
418 		   otmph->otyp == LEATHER_ARMOR ||
419 		   otmph->otyp == STUDDED_LEATHER_ARMOR) {
420 			pline("Your %s not affected!",
421 				aobjnam(otmph, "are"));
422 			return;
423 		}
424 		pline("Your %s!", aobjnam(otmph, "corrode"));
425 		otmph->spe--;
426 	}
427 }
428