Skip to content

Instantly share code, notes, and snippets.

@hsk
Created January 12, 2023 06:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hsk/32fa7aa16dd0bca22474b23465b7c88c to your computer and use it in GitHub Desktop.
Save hsk/32fa7aa16dd0bca22474b23465b7c88c to your computer and use it in GitHub Desktop.
Roguelike PacMan
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