-
-
Save dzaima/5376c4d2a1827e87a941c0424a0f815e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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