| 1 | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ |
| 2 | /* hack.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 | #define WIZSHOT 6 /* one chance in WIZSHOT that wizard will try magic */ |
| 11 | #define BOLT_LIM 8 /* from this distance D and 1 will try to hit you */ |
| 12 | |
| 13 | char wizapp[] = "@DNPTUVXcemntx"; |
| 14 | |
| 15 | /* If he has found the Amulet, make the wizard appear after some time */ |
| 16 | amulet(){ |
| 17 | register struct obj *otmp; |
| 18 | register struct monst *mtmp; |
| 19 | |
| 20 | if(!flags.made_amulet || !flags.no_of_wizards) |
| 21 | return; |
| 22 | /* find wizard, and wake him if necessary */ |
| 23 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) |
| 24 | if(mtmp->data->mlet == '1' && mtmp->msleep && !rn2(40)) |
| 25 | for(otmp = invent; otmp; otmp = otmp->nobj) |
| 26 | if(otmp->olet == AMULET_SYM && !otmp->spe) { |
| 27 | mtmp->msleep = 0; |
| 28 | if(dist(mtmp->mx,mtmp->my) > 2) |
| 29 | pline( |
| 30 | "You get the creepy feeling that somebody noticed your taking the Amulet." |
| 31 | ); |
| 32 | return; |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | wiz_hit(mtmp) |
| 37 | register struct monst *mtmp; |
| 38 | { |
| 39 | /* if we have stolen or found the amulet, we disappear */ |
| 40 | if(mtmp->minvent && mtmp->minvent->olet == AMULET_SYM && |
| 41 | mtmp->minvent->spe == 0) { |
| 42 | /* vanish -- very primitive */ |
| 43 | fall_down(mtmp); |
| 44 | return(1); |
| 45 | } |
| 46 | |
| 47 | /* if it is lying around someplace, we teleport to it */ |
| 48 | if(!carrying(AMULET_OF_YENDOR)) { |
| 49 | register struct obj *otmp; |
| 50 | |
| 51 | for(otmp = fobj; otmp; otmp = otmp->nobj) |
| 52 | if(otmp->olet == AMULET_SYM && !otmp->spe) { |
| 53 | if((u.ux != otmp->ox || u.uy != otmp->oy) && |
| 54 | !m_at(otmp->ox, otmp->oy)) { |
| 55 | |
| 56 | /* teleport to it and pick it up */ |
| 57 | mtmp->mx = otmp->ox; |
| 58 | mtmp->my = otmp->oy; |
| 59 | freeobj(otmp); |
| 60 | mpickobj(mtmp, otmp); |
| 61 | pmon(mtmp); |
| 62 | return(0); |
| 63 | } |
| 64 | goto hithim; |
| 65 | } |
| 66 | return(0); /* we don't know where it is */ |
| 67 | } |
| 68 | hithim: |
| 69 | if(rn2(2)) { /* hit - perhaps steal */ |
| 70 | |
| 71 | /* if hit 1/20 chance of stealing amulet & vanish |
| 72 | - amulet is on level 26 again. */ |
| 73 | if(hitu(mtmp, d(mtmp->data->damn,mtmp->data->damd)) |
| 74 | && !rn2(20) && stealamulet(mtmp)) |
| 75 | ; |
| 76 | } |
| 77 | else |
| 78 | inrange(mtmp); /* try magic */ |
| 79 | return(0); |
| 80 | } |
| 81 | |
| 82 | inrange(mtmp) |
| 83 | register struct monst *mtmp; |
| 84 | { |
| 85 | register schar tx,ty; |
| 86 | |
| 87 | /* do nothing if cancelled (but make '1' say something) */ |
| 88 | if(mtmp->data->mlet != '1' && mtmp->mcan) |
| 89 | return; |
| 90 | |
| 91 | /* spit fire only when both in a room or both in a corridor */ |
| 92 | if(inroom(u.ux,u.uy) != inroom(mtmp->mx,mtmp->my)) return; |
| 93 | tx = u.ux - mtmp->mx; |
| 94 | ty = u.uy - mtmp->my; |
| 95 | if((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM) |
| 96 | || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)){ |
| 97 | switch(mtmp->data->mlet) { |
| 98 | case 'D': |
| 99 | /* spit fire in the direction of @ (not nec. hitting) */ |
| 100 | buzz(-1,mtmp->mx,mtmp->my,sgn(tx),sgn(ty)); |
| 101 | break; |
| 102 | case '1': |
| 103 | if(rn2(WIZSHOT)) break; |
| 104 | /* if you zapped wizard with wand of cancellation, |
| 105 | he has to shake off the effects before he can throw |
| 106 | spells successfully. 1/2 the time they fail anyway */ |
| 107 | if(mtmp->mcan || rn2(2)) { |
| 108 | if(canseemon(mtmp)) |
| 109 | pline("%s makes a gesture, then curses.", |
| 110 | Monnam(mtmp)); |
| 111 | else |
| 112 | pline("You hear mumbled cursing."); |
| 113 | if(!rn2(3)) { |
| 114 | mtmp->mspeed = 0; |
| 115 | mtmp->minvis = 0; |
| 116 | } |
| 117 | if(!rn2(3)) |
| 118 | mtmp->mcan = 0; |
| 119 | } else { |
| 120 | if(canseemon(mtmp)){ |
| 121 | if(!rn2(6) && !Invis) { |
| 122 | pline("%s hypnotizes you.", Monnam(mtmp)); |
| 123 | nomul(rn2(3) + 3); |
| 124 | break; |
| 125 | } else |
| 126 | pline("%s chants an incantation.", |
| 127 | Monnam(mtmp)); |
| 128 | } else |
| 129 | pline("You hear a mumbled incantation."); |
| 130 | switch(rn2(Invis ? 5 : 6)) { |
| 131 | case 0: |
| 132 | /* create a nasty monster from a deep level */ |
| 133 | /* (for the moment, 'nasty' is not implemented) */ |
| 134 | (void) makemon((struct permonst *)0, u.ux, u.uy); |
| 135 | break; |
| 136 | case 1: |
| 137 | pline("\"Destroy the thief, my pets!\""); |
| 138 | aggravate(); /* aggravate all the monsters */ |
| 139 | /* fall into next case */ |
| 140 | case 2: |
| 141 | if (flags.no_of_wizards == 1 && rnd(5) == 0) |
| 142 | /* if only 1 wizard, clone himself */ |
| 143 | clonewiz(mtmp); |
| 144 | break; |
| 145 | case 3: |
| 146 | if(mtmp->mspeed == MSLOW) |
| 147 | mtmp->mspeed = 0; |
| 148 | else |
| 149 | mtmp->mspeed = MFAST; |
| 150 | break; |
| 151 | case 4: |
| 152 | mtmp->minvis = 1; |
| 153 | break; |
| 154 | case 5: |
| 155 | /* Only if not Invisible */ |
| 156 | pline("You hear a clap of thunder!"); |
| 157 | /* shoot a bolt of fire or cold, or a sleep ray */ |
| 158 | buzz(-rnd(3),mtmp->mx,mtmp->my,sgn(tx),sgn(ty)); |
| 159 | break; |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | if(u.uhp < 1) done_in_by(mtmp); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | aggravate() |
| 168 | { |
| 169 | register struct monst *mtmp; |
| 170 | |
| 171 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { |
| 172 | mtmp->msleep = 0; |
| 173 | if(mtmp->mfroz && !rn2(5)) |
| 174 | mtmp->mfroz = 0; |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | clonewiz(mtmp) |
| 179 | register struct monst *mtmp; |
| 180 | { |
| 181 | register struct monst *mtmp2; |
| 182 | |
| 183 | if(mtmp2 = makemon(PM_WIZARD, mtmp->mx, mtmp->my)) { |
| 184 | flags.no_of_wizards = 2; |
| 185 | unpmon(mtmp2); |
| 186 | mtmp2->mappearance = wizapp[rn2(sizeof(wizapp)-1)]; |
| 187 | pmon(mtmp); |
| 188 | } |
| 189 | } |