I’ve been working on a longer, reverse-engineering piece about Neuromancer, but couldn’t get it finished in time to post this week. In it’s place, a simple javascript implementation of the game’s code wheel.
If you’re inclined to dig into the details of the implementation, you’ll find a fairly faithful re-creation of the game’s logic – 3 bit BCD and all. Here’s a link to the source, since WordPress likes to mangle code, as reproduced below.
// Application object class
function App() {
// Window shift LUT
this.lut0 = [0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9];
// Window rank LUT
this.lut1 = [2, 5, 0, 7, 3, 1, 6, 4, 0, 7, 2, 4, 6, 1, 3, 5];
// BCD data LUT (3-bit, 6-digit, MSD has only 1 bit)
this.lut2 = [ 39889, 9133, 38839, 25052, 45749, 26196, 58580, 30601,
25260, 44664, 28260, 13310, 13304, 41983, 40698, 5114,
28243, 15472, 5654, 54494, 54783, 16599, 2507, 21277,
56979, 23681, 22615, 39146, 44323, 12716, 6487, 46143,
18634, 29386, 18641, 32153, 25443, 28682, 14840, 18103,
8960, 27208, 25555, 21430, 12984, 19449, 17103, 25390,
29334, 25495, 726, 25261, 3826, 25509, 15434, 20567,
31149, 28319, 14829, 10169, 29652, 134, 9466, 17468,
275, 2640, 3150, 1617, 127, 2895, 3655, 2114, 120, 2638,
3184, 2677, 15, 555, 2835, 1659, 3156, 735, 2240, 58,
2128, 718, 1921, 1767, 1023, 1496, 2263, 451, 3104, 2664,
3186, 1148, 475, 398, 119, 139, 330, 448, 172, 15, 347,
443, 219, 284, 192, 264, 44, 203, 67, 37, 158, 460, 20,
276, 315, 396, 442, 209, 58, 327, 469, 377, 280, 509];
// Fill in the user interface
function Populate(s, a)
{
while (s.firstChild)
{
s.removeChild(s.firstChild);
}
var i, o;
for (i = 0; i < a.length; i++)
{
o = s.appendChild(document.createElement('OPTION'));
o.appendChild(document.createTextNode(a[i]));
o.value = i;
}
}
var outer = [ 'Chatsubo', 'Cyberspace', 'Gemeinschaft', 'Crazy Edo',
'Microsofts', 'Cheap Hotel', 'Julius Deane', 'Donut World',
'Lawbot', 'database', 'Shiva', 'Freeside', 'softwarez',
'Matrix', 'Matt Shaw', 'Night City News'];
var inner = [ 'Ratz', 'Holografix', 'Larry Moe', 'PAX',
'Skill Chips', "Shin's Pawn", 'Gentleman Loser', 'Maas Biolabs',
'Justice Booth', 'Cyberdeck', 'Comlink', 'Icebreaker',
'ROM construct', 'Cowboy', 'Emperor Norton', 'Cyberjack'];
var names = [ 'Zion Cluster', 'Chiba City', 'Asano Computing', 'Hitachi Biotech',
'Cryptology', 'Space colony', 'Holy Joystick', 'Bank of Berne',
'Spacedock', 'Ono-Sendai', 'Marcus Garvey', 'Bank of Zurich',
'Compu-Judge', 'flatline', 'AI', 'Fuji Electric'];
Populate(document.getElementById('outer'), outer);
Populate(document.getElementById('inner'), inner);
Populate(document.getElementById('window'), names);
this.UpdateCode();
// Install hooks
var hook = this.MakeControllerHook();
document.getElementById('outer').onchange = hook;
document.getElementById('inner').onchange = hook;
document.getElementById('window').onchange = hook;
};
// Application object methods
App.prototype.MakeControllerHook = function () {
var o = this;
return function () { o.UpdateCode(); };
};
App.prototype.UpdateCode = function () {
var outer = document.getElementById('outer').selectedIndex;
var inner = document.getElementById('inner').selectedIndex;
var windex = document.getElementById('window').selectedIndex;
var index = ((this.lut0[windex] + outer - inner) & 0xf) + (this.lut1[windex] << 4);
var bcd = this.lut2[index];
function Decode(shift) { return String.fromCharCode(((bcd>>shift)&0x7) + 0x30); }
var s = Decode(15) + Decode(12) + Decode(9) + Decode(6) + Decode(3) + Decode(0);
var l = 3 + ((7-this.lut1[windex])>>1);
document.getElementById('code').value = s.slice(6-l);
};
// Global application object
var app = new App();