1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64: #include <sys/cdefs.h>
65: #ifndef lint
66: __RCSID("$NetBSD: hack.invent.c,v 1.9 2004/01/27 20:30:29 jsm Exp $");
67: #endif
68:
69: #include <stdlib.h>
70: #include "hack.h"
71: #include "extern.h"
72:
73: #ifndef NOWORM
74: #include "def.wseg.h"
75: #endif
76:
77: #define NOINVSYM '#'
78:
79: static int lastinvnr = 51;
80:
81: static void assigninvlet(struct obj *);
82: static char *xprname(struct obj *, char);
83:
84: static void
85: assigninvlet(otmp)
86: struct obj *otmp;
87: {
88: boolean inuse[52];
89: int i;
90: struct obj *obj;
91:
92: for (i = 0; i < 52; i++)
93: inuse[i] = FALSE;
94: for (obj = invent; obj; obj = obj->nobj)
95: if (obj != otmp) {
96: i = obj->invlet;
97: if ('a' <= i && i <= 'z')
98: inuse[i - 'a'] = TRUE;
99: else if ('A' <= i && i <= 'Z')
100: inuse[i - 'A' + 26] = TRUE;
101: if (i == otmp->invlet)
102: otmp->invlet = 0;
103: }
104: if ((i = otmp->invlet) &&
105: (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
106: return;
107: for (i = lastinvnr + 1; i != lastinvnr; i++) {
108: if (i == 52) {
109: i = -1;
110: continue;
111: }
112: if (!inuse[i])
113: break;
114: }
115: otmp->invlet = (inuse[i] ? NOINVSYM :
116: (i < 26) ? ('a' + i) : ('A' + i - 26));
117: lastinvnr = i;
118: }
119:
120: struct obj *
121: addinv(obj)
122: struct obj *obj;
123: {
124: struct obj *otmp;
125:
126:
127: if (!invent) {
128: invent = obj;
129: otmp = 0;
130: } else
131: for (otmp = invent; ; otmp = otmp->nobj) {
132: if (merged(otmp, obj, 0))
133: return (otmp);
134: if (!otmp->nobj) {
135: otmp->nobj = obj;
136: break;
137: }
138: }
139: obj->nobj = 0;
140:
141: if (flags.invlet_constant) {
142: assigninvlet(obj);
143:
144:
145:
146:
147:
148: if (otmp) {
149: otmp->nobj = 0;
150: if ((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
151: obj->nobj = invent;
152: invent = obj;
153: } else
154: for (otmp = invent;; otmp = otmp->nobj) {
155: if (!otmp->nobj ||
156: (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)) {
157: obj->nobj = otmp->nobj;
158: otmp->nobj = obj;
159: break;
160: }
161: }
162: }
163: }
164: return (obj);
165: }
166:
167: void
168: useup(obj)
169: struct obj *obj;
170: {
171: if (obj->quan > 1) {
172: obj->quan--;
173: obj->owt = weight(obj);
174: } else {
175: setnotworn(obj);
176: freeinv(obj);
177: obfree(obj, (struct obj *) 0);
178: }
179: }
180:
181: void
182: freeinv(obj)
183: struct obj *obj;
184: {
185: struct obj *otmp;
186:
187: if (obj == invent)
188: invent = invent->nobj;
189: else {
190: for (otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
191: if (!otmp->nobj)
192: panic("freeinv");
193: otmp->nobj = obj->nobj;
194: }
195: }
196:
197:
198: void
199: delobj(obj)
200: struct obj *obj;
201: {
202: freeobj(obj);
203: unpobj(obj);
204: obfree(obj, (struct obj *) 0);
205: }
206:
207:
208: void
209: freeobj(obj)
210: struct obj *obj;
211: {
212: struct obj *otmp;
213:
214: if (obj == fobj)
215: fobj = fobj->nobj;
216: else {
217: for (otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj)
218: if (!otmp)
219: panic("error in freeobj");
220: otmp->nobj = obj->nobj;
221: }
222: }
223:
224:
225: void
226: freegold(gold)
227: struct gold *gold;
228: {
229: struct gold *gtmp;
230:
231: if (gold == fgold)
232: fgold = gold->ngold;
233: else {
234: for (gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
235: if (!gtmp)
236: panic("error in freegold");
237: gtmp->ngold = gold->ngold;
238: }
239: free((char *) gold);
240: }
241:
242: void
243: deltrap(trap)
244: struct trap *trap;
245: {
246: struct trap *ttmp;
247:
248: if (trap == ftrap)
249: ftrap = ftrap->ntrap;
250: else {
251: for (ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap);
252: ttmp->ntrap = trap->ntrap;
253: }
254: free((char *) trap);
255: }
256:
257: struct wseg *m_atseg;
258:
259: struct monst *
260: m_at(x, y)
261: int x, y;
262: {
263: struct monst *mtmp;
264: #ifndef NOWORM
265: struct wseg *wtmp;
266: #endif
267:
268: m_atseg = 0;
269: for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
270: if (mtmp->mx == x && mtmp->my == y)
271: return (mtmp);
272: #ifndef NOWORM
273: if (mtmp->wormno) {
274: for (wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)
275: if (wtmp->wx == x && wtmp->wy == y) {
276: m_atseg = wtmp;
277: return (mtmp);
278: }
279: }
280: #endif
281: }
282: return (0);
283: }
284:
285: struct obj *
286: o_at(x, y)
287: int x, y;
288: {
289: struct obj *otmp;
290:
291: for (otmp = fobj; otmp; otmp = otmp->nobj)
292: if (otmp->ox == x && otmp->oy == y)
293: return (otmp);
294: return (0);
295: }
296:
297: struct obj *
298: sobj_at(n, x, y)
299: int n, x, y;
300: {
301: struct obj *otmp;
302:
303: for (otmp = fobj; otmp; otmp = otmp->nobj)
304: if (otmp->ox == x && otmp->oy == y && otmp->otyp == n)
305: return (otmp);
306: return (0);
307: }
308:
309: int
310: carried(obj)
311: struct obj *obj;
312: {
313: struct obj *otmp;
314: for (otmp = invent; otmp; otmp = otmp->nobj)
315: if (otmp == obj)
316: return (1);
317: return (0);
318: }
319:
320: int
321: carrying(type)
322: int type;
323: {
324: struct obj *otmp;
325:
326: for (otmp = invent; otmp; otmp = otmp->nobj)
327: if (otmp->otyp == type)
328: return (TRUE);
329: return (FALSE);
330: }
331:
332: struct obj *
333: o_on(id, objchn)
334: unsigned int id;
335: struct obj *objchn;
336: {
337: while (objchn) {
338: if (objchn->o_id == id)
339: return (objchn);
340: objchn = objchn->nobj;
341: }
342: return ((struct obj *) 0);
343: }
344:
345: struct trap *
346: t_at(x, y)
347: int x, y;
348: {
349: struct trap *trap = ftrap;
350: while (trap) {
351: if (trap->tx == x && trap->ty == y)
352: return (trap);
353: trap = trap->ntrap;
354: }
355: return (0);
356: }
357:
358: struct gold *
359: g_at(x, y)
360: int x, y;
361: {
362: struct gold *gold = fgold;
363: while (gold) {
364: if (gold->gx == x && gold->gy == y)
365: return (gold);
366: gold = gold->ngold;
367: }
368: return (0);
369: }
370:
371:
372: struct obj *
373: mkgoldobj(q)
374: long q;
375: {
376: struct obj *otmp;
377:
378: otmp = newobj(0);
379:
380: otmp->olet = '$';
381: u.ugold -= q;
382: OGOLD(otmp) = q;
383: flags.botl = 1;
384: return (otmp);
385: }
386:
387:
388:
389:
390:
391:
392:
393: struct obj *
394: getobj(let, word)
395: const char *let, *word;
396: {
397: struct obj *otmp;
398: char ilet, ilet1, ilet2;
399: char buf[BUFSZ];
400: char lets[BUFSZ];
401: int foo = 0, foo2;
402: char *bp = buf;
403: xchar allowcnt = 0;
404: boolean allowgold = FALSE;
405: boolean allowall = FALSE;
406: boolean allownone = FALSE;
407: xchar foox = 0;
408: long cnt;
409:
410: if (*let == '0')
411: let++, allowcnt = 1;
412: if (*let == '$')
413: let++, allowgold = TRUE;
414: if (*let == '#')
415: let++, allowall = TRUE;
416: if (*let == '-')
417: let++, allownone = TRUE;
418: if (allownone)
419: *bp++ = '-';
420: if (allowgold)
421: *bp++ = '$';
422: if (bp > buf && bp[-1] == '-')
423: *bp++ = ' ';
424:
425: ilet = 'a';
426: for (otmp = invent; otmp; otmp = otmp->nobj) {
427: if (!*let || strchr(let, otmp->olet)) {
428: bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;
429:
430:
431: if ((!strcmp(word, "take off") &&
432: !(otmp->owornmask & (W_ARMOR - W_ARM2)))
433: || (!strcmp(word, "wear") &&
434: (otmp->owornmask & (W_ARMOR | W_RING)))
435: || (!strcmp(word, "wield") &&
436: (otmp->owornmask & W_WEP))) {
437: foo--;
438: foox++;
439: }
440: }
441: if (ilet == 'z')
442: ilet = 'A';
443: else
444: ilet++;
445: }
446: bp[foo] = 0;
447: if (foo == 0 && bp > buf && bp[-1] == ' ')
448: *--bp = 0;
449: (void) strcpy(lets, bp);
450: if (foo > 5) {
451: foo = foo2 = 1;
452: ilet2 = bp[0];
453: ilet1 = bp[1];
454: while ((ilet = bp[++foo2] = bp[++foo]) != '\0') {
455: if (ilet == ilet1 + 1) {
456: if (ilet1 == ilet2 + 1)
457: bp[foo2 - 1] = ilet1 = '-';
458: else if (ilet2 == '-') {
459: bp[--foo2] = ++ilet1;
460: continue;
461: }
462: }
463: ilet2 = ilet1;
464: ilet1 = ilet;
465: }
466: }
467: if (!foo && !allowall && !allowgold && !allownone) {
468: pline("You don't have anything %sto %s.",
469: foox ? "else " : "", word);
470: return (0);
471: }
472: for (;;) {
473: if (!buf[0])
474: pline("What do you want to %s [*]? ", word);
475: else
476: pline("What do you want to %s [%s or ?*]? ",
477: word, buf);
478:
479: cnt = 0;
480: ilet = readchar();
481: while (digit(ilet) && allowcnt) {
482: if (cnt < 100000000)
483: cnt = 10 * cnt + (ilet - '0');
484: else
485: cnt = 999999999;
486: allowcnt = 2;
487: ilet = readchar();
488: }
489: if (digit(ilet)) {
490: pline("No count allowed with this command.");
491: continue;
492: }
493: if (strchr(quitchars, ilet))
494: return ((struct obj *) 0);
495: if (ilet == '-') {
496: return (allownone ? &zeroobj : (struct obj *) 0);
497: }
498: if (ilet == '$') {
499: if (!allowgold) {
500: pline("You cannot %s gold.", word);
501: continue;
502: }
503: if (!(allowcnt == 2 && cnt < u.ugold))
504: cnt = u.ugold;
505: return (mkgoldobj(cnt));
506: }
507: if (ilet == '?') {
508: doinv(lets);
509: if (!(ilet = morc))
510: continue;
511:
512: } else if (ilet == '*') {
513: doinv((char *) 0);
514: if (!(ilet = morc))
515: continue;
516:
517: }
518: if (flags.invlet_constant) {
519: for (otmp = invent; otmp; otmp = otmp->nobj)
520: if (otmp->invlet == ilet)
521: break;
522: } else {
523: if (ilet >= 'A' && ilet <= 'Z')
524: ilet += 'z' - 'A' + 1;
525: ilet -= 'a';
526: for (otmp = invent; otmp && ilet;
527: ilet--, otmp = otmp->nobj);
528: }
529: if (!otmp) {
530: pline("You don't have that object.");
531: continue;
532: }
533: if (cnt < 0 || otmp->quan < cnt) {
534: pline("You don't have that many! [You have %u]"
535: ,otmp->quan);
536: continue;
537: }
538: break;
539: }
540: if (!allowall && let && !strchr(let, otmp->olet)) {
541: pline("That is a silly thing to %s.", word);
542: return (0);
543: }
544: if (allowcnt == 2) {
545: if (cnt == 0)
546: return (0);
547: if (cnt != otmp->quan) {
548: struct obj *obj;
549: obj = splitobj(otmp, (int) cnt);
550: if (otmp == uwep)
551: setuwep(obj);
552: