* called with [x,y] = coordinates; * [0,0] means anyplace * [u.ux,u.uy] means: near player (if !gi.in_mklev) * * In case we make a monster group, only return the one at [x,y]. */
| 1144 | * In case we make a monster group, only return the one at [x,y]. |
| 1145 | */ |
| 1146 | struct monst * |
| 1147 | makemon( |
| 1148 | struct permonst *ptr, |
| 1149 | coordxy x, coordxy y, |
| 1150 | mmflags_nht mmflags) |
| 1151 | { |
| 1152 | struct monst *mtmp; |
| 1153 | struct monst fakemon; |
| 1154 | coord cc; |
| 1155 | int mndx, mcham, ct, mitem; |
| 1156 | boolean femaleok, maleok, |
| 1157 | anymon = !ptr, |
| 1158 | byyou = u_at(x, y), |
| 1159 | allow_minvent = ((mmflags & NO_MINVENT) == 0), |
| 1160 | countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0), |
| 1161 | allowtail = ((mmflags & MM_NOTAIL) == 0); |
| 1162 | mmflags_nht gpflags = (((mmflags & MM_IGNOREWATER) ? MM_IGNOREWATER : 0) |
| 1163 | | GP_CHECKSCARY | GP_AVOID_MONPOS); |
| 1164 | |
| 1165 | fakemon = cg.zeromonst; |
| 1166 | cc.x = cc.y = 0; |
| 1167 | |
| 1168 | if (iflags.debug_mongen || (!svl.level.flags.rndmongen && !ptr)) |
| 1169 | return (struct monst *) 0; |
| 1170 | |
| 1171 | /* if caller wants random location, do it here */ |
| 1172 | if (x == 0 && y == 0) { |
| 1173 | fakemon.data = ptr; /* set up for goodpos */ |
| 1174 | if (!makemon_rnd_goodpos(ptr ? &fakemon : (struct monst *) 0, |
| 1175 | gpflags, &cc)) |
| 1176 | return (struct monst *) 0; |
| 1177 | x = cc.x; |
| 1178 | y = cc.y; |
| 1179 | } else if (byyou && !gi.in_mklev) { |
| 1180 | if (!enexto_core(&cc, u.ux, u.uy, ptr, gpflags) |
| 1181 | && !enexto_core(&cc, u.ux, u.uy, ptr, gpflags & ~GP_CHECKSCARY)) |
| 1182 | return (struct monst *) 0; |
| 1183 | x = cc.x; |
| 1184 | y = cc.y; |
| 1185 | } |
| 1186 | |
| 1187 | /* sanity check */ |
| 1188 | if (!isok(x, y)) { |
| 1189 | impossible("makemon trying to create a monster at <%d,%d>?", x, y); |
| 1190 | return (struct monst *) 0; |
| 1191 | } |
| 1192 | |
| 1193 | /* Does monster already exist at the position? */ |
| 1194 | if (MON_AT(x, y)) { |
| 1195 | if (!(mmflags & MM_ADJACENTOK) |
| 1196 | || !enexto_core(&cc, x, y, ptr, gpflags)) |
| 1197 | return (struct monst *) 0; |
| 1198 | x = cc.x; |
| 1199 | y = cc.y; |
| 1200 | } |
| 1201 | |
| 1202 | if (ptr) { |
| 1203 | mndx = monsndx(ptr); |
no test coverage detected