1 /*
2  * Read a scroll and let it happen
3  *
4  * scrolls.c	1.4 (AI Design)	12/14/84
5  */
6 
7 #include "rogue.h"
8 #include "curses.h"
9 
10 char *laugh = "you hear maniacal laughter%s.";
11 char *in_dist = " in the distance";
12 /*
13  * read_scroll:
14  *	Read a scroll from the pack and do the appropriate thing
15  */
16 read_scroll()
17 {
18     register THING *obj;
19     register int y, x;
20     register byte ch;
21     register THING *op;
22     register int index;
23     register bool discardit = FALSE;
24 
25     obj = get_item("read", SCROLL);
26     if (obj == NULL)
27 		return;
28     if (obj->o_type != SCROLL){
29 		msg("there is nothing on it to read");
30 		return;
31     }
32     ifterse0("the scroll vanishes","as you read the scroll, it vanishes");
33     /*
34      * Calculate the effect it has on the poor guy.
35      */
36     if (obj == cur_weapon)
37 		cur_weapon = NULL;
38     switch (obj->o_which){
39 	when S_CONFUSE:
40 	    /*
41 	     * Scroll of monster confusion.  Give him that power.
42 	     */
43 	    player.t_flags |= CANHUH;
44 	    msg("your hands begin to glow red");
45 	when S_ARMOR:
46 	    if (cur_armor != NULL) {
47 			cur_armor->o_ac--;
48 			cur_armor->o_flags &= ~ISCURSED;
49 			ifterse0("your armor glows faintly","your armor glows faintly for a moment");
50 	    }
51 	when S_HOLD:
52 	    /*
53 	     * Hold monster scroll.  Stop all monsters within two spaces
54 	     * from chasing after the hero.
55 	     */
56 
57 	    for (x = hero.x - 3; x <= hero.x + 3; x++)
58 			if (x >= 0 && x < COLS)
59 			    for (y = hero.y - 3; y <= hero.y + 3; y++)
60 					if ((y > 0 && y < maxrow) && ((op=moat(y, x)) != NULL)) {
61 					    op->t_flags &= ~ISRUN;
62 					    op->t_flags |= ISHELD;
63 					}
64 	when S_SLEEP:
65 	    /*
66 	     * Scroll which makes you fall asleep
67 	     */
68 	    s_know[S_SLEEP] = TRUE;
69 	    no_command += rnd(SLEEPTIME) + 4;
70 	    player.t_flags &= ~ISRUN;
71 	    msg("you fall asleep");
72 	when S_CREATE:
73 	    {
74 		coord mp;
75 
76 		if (plop_monster(hero.y, hero.x, &mp) && (op=new_item()) != NULL)
77 			new_monster(op, randmonster(FALSE), &mp);
78 		else
79 			ifterse0("you hear a faint cry of anguish",
80 				"you hear a faint cry of anguish in the distance");
81 	    }
82 	when S_IDENT:
83 	    /*
84 	     * Identify, let the rogue figure something out
85 	     */
86 	    s_know[S_IDENT] = TRUE;
87 	    msg("this scroll is an identify scroll");
88 	    if (! strcmp(s_menu,"on") || !strcmp(s_menu,"sel"))
89 	    	more(" More ");
90 	    whatis(TRUE);
91 	when S_MAP:
92 	    /*
93 	     * Scroll of magic mapping.
94 	     */
95 	    s_know[S_MAP] = TRUE;
96 	    msg("oh, now this scroll has a map on it");
97 	    /*
98 	     * Take all the things we want to keep hidden out of the window
99 	     */
100 	    for (y = 1; y < maxrow; y++)
101 			for (x = 0; x < COLS; x++) {
102 			    index = INDEX(y, x);
103 			    switch (ch = _level[index])
104 			    {
105 				case VWALL:
106 				case HWALL:
107 				case ULWALL:
108 				case URWALL:
109 				case LLWALL:
110 				case LRWALL:
111 				    if (!(_flags[index] & F_REAL)) {
112 						ch = _level[index] = DOOR;
113 						_flags[index] &= ~F_REAL;
114 				    }
115 				case DOOR:
116 				case PASSAGE:
117 				case STAIRS:
118 				    if ((op = moat(y, x)) != NULL)
119 						if (op->t_oldch == ' ')
120 						    op->t_oldch = ch;
121 				    break;
122 				default:
123 				    ch = ' ';
124 			    }
125 			    if (ch == DOOR) {
126 			        move(y,x);
127 			        if (inch() != DOOR)
128 			            standout();
129 			    }
130 			    if (ch != ' ')
131 					mvaddch(y, x, ch);
132 			    standend();
133 			}
134 	when S_GFIND:
135 	    /*
136 	     * Scroll of food detection
137 	     */
138 	    ch = FALSE;
139 	    for (op = lvl_obj; op != NULL; op = next(op)) {
140 			if (op->o_type == FOOD) {
141                 ch = TRUE;
142 			    standout();
143 			    mvwaddch(hw, op->o_pos.y, op->o_pos.x, FOOD);
144 			    standend();
145 			} else /* as a bonus this will detect amulets as well */
146 			if (op->o_type == AMULET) {
147                 ch = TRUE;
148 			    standout();
149 			    mvwaddch(hw, op->o_pos.y, op->o_pos.x, AMULET);
150 			    standend();
151 			}
152 	    }
153 	    if (ch) {
154 			s_know[S_GFIND] = TRUE;
155 			msg("your nose tingles as you sense food");
156 	    } else
157 			ifterse0("you hear a growling noise close by","you hear a growling noise very close to you");
158 	when S_TELEP:
159 	    /*
160 	     * Scroll of teleportation:
161 	     * Make him dissapear and reappear
162 	     */
163 	    {
164 		register struct room *cur_room;
165 
166 		cur_room = proom;
167 		teleport();
168 		if (cur_room != proom)
169 		    s_know[S_TELEP] = TRUE;
170 	    }
171 	when S_ENCH:
172 	    if (cur_weapon == NULL || cur_weapon->o_type != WEAPON)
173 		msg("you feel a strange sense of loss");
174 	    else
175 	    {
176 		cur_weapon->o_flags &= ~ISCURSED;
177 		if (rnd(2) == 0)
178 		    cur_weapon->o_hplus++;
179 		else
180 		    cur_weapon->o_dplus++;
181 		ifterse1("your %s glows blue","your %s glows blue for a moment", w_names[cur_weapon->o_which]);
182 	    }
183 	when S_SCARE:
184 	    /*
185 	     * Reading it is a mistake and produces laughter at the
186 	     * poor rogue's boo boo.
187 	     */
188     	    msg(laugh, terse || expert ? "" : in_dist);
189 	when S_REMOVE:
190 	    if (cur_armor != NULL)
191 			cur_armor->o_flags &= ~ISCURSED;
192 	    if (cur_weapon != NULL)
193 			cur_weapon->o_flags &= ~ISCURSED;
194 	    if (cur_ring[LEFT] != NULL)
195 			cur_ring[LEFT]->o_flags &= ~ISCURSED;
196 	    if (cur_ring[RIGHT] != NULL)
197 			cur_ring[RIGHT]->o_flags &= ~ISCURSED;
198 	    ifterse0("somebody is watching over you","you feel as if somebody is watching over you");
199 	when S_AGGR:
200 	    /*
201 	     * This scroll aggravates all the monsters on the current
202 	     * level and sets them running towards the hero
203 	     */
204 	    aggravate();
205 	    ifterse("you hear a humming noise",
206 					"you hear a high pitched humming noise");
207 	when S_NOP:
208 	    msg("this scroll seems to be blank");
209 	when S_VORPAL:
210 	    /*
211 	     * Extra Vorpal Enchant Weapon
212 	     *     Give weapon +1,+1
213 	     *     Is extremely vorpal against one certain type of monster
214 	     *     Against this type (o_enemy) the weapon gets:
215 	     *		+4,+4
216 	     *		The ability to zap one such monster into oblivion
217 	     *
218 	     *     Some of these are cursed and if the rogue misses her saving
219 	     *     throw she will be forced to attack monsters of this type
220 	     *     whenever she sees one (not yet implemented)
221 	     *
222 	     * If he doesn't have a weapon I get to chortle again!
223 	     */
224 	    if (cur_weapon == NULL || cur_weapon->o_type != WEAPON)
225     		msg(laugh, terse || expert ? "" : in_dist);
226 	    else {
227 			/*
228 			 * You aren't allowed to doubly vorpalize a weapon.
229 			 */
230 			if (cur_weapon->o_enemy != 0) {
231 			    msg("your %s vanishes in a puff of smoke",
232 				w_names[cur_weapon->o_which]);
233 			    detach(pack, cur_weapon);
234 			    discard(cur_weapon);
235 			    cur_weapon = NULL;
236 			} else {
237 			    cur_weapon->o_enemy = pick_mons();
238 			    cur_weapon->o_hplus++;
239 			    cur_weapon->o_dplus++;
240 			    cur_weapon->o_charges = 1;
241 			    msg(flash, w_names[cur_weapon->o_which],
242 		    		terse || expert ? "" : intense);
243 
244 			    /*
245 			     * Sometimes this is a mixed blessing ...
246 				    if (rnd(20) == 0) {
247 						cur_weapon->o_flags |= ISCURSED;
248 						if (!save(VS_MAGIC)) {
249 						    cur_weapon->o_flags |= ISEGO|ISREVEAL;
250 						    s_know[S_VORPAL] = TRUE;
251 						    msg("you feel a sudden desire to kill %ss.",
252 							monsters[cur_weapon->o_enemy-'A'].m_name);
253 						}
254 				    }
255 			     */
256 			}
257 	    }
258 	otherwise:
259 	    msg("what a puzzling scroll!");
260 	    return;
261     }
262     look(TRUE);	/* put the result of the scroll on the screen */
263     status();
264     /*
265      * Get rid of the thing
266      */
267     inpack--;
268     if (obj->o_count > 1)
269 	obj->o_count--;
270     else
271     {
272 	detach(pack, obj);
273 	discardit = TRUE;
274     }
275     call_it(s_know[obj->o_which], &s_guess[obj->o_which]);
276 
277     if (discardit)
278 	discard(obj);
279 }
280 