| 1 |
#!/usr/bin/swipl |
| 2 |
% vim: ft=prolog textwidth=80 tabstop=4 softtabstop=4 shiftwidth=4 expandtab |
| 3 |
|
| 4 |
map_size(78, 23). |
| 5 |
map_upper_bound(XMax, YMax) :- |
| 6 |
map_size(XSize, YSize), |
| 7 |
XMax is XSize - 1, |
| 8 |
YMax is YSize - 1. |
| 9 |
|
| 10 |
in_map(X, Y) :- |
| 11 |
X >= 0, |
| 12 |
Y >= 0, |
| 13 |
map_size(XSize, YSize), |
| 14 |
X < XSize, |
| 15 |
Y < YSize. |
| 16 |
|
| 17 |
tile(wall, X, Y) :- \+ in_map(X, Y). |
| 18 |
tile(floor, X, Y) :- in_map(X, Y). |
| 19 |
% tile(wall, 0, _). |
| 20 |
% tile(wall, _, 0). |
| 21 |
% tile(wall, X, _) :- map_upper_bound(X, _). |
| 22 |
% tile(wall, _, Y) :- map_upper_bound(_, Y). |
| 23 |
|
| 24 |
:- dynamic(player/2, messages/1). |
| 25 |
|
| 26 |
player(2,3). |
| 27 |
messages(["", ""]). |
| 28 |
message_lines(2). |
| 29 |
|
| 30 |
msg(Message) :- |
| 31 |
messages(Tail), |
| 32 |
retractall(messages(_)), |
| 33 |
assertz(messages([Message|Tail])). |
| 34 |
|
| 35 |
%%%%%%%%%%%%%%%% |
| 36 |
% drawing code % |
| 37 |
%%%%%%%%%%%%%%%% |
| 38 |
|
| 39 |
draw_char(_X, Y) :- |
| 40 |
tty_size(YSize, _), |
| 41 |
% map_size(_, YSize), |
| 42 |
Y >= YSize. |
| 43 |
draw_char(X, Y) :- |
| 44 |
tty_size(_, XSize), |
| 45 |
% map_size(XSize, _), |
| 46 |
X >= XSize, |
| 47 |
NY is Y + 1, |
| 48 |
%nl, |
| 49 |
draw_char(0, NY). |
| 50 |
draw_char(X, Y) :- |
| 51 |
( X = 0 |
| 52 |
->tty_goto(X, Y) |
| 53 |
; true |
| 54 |
), |
| 55 |
|
| 56 |
message_lines(YMsgs), |
| 57 |
( Y < YMsgs |
| 58 |
-> write(' ') |
| 59 |
; display_offset(XOff, YOff), |
| 60 |
XMap is X + XOff, |
| 61 |
YMap is Y + YOff, |
| 62 |
get_character(XMap, YMap, C), |
| 63 |
format('~s', [C]) |
| 64 |
), |
| 65 |
NX is X + 1, |
| 66 |
draw_char(NX, Y). |
| 67 |
|
| 68 |
display_offset(X, Y) :- |
| 69 |
player(XPos, YPos), |
| 70 |
tty_size(YSize, XSize), |
| 71 |
message_lines(YMsgs), |
| 72 |
X is XPos - floor(XSize / 2), |
| 73 |
Y is YPos - floor((YSize - YMsgs) / 2). |
| 74 |
|
| 75 |
display_msgs(Line) :- message_lines(Line). |
| 76 |
display_msgs(Line) :- |
| 77 |
message_lines(LineCount), |
| 78 |
MsgId is LineCount - Line, |
| 79 |
messages(Messages), |
| 80 |
nth1(MsgId, Messages, Message), |
| 81 |
tty_goto(0, Line), |
| 82 |
format('~s', [Message]), |
| 83 |
NextLine is Line + 1, |
| 84 |
display_msgs(NextLine). |
| 85 |
|
| 86 |
draw :- |
| 87 |
once(draw_char(0, 0)), |
| 88 |
map_size(_, YSize), |
| 89 |
display_msgs(0), |
| 90 |
tty_goto(0, YSize). |
| 91 |
|
| 92 |
% character displayed for a position on map |
| 93 |
get_character(X, Y, "@") :- player(X, Y). |
| 94 |
get_character(X, Y, C) :- |
| 95 |
tile(Tile, X, Y), |
| 96 |
tile_display(Tile, C). |
| 97 |
|
| 98 |
tile_display(wall, "#"). |
| 99 |
tile_display(floor, "."). |
| 100 |
|
| 101 |
tile_passable(floor). |
| 102 |
|
| 103 |
% % get line of a map to display as a string into aggregator, starting from XCur |
| 104 |
% % as rightmost character |
| 105 |
% get_line(Y, XCur, Trail, Agg) :- |
| 106 |
% ( XCur < 0 |
| 107 |
% -> Trail = Agg |
| 108 |
% ; XPrev is XCur - 1, |
| 109 |
% get_character(XCur, Y, C), |
| 110 |
% get_line(Y, XPrev, [C|Trail], Agg) |
| 111 |
% ). |
| 112 |
|
| 113 |
% get_screen(YCur, Trail, Agg) :- |
| 114 |
% ( YCur < 0 |
| 115 |
% -> Trail = Agg |
| 116 |
% ; YPrev is YCur - 1, |
| 117 |
% map_size(XSize, _), |
| 118 |
% XLast is XSize - 1, |
| 119 |
% get_line(YCur, XLast, [], Line), |
| 120 |
% get_screen(YPrev, [Line|Trail], Agg) |
| 121 |
% ). |
| 122 |
|
| 123 |
% get_screen(Lines) :- |
| 124 |
% map_size(_, YSize), |
| 125 |
% YLast is YSize - 1, |
| 126 |
% get_screen(YLast, [], Lines). |
| 127 |
|
| 128 |
% % draw a list of lines on screen |
| 129 |
% draw_lines([]). |
| 130 |
% draw_lines([Line|Rest]) :- |
| 131 |
% name(LineAtom, Line), |
| 132 |
% write(LineAtom), |
| 133 |
% nl, |
| 134 |
% draw_lines(Rest). |
| 135 |
|
| 136 |
% % draw current map |
| 137 |
% draw :- get_screen(Lines), draw_lines(Lines). |
| 138 |
|
| 139 |
%%%%%%%%%%%%%%%%%%%% |
| 140 |
% interaction code % |
| 141 |
%%%%%%%%%%%%%%%%%%%% |
| 142 |
|
| 143 |
move_player(X, Y) :- |
| 144 |
player(XCur, YCur), |
| 145 |
XNew is XCur + X, |
| 146 |
YNew is YCur + Y, |
| 147 |
( tile(Tile, XNew, YNew), |
| 148 |
tile_passable(Tile) |
| 149 |
-> retractall(player(_, _)), |
| 150 |
asserta(player(XNew, YNew)) |
| 151 |
; print('Bump!'), nl |
| 152 |
). |
| 153 |
|
| 154 |
act("\n"). |
| 155 |
act("\r"). |
| 156 |
|
| 157 |
act("h") :- msg("left"), move_player(-1, 0). |
| 158 |
act("j") :- msg("down"), move_player( 0, 1). |
| 159 |
act("k") :- msg("up"), move_player( 0, -1). |
| 160 |
act("l") :- msg("right"), move_player( 1, 0). |
| 161 |
|
| 162 |
act("y") :- move_player(-1, -1). |
| 163 |
act("u") :- move_player( 1, -1). |
| 164 |
act("b") :- move_player(-1, 1). |
| 165 |
act("n") :- move_player( 1, 1). |
| 166 |
|
| 167 |
mainloop :- |
| 168 |
draw, |
| 169 |
get_single_char(C), |
| 170 |
( act([C]) |
| 171 |
-> true |
| 172 |
; format(codes(Msg), 'unknown character code: ~d', [C]), |
| 173 |
msg(Msg) |
| 174 |
), |
| 175 |
mainloop. |
| 176 |
|
| 177 |
main :- mainloop. |
| 178 |
|
| 179 |
% From https://github.com/Anniepoo/prolog-examples/blob/master/roguelike.pl |
| 180 |
|