diff --git a/debug/debug.php b/debug/debug.php index 41f3d3b..850ef14 100644 --- a/debug/debug.php +++ b/debug/debug.php @@ -68,9 +68,12 @@ function readJsonFile($file)
- + Block heads Attack heads + Snake bodies + Borders + Dead ends
@@ -89,6 +92,8 @@ function readJsonFile($file)
+ Next + Previous
diff --git a/debug/styles.css b/debug/styles.css index 7ce06a7..d5ac13f 100644 --- a/debug/styles.css +++ b/debug/styles.css @@ -91,6 +91,10 @@ pre { flex: 1; width: 100%; border: 1px solid #eee; + text-align: center; + font-size: 22px; + line-height: 4; + color: #fff; } .weight { diff --git a/src/lib/moveTowardsFoodPf.ts b/src/lib/moveTowardsFoodPf.ts index 48a8376..a284187 100644 --- a/src/lib/moveTowardsFoodPf.ts +++ b/src/lib/moveTowardsFoodPf.ts @@ -29,10 +29,7 @@ function sortedFood(request: BTRequest, weightOptions: WeightOptions): Sorted[] food: food, distance: path.distance, direction: path.direction, - weight: weight(request, food.x, food.y, { - blockHeads: true, - attackHeads: true, - }) + weight: weight(request, food.x, food.y, weightOptions) }); } } @@ -71,7 +68,7 @@ function isSquadCloser(request: BTRequest, closest: Sorted, weightOptions: Weigh export function moveTowardsFoodPf(request: BTRequest, weightOptions: WeightOptions, ignoreCloserSquads: boolean) { const sorted = sortedFood(request, weightOptions); if (!sorted.length) { - log('moveTowardsFoodPf', 'no food'); + request.log('moveTowardsFoodPf', 'no food'); return; } for (const closest of sorted) { @@ -85,10 +82,10 @@ export function moveTowardsFoodPf(request: BTRequest, weightOptions: WeightOptio } // Check if squad is closer if (!ignoreCloserSquads || !isSquadCloser(request, closest, weightOptions)) { - log('moveTowardsFoodPf', closest.direction, closest.food, closest.weight, closest.distance); + request.log('moveTowardsFoodPf', closest.direction, closest.food, closest.weight, closest.distance); return closest.direction; } } } - log('moveTowardsFoodPf', 'no options'); + request.log('moveTowardsFoodPf', 'no options'); } diff --git a/src/lib/weight.ts b/src/lib/weight.ts index 8b472e8..79a34a4 100644 --- a/src/lib/weight.ts +++ b/src/lib/weight.ts @@ -101,9 +101,22 @@ const isNearTail = (data: BTData, x: number, y: number) => { export interface WeightOptions { blockHeads: boolean, attackHeads: boolean, + borders?: boolean, + snakeBodies?: boolean, + deadEnds?: boolean, } export function weight(request: BTRequest, x: number, y: number, options: WeightOptions): number { + if (options.borders === undefined) { + options.borders = true; + } + if (options.snakeBodies === undefined) { + options.snakeBodies = true; + } + if (options.deadEnds === undefined) { + options.deadEnds = true; + } + request.grid[y][x].weight = computeWeight(request, x, y, options); let color = Math.round((request.grid[y][x].weight) / 100 * 255); @@ -123,13 +136,11 @@ function computeWeight(request: BTRequest, x: number, y: number, options: Weight let result = 100; for (const snake of request.body.board.snakes) { - const body = snake.body; - // const body = snake.body.filter((p1, i, a) => a.findIndex(p2 => p1.x == p2.x && p1.y == p2.y) === i); - for (const [p, part] of body.entries()) { + for (const [p, part] of snake.body.entries()) { // Is part of snake? if (part.x == x && part.y == y) { // Is end of snake? - if (p != body.length - 1) { + if (p != snake.body.length - 1) { // Is head of snake, and head blocking? if (p === 0 && !options.blockHeads) { continue; @@ -152,13 +163,15 @@ function computeWeight(request: BTRequest, x: number, y: number, options: Weight // return 75; // } - if (isDeadEnd(request.body, x, y) && !isNearTail(request.body, x, y)) { - return 0; - } + if (options.deadEnds) { + if (isDeadEnd(request.body, x, y) && !isNearTail(request.body, x, y)) { + return 1; + } - const fillCount = floodFill(request, x, y); - if (fillCount < request.body.you.body.length) { - result = Math.min(result, fillCount); + const fillCount = floodFill(request, x, y); + if (fillCount < request.body.you.body.length) { + result = Math.min(result, fillCount); + } } if (options.attackHeads) { @@ -176,43 +189,47 @@ function computeWeight(request: BTRequest, x: number, y: number, options: Weight } } - for (const snake of request.body.board.snakes) { - const body = snake.body; - for (const [p, part] of body.entries()) { - let tailWeight = 40; - if (p == body.length - 1) { - tailWeight = 55; - } - if (x + 1 == part.x && y == part.y) { - result = Math.min(result, tailWeight); - } - if (x - 1 == part.x && y == part.y) { - result = Math.min(result, tailWeight); - } - if (x == part.x && y + 1 == part.y) { - result = Math.min(result, tailWeight); - } - if (x == part.x && y - 1 == part.y) { - result = Math.min(result, tailWeight); + if (options.snakeBodies) { + for (const snake of request.body.board.snakes) { + const body = snake.body; + for (const [p, part] of body.entries()) { + let tailWeight = 40; + if (p == body.length - 1) { + tailWeight = 55; + } + if (x + 1 == part.x && y == part.y) { + result = Math.min(result, tailWeight); + } + if (x - 1 == part.x && y == part.y) { + result = Math.min(result, tailWeight); + } + if (x == part.x && y + 1 == part.y) { + result = Math.min(result, tailWeight); + } + if (x == part.x && y - 1 == part.y) { + result = Math.min(result, tailWeight); + } } } } // Borders - if (x == 0) { - result = Math.min(result, 35); - } + if (options.borders) { + if (x == 0) { + result = Math.min(result, 35); + } - if (y == 0) { - result = Math.min(result, 35); - } + if (y == 0) { + result = Math.min(result, 35); + } - if (x == request.body.board.width - 1) { - result = Math.min(result, 35); - } + if (x == request.body.board.width - 1) { + result = Math.min(result, 35); + } - if (y == request.body.board.height - 1) { - result = Math.min(result, 35); + if (y == request.body.board.height - 1) { + result = Math.min(result, 35); + } } result = Math.min(result, 50); diff --git a/src/server/snakes/tail-chase.ts b/src/server/snakes/tail-chase.ts index fca2a31..2cd8dc6 100644 --- a/src/server/snakes/tail-chase.ts +++ b/src/server/snakes/tail-chase.ts @@ -29,9 +29,19 @@ export class TailChase extends BaseSnake implements ISnake { private getFood(request: BTRequest): MoveDirection { if (request.body.you.health < request.body.board.width || request.body.you.health < request.body.board.height) { + request.log('TailChase', 'gettingFood', { + blockHeads: true, + attackHeads: true, + borders: false, + snakeBodies: false, + deadEnds: false, + }, true); return moveTowardsFoodPf(request, { blockHeads: true, attackHeads: true, + borders: false, + snakeBodies: false, + deadEnds: false, }, true); } } @@ -40,6 +50,9 @@ export class TailChase extends BaseSnake implements ISnake { return moveTowardsTail(request, { blockHeads: true, attackHeads: false, + borders: false, + snakeBodies: false, + deadEnds: false, }); } diff --git a/src/web/controllers/debug.ts b/src/web/controllers/debug.ts index f9e3648..5a02256 100644 --- a/src/web/controllers/debug.ts +++ b/src/web/controllers/debug.ts @@ -5,7 +5,7 @@ import { BTRequest } from '../../types/BTData'; interface DebugControllerScope extends AngularScope { request: BTRequest, - recomputeWeights: (blockHeads: boolean, attackHeads: boolean) => void, + recomputeWeights: (...any: any[]) => void, } export const DebugController = [ @@ -17,13 +17,16 @@ export const DebugController = [ loadGrid($scope.request); }); - $scope.recomputeWeights = (blockHeads: boolean, attackHeads: boolean) => { + $scope.recomputeWeights = (blockHeads: boolean, attackHeads: boolean, snakeBodies: boolean, borders: boolean, deadEnds: boolean) => { console.log('Recompute weights'); for (var y = 0; y < $scope.request.body.board.height; y++) { for (var x = 0; x < $scope.request.body.board.width; x++) { $scope.request.grid[y][x].weight = weight($scope.request, x, y, { - blockHeads, - attackHeads, + blockHeads: blockHeads || false, + attackHeads: attackHeads || false, + snakeBodies: snakeBodies || false, + borders: borders || false, + deadEnds: deadEnds || false, }); } } diff --git a/src/web/grid.ts b/src/web/grid.ts index 0d4ee78..0402c74 100644 --- a/src/web/grid.ts +++ b/src/web/grid.ts @@ -1,4 +1,4 @@ -import { BTRequest } from '../types/BTData'; +import { BTRequest, BTXY } from '../types/BTData'; import snakes from "../server/snakes"; import { invertColor } from '../lib/invertColor'; import * as Color from 'color'; @@ -71,13 +71,31 @@ export function loadGrid(request: BTRequest) { } else if (request.body.you.squad && request.body.you.squad == snake.squad) { color = '#3c69e7'; } + let previousPart: BTXY; for (const [p, part] of snake.body.entries()) { const col = getCol(part.x, part.y); $('
').addClass('snake').css({ backgroundColor: color, borderColor: new Color(color).darken(0.2).hex(), borderRadius: p == 0 ? 100 : 0, - }).text(' ').appendTo(col); + }).text(p === 0 ? ' ' : getArrow(part, previousPart)).appendTo(col); + previousPart = part; } } -}; \ No newline at end of file +}; + +function getArrow(current: BTXY, previous?: BTXY) { + if (previous) { + if (current.x == previous.x - 1 && current.y == previous.y) { + return '→'; + } else if (current.x == previous.x + 1 && current.y == previous.y) { + return '←'; + } else if (current.x == previous.x && current.y == previous.y - 1) { + return '↓'; + } else if (current.x == previous.x && current.y == previous.y + 1) { + return '↑'; + } + + } + return ' '; +}