Created
January 12, 2023 06:26
-
-
Save hsk/32fa7aa16dd0bca22474b23465b7c88c to your computer and use it in GitHub Desktop.
Roguelike PacMan
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
read_key([Code|Codes]):- get_single_char(Code), read_pending_codes(user,Codes,[]). | |
read_keyatom(KAtom) :- read_key(Codes), codes_keyatom(Codes,KAtom). | |
codes_keyatom([27,91,65],up) :- !. | |
codes_keyatom([27,91,66],down) :- !. | |
codes_keyatom([27,91,67],right) :- !. | |
codes_keyatom([27,91,68],left) :- !. | |
data('#####################'). | |
data('#.........#.........#'). | |
data('#o###.###.#.###.###o#'). | |
data('#.# #.# #.#.# #.# #.#'). | |
data('#.###.###.#.###.###.#'). | |
data('#...................#'). | |
data('#.###.#.#####.#.###.#'). | |
data('#.###.#.#####.#.###.#'). | |
data('#.....#...#...#.....#'). | |
data('#####.### # ###.#####'). | |
data(' #.# r #.# '). | |
data(' #.# ##-## #.# '). | |
data('#####.# # # #.#####'). | |
data(' . #byp# . '). | |
data('#####.# ##### #.#####'). | |
data(' #.# #.# '). | |
data(' #.# ##### #.# '). | |
data('#####.# ##### #.#####'). | |
data('#.....#...#...#.....#'). | |
data('#.###.###.#.###.###.#'). | |
data('#o..#.....@.....#..o#'). | |
data('###.#.#.#####.#.#.###'). | |
data('###.#.#.#####.#.#.###'). | |
data('#.....#...#...#.....#'). | |
data('#.#######.#.#######.#'). | |
data('#...................#'). | |
data('#####################'). | |
width(21). | |
height(27). | |
mkmap(Ms):- findall(D,data(D),Ds), atomic_list_concat(Ds,Ls),atom_chars(Ls,Cs), | |
maplist(mkmap,Cs,Ms),!. | |
mkmap(A,V):-db(V,A,_,_). | |
db(none ,' ',' ',tip ). | |
db(dot ,'.',' .',tip ). | |
db(pow ,'o',' o',tip ). | |
db(wall2 ,'-','--',tip ). | |
db(wall ,'#','##',tip ). | |
db(pac ,'@',' @',monster). | |
db(red ,'r',' R',monster). | |
db(blue ,'b',' B',monster). | |
db(orange,'y',' O',monster). | |
db(pink ,'p',' P',monster). | |
esa(dot). | |
esa(pow). | |
drawcnv(R,T):- db(T,_,R,_),!;T=R. | |
monster(M):-db(M,_,_,monster). | |
x(I,X):- width(W),X is I mod W. | |
y(I,Y):- width(W),Y is I div W. | |
monsters([T|Ts],I,P/[none|Ts1]/[T:[X,Y,up]|Ms]):- | |
monster(T),x(I,X),y(I,Y), I1 is I+1,!,monsters(Ts,I1,P/Ts1/Ms). | |
monsters([T|Ts],I,P/[T|Ts1]/Ms):- I1 is I+1,!,monsters(Ts,I1,P1/Ts1/Ms), | |
(esa(T)->P is P1+1;P=P1). | |
monsters([],_,0/[]/[]). | |
monsters(T,R):- monsters(T,0,R). | |
draw(P/I/T/Ms,P/I/T/Ms):- drawMap(T,I,Ms,0,R),write(R),!. | |
getTip(_,I,N,Ms,M):-x(N,X),y(N,Y),member(M1:[X,Y,_],Ms),!, | |
((I=0;M1=pac)->M=M1;I < 10 -> M='!!' ; M='??'),!. | |
getTip(T,_,_,_,T). | |
drawMap([T|Ts],I,Ms,N,R1):- getTip(T,I,N,Ms,M),drawcnv(A,M), | |
N1 is N+1,drawnl(N,A2),!,drawMap(Ts,I,Ms,N1,R),atomic_list_concat([A,A2,R],R1). | |
drawMap([],_,_,_,''). | |
drawnl(N,'\n'):- width(W),0 is (N+1) mod W,!. | |
drawnl(_,''). | |
wall(Ts,X/Y):-width(W),N is X+Y*W,nth0(N,Ts,T),member(T,[wall,wall2]),!. | |
wall2(Ts,X/Y):-width(W),N is X+Y*W,nth0(N,Ts,T),member(T,[wall]),!. | |
replace([H|T], 0, V, [V|T], H). | |
replace([H|T], N, V, [H|R], R2):- N1 is N-1, !, replace(T, N1, V, R, R2). | |
eat(X/Y, G/P/I/Ts/Ms, G1/P1/I1/Ts1/Ms1):- | |
not(wall(Ts,X/Y)), | |
width(W),N is X+Y*W,replace(Ts,N,none,Ts1,V),!, | |
(V=pow->I1=40;I1=I),!, | |
(esa(V)->P1 is P-1;P1=P),!, | |
(select(M:[X,Y,D],Ms,M:[10,13,D],Ms1),M\=pac,I>0;Ms1=Ms), | |
(member(M:[X,Y,D],Ms),M\=pac,I=0->G1=gameover;G1=G). | |
dmove(left,X/Y,X1/Y):-width(W),X1 is (W+X-1)mod W. | |
dmove(right,X/Y,X1/Y):-width(W),X1 is (X+1)mod W. | |
dmove(up,X/Y,X/Y1):-Y1 is Y-1. | |
dmove(down,X/Y,X/Y1):-Y1 is Y+1. | |
move1(D,X1/Y1,G/P/I/Ts/Ms,G/P/I/Ts/Ms):- member(pac:[X,Y,_],Ms),dmove(D,X/Y,X1/Y1). | |
move(X/Y,G/P/I/Ts/Ms,G/P/I/Ts/Ms1):- select(pac:[_,_,D],Ms,pac:[X,Y,D],Ms1). | |
pac_move(K,S,S3):-move1(K,XY,S,S1),eat(XY,S1,S2),!,move(XY,S2,S3). | |
pac_move(K,S,S). | |
invisible(G/P/I/Ts/Ms,G/P/I1/Ts/Ms):- I > 0,I1 is I-1,!. | |
invisible(G/P/I/Ts/Ms,G/P/I/Ts/Ms). | |
monster_move(_,M:V,G/Ms,G/Ms):-M=pac,!. | |
monster_move(I/T,M:[X,Y,D],G/Ms,G1/Ms1):- | |
dmove(D,X/Y,X1/Y1),not(wall2(T,X1/Y1)), | |
(member(M1:[X1,Y1,_],Ms)->(M1\=pac->fail;M1=pac->(I=0->G1=gameover,MD=0;G1=G,MD=1));G1=G,MD=0),!, | |
(MD=0->X2=X1,Y2=Y1;X2=10,Y2=13), | |
select(M:[_,_,D],Ms,M:[X2,Y2,D1],Ms1), | |
(X2=10,Y2=12->D1=up;D1=D). | |
monster_move(_,M:[X,Y,D],G/Ms,G/Ms1):- | |
random(N),N1 is integer(N*4-0.5),% ランダムに方向を選択 | |
nth0(N1,[up,down,left,right],D1), | |
select(M:[_,_,D],Ms,M:[X,Y,D1],Ms1). | |
monsters_move(G/P/I/Ts/Ms,G1/P/I/Ts/Ms1):-foldl(monster_move(I/Ts),Ms,G/Ms,G1/Ms1). | |
run(gameover/P/I/Ts/Ms,_):-draw(gameover/P/I/Ts/Ms,_),writeln('GAME OVER\a'). | |
run(G/0/I/Ts/Ms,_):-draw(gameclear/P/I/Ts/Ms,_),writeln('GAME CLEAR !!\a'). | |
run --> {read_keyatom(K)},pac_move(K),invisible,monsters_move,draw,run. | |
run(_,_). | |
:- mkmap(T),monsters(T,P/Ts/Ms),draw(0/0/Ts/Ms,_),run(game/P/0/Ts/Ms,_). | |
:- halt. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment