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