-
-
Save dzaima/78b65fea58fe755c937403749c89a123 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; | |
//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