|
|
|
@ -1214,7 +1214,8 @@ class Game { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
placeOrbs(template) { |
|
|
|
|
let placer = new RadialOrbPlacer(this, template); |
|
|
|
|
// let placer = new RadialOrbPlacer(this, template);
|
|
|
|
|
let placer = new RecursiveOrbPlacer(this, template); |
|
|
|
|
return placer.place(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1960,6 +1961,78 @@ class RadialOrbPlacer extends BaseOrbPlacer { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class RecursiveOrbPlacer extends BaseOrbPlacer { |
|
|
|
|
doPlace(toPlace) { |
|
|
|
|
this.toPlace = toPlace; |
|
|
|
|
this.recDepth = 0; |
|
|
|
|
|
|
|
|
|
this.placeOne(0); |
|
|
|
|
|
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
placeOne() { |
|
|
|
|
this.recDepth++; |
|
|
|
|
if (this.recDepth > 2000) { |
|
|
|
|
throw new Error("Too many backtracks"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let symbol = this.toPlace.pop(); |
|
|
|
|
|
|
|
|
|
let candidates = [[],[],[],[],[],[],[]]; |
|
|
|
|
for (let n of this.template) { |
|
|
|
|
if (!this.board.grid[n]) { |
|
|
|
|
// is free
|
|
|
|
|
const cell = this.getCellInfo(n); |
|
|
|
|
if (cell.freeSequence >= 3) { |
|
|
|
|
candidates[cell.neighbours].push(n); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (let neighs = 6; neighs >= 0; neighs--) { |
|
|
|
|
this.rng.arrayShuffle(candidates[neighs]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (let i = 6; i >= 0; i--) { |
|
|
|
|
if (candidates[i].length) { |
|
|
|
|
for (let n of candidates[i]) { |
|
|
|
|
this.placeOrb(n, symbol); |
|
|
|
|
|
|
|
|
|
// avoid deadlocking
|
|
|
|
|
if (this.solution.length % 2 === 0) { |
|
|
|
|
// this is the second orb in a pair (solution starts with gold)
|
|
|
|
|
let prevn = this.solution[this.solution.length-1][1]; |
|
|
|
|
if (!this.isAvailable(prevn)) { |
|
|
|
|
this.trace("Avoid deadlock (this is the second of a pair)"); |
|
|
|
|
this.removeOrb(n); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.solution.push([symbol, n]); |
|
|
|
|
|
|
|
|
|
if (this.toPlace.length) { |
|
|
|
|
if (this.placeOne()) { |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
this.trace("Undo and continue"); |
|
|
|
|
this.removeOrb(n); |
|
|
|
|
this.solution.pop(); |
|
|
|
|
// and continue the iteration
|
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// give it back
|
|
|
|
|
this.toPlace.push(symbol); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Start */ |
|
|
|
|
|
|
|
|
|