Adventura
-=-=-=-=-=-
The best defense against logic is ignorance.
Protože se prologácká databáze hodí téměř na všechno, je velmi
snadné do ni popsat bludiště nějaké hry. Navíc se pravidla hodí
pro zápis různých problémů ve hře a proto je prolog vlastně ideální
jazyk pro popis adventur. Jednu takovou jsem tu napsal.
Bludiště se skládá ze tří místností - zahrady, chodby,
a záchodu. Chodba spojuje záchod a zahradu. Ze záchodu na zahradu
jze ještě vyskočit oknem, ale zpátky to už nejde:
% Bludiště
connect(zachod,zahrada).
connect(zachod,chodba). zachod<--->chodba<--->zahrada
connect(chodba,zachod). | ^
connect(zahrada,chodba). +----------------------+
connect(chodba,zahrada).
% Popisy pro jednotlivé místnosti
describe(papir,'proste toaletak').
describe(zachod,'Jsi na zachode..nelibe to tu voni').
describe(zahrada,'Jsi na zahrade..ptaci zpivaji, slunce sviti...').
describe(chodba,'Jsi na chodbe..vede ze zachodu na zahradu').
Na záchodě se nachází papír, který když vemete a položíte
na zahradu, dostanete vynadáno za znečišťování životního prostředí:
%Umístění předmětů
location(papir,zachod).
akce :-
location(papir,zahrada), %Pokud je papír na zahradě
write(' Vrhla se na tebe duchodkyne z holi a utloukla te ze slovy'),nl,
write(' "Takhle znecistovat zivotni prostredi! Kam se ten svet riti!" '
smrt.
A nyní jenom napsat vlastní engine pro hru. Ta musí měnit popis
světa podle toho, jak se hra vyvíjí. K tomu slouží dva predikáty -
assert, který přidá nějaký predikát do databáze a retract, který ho
zruší.
Napřed budeme potřebovat predikáty pro popis situace. Klasické
textovky většinou popisují kde jsi, co vidíš a kam jdeš. To jde
napsat jednoduše. Pozice hráče se bude určovat pomocí predikátu you,
který bude vždy pravdivý pouze pro místnost, kde hráč právě stojí.
popis :- %vypíše popis místnosti
you(L), %do L uloží pozici hráče
describe(L,X),%popis místnosti L
write(X),nl. %vypíše
cesty :- %vypise všechny cesty s místnosti
you(L), %uloží do L pozici hráče
connect(L,X), %zjistí cestu z L a do X uloží cíl-tady se děla backtracin
%pokud je předmětů v místnosti víc
write(X), %vypíše cílovou místnost
write(' '), %oddělí slova
fail. %selže,aby se system pokusil najít dalsi cestu a také ji vy
cesty :- %to se vyvolá,když už není žádná cesta k vypsaní
nl. %novy řádek-konec výpisu
vydis :- %vypíše předmety v místnosti
you(L),
location(X,L),
write(X),
write(' '),
fail.
vydis :-
nl.
mistnost :- %všechno to zavolá
popis, %Vypíše popis místnosti
write('cesty:'),%Vypíše cesty z místnosti
cesty,
write('vydis:'),%Vypíěe předměty
vydis,
Další důležitá část jsou příkazy. Klasické příkazy jsou jdi,
seber, polož a inventář.
Příkaz jdi musí zrušit starý predikát you a vytvořit nový, který
ukazuje do nové místnosti. Sbírání a pokládání předmětů lze vyřešit
tak, že se budou přesouvat do speciální místnosti you.
Mezi příkazy jde zahrnout i predikát, který hráče zabije - smrt.
To lze vyřešit tak, že přesune hráče do speciální místnosti nebe.
inventar :- %vypíše,co uzivatel nese-funguje stejne jako vidíš
location(X,you), %pro místnost you
write(X),
write(' '),
fail.
inventar :-
nl.
jdi(X) :- %funkce na chození
you(L),
connect(L,X),%musí existovat cesta z L do X
retract(you(L)), %Zruší spojení se starou místností
assert(you(X)). %Zavede do databáze novou pozici
jdi(X):- %V případě, že cesta nevede-prvni jdi selhalo
write(' Tam to nejde. '),nl.
smrt :-
you(L),
retract(you(L)), %Vezme hráče se staré pozice
assert(you(nebe)). %a přesune ho do nebe
zvedni(X) :- %Zvedne předmět
you(L),
location(X,L),%Předmět musí být v místnosti L
retract(location(X,L)),%Zruší spojení předmetu s místností
assert(location(X,you)),%a předá ho hráči
write(' Zvedl jsi '),write(X),nl.%vypíše to
zvedni(X) :- %V případě že předchozí predikát selhal
write(X),write(' tu nikde neni').
poloz(X) :- %Položí predmet
location(X,you),
you(L),
retract(location(X,you)),
assert(location(X,L)),
write(' Polozil jsi'),write(X),nl.
poloz(X) :-
write(X),write(' u sebe nemas').
Vlastní herní smyčka potom musí jenom žádat hráče o příkaz,
ten provédst a v případě, že se hráč objevil v nebi zkončit.
Pro jednoduchost použiju pro čtení příkazu predikátu read(X),
který načte term z klávesnice do X a call, který daný příkaz vyvolá.
Příkazy bude tedy hráč zadávat ve stejném formátu jako na příkazové
řádce prologu.
done :- %zjišťuje jestli hra nezkoncila
you(nebe),
write(' Sice jste zemrel ale nevadi...vlastne sjte hru vyhral ').
%Hlavni smycka
akce :- %Toto je posledni z akcí-nic se nestalo. To je proto,aby
%volaní akce z go neselhalo a nezrušilo tím provadění
%celé hry
nl.
go :- done. %Tímto je zaručeno aby hra zkoncila v případě
%že je konec
go :- %vlastní herní smyčka
mistnost,
write('>> '), %Prompt
read(X), %Načte term z klávesnice
call(X), %Vznese načtenoý dotas
akce, %Provede všechny akce
go. %Smyčka pomocí rekurze
Nakonec je ještě nutné hráče někam umístit - you(zachod). a hra
je hotova. Toto je příklad hry:
1 ?- [pll].
pll compiled, 0.03 sec, 6,300 bytes.
Yes
2 ?- go.
Jdi na zachode..nelibe to tu voni
cesty:zahrada chodba
vydis:papir
>> |: zvedni(papir).
Zvedl jsi papir
Jdi na zachode..nelibe to tu voni
cesty:zahrada chodba
vydis:
>> |: jdi(chodba).
Jsi na chodbe..vede ze zachodu na zahradu
cesty:zachod zahrada
vydis:
>> |: inventar.
papir
Jsi na chodbe..vede ze zachodu na zahradu
cesty:zachod zahrada
vydis:
>> |: poloz(papir).
Polozil jsi papir
Jsi na chodbe..vede ze zachodu na zahradu
cesty:zachod zahrada
vydis:papir
>> |: zvedni(papir).
Zvedl jsi papir
Jsi na chodbe..vede ze zachodu na zahradu
cesty:zachod zahrada
vydis:
>> |: jdi(zahrada).
Jsi na zahrade..ptaci zpivaji, slunce sviti...
cesty:chodba
vydis:
>> |:
>> |: poloz(papir).
Polozil jsi papir
Vrhla se na tebe diva duchodkyne z holi a utloukla te ze slovy
"Takhle znecistovat zivotni prostredi! Kam se ten svet riti!"
Sice jste zemrel ale nevadi...vlastne sjte hru vyhral
Yes
výheň