Published
Edited
Feb 9, 2021
Importers
Insert cell
md`# Chess Programming: x88

TODO

- [ ] draw out what I'm trying to do.
- [ ] visualize the x88 table
- [ ] show what the "difference" means, something about antidiagonals & rank
- [ ] attacks w/ bits
- [ ] RAYS for obstruction


https://observablehq.com/@rreusser/binary-input

## Other resources

- [ChessProgramming.com: x88](https://www.chessprogramming.org/0x88)
- [Adam's Computer Chess Pages](http://adamsccpages.blogspot.com/p/chess-programming-resources.html) Mountain of links related to Chess Programming
`
Insert cell
md`
# Make a grid

based on: https://bl.ocks.org/cagrimmett/07f8c8daea00946b9e704e3efcbd5739
`
Insert cell
{
function gridData() {
var data = new Array();
var xpos = 1; //starting xpos and ypos at 1 so the stroke will show when we make the grid below
var ypos = 1;
var width = 50;
var height = 50;
var click = 0;

// iterate for rows
for (var row = 0; row < 10; row++) {
data.push( new Array() );

// iterate for cells/columns inside rows
for (var column = 0; column < 10; column++) {
data[row].push({
x: xpos,
y: ypos,
width: width,
height: height,
click: click
})
// increment the x position. I.e. move it over by 50 (width variable)
xpos += width;
}
// reset the x position after a row is complete
xpos = 1;
// increment the y position for the next row. Move it down 50 (height variable)
ypos += height;
}
return data;
}

var griddata = gridData();
// I like to log the data to the console for quick debugging
console.log(gridData);
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, 500]);

// var grid = d3.select("#grid")
// .append("svg")
// .attr("width","510px")
// .attr("height","510px");

var row = svg.selectAll(".row")
.data(griddata)
.enter().append("g")
.attr("class", "row");

var column = row.selectAll(".square")
.data(function(d) { return d; })
.enter().append("rect")
.attr("class","square")
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.attr("width", function(d) { return d.width; })
.attr("height", function(d) { return d.height; })
.style("fill", "#fff")
.style("stroke", "#222")
.on('click', function(d) {
d.click ++;
if ((d.click)%4 == 0 ) { d3.select(this).style("fill","#fff"); }
if ((d.click)%4 == 1 ) { d3.select(this).style("fill","#2C93E8"); }
if ((d.click)%4 == 2 ) { d3.select(this).style("fill","#F56C4E"); }
if ((d.click)%4 == 3 ) { d3.select(this).style("fill","#838690"); }
});
return svg.node()
}
Insert cell
util = {

return {
getx88,
fillx88board,
ATTACKS,
SHIFTS,
RAYS,
SQUARESx88
}
}
Insert cell
pieces = {return { PAWN: 'p', KNIGHT: 'n', BISHOP: 'b', ROOK: 'r', QUEEN: 'q', KING: 'k'} }
Insert cell
colors = {return { WHITE: 'w', BLACK: 'b' }}
Insert cell
SQUARESx88 = {return {
a8: 0, b8: 1, c8: 2, d8: 3, e8: 4, f8: 5, g8: 6, h8: 7,
a7: 16, b7: 17, c7: 18, d7: 19, e7: 20, f7: 21, g7: 22, h7: 23,
a6: 32, b6: 33, c6: 34, d6: 35, e6: 36, f6: 37, g6: 38, h6: 39,
a5: 48, b5: 49, c5: 50, d5: 51, e5: 52, f5: 53, g5: 54, h5: 55,
a4: 64, b4: 65, c4: 66, d4: 67, e4: 68, f4: 69, g4: 70, h4: 71,
a3: 80, b3: 81, c3: 82, d3: 83, e3: 84, f3: 85, g3: 86, h3: 87,
a2: 96, b2: 97, c2: 98, d2: 99, e2: 100, f2: 101, g2: 102, h2: 103,
a1: 112, b1: 113, c1: 114, d1: 115, e1: 116, f1: 117, g1: 118, h1: 119
}
}
Insert cell
Insert cell
SHIFTS = {return { p: 0, n: 1, b: 2, r: 3, q: 4, k: 5 }};
Insert cell
ATTACKS = [
20, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0,20, 0,
0,20, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0,20, 0, 0,
0, 0,20, 0, 0, 0, 0, 24, 0, 0, 0, 0,20, 0, 0, 0,
0, 0, 0,20, 0, 0, 0, 24, 0, 0, 0,20, 0, 0, 0, 0,
0, 0, 0, 0,20, 0, 0, 24, 0, 0,20, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,20, 2, 24, 2,20, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 2,53, 56, 53, 2, 0, 0, 0, 0, 0, 0,
24,24,24,24,24,24,56, 0, 56,24,24,24,24,24,24, 0,
0, 0, 0, 0, 0, 2,53, 56, 53, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,20, 2, 24, 2,20, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,20, 0, 0, 24, 0, 0,20, 0, 0, 0, 0, 0,
0, 0, 0,20, 0, 0, 0, 24, 0, 0, 0,20, 0, 0, 0, 0,
0, 0,20, 0, 0, 0, 0, 24, 0, 0, 0, 0,20, 0, 0, 0,
0,20, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0,20, 0, 0,
20, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0,20
];
Insert cell
getx88 = (sq) => {
const rank07 = 7 - (parseInt(sq[1]) - 1); // chess.js uses a bit of a different layout with a8 as 0,0
const atoi = (l) => { return l.charCodeAt(0) - 'a'.charCodeAt(0) };
const file07 = atoi(sq[0]);
const offset = (rank07 << 4) + file07;
return {rank: rank07, file: file07, offset}
}
Insert cell
fillx88board = (game) => {
// Turns a chess.js game into it's x88 single array equivalent
const board88 = [];
const flatb = game.board().flat();
const sqRef = game.SQUARES;
for (var i = 0; i < flatb.length; i++) {
let sq = sqRef[i];
let idx = getx88(sq);
board88[idx] = flatb[i];
}
return board88;
}
Insert cell
getAttackersx88 = (boardx88, sqx88, color) => {
const attackers = [];
const board = boardx88;

for (var i = SQUARESx88.a8; i <= SQUARESx88.h1; i++) {
/* did we run off the end of the board */
if (i & 0x88) {
i += 7
continue
}

/* if empty square or wrong color */
if (board[i] == null || board[i].color !== color) continue

var piece = board[i];


// let's say we're at c7, so a pawn

// difference = (18 - 33) = -15
var difference = i - sqx88
// index = 104
var index = difference + 119

// ATTACKS[104] = 53 (looks like a diaganol)
// 110101

// shifts[Pawn] = 0
// 1 << 0 = 1
// 110101 & 1 = 1, so true


if (ATTACKS[index] & (1 << SHIFTS[piece.type])) {

// true
if (piece.type === pieces.PAWN) {
// no
if (difference > 0) {
if (piece.color === colors.WHITE) {
attackers.push(piece);
continue;
}
} else {
// yes! and it's black so true. so negative difference means up the board,
// since it's a pawn, we move on
if (piece.color === colors.BLACK) {
attackers.push(piece);
continue;
}
}
continue
}

/* if the piece is a knight or a king */
if (piece.type === 'n' || piece.type === 'k') {
attackers.push(piece);
continue;
}

var offset = RAYS[index]
var j = i + offset

var blocked = false
while (j !== sqx88) {
if (board[j] != null) {
blocked = true
break
}
j += offset
}

if (!blocked) {
attackers.push(piece);
}
}
}

return attackers
}
Insert cell
d3 = require('d3')
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more