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