Skip to content

Instantly share code, notes, and snippets.

@dzaima

dzaima/.js Secret

Created January 31, 2018 19:08
Show Gist options
  • Save dzaima/3b0b3650faf9568202ad9b57d60ab4fe to your computer and use it in GitHub Desktop.
Save dzaima/3b0b3650faf9568202ad9b57d60ab4fe to your computer and use it in GitHub Desktop.
const DEBUG = false;
//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;
//binary directions
const bUL = 3; const bU = 1; const bUR = 5;
const bL = 2; const bC = 0; const bR = 4;
const bDL = 10; const bD = 8; const bDR = 12;
const rp = 16;
const NOP = {cell:C};
var toReturn = undefined;
const me = view[C].ant;
const type = me.type;
const food = me.food;
const isQueen = type == 5;
const allvs = allRots(view);
const ixs = [0,1,2,3,4,5,6,7,8];
const cols = ixs.map(a=>view[a].color);
const allcs = allRots(cols);
// color -1 is ignore
const WH = 1;
const C1 = 6; // should stay green (or whatever is trail-eraser most ignorant of :p)
const C2 = 2; // yellow
const C3 = 3; // purple
const C4 = 4; // cyan
const C5 = 5; // red
const C6 = 8; // black
const C7 = 7; // blue
const TRAIL = C1;
const SETTINGUP = WH;
const DONE = C5;
const H1 = 1;
const H2 = 2;
const MINER = 3;
const QUEENOBJ = {ant:{friend:true,type:5}};
const defRail = [[C1,C7,C3],
[C1,C6,C4],
[C7,C1,C3]];
defRail.vp = 0;
defRail.hp = 0;
const railParts = translates(defRail, R);
const TRlambda = (side) => (rp, ctr) => translatePt(rp, side)
const rail = {or:
[
...railParts,
...isQueen?[]:(railParts.map(TRlambda(U))),
...isQueen?[]:(railParts.map(TRlambda(D)))
].map(c => limitSize(c, 3, 3))
};
var foods;
var ref;
reference(rail);
// CODE
if (isQueen) {
var h1found = 1+find({ant:{type:H1}});
var h2found = 1+find({ant:{type:H2}});
if (!h2found && !h1found) {
if (food > 0) {
spawn(DL,H1);
} else {
diagonalSearch(C1);
}
} else if (h1found && !h2found) {
if (food <= 8) {
move(rotate1CW(h1found-1));
} else {
if (repair()) {
spawn(l, H2);
}
}
} else if (h1found && h2found) {
spawn(random4(), MINER)
}
} else if (type == H1) {
if (find({ant:{type:H1}}) !== 1) {
move(rotate1CCW(find({ant:{type:5}})));
}
} else if (type == H2) {
move(c);
} else if (type == MINER) {
move(U); // lazy
}
// END CODE
if (!toReturn) toReturn = NOP;
return toReturn;
//---------------------------------helper functions below---------------------------------
function diagonalSearch (cl) {
var colors = view.map(c=>c.color === cl);
if (!colors.includes(true)) return color(UL, cl);
const nc = [WH,C1,C2,C3,C4,C5,C6,C7].filter(c => c !== cl);
if (exactReference([[cl,nc,nc],
[nc,cl,nc],
[nc,nc,nc]])) return move(dr);
if (exactReference([[cl,nc,nc],
[nc,nc,nc],
[nc,nc,nc]])) return color(C, cl);
move(random4()? U : UL);
}
function generateFoods (useRef) {
if (!foods || useRef)
foods = ixs.map(a=>view[a].food);
if (useRef) {
foods = allRots(foods)[ref.rot];
}
}
/*
false - ??
true - gonna draw the color
1 - already colored
*/
function color (where, color) {
if (where&rp) where = rawp(where);
if (get(where).color === color) return 1;
return result({cell:where, color:color});
}
function move (where) {
if (Array.isArray(where)) {
return where.some(move /*is possible :p*/);
}
if (where&rp) where = rawp(where);
return result({cell:where});
}
function spawn (where, what) {
if (Array.isArray(where)) {
return where.some(c => spawn(c, what));
}
if (where&rp) where = rawp(where);
return result({cell:where, type:what});
}
function repair (firstdirs) {
if (ref.dist == 0) return true;
var possibilities = [];
var repaired = ref.pt.every((shouldbe, index) => {//return if every cell is correct
if (!cellsEq(ref.view[index], shouldbe)) {
let ccolor = defColor(shouldbe);
if (ccolor != ref.view[index]) {
if (!firstdirs || firstdirs.includes(index)) {
color(index|rp, ccolor);
return false;
} else possibilities.push({i:index|rp, c:ccolor});
}
}
return true;
});
if (repaired && possibilities.length > 0) {
repaired = false;
color(possibilities[0].i, possibilities[0].c);
}
return repaired;
}
function defColor (cell) {
if (typeof cell === "number") return cell;
if (Array.isArray(cell)) return cell[0];
ohno("defColor recieved bad param type ", cell);
}
function get (pos) {
if (pos&rp) return ref.view[pos^rp];
else return view[pos];
}
function gc (pos) {
return get(pos).color;
}
function exactReference (...args) {
var pt = match(...args);
if (pt.dist === 0) {
return ref = pt;
}
return false;
}
function reference (...args) {
return ref = match(...args);
}
/*
this function makes a pseudo-reference out of a value of a direction
For example, if you want a type-2 worker orthogonally to you to be able to be referenced as `r` (and of course the other directions are relative), do
define(r, find({ant:{type:2,friend:true}}))
*/
function define (whichDir, whatCellItIs) {
var rot = [0,1,2,3].find(rot => rotate(whatCellItIs, -rot) === (whichDir&~rp));
ref = {rot:rot, view:allvs[rot]};
}
function match (pattern, givendir) {
if (Array.isArray(pattern.or)) {
var bestPattern = {dist:999, correct: -1};
pattern.or.forEach((cOr) => {
let cres = match(cOr, givendir);
if (compareScores(cres.dist, cres.correct, bestPattern.dist, bestPattern.correct) > 0) {
bestPattern = cres;
}
});
return bestPattern;
}
var bestRotation = 0;
var bestDist = 999;
var bestCorrect = -1;
if (Array.isArray(pattern)) {
let opattern = pattern;
pattern = [...pattern[0],...pattern[1],...pattern[2]];
pattern.vp = opattern.vp;
pattern.hp = opattern.hp;
((givendir != undefined)? [allvs[givendir]] : allvs).forEach((cVRot, cRot) => {
if (givendir != undefined) cRot = givendir;
let dist = 0;
let correct = 0;
let fatalFail = false;
// log("match going trough", cVRot.map(c=>c.color), "at", pattern, pattern.hp);
cVRot.some((cVCell, cCell) => {//log(cCell, pattern)
let eqt = cellsEq(cVCell, pattern[cCell]);
if (eqt === 3) correct+=2;
if (eqt === 0) fatalFail = true;
if (eqt === true) correct++;
if (eqt === false) dist++;
return fatalFail;
});
//log("distance",dist, "correct",correct);
if (!fatalFail && compareScores(dist, correct, bestDist, bestCorrect)>0) {
bestDist = dist;
bestCorrect = correct;
bestRotation = cRot;
}
});
return {dist:bestDist, correct:bestCorrect, rot:bestRotation, pt:pattern, view:allvs[bestRotation], opt:opattern};
}
ohno("match failed to do anything", pattern);
}
function compareScores (ad, ac, bd, bc) {
//scoring by percentage correct
let a = ac / (ad+ac+1);
let b = bc / (bd+bc+1);
//scoring by correct overhead
///let a = ac - ad
///let b = bc - bd
return a==b? 0 : ((a>b)? 1 : -1);
}
function bitify (num) {
num&=~rp;
if (num === U) return bU;
if (num === D) return bD;
if (num === L) return bL;
if (num === R) return bR;
if (num === UL) return bUL;
if (num === DL) return bDL;
if (num === UR) return bUR;
if (num === DR) return bDR;
}
function rawp (dir) {
dir &= ~rp; // remove rp 'flag'
return rotate(dir, ref.rot);
}
function refp (dir) {
return rp | rotate(dir, -ref.rot);
}
function rotate (torot, am) {
am = am%4;
if (am < 0) am+= 4;
for (let i = 0; i < am; i++) torot = [2,5,8, 1,4,7, 0,3,6][torot];
return torot;
}
function find (obj) {
var res = view.findIndex(c => cellsEq(c, obj));
if (res === -1) return -1;
return res;
}
/*
0 - ant isn't how it should be
false - colors don't match
true - match
2 - match, but very easy to match, so shouldn't count
3 - matched ants
1st param - full object, aka anything that comes from view[x]
2nd param - the partical object you want it to equal (e.g. {ant:{friend:true}}; 6 )
*/
function cellsEq (full, required) { // log(full, new Error().stack);
if (typeof required === "number") {
if (required === -1) return 2;
if (required === full.color) return true;
return false;
} else if (Array.isArray(required)) {
let best = 0;
required.some((c) => {
let res = cellsEq(full, c);
if (res === false && best === 0) best = false;
if (res === true && best !== 3) best = true;
if (res === 3) best = 3;
});
//log("cellsEq array",required,full,best);
return best;
} else if (typeof required === "object") {
if (required.ant==false && full.ant) return 0;
if (required.ant) {
if (required.ant==="notQueen") {
if (full.ant) {
if (full.ant.type==5 && full.ant.friend) return 0;
}
} else {
if (!full.ant) return 0;
else {
// ಠ_ಠ
if (required.ant.type && required.ant.type != full.ant.type) return 0;
if (required.ant.friend && required.ant.friend != full.ant.friend) return 0;
}
}
}
if (required.color && required.color !== full.color) return false;
if (required.food !== undefined && full.food !== required.food) return false;
if (required.ant) return 3;
return true;
}
ohno("cellsEq failed to do anything", arguments);
}
function limitSize (pattern, xs, ys) {
var out = pattern.slice(0, ys).map(c => c.slice(0,xs));
out.hp = pattern.hp;
out.vp = pattern.vp;
return out;
}
function translates (pattern, direction) {
var ovp = pattern.vp;
var ohp = pattern.hp;
var out = [pattern.slice()];
out[0].vp = ovp;
out[0].hp = ohp;
//if (direction & L || direction & R) {
// out[0].hp = 0;
// out[0].vp = ohp;
//} else {
// out[0].vp = 0;
// out[0].hp = ohp;
//}
for (let i = 0; i < lengthIn(pattern, direction)-1; i++) {
pattern = rotatePt(pattern, direction);
//if (direction & L || direction & R) {
// pattern.hp = i+1;
// pattern.vp = ohp;
//} else {
// pattern.vp = i+1;
// pattern.hp = ohp;
//}
out.push(pattern);
}
return out;
}
function rotatePt (pattern, direction) {
if (direction == DR) {
return rotatePt(rotatePt(pattern, D), R);
}
if (direction == R) {
let np = pattern.map((c, ln) => c.slice(1).concat([c[0]]));
np.vp = pattern.vp;
np.hp = pattern.hp+1;
return np;
}
if (direction == D) {
let np = pattern.slice(1).concat([pattern[0]]);
np.vp = pattern.vp+1;
np.hp = pattern.hp;
return np;
}
if (direction == U) {
let np = pattern.slice();
np.splice(0,0,...np.splice(np.length-1));
np.vp = pattern.vp-1;
np.hp = pattern.hp;
return np;
}
ohno("rotatePt failed to do anything", arguments);
}
function translatePt (pattern, direction) {
if (direction == R) {
let np = pattern.map((ln) => ln.slice(1).concat(-1));
np.hp = pattern.hp+1;
np.vp = pattern.vp;
return np;
}
if (direction == L) {
let np = pattern.map((ln) => [-1].concat(ln.slice(0,-1)));
np.hp = pattern.hp-1;
np.vp = pattern.vp;
return np;
}
if (direction == U) {
let np = [new Array(pattern[0].length).fill(-1)].concat(pattern.slice(0,-1));
np.hp = pattern.hp;
np.vp = pattern.vp-1;
return np;
}
if (direction == D) {
let np = pattern.slice(1).concat([new Array(pattern[0].length).fill(-1)]);
np.hp = pattern.hp;
np.vp = pattern.vp+1;
return np;
}
ohno("translatePt failed to do anything", arguments);
}
function lengthIn (pattern, direction) {
if (direction == U || direction == D) return pattern.length;
if (direction == L || direction == R) return pattern[0].length;
ohno("lengthIn failed to do anything", arguments);
}
function ohno (msg) {
log(new Error());
log("FAILURE");
log(...arguments);
if (DEBUG) throw msg;
else toReturn = NOP;
}
function log() {
if (!DEBUG) console.log(...arguments);
}
//---------------------------------functions from Rail Miners---------------------------------
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 && ((view[cell].ant && cell != 4) || (isQueen? (view[cell].food && type) : (food && view[cell].food)))) return false;
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;
}
function resultForce() {
var temptoReturn = toReturn;
toReturn = undefined;
if (result) {
return true;
} else {
toReturn = temptoReturn;
return false;
}
}
function random4 () {
var scores = allcs.map((cs) => {
let cscore = 0;
cs.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 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 rotate1CW (c) {
return [1, 2, 5, 0, undefined, 8, 3, 6, 7][c];
}
function rotate1CCW (c) {
return [3, 0, 1, 6, undefined, 2, 7, 8, 5][c];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment