({ thangsSrc, thangsNew, visitedPositions })
| 1478 | } |
| 1479 | |
| 1480 | function repositionFriendsAndExplosives ({ thangsSrc, thangsNew, visitedPositions }) { |
| 1481 | // Find any TNT or chickens that weren't moved into position (x == y == placeholderPosition), and try to put them where they might go |
| 1482 | // Perhaps there is an accurate way to do this, but we can also try semi-randomly until it works: |
| 1483 | // - For each leftover explosive: |
| 1484 | // - Place explosive same manhattan distance from hero start point as in the source |
| 1485 | // - Pick a random rotation and use that, maybe bias towards the one we used first in this sequence |
| 1486 | // - For each nearby chicken (also explosives but let me just not make to-avoid chain reactions) |
| 1487 | // - Use the same rotation and distance to preserve offset |
| 1488 | // Technically, we would want to move standalone friends, too, but I don't think I've used those (only friends next to TNT) |
| 1489 | |
| 1490 | const heroSrc = _.find(thangsSrc, { id: 'Hero Placeholder' }) |
| 1491 | const heroNew = _.find(thangsNew, { id: 'Hero Placeholder' }) |
| 1492 | const heroStartPosSrc = simplifyPos(_.find(heroSrc.components, (component) => component.original === PhysicalID).config.pos) |
| 1493 | const heroStartPosNew = simplifyPos(_.find(heroNew.components, (component) => component.original === PhysicalID).config.pos) |
| 1494 | |
| 1495 | const explosives = thangsNew.filter(thang => { |
| 1496 | const spriteName = thangTypesToSpriteNames[thang.thangType] |
| 1497 | if (spriteName !== 'Explosive Junior') return false |
| 1498 | const pos = simplifyPos(_.find(thang.components, (component) => component.original === PhysicalID).config.pos) |
| 1499 | return pos.x >= placeholderPositionSimple || pos.y >= placeholderPositionSimple |
| 1500 | }) |
| 1501 | // console.log('Found unplaced explosives', explosives) |
| 1502 | |
| 1503 | const processedFriendsAndExplosives = [] |
| 1504 | for (const explosiveThang of explosives) { |
| 1505 | const explosiveThangSrc = _.find(thangsSrc, { id: explosiveThang.id }) |
| 1506 | const explosivePosSrc = simplifyPos(_.find(explosiveThangSrc.components, (component) => component.original === PhysicalID).config.pos) |
| 1507 | |
| 1508 | const directions = [ |
| 1509 | new Direction('up'), |
| 1510 | new Direction('right'), |
| 1511 | new Direction('down'), |
| 1512 | new Direction('left'), |
| 1513 | { name: 'upleft', vector: new Vector(-1, 1) }, |
| 1514 | { name: 'upright', vector: new Vector(1, 1) }, |
| 1515 | { name: 'downleft', vector: new Vector(-1, -1) }, |
| 1516 | { name: 'downright', vector: new Vector(1, -1) } |
| 1517 | ] |
| 1518 | |
| 1519 | const adjacentFriendsAndExplosives = [{ thang: explosiveThang, offset: new Vector(0, 0) }] |
| 1520 | for (const direction of directions) { |
| 1521 | const nearbyPosSrc = explosivePosSrc.copy().add(direction.vector) |
| 1522 | const nearbyThang = findThangAt(nearbyPosSrc, thangsSrc, ['Explosive Junior', 'Chicken Junior']) |
| 1523 | if (nearbyThang && !floorSpriteNames.includes(thangTypesToSpriteNames[nearbyThang.thangType]) && processedFriendsAndExplosives.indexOf(nearbyThang) === -1) { |
| 1524 | adjacentFriendsAndExplosives.push({ thang: nearbyThang, offset: direction.vector }) |
| 1525 | processedFriendsAndExplosives.push(nearbyThang) |
| 1526 | } |
| 1527 | } |
| 1528 | |
| 1529 | let allPlaced = false |
| 1530 | let tries = 0 |
| 1531 | while (!allPlaced && tries < 50) { |
| 1532 | const permutationVector = new Vector(Math.random() < 0.5 ? -1 : 1, Math.random() < 0.5 ? -1 : 1) |
| 1533 | let placed = true |
| 1534 | for (const { offset } of adjacentFriendsAndExplosives) { |
| 1535 | const posSrc = explosivePosSrc.copy().add(offset) |
| 1536 | const heroToThangVectorSrc = posSrc.copy().subtract(heroStartPosSrc) |
| 1537 | const heroToThangVectorNew = heroToThangVectorSrc.copy() |
no test coverage detected