Skip to content

Instantly share code, notes, and snippets.

@dzaima

dzaima/qd.js Secret

Created January 26, 2018 14:00
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/78b65fea58fe755c937403749c89a123 to your computer and use it in GitHub Desktop.
Save dzaima/78b65fea58fe755c937403749c89a123 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;
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;
var foods;
var ref;
if (reference([
[1,1,1],
[1,1,2],
[2,1,1]
]).dist == 0) {
move(ur);
} else if (reference([
[1,1,1],
[1,1,1],
[1,2,1]
]).dist == 0) {
move(r);
} else if (reference([
[1,1,1],
[1,1,1],
[2,1,1]
]).dist == 0) {
color(r, 2);
} else color(D,2);
if (!toReturn) toReturn = NOP;
return toReturn;
//---------------------------------helper functions below---------------------------------
function generateFoods (useRef) {
if (!foods || useRef)
foods = ixs.map(a=>view[a].food);
if (useRef) {
foods = allRots(foods)[ref.rot];
}
}
function color (where, color) {
if (where&rp) {
log("coloring "+ where +" with "+ color);
where = rawp(where);
}
return result({cell:where, color:color});
}
function move (where) {
if (Array.isArray(where)) {
return where.some(move);//is possible
}
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) {
return ref.view[pos&~rp];
}
function gc (pos) {
return get(pos).color;
}
function reference (pattern, givendir) {
return ref = match(pattern, givendir);
}
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+=3;
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 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) {
for (let i = 0; i < 9; i++) {
if (cellsEq(ref.view[i], obj)) return i|rp;
}
return false;
}
/*
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.color && required.color !== full.color) return false;
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;
}
}
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 [2, 3, 6, 1, 0, 9, 4, 7, 8];
}
function rotate1CCW (c) {
return [4, 1, 2, 7, 0, 3, 8, 9, 6];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment