wizard.c (8225B)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* wizard.c - version 1.0.3 */ 3 4 /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */ 5 6 #include "hack.h" 7 extern struct permonst pm_wizard; 8 extern struct monst *makemon(); 9 10 #ifdef DGK 11 #define WIZSHOT 2 /* one chance in WIZSHOT that wizard will try magic */ 12 #else 13 #define WIZSHOT 6 /* one chance in WIZSHOT that wizard will try magic */ 14 #endif 15 #define BOLT_LIM 8 /* from this distance D and 1 will try to hit you */ 16 17 char wizapp[] = "@DNPTUVXcemntx"; 18 19 #ifdef DGK 20 #define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y)) 21 extern char mlarge[]; 22 23 movedist(x0, x1, y0, y1) 24 { 25 register int absdx, absdy; 26 27 absdx = abs(x1 - x0); 28 absdy = abs(y1 - y0); 29 30 return (absdx + absdy - min(absdx, absdy)); 31 } 32 #endif 33 34 /* If he has found the Amulet, make the wizard appear after some time */ 35 amulet(){ 36 register struct obj *otmp; 37 register struct monst *mtmp; 38 39 if(!flags.made_amulet || !flags.no_of_wizards) 40 return; 41 /* find wizard, and wake him if necessary */ 42 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 43 if(mtmp->data->mlet == '1' && mtmp->msleep && !rn2(40)) 44 for(otmp = invent; otmp; otmp = otmp->nobj) 45 if(otmp->olet == AMULET_SYM && !otmp->spe) { 46 mtmp->msleep = 0; 47 if(dist(mtmp->mx,mtmp->my) > 2) 48 pline( 49 "You get the creepy feeling that somebody noticed your taking the Amulet." 50 ); 51 return; 52 } 53 } 54 55 wiz_hit(mtmp) 56 register struct monst *mtmp; 57 { 58 /* if we have stolen or found the amulet, we disappear */ 59 if(mtmp->minvent && mtmp->minvent->olet == AMULET_SYM && 60 mtmp->minvent->spe == 0) { 61 /* vanish -- very primitive */ 62 fall_down(mtmp); 63 return(1); 64 } 65 66 /* if it is lying around someplace, we teleport to it */ 67 if(!carrying(AMULET_OF_YENDOR)) { 68 register struct obj *otmp; 69 70 for(otmp = fobj; otmp; otmp = otmp->nobj) 71 if(otmp->olet == AMULET_SYM && !otmp->spe) { 72 if((u.ux != otmp->ox || u.uy != otmp->oy) && 73 !m_at(otmp->ox, otmp->oy)) { 74 75 /* teleport to it and pick it up */ 76 mtmp->mx = otmp->ox; 77 mtmp->my = otmp->oy; 78 freeobj(otmp); 79 mpickobj(mtmp, otmp); 80 pmon(mtmp); 81 return(0); 82 } 83 goto hithim; 84 } 85 return(0); /* we don't know where it is */ 86 } 87 hithim: 88 if(rn2(2)) { /* hit - perhaps steal */ 89 90 /* if hit 1/20 chance of stealing amulet & vanish 91 - amulet is on level 26 again. */ 92 if(hitu(mtmp, d(mtmp->data->damn,mtmp->data->damd)) 93 && !rn2(20) && stealamulet(mtmp)) 94 ; 95 } 96 else 97 inrange(mtmp); /* try magic */ 98 return(0); 99 } 100 101 #ifdef DGK 102 /* Check if a monster is carrying a particular item. 103 */ 104 struct obj * 105 m_carrying(mtmp, type) 106 struct monst *mtmp; 107 int type; 108 { 109 register struct obj *otmp; 110 111 for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 112 if(otmp->otyp == type) 113 return(otmp); 114 return((struct obj *) 0); 115 } 116 117 /* Remove an item from the monster's inventory. 118 */ 119 m_useup(mon, obj) 120 struct monst *mon; 121 struct obj *obj; 122 { 123 struct obj *otmp, *prev; 124 125 prev = ((struct obj *) 0); 126 for (otmp = mon->minvent; otmp; otmp = otmp->nobj) { 127 if (otmp == obj) { 128 if (prev) 129 prev->nobj = obj->nobj; 130 else 131 mon->minvent = obj->nobj; 132 free((char *) obj); 133 break; 134 } 135 prev = otmp; 136 } 137 } 138 139 m_throw(x, y, dx, dy, range, obj) 140 register int x,y,dx,dy,range; /* direction and range */ 141 register struct obj *obj; 142 { 143 register struct monst *mtmp; 144 struct objclass *oclass = &objects[obj->otyp]; 145 char sym = obj->olet; 146 int damage; 147 extern char *exclam(); 148 149 bhitpos.x = x; 150 bhitpos.y = y; 151 152 if(sym) tmp_at(-1, sym); /* open call */ 153 while(range-- > 0) { 154 bhitpos.x += dx; 155 bhitpos.y += dy; 156 if(mtmp = m_at(bhitpos.x,bhitpos.y)) { 157 damage = index(mlarge, mtmp->data->mlet) 158 ? oclass->wldam 159 : oclass->wsdam; 160 hit(oclass->oc_name, mtmp, exclam(damage)); 161 mtmp->mhp -= damage; 162 if(mtmp->mhp < 1) { 163 pline("%s is killed!", Monnam(mtmp)); 164 mondied(mtmp); 165 } 166 range = 0; 167 } 168 if (bhitpos.x == u.ux && bhitpos.y == u.uy) { 169 if (multi) 170 nomul(0); 171 if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)) { 172 mksobj_at(obj->otyp, u.ux, u.uy); 173 fobj->quan = 1; 174 stackobj(fobj); 175 } 176 range = 0; 177 } 178 tmp_at(bhitpos.x, bhitpos.y); 179 } 180 tmp_at(-1, -1); 181 } 182 #endif 183 184 /* Return 1 if it's OK for the monster to move as well as (throw, 185 * zap, etc). 186 */ 187 inrange(mtmp) 188 register struct monst *mtmp; 189 { 190 register schar tx,ty; 191 #ifdef DGK 192 struct obj *otmp; 193 register xchar x, y; 194 #endif 195 196 /* do nothing if cancelled (but make '1' say something) */ 197 if(mtmp->data->mlet != '1' && mtmp->mcan) 198 return 1; 199 200 /* spit fire only when both in a room or both in a corridor */ 201 if(inroom(u.ux,u.uy) != inroom(mtmp->mx,mtmp->my)) return 1; 202 tx = u.ux - mtmp->mx; 203 ty = u.uy - mtmp->my; 204 #ifdef DGK 205 if ((!tx || !ty || abs(tx) == abs(ty)) /* straight line or diagonal */ 206 && movedist(tx, 0, ty, 0) < BOLT_LIM) { 207 /* Check if there are any dead squares between. If so, 208 * it won't be possible to shoot. 209 */ 210 for (x = mtmp->mx, y = mtmp->my; x != u.ux || y != u.uy; 211 x += sgn(tx), y += sgn(ty)) 212 if (!ACCESSIBLE(levl[x][y].typ)) 213 return 1; 214 215 switch(mtmp->data->mlet) { 216 case 'K': 217 case 'C': 218 /* If you're coming toward the monster, the monster 219 * should try to soften you up with arrows. If you're 220 * going away, you are probably hurt or running. Give 221 * chase, but if you're getting too far away, throw. 222 */ 223 x = mtmp->mx; 224 y = mtmp->my; 225 otmp = (mtmp->data->mlet == 'K') ? m_carrying(mtmp, DART) 226 : m_carrying(mtmp, CROSSBOW_BOLT); 227 if (otmp && (!URETREATING(x,y) 228 || !rn2(BOLT_LIM - movedist(x, u.ux, y, u.uy)))) { 229 m_throw(mtmp->mx, mtmp->my, sgn(tx), sgn(ty), 230 BOLT_LIM,otmp); 231 if (!--otmp->quan) 232 m_useup(mtmp, otmp); 233 return 0; 234 } 235 break; 236 #else 237 if((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM) 238 || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)){ 239 switch(mtmp->data->mlet) { 240 #endif 241 case 'D': 242 /* spit fire in the direction of @ (not nec. hitting) */ 243 buzz(-1,mtmp->mx,mtmp->my,sgn(tx),sgn(ty)); 244 break; 245 case '1': 246 if(rn2(WIZSHOT)) break; 247 /* if you zapped wizard with wand of cancellation, 248 he has to shake off the effects before he can throw 249 spells successfully. 1/2 the time they fail anyway */ 250 if(mtmp->mcan || rn2(2)) { 251 if(canseemon(mtmp)) 252 pline("%s makes a gesture, then curses.", 253 Monnam(mtmp)); 254 else 255 pline("You hear mumbled cursing."); 256 if(!rn2(3)) { 257 mtmp->mspeed = 0; 258 mtmp->minvis = 0; 259 } 260 if(!rn2(3)) 261 mtmp->mcan = 0; 262 } else { 263 if(canseemon(mtmp)){ 264 if(!rn2(6) && !Invis) { 265 pline("%s hypnotizes you.", Monnam(mtmp)); 266 #ifdef DGK 267 /* bug fix by ab@unido 268 */ 269 nomul(-(rn2(3) + 3)); 270 #else 271 nomul(rn2(3) + 3); 272 #endif 273 break; 274 } else 275 pline("%s chants an incantation.", 276 Monnam(mtmp)); 277 } else 278 pline("You hear a mumbled incantation."); 279 switch(rn2(Invis ? 5 : 6)) { 280 case 0: 281 /* create a nasty monster from a deep level */ 282 /* (for the moment, 'nasty' is not implemented) */ 283 (void) makemon((struct permonst *)0, u.ux, u.uy); 284 break; 285 case 1: 286 pline("\"Destroy the thief, my pets!\""); 287 aggravate(); /* aggravate all the monsters */ 288 /* fall into next case */ 289 case 2: 290 if (flags.no_of_wizards == 1 && rnd(5) == 0) 291 /* if only 1 wizard, clone himself */ 292 clonewiz(mtmp); 293 break; 294 case 3: 295 if(mtmp->mspeed == MSLOW) 296 mtmp->mspeed = 0; 297 else 298 mtmp->mspeed = MFAST; 299 break; 300 case 4: 301 mtmp->minvis = 1; 302 break; 303 case 5: 304 /* Only if not Invisible */ 305 pline("You hear a clap of thunder!"); 306 /* shoot a bolt of fire or cold, or a sleep ray */ 307 buzz(-rnd(3),mtmp->mx,mtmp->my,sgn(tx),sgn(ty)); 308 break; 309 } 310 } 311 } 312 if(u.uhp < 1) done_in_by(mtmp); 313 } 314 return 1; 315 } 316 317 aggravate() 318 { 319 register struct monst *mtmp; 320 321 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 322 mtmp->msleep = 0; 323 if(mtmp->mfroz && !rn2(5)) 324 mtmp->mfroz = 0; 325 } 326 } 327 328 clonewiz(mtmp) 329 register struct monst *mtmp; 330 { 331 register struct monst *mtmp2; 332 333 if(mtmp2 = makemon(PM_WIZARD, mtmp->mx, mtmp->my)) { 334 flags.no_of_wizards = 2; 335 unpmon(mtmp2); 336 mtmp2->mappearance = wizapp[rn2(sizeof(wizapp)-1)]; 337 pmon(mtmp); 338 } 339 }