1 /* $NetBSD: hack.makemon.c,v 1.4 1997/10/19 16:58:17 christos Exp $ */ 2 3 /* 4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. 5 */ 6 7 #include <sys/cdefs.h> 8 #ifndef lint 9 __RCSID("$NetBSD: hack.makemon.c,v 1.4 1997/10/19 16:58:17 christos Exp $"); 10 #endif /* not lint */ 11 12 #include "hack.h" 13 #include "extern.h" 14 15 struct monst zeromonst; 16 17 /* 18 * called with [x,y] = coordinates; 19 * [0,0] means anyplace 20 * [u.ux,u.uy] means: call mnexto (if !in_mklev) 21 * 22 * In case we make an Orc or killer bee, we make an entire horde (swarm); 23 * note that in this case we return only one of them (the one at [x,y]). 24 */ 25 struct monst * 26 makemon(ptr, x, y) 27 struct permonst *ptr; 28 { 29 struct monst *mtmp; 30 int tmp, ct; 31 boolean anything = (!ptr); 32 33 if (x != 0 || y != 0) 34 if (m_at(x, y)) 35 return ((struct monst *) 0); 36 if (ptr) { 37 if (strchr(fut_geno, ptr->mlet)) 38 return ((struct monst *) 0); 39 } else { 40 ct = CMNUM - strlen(fut_geno); 41 if (strchr(fut_geno, 'm')) 42 ct++; /* make only 1 minotaur */ 43 if (strchr(fut_geno, '@')) 44 ct++; 45 if (ct <= 0) 46 return (0); /* no more monsters! */ 47 tmp = rn2(ct * dlevel / 24 + 7); 48 if (tmp < dlevel - 4) 49 tmp = rn2(ct * dlevel / 24 + 12); 50 if (tmp >= ct) 51 tmp = rn1(ct - ct / 2, ct / 2); 52 for (ct = 0; ct < CMNUM; ct++) { 53 ptr = &mons[ct]; 54 if (strchr(fut_geno, ptr->mlet)) 55 continue; 56 if (!tmp--) 57 goto gotmon; 58 } 59 panic("makemon?"); 60 } 61 gotmon: 62 mtmp = newmonst(ptr->pxlth); 63 *mtmp = zeromonst; /* clear all entries in structure */ 64 for (ct = 0; ct < ptr->pxlth; ct++) 65 ((char *) &(mtmp->mextra[0]))[ct] = 0; 66 mtmp->nmon = fmon; 67 fmon = mtmp; 68 mtmp->m_id = flags.ident++; 69 mtmp->data = ptr; 70 mtmp->mxlth = ptr->pxlth; 71 if (ptr->mlet == 'D') 72 mtmp->mhpmax = mtmp->mhp = 80; 73 else if (!ptr->mlevel) 74 mtmp->mhpmax = mtmp->mhp = rnd(4); 75 else 76 mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8); 77 mtmp->mx = x; 78 mtmp->my = y; 79 mtmp->mcansee = 1; 80 if (ptr->mlet == 'M') { 81 mtmp->mimic = 1; 82 mtmp->mappearance = ']'; 83 } 84 if (!in_mklev) { 85 if (x == u.ux && y == u.uy && ptr->mlet != ' ') 86 mnexto(mtmp); 87 if (x == 0 && y == 0) 88 rloc(mtmp); 89 } 90 if (ptr->mlet == 's' || ptr->mlet == 'S') { 91 mtmp->mhide = mtmp->mundetected = 1; 92 if (in_mklev) 93 if (mtmp->mx && mtmp->my) 94 (void) mkobj_at(0, mtmp->mx, mtmp->my); 95 } 96 if (ptr->mlet == ':') { 97 mtmp->cham = 1; 98 (void) newcham(mtmp, &mons[dlevel + 14 + rn2(CMNUM - 14 - dlevel)]); 99 } 100 if (ptr->mlet == 'I' || ptr->mlet == ';') 101 mtmp->minvis = 1; 102 if (ptr->mlet == 'L' || ptr->mlet == 'N' 103 || (in_mklev && strchr("&w;", ptr->mlet) && rn2(5)) 104 ) 105 mtmp->msleep = 1; 106 107 #ifndef NOWORM 108 if (ptr->mlet == 'w' && getwn(mtmp)) 109 initworm(mtmp); 110 #endif /* NOWORM */ 111 112 if (anything) 113 if (ptr->mlet == 'O' || ptr->mlet == 'k') { 114 coord mm; 115 int cnt = rnd(10); 116 mm.x = x; 117 mm.y = y; 118 while (cnt--) { 119 mm = enexto(mm.x, mm.y); 120 (void) makemon(ptr, mm.x, mm.y); 121 } 122 } 123 return (mtmp); 124 } 125 126 coord 127 enexto(xx, yy) 128 xchar xx, yy; 129 { 130 xchar x, y; 131 coord foo[15], *tfoo; 132 int range; 133 134 tfoo = foo; 135 range = 1; 136 do { /* full kludge action. */ 137 for (x = xx - range; x <= xx + range; x++) 138 if (goodpos(x, yy - range)) { 139 tfoo->x = x; 140 tfoo++->y = yy - range; 141 if (tfoo == &foo[15]) 142 goto foofull; 143 } 144 for (x = xx - range; x <= xx + range; x++) 145 if (goodpos(x, yy + range)) { 146 tfoo->x = x; 147 tfoo++->y = yy + range; 148 if (tfoo == &foo[15]) 149 goto foofull; 150 } 151 for (y = yy + 1 - range; y < yy + range; y++) 152 if (goodpos(xx - range, y)) { 153 tfoo->x = xx - range; 154 tfoo++->y = y; 155 if (tfoo == &foo[15]) 156 goto foofull; 157 } 158 for (y = yy + 1 - range; y < yy + range; y++) 159 if (goodpos(xx + range, y)) { 160 tfoo->x = xx + range; 161 tfoo++->y = y; 162 if (tfoo == &foo[15]) 163 goto foofull; 164 } 165 range++; 166 } while (tfoo == foo); 167 foofull: 168 return (foo[rn2(tfoo - foo)]); 169 } 170 171 int 172 goodpos(x, y) 173 { /* used only in mnexto and rloc */ 174 return ( 175 !(x < 1 || x > COLNO - 2 || y < 1 || y > ROWNO - 2 || 176 m_at(x, y) || !ACCESSIBLE(levl[x][y].typ) 177 || (x == u.ux && y == u.uy) 178 || sobj_at(ENORMOUS_ROCK, x, y) 179 )); 180 } 181 182 void 183 rloc(mtmp) 184 struct monst *mtmp; 185 { 186 int tx, ty; 187 char ch = mtmp->data->mlet; 188 189 #ifndef NOWORM 190 if (ch == 'w' && mtmp->mx) 191 return; /* do not relocate worms */ 192 #endif /* NOWORM */ 193 do { 194 tx = rn1(COLNO - 3, 2); 195 ty = rn2(ROWNO); 196 } while (!goodpos(tx, ty)); 197 mtmp->mx = tx; 198 mtmp->my = ty; 199 if (u.ustuck == mtmp) { 200 if (u.uswallow) { 201 u.ux = tx; 202 u.uy = ty; 203 docrt(); 204 } else 205 u.ustuck = 0; 206 } 207 pmon(mtmp); 208 } 209 210 struct monst * 211 mkmon_at(let, x, y) 212 char let; 213 int x, y; 214 { 215 int ct; 216 struct permonst *ptr; 217 218 for (ct = 0; ct < CMNUM; ct++) { 219 ptr = &mons[ct]; 220 if (ptr->mlet == let) 221 return (makemon(ptr, x, y)); 222 } 223 return (0); 224 } 225