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