A Starknight hacked an old slot machine and turned it into something strange?! I heard that you win a secret message if you manage to get triple cherries, but...
Last updated
This challenge gives us a slot machine, and our goal is to make all the slots become cherries. The main logic of the program is in script.js:
let slotSymbols = [];
let m = 0; // gets initialised to 32768
let awascii32 = 'awjelyhosiumpcntbdfgr.,!{}_/;CTF';
let spinMode = 0; // either 0, 1 or 2
let spinCounts = [0,0,0]; // how much we've spun in each mode. reset by reset()
let slotIndices = [0,0,0]; // the current index of the character being displayed
let slotSpins = [0,0,0]; // depends on spinMode
let ciphertextIndex = 0; // modified by change()
fetch('static/slotsymbols.txt')
.then(response => response.text())
.then(text => {
slotSymbols = text.split(/(?:)/u);
m = slotSymbols.length;
}).then(() => {
playCoin(0);
reset();
});
function change() {
ciphertextIndex = (ciphertextIndex + 1) % 3;
reset();
}
function reset() {
if (ciphertextIndex == 0) slotIndices = [10992, 30978, 12520];
else if (ciphertextIndex == 1) slotIndices = [30983, 7390, 481];
else if (ciphertextIndex == 2) slotIndices = [25974, 26744, 9122];
spinCounts = [0,0,0];
updatePlaintextDisplay();
doSpinCleanup();
}
function spin() {
const buttons = document.querySelectorAll('.button');
buttons.forEach((b) => b.disabled = true);
spinCounts[spinMode] += 1;
updateModeDisplay();
updatePlaintextDisplay();
doSpinAnimation();
for (let columnIndex = 0; columnIndex < 3; columnIndex++) {
}
setTimeout(() => {
doSpinCleanup();
buttons.forEach((b) => b.disabled = false);
}, 1)
}
function playCoin(n){
spinMode = n;
if (n == 0) slotSpins = [ 19, 22, 19];
else if (n == 1) slotSpins = [ 32, 27, 29];
else if (n == 2) slotSpins = [347, 349, 353];
updateModeDisplay();
}
function updatePlaintextDisplay() {
let decToAwascii32 = (x) => {return awascii32.charAt(x % 32) + awascii32.charAt((x >> 5) % 32) + awascii32.charAt((x >> 10) % 32)};
document.getElementById('spinCount0').innerHTML = decToAwascii32(spinCounts[0]);
document.getElementById('spinCount1').innerHTML = decToAwascii32(spinCounts[1]);
document.getElementById('spinCount2').innerHTML = decToAwascii32(spinCounts[2]);
}
/**
*
* NOTE: Everything below this point is purely visual and not needed to solve the challenge.
*
*/
function createSymbolElement(symbol) {
const div = document.createElement('div');
div.classList.add('symbol');
div.textContent = symbol;
return div;
}
function doSpinAnimation() {
const slots = document.querySelectorAll('.slot');
slots.forEach((slot, columnIndex) => {
const symbols = slot.querySelector('.symbols');
symbols.style.transition = 'none';
symbols.style.top = '0';
symbols.replaceChildren();
for (let i = slotIndices[columnIndex]; i <= slotIndices[columnIndex] + slotSpins[columnIndex]; i++) {
symbols.appendChild(createSymbolElement(slotSymbols[i % m]))
}
symbols.offsetHeight;
symbols.style.transition = '';
const symbolHeight = symbols.querySelector('.symbol')?.clientHeight;
const offset = -(symbols.childElementCount - 1) * symbolHeight;
symbols.style.top = `${offset}px`;
});
}
function doSpinCleanup() {
const slots = document.querySelectorAll('.slot');
slots.forEach((slot, columnIndex) => {
const symbols = slot.querySelector('.symbols');
symbols.style.transition = 'none';
symbols.style.top = '0';
symbols.replaceChildren(createSymbolElement(slotSymbols[slotIndices[columnIndex]]));
symbols.offsetHeight;
symbols.style.transition = '';
});
}
function updateModeDisplay() {
document.getElementById('spinMode').innerHTML = spinMode;
}
When the script first runs, m is set to slotSymbols.length, which is the number of symbols available and is always 32768.
Initially, before spinning, the characters we are shown depends on cipherTextIndex. Its value can be 0, 1, or 2. Depending on its value, reset() gives us a different combination of initial indexes to use in slotIndices.
When we spin(), the change of indices also depends on slotSpins. slotSpins is set by the playCoin() function. We can play with either 0, 1, or 2 coins, and each gives us a different array slotSpins.
The equation determining the next indices is given by this line of code:
slotIndices[columnIndex] = (slotIndices[columnIndex] + slotSpins[columnIndex]) % m;
Upon inspecting slotsymbols.txt, we can see that the cherry is at index 0 since it is the first symbol in the file. So our objective is to make slotIndices[0] = 0, slotIndices[1] = 0 and slotIndices[2] = 0.
Let's formulate the problem. For each of the 3 cipherTextIndex values, we can spin with 0 coins i times, spin with 1 coin j times, and spin with 2 coins k times. Hence our equations are: