| 1210 | * damage is how much it deals to afflicted creatures. */ |
| 1211 | #define MAX_CLOUD_SIZE 150 |
| 1212 | NhRegion * |
| 1213 | create_gas_cloud( |
| 1214 | coordxy x, coordxy y, |
| 1215 | int cloudsize, |
| 1216 | int damage) |
| 1217 | { |
| 1218 | NhRegion *cloud; |
| 1219 | int i, j; |
| 1220 | NhRect tmprect; |
| 1221 | |
| 1222 | /* store visited coords */ |
| 1223 | coordxy xcoords[MAX_CLOUD_SIZE]; |
| 1224 | coordxy ycoords[MAX_CLOUD_SIZE]; |
| 1225 | xcoords[0] = x; |
| 1226 | ycoords[0] = y; |
| 1227 | int curridx; |
| 1228 | int newidx = 1; /* initial spot is already taken */ |
| 1229 | boolean inside_cloud = is_hero_inside_gas_cloud(); |
| 1230 | |
| 1231 | /* a single-point cloud on hero and it deals no damage. |
| 1232 | probably a natural cause of being polyed. don't message about it */ |
| 1233 | if (!svc.context.mon_moving && u_at(x, y) && cloudsize == 1 |
| 1234 | && (!damage |
| 1235 | || (damage && m_poisongas_ok(&gy.youmonst) == M_POISONGAS_OK))) |
| 1236 | inside_cloud = TRUE; |
| 1237 | |
| 1238 | if (cloudsize > MAX_CLOUD_SIZE) { |
| 1239 | impossible("create_gas_cloud: cloud too large (%d)!", cloudsize); |
| 1240 | cloudsize = MAX_CLOUD_SIZE; |
| 1241 | } |
| 1242 | |
| 1243 | for (curridx = 0; curridx < newidx; curridx++) { |
| 1244 | if (newidx >= cloudsize) |
| 1245 | break; |
| 1246 | int xx = xcoords[curridx]; |
| 1247 | int yy = ycoords[curridx]; |
| 1248 | /* Do NOT check for if there is already a gas cloud created at some |
| 1249 | * other time at this position. They can overlap. */ |
| 1250 | |
| 1251 | /* Primitive Fisher-Yates-Knuth shuffle to randomize the order of |
| 1252 | * directions chosen. */ |
| 1253 | coord dirs[4] = { {0, -1}, {0, 1}, {-1, 0}, {1, 0} }; |
| 1254 | for (i = 4; i > 0; --i) { |
| 1255 | coordxy swapidx = rn2(i); |
| 1256 | coord tmp = dirs[swapidx]; |
| 1257 | |
| 1258 | dirs[swapidx] = dirs[i - 1]; |
| 1259 | dirs[i - 1] = tmp; |
| 1260 | } |
| 1261 | int nvalid = 0; /* # of valid adjacent spots */ |
| 1262 | for (i = 0; i < 4; ++i) { |
| 1263 | /* try all 4 cardinal directions */ |
| 1264 | int dx = dirs[i].x, dy = dirs[i].y; |
| 1265 | boolean isunpicked = TRUE; |
| 1266 | |
| 1267 | if (valid_cloud_pos(xx + dx, yy + dy)) { |
| 1268 | nvalid++; |
| 1269 | /* don't pick a location we've already picked */ |
no test coverage detected