|
|
1.1 root 1: /*
2: * object.c
3: *
4: * This source herein may be modified and/or distributed by anybody who
5: * so desires, with the following restrictions:
6: * 1.) No portion of this notice shall be removed.
7: * 2.) Credit shall not be taken for the creation of this source.
8: * 3.) This code is not to be traded, sold, or used for personal
9: * gain or profit.
10: *
11: */
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)object.c 5.1 (Berkeley) 11/25/87";
15: #endif /* not lint */
16:
17: #include "rogue.h"
18:
19: object level_objects;
20: unsigned short dungeon[DROWS][DCOLS];
21: short foods = 0;
22: object *free_list = (object *) 0;
23: char *fruit = (char *) 0;
24:
25: fighter rogue = {
26: INIT_AW, /* armor, weapon */
27: INIT_RINGS, /* rings */
28: INIT_HP, /* Hp current,max */
29: INIT_STR, /* Str current,max */
30: INIT_PACK, /* pack */
31: INIT_GOLD, /* gold */
32: INIT_EXP, /* exp level,points */
33: 0, 0, /* row, col */
34: INIT_CHAR, /* char */
35: INIT_MOVES /* moves */
36: };
37:
38: struct id id_potions[POTIONS] = {
39: {100, "blue \0 ", "of increase strength ", 0},
40: {250, "red \0 ", "of restore strength ", 0},
41: {100, "green \0 ", "of healing ", 0},
42: {200, "grey \0 ", "of extra healing ", 0},
43: {10, "brown \0 ", "of poison ", 0},
44: {300, "clear \0 ", "of raise level ", 0},
45: {10, "pink \0 ", "of blindness ", 0},
46: {25, "white \0 ", "of hallucination ", 0},
47: {100, "purple \0 ", "of detect monster ", 0},
48: {100, "black \0 ", "of detect things ", 0},
49: {10, "yellow \0 ", "of confusion ", 0},
50: {80, "plaid \0 ", "of levitation ", 0},
51: {150, "burgundy \0 ", "of haste self ", 0},
52: {145, "beige \0 ", "of see invisible ", 0}
53: };
54:
55: struct id id_scrolls[SCROLS] = {
56: {505, " ", "of protect armor ", 0},
57: {200, " ", "of hold monster ", 0},
58: {235, " ", "of enchant weapon ", 0},
59: {235, " ", "of enchant armor ", 0},
60: {175, " ", "of identify ", 0},
61: {190, " ", "of teleportation ", 0},
62: {25, " ", "of sleep ", 0},
63: {610, " ", "of scare monster ", 0},
64: {210, " ", "of remove curse ", 0},
65: {80, " ", "of create monster ",0},
66: {25, " ", "of aggravate monster ",0},
67: {180, " ", "of magic mapping ", 0},
68: {90, " ", "of confuse monster ", 0}
69: };
70:
71: struct id id_weapons[WEAPONS] = {
72: {150, "short bow ", "", 0},
73: {8, "darts ", "", 0},
74: {15, "arrows ", "", 0},
75: {27, "daggers ", "", 0},
76: {35, "shurikens ", "", 0},
77: {360, "mace ", "", 0},
78: {470, "long sword ", "", 0},
79: {580, "two-handed sword ", "", 0}
80: };
81:
82: struct id id_armors[ARMORS] = {
83: {300, "leather armor ", "", (UNIDENTIFIED)},
84: {300, "ring mail ", "", (UNIDENTIFIED)},
85: {400, "scale mail ", "", (UNIDENTIFIED)},
86: {500, "chain mail ", "", (UNIDENTIFIED)},
87: {600, "banded mail ", "", (UNIDENTIFIED)},
88: {600, "splint mail ", "", (UNIDENTIFIED)},
89: {700, "plate mail ", "", (UNIDENTIFIED)}
90: };
91:
92: struct id id_wands[WANDS] = {
93: {25, " ", "of teleport away ",0},
94: {50, " ", "of slow monster ", 0},
95: {8, " ", "of invisibility ",0},
96: {55, " ", "of polymorph ",0},
97: {2, " ", "of haste monster ",0},
98: {20, " ", "of magic missile ",0},
99: {20, " ", "of cancellation ",0},
100: {0, " ", "of do nothing ",0},
101: {35, " ", "of drain life ",0},
102: {20, " ", "of cold ",0},
103: {20, " ", "of fire ",0}
104: };
105:
106: struct id id_rings[RINGS] = {
107: {250, " ", "of stealth ",0},
108: {100, " ", "of teleportation ", 0},
109: {255, " ", "of regeneration ",0},
110: {295, " ", "of slow digestion ",0},
111: {200, " ", "of add strength ",0},
112: {250, " ", "of sustain strength ",0},
113: {250, " ", "of dexterity ",0},
114: {25, " ", "of adornment ",0},
115: {300, " ", "of see invisible ",0},
116: {290, " ", "of maintain armor ",0},
117: {270, " ", "of searching ",0},
118: };
119:
120: extern short cur_level, max_level;
121: extern short party_room;
122: extern char *error_file;
123: extern boolean is_wood[];
124:
125: put_objects()
126: {
127: short i, n;
128: object *obj;
129:
130: if (cur_level < max_level) {
131: return;
132: }
133: n = coin_toss() ? get_rand(2, 4) : get_rand(3, 5);
134: while (rand_percent(33)) {
135: n++;
136: }
137: if (party_room != NO_ROOM) {
138: make_party();
139: }
140: for (i = 0; i < n; i++) {
141: obj = gr_object();
142: rand_place(obj);
143: }
144: put_gold();
145: }
146:
147: put_gold()
148: {
149: short i, j;
150: short row,col;
151: boolean is_maze, is_room;
152:
153: for (i = 0; i < MAXROOMS; i++) {
154: is_maze = (rooms[i].is_room & R_MAZE) ? 1 : 0;
155: is_room = (rooms[i].is_room & R_ROOM) ? 1 : 0;
156:
157: if (!(is_room || is_maze)) {
158: continue;
159: }
160: if (is_maze || rand_percent(GOLD_PERCENT)) {
161: for (j = 0; j < 50; j++) {
162: row = get_rand(rooms[i].top_row+1,
163: rooms[i].bottom_row-1);
164: col = get_rand(rooms[i].left_col+1,
165: rooms[i].right_col-1);
166: if ((dungeon[row][col] == FLOOR) ||
167: (dungeon[row][col] == TUNNEL)) {
168: plant_gold(row, col, is_maze);
169: break;
170: }
171: }
172: }
173: }
174: }
175:
176: plant_gold(row, col, is_maze)
177: short row, col;
178: boolean is_maze;
179: {
180: object *obj;
181:
182: obj = alloc_object();
183: obj->row = row; obj->col = col;
184: obj->what_is = GOLD;
185: obj->quantity = get_rand((2 * cur_level), (16 * cur_level));
186: if (is_maze) {
187: obj->quantity += obj->quantity / 2;
188: }
189: dungeon[row][col] |= OBJECT;
190: (void) add_to_pack(obj, &level_objects, 0);
191: }
192:
193: place_at(obj, row, col)
194: object *obj;
195: {
196: obj->row = row;
197: obj->col = col;
198: dungeon[row][col] |= OBJECT;
199: (void) add_to_pack(obj, &level_objects, 0);
200: }
201:
202: object *
203: object_at(pack, row, col)
204: register object *pack;
205: short row, col;
206: {
207: object *obj = (object *) 0;
208:
209: if (dungeon[row][col] & (MONSTER | OBJECT)) {
210: obj = pack->next_object;
211:
212: while (obj && ((obj->row != row) || (obj->col != col))) {
213: obj = obj->next_object;
214: }
215: if (!obj) {
216: message("object_at(): inconsistent", 1);
217: }
218: }
219: return(obj);
220: }
221:
222: object *
223: get_letter_object(ch)
224: {
225: object *obj;
226:
227: obj = rogue.pack.next_object;
228:
229: while (obj && (obj->ichar != ch)) {
230: obj = obj->next_object;
231: }
232: return(obj);
233: }
234:
235: free_stuff(objlist)
236: object *objlist;
237: {
238: object *obj;
239:
240: while (objlist->next_object) {
241: obj = objlist->next_object;
242: objlist->next_object =
243: objlist->next_object->next_object;
244: free_object(obj);
245: }
246: }
247:
248: char *
249: name_of(obj)
250: object *obj;
251: {
252: char *retstring;
253:
254: switch(obj->what_is) {
255: case SCROL:
256: retstring = obj->quantity > 1 ? "scrolls " : "scroll ";
257: break;
258: case POTION:
259: retstring = obj->quantity > 1 ? "potions " : "potion ";
260: break;
261: case FOOD:
262: if (obj->which_kind == RATION) {
263: retstring = "food ";
264: } else {
265: retstring = fruit;
266: }
267: break;
268: case WAND:
269: retstring = is_wood[obj->which_kind] ? "staff " : "wand ";
270: break;
271: case WEAPON:
272: switch(obj->which_kind) {
273: case DART:
274: retstring=obj->quantity > 1 ? "darts " : "dart ";
275: break;
276: case ARROW:
277: retstring=obj->quantity > 1 ? "arrows " : "arrow ";
278: break;
279: case DAGGER:
280: retstring=obj->quantity > 1 ? "daggers " : "dagger ";
281: break;
282: case SHURIKEN:
283: retstring=obj->quantity > 1?"shurikens ":"shuriken ";
284: break;
285: default:
286: retstring = id_weapons[obj->which_kind].title;
287: }
288: break;
289: case ARMOR:
290: retstring = "armor ";
291: break;
292: case RING:
293: retstring = "ring ";
294: break;
295: case AMULET:
296: retstring = "amulet ";
297: break;
298: default:
299: retstring = "unknown ";
300: break;
301: }
302: return(retstring);
303: }
304:
305: object *
306: gr_object()
307: {
308: object *obj;
309:
310: obj = alloc_object();
311:
312: if (foods < (cur_level / 3)) {
313: obj->what_is = FOOD;
314: foods++;
315: } else {
316: obj->what_is = gr_what_is();
317: }
318: switch(obj->what_is) {
319: case SCROL:
320: gr_scroll(obj);
321: break;
322: case POTION:
323: gr_potion(obj);
324: break;
325: case WEAPON:
326: gr_weapon(obj, 1);
327: break;
328: case ARMOR:
329: gr_armor(obj);
330: break;
331: case WAND:
332: gr_wand(obj);
333: break;
334: case FOOD:
335: get_food(obj, 0);
336: break;
337: case RING:
338: gr_ring(obj, 1);
339: break;
340: }
341: return(obj);
342: }
343:
344: unsigned short
345: gr_what_is()
346: {
347: short percent;
348: unsigned short what_is;
349:
350: percent = get_rand(1, 91);
351:
352: if (percent <= 30) {
353: what_is = SCROL;
354: } else if (percent <= 60) {
355: what_is = POTION;
356: } else if (percent <= 64) {
357: what_is = WAND;
358: } else if (percent <= 74) {
359: what_is = WEAPON;
360: } else if (percent <= 83) {
361: what_is = ARMOR;
362: } else if (percent <= 88) {
363: what_is = FOOD;
364: } else {
365: what_is = RING;
366: }
367: return(what_is);
368: }
369:
370: gr_scroll(obj)
371: object *obj;
372: {
373: short percent;
374:
375: percent = get_rand(0, 91);
376:
377: obj->what_is = SCROL;
378:
379: if (percent <= 5) {
380: obj->which_kind = PROTECT_ARMOR;
381: } else if (percent <= 10) {
382: obj->which_kind = HOLD_MONSTER;
383: } else if (percent <= 20) {
384: obj->which_kind = CREATE_MONSTER;
385: } else if (percent <= 35) {
386: obj->which_kind = IDENTIFY;
387: } else if (percent <= 43) {
388: obj->which_kind = TELEPORT;
389: } else if (percent <= 50) {
390: obj->which_kind = SLEEP;
391: } else if (percent <= 55) {
392: obj->which_kind = SCARE_MONSTER;
393: } else if (percent <= 64) {
394: obj->which_kind = REMOVE_CURSE;
395: } else if (percent <= 69) {
396: obj->which_kind = ENCH_ARMOR;
397: } else if (percent <= 74) {
398: obj->which_kind = ENCH_WEAPON;
399: } else if (percent <= 80) {
400: obj->which_kind = AGGRAVATE_MONSTER;
401: } else if (percent <= 86) {
402: obj->which_kind = CON_MON;
403: } else {
404: obj->which_kind = MAGIC_MAPPING;
405: }
406: }
407:
408: gr_potion(obj)
409: object *obj;
410: {
411: short percent;
412:
413: percent = get_rand(1, 118);
414:
415: obj->what_is = POTION;
416:
417: if (percent <= 5) {
418: obj->which_kind = RAISE_LEVEL;
419: } else if (percent <= 15) {
420: obj->which_kind = DETECT_OBJECTS;
421: } else if (percent <= 25) {
422: obj->which_kind = DETECT_MONSTER;
423: } else if (percent <= 35) {
424: obj->which_kind = INCREASE_STRENGTH;
425: } else if (percent <= 45) {
426: obj->which_kind = RESTORE_STRENGTH;
427: } else if (percent <= 55) {
428: obj->which_kind = HEALING;
429: } else if (percent <= 65) {
430: obj->which_kind = EXTRA_HEALING;
431: } else if (percent <= 75) {
432: obj->which_kind = BLINDNESS;
433: } else if (percent <= 85) {
434: obj->which_kind = HALLUCINATION;
435: } else if (percent <= 95) {
436: obj->which_kind = CONFUSION;
437: } else if (percent <= 105) {
438: obj->which_kind = POISON;
439: } else if (percent <= 110) {
440: obj->which_kind = LEVITATION;
441: } else if (percent <= 114) {
442: obj->which_kind = HASTE_SELF;
443: } else {
444: obj->which_kind = SEE_INVISIBLE;
445: }
446: }
447:
448: gr_weapon(obj, assign_wk)
449: object *obj;
450: int assign_wk;
451: {
452: short percent;
453: short i;
454: short blessing, increment;
455:
456: obj->what_is = WEAPON;
457: if (assign_wk) {
458: obj->which_kind = get_rand(0, (WEAPONS - 1));
459: }
460: if ((obj->which_kind == ARROW) || (obj->which_kind == DAGGER) ||
461: (obj->which_kind == SHURIKEN) | (obj->which_kind == DART)) {
462: obj->quantity = get_rand(3, 15);
463: obj->quiver = get_rand(0, 126);
464: } else {
465: obj->quantity = 1;
466: }
467: obj->hit_enchant = obj->d_enchant = 0;
468:
469: percent = get_rand(1, 96);
470: blessing = get_rand(1, 3);
471:
472: if (percent <= 16) {
473: increment = 1;
474: } else if (percent <= 32) {
475: increment = -1;
476: obj->is_cursed = 1;
477: }
478: if (percent <= 32) {
479: for (i = 0; i < blessing; i++) {
480: if (coin_toss()) {
481: obj->hit_enchant += increment;
482: } else {
483: obj->d_enchant += increment;
484: }
485: }
486: }
487: switch(obj->which_kind) {
488: case BOW:
489: case DART:
490: obj->damage = "1d1";
491: break;
492: case ARROW:
493: obj->damage = "1d2";
494: break;
495: case DAGGER:
496: obj->damage = "1d3";
497: break;
498: case SHURIKEN:
499: obj->damage = "1d4";
500: break;
501: case MACE:
502: obj->damage = "2d3";
503: break;
504: case LONG_SWORD:
505: obj->damage = "3d4";
506: break;
507: case TWO_HANDED_SWORD:
508: obj->damage = "4d5";
509: break;
510: }
511: }
512:
513: gr_armor(obj)
514: object *obj;
515: {
516: short percent;
517: short blessing;
518:
519: obj->what_is = ARMOR;
520: obj->which_kind = get_rand(0, (ARMORS - 1));
521: obj->class = obj->which_kind + 2;
522: if ((obj->which_kind == PLATE) || (obj->which_kind == SPLINT)) {
523: obj->class--;
524: }
525: obj->is_protected = 0;
526: obj->d_enchant = 0;
527:
528: percent = get_rand(1, 100);
529: blessing = get_rand(1, 3);
530:
531: if (percent <= 16) {
532: obj->is_cursed = 1;
533: obj->d_enchant -= blessing;
534: } else if (percent <= 33) {
535: obj->d_enchant += blessing;
536: }
537: }
538:
539: gr_wand(obj)
540: object *obj;
541: {
542: obj->what_is = WAND;
543: obj->which_kind = get_rand(0, (WANDS - 1));
544: obj->class = get_rand(3, 7);
545: }
546:
547: get_food(obj, force_ration)
548: object *obj;
549: boolean force_ration;
550: {
551: obj->what_is = FOOD;
552:
553: if (force_ration || rand_percent(80)) {
554: obj->which_kind = RATION;
555: } else {
556: obj->which_kind = FRUIT;
557: }
558: }
559:
560: put_stairs()
561: {
562: short row, col;
563:
564: gr_row_col(&row, &col, (FLOOR | TUNNEL));
565: dungeon[row][col] |= STAIRS;
566: }
567:
568: get_armor_class(obj)
569: object *obj;
570: {
571: if (obj) {
572: return(obj->class + obj->d_enchant);
573: }
574: return(0);
575: }
576:
577: object *
578: alloc_object()
579: {
580: object *obj;
581:
582: if (free_list) {
583: obj = free_list;
584: free_list = free_list->next_object;
585: } else if (!(obj = (object *) md_malloc(sizeof(object)))) {
586: message("cannot allocate object, saving game", 0);
587: save_into_file(error_file);
588: }
589: obj->quantity = 1;
590: obj->ichar = 'L';
591: obj->picked_up = obj->is_cursed = 0;
592: obj->in_use_flags = NOT_USED;
593: obj->identified = UNIDENTIFIED;
594: obj->damage = "1d1";
595: return(obj);
596: }
597:
598: free_object(obj)
599: object *obj;
600: {
601: obj->next_object = free_list;
602: free_list = obj;
603: }
604:
605: make_party()
606: {
607: short n;
608:
609: party_room = gr_room();
610:
611: n = rand_percent(99) ? party_objects(party_room) : 11;
612: if (rand_percent(99)) {
613: party_monsters(party_room, n);
614: }
615: }
616:
617: show_objects()
618: {
619: object *obj;
620: short mc, rc, row, col;
621: object *monster;
622:
623: obj = level_objects.next_object;
624:
625: while (obj) {
626: row = obj->row;
627: col = obj->col;
628:
629: rc = get_mask_char(obj->what_is);
630:
631: if (dungeon[row][col] & MONSTER) {
632: if (monster = object_at(&level_monsters, row, col)) {
633: monster->trail_char = rc;
634: }
635: }
636: mc = mvinch(row, col);
637: if (((mc < 'A') || (mc > 'Z')) &&
638: ((row != rogue.row) || (col != rogue.col))) {
639: mvaddch(row, col, rc);
640: }
641: obj = obj->next_object;
642: }
643:
644: monster = level_monsters.next_object;
645:
646: while (monster) {
647: if (monster->m_flags & IMITATES) {
648: mvaddch(monster->row, monster->col, (int) monster->disguise);
649: }
650: monster = monster->next_monster;
651: }
652: }
653:
654: put_amulet()
655: {
656: object *obj;
657:
658: obj = alloc_object();
659: obj->what_is = AMULET;
660: rand_place(obj);
661: }
662:
663: rand_place(obj)
664: object *obj;
665: {
666: short row, col;
667:
668: gr_row_col(&row, &col, (FLOOR | TUNNEL));
669: place_at(obj, row, col);
670: }
671:
672: c_object_for_wizard()
673: {
674: short ch, max, wk;
675: object *obj;
676: char buf[80];
677:
678: if (pack_count((object *) 0) >= MAX_PACK_COUNT) {
679: message("pack full", 0);
680: return;
681: }
682: message("type of object?", 0);
683:
684: while (r_index("!?:)]=/,\033", (ch = rgetchar()), 0) == -1) {
685: sound_bell();
686: }
687: check_message();
688:
689: if (ch == '\033') {
690: return;
691: }
692: obj = alloc_object();
693:
694: switch(ch) {
695: case '!':
696: obj->what_is = POTION;
697: max = POTIONS - 1;
698: break;
699: case '?':
700: obj->what_is = SCROL;
701: max = SCROLS - 1;
702: break;
703: case ',':
704: obj->what_is = AMULET;
705: break;
706: case ':':
707: get_food(obj, 0);
708: break;
709: case ')':
710: gr_weapon(obj, 0);
711: max = WEAPONS - 1;
712: break;
713: case ']':
714: gr_armor(obj);
715: max = ARMORS - 1;
716: break;
717: case '/':
718: gr_wand(obj);
719: max = WANDS - 1;
720: break;
721: case '=':
722: max = RINGS - 1;
723: obj->what_is = RING;
724: break;
725: }
726: if ((ch != ',') && (ch != ':')) {
727: GIL:
728: if (get_input_line("which kind?", "", buf, "", 0, 1)) {
729: wk = get_number(buf);
730: if ((wk >= 0) && (wk <= max)) {
731: obj->which_kind = (unsigned short) wk;
732: if (obj->what_is == RING) {
733: gr_ring(obj, 0);
734: }
735: } else {
736: sound_bell();
737: goto GIL;
738: }
739: } else {
740: free_object(obj);
741: return;
742: }
743: }
744: get_desc(obj, buf);
745: message(buf, 0);
746: (void) add_to_pack(obj, &rogue.pack, 1);
747: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.