Skip to content

Instantly share code, notes, and snippets.

@dzaima

dzaima/SlM4.js Secret

Last active March 16, 2018 20:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dzaima/5376c4d2a1827e87a941c0424a0f815e to your computer and use it in GitHub Desktop.
Save dzaima/5376c4d2a1827e87a941c0424a0f815e to your computer and use it in GitHub Desktop.
const DEBUG = false;
const ADD = (a,b) => a + b;
var toReturn;
var me = view[4].ant;
me.me = true; // for basedOn to know
var food = me.food;
var type = me.type;
var isQueen = type == 5;
// raw directions
const UL = 0; const U = 1; const UR = 2;
const L = 3; const C = 4; const R = 5;
const DL = 6; const D = 7; const DR = 8;
// directions from the reference point
const ul = 16; const u = 17; const ur = 18;
const l = 19; const c = 20; const r = 21;
const dl = 22; const d = 23; const dr = 24;
const rp = 16;
const FOOD = {food:1};
const QUEEN = {ant:{type:5}};
function allRots (arr) {
return [arr,
[arr[2], arr[5], arr[8],
arr[1], arr[4], arr[7],
arr[0], arr[3], arr[6]],
[arr[8], arr[7], arr[6],
arr[5], arr[4], arr[3],
arr[2], arr[1], arr[0]],
[arr[6], arr[3], arr[0],
arr[7], arr[4], arr[1],
arr[8], arr[5], arr[2]]];
}
function find (what) {
return view.findIndex(c=>basedOn(c, what));
}
function findAll (what) {
return view.map((c,i)=>[c,i]).filter(c=>basedOn(c[0], what)).map(c=>c[1]);
}
function findRel (what) {
return ref(find(what));
}
function findAllRel (what) {
return findAll(what).map(c=>ref(c));
}
function found (what) {
return find(what) != -1;
}
function get (dir) {
if (Array.isArray(dir)) return dir.map(c=>get(c));
return view[raw(dir)];
}
function deq (a, b) {
return a==b || raw(a)==raw(b);
}
// returns a random number from 0 to 4, based on the rotation. Will always have a possibility of being 0
function random4 () {
var scores = allRots(view.map(c=>c.color)).map((c) => {
let cscore = 0;
c.forEach((c) => {
cscore*= 8;
cscore+= c-1;
});
return cscore;
});
var bestscore = -1, bestindex = 1;
scores.forEach((score, index) => {
if (score > bestscore) {
bestscore = score;
bestindex = index;
}
})
return bestindex;
}
function rotate (what, times) {
for (var i = 0; i < times; i++) what = [2,5,8,1,4,7,0,3,6][what];
return what;
}
function raw(dir) {
if (dir&rp) return rotate(dir&~rp, Pattern.rot);
return dir;
}
function ref(dir) {
if (dir == -1) return -1;
if (dir&rp) return dir;
return rotate(dir, 4-Pattern.rot)|rp;
}
function move(dir) {
if (Array.isArray(dir)) return dir.some(c=>move(c));
dir = raw(dir);
return result({cell:dir});
}
function color(dir, col) {
dir = raw(dir);
return result({cell:dir, color:Math.abs(col)});
}
function colOf(what) {
return Math.abs(Number.isInteger(what)? what : what.color);
}
function sees(c1,c2) {
c1 = raw(c1);
c2 = raw(c2);
return Math.abs(c1%3-c2%3)<2 && Math.abs(Math.floor(c1/3)-Math.floor(c2/3))<2;
}
function spawn(dir, t) {
if (Array.isArray(dir)) return dir.some(c=>spawn(c, t));
dir = raw(dir);
return result({cell:dir, type:t});
}
// repairs a single cell
function correct(dir) {
dir = raw(dir);
let col = colOf(Pattern.pt[dir]);
if (col && view[dir].color != col) {
color(dir, col);
return false;
}
return true;
}
// if pattern is repaired, returns true, otherwise fixes one cell
function repair(firstdirs) {
if (!Array.isArray(firstdirs)) firstdirs = [];
firstdirs = firstdirs.map(c=>raw(c));
//console.log("FD",firstdirs);
var found = [];
view.forEach((v, i) => {
let col = colOf(Pattern.pt[i]);
if (col && v.color != col) {
found.push(i);
}
});
if (found.length == 0) return true;
if (firstdirs.some(c=>found.includes(c))) {
let dir = firstdirs.find(c=>found.includes(c));
let col = colOf(Pattern.pt[dir]);
color(dir, col);
return false;
}
let dir = found[0];
let col = colOf(Pattern.pt[dir]);
color(dir, col);
return false;
}
function flatten (arr) {
return arr.reduce((a,b)=>a.concat(b));
}
class Pattern {
constructor(pattern, inherit) {
this.pt = pattern;
if (inherit) {
this.vp = inherit.vp;
this.hp = inherit.hp;
this.rot = inherit.rot;
} else {
this.vp = 0;
this.hp = 0;
this.rot = 0;
}
}
rotateClockwise() {
var arr = [];
for (var i = 0; i < this.pt[0].length; i++) {
var sarr = [];
for (var j = this.pt.length-1; j >= 0; j--) {
sarr.push(this.pt[j][i]);
}
arr.push(sarr);
}
//console.log(arr);
var res = new Pattern(arr, this);
res.rot = (this.rot+1) % 4;
return res;
}
select(x, y, w, h) {
var res = new Pattern(this.pt.slice(y, y+h).map(c=>c.slice(x, x+w)), this);
res.hp+= x;
res.vp+= y;
return res;
}
rots(dir) {
var pts = [];
var pt = new Pattern(this.pt, this);
for (let i = 0; i < this.lengthIn(dir); i++) {
pts.push(pt);
pt = pt.rotate(dir);
}
return pts;
}
map(fn) {
return new Pattern(this.pt.map(ln=>ln.map(fn)), this);
}
lengthIn(dir) {
if (dir == U || dir == D) return this.pt.length;
else if (this.pt.length > 0) return this.pt[0].length;
else return 0;
}
rotate(dir) { // moves the center to that direction
if (dir == R) {
var res = new Pattern(this.pt.map(c=>((h,...t)=>t.concat(h))(...c)), this);
res.hp++;
return res;
}
if (dir == L) {
var res = new Pattern(this.pt.map(a=>(a=>a.slice(-1).concat(a.slice(0,-1)))(a)), this);
res.hp++;
return res;
}
if (dir == D) {
var res = new Pattern(((h,...t)=>t.concat([h]))(...this.pt), this);
res.vp++;
return res;
}
throw "rotate unimplemented dir!";
}
setSize(xs, ys) {
var arr = [];
for (let y = 0; y < ys; y++) {
var ca = [];
for (let x = 0; x < xs; x++) {
ca.push(this.pt[y % this.pt.length][x % this.pt[0].length]);
}
arr.push(ca);
}
return new Pattern(arr, this);
}
static clear() {
Pattern.patterns = [];
}
static add(pattern, repairBeforeAction = true, action, scorer, presetRot) {
//if (!(action instanceof Function)) action=()=>{};
if (Array.isArray(pattern)) pattern = new Pattern(pattern);
pattern = pattern.setSize(3,3);
if (scorer === undefined) {
scorer = (pt) => () => {
var free = 0;
var corrects = flatten(pt.pt).map((guess, index) => guess==0? (free++,0) : basedOn(view[index], guess, true));
var correctsHard = flatten(pt.pt).map((guess, index) => guess==0? 0 : basedOn(view[index], guess));
var corrstr = correctsHard.map(c=>c?"#":" ").reduce((a,b)=>a+b);
var score = corrects.reduce(ADD)*9 / (9-free);
if (/(...)?######.*|.?##.##.##/.test(corrstr)) score+= 2;
if (!found({ant:"enemy"}) && !corrects[4]) score-= 3; // all hail the holy center cell
// console.log(pt.pt);
if (logScoring) console.log(flatten(pt.pt).map(c=>c.ant? "A"+c.ant.type : c));
if (logScoring) console.log("scored", score, "free", free, "corr", corrects.map(c=>+c));
return score;
}
}
var cpt = pattern.setSize(3,3);
var orig = cpt.pt;
for (let i = 0; i < 4; i++) {
cpt = cpt.rotateClockwise();
if (!presetRot || presetRot == cpt.rot) {
cpt.repairBeforeAction = repairBeforeAction;
cpt.action = action;
cpt.scorer = scorer(cpt);
cpt.raw = orig;
cpt.view = allRots(view)[cpt.rot]; // TODO FLIP
Pattern.patterns.push(cpt);
}
}
}
static choose() {
var maxScore = -1e307;
var nextScore = -1e308;
var maxPt;
Pattern.patterns.forEach((c) => {
var score = c.scorer();
if (score >= maxScore) {
nextScore = maxScore;
maxScore = score;
maxPt = c;
}
});
var free = 0;
var corrects = flatten(maxPt.pt).map((guess, index) => guess==0? (free++,1) : basedOn(view[index], guess));
Pattern.hardcorr = flatten(maxPt.pt).map((guess, index) => colOf(guess)<2? 0 : basedOn(view[index], guess)).reduce(ADD);
Pattern.corr = corrects.reduce(ADD);
Pattern.incorr = 9-Pattern.corr;
Pattern.confidence = maxScore-nextScore;
Pattern.rot = maxPt.rot;
Pattern.action = maxPt.repairBeforeAction? () => { if (repair(maxPt.repairBeforeAction) && maxPt.action) maxPt. action(); } : maxPt.action;
Pattern.pt = flatten(maxPt.pt);
Pattern.hp = maxPt.hp;
Pattern.raw = maxPt.raw;
Pattern.view = maxPt.view;
Pattern.vp = maxPt.vp;
if (logScoring) console.log("score", maxScore, "confidence", Pattern.confidence, "corr", Pattern.corr, "fn", maxPt.action+"");
if (logScoring) console.log(maxPt.pt);
}
static ref(...args) {
Pattern.clear();
Pattern.add(...args);
Pattern.choose();
}
}
Pattern.patterns = [];
/*
is the 2nd param a subset of the 1st param.
guess can be a number (color), or an object ({color:..,ant:..,..})
guess.ant can be "worker", "queen", "enemy", "enemyworker", "enemyqueen" with obvious meanings. Note that "friend" ≠ me
guess.ant.type can be an array, ORing
*/
function basedOn(real, guess, negativesEqual) { // console.log(real,guess,new Error().stack);
if (Number.isInteger(guess)) guess = {color:guess};
if (guess.color && Math.abs(guess.color) != real.color && !(negativesEqual && guess.color<0)) return false; // 0 handles itself
if (guess.notqueen && real.ant && real.ant.friend && real.ant.type==5) return false;
if (guess.ant) {
if (!real.ant) return false;
if (guess.ant == "worker" &&!( real.ant.friend && real.ant.type!=5)) return false;
if (guess.ant == "queen" &&!( real.ant.friend && real.ant.type==5)) return false;
if (guess.ant == "enemyqueen" &&!(!real.ant.friend && real.ant.type==5)) return false;
if (guess.ant == "enemyworker" &&!(!real.ant.friend && real.ant.type!=5)) return false;
if (guess.ant == "friend" && (!real.ant.friend || real.ant.me)) return false;
if (guess.ant == "enemy" && real.ant.friend) return false;
if (Number.isInteger(guess.ant) && real.ant.type != guess.ant) return false;
if (guess.ant.friend !== undefined && guess.ant.friend !== real.ant.friend) return false;
if (guess.ant.type !== undefined && !(Array.isArray(guess.ant.type)? guess.ant.type.some(c=>c == real.ant.type) : guess.ant.type == real.ant.type)) return false;
if (guess.ant.food !== undefined && guess.ant.food !== real.ant.food) return false;
}
if (guess.food !== undefined && guess.food !== real.food) return false;
// console.log("matched");
return true;
}
function result (action) {
if (toReturn !== undefined) return 0;
var color = action.color;
var type = action.type;
var cell = action.cell;
if (!(cell >= 0 && cell <= 8)) return false;
if (color < 1 || color > 8) return false;
if (!color && ((view[cell].ant && cell != 4) || (isQueen? (view[cell].food && type) : (food && view[cell].food)))) return false; // can't walk onto ant, can't spawn on food, can't move to food with food
if (!isQueen && type) return false;
if (!isQueen && !color && food && view[cell].food) return false;
if (isQueen && !food && type) return false;
if (type && cell==C) return false;
if (color && type) return false;
toReturn = action;
return true;
}
// const COLORS = [1, 6, 2, 3, 4, 5, 8, 7];
// const WH = COLORS[0]; // 1
// const C1 = COLORS[1]; // 6/should stay green (or whatever is trail-eraser most ignorant of :p)
// const C2 = COLORS[2]; // 2/yellow
// const C3 = COLORS[3]; // 3/purple
// const C4 = COLORS[4]; // 4/cyan
// const C5 = COLORS[5]; // 5/red
// const C6 = COLORS[6]; // 8/black
// const C7 = COLORS[7]; // 7/blue
const WH = 1; // white
const C1 = 6; // should stay green (or whatever is trail-eraser most ignorant of :p)
const C2 = 7; // blue
const C3 = 3; // purple
const C4 = 2; // yellow
const C5 = 8; // black
const C6 = 5; // red
const C7 = 4; // cyan
// C1=GR,C2=BL,C4=YL,C5=DK
//-----------------------------------------------------------------------------------------------------------------------------------------------------\\
//----------------------------------------------------------------------- MAIN CODE ---------------------------------------------------------------------\\
//---------------------------------------------------------------------------------------------------------------------------------------------------------\\
// console.log();
// console.log();
// console.log(type, view.map(c=>c.ant? "A"+c.ant.type : c.color));
const logScoring = false;
const MU = 1; // miner up
const MD = 2; // miner down
const PROTECTOR = 3; // ---the two ants in by/front of the queen, preventing head-on collisions--- forget that, that's now helepr
const HELPER = 4; // LS helper & follower
const Uo = {ant:{type:MU,friend:true}};
const Do = {ant:{type:MD,friend:true}};
const Mo = {ant:{type:[MD,MU],friend:true}};
const Po = {ant:{type:PROTECTOR,friend:true}};
const Ho = {ant:{type:HELPER,friend:true}};
const STARTINGFOOD = 5;
// C6 & C7 - miners
// C1, C2, ---C3---, C4, C5 - rail
const rail = new Pattern(
[[-1,-1,C7,-1],
[-C6,-1,-1,-1],
//[C1,C2,C5,C4],
//[C5,C1,C1,C1],
//[C2,C4,C4,C2],
[C2,C4,C2,C1],
[C5,C1,C4,C4],
[C2,C5,C1,C5],
[-C6,-1,-1,-1],
[-1,-1,C7,-1]]
//[[-1,-1,C5,-1],
// [C4,-1,-1,-1],
// [C1,C1,C3,C6],
// [C6,C4,C1,C7],
// [C2,C5,C2,C1],
// [C4,-1,-1,-1],
// [-1,-1,C5,-1]]
.map((ln,i) => i==3? ln : ln.map(color=>({color,notqueen:true}))) // queen only ever is in the middle
);
const foodExt = [C7,C3,C1];
rail.hp = 0;
rail.vp = -2;
function section(ln) {
var res = rail.select(0, ln+2, 4, 3);
return Math.abs(ln)==2? [res] : res.rots(R);
}
function spawnMiners() {
if (view.filter(c=>c.ant).length>3) return false; // we have enough
var fu = found({ant:MU}); // found up
var fd = found({ant:MD}); // found down
if (fu&&!fd) return spawn(dl,MD) || spawn(ul,MU); // spawn opposite
if (fd&&!fu) return spawn(ul,MU) || spawn(dl,MD);
if (random4()<2) return spawn(ul,MU) || spawn(dl,MD); // or spawn random if found both
else return spawn(dl,MD) || spawn(ul,MU);
}
const mydir = type==MU? u : d;
const unmydir = type==MU? d : u;
const isHelper = type==HELPER;
const queenFound = found(QUEEN);
section(0).forEach(c=>
Pattern.add(c, false, ()=>{
if (isQueen) {
if (random4()==0 && findAll({ant:{}}).length > 5) move(r); // peer pressure (queen)
var helpers = findAllRel(Ho);
var helperRows = ((A,B,C,D,E,F,G,H,I)=>[[A,B,C],[D,E,F],[G,H,I]])(...Pattern.view.map(cell=>basedOn(cell,Ho)))
.map(row=>row.indexOf(true));
var helperPos = helperRows.reduce((a,b)=>Math.max(a,b)); // the furthest helper of the last of each collumn
if (helperRows[0] == -1 || helperRows[2] == -1) { // spawn helpers if they're gone
if (repair()) {
if (helperRows[0] == -1) spawn([u,ur,ul],HELPER);
else spawn([d,dr,dl],HELPER);
}
} else if (!(Pattern.incorr == 1 && food < 100 && spawnMiners())) // try spawning miners if the time is right
if (repair()) {
//if (get([u,d]).some(c=>basedOn(c,Mo)))
if (basedOn(get(ul), Do) && basedOn(get(dl), Uo)) move(r);
else if (helperPos == 2) move(r);
else if (Pattern.hp != 1) move(r);
}
} else {
if (basedOn(get(l),QUEEN)) move([u,d,mydir+1]); // oh no, I'm blocking the queen!
else if (repair()) {
move([mydir,r,unmydir]);
}
}
})
);
if (!isQueen) section(1).concat(section(-1)).forEach(cpt=>
Pattern.add(cpt, type==HELPER && (random4()!=4 || !found({ant:{}})), ()=>{
const dir = Pattern.vp==1? d : u;
const undir = Pattern.vp==1? u : d;
var queenPos = findRel(QUEEN);
if (isHelper) { // helpers helpin'
var queenDir = (queenPos-rp)%3; // 0 - before me, 1 - by me, 2 - ahead of me
if (!queenFound) move(c); // oh no, the queen is nowhere to be found :/
else if (basedOn(get(l), Ho) && !found({ant:"enemy"})) move(r); // additional helper needs space!
else if (get([r,dr,ur]).some(c=>basedOn(c, {ant:"enemy"}))) move(r); // protect!
else if (queenDir==2) move(r); // move on if queen says so
else if (queenDir==1 && Pattern.hp == 1 && basedOn(get(dir-1), Mo)) move(r); // move away for miners to have a place to stay
} else { // miners moving forward
var correctcnt = Pattern.pt.map((guess, index) => guess==0? 1 : basedOn(view[index], guess, true)).reduce(ADD);
if (dir==mydir && Pattern.hp!=0 && queenPos == undir+1 && basedOn(get(r),Ho)) { if (repair()) move(c) } // do nothing if waiting to move on for shafting
else if (queenFound && Pattern.hp == 0 && (basedOn(get(r), Ho) || basedOn(get(l), Ho))) { if (repair()) move([mydir,l,r]) } // move out
else if (!(random4()==0 && findAll({ant:{}}).length > 2 && (found({ant:"enemy"}) || correct(c)) && correctcnt > 6) || !move([r, undir, ...(queenFound? [] : [undir+1])])) // peer pressure (miners) COMBAK breaks golden rule
if (repair()) {
var queenDir = (queenPos-rp)%3; // 0 - before me, 1 - by me, 2 - ahead of me
if (queenDir != 0 && queenDir != 1) move(dir==mydir? [r, ...(queenFound? [] : [undir+1]), undir] : [undir, undir+1, undir-1, r]); // otherwise, move along (and act nicely around the queen) COMBAK breaks golden rule
}
}
})
);
if ((type==MU || type==MD) && !queenFound) {
section(2).concat(section(-2)).forEach(c=> // off the rail
Pattern.add(c, true, ()=>{
move(food? [unmydir, mydir] : [mydir, unmydir]);
}, (pt) => () => {
var free = 0;
var corrects = flatten(pt.raw).map((guess, index) => guess==0? (free++,0) : basedOn(pt.view[index], guess, true));
var score = corrects.reduce(ADD)*9 / (9-free);
var corrstr = corrects.map(c=>c?"#":" ").reduce((a,b)=>a+b);
if (!(pt.vp == -2? /......###/ : /###....../).test(corrstr)) score = 0; // the rail row must be completely intact
return score;
})
);
rail.select(0, 0, 3, 2).map(c=>c.color==-C6? C6 : c).rots(D).map(c=>c.setSize(3,3)).forEach(c=> // shafts
Pattern.add(c, false, ()=>{
var onL = get(l).food;
if (!food && (onL || get(r).food)) {
if (correct(mydir-1) && correct(mydir+1)) {
Pattern.ref(Pattern.raw.map((ln,i)=>[ln[0], foodExt[onL? i : 2-i], ln[2]]), true, ()=>{
move(onL?l:r);
}, undefined, Pattern.rot);
Pattern.action();
}
}
else if (repair()) {
move((food^(type==MU))? [u,d] : [d,u]);
}
}, (pt) => () => {
var free = 0;
var corrects = flatten(pt.raw).map((guess, index) => guess==0? (free++,0) : basedOn(pt.view[index], guess));
var score = corrects.reduce(ADD) + 1;
var corrstr = corrects.map(c=>c?"#":" ").reduce((a,b)=>a+b);
var upCorrect, downCorrect;
if (mydir==u || food) downCorrect = /...######/.test(corrstr);
if (mydir==d || food) upCorrect = /######.../.test(corrstr);
// if ((mydir==u? upCorrect : downCorrect) && food) score+= 4;
if (upCorrect) score = 9;
if (downCorrect) score = 9;
if (/#.##.##.#/.test(corrstr)) score = 9;
if (logScoring) console.log(flatten(pt.pt).map(c=>c.ant? "A"+c.ant.type : c));
if (logScoring) console.log("SCOREDD", score, "free", free, "corr", corrects.map(c=>+c), upCorrect, downCorrect);
return Math.min(score, 8.5);
})
);
if (food) {
Pattern.add([foodExt, [0,0,0], [0,0,0]], false, ()=>move(u), (pt) => () => {
var corrects = flatten(pt.pt).map((guess, index) => basedOn(view[index], guess, true));
if (logScoring) console.log("BAK",corrects,pt.pt,view);
return corrects.indexOf(false) == -1? 9 : 0;
});
}
}
Pattern.choose();
var notFound = false;
if (Pattern.confidence < 0.1 || (Pattern.corr < 4 && Pattern.score < 5)) notFound = true;
if (notFound) Pattern.action = ()=>{
if(!queenFound && found(FOOD)) move(find(FOOD));
// if(queenFound) { commented because messes with startup :|
// ref([[QUEEN,QUEEN,0],[0,0,0],[0,0,0]]);
// move([u,ul,l,ur,r,d,dl,dr]);
// }
if (found({ant:"enemy"})) {
//var mycol = [C3,C6,C7,WH][random4()];
var enemyPos = find({ant:"enemy"});
if (view[4].color != C3) color(C, C3);
else {
switch(view[enemyPos].color) {
case C3: color(enemyPos, WH); break;
case WH: color(enemyPos, C3); break;
default: color(enemyPos, C3);
}
}
//var enemycol = [C3,C6][random4()];
}
}; // TODO not move if all cells seen by queen are white & unshit in general
// if (!isQueen || ((food >= 1 || Pattern.corr >= 6))) Pattern.action();
// else {
if (type == MU || type == MD) Pattern.action(); // miners always pattern
if (type == HELPER && (Pattern.hardcorr>=4 || find(QUEEN).food>STARTINGFOOD)) Pattern.action(); // helper patterns when corr>4
else if (isQueen && (Pattern.corr>=6 || food>STARTINGFOOD+4)) Pattern.action(); // queen patterns
else if (isQueen && food >= STARTINGFOOD && findAll({ant:"friend"}).length < 2) { // queen start railprep
Pattern.ref([[1,1,{ant:Ho.ant,color:WH}],
[1,1,1],
[1,1,1]], true, ()=>get(ur).ant? spawn(u,MU) : 0);
Pattern.action();
}
else if (isQueen && view.filter(c=>c.ant && c.ant.friend).length >= 3 && !found({ant:"enemy"})) { // queen continue railprep
Pattern.ref([[Uo,Uo,Ho],
[-1,-1,-1],
[Do,Do,Ho]]);
if (!(spawn(d,MD) || spawn(dr,HELPER) || spawn(dl,MD) || spawn(ul,MU))) { // spawn the remaining workers
Pattern.ref(rail.select(0,2,3,3), [c,dr,ur,r,u,d,l,ul,dl], undefined, undefined, Pattern.rot); // and color the rail!
Pattern.action();
}
} else if ((isQueen && found(Ho)) || type==HELPER) { // LS or railprep for helper
const FRIEND = {ant:"friend"};
var other = find(isQueen? Ho : QUEEN);
var orth = other%2;
if (!isQueen && (other == -1 || view.filter(c=>basedOn(c,FRIEND)).length > 1 || view[other].ant.food >= STARTINGFOOD)) { // prepeare for rail
if (orth) {
Pattern.ref([[0,QUEEN,0],
[0,0,0],
[0,0,0]], false, ()=>move(r));
Pattern.action();
}
} else { // LS
if (orth && found(FOOD)) { // grab easy food
var fp = find(FOOD);
if (sees(other, fp)) move(fp);
else {
Pattern.ref([[0,FRIEND,0],
[0,0,0],
[0,0,0]], false);
move(l);
}
}
Pattern.clear();
Pattern.add([[0,FRIEND,0],
[0,0,0],
[0,0,0]], false, ()=>isQueen? move(ul) : move(ur));
Pattern.add([[0,0,FRIEND],
[0,0,0],
[0,0,0]], false, ()=>move(u));
Pattern.choose();
Pattern.action();
}
} else if (food == 0 && isQueen) { // diagonal search
if (found(FOOD)) {
move(find(FOOD));
} else {
Pattern.clear();
Pattern.add([[WH,WH,WH],
[WH,C1,WH],
[C1,WH,WH]], false, ()=>move(ur));
Pattern.add([[WH,WH,WH],
[WH,WH,WH],
[C1,WH,WH]], false, ()=>color(C, C1));
Pattern.add([[WH,WH,WH],
[WH,WH,WH],
[WH,WH,WH]], false, ()=>color(DL, C1));
Pattern.choose();
if (Pattern.corr == 9) Pattern.action();
else move(random4()? DL : D);
}
} else spawn(U,HELPER);
// console.log(type, view.map(c=>c.ant? "A"+c.ant.type : c.color));
// console.log(rail);
if (toReturn) return toReturn;
else return {cell:4};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment