Skip to content

Instantly share code, notes, and snippets.

@dzaima

dzaima/SlM5.js Secret

Created March 18, 2018 18:18
Show Gist options
  • Save dzaima/ef83fff370bd93da3e24a6d752754f62 to your computer and use it in GitHub Desktop.
Save dzaima/ef83fff370bd93da3e24a6d752754f62 to your computer and use it in GitHub Desktop.
const DEBUG = true;
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;
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 on (where, what) {
if (Array.isArray(where)) return where.some(c=>on(c, what));
return basedOn(get(where), what);
}
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 count (what) {
return findAll(what).length;
}
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 rcolOf(what) {
return Number.isInteger(what)? what : what.color;
}
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(t)) return t.some(c=>spawn(dir, c));
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, action, scorer, presetRot) {
if (Array.isArray(pattern)) pattern = new Pattern(pattern);
pattern = pattern.setSize(3,3);
if (scorer === undefined) {
scorer = (pt) => () => {
var free = 0;
var T; // temp
var corrects = flatten(pt.pt).map((guess, index) => rcolOf(guess)==0? (free++,null) : (T=basedOn(view[index], guess, true))===false? false : T*(rcolOf(guess)<0? (free++,0.1) : 1));
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; // 2x3 = good
if (!found({ant:"enemy"}) && !corrects[4] && corrects[4] !== null) score-= 3; // all hail the holy center cell
// console.log(pt.pt);
if (corrects.includes(0)) score = 0; // queen is in an unallowed place; abort all
if (DEBUG && score > 4) console.log("scored", score, "free", free, "corr", corrects.map(c=>+c), flatten(pt.pt).map(c=>c.ant? "A"+c.ant.type : c), pt.vp);
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.action = action;
cpt.scorer = scorer(cpt);
cpt.raw = orig;
cpt.view = allRots(view)[cpt.rot];
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.action;
Pattern.pt = flatten(maxPt.pt);
Pattern.hp = maxPt.hp;
Pattern.raw = maxPt.raw;
Pattern.view = maxPt.view;
Pattern.vp = maxPt.vp;
Pattern.score = maxScore;
if (DEBUG) console.log("score", maxScore, "confidence", Pattern.confidence, "corr", Pattern.corr, "pt", maxPt.pt);//, "fn", maxPt.action+""
}
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
true - correct!
false - not correct
0 - notqueen doesn't match (aka very bad)
*/
function basedOn(real, guess, negativesEqual) {
if (Array.isArray(real)) return real.some(c=>basedOn(c, guess, negativesEqual));
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 0;
if (guess.obstacle !== undefined) {
if (guess.obstacle && !real.ant && !(food && real.food && !isQueen)) return false;
if (!guess.obstacle && (real.ant || (food && real.food && !isQueen))) return false;
}
if (guess.badobstacle !== undefined) {
if (guess.badobstacle && !(real.ant && !real.ant.friend) && !(food && real.food && !isQueen)) return false;
if (!guess.badobstacle && ((real.ant && !real.ant.friend) || (food && real.food && !isQueen))) 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 (type < 1 || type > 4) return false;
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 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 ---------------------------------------------------------------------\\
//---------------------------------------------------------------------------------------------------------------------------------------------------------\\
if (DEBUG) {
console.log();
console.log(type, view.map(c=>c.ant? "A"+c.ant.type : c.color));
}
const Ut = 1;
const Dt = 2;
const Ht = 4;
const Uo = {ant:{type:Ut,friend:true}};
const Do = {ant:{type:Dt,friend:true}};
const Ho = {ant:{type:Ht,friend:true}};
const Mo = {ant:{type:[Ut,Dt],friend:true}};
const Fo = {food:1};
const Qo = {ant:{type:5}};
const FRIEND = {ant:"friend"};
const ENEMY = {ant:"enemy"};
const OBSTACLE = {obstacle:true};
const FREE = {obstacle:false};
const BADOBSTACLE = {badobstacle:true};
const STARTINGFOOD = 7;
const ENDINGFOOD = 100;
const isMiner = type==Ut || type==Dt;
var friendCount = count(FRIEND);
const mydir = type==Ut? u : d;
const notmydir = type==Ut? d : u;
const foodExt = [C5, C7, C2];
const rawRail = [
[-1,-1,C7,-1], // 44 04 14 24
[C6,-1,-1,-1], // 43 03 13 23
[C5,C3,C4,C1], // 42 02 12 22
[C4,C5,C2,C3], // 41 01 11 21
[C3,C2,C1,C2], // 40 00 10 20
[C1,C3,C3,C4], // 41 01 11 21
[C5,C2,C4,C1], // 42 02 12 22
[C6,-1,-1,-1], // 43 03 13 23
[-1,-1,C7,-1] // 44 04 14 24
].map((ln,row)=>(row<3||row>5)? ln.map(c=>({notqueen:true,color:c})) : ln); // queen can't be in the top & bottom 3 rows
const railPtt = new Pattern(rawRail);
railPtt.hp = 0;
railPtt.vp = -3;
function section(ln, action, scorer) {
if (ln > 0) section(-ln, action, scorer);
var sct = railPtt.select(0, ln+3, 4, 3);
var parts = Math.abs(ln)==3? [sct.setSize(3,3)] : sct.rots(R);
parts.map(c=>Pattern.add(c, action, scorer));
}
section(0, () => {
if (isQueen) { // queen
var HM = Pattern.view.map(c=>+basedOn(c, Ho));
var helperRows = [HM.slice(0,3),HM.slice(6,9)].map(c=>c.lastIndexOf(1)).map((c,i) => (c==0 && on(i==0? u : d, OBSTACLE)) ? -1 : c);
var minH = Math.min(helperRows[0],helperRows[1]);
var maxH = Math.max(helperRows[0],helperRows[1]);
if ((minH == -1 || maxH == 2) && on(r, ENEMY)) move(on(ur, ENEMY)? [d,u] : [u,d]); // initialize transporting around enemy
else if (on([u,d], ENEMY)) move(r);
else if (minH != -1 && friendCount < 3 && Pattern.corr != 9 && Pattern.hp != 1 && food < ENDINGFOOD) { // spawn miners
if (random4()%2 && helperRows[0] != 0) spawn([u,ul], Ut);
else if (helperRows[1] != 0) spawn([d,dl], Dt);
else spawn(l, [Ut,Dt]);
} else if (repair()) {
if (found(ENEMY)) move(r); // move away from the enemy
else if (minH == -1 && count(Ho) < 2) { // spawn helpers
if (helperRows[0] == -1) spawn([u,ur,ul],Ht);
else spawn([d,dr,dl],Ht);
} else if (minH != 0 && maxH == 2) {
move(r);
} else if (minH > 0 && Pattern.hp != 1) move(r);
}
} else if (isMiner) { // miners
if (repair()) {
if (on(l, Qo)) move([u,d]);
else if (on(mydir+1, OBSTACLE)) {
if (on(r, Qo)) move(mydir);
else if (on(r, OBSTACLE)) move([notmydir,notmydir+1]);
else move([r,mydir,notmydir,notmydir+1]);
} else move([mydir,r,notmydir]);
}
} else { // helper
if (repair()) { // TODO restore to queen
move(on([d,dr,dl], Ho)? [u,d] : [d,u]);
}
}
});
section(1, () => {
var dir = Pattern.vp > 0? d : u;
var notdir = Pattern.vp > 0? u : d;
// console.log(dir,mydir,Pattern.hp,Pattern.vp);
if (isQueen) {
if (repair()) {
if (on(notdir, FREE) && on(notdir+1, FREE)) move(notdir);
else move(random4()? r : [r, notdir+1]);
}
} else if (type==Ht) { // helpers
var queenRel = (findRel(Qo)-rp)%3;
if (queenRel == 1 && Pattern.hp == 1 && on(dir-1, {ant:{}})) move(r);
else if (queenRel == 2 && on(r, FREE)) move(r); // queen's moving forward
else if (repair()) {
//console.log(on([r,l], Ho),queenRel);
if (on([r,l], Ho)) move(notdir);
else if (queenRel == 0 && on(l, Qo)) move(r); // queen's moving around enemy
else if (queenRel == 1 && on(notdir+1, ENEMY)) move(r); // queen needs space to move
}
} else { // miners
if (!food && dir == mydir && on(r, Ho) && on(notmydir+1, Qo)) {
if (Pattern.hp == 0) move(mydir); // move out!
} else if (repair()) {
var queenRel = (findRel(Qo)-rp)%3;
if (queenRel == 2 && !on(r,Ho)) move(C); // stay still, queen's moving forward
if (on(l, Ho) && on(notdir-1, Qo)) move(dir-1); // I'm in front of the queen :/
else if (on(notdir, Qo)) move([l, dir, dir-1]); // don't move in front of the queen!
else if (dir != mydir) {
if (on(notdir+1, OBSTACLE)) move([...(random4()? [r] : []),notmydir, notdir+1, dir+1]);
else move(random4()? mydir : [mydir,r, notdir+1, dir+1]); // TODO
if (toReturn && toReturn.cell == (Pattern.hp == 4? dir+1 : Pattern.hp == 0? dir : -13.5) && random4()) toReturn = {cell:4};
} else if (Pattern.hp == 4) move([r, notmydir, mydir, notmydir+1]); // no ur
else if (Pattern.hp == 0) move([r, notmydir, notmydir+1, mydir+1]); // no u
else move([r, notmydir, mydir, ...(food? [mydir+1] : []), notmydir+1]);
}
}
});
if (isMiner) {
section(2, () => {
if (repair()) {
var hRel = (findRel(Ho)-rp)%3;
var dir = Pattern.vp > 0? d : u;
var notdir = Pattern.vp > 0? u : d;
if (hRel == 1) move([l, C]); // don't go past helper
else if (on(notdir+1, OBSTACLE) && !random4() && dir==mydir) move([r,notdir,notdir+1]); // if block downwards, continue moving here
else if (dir != mydir) {
move([mydir, mydir+1, mydir-1]); // TODO
}
else if (food) move([notmydir, r, notmydir+1]);
else if (Pattern.hp == 0) move(mydir);
else if (Pattern.hp == 4) move([notmydir,notmydir+1,notmydir-1]);
else move([notmydir,r,notmydir+1,notmydir-1]);
}
});
section(3, () => {
if (repair()) move(food? [notmydir, notmydir+1, notmydir-1] : [mydir,notmydir+1]);
}, (pt) => () => {
var corrects = flatten(pt.raw).map((guess, index) => basedOn(pt.view[index], guess, true));
var corrstr = corrects.map(c=>c?"#":" ").reduce((a,b)=>a+b);
var score = (pt.vp>0? /###....../ : /......###/).test(corrstr)? 20 : 0;
if (DEBUG && score > 0) console.log("scored", score, corrstr, flatten(pt.raw).map(c=>c.ant? "A"+c.ant.type : c), pt.vp);
return score;
});
if (!found(Ho)) railPtt.select(0, 0, 3, 2).rots(D).map(c=>Pattern.add(c, () => {
var fol = on(l, Fo); // fool on left
if (!food && (fol || on(r, Fo))) {
Pattern.ref(Pattern.raw.map((ln, i) => [ln[0], foodExt[fol? i : 2-i], ln[2]]), () => {
if (repair()) move(fol? l : r);
}, undefined, Pattern.rot);
Pattern.action();
} else if (repair()) {
if (food) move([notmydir, mydir]);
else move([mydir, notmydir]);
}
}, (pt) => () => {
var free = 0;
var T; // temp
var corrects = flatten(pt.raw).map((guess, index) => rcolOf(guess)==0? (free++,null) : (T=basedOn(pt.view[index], guess, true))===false? false : T*(rcolOf(guess)<0? (free++,0.1) : 1));
var score = corrects.reduce(ADD)*9 / (9-free);
var corrstr = corrects.map(c=>c?"#":" ").reduce((a,b)=>a+b);
var DCorrect = /...######/.test(corrstr);
var UCorrect = /######.../.test(corrstr);
if ((mydir==u ^ food) && DCorrect) score = 15;
else if ((mydir==d ^ food) && UCorrect) score = 15;
else if (/#.##.##.#/.test(corrstr)) score=15;
else if (UCorrect || DCorrect) score = 6;
if (corrects.includes(0)) score = 0; // queen is in an unallowed place; abort all
if (DEBUG && score > 0) console.log("scored", score, "free", free, "corr", corrects.map(c=>+c), flatten(pt.pt).map(c=>c.ant? "A"+c.ant.type : c));
return score;
}));
if (food) Pattern.add([foodExt, [0, 0, 0], [0, 0, 0]], ()=>move(u));
}
Pattern.choose();
var confident = (Pattern.confidence >= 1 && (Pattern.score > 4 || Pattern.corr >= 4)) || (Pattern.score >= 9 && Pattern.confidence > 0.05);
if (!confident) Pattern.action = () => {
if (!isQueen) {
if (!found(Qo) && found(Fo)) move(find(Fo));
}
}
if (isMiner) {
if ((Pattern.corr > 3 || Pattern.score > 3) && confident) Pattern.action();
} else if (isQueen) {
if ((Pattern.corr >= 6 || food > STARTINGFOOD+2 || friendCount>1) && confident) Pattern.action();
else if (food >= STARTINGFOOD && friendCount == 1) {
Pattern.clear();
Pattern.add([[1,{ant:Ho.ant,color:1},1],
[1,1,1],
[1,1,1]], ()=>spawn([ur,ul],Ht));
Pattern.add([[1,1,{ant:Ho.ant,color:1}],
[1,1,1],
[1,1,1]], ()=>spawn([ur,u],Ht));
Pattern.choose();
if (repair()) Pattern.action();
} else if (food == 0 && friendCount == 0) { // diagonal search
if (found(Fo)) {
move(find(Fo));
} else {
Pattern.clear();
Pattern.add([[WH,WH,WH],
[WH,C1,WH],
[C1,WH,WH]], ()=>move(ur));
Pattern.add([[WH,WH,WH],
[WH,WH,WH],
[C1,WH,WH]], ()=>color(C, C1));
Pattern.add([[WH,WH,WH],[WH,WH,WH],[WH,WH,WH]], ()=>color(DL, C1));
Pattern.choose();
if (Pattern.corr == 9) Pattern.action();
else move(random4()? [DL,UL,DR,UL] : [D,L,U,R]);
}
} else if (food == 1 && friendCount == 0) spawn([U,L,D,R,UL,DL,UR,DR], Ht);
else if (friendCount == 1) lightSpeed();
else {
Pattern.ref(railPtt.select(0,3,4,3).rotate(L).rotate(L));
repair();
}
} else if (type == Ht) {
if (Pattern.corr >= 5 || friendCount>1) Pattern.action();
else if (found(Qo)) lightSpeed();
else if (Pattern.corr >= 3 && confident) repair();
}
function lightSpeed() {
var other = find(isQueen? Ho : Qo);
var orth = other%2;
if (isQueen || (view[other].ant.food < STARTINGFOOD && count(Ho) == 1)) { // LS
if (orth && found(Fo)) { // grab easy food
var fp = find(Fo);
if (sees(other, fp)) move(fp);
else {
Pattern.ref([[0,FRIEND,0],
[0,0,0],
[0,0,0]]);
move(l);
}
}
Pattern.clear();
// Pattern.when(U,find(FRIEND), ()=>isQueen? move(ul) : move(ur)); when I'm not lazy imma make this a replacement of the below
Pattern.add([[0,FRIEND,0],
[0,0,0],
[0,0,0]], ()=>isQueen? move(ul) : move(ur));
Pattern.add([[0,0,FRIEND],
[0,0,0],
[0,0,0]], ()=>move(u));
Pattern.choose();
Pattern.action();
}
}
if (DEBUG) console.log(type, view.map(c=>c.ant? "A"+c.ant.type : c.color));
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