Files
Basalt2/node_modules/shiki/samples/prolog.sample
Robert Jelic 5c15cf28fa Test
2025-02-10 07:12:35 +01:00

180 lines
3.9 KiB
Prolog

#!/usr/bin/swipl
% vim: ft=prolog textwidth=80 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
map_size(78, 23).
map_upper_bound(XMax, YMax) :-
map_size(XSize, YSize),
XMax is XSize - 1,
YMax is YSize - 1.
in_map(X, Y) :-
X >= 0,
Y >= 0,
map_size(XSize, YSize),
X < XSize,
Y < YSize.
tile(wall, X, Y) :- \+ in_map(X, Y).
tile(floor, X, Y) :- in_map(X, Y).
% tile(wall, 0, _).
% tile(wall, _, 0).
% tile(wall, X, _) :- map_upper_bound(X, _).
% tile(wall, _, Y) :- map_upper_bound(_, Y).
:- dynamic(player/2, messages/1).
player(2,3).
messages(["", ""]).
message_lines(2).
msg(Message) :-
messages(Tail),
retractall(messages(_)),
assertz(messages([Message|Tail])).
%%%%%%%%%%%%%%%%
% drawing code %
%%%%%%%%%%%%%%%%
draw_char(_X, Y) :-
tty_size(YSize, _),
% map_size(_, YSize),
Y >= YSize.
draw_char(X, Y) :-
tty_size(_, XSize),
% map_size(XSize, _),
X >= XSize,
NY is Y + 1,
%nl,
draw_char(0, NY).
draw_char(X, Y) :-
( X = 0
->tty_goto(X, Y)
; true
),
message_lines(YMsgs),
( Y < YMsgs
-> write(' ')
; display_offset(XOff, YOff),
XMap is X + XOff,
YMap is Y + YOff,
get_character(XMap, YMap, C),
format('~s', [C])
),
NX is X + 1,
draw_char(NX, Y).
display_offset(X, Y) :-
player(XPos, YPos),
tty_size(YSize, XSize),
message_lines(YMsgs),
X is XPos - floor(XSize / 2),
Y is YPos - floor((YSize - YMsgs) / 2).
display_msgs(Line) :- message_lines(Line).
display_msgs(Line) :-
message_lines(LineCount),
MsgId is LineCount - Line,
messages(Messages),
nth1(MsgId, Messages, Message),
tty_goto(0, Line),
format('~s', [Message]),
NextLine is Line + 1,
display_msgs(NextLine).
draw :-
once(draw_char(0, 0)),
map_size(_, YSize),
display_msgs(0),
tty_goto(0, YSize).
% character displayed for a position on map
get_character(X, Y, "@") :- player(X, Y).
get_character(X, Y, C) :-
tile(Tile, X, Y),
tile_display(Tile, C).
tile_display(wall, "#").
tile_display(floor, ".").
tile_passable(floor).
% % get line of a map to display as a string into aggregator, starting from XCur
% % as rightmost character
% get_line(Y, XCur, Trail, Agg) :-
% ( XCur < 0
% -> Trail = Agg
% ; XPrev is XCur - 1,
% get_character(XCur, Y, C),
% get_line(Y, XPrev, [C|Trail], Agg)
% ).
% get_screen(YCur, Trail, Agg) :-
% ( YCur < 0
% -> Trail = Agg
% ; YPrev is YCur - 1,
% map_size(XSize, _),
% XLast is XSize - 1,
% get_line(YCur, XLast, [], Line),
% get_screen(YPrev, [Line|Trail], Agg)
% ).
% get_screen(Lines) :-
% map_size(_, YSize),
% YLast is YSize - 1,
% get_screen(YLast, [], Lines).
% % draw a list of lines on screen
% draw_lines([]).
% draw_lines([Line|Rest]) :-
% name(LineAtom, Line),
% write(LineAtom),
% nl,
% draw_lines(Rest).
% % draw current map
% draw :- get_screen(Lines), draw_lines(Lines).
%%%%%%%%%%%%%%%%%%%%
% interaction code %
%%%%%%%%%%%%%%%%%%%%
move_player(X, Y) :-
player(XCur, YCur),
XNew is XCur + X,
YNew is YCur + Y,
( tile(Tile, XNew, YNew),
tile_passable(Tile)
-> retractall(player(_, _)),
asserta(player(XNew, YNew))
; print('Bump!'), nl
).
act("\n").
act("\r").
act("h") :- msg("left"), move_player(-1, 0).
act("j") :- msg("down"), move_player( 0, 1).
act("k") :- msg("up"), move_player( 0, -1).
act("l") :- msg("right"), move_player( 1, 0).
act("y") :- move_player(-1, -1).
act("u") :- move_player( 1, -1).
act("b") :- move_player(-1, 1).
act("n") :- move_player( 1, 1).
mainloop :-
draw,
get_single_char(C),
( act([C])
-> true
; format(codes(Msg), 'unknown character code: ~d', [C]),
msg(Msg)
),
mainloop.
main :- mainloop.
% From https://github.com/Anniepoo/prolog-examples/blob/master/roguelike.pl