Search code examples
prolog

How to sort and print coordinates of a chess board with pieces in them


I tried something like this:

boardN([w-k-(a-1), b-k-(h-8), b-q-(h-1)]).


small(a-1).
small(h-8).
small(h-1).
small(h-7).

pretty(B) :- findall(X, small(X), Ps), pretty_h(Ps, B).
pretty_h([], _).
pretty_h([P|Rest], B) :- (member(Piece-P, B), uci(Piece);format('X')), pretty_h(Rest, B).

But I am lost in infinite loops and backtracking nonsense.

I have this representation of a chess board.

board([w-k-(a-2), b-q-(c-3), w-r-(a-1), b-b-(h-8)]).

I want to print this like that:

8       b
7
6
5
4
3 q
2K
1R
 abcdefgh

I have already written how to format pieces:

uci(w-r) :- format('R').
uci(w-q) :- format('Q').
uci(w-k) :- format('K').
uci(w-n) :- format('N').
uci(w-b) :- format('B').
uci(w-p) :- format('P').
uci(b-Role) :- format('~a', Role).

I just need to fill this in:

pretty(B) :- format('r k k \nhello~a', B).

So ?- board(B), pretty(B). will print out the board. I thought B should be sorted by positions a-8 to h-1 . So how would I sort this array of pieces by the third pair. I also have this predicate fact of what is bigger:

up(1-2).
up(2-3).
up(3-4).
up(4-5).
up(5-6).
up(6-7).
up(7-8).
upper(X-Y, []) :- up(X-Y).
upper(X-Y, [Z|Rest]) :- up(X-Z), upper(Z-Y, Rest).
right(a-b).
right(b-c).
right(c-d).
right(d-e).
right(e-f).
right(f-g).
right(g-h).
righter(X-Y, []) :- right(X-Y).
righter(X-Y, [Z|Rest]) :- right(X-Z), righter(Z-Y, Rest).
bigger(X-Y,X_-Y_) :- upper(Y-Y_); Y=Y_, righter(X-X_).

I want something as simple and precise as possible, no need to make a mess. Something like,

Get a list of all positions sorted from a-8 to h-1, ask if a position has a piece to the board, if it has print the piece otherwise print a space, for each row.


Solution

  • A possible solution is:

    print_board(Board) :-
        forall( member(Y, [8,7,6,5,4,3,2,1]),
                ( findall(X-Piece, member(Piece-(X-Y), Board), Pieces),
                  print_row(Y, Pieces) ) ),
        format('\n  abcdefgh\n\n').
    
    print_row(Y, Pieces) :-
        format('\n~w ', [Y]),
        forall( member(X, [a,b,c,d,e,f,g,h]),
                (   member(X-(_-P), Pieces)
                ->  format('~w', [P])
                ;   format('.') ) ).
    
    board([w-k-(a-2), b-q-(c-3), w-r-(a-1), b-b-(h-8), w-n-(f-8)]).
    

    Example:

    ?- board(B), print_board(B).
    
    8 .....n.b
    7 ........
    6 ........
    5 ........
    4 ........
    3 ..q.....
    2 k.......
    1 r.......
      abcdefgh
    
    B = [w-k-(a-2), b-q-(c-3), w-r-(a-1), b-b-(h-8), w-n-(f-8)].