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