Skip to content

Instantly share code, notes, and snippets.

@cheery
Created November 23, 2018 21:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cheery/5f22958e5cf0e456f1a419167c7fed4b to your computer and use it in GitHub Desktop.
Save cheery/5f22958e5cf0e456f1a419167c7fed4b to your computer and use it in GitHub Desktop.
TAU prolog chess model (23.11.2018)
% Written for TAU prolog.
:- use_module(library(lists)).
chess(doh, End) :-
initial_board(InitialBoard),
move(InitialBoard, black, XX),
move(XX, white, YY),
move(YY, black, End).
% Pawn movements.
move(Board, Color, End) :-
select(piece(Color, pawn, X, Y), Board, Motion),
(Color = black, N_Y is Y - 1;
Color = white, N_Y is Y + 1),
vacant(X, N_Y, Board),
(
End = [piece(Color, pawn, X, N_Y) | Motion]
;
initial(piece(Color, pawn, X, Y)),
(Color = black, NN_Y is Y - 2;
Color = white, NN_Y is Y + 2),
vacant(X, NN_Y, Board),
End = [piece(Color, pawn, X, NN_Y) | Motion]
).
% pawn's En-passant requires
% knowledge about the previous move.
% Current description of moves cannot explain it.
%move(Board, Color, End) :-
% select(piece(Color, pawn, X, Y), Board, Motion),
% (Color = black, N_Y is Y - 1;
% Color = white, N_Y is Y + 1),
% (N_X is X + 1; N_X is X - 1),
% capture(piece(Color, pawn, X, Y), End, Motion).
% Knight motions.
move(Board, Color, End) :-
select(piece(Color, knight, X, Y), Board, Motion),
(
N_X is X + 1, N_Y is Y + 2;
N_X is X - 1, N_Y is Y + 2;
N_X is X + 1, N_Y is Y - 2;
N_X is X - 1, N_Y is Y - 2;
N_X is X + 2, N_Y is Y + 1;
N_X is X - 2, N_Y is Y + 1;
N_X is X + 2, N_Y is Y - 1;
N_X is X - 2, N_Y is Y - 1
),
vacant(N_X, N_Y, Board),
End = [piece(Color, knight, N_X, N_Y) | Motion].
capture(piece(Color, Which, X, Y), Motion, End) :-
opponent(Color, Other),
select(piece(Other, _, X, Y), Motion, Motion2),
End = [piece(Color, Which, X, Y) | Motion2].
vacant(X, Y, Board) :-
between(1, 8, X),
between(1, 8, Y),
\+(member(piece(_, _, X, Y), Board)).
opponent(white, black).
opponent(black, white).
%
initial_board(Board) :-
findall(Piece, initial(Piece), Board).
initial(piece(white, rook, 1, 1)).
initial(piece(white, knight, 2, 1)).
initial(piece(white, bishop, 3, 1)).
initial(piece(white, queen, 4, 1)).
initial(piece(white, king, 5, 1)).
initial(piece(white, bishop, 6, 1)).
initial(piece(white, knight, 7, 1)).
initial(piece(white, rook, 8, 1)).
initial(piece(white, pawn, X, 2)) :-
between(1, 8, X).
initial(piece(black, rook, 1, 8)).
initial(piece(black, knight, 2, 8)).
initial(piece(black, bishop, 3, 8)).
initial(piece(black, queen, 4, 8)).
initial(piece(black, king, 5, 8)).
initial(piece(black, bishop, 6, 8)).
initial(piece(black, knight, 7, 8)).
initial(piece(black, rook, 8, 8)).
initial(piece(black, pawn, X, 7)) :-
between(1, 8, X).
% member(piece(_, _, R_X, R_Y))
% member(piece(Color, pawn, X, Y), A),
% pawn, rook, knight, bishop, queen, king
% ; Here's a game of chess described with logic.
% ;
% ; Every proposition represents a type,
% ; concretely this means that variables refer to types.
% ; They concisely describe the valid states and state transitions
% ; in the system.
%
% ; This program uses A{}B -syntax to refer on interaction through
% ; the channel of type 'A', where the channel becomes a type 'B'.
%
% ; We have some formulas that we haven't defined,
% ; they are described here.
%
% ; move(A, Side, B) - describes valid movements for black/white player.
% ; checkmate(A, Side) - describes a situation where either player has
% ; run out of valid moves.
%
% ; White player starts and the black player responds on it.
% chess(Game1, A) :-
% Game1{send B, receive C}Game2,
% move(A, white, B),
% move(B, black, C),
% chess(Game2, C).
%
% ; The situation where the white loses to the black.
% chess(Game1, A) :-
% checkmate(A, white),
% Game1{}, fail.
%
% ; The situation where the white wins against the black.
% chess(Game1, A) :-
% move(A, white, B),
% checkmate(B, black),
% Game1{send B}.
%
% ; The lose condition is a bit uncertain because the contradiction
% ; means that the program state has collapsed
% ; and the program for computation does not exist.
draw_board(Board) :-
nl, draw_row(1, 1, Board), nl.
draw_row(X, Y, Board) :-
X =< 8,
draw_piece(X, Y, Board),
X1 is X+1,
draw_row(X1, Y, Board).
draw_row(9, Y, Board) :-
Y =< 7,
nl,
Y1 is Y+1,
draw_row(1, Y1, Board).
draw_row(9, 8, _) :-
nl.
draw_piece(X, Y, Board) :-
X == 1,
write(' .'),
draw_piece_on_board(X, Y, Board),
write('.').
draw_piece(X, Y, Board) :-
X > 1,
draw_piece_on_board(X, Y, Board),
write('.').
draw_piece_on_board(X, Y, Board) :-
( member(piece(_, Which, X, Y), Board) ->
letter(Which, Letter),
write(Letter)
;
write('_')
).
letter(bishop, 'b').
letter(king, 'k').
letter(knight, 'h').
letter(pawn, 'p').
letter(queen, 'q').
letter(rook, 'r').
<html>
<head>
<title>tau chess</title>
</head>
<body>
<script type="text/javascript" src="tau-prolog.js"></script>
<script type="text/prolog" id="chess.pl" src="chess.pl"></script>
<canvas id="screen" width="512" height="512"></canvas>
<script>
fetch("chess.pl").then(function(data) {
return data.text();
}).then(function(text){
var ctx = document.getElementById("screen").getContext("2d");
var k = 20;
draw_blank_board(ctx, k);
var session = pl.create(100000);
session.consult(text);
session.query("chess(X, Y).");
function next_frame() {
session.answer(function(answer) {
if (answer === null) {
console.log(answer);
}
else if (answer === false) {
}
else if (answer.id == "throw") {
console.log("thrown", answer);
} else {
//console.log(answer.lookup("X").toString());
//console.log(answer.lookup("Y").toString());
//console.log(answer.lookup("Y"));
draw_blank_board(ctx, k);
draw_state(ctx, k, answer.lookup("Y"));
requestAnimationFrame(next_frame);
}
});
}
next_frame();
});
window.addEventListener("load", function() {
});
function draw_state(ctx, k, board) {
if (board instanceof pl.type.Term) {
if (board.indicator === "./2") {
var piece = board.args[0];
var x = piece.args[2].toJavaScript() - 1;
var y = piece.args[3].toJavaScript() - 1;
ctx.fillStyle = piece.args[0].id;
ctx.fillRect(x*k+5, y*k+5, k-10, k-10);
draw_state(ctx, k, board.args[1]);
} else if (board.indicator === "[]/0") {
}
else {
throw "hmm";
}
}
}
function draw_blank_board(ctx, k) {
ctx.clearRect(0, 0, k*8, k*8);
for (var i = 0; i < 8; i++) {
ctx.fillStyle = "#888";
for (var j = i&1; j < 8; j += 2) {
ctx.fillRect(i*k, j*k, k, k);
}
ctx.fillStyle = "#ccc";
for (var j = ~(i&1); j < 8; j += 2) {
ctx.fillRect(i*k, j*k, k, k);
}
}
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment