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