% Adventure % Matthijs Melissen (0423165) % % Inleveropdracht bij het vak Logisch Programmeren % Februari 2005 % Bonuswaardige extra's: % - Tijd opgedeeld in uren en minuten, apart predicaat voor het aftrekken van tijd, controle van tijd mbv recursie % - Het is mogelijk de opdracht 'ga terug' te geven % - Prachtig ascii-art monster ;) %dynamische variabelen :- dynamic hier/1, bezit/1, in/2, uren/1, minuten/1, inloggenWerkt/0, deur/2, geopend/1, vorige/1. % HOOFDLUS % spel/0 % Dit is de hoofdlus spel :- intro, % vertelt de introductie repeat, % slaagt altijd tijd, % houdt de tijd bij kijk, % Schrijft elke keer waar je bent monster, % verschijnt op onvoorspelbare momenten ontvangcommando(C), % je geeft een commando nl, % extra lege regel puzzel(C), % een extra taak uitvoeren(C), % voert het commando uit eindconditie(C). % slaagt als je dood bent % of als je zelf 'stop' roept % of als je hebt gewonnen % intro/0 % Schrijft informatie over de huidige toestand naar het scherm intro :- nl, nl, nl, write('ADVENTURE'), nl, nl, write('Gemaakt door Matthijs Melissen'), nl, nl, write('Inleveropdracht bij het vak Logisch Programmeren,'), nl, write('Onderdeel van de studie Cognitieve Kunstmatige Intelligentie.'), nl, nl, write('Februari 2005'), nl, nl, write('+++++++++++++++++++++++++++++++++++'), nl, nl, write('Je bent op de faculteit Wijsbegeerte van de Universiteit Utrecht.'), nl, write('Je moet op zoek naar het geheime metrostation dat zich hier op de Uithof bevindt...'), nl. % tijd/0 % Trekt bij elke actie tijd af tijd :- minderTijd(3), !. % monster/0 % Laat af en toe een monster langs komen om tijd af te trekken monster :- R is random(10), R is 1, nl, teken(monster), write('Het facultaire monster komt langs! Je bent twintig minuten kwijt.'), nl, minderTijd(20), !. monster. % uitvoeren/1 % uitvoeren(+Commando) voert een bepaald commando uit uitvoeren(Commando) :- Commando, !. % eindconditie/1 % eindconditie(+Commando) slaagt als de tijd op is, er om stoppen gevraagd is of het spel afgelopen is eindconditie(_) :- gewonnen(spel), write('Gefeliciteerd!'), nl, write('Je hebt het metrostation gevonden!'), nl, write('Het spel is nu afgelopen.'), nl. eindconditie(stop) :- write('Weet je het zeker [ja. / nee.]?'), read('ja'), write('Je hebt opgegeven.'), nl. eindconditie(_) :- uren(Uren), minuten(Minuten), Uren >= 18, Minuten >= 0, write('De universiteit gaat nu sluiten.'), nl, write('Je hebt verloren.'), nl. % BESCHRIJVING VAN DE WERELD % beschrijving/2 % beschrijving(?Ruimte, ?Beschrijving) bevat de Beschrijving per Ruimte % beschrijving van de ruimtes beschrijving('de computerzaal', 'Je kunt niet inloggen, want je hebt te veel schrijfruimte gebruikt.') :- \+ inloggenWerkt. beschrijving('de computerzaal', 'Je kunt nu inloggen.') :- inloggenWerkt. beschrijving('de onderwijsadministratie', 'Vreemd genoeg is er niemand aanwezig. In de hoek staat een archiefkast. Die zou je misschien open kunnen maken?') :- \+ geopend('de archiefkast'). beschrijving('de onderwijsadministratie', 'Er is nog steeds niemand... De archiefkast staat nu halfopen.') :- geopend('de archiefkast'). beschrijving('het trapgat', 'Aan het einde van de trap zit een deur. De deur is dicht.') :- \+ geopend('de deur'). beschrijving('het trapgat', 'Aan het einde van de trap staat een open deur.') :- geopend('de deur'). beschrijving('de gang', 'Hier staat onder andere een kopieerapparaat.'). beschrijving('de eerste etage', 'Deze gang loopt door heel het bestuursgebouw heen.'). beschrijving('hocki', 'Dit is het thuishonk van Incognito, de studievereniging CKI.'). beschrijving('de helpdesk', 'De helpdesk helpt je als je problemen met de wijsbegeerte-computers hebt.'). beschrijving('de binnenplaats', 'Je staat nu tussen het Ruppert-gebouw en het Bestuursgebouw.'). beschrijving('ruppert', 'Onder de trap naar de eerste verdieping loopt een klein trapje omlaag. Er zitten ventilatieluiken in de grond...'). beschrijving('de rode zaal', 'Dit is de kleine collegezaal in het Ruppert-gebouw. Als je bij de ingang van de zaal staat voel je de grond trillen. Misschien rijdt de metro wel hieronder?'). % gewonnen/1 % gewonnen(spel) slaagt als je op het metrostation bent gewonnen(spel) :- hier('het metrostation'). % verbonden/2 % verbonden(?Kamer1, ?Kamer2) kijkt of twee kamers verbonden zijn verbonden(X, Y) :- deur(X, Y). verbonden(X, Y) :- deur(Y, X). % kijk/0 Beschrijft je omgeving kijk :- nl, hier(Plaats), write('Je bent in '), write(Plaats), write('.'), nl, beschrijving(Plaats, Beschrijving), write(Beschrijving), nl, fail. kijk :- write('Je kan naar de volgende ruimtes: '), nl, hier(Plaats), verbonden(Plaats, AnderePlaats), write(' '), write(AnderePlaats), nl, fail. kijk :- hier(Plaats), ( in(_, Plaats) -> write('Hier ligt: '), nl, in(Ding, Plaats), write(' '), write(Ding), nl, fail ). kijk :- ( bezit(_) -> write('Je hebt: '), nl, bezit(Ding), write(' '), write(Ding), nl, fail ). kijk :- nl, uren(Uren), minuten(Minuten), write('Het is nu '), write(Uren), write(':'), ( Minuten < 10 -> write('0') ; write('') ), write(Minuten), write(' uur.'), nl, write('-----------------------------------'), nl, !. kijk. % PUZZELS % puzzel/1 % puzzel(+Commando) kijkt of je een commando wel uit kan voeren of dat eerst iets anders vereist is. puzzel(ga_naar(Hier)) :- hier(Hier), write('Daar ben je al!'), nl, !, fail. puzzel(ga_naar(Nieuw)) :- hier(Oud), \+ verbonden(Oud, Nieuw), write('Ik kan helemaal niet naar '), write(Nieuw), write(' toe vanaf hier!'), nl, !, fail. puzzel(ga_naar('de onderwijsadministratie')) :- \+ geopend('de onderwijsadministratie'), write('De onderwijsadministratie is gesloten. Probeer het later nog eens!'), nl, !, fail. puzzel(ga_naar(Nieuw)) :- hier(Oud), verbonden(Oud, Nieuw), ( \+ Nieuw = 'de onderwijsadministratie' ; geopend('de onderwijsadministratie') ), ( \+ Nieuw = 'het trapgat' ; geopend('de onderwijsadministratie') ), !. puzzel(pak(Ding)) :- hier(Plaats), \+ in(Ding, Plaats), write('Ik zie '), write(Ding), write(' hier helemaal niet.'), nl, !, fail. puzzel(pak(Ding)) :- hier(Plaats), in(Ding, Plaats), !. puzzel(leg(Ding)) :- \+ bezit(Ding), write('Je hebt '), write(Ding), write(' helemaal niet.'), nl, !, fail. puzzel(leg(Ding)) :- bezit(Ding), !. puzzel(log_in) :- \+ hier('de computerzaal'), write('Er is geen computer om op in te loggen hier...'), nl, !, fail. puzzel(log_in) :- hier('de computerzaal'), \+ inloggenWerkt, write('Nee, het inloggen werkt echt niet!'), nl, !, fail. puzzel(log_in) :- hier('de computerzaal'), inloggenWerkt, !. puzzel(open('de archiefkast')) :- hier('de onderwijsadministratie'), !. puzzel(open('de deur')) :- hier('het trapgat'), !. puzzel(open(Iets)) :- write('Er is hier geen '), write(Iets), write(' die je kan openen!'), nl, !, fail. puzzel(open('de deur')) :- hier('het trapgat'), \+ bezit('de sleutel'), write('Dat kan niet, de deur zit op slot en je hebt de sleutel niet!'), nl, !, fail. puzzel(open(Iets)) :- ( hier('de onderwijsadministratie'), Iets = 'de archiefkast' ; hier('het trapgat'), bezit('de sleutel'), Iets = 'de deur' ), !. puzzel(ga(terug)). puzzel(stop). % GRAPHICS % teken/1 schrijft wat ascii-art naar het scherm % teken(+Naam) teken(monster) :- nl, write(' ^^^^^'), nl, write(' |0 0|'), nl, write(' \\_P_/'), nl, write(' / \\'), nl, write(' | |'), nl. % COMMANDO'S % ga_naar/1 % ga_naar(+Richting) laat je door de wereld verplaatsen ga_naar(Nieuw) :- hier(Oud), vorige(NogOuder), retract(hier(Oud)), assert(hier(Nieuw)), retract(vorige(NogOuder)), assert(vorige(Oud)), ( Nieuw = 'hocki' -> ( \+ geopend('de onderwijsadministratie') -> write('Je bent wel anderhalf uur op hocki blijven hangen.'), nl, write('Een voordeel: de onderwijsadministratie is nu wel open.'), nl, assert(geopend('de onderwijsadministratie')), minderTijd(90) ; true ) ; ( Nieuw = 'de helpdesk', \+ inloggenWerkt -> write('De helpdesk verhelpt je probleem. Je kunt weer inloggen.'), nl, assert(inloggenWerkt) ; true ) ). % ga/1 % ga(terug) laat je teruggaan ga(terug) :- hier(Oud), vorige(NogOuder), retract(hier(Oud)), assert(hier(NogOuder)), retract(vorige(NogOuder)), assert(vorige(Oud)). % pak/1 % pak(+Ding) laat je iets oppakken % pak een voorwerp op pak(Ding) :- hier(Plaats), retract(in(Ding, Plaats)), assert(bezit(Ding)), ( Ding = 'het smobo' -> write('Je weet nu hoe je bij de heldesk moet komen!'), nl, write('De helpdesk bevindt zich op de eerste etage.'), nl, assert(deur('eerste etage', 'de helpdesk')) ). % leg/1 % leg(+Ding) laat je iets neerleggen leg(Ding) :- hier(Plaats), retract(bezit(Ding)), assert(in(Ding, Plaats)), ( Ding = 'het smobo' -> write('Nu weet je niet meer precies waar de helpdesk is...'), nl, retract(deur('eerste etage', 'de helpdesk')) ). % log_in % log_in laat je inloggen op de computer log_in :- write('Bezig met inloggen...'), nl, write('47669'), nl, write('Inloggen voltooid'). % open/1 % open(+Ding) laat je iets openen open('de deur') :- assert(deur('het trapgat', 'het metrostation')), write('Je ziet het metrostation nu!'), nl, nl, !. open('de archiefkast') :- write('Wat is de code van het cijferslot? Sluit af met een punt.'), nl, read(Invoer), nl, ( Invoer = 47669 -> nl, write('De archiefkast is geopend! Er zit een sleutel in!'), nl, assert(bezit('de sleutel')), assert(geopend('de archiefkast')) ; write('De code is onjuist.'), nl ), !. % stop/0 % stop beeindigd het spel. stop. % TIJDSWIJZIGING % minderTijd/1 % minderTijd(+MinderMinuten) maakt de tijd MinderMinuten later minderTijd(MinderMinuten) :- minuten(OudeMinuten), NieuweMinuten is OudeMinuten + MinderMinuten, retract(minuten(OudeMinuten)), assert(minuten(NieuweMinuten)), corrigeerTijd, !. % corrigeerTijd/0 % zorgt dat het aantal minuten tussen de 0 en de 60 komt corrigeerTijd :- minuten(OudeMinuten), OudeMinuten < 60, OudeMinuten >= 0, !. corrigeerTijd :- uren(OudeUren), minuten(OudeMinuten), OudeMinuten >= 60, NieuweMinuten is OudeMinuten - 60, NieuweUren is OudeUren + 1, retract(uren(OudeUren)), retract(minuten(OudeMinuten)), assert(uren(NieuweUren)), assert(minuten(NieuweMinuten)), corrigeerTijd, !. corrigeerTijd :- uren(OudeUren), minuten(OudeMinuten), OudeMinuten < 0, NieuweMinuten is OudeMinuten + 60, NieuweUren is OudeUren - 1, retract(uren(OudeUren)), retract(minuten(OudeMinuten)), assert(uren(NieuweUren)), assert(minuten(NieuweMinuten)), corrigeerTijd, !. % DCG % ontvangcommando/1 % ontvangcommando(+Commando) zet een Nederlandse zin om in een Commando voor prolog. ontvangcommando(Prolog) :- write('> '), % de prompt lees_tekst_naar_lijst(Lijst), % leest een rij characters van toetsenbord % en bouwt een lijst Lijst van woorden vertaal(Lijst,Prolog). % gebruikt een DCG die een categorie % vp/1 bevat om Lijst te vertalen naar % een Prolog query Prolog vertaal(Lijst,Query) :- vp(Query,Lijst,[]), !. vertaal(_,_) :- R is random(2), ( R is 0 -> write('Daar heb je echt helemaal niets aan.'), nl, fail ; ( R is 1 -> write('Waarom zou je dat willen?'), nl, fail ) ), fail. vp(V) --> v(X^V, transitief), np(X). vp(V) --> v(V, intransitief). vp(V) --> v(X^V, Soort), pp(X, Soort). vp(V) --> v(Adv^V, metbijwoord), adv(Adv). pp(X, Soort) --> prep(naar, Soort), np(X). np(X) --> det, n(X). v(X^pak(X), transitief) --> [pak]. v(X^leg(X), transitief) --> [leg]. v(X^open(X), transitief) --> [open]. v(X^ga_naar(X), richting) --> [ga]. v(A^ga(A), metbijwoord) --> [ga]. v(A^ga(A), metbijwoord) --> [ga]. v(log_in, intransitief) --> [log,in]. v(stop, intransitief) --> [stop]. adv(terug) --> [terug]. det --> []. det --> [de]. det --> [het]. prep(naar, richting) --> [naar]. n('het smobo') --> [smobo]. n('de computerzaal') --> [computerzaal]. n('de gang') --> [gang]. n('de onderwijsadministratie') --> [onderwijsadministratie]. n('de binnenplaats') --> [binnenplaats]. n('de helpdesk') --> [helpdesk]. n('eerste etage') --> [eerste, etage]. n(hocki) --> [hocki]. n(ruppert) --> [ruppert]. n('de rode zaal') --> [rode,zaal]. n('het trapgat') --> [trapgat]. n('het metrostation') --> [metrostation]. n('de deur') --> [deur]. n('de archiefkast') --> [archiefkast]. n('de sleutel') --> [sleutel]. n('het kopieerapparaat') --> [kopieerapparaat]. lees_tekst_naar_lijst(L) :- % leest characters van toetsenbord, tot ENTER % negeert non-letters % kreeert lijst atomen, corresponderend met % de woorden in de input readline(T), wordlist(L,T,[]). readline(L) :- get0(Char),buildlist(Char,L). buildlist(10,[]) :- !. buildlist(Char,[Char|X]) :- get0(Char2),buildlist(Char2,X). wordlist([X|Y]) --> word(X),whitespace,wordlist(Y). wordlist([X]) --> whitespace,wordlist(X). wordlist([X]) --> word(X). wordlist([X]) --> word(X),whitespace. word(W) --> charlist(X),{name(W,X)}. charlist([X|Y]) --> chr(X),charlist(Y). charlist([X]) --> chr(X). chr(X) --> [X], {X>=48}. whitespace --> whsp,whitespace. whitespace --> whsp. whsp --> [X],{X<48}. testvp :- testvp([]). % testvp, voor debuggen % onderstaand feit zal de test laten stoppen na alle vertalingen van lengte 10 % als je het uitcomment dan zal testvp loopen testvp([_,_,_,_,_,_,_,_,_,_,_]). testvp(Input) :- vp(Prolog,Input,[]), write(Input), write(' ==> '), write(Prolog), nl, fail. testvp(L) :- testvp([_|L]). % OPSTARTEN start :- % gooi alles weg retractall(hier(_)), retractall(vorige(_)), retractall(bezit(_)), retractall(in(_,_)), retractall(uren(_)), retractall(minuten(_)), retractall(inloggenWerkt), retractall(deur(_,_)), retractall(geopend(_)), % begintijd assert(uren(15)), assert(minuten(0)), % beginpositie assert(hier('de computerzaal')), assert(vorige('de computerzaal')), % deuren assert(deur('de computerzaal', 'de gang')), assert(deur('de gang', 'de onderwijsadministratie')), assert(deur('de gang', 'de binnenplaats')), assert(deur('de gang', 'eerste etage')), assert(deur('eerste etage', 'hocki')), assert(deur('de binnenplaats', ruppert)), assert(deur(ruppert, 'de rode zaal')), assert(deur(ruppert, 'het trapgat')), % beginpositie van voorwerpen assert(in('het smobo', hocki)), spel. :- start.