class Game { #colorsBank = ['black','silver','gray','maroon','red','purple','fuchsia','green','lime','olive','yellow','navy','blue','teal','aqua']; constructor(nbTubes, tubeLevel) { this.tubes = []; this.selectedTube = null; for (let i = 0; i < nbTubes; i++) { this.tubes.push(new Tube(tubeLevel)); } this.initializeColorTubes(tubeLevel); } /* The goal is to have each tube filled with its own color. Thus, there is (tubes minus one) different colors divided in (tubeLevel) layers mixed in the tubes. One tube is empty to allow movement. */ initializeColorTubes(tubeLevel) { let nbTubes = this.tubes.length - 1; let allColors = []; for (let i = 0; i < nbTubes; i++) { let coloridx = i % this.#colorsBank.length; for (let times = 0; times < tubeLevel-1; times++) { allColors.push(this.#colorsBank[coloridx]); } } for (let i = allColors.length - 1; i > 0; i--) { let j = Math.floor(Math.random() * (i + 1)); let temp = allColors[i]; allColors[i] = allColors[j]; allColors[j] = temp; } for (let index = 0; index < allColors.length; index++) { let tubeIndex = Math.floor(index/(tubeLevel-1)); this.tubes[tubeIndex].addColorLayer(allColors[index]); } } selectTube(tubeId) { let newSelectedTube = this.tubes[tubeId]; if (this.selectedTube == newSelectedTube) this.selectedTube = null; else if (this.canPourInto(this.selectedTube, newSelectedTube)){ this.pourColorInto(this.selectedTube, newSelectedTube); this.selectedTube = null; } else if (!newSelectedTube.isEmpty()) this.selectedTube = newSelectedTube; } canPourInto(sourceTube, targetTube) { return sourceTube != null && targetTube != null && sourceTube != targetTube && (targetTube.isEmpty() || sourceTube.peekTopColor() == targetTube.peekTopColor()) && !targetTube.isFull(); } pourColorInto(sourceTube, targetTube) { while (this.canPourInto(sourceTube, targetTube)) { targetTube.addColorLayer(sourceTube.removeColorLayer()); } this.checkTubeCompletion(sourceTube); this.checkTubeCompletion(targetTube); } checkTubeCompletion(tube) { if (tube.isComplete()) { let tubeIndex = this.tubes.indexOf(tube); this.tubes.splice(tubeIndex, 1); if (this.selectedTube == tube) this.selectedTube = null; this.checkGameCompletion(); } } checkGameCompletion() { if (this.tubes.length == 1 && this.tubes[0].isEmpty()) { this.tubes = []; } } }