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