Guest User

Untitled

a guest
Apr 27th, 2018
21
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  //  FORMIC FRAMEWORK  //
  2. // Version 6.1.10     //
  3. const WHITE = 1;
  4. const QUEEN = 5;
  5. const CENTER = 4;
  6. const HERE = view[CENTER];
  7. const ME = HERE.ant;
  8. const ORTHOGONALS = [1, 3, 5, 7];
  9. const DIAGONALS = [0, 2, 6, 8];
  10. const DIAGONALS_ORTHOGONALS = [0, 2, 6, 8, 1, 3, 5, 7];
  11. const DIRECTIONS = [0, 1, 2, 3, 5, 6, 7, 8];
  12. const CLOCKWISE_DIRECTIONS = [0, 1, 2, 5, 8, 7, 6, 3];
  13. const CELLS = [0, 1, 2, 3, 4, 5, 6, 7, 8];
  14. const ROTATIONS = [
  15.   [0, 1, 2,
  16.    3, 4, 5,
  17.    6, 7, 8],
  18.  
  19.   [6, 3, 0,
  20.    7, 4, 1,
  21.    8, 5, 2],
  22.  
  23.   [8, 7, 6,
  24.    5, 4, 3,
  25.    2, 1, 0],
  26.  
  27.   [2, 5, 8,
  28.    1, 4, 7,
  29.    0, 3, 6]
  30. ];
  31. const NEIGHBORS = [
  32.   [1, 4, 3],
  33.   [2, 5, 4, 3, 0],
  34.   [5, 4, 1],
  35.   [0, 1, 4, 7, 6],
  36.   [0, 1, 2, 5, 8, 7, 6, 3],
  37.   [8, 7, 4, 1, 2],
  38.   [3, 4, 7],
  39.   [6, 3, 4, 5, 8],
  40.   [7, 4, 5]
  41. ];
  42. const HORIZONTAL_FLIP = [2, 1, 0, 5, 4, 3, 8, 7, 6];
  43. const VERTICAL_FLIP = [6, 7, 8, 3, 4, 5, 0, 1, 2];
  44.  
  45. const DEBUG_MODE = true;
  46. function dump() {
  47.   if (DEBUG_MODE) {
  48.     throw "dump() not implemented";
  49.   }
  50. }
  51. function log(...args) {
  52.   if (DEBUG_MODE) {
  53.     console.log(...args);
  54.   }
  55. }
  56. function error(...args) {
  57.   log("Transformed view state:", view);
  58.   log(...args);
  59.   throw "A critical error has occurred!";
  60. }
  61.  
  62. function createArray(func, length) {
  63.   const arr = [];
  64.   for (let i = 0; i < length; i++) {
  65.     arr.push(func(i, arr));
  66.   }
  67.   return arr;
  68. }
  69.  
  70. class Test {
  71.   run(cell) {
  72.     error("No run method defined for this instance of Test:", this);
  73.   }
  74.   find(cells = CELLS) {
  75.     return cells.find((c) => this.run(c));
  76.   }
  77.   findIndex(cells = CELLS) {
  78.     return cells.findIndex((c) => this.run(c));
  79.   }
  80.   filter(cells = CELLS) {
  81.     return cells.filter((c) => this.run(c));
  82.   }
  83.   every(cells = CELLS) {
  84.     return cells.every((c) => this.run(c));
  85.   }
  86.   some(cells = CELLS) {
  87.     return cells.some((c) => this.run(c));
  88.   }
  89.   count(cells = CELLS) {
  90.     return this.filter(cells).length;
  91.   }
  92.   invert() {
  93.     return new InverseTest(this);
  94.   }
  95.   and(test) {
  96.     return new EveryTest(this, test);
  97.   }
  98.   or(test) {
  99.     return new SomeTest(this, test);
  100.   }
  101. }
  102.  
  103. class InverseTest extends Test {
  104.   constructor(test) {
  105.     super();
  106.     this.test = test;
  107.   }
  108.   run(cell) {
  109.     return !this.test.run(cell);
  110.   }
  111.   invert() {
  112.     return this.test;
  113.   }
  114. }
  115.  
  116. class CombinedTest extends Test {
  117.   constructor(...tests) {
  118.     super();
  119.     this.tests = tests;
  120.   }
  121.   append(test) {
  122.     this.tests.push(test);
  123.     return this;
  124.   }
  125. }
  126. class EveryTest extends CombinedTest {
  127.   run(cell) {
  128.     return this.tests.every((test) => test.run(cell));
  129.   }
  130.   and(test) {
  131.     return this.append(test);
  132.   }
  133. }
  134. class SomeTest extends CombinedTest {
  135.   run(cell) {
  136.     return this.tests.some((test) => test.run(cell));
  137.   }
  138.   or(test) {
  139.     return this.append(test);
  140.   }
  141. }
  142.  
  143. class ColorTest extends Test {
  144.   constructor(color) {
  145.     super();
  146.     this.color = color;
  147.   }
  148.   run(cell) {
  149.     return view[cell].color === this.color;
  150.   }
  151. }
  152. class ColorBandTest extends SomeTest {
  153.   constructor(colorBand) {
  154.     super(...colorBand.map((color) => new ColorTest(color)));
  155.   }
  156. }
  157.  
  158. class FoodTest extends Test {
  159.   constructor(hasFood = true) {
  160.     super();
  161.     this.food = hasFood ? 1 : 0;
  162.   }
  163.   run(cell) {
  164.     return view[cell].food === this.food;
  165.   }
  166. }
  167.  
  168. class AntTest extends Test {
  169.   constructor(friend, type, food) {
  170.     super();
  171.     this.friend = friend;
  172.     this.type = type;
  173.     this.food = food;
  174.   }
  175.   run(cell) {
  176.     const ant = view[cell].ant;
  177.     return ant !== null && (this.type === undefined || ant.type === this.type) && (this.friend === undefined || ant.friend === this.friend) && (this.food === undefined || (this.food ? ant.food > 0 : ant.food === 0));
  178.   }
  179. }
  180.  
  181. class NeighborTest extends Test {
  182.   constructor(test) {
  183.     super();
  184.     this.test = test;
  185.   }
  186.   run(cell) {
  187.     return this.test.some(NEIGHBORS[cell]);
  188.   }
  189. }
  190.  
  191. class MatchTest extends Test {
  192.   constructor(matches) {
  193.     super();
  194.     this.matches = matches;
  195.   }
  196.   run(cell) {
  197.     return this.matches[cell];
  198.   }
  199. }
  200.  
  201. class CustomTest extends Test {
  202.   constructor(func, ...args) {
  203.     super();
  204.     this.func = func;
  205.     this.args = args;
  206.   }
  207.   run(cell) {
  208.     return this.func(cell, ...this.args);
  209.   }
  210. }
  211.  
  212. class Action {
  213.   constructor(cell, test) {
  214.     this.cell = cell;
  215.     this.test = test;
  216.   }
  217.  
  218.   valid() {
  219.     return this.cell >= 0 && this.cell < 9 && (!this.test || this.test.run(this.cell));
  220.   }
  221.   attempt() {
  222.     return this.valid() ? this : null;
  223.   }
  224.   static tryAll(...actions) {
  225.     return actions.find((action) => action instanceof this && action.valid()) || null;
  226.   }
  227. }
  228. class Move extends Action {
  229.   constructor(cell, test) {
  230.     super(cell, test);
  231.   }
  232.  
  233.   valid() {
  234.     return super.valid() && view[this.cell].ant === null && (view[this.cell].food === 0 || ME.food === 0 || ME.type === QUEEN);
  235.   }
  236.   static many(cells, test) {
  237.     return cells.map((cell) => new this(cell, test));
  238.   }
  239. }
  240. class Paint extends Action {
  241.   constructor(cell, color, test) {
  242.     super(cell, test);
  243.     this.color = color;
  244.   }
  245.  
  246.   valid() {
  247.     return super.valid() && view[this.cell].color !== this.color && this.color >= 1 && this.color <= 8;
  248.   }
  249.   static many(cells, colors, test) {
  250.     return cells.map((cell, i) => new this(cell, colors[i % colors.length], test));
  251.   }
  252. }
  253. class Spawn extends Action {
  254.   constructor(cell, type, test) {
  255.     super(cell, test);
  256.     this.type = type;
  257.   }
  258.  
  259.   valid() {
  260.     return super.valid() && view[this.cell].ant === null && view[this.cell].food === 0 && ME.food > 0 && ME.type === QUEEN && this.type >= 1 && this.type <= 4;
  261.   }
  262.   static many(cells, type, test) {
  263.     return cells.map((cell, i) => new this(cell, type, test));
  264.   }
  265. }
  266. class NOP extends Action {
  267.   constructor() {
  268.     super(CENTER);
  269.   }
  270.  
  271.   valid() {
  272.     return true;
  273.   }
  274. }
  275.  
  276. class Context {
  277.   apply(func, ...args) {
  278.     const hiddenView = view;
  279.     if (this.viewTranslator) {
  280.       view = this.viewTranslator(hiddenView);
  281.     }
  282.    
  283.     let output = func(...args);
  284.     if (output instanceof Action && this.outputTranslator) {
  285.       this.outputTranslator(output);
  286.     }
  287.    
  288.     view = hiddenView;
  289.     return output;
  290.   }
  291. }
  292.  
  293. class TranslationContext extends Context {
  294.   constructor(translationArray) {
  295.     super();
  296.     this.translationArray = translationArray;
  297.   }
  298.  
  299.   viewTranslator(oldView) {
  300.     const newView = [];
  301.     for (let i = 0; i < 9; i++) {
  302.       newView.push(oldView[this.translationArray[i]]);
  303.     }
  304.     return newView;
  305.   }
  306.  
  307.   outputTranslator(out) {
  308.     out.cell = this.translationArray[out.cell];
  309.   }
  310. }
  311. class RotationContext extends TranslationContext {
  312.   constructor(orientation) {
  313.     super(ROTATIONS[orientation]);
  314.     this.orientation = orientation;
  315.   }
  316. }
  317. class OffsetContext extends TranslationContext {
  318.   constructor(centerCell) {
  319.     throw "OffsetContext not implemented";
  320.   }
  321. }
  322. class HorizontalReflectionContext extends TranslationContext {
  323.   constructor() {
  324.     super(HORIZONTAL_FLIP);
  325.   }
  326. }
  327. class VerticalReflectionContext extends TranslationContext {
  328.   constructor() {
  329.     super(VERTICAL_FLIP);
  330.   }
  331. }
  332.  
  333. class ColorMapContext extends Context {
  334.   constructor(map, unmap) {
  335.     super();
  336.     this.map = map;
  337.     this.unmap = unmap;
  338.   }
  339.  
  340.   viewTranslator(oldView) {
  341.     return oldView.map((cell) => ({color: this.map[cell.color - 1], food: cell.food, ant: cell.ant}));
  342.   }
  343.  
  344.   outputTranslator(out) {
  345.     out.color = this.unmap[out.color - 1];
  346.   }
  347. }
  348.  
  349. class XY {
  350.   constructor(x = 0, y = 0) {
  351.     this.x = x;
  352.     this.y = y;
  353.   }
  354.  
  355.   static fromTuples(...xyTuples) {
  356.     return xyTuples.map((xy) => new this(xy[0], xy[1]));
  357.   }
  358. }
  359.  
  360. class WrapProperties {
  361.   constructor(horizontal, vertical, size, wrapOffsets) {
  362.     this.horizontal = !!horizontal;
  363.     this.vertical = !!vertical;
  364.     this.size = size;
  365.     this.wrapOffsets = wrapOffsets || {};
  366.   }
  367. }
  368.  
  369. class ScoredTest {
  370.   constructor(test, score = 1) {
  371.     this.test = test;
  372.     this.score = score;
  373.   }
  374.  
  375.   run(cell) {
  376.     return this.test.run(cell) ? this.score : 0;
  377.   }
  378. }
  379.  
  380. class Environment {
  381.   constructor(tests, wrapping) {
  382.     this.tests = tests.map((test) => test instanceof Test ? new ScoredTest(test) : test);
  383.     this.wrapping = wrapping;
  384.   }
  385.  
  386.   at(x, y) {
  387.     const w = this.wrapping;
  388.     while ((w.horizontal && (x < 0 || x >= w.size.x)) || (w.vertical && (y < 0 || y >= w.size.y))) {
  389.       if (w.horizontal) {
  390.         if (x < 0) {
  391.           x += w.size.x;
  392.           y += w.wrapOffsets.left || 0;
  393.         } else if (x >= w.size.x) {
  394.           x -= w.size.x;
  395.           y += w.wrapOffsets.right || 0;
  396.         }
  397.       }
  398.      
  399.       if (w.vertical) {
  400.         if (y < 0) {
  401.           y += w.size.y;
  402.           x += w.wrapOffsets.up || 0;
  403.         } else if (y >= w.size.y) {
  404.           y -= w.size.y;
  405.           x += w.wrapOffsets.down || 0;
  406.         }
  407.       }
  408.     }
  409.    
  410.     if ((!w.horizontal || (x >= 0 && x < w.size.x)) && (!w.vertical || (y >= 0 || y < w.size.y))) {
  411.       return this.tests[x + y * w.size.x];
  412.     } else {
  413.       return null;
  414.     }
  415.   }
  416.   around(x, y) {
  417.     const arr = [];
  418.     for (let oy = -1; oy <= 1; oy++) {
  419.       for (let ox = -1; ox <= 1; ox++) {
  420.         arr.push(this.at(x + ox, y + oy));
  421.       }
  422.     }
  423.     return arr;
  424.   }
  425.  
  426.   detect(...positions) {
  427.     return createArray((i) => new RotationContext(i), 4).reduce((best, context) => {
  428.       const next = context.apply(() => {
  429.         return positions.reduce((best, pos, i) => {
  430.           let score = 0;
  431.           const matches = this.around(pos.x, pos.y).map((test, i) => {
  432.             if (test && (test.test instanceof Test)) {
  433.               const result = test.run(i);
  434.               if (result) {
  435.                 score += result;
  436.                 return true;
  437.               } else {
  438.                 return false;
  439.               }
  440.             } else {
  441.               return null;
  442.             }
  443.           });
  444.           if (score > best.score) {
  445.             return {position: pos, positionIndex: i, orientation: context.orientation, environment: this, matches: matches, score: score, confidence: score - best.score};
  446.           } else {
  447.             best.confidence = Math.min(best.score - score, best.confidence);
  448.             return best;
  449.           }
  450.         }, {position: positions[0], positionIndex: 0, orientation: 0, environment: this, matches: [], score: 0, confidence: 0});
  451.       });
  452.       if (next.score > best.score) {
  453.         next.confidence = next.score - best.score;
  454.         return next;
  455.       } else {
  456.         best.confidence = Math.min(best.score - next.score, best.confidence);
  457.         return best;
  458.       }
  459.     }, {position: positions[0], positionIndex: 0, orientation: 0, environment: this, matches: [], score: 0, confidence: 0});
  460.   }
  461.  
  462.   static chooseBest(...detectionResults) {
  463.     const r = detectionResults.reduce((best, result, i) => {
  464.       if (result.score > best.score) {
  465.         result.index = i;
  466.         result.confidence = result.score - best.score;
  467.         return result;
  468.       } else {
  469.         best.confidence = Math.min(best.score - result.score, best.confidence);
  470.         return best;
  471.       }
  472.     });
  473.     r.index = r.index || 0;
  474.     return r;
  475.   }
  476. }
  477.  
  478. class ColoredEnvironment extends Environment {
  479.   constructor(colors, wrapping) {
  480.     super(colors.map((color) => new ColorTest(color)), wrapping);
  481.   }
  482.  
  483.   getPainter(detectionResult) {
  484.     return new (class Painter {
  485.       constructor(loc) {
  486.         this.pos = loc.position;
  487.         this.matches = loc.matches;
  488.         this.colors = loc.environment.around(this.pos.x, this.pos.y).map((test) => test && test.test instanceof ColorTest ? test.test.color : null);
  489.         this.test = new MatchTest(loc.matches).invert();
  490.         this.orient = loc.orientation;
  491.       }
  492.      
  493.       paint(...cells) {
  494.         return cells.map((cell) => new Paint(cell, this.colors[cell], this.test));
  495.       }
  496.       cleanup(eraseColor, eraseTargets, ...cells) {
  497.         const eraseQual = this.test.and(new ColorBandTest(eraseTargets));
  498.         return cells.map((cell) => new Paint(cell, eraseColor, eraseQual));
  499.       }
  500.     })(detectionResult);
  501.   }
  502. }
  503.  
  504. // HIGH-LEVEL LOGIC STARTS HERE //
  505. const COLOR_BAND = [4, 7, 3, 2, 8];
  506.  
  507. const PARTNER = 2;
  508. const WORKER = 1;
  509.  
  510. const START_FOOD = 6;
  511. const MIN_CONFIDENCE = 2;
  512.  
  513. const PATTERN = new ColoredEnvironment(COLOR_BAND, new WrapProperties(true, true, new XY(COLOR_BAND.length, 1), {up: 2, down: -2})).detect(...createArray((i) => new XY(i, 0), COLOR_BAND.length));
  514.  
  515. function shouldSpawn() {
  516.   return PATTERN.orientation === 0 && PATTERN.positionIndex % 3 === 0 && (ME.food < 50 || PATTERN.positionIndex === 0) && ME.food < 400;
  517. }
  518.  
  519. function lightspeed() {
  520.   // TODO: Do a 180 when 3 workers are in front of us
  521.   function logicOrthogonal(frontC, sideC, backC, backCells, moveCells) {
  522.     const a = [frontC, sideC, backC, backCells, moveCells];
  523.     const f = new FoodTest;
  524.     return Action.tryAll(
  525.       ...Move.many([frontC, sideC], f),
  526.       f.some(backCells) ? new Move(backC) : null,
  527.       ...Move.many(moveCells),
  528.       new NOP
  529.     );
  530.   }
  531.   function logicDiagonal(adjacentC) {
  532.     return Action.tryAll(...Move.many(adjacentC), new NOP);
  533.   }
  534.   function logic(partnerTest, partnerOrthC, partnerDiagC, frontC, sideC, backC, backCells, moveCells, adjacentC) {
  535.     function detectEnv(c) {
  536.       return new Environment(createArray((i) => i === c ? partnerTest : undefined, 9), new WrapProperties(false, false, new XY(3, 3), null)).detect(new XY(1, 1));
  537.     }
  538.     const orth = detectEnv(partnerOrthC);
  539.     const diag = detectEnv(partnerDiagC);
  540.     return orth.score === 1 ? new RotationContext(orth.orientation).apply(() => logicOrthogonal(frontC, sideC, backC, backCells, moveCells)) :
  541.       diag.score === 1 ? new RotationContext(diag.orientation).apply(() => logicDiagonal(adjacentC)) :
  542.       error("How did we get here?");
  543.   }
  544.  
  545.   if (ME.type === QUEEN) {
  546.     const partner = new AntTest(true, PARTNER);
  547.     if (partner.some(DIRECTIONS)) {
  548.       return logic(partner, 5, 8, 2, 1, 7, [0, 3, 6, 7], [2, 7, 1, 8], [5, 7]);
  549.     } else {
  550.       const COLOR = 5;
  551.       const bgTest = new ColorTest(WHITE);
  552.       if (bgTest.run(CENTER)) {
  553.         return new Paint(CENTER, COLOR).attempt() || error("Something went terribly wrong while painting own cell");
  554.       }
  555.      
  556.       const food = new FoodTest().find(DIRECTIONS);
  557.       if (food !== undefined) {
  558.         return new Move(food);
  559.       }
  560.      
  561.       const det = new ColoredEnvironment([
  562.         WHITE, WHITE, WHITE,
  563.         WHITE, undefined, undefined,
  564.         WHITE, undefined, COLOR
  565.       ], new WrapProperties(false, false, new XY(3, 3))).detect(new XY(1, 1));
  566.       return (ME.food > 0 ? Action.tryAll(...Spawn.many(ORTHOGONALS, PARTNER)) : null) ||
  567.         (det.score === 6 ? new RotationContext(det.orientation).apply(() => Action.tryAll(...Move.many([0, 2, 6, 1, 3, 5, 7, 8]))) : null) ||
  568.         Action.tryAll(...Move.many(DIAGONALS_ORTHOGONALS), new NOP);
  569.     }
  570.   } else {
  571.     return logic(new AntTest(true, QUEEN), 1, 0, 2, 5, 3, [8, 7, 6, 3], [2, 3, 5, 0], [1, 3]);
  572.   }
  573. }
  574.  
  575. function queen() {
  576.   if (PATTERN.confidence < MIN_CONFIDENCE && ME.food < START_FOOD) return lightspeed();
  577.   return new RotationContext(PATTERN.orientation).apply(() => {
  578.     const partnerCell = new AntTest(true, PARTNER).find(DIRECTIONS);
  579.     const p = PATTERN.environment.getPainter(PATTERN);
  580.     const e = new AntTest(false);
  581.     const enemy = e.some(DIRECTIONS);
  582.     return Action.tryAll(
  583.       ...!PATTERN.matches[8] ? [
  584.         ...!enemy ? [...p.paint(6, 7, 3, 4, 5, 0, 1, 2), ...shouldSpawn() ? Spawn.many([0, 2], WORKER) : []] : [],
  585.         ...partnerCell === 1 ? Move.many(e.run(5) ? [0, 2] : [5, 2]) :
  586.           partnerCell === 0 ? Move.many(e.run(1) ? [3] : e.run(2) ? [1, 3] : []) :
  587.           []
  588.       ] : [
  589.         ...!enemy ? p.paint(8, 7, 6, 5, 4, 3, 2, 1, 0) : [],
  590.         ...Move.many(partnerCell === 1 ? [2, 0] : partnerCell === 0 ? [1, 3] : [])
  591.       ],
  592.       new NOP
  593.     )
  594.   });
  595. }
  596. function partner() {
  597.   const queenTest = new AntTest(true, QUEEN)
  598.   const queenCell = queenTest.find(DIRECTIONS);
  599.   if (queenCell === undefined) {
  600.     return new NOP; // TODO: What do we do if we've lost our queen?
  601.   }
  602.   if (PATTERN.confidence < MIN_CONFIDENCE && view[queenCell].ant.food < START_FOOD) return lightspeed();
  603.   return PATTERN.confidence >= MIN_CONFIDENCE ? new RotationContext(PATTERN.orientation).apply(() => {
  604.     const queenCell = queenTest.find(DIRECTIONS);
  605.     const e = new AntTest(false);
  606.     const enemy = e.some(DIRECTIONS);
  607.     return Action.tryAll(
  608.       ...!enemy ? PATTERN.environment.getPainter(PATTERN).paint(...CELLS) : [],
  609.       ...Move.many([
  610.         [1],
  611.         [0, 2],
  612.         [1],
  613.         [0, 1],
  614.         [], // Queen can't be on cell 4 - I'm here, after all!
  615.         [2, 1],
  616.         [3],
  617.         [],
  618.         [5]
  619.       ][queenCell]),
  620.       new NOP
  621.     )
  622.   }) : new NOP;
  623. }
  624. function worker() {
  625.   const m = new MatchTest(PATTERN.matches);
  626.   const n = m.invert();
  627.   const u = new AntTest(true, WORKER, false);
  628.   const l = new AntTest(true, WORKER, true);
  629.   const q = new AntTest(true, QUEEN);
  630.   const pt = new AntTest(true, PARTNER);
  631.   const p = PATTERN.environment.getPainter(PATTERN);
  632.   return new RotationContext(PATTERN.orientation).apply(() => { // TODO: Unique (random?) behavior when confidence low
  633.     if (ME.food === 0) {
  634.       const f = new FoodTest();
  635.       const count = n.count([6, 7, 8]);
  636.       return Action.tryAll(
  637.         ...p.paint(4, 0, 1, 2),
  638.         //...p.cleanup(WHITE, COLOR_BAND, ...CELLS),
  639.         ...((food) => food !== undefined ? [...p.paint(...NEIGHBORS[food], food), new Move(food)] : [])(f.find(DIRECTIONS)),
  640.         ...q.or(pt).some(DIRECTIONS) || u.some([6, 7, 8, 5, 2]) ? Move.many([0, 1, 3], m) : [],
  641.         ...count > 1 ? p.paint(...[6, 7, 8]) : [],
  642.         ...count === 1 ? [...p.paint(...[3, 5]), ...Move.many([7, 6, 3, 8], m)] : [],
  643.         /*n.run(6) ? new Move(3, m) : null,
  644.         ...n.run(7) ? Move.many([6, 3], m) : [],
  645.         n.run(8) ? new Move(7, m) : null,*/
  646.         n.run(5) ? new Move(5) : null,
  647.         ...Move.many([2, 1, 0, 3], m),
  648.         new NOP
  649.         /*
  650.         ...(PATTERN.confidence >= 2 ? [...(PATTERN.score < 8 || new AntTest(false).some(DIRECTIONS) ? p.paint(4, 3, 0, 1, 2, 5) : []), ...p.cleanup(WHITE, COLOR_BAND, ...CELLS)] : []),
  651.         ...((food) => food !== undefined ? [...p.paint(...NEIGHBORS[food]), new Move(food)] : [])(f.find(DIRECTIONS)), ...(
  652.           w ? Move.many([1, 0, 2]) :
  653.           m.some([4, 3]) ? p.paint(4, 3) :
  654.           m.some([0, 1, 2]) ? Move.many([1, 5]) :
  655.           m.run(6) ? [new Move(3)] :
  656.           m.run(7) ? Move.many([6, 3]) :
  657.           m.run(8) ? [new Move(7)] :
  658.           m.run(5) ? Move.many([5, 7]) :
  659.           Move.many([2, 1, 5])
  660.         )
  661.         new NOP*/
  662.       );
  663.     } else {
  664.       return Action.tryAll(
  665.         //...Move.many(new AntTest(true, WORKER).some([2, 5, 8, 7]) || PATTERN.score < 9 ? [8, 7, 6, 3] : [5, 8, 2], m.invert()),
  666.         ...((test) => createArray((i) => new Move(CLOCKWISE_DIRECTIONS[(6 - i) % 8], test), 5))(new CustomTest((cell, moveTest, blockTest) => {
  667.           const i = CLOCKWISE_DIRECTIONS.findIndex((c) => c === cell);
  668.           return moveTest.run(CLOCKWISE_DIRECTIONS[i]) && blockTest.run(CLOCKWISE_DIRECTIONS[((i - 1) + 8) % 8]);
  669.         }, m, n.or(new AntTest().and(l.invert())))),
  670.         ...Move.many([2, 5, 1, 8], m),
  671.         //...Move.many([...(PATTERN.score === 9 && !new AntTest(true, WORKER).some(DIRECTIONS) ? [2] : []), 5, 8, 7, 6, 3], m),
  672.         new NOP
  673.       );
  674.     }
  675.   });
  676. }
  677.  
  678. switch (ME.type) {
  679.   case QUEEN: {
  680.     return queen();
  681.   }
  682.   case PARTNER: {
  683.     return partner();
  684.   }
  685.   case WORKER: {
  686.     return worker();
  687.   }
  688. }
Advertisement
Add Comment
Please, Sign In to add comment