Created
November 23, 2018 21:40
-
-
Save cheery/5f22958e5cf0e456f1a419167c7fed4b to your computer and use it in GitHub Desktop.
TAU prolog chess model (23.11.2018)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% 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'). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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