Skip to content

Instantly share code, notes, and snippets.

@alexey-krivoshapko
Created February 20, 2019 10:40
Show Gist options
  • Save alexey-krivoshapko/c49f8cff44b018307c73ac7ad66543d9 to your computer and use it in GitHub Desktop.
Save alexey-krivoshapko/c49f8cff44b018307c73ac7ad66543d9 to your computer and use it in GitHub Desktop.
import { getBoardAsString, getXYByPosition, getElementByXY, getBoardSize, getHeadPosition } from './utils';
import {ELEMENT, COMMANDS} from './constants';
export class Bot {
constructor() {
this.init();
}
run(board) {
this.update(board);
for (let i = 0; i < this.data.length; i++) {
let p = this.data[i];
this.enemiesLength += this.enemiesElements().indexOf(p) > -1;
this.playersLength += this.playersElements().indexOf(p) > -1;
}
for (let i = 0; i < this.data.length; i++) {
let p = this.data[i];
if (this.needed(p)) {
let x = i % this.size;
let y = Math.floor(i / this.size);
this.targets.push({
x: x,
y: y,
l: Math.abs(x - this.head.position.x) + Math.abs(y - this.head.position.y),
c: p,
});
}
if (this.debug) {
let state = this.validate(this.data[i], i);
this.updateBoard(state);
}
}
if (this.debug) {
this.debugInfo();
}
return this;
}
update(board) {
this.board = '';
this.data = board;
this.targets = [];
this.target = null;
this.enemiesLength = 0;
this.playersLength = 0;
this.size = getBoardSize(board);
this.setHead();
}
init() {
this.board = '';
this.data = '';
this.debug = true;
this.targets = [];
this.target = null;
this.prevHead = {x:14, y:14};
this.enemiesLength = 0;
this.playersLength = 0;
this.command = COMMANDS.RIGHT;
this.size = getBoardSize(board);
this.head = {
head: 'head',
sing: ELEMENT.HEAD_RIGHT,
position: {
x: 0,
y: 0
},
evil: 0,
fly: 0,
};
}
setHead() {
let head_p = getHeadPosition(this.data);
let head_c = getElementByXY(this.data, head_p);
let head = function() {
if (head_c === ELEMENT.HEAD_EVIL) {
return 'evil';
} else if(head_c === ELEMENT.HEAD_FLY) {
return 'fly';
} else {
return 'head';
}
}();
let evil = function(this_head) {
if (this_head !== head && head === 'evil') {
return 10;
} else {
return Math.max(this_head.evil - 1, 0);
}
}(this.head);
let fly = function(this_head) {
if (this_head !== head && head === 'fly') {
return 10;
} else {
return Math.max(this_head.fly - 1, 0);
}
}(this.head);
this.head = {
head: head,
sing: head_c,
position: {
x: head_p.x,
y: head_p.y
},
evil: evil,
fly: fly,
};
}
debugInfo() {
console.log(getBoardAsString(this.board));
console.log({
head: this.head,
// size: this.size,
// command: this.command,
playersLength: this.playersLength,
enemiesLength: this.enemiesLength,
isBiggest: this.isBiggest(),
target: this.target
});
}
updateBoard(state) {
this.board += (state ? '⛉' : '⛊');
}
validate(point, i) {
return this.nearOpen(i) && this.allowed(point);
}
nearOpen(i) {
let rate = 0;
let position = getXYByPosition(this.data, i);
let allowed = { t: 0, r: 0, b: 0, l: 0 };
allowed.t = this.nearRate(position, 'top');
rate += allowed.t;
allowed.r = this.nearRate(position, 'right');
rate += allowed.r;
allowed.b = this.nearRate(position, 'bottom');
rate += allowed.b;
allowed.l = this.nearRate(position, 'left');
rate += allowed.l;
if (rate < 2) {
return false;
} else if (rate > 2) {
return true;
} else {
// return true;
let reverseRate = 0;
if (allowed.t) {
reverseRate += this.nearRate({x: position.x, y: position.y - 2}, 'top');
reverseRate += this.nearRate({x: position.x, y: position.y - 2}, 'right');
reverseRate += this.nearRate({x: position.x, y: position.y - 2}, 'left');
}
if (allowed.r) {
reverseRate += this.nearRate({x: position.x + 2, y: position.y}, 'top');
reverseRate += this.nearRate({x: position.x + 2, y: position.y}, 'right');
reverseRate += this.nearRate({x: position.x + 2, y: position.y}, 'bottom');
}
if (allowed.b) {
reverseRate += this.nearRate({x: position.x, y: position.y + 2}, 'bottom');
reverseRate += this.nearRate({x: position.x, y: position.y + 2}, 'right');
reverseRate += this.nearRate({x: position.x, y: position.y + 2}, 'left');
}
if (allowed.l) {
reverseRate += this.nearRate({x: position.x - 2, y: position.y}, 'top');
reverseRate += this.nearRate({x: position.x - 2, y: position.y}, 'right');
reverseRate += this.nearRate({x: position.x - 2, y: position.y}, 'bottom');
}
return reverseRate > 3;
}
}
getCommand() {
let command = '';
let head = getHeadPosition(this.data);
this.targets.sort(function (a, b) {
return a.l - b.l;
});
console.log(this.targets[0]);
let target = this.targets[0] || {x: 14, y: 14};
let commands = [
COMMANDS.UP,
COMMANDS.RIGHT,
COMMANDS.DOWN,
COMMANDS.LEFT,
COMMANDS.ACT,
];
let index = head.x + head.y * this.size;
if (head.x < target.x && head.x >= this.prevHead.x) {
commands.unshift(COMMANDS.RIGHT);
} else if (head.x > target.x && head.x <= this.prevHead.x) {
commands.unshift(COMMANDS.LEFT);
} else if (head.y < target.y && head.y >= this.prevHead.y) {
commands.unshift(COMMANDS.DOWN);
} else if (head.y > target.y && head.y <= this.prevHead.y) {
commands.unshift(COMMANDS.UP);
}
if (this.needed(this.data[index + 1])) {
commands.unshift(COMMANDS.RIGHT);
} else if (this.needed(this.data[index - 1])) {
commands.unshift(COMMANDS.LEFT);
} else if (this.needed(this.data[index + this.size])) {
commands.unshift(COMMANDS.DOWN);
} else if (this.needed(this.data[index - this.size])) {
commands.unshift(COMMANDS.UP);
}
for (let i = 0; i < commands.length; i++) {
if (commands[i] === COMMANDS.UP && this.validate(this.data[index - this.size], index - this.size)) {
command = COMMANDS.UP;
break;
} else if (commands[i] === COMMANDS.RIGHT && this.validate(this.data[index + 1], index + 1)) {
command = COMMANDS.RIGHT;
break;
} else if (commands[i] === COMMANDS.DOWN && this.validate(this.data[index + this.size], index + this.size)) {
command = COMMANDS.DOWN;
break;
} else if (commands[i] === COMMANDS.LEFT && this.validate(this.data[index - 1], index - 1)) {
command = COMMANDS.LEFT;
break;
}
}
this.prevHead = head;
if (this.isBiggest() && this.command === command) {
command = COMMANDS.ACT;
} else {
this.command = command;
}
return command;
}
nearRate(position, direction) {
let coordinates = { x: position.x, y: position.y };
switch (direction) {
case ('top') : coordinates = { x: position.x, y: position.y - 1 }; break;
case ('right') : coordinates = { x: position.x + 1, y: position.y }; break;
case ('bottom') : coordinates = { x: position.x, y: position.y + 1 }; break;
case ('left') : coordinates = { x: position.x - 1, y: position.y }; break;
}
return Number(this.allowed(getElementByXY(this.data, coordinates)));
}
allowed(point) {
let allowed = [ELEMENT.NONE].concat(ELS.HEAD, ELS.BODY, ELS.TAIL, ELS.ALLOW);
return allowed.indexOf(point) > -1;
}
needed(point) {
let elements = [];
if(this.isBiggest()) {
if (this.head.evil) {
return this.enemiesElements().indexOf(point) > -1;
} else if(this.data.indexOf(ELEMENT.FURY_PILL) > -1) {
elements = elements.concat([ELEMENT.FURY_PILL, ELEMENT.STONE], ELS.ENEMY_HEAD);
} else {
elements = elements.concat(ELS.ENEMY_HEAD);
}
} else {
elements = elements.concat(ELS.ALLOW);
}
return elements.indexOf(point) > -1;
}
enemiesElements() {
return [].concat(ELS.ENEMY_HEAD, ELS.ENEMY_BODY, ELS.ENEMY_TAIL);
}
playersElements() {
return [].concat(ELS.HEAD, ELS.BODY, ELS.TAIL);
}
isBiggest(count = 2) {
return this.enemiesLength + count < this.playersLength;
}
}
const ELS = {
'HEAD': [
ELEMENT.HEAD_DOWN,
ELEMENT.HEAD_LEFT,
ELEMENT.HEAD_RIGHT,
ELEMENT.HEAD_UP,
ELEMENT.HEAD_DEAD,
ELEMENT.HEAD_EVIL,
ELEMENT.HEAD_FLY,
ELEMENT.HEAD_SLEEP,
],
'TAIL': [
ELEMENT.TAIL_END_DOWN,
ELEMENT.TAIL_END_LEFT,
ELEMENT.TAIL_END_UP,
ELEMENT.TAIL_END_RIGHT,
ELEMENT.TAIL_INACTIVE,
],
'BODY': [
ELEMENT.BODY_HORIZONTAL,
ELEMENT.BODY_VERTICAL,
ELEMENT.BODY_LEFT_DOWN,
ELEMENT.BODY_LEFT_UP,
ELEMENT.BODY_RIGHT_DOWN,
ELEMENT.BODY_RIGHT_UP,
],
'ENEMY_HEAD': [
ELEMENT.ENEMY_HEAD_DOWN,
ELEMENT.ENEMY_HEAD_LEFT,
ELEMENT.ENEMY_HEAD_RIGHT,
ELEMENT.ENEMY_HEAD_UP,
ELEMENT.ENEMY_HEAD_DEAD,
ELEMENT.ENEMY_HEAD_EVIL,
ELEMENT.ENEMY_HEAD_FLY,
ELEMENT.ENEMY_HEAD_SLEEP,
],
'ENEMY_TAIL': [
ELEMENT.ENEMY_TAIL_END_DOWN,
ELEMENT.ENEMY_TAIL_END_LEFT,
ELEMENT.ENEMY_TAIL_END_UP,
ELEMENT.ENEMY_TAIL_END_RIGHT,
ELEMENT.ENEMY_TAIL_INACTIVE,
],
'ENEMY_BODY': [
ELEMENT.ENEMY_BODY_HORIZONTAL,
ELEMENT.ENEMY_BODY_VERTICAL,
ELEMENT.ENEMY_BODY_LEFT_DOWN,
ELEMENT.ENEMY_BODY_LEFT_UP,
ELEMENT.ENEMY_BODY_RIGHT_DOWN,
ELEMENT.ENEMY_BODY_RIGHT_UP,
],
'ALLOW': [
ELEMENT.APPLE,
ELEMENT.FLYING_PILL,
ELEMENT.FURY_PILL,
ELEMENT.GOLD,
],
'ENEMY__': [],
};
@codenjoyme
Copy link

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment