Путеводитель разработчика по Garbo-боту
- суббота, 26 июня 2021 г. в 00:38:33
function MakeSquare(row, column) {
return ((row + 2) << 4) | (column + 4);
}
var colorBlack = 0x10;
var colorWhite = 0x08;
var pieceEmpty = 0x00;
var piecePawn = 0x01;
var pieceKnight = 0x02;
var pieceBishop = 0x03;
var pieceRook = 0x04;
var pieceQueen = 0x05;
var pieceKing = 0x06;
var otherColor = 8 - g_toMove;
...
g_toMove = otherColor;
var moveflagEPC = 0x2 << 16;
var moveflagCastleKing = 0x4 << 16;
var moveflagCastleQueen = 0x8 << 16;
var moveflagPromotion = 0x10 << 16;
var moveflagPromoteKnight = 0x20 << 16;
var moveflagPromoteQueen = 0x40 << 16;
var moveflagPromoteBishop = 0x80 << 16;
+var g_flags = moveflagPromoteKnight | moveflagPromoteQueen | moveflagPromoteBishop | moveflagCastleKing | moveflagCastleQueen | moveflagEPC;
function MovePawnTo(moveStack, start, square) {
var row = square & 0xF0;
+ var delta = (8 - g_height) << 4;
- if ((row == 0x90 || (row == 0x20))) {
+ if ((row == (0x90 - delta) || (row == 0x20))) {
+ if (g_flags & moveflagPromoteQueen) {
moveStack[moveStack.length] = GenerateMove(start, square,
moveflagPromotion | moveflagPromoteQueen);
+ }
+ if (g_flags & moveflagPromoteKnight) {
moveStack[moveStack.length] = GenerateMove(start, square,
moveflagPromotion | moveflagPromoteKnight);
+ }
+ if (g_flags & moveflagPromoteBishop) {
moveStack[moveStack.length] = GenerateMove(start, square,
moveflagPromotion | moveflagPromoteBishop);
+ }
moveStack[moveStack.length] = GenerateMove(start, square,
moveflagPromotion);
}
else {
moveStack[moveStack.length] = GenerateMove(start, square, 0);
}
}
if (move & moveflagPromotion) {
if (move & moveflagPromoteBishop) result += "=B";
else if (move & moveflagPromoteKnight) result += "=N";
else if (move & moveflagPromoteQueen) result += "=Q";
else result += "=R";
}
var pawnAdj =
[
0, 0, 0, 0, 0, 0, 0, 0,
-25, 105, 135, 270, 270, 135, 105, -25,
-80, 0, 30, 176, 176, 30, 0, -80,
-85, -5, 25, 175, 175, 25, -5, -85,
-90, -10, 20, 125, 125, 20, -10, -90,
-95, -15, 15, 75, 75, 15, -15, -95,
-100, -20, 10, 70, 70, 10, -20, -100,
0, 0, 0, 0, 0, 0, 0, 0
];
var knightAdj =
[-200, -100, -50, -50, -50, -50, -100, -200,
-100, 0, 0, 0, 0, 0, 0, -100,
-50, 0, 60, 60, 60, 60, 0, -50,
-50, 0, 30, 60, 60, 30, 0, -50,
-50, 0, 30, 60, 60, 30, 0, -50,
-50, 0, 30, 30, 30, 30, 0, -50,
-100, 0, 0, 0, 0, 0, 0, -100,
-200, -50, -25, -25, -25, -25, -50, -200
];
var bishopAdj =
[ -50,-50,-25,-10,-10,-25,-50,-50,
-50,-25,-10, 0, 0,-10,-25,-50,
-25,-10, 0, 25, 25, 0,-10,-25,
-10, 0, 25, 40, 40, 25, 0,-10,
-10, 0, 25, 40, 40, 25, 0,-10,
-25,-10, 0, 25, 25, 0,-10,-25,
-50,-25,-10, 0, 0,-10,-25,-50,
-50,-50,-25,-10,-10,-25,-50,-50
];
var rookAdj =
[ -60, -30, -10, 20, 20, -10, -30, -60,
40, 70, 90,120,120, 90, 70, 40,
-60, -30, -10, 20, 20, -10, -30, -60,
-60, -30, -10, 20, 20, -10, -30, -60,
-60, -30, -10, 20, 20, -10, -30, -60,
-60, -30, -10, 20, 20, -10, -30, -60,
-60, -30, -10, 20, 20, -10, -30, -60,
-60, -30, -10, 20, 20, -10, -30, -60
];
var kingAdj =
[ 50, 150, -25, -125, -125, -25, 150, 50,
50, 150, -25, -125, -125, -25, 150, 50,
50, 150, -25, -125, -125, -25, 150, 50,
50, 150, -25, -125, -125, -25, 150, 50,
50, 150, -25, -125, -125, -25, 150, 50,
50, 150, -25, -125, -125, -25, 150, 50,
50, 150, -25, -125, -125, -25, 150, 50,
150, 250, 75, -25, -25, 75, 250, 150
];
var emptyAdj =
[0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];
pieceSquareAdj[piecePawn] = MakeTable(
((g_width == 8) && (g_height == 8)) ? pawnAdj : emptyAdj);
pieceSquareAdj[pieceKnight] = MakeTable(
((g_width == 8) && (g_height == 8)) ? knightAdj : emptyAdj);
pieceSquareAdj[pieceBishop] = MakeTable(
((g_width == 8) && (g_height == 8)) ? bishopAdj: emptyAdj);
pieceSquareAdj[pieceRook] = MakeTable(
((g_width == 8) && (g_height == 8)) ? rookAdj : emptyAdj);
pieceSquareAdj[pieceQueen] = MakeTable(emptyAdj);
pieceSquareAdj[pieceKing] = MakeTable(
((g_width == 8) && (g_height == 8)) ? kingAdj: emptyAdj);
-var materialTable = [0, 800, 3350, 3450, 5000, 9750, 600000];
+var materialTable = [0, 800, 3350, 1500, 5000, 2500, 600000];
// Bishop mobility
mob = -4;
pieceIdx = (color | 3) << 4;
from = g_pieceList[pieceIdx++];
while (from != 0) {
mob += mobUnit[g_board[from + 30]];
mob += mobUnit[g_board[from + 34]];
mob += mobUnit[g_board[from - 30]];
mob += mobUnit[g_board[from - 34]];
from = g_pieceList[pieceIdx++];
}
result += 44 * mob;
...
// Queen mobility
mob = -2;
pieceIdx = (color | 5) << 4;
from = g_pieceList[pieceIdx++];
while (from != 0) {
mob += mobUnit[g_board[from + 15]];
mob += mobUnit[g_board[from + 17]];
mob += mobUnit[g_board[from - 15]];
mob += mobUnit[g_board[from - 17]];
from = g_pieceList[pieceIdx++];
}
result += 22 * mob;
// Bishop quiet moves
pieceIdx = (g_toMove | 3) << 4;
from = g_pieceList[pieceIdx++];
while (from != 0) {
to = from + 30;
if (g_board[to] == 0)
moveStack[moveStack.length] = GenerateMove(from, to);
to = from + 34;
if (g_board[to] == 0)
moveStack[moveStack.length] = GenerateMove(from, to);
to = from - 30;
if (g_board[to] == 0)
moveStack[moveStack.length] = GenerateMove(from, to);
to = from - 34;
if (g_board[to] == 0)
moveStack[moveStack.length] = GenerateMove(from, to);
from = g_pieceList[pieceIdx++];
}
...
// Queen quiet moves
pieceIdx = (g_toMove | 5) << 4;
from = g_pieceList[pieceIdx++];
while (from != 0) {
to = from + 15;
if (g_board[to] == 0)
moveStack[moveStack.length] = GenerateMove(from, to);
to = from + 17;
if (g_board[to] == 0)
moveStack[moveStack.length] = GenerateMove(from, to);
to = from - 15;
if (g_board[to] == 0)
moveStack[moveStack.length] = GenerateMove(from, to);
to = from - 17;
if (g_board[to] == 0)
moveStack[moveStack.length] = GenerateMove(from, to);
from = g_pieceList[pieceIdx++];
}
function IsSquareAttackableFrom(target, from){
var index = from - target + 128;
var piece = g_board[from];
if (g_vectorDelta[index].pieceMask[(piece >> 3) & 1] &
(1 << (piece & 0x7))) {
// Yes, this square is pseudo-attackable.
// Now, check for real attack
var inc = g_vectorDelta[index].delta;
do {
from += inc;
if (from == target)
return true;
} while (g_board[from] == 0);
}
return false;
}
var g_vectorDelta = new Array(256);
var g_bishopDeltas = [-30, -34, 30, 34];
var g_knightDeltas = [31, 33, 14, -14, -31, -33, 18, -18];
var g_rookDeltas = [-1, +1, -16, +16];
var g_queenDeltas = [-15, -17, 15, 17];
var g_kingDeltas = [-1, +1, -15, +15, -17, +17, -16, +16];
...
var pieceDeltas = [[], [], g_knightDeltas, g_bishopDeltas, g_rookDeltas,
g_queenDeltas, g_kingDeltas];
for (var i = 0; i < 256; i++) {
g_vectorDelta[i] = new Object();
g_vectorDelta[i].delta = 0;
g_vectorDelta[i].pieceMask = new Array(2);
g_vectorDelta[i].pieceMask[0] = 0;
g_vectorDelta[i].pieceMask[1] = 0;
}
// Initialize the vector delta table
for (var row = 0; row < 0x80; row += 0x10)
for (var col = 0; col < 0x8; col++) {
var square = row | col;
// Pawn moves
var index = square - (square - 17) + 128;
g_vectorDelta[index].pieceMask[colorWhite >> 3] |=
(1 << pieceSarbaz);
index = square - (square - 15) + 128;
g_vectorDelta[index].pieceMask[colorWhite >> 3] |=
(1 << pieceSarbaz);
index = square - (square + 17) + 128;
g_vectorDelta[index].pieceMask[0] |= (1 << pieceSarbaz);
index = square - (square + 15) + 128;
g_vectorDelta[index].pieceMask[0] |= (1 << pieceSarbaz);
for (var i = pieceAsb; i <= pieceShah; i++) {
for (var dir = 0; dir < pieceDeltas[i].length; dir++) {
var target = square + pieceDeltas[i][dir];
while (!(target & 0x88)) {
index = square - target + 128;
g_vectorDelta[index].pieceMask[colorWhite >> 3] |=
(1 << i);
g_vectorDelta[index].pieceMask[0] |= (1 << i);
var flip = -1;
if (square < target)
flip = 1;
if ((square & 0xF0) == (target & 0xF0)) {
// On the same row
g_vectorDelta[index].delta = flip * 1;
} else if ((square & 0x0F) == (target & 0x0F)) {
// On the same column
g_vectorDelta[index].delta = flip * 16;
} else if ((square % 15) == (target % 15)) {
g_vectorDelta[index].delta = flip * 15;
} else if ((square % 17) == (target % 17)) {
g_vectorDelta[index].delta = flip * 17;
}
if ((i == pieceAsb) || (i == pieceAlfil) ||
(i == pieceFers)) {
g_vectorDelta[index].delta = pieceDeltas[i][dir];
break;
}
if (i == pieceShah)
break;
target += pieceDeltas[i][dir];
}
}
}
}
var g_pieceIndex = new Array(256);
var g_pieceList = new Array(2 * 8 * 16);
var g_pieceCount = new Array(2 * 8);
function InitializePieceList() {
for (var i = 0; i < 16; i++) {
g_pieceCount[i] = 0;
for (var j = 0; j < 16; j++) {
// 0 is used as the terminator for piece lists
g_pieceList[(i << 4) | j] = 0;
}
}
for (var i = 0; i < 256; i++) {
g_pieceIndex[i] = 0;
if (g_board[i] & (colorWhite | colorBlack)) {
var piece = g_board[i] & 0xF;
g_pieceList[(piece << 4) | g_pieceCount[piece]] = i;
g_pieceIndex[i] = g_pieceCount[piece];
g_pieceCount[piece]++;
}
}
}