mirror of https://github.com/01-edu/public.git
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
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) |
|
}
|
|
|