comparison rogue5/things.c @ 33:f502bf60e6e4

Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author elwin
date Mon, 24 May 2010 20:10:59 +0000
parents
children ded75a57405c
comparison
equal deleted inserted replaced
32:2dcd75e6a736 33:f502bf60e6e4
1 /*
2 * Contains functions for dealing with things like potions, scrolls,
3 * and other items.
4 *
5 * @(#)things.c 4.53 (Berkeley) 02/05/99
6 *
7 * Rogue: Exploring the Dungeons of Doom
8 * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
9 * All rights reserved.
10 *
11 * See the file LICENSE.TXT for full copyright and licensing information.
12 */
13
14 #include <stdlib.h>
15 #include <curses.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include "rogue.h"
19
20 /*
21 * inv_name:
22 * Return the name of something as it would appear in an
23 * inventory.
24 */
25 char *
26 inv_name(const THING *obj, int drop)
27 {
28 char *pb;
29 struct obj_info *op;
30 const char *sp;
31 int which;
32
33 pb = prbuf;
34 which = obj->o_which;
35 switch (obj->o_type)
36 {
37 case POTION:
38 nameit(obj, "potion", p_colors[which], &pot_info[which], nullstr);
39 when RING:
40 nameit(obj, "ring", r_stones[which], &ring_info[which], ring_num);
41 when STICK:
42 nameit(obj, ws_type[which], ws_made[which], &ws_info[which], charge_str);
43 when SCROLL:
44 if (obj->o_count == 1)
45 {
46 strcpy(pb, "A scroll ");
47 pb = &prbuf[9];
48 }
49 else
50 {
51 sprintf(pb, "%d scrolls ", obj->o_count);
52 pb = &prbuf[strlen(prbuf)];
53 }
54 op = &scr_info[which];
55 if (op->oi_know)
56 sprintf(pb, "of %s", op->oi_name);
57 else if (op->oi_guess)
58 sprintf(pb, "called %s", op->oi_guess);
59 else
60 sprintf(pb, "titled '%s'", s_names[which]);
61 when FOOD:
62 if (which == 1)
63 if (obj->o_count == 1)
64 sprintf(pb, "A%s %s", vowelstr(fruit), fruit);
65 else
66 sprintf(pb, "%d %ss", obj->o_count, fruit);
67 else
68 if (obj->o_count == 1)
69 strcpy(pb, "Some food");
70 else
71 sprintf(pb, "%d rations of food", obj->o_count);
72 when WEAPON:
73 sp = weap_info[which].oi_name;
74 if (obj->o_count > 1)
75 sprintf(pb, "%d ", obj->o_count);
76 else
77 sprintf(pb, "A%s ", vowelstr(sp));
78 pb = &prbuf[strlen(prbuf)];
79 if (obj->o_flags & ISKNOW)
80 sprintf(pb, "%s %s", num(obj->o_hplus,obj->o_dplus,WEAPON), sp);
81 else
82 sprintf(pb, "%s", sp);
83 if (obj->o_count > 1)
84 strcat(pb, "s");
85 if (obj->o_label != NULL)
86 {
87 pb = &prbuf[strlen(prbuf)];
88 sprintf(pb, " called %s", obj->o_label);
89 }
90 when ARMOR:
91 sp = arm_info[which].oi_name;
92 if (obj->o_flags & ISKNOW)
93 {
94 sprintf(pb, "%s %s [",
95 num(a_class[which] - obj->o_arm, 0, ARMOR), sp);
96 if (!terse)
97 strcat(pb, "protection ");
98 pb = &prbuf[strlen(prbuf)];
99 sprintf(pb, "%d]", 10 - obj->o_arm);
100 }
101 else
102 sprintf(pb, "%s", sp);
103 if (obj->o_label != NULL)
104 {
105 pb = &prbuf[strlen(prbuf)];
106 sprintf(pb, " called %s", obj->o_label);
107 }
108 when AMULET:
109 strcpy(pb, "The Amulet of Yendor");
110 when GOLD:
111 sprintf(prbuf, "%d Gold pieces", obj->o_goldval);
112 #ifdef MASTER
113 otherwise:
114 debug("Picked up something funny %s", unctrl(obj->o_type));
115 sprintf(pb, "Something bizarre %s", unctrl(obj->o_type));
116 #endif
117 }
118 if (inv_describe)
119 {
120 if (obj == cur_armor)
121 strcat(pb, " (being worn)");
122 if (obj == cur_weapon)
123 strcat(pb, " (weapon in hand)");
124 if (obj == cur_ring[LEFT])
125 strcat(pb, " (on left hand)");
126 else if (obj == cur_ring[RIGHT])
127 strcat(pb, " (on right hand)");
128 }
129 if (drop && isupper((int)prbuf[0]))
130 prbuf[0] = (char) tolower(prbuf[0]);
131 else if (!drop && islower((int)*prbuf))
132 *prbuf = (char) toupper(*prbuf);
133 prbuf[MAXSTR-1] = '\0';
134 return prbuf;
135 }
136
137 /*
138 * drop:
139 * Put something down
140 */
141
142 void
143 drop(void)
144 {
145 int ch;
146 THING *obj;
147
148 ch = chat(hero.y, hero.x);
149 if (ch != FLOOR && ch != PASSAGE)
150 {
151 after = FALSE;
152 msg("there is something there already");
153 return;
154 }
155 if ((obj = get_item("drop", 0)) == NULL)
156 return;
157 if (!dropcheck(obj))
158 return;
159 obj = leave_pack(obj, TRUE, !ISMULT(obj->o_type));
160 /*
161 * Link it into the level object list
162 */
163 attach(lvl_obj, obj);
164 chat(hero.y, hero.x) = obj->o_type;
165 flat(hero.y, hero.x) |= F_DROPPED;
166 obj->o_pos = hero;
167 if (obj->o_type == AMULET)
168 amulet = FALSE;
169 msg("dropped %s", inv_name(obj, TRUE));
170 }
171
172 /*
173 * dropcheck:
174 * Do special checks for dropping or unweilding|unwearing|unringing
175 */
176 int
177 dropcheck(const THING *obj)
178 {
179 if (obj == NULL)
180 return TRUE;
181 if (obj != cur_armor && obj != cur_weapon
182 && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT])
183 return TRUE;
184 if (obj->o_flags & ISCURSED)
185 {
186 msg("you can't. It appears to be cursed");
187 return FALSE;
188 }
189 if (obj == cur_weapon)
190 cur_weapon = NULL;
191 else if (obj == cur_armor)
192 {
193 waste_time();
194 cur_armor = NULL;
195 }
196 else
197 {
198 cur_ring[obj == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
199 switch (obj->o_which)
200 {
201 case R_ADDSTR:
202 chg_str(-obj->o_arm);
203 break;
204 case R_SEEINVIS:
205 unsee();
206 extinguish(unsee);
207 break;
208 }
209 }
210 return TRUE;
211 }
212
213 /*
214 * new_thing:
215 * Return a new thing
216 */
217 THING *
218 new_thing(void)
219 {
220 THING *cur;
221 int r;
222
223 cur = new_item();
224 cur->o_hplus = 0;
225 cur->o_dplus = 0;
226 strncpy(cur->o_damage, "0x0", sizeof(cur->o_damage));
227 strncpy(cur->o_hurldmg, "0x0", sizeof(cur->o_hurldmg));
228 cur->o_arm = 11;
229 cur->o_count = 1;
230 cur->o_group = 0;
231 cur->o_flags = 0;
232 /*
233 * Decide what kind of object it will be
234 * If we haven't had food for a while, let it be food.
235 */
236 switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS))
237 {
238 case 0:
239 cur->o_type = POTION;
240 cur->o_which = pick_one(pot_info, MAXPOTIONS);
241 when 1:
242 cur->o_type = SCROLL;
243 cur->o_which = pick_one(scr_info, MAXSCROLLS);
244 when 2:
245 cur->o_type = FOOD;
246 no_food = 0;
247 if (rnd(10) != 0)
248 cur->o_which = 0;
249 else
250 cur->o_which = 1;
251 when 3:
252 init_weapon(cur, pick_one(weap_info, MAXWEAPONS));
253 if ((r = rnd(100)) < 10)
254 {
255 cur->o_flags |= ISCURSED;
256 cur->o_hplus -= rnd(3) + 1;
257 }
258 else if (r < 15)
259 cur->o_hplus += rnd(3) + 1;
260 when 4:
261 cur->o_type = ARMOR;
262 cur->o_which = pick_one(arm_info, MAXARMORS);
263 cur->o_arm = a_class[cur->o_which];
264 if ((r = rnd(100)) < 20)
265 {
266 cur->o_flags |= ISCURSED;
267 cur->o_arm += rnd(3) + 1;
268 }
269 else if (r < 28)
270 cur->o_arm -= rnd(3) + 1;
271 when 5:
272 cur->o_type = RING;
273 cur->o_which = pick_one(ring_info, MAXRINGS);
274 switch (cur->o_which)
275 {
276 case R_ADDSTR:
277 case R_PROTECT:
278 case R_ADDHIT:
279 case R_ADDDAM:
280 if ((cur->o_arm = rnd(3)) == 0)
281 {
282 cur->o_arm = -1;
283 cur->o_flags |= ISCURSED;
284 }
285 when R_AGGR:
286 case R_TELEPORT:
287 cur->o_flags |= ISCURSED;
288 }
289 when 6:
290 cur->o_type = STICK;
291 cur->o_which = pick_one(ws_info, MAXSTICKS);
292 fix_stick(cur);
293 #ifdef MASTER
294 otherwise:
295 debug("Picked a bad kind of object");
296 wait_for(stdscr, ' ');
297 #endif
298 }
299 return cur;
300 }
301
302 /*
303 * pick_one:
304 * Pick an item out of a list of nitems possible objects
305 */
306 int
307 pick_one(const struct obj_info *info, int nitems)
308 {
309 const struct obj_info *end;
310 const struct obj_info *start;
311 int i;
312
313 start = info;
314 for (end = &info[nitems], i = rnd(100); info < end; info++)
315 if (i < info->oi_prob)
316 break;
317 if (info == end)
318 {
319 #ifdef MASTER
320 if (wizard)
321 {
322 msg("bad pick_one: %d from %d items", i, nitems);
323 for (info = start; info < end; info++)
324 msg("%s: %d%%", info->oi_name, info->oi_prob);
325 }
326 #endif
327 info = start;
328 }
329 return (int)(info - start);
330 }
331
332 /*
333 * discovered:
334 * list what the player has discovered in this game of a certain type
335 */
336 static int line_cnt = 0;
337
338 static int newpage = FALSE;
339
340 static const char *lastfmt, *lastarg;
341
342
343 void
344 discovered(void)
345 {
346 int ch;
347 int disc_list;
348
349 do {
350 disc_list = FALSE;
351 if (!terse)
352 addmsg("for ");
353 addmsg("what type");
354 if (!terse)
355 addmsg(" of object do you want a list");
356 msg("? (* for all)");
357 ch = readchar();
358 switch (ch)
359 {
360 case ESCAPE:
361 msg("");
362 return;
363 case POTION:
364 case SCROLL:
365 case RING:
366 case STICK:
367 case '*':
368 disc_list = TRUE;
369 break;
370 default:
371 if (terse)
372 msg("Not a type");
373 else
374 msg("Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK);
375 }
376 } while (!disc_list);
377 if (ch == '*')
378 {
379 print_disc(POTION);
380 add_line("", NULL);
381 print_disc(SCROLL);