You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

97 lines
2.9 KiB

const SIZE = 100
const MAP = new Int8Array(SIZE * SIZE) // State of the Map
const isFree = ({ x, y }) => MAP[y * SIZE + x] === 0 // 0 = block free
const isOccupied = ({ x, y }) => MAP[y * SIZE + x] === 1 // 1 = block occupied
const inBounds = n => n < SIZE && n >= 0
const isInBounds = ({ x, y }) => inBounds(x) && inBounds(y)
const pickRandom = arr => arr[Math.floor(Math.random() * arr.length)]
// ok check if we can move on this block
const ok = (x = -1, y = -1) => {
const coords = typeof x !== 'number' ? x : { x, y }
return isFree(coords) && isInBounds(coords)
}
const isAlley = (card, x, y) => {
switch (card) {
case 0:
if (ok(x, y - 1) && !ok(x + 1, y - 1) && !ok(x - 1, y - 1)) {
while (ok(x, y - 1) && !hasLateralWalls(0, x, y)) {
y--
if (hasLateralWalls(0, x, y)) return true
}
}
return false
case 1:
if (ok(x + 1, y) && !ok(x + 1, y + 1) && !ok(x + 1, y - 1)) {
while (ok(x + 1, y) && !hasLateralWalls(1, x, y)) {
x++
if (hasLateralWalls(1, x, y)) return true
}
}
return false
case 2:
if (ok(x, y + 1) && !ok(x + 1, y + 1) && !ok(x - 1, y + 1)) {
while (ok(x, y + 1) && !hasLateralWalls(2, x, y)) {
y++
if (hasLateralWalls(2, x, y)) return true
}
}
return false
case 3:
if (ok(x - 1, y) && !ok(x - 1, y + 1) && !ok(x - 1, y - 1)) {
while (ok(x - 1, y) && !hasLateralWalls(3, x, y)) {
x--
if (hasLateralWalls(3, x, y)) return true
}
}
return false
}
}
const hasLateralWalls = (card, x, y) => {
switch (card) {
case 0: return !(ok(x + 1, y) || ok(x - 1, y) || ok(x, y - 1))
case 1: return !(ok(x, y - 1) || ok(x, y + 1) || ok(x + 1, y))
case 2: return !(ok(x + 1, y) || ok(x - 1, y) || ok(x, y + 1))
case 3: return !(ok(x, y - 1) || ok(x, y + 1) || ok(x - 1, y))
}
}
const goDirection = (ai, card) =>
ok(ai.coords[card]) &&
!isAlley(card, ai.x, ai.y) &&
ai.coords[card]
const findEnemy = state =>
state.ais.filter(p => state.ai.name !== p.name)[0]
const seekEnemy = state => {
if (state.ais.length === 1) return
const enemy = findEnemy(state)
const xPla = state.ai.x
const yPla = state.ai.y
const xOpo = enemy.x
const yOpo = enemy.y
const xDif = xPla - xOpo
const yDif = yPla - yOpo
return (
(Math.abs(xDif) > Math.abs(yDif) &&
goDirection(state.ai, xPla < xOpo ? 1 : 3)) ||
goDirection(state.ai, yPla < yOpo ? 2 : 0)
)
}
const walk = state =>
seekEnemy(state) ||
goDirection(state.ai, 0) ||
goDirection(state.ai, 1) ||
goDirection(state.ai, 2) ||
goDirection(state.ai, 3)
const addToMap = ({ x, y }) => (MAP[y * SIZE + x] = 1)
const update = state => {
state.ais.forEach(addToMap)
return walk(state)
}