1 /*        $NetBSD: ring.c,v 1.9 2008/01/14 03:50:02 dholland Exp $    */
2 
3 /*
4  * Copyright (c) 1988, 1993
5  *        The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Timothy C. Stoehr.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. 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  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)ring.c      8.1 (Berkeley) 5/31/93";
39 #else
40 __RCSID("$NetBSD: ring.c,v 1.9 2008/01/14 03:50:02 dholland Exp $");
41 #endif
42 #endif /* not lint */
43 
44 /*
45  * ring.c
46  *
47  * This source herein may be modified and/or distributed by anybody who
48  * so desires, with the following restrictions:
49  *    1.)  No portion of this notice shall be removed.
50  *    2.)  Credit shall not be taken for the creation of this source.
51  *    3.)  This code is not to be traded, sold, or used for personal
52  *         gain or profit.
53  *
54  */
55 
56 #include "rogue.h"
57 
58 static const char left_or_right[] = "left or right hand?";
59 static const char no_ring[] = "there's no ring on that hand";
60 
61 short stealthy;
62 short r_rings;
63 short add_strength;
64 short e_rings;
65 short regeneration;
66 short ring_exp;
67 short auto_search;
68 boolean r_teleport;
69 boolean r_see_invisible;
70 boolean sustain_strength;
71 boolean maintain_armor;
72 
73 void
put_on_ring(void)74 put_on_ring(void)
75 {
76           short ch;
77           char desc[DCOLS];
78           object *ring;
79 
80           if (r_rings == 2) {
81                     messagef(0, "wearing two rings already");
82                     return;
83           }
84           if ((ch = pack_letter("put on what?", RING)) == CANCEL) {
85                     return;
86           }
87           if (!(ring = get_letter_object(ch))) {
88                     messagef(0, "no such item.");
89                     return;
90           }
91           if (!(ring->what_is & RING)) {
92                     messagef(0, "that's not a ring");
93                     return;
94           }
95           if (ring->in_use_flags & (ON_LEFT_HAND | ON_RIGHT_HAND)) {
96                     messagef(0, "that ring is already being worn");
97                     return;
98           }
99           if (r_rings == 1) {
100                     ch = (rogue.left_ring ? 'r' : 'l');
101           } else {
102                     messagef(0, "%s", left_or_right);
103                     do {
104                               ch = rgetchar();
105                     } while ((ch != CANCEL) && (ch != 'l') && (ch != 'r') && (ch != '\n') &&
106                                         (ch != '\r'));
107           }
108           if ((ch != 'l') && (ch != 'r')) {
109                     check_message();
110                     return;
111           }
112           if (((ch == 'l') && rogue.left_ring)||((ch == 'r') && rogue.right_ring)) {
113                     check_message();
114                     messagef(0, "there's already a ring on that hand");
115                     return;
116           }
117           if (ch == 'l') {
118                     do_put_on(ring, 1);
119           } else {
120                     do_put_on(ring, 0);
121           }
122           ring_stats(1);
123           check_message();
124           get_desc(ring, desc, sizeof(desc));
125           messagef(0, "%s", desc);
126           (void)reg_move();
127 }
128 
129 /*
130  * Do not call ring_stats() from within do_put_on().  It will cause
131  * serious problems when do_put_on() is called from read_pack() in restore().
132  */
133 
134 void
do_put_on(object * ring,boolean on_left)135 do_put_on(object *ring, boolean on_left)
136 {
137           if (on_left) {
138                     ring->in_use_flags |= ON_LEFT_HAND;
139                     rogue.left_ring = ring;
140           } else {
141                     ring->in_use_flags |= ON_RIGHT_HAND;
142                     rogue.right_ring = ring;
143           }
144 }
145 
146 void
remove_ring(void)147 remove_ring(void)
148 {
149           boolean left = 0, right = 0;
150           short ch;
151           char buf[DCOLS];
152           object *ring;
153 
154           ring = NULL;
155           if (r_rings == 0) {
156                     inv_rings();
157           } else if (rogue.left_ring && !rogue.right_ring) {
158                     left = 1;
159           } else if (!rogue.left_ring && rogue.right_ring) {
160                     right = 1;
161           } else {
162                     messagef(0, "%s", left_or_right);
163                     do {
164                               ch = rgetchar();
165                     } while ((ch != CANCEL) && (ch != 'l') && (ch != 'r') &&
166                               (ch != '\n') && (ch != '\r'));
167                     left = (ch == 'l');
168                     right = (ch == 'r');
169                     check_message();
170           }
171           if (left || right) {
172                     if (left) {
173                               if (rogue.left_ring) {
174                                         ring = rogue.left_ring;
175                               } else {
176                                         messagef(0, "%s", no_ring);
177                               }
178                     } else {
179                               if (rogue.right_ring) {
180                                         ring = rogue.right_ring;
181                               } else {
182                                         messagef(0, "%s", no_ring);
183                               }
184                     }
185                     if (ring->is_cursed) {
186                               messagef(0, "%s", curse_message);
187                     } else {
188                               un_put_on(ring);
189                               get_desc(ring, buf, sizeof(buf));
190                               messagef(0, "removed %s", buf);
191                               (void)reg_move();
192                     }
193           }
194 }
195 
196 void
un_put_on(object * ring)197 un_put_on(object *ring)
198 {
199           if (ring && (ring->in_use_flags & ON_LEFT_HAND)) {
200                     ring->in_use_flags &= (~ON_LEFT_HAND);
201                     rogue.left_ring = NULL;
202           } else if (ring && (ring->in_use_flags & ON_RIGHT_HAND)) {
203                     ring->in_use_flags &= (~ON_RIGHT_HAND);
204                     rogue.right_ring = NULL;
205           }
206           ring_stats(1);
207 }
208 
209 void
gr_ring(object * ring,boolean assign_wk)210 gr_ring(object *ring, boolean assign_wk)
211 {
212           ring->what_is = RING;
213           if (assign_wk) {
214                     ring->which_kind = get_rand(0, (RINGS - 1));
215           }
216           ring->class = 0;
217 
218           switch(ring->which_kind) {
219           /*
220           case STEALTH:
221                     break;
222           case SLOW_DIGEST:
223                     break;
224           case REGENERATION:
225                     break;
226           case R_SEE_INVISIBLE:
227                     break;
228           case SUSTAIN_STRENGTH:
229                     break;
230           case R_MAINTAIN_ARMOR:
231                     break;
232           case SEARCHING:
233                     break;
234           */
235           case R_TELEPORT:
236                     ring->is_cursed = 1;
237                     break;
238           case ADD_STRENGTH:
239           case DEXTERITY:
240                     while ((ring->class = (get_rand(0, 4) - 2)) == 0)
241                               ;
242                     ring->is_cursed = (ring->class < 0);
243                     break;
244           case ADORNMENT:
245                     ring->is_cursed = coin_toss();
246                     break;
247           }
248 }
249 
250 void
inv_rings(void)251 inv_rings(void)
252 {
253           char buf[DCOLS];
254 
255           if (r_rings == 0) {
256                     messagef(0, "not wearing any rings");
257           } else {
258                     if (rogue.left_ring) {
259                               get_desc(rogue.left_ring, buf, sizeof(buf));
260                               messagef(0, "%s", buf);
261                     }
262                     if (rogue.right_ring) {
263                               get_desc(rogue.right_ring, buf, sizeof(buf));
264                               messagef(0, "%s", buf);
265                     }
266           }
267           if (wizard) {
268                     messagef(0, "ste %d, r_r %d, e_r %d, r_t %d, s_s %d, a_s %d, reg %d, r_e %d, s_i %d, m_a %d, aus %d",
269                               stealthy, r_rings, e_rings, r_teleport, sustain_strength,
270                               add_strength, regeneration, ring_exp, r_see_invisible,
271                               maintain_armor, auto_search);
272           }
273 }
274 
275 void
ring_stats(boolean pr)276 ring_stats(boolean pr)
277 {
278           short i;
279           object *ring;
280 
281           stealthy = 0;
282           r_rings = 0;
283           e_rings = 0;
284           r_teleport = 0;
285           sustain_strength = 0;
286           add_strength = 0;
287           regeneration = 0;
288           ring_exp = 0;
289           r_see_invisible = 0;
290           maintain_armor = 0;
291           auto_search = 0;
292 
293           for (i = 0; i < 2; i++) {
294                     if (!(ring = ((i == 0) ? rogue.left_ring : rogue.right_ring))) {
295                               continue;
296                     }
297                     r_rings++;
298                     e_rings++;
299                     switch(ring->which_kind) {
300                     case STEALTH:
301                               stealthy++;
302                               break;
303                     case R_TELEPORT:
304                               r_teleport = 1;
305                               break;
306                     case REGENERATION:
307                               regeneration++;
308                               break;
309                     case SLOW_DIGEST:
310                               e_rings -= 2;
311                               break;
312                     case ADD_STRENGTH:
313                               add_strength += ring->class;
314                               break;
315                     case SUSTAIN_STRENGTH:
316                               sustain_strength = 1;
317                               break;
318                     case DEXTERITY:
319                               ring_exp += ring->class;
320                               break;
321                     case ADORNMENT:
322                               break;
323                     case R_SEE_INVISIBLE:
324                               r_see_invisible = 1;
325                               break;
326                     case MAINTAIN_ARMOR:
327                               maintain_armor = 1;
328                               break;
329                     case SEARCHING:
330                               auto_search += 2;
331                               break;
332                     }
333           }
334           if (pr) {
335                     print_stats(STAT_STRENGTH);
336                     relight();
337           }
338 }
339