W umpus orld SLI

advertisement
Wumpus World
SLI 370
Eksamen Hsten 1999
av
Gyrd Brndeland
og
Linn Iren Humlekjr.
Universitetet i Oslo
Institutt for lingvistiske fag
1999-11-29
Innhold
1 En logisk agent
1.1 Konseptet \Wumpus World" . . . . . . . . . . . . .
1.1.1 Spillet |en beskrivelse . . . . . . . . . . . .
1.1.2 Agenten . . . . . . . . . . . . . . . . . . . .
1.1.3 Omgivelsen . . . . . . . . . . . . . . . . . .
1.1.4 Kunnskapsbasen . . . . . . . . . . . . . . .
1.2 Strategier . . . . . . . . . . . . . . . . . . . . . . .
1.2.1 Skestrategi . . . . . . . . . . . . . . . . . .
1.2.2 Prioritering mellom ulike m
al . . . . . . . .
1.3 Spr
aket, slutningsmekanismen og Prolog . . . . . .
1.3.1 Begrensninger i utsagnslogikk . . . . . . . .
1.3.2 Begrensninger i predikatlogikk . . . . . . . .
1.3.3 Skille mellom fakta og deres representasjon .
1.3.4 Forskjeller mellom Prolog og predikatlogikk
1.3.5 Problemer med eksistens . . . . . . . . . . .
1.3.6 Problemer med negasjon . . . . . . . . . . .
1.3.7 Eektivisering av sk . . . . . . . . . . . . .
1.4 Aktuelle utvidelser av applikasjonen . . . . . . . . .
1.4.1 Omgivelsen . . . . . . . . . . . . . . . . . .
1.4.2 Agenten . . . . . . . . . . . . . . . . . . . .
1.4.3 Kunnskapsbasen . . . . . . . . . . . . . . .
2 Teknisk dokumentasjon
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
Getting started . . . . . . . . . . . . . . . . . . .
Defsystem . . . . . . . . . . . . . . . . . . . . . .
Agenten . . . . . . . . . . . . . . . . . . . . . . .
Omgivelsen . . . . . . . . . . . . . . . . . . . . .
Kunnskapsbasen . . . . . . . . . . . . . . . . . . .
Typer og metoder . . . . . . . . . . . . . . . . . .
Kommunikasjon mellom agenten, KB og brukeren
Miscellaneous . . . . . . . . . . . . . . . . . . . .
Eektivisering og optimering . . . . . . . . . . . .
2.9.1 Eektiviserings-tiltak . . . . . . . . . . . .
2.9.2 Optimerings-tiltak . . . . . . . . . . . . .
3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
7
8
9
10
10
10
11
12
12
13
13
13
14
15
16
16
16
17
19
19
20
20
21
21
22
22
22
23
23
24
A Wumpus World |kildekode
A.1 wumpus-types.cl
A.2 kb-agent.lisp . . .
A.3 system.cl . . . . .
A.4 optimizing.cl . . .
A.5 actions.cl . . . . .
A.6 action-value.cl . .
A.7 wumpus-rules.cl .
A.8 new-values.cl . .
A.9 chicke-value.cl . .
A.10 abstractions.cl . .
A.11 utilities.cl . . . .
A.12 init.cl . . . . . . .
A.13 pretty-printing.cl
A.14 gold-digger.cl . .
A.15 prolog-till.cl . . .
A.16 onprolog3.lisp . .
B Kjringseksempel
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
27
28
29
30
31
34
38
44
45
48
50
52
53
56
57
60
67
Innledning
Jeg gir stort sett faen i rom, men jeg har problemer med tid.
|Erlend Loe
Dette dokumentet inneholder dokumentasjon for spillet Wumpus World, og er en del av SLI
370 eksamen, hsten 1999, ved Universitetet i Oslo. Dokumentasjonen er delt i to: kapittel
1 inneholder en beskrivelese av spillet og strategien, samt begrunnelse av ulike valg vi har
foretatt, kapittel 2 er en teknisk rapport av spillet.
Valg av oppgave
M
alet med oppgaven er a lage en agent som ved hjelp av logisk resonnering kan lse oppgaver
i en forholdsvis enkel kunstig omgivelse. Vi har valgt a bruke Wumpus-verden, omtalt i del
III, kapittel 6 - 10, i Russel og Norvig (1995). Vi valgte Wumpus-verden, blant annet for a ha
en omgivelse hvor det ville vre gjennomfrbart a implementere en logisk slutningsmekanisme
som kunne fungere, i lpet av overskuelig tid.
nske om en enkel omgivelse I startfasen samarbeidet vi med Karl Otto Dviken
Ekle om Robo Rally. Dette spillet er mer omfattende en Wumpus-verden, b
ade med hensyn
p
a selve implementasjonen av brettet og kompleksiteten av omgivelsen. Blant annet kan
omgivelsen til Robo rally-spillet sies a vre ikke-deterministisk, fordi nye tilstander i verden
ikke bare er bestemt av foreg
aende tilstand pluss agentens handling, men ogs
a av endringer
i verden og andre agenters trekk. Vi skiftet derfor til et enklere spill, hvor implementasjonen
av brettet og metodene rundt det er forholdsvis enkel, slik at vi kunne vie mer av arbeidet
til a bygge opp en kunnskapsbase for en agent og f
a en slutningsmekanisme til a fungere.
Vurdering av applikasjonen
Vi har oppn
add m
alsetningen om a lage en agent som bruker et logisk spr
ak til a resonnere
for a lse oppgaver i Wumpus-verden. Vi har laget et minimum av setninger i Prolog, som er
tilstrekkelig for a f
a agenten til a fungere. B
ade oppgaven som agenten skal lse og omgivelsen
er svrt enkel. En kunne tenke seg utvidelser for a gi agenten ere oppgaver, og endringer
i omgivelsen som ville gjre den mer kompleks, men dette ville krevd en mer omfattende
kunnskapsbase.
Kunnskapen agenten har er nok til a lse oppgaven i noen instansieringer av Wumpusverden, men ikke i alle. Den strste utfordringen har ligget i a bygge opp en kunnskapsbase
5
med setninger om verden som er generelle nok til a kunne gjelde i alle tilfeller. Et sprsm
al i
arbeidet med a lage en logisk agent, er hvor mange fakta om en omgivelse det er mulig a fange
inn med logiske setninger. Dette har vist seg vanskeligere enn vi trodde p
a forh
and. Selv for
en s
a enkel omgivelse som Wumpus-verden, en det problematisk a gi agenten kategoriske
imperativ om allmene gode eller d
arlige handlinger. Dersom en skulle prve a fange inn alle
mulige situasjoner en kunne tenke seg (hvis det i det hele tatt er mulig), ville ske jobben blitt
veldig stor. En mer komplett skestrateg, kan derfor g
a p
a bekostning av tidskompleksitet
og romkompleksitet ved skingen. Det at vi mter denne typen problemer i en s
a enkel
omgivelse som Wumpus-verden, indikerer at en mer kompleks omgivelse hvor ikke alle fakta
er kjent, trolig vil kreve en noe mer eksibel h
andtering av hva som er rett og galt. For mer
om dette, se 1.4.2.
Problemer under utvikling Underveis i arbeidet sttte vi pa problemer med hensyn
p
a hvilket logisk spr
ak vi skulle velge til a representere kunnskap, og sprsm
al om hvor
detaljert vi klarer a beskrive verden ved hjelp av logikk, se 1.3. Videre hadde vi en del
tekniske problemer med optimering av koden, for a f
a den til a kjre i Allegro CL 2.
Hvordan behandle ting som kunne vrt gjort annerledes Vi har gjort ere valg
b
ade med hensyn til den fysiske implementasjonen av spillet, og med hensyn p
a valg av
spr
ak for a representere kunnskap. Valgene har ofte vrt styrt av praktiske hensyn, det vi si
vi har valgt de metodene vi har f
att til a fungere. Men vi mener de valgene vi har foretatt
kan forsvares i forhold til beskrivelsen av oppgaven. Der vi har foretatt valg har vi forskt a
begrunne dette i dokumentasjonen.
Kapittel 1
En logisk agent
1.1 Konseptet \Wumpus World"
1.1.1 Spillet |en beskrivelse
Spillet best
ar av en kunnskapsbasert agent og en kunstig omgivelse. Det er ingen fysiske
spillere, kun en virtuell (agenten) og en statisk spiller (Wumpus). Wumpus World er et lukket
informasjons-spill der agenten ikke har informasjon om spill-brettet (omgivelsen). Agenten
har et hovedmaal og ere delm
al, som hun forsker a oppn
a ved et uinformert sk, det vil
si agenten kan skille m
al-tilstand fra ikke-m
altilstand, men har ikke informasjon om hvor
mange steg som m
a til eller hva kostnaden er, for a komme i m
al. Dette gir forvrig et s
akalt
horisont-problem, som innebrer at agenten ikke kan forutsi eller kaste blikk over spill-brettet
for a planlegge neste trekk. Trekkene eller de handlingene som agenten utfrer bestemmes
ikke fr etter at agenten har sanset, og informasjonen om de sansede persepsjonene er lagt
til kunnskapsbasen (agentens hukommelse). Det er to farer som truer agentens sikkerhet.
Agenten kan falle i endelse brnner, og hun kan stte p
a en Wumpus. I begge tilfellene vil
agenten d p
a stedet.
Hvert brett genereres tilfeldig og pnget er at agenten skal kunne klare oppgaven sin p
a en
tilfredsstillende m
ate innenfor et sett av ulike brett. For a f
a til dette m
a reglene i kunnskapsbasen vre b
ade generelle og kompakte. Vi nsker a beskrive trekk ved omgivelsen
som gjelder i alle mulige permutasjoner av Wumpus-verden med enkle og konsise regler. En
viktig utfordring ved a lage en "god" spiller i Wumpus-verden ligger derfor i oppbyggingen
av kunnskapsbasen
De beste trekkene som agenten foretar er bestemt ut fra strategien og vurdert etter verdien
p
a konsekvensen av handlingen.
1.1.2 Agenten
En m
albasert agent har de samme egenskapene som en en modell-basert agent i tillegg til at
den har viten om m
al og den har evner til a konstruere en indre representasjon av verdenen
eller omgivelsen den benner seg i. Denne indre representasjonen bruker agenten til a handle.
Den setter seg m
al og forsker a oppn
a disse. Agenten i Wumpus World er en m
al-basert
7
agent. Hun har en indre representasjonen av persepsjoner, som hun bruker til a utfre og
valuere handlinger. P
a grun av dette kan vi si at hun til en viss utstrekning er autonom (jfr
AI s 49). Til tross for at hun famler rundt i mrke, kan hun via sine sanser, vite om det det
er gull i det rommet hun er eller om det er en Wumpus eller et sort hull i umiddelbar nrhet.
Hun resonnerer seg frem, via kunnskapsbasen, til hva som til enhver tid er delm
al og hva det
overordnede (hoved-) m
alet er. Hovedm
alet er a nne gullet for s
a
a komme seg til tilbake
til *start*, levende og p
a kortest mulig antall skritt. Siden agenten vet om hun brer med
seg gullet, er hun i stand til a utfre fruktbare handlinger i forhold til de delm
alene som er
satt n
ar agenten benner seg i en gitt situasjon.
Agentens sentrale bestanddeler er en kunnskapsbase og en slutningsmekanisme. Kunnskapsbasen inneholder setninger, som representerer fakta om verden. Agenten har et logisk spr
ak
som den bruker til a representere fakta om verden, og en fysikalistisk del av sensorer som
mottar input fra omgivelsen. Etterhvert som agenten g
ar rundt p
a brettet, oppdaterer den
kunnskapsbasen med de erfaringene den gjr seg. Ved hjelp av regler og erfaringer skal agenten kunne slutte seg til hvor det er trygt/ikke trygt a g
a, hvor det er lurt a g
a osv.
1.1.3 Omgivelsen
Kort beskrevet best
ar omgivelsen til Wumpus-verden av en hule, representert som et brett
med 4x4 ruter, omgitt av vegger. Et monster og en klump med gull plasseres tilfeldig p
a
brettet, men aldri i startposisjonen. I tillegg kan hver rute med sannsynlighet 0.2 vre en
bunnls brnn. Agenten starter i rute (1 1), i henhold til det kartesiske koordinatsystemet
(se ogs
a avsnittet om koordinater, seksjon 2.8). En mer utfrlig beskrivelse av omgivelsen
for Wumpus-spillet gis p
a side 154 - 155 i "Articial Intelligence".
P
a side 46 i "Ariticial Intelligence" gis en oversikt over noen ulike omgivelser og deres
karakteristikker. Vi gir her en kort oppsummering av de
viktigste distinksjonene:
* Aksessibelt versus inaksessibelt, som g
ar p
a hvorvidt den komplette tilstanden til en
omgivelse er tilgjengelig fra agentens sesorer eller ikke.
* Determisitisk versus ikke-deterministisk. Det vil si hvorvidt neste tilstand av omgivelsen er bestemt kun av foreg
aende tilstand samt agentens handling, eller ikke.
* Episodisk versus ikke-episodisk. I en episodisk omgivelse er agentens erfaringshistorie
delt opp i "episoder" som best
ar av sensor-input for agenten + en handling. Kvaliteten
av handlingene avhenger kun av episoden selv, og agenten trenger dermed ikke tenke
framover.
* Statisk versus dynamisk. En omgivelse sies a vre dynamisk hvis den kan endre seg
samtidig med at agenten resonnerer, ellers er den statisk. En kan ogs
a ha semidynamiske
omgivelser hvor omgivelsen ikke endrer seg, men kvaliteten p
a responsen endres.
* Diskret versus kontinuerlig. En diskret omgivelse kjennetegnes ved at det nnes et endelig antall utvetydige beskrivelser av mulige handlinger og sensor-input. En omgivelse
er kontinuerlig n
ar uforutsatte, ikke-denerte fenomener plutselig oppst
ar.
Hvilken type omgivelse man velger har betydning for utforming av agenten. Det nnes ere
typer av omgivelser og hvor kompleks den er avhenger av dens karakteristika. V
ar versjon
av Wumpus-verden er en av de enklere omgivelsene man kan lage. Den er riktignok ikke
aksessibel; agenten har kun oversikt over den ruten hun benner seg i. Av andre mulige
karakteristikker passer imidlertid Wumpus-verden med de enklere variantene. Omgivelsen er
deterministisk - det er kun agenten som ytter p
a seg. Derfor vil de trekkene ved verden
som agenten oppdager holde seg stabile igjennom et helt spill. V
ar Wumpus-verden er ogs
a
episodisk, statisk og diskret.
En kan argumentere for at det ikke nnes et endelig antall regler om trekk ved verden. Det
vil sannsynligvis alltid vre mulig a utvide kunnskapsbasen med regler om sammenhenger i
verden og nytten av ulike handlinger for a gjre agenten enda bedre, slik at omgivelsen ikke
kan kalles hundre prosent deterministisk. Poenget er imidlertid at det kun nnes et endelig
antall lovlige handlinger (g
a fram, snu til venstre, snu til hyre, skyt, grip og klatr) og mulige
sensor-input (lukt, vind, glitring, skrik og bump). Slik vi tolker Russel/Norvig er det dette
som avgjr om verden er diskret.
1.1.4 Kunnskapsbasen
Kunnskapsbasen best
ar av
* Konkrete ting som gull
* Hendelse, ting i tid og rom
* Historieforlp
* Valuerte handlinger
Oppbygging av kunnskapsbasen
Kunnskapsbasen er delt i tre. Filene wumpus-rules inneholder setninger om sammenhenger i
verden. Filene action-value og new-values inneholder nytteregler, hvor en verdi knyttes til en
handling, som agenten bruker p
a sin vei til a oppn
a m
alene. N
ar agenten har funnet gull m
a
hun skifte strategi, og da m
a handlingene evalueres p
a en annen m
ate enn tidligere. Hvordan
man skal f
a til dette kan gjres p
a ere m
ater, for eksempel ved a la hver regel sjekke om
agenten holder gullet eller ikke. Vi valgte isteden a legge setningene om verdier i to atskilte
baser, og bytte base n
ar agenten har gullet. P
a den m
aten begrenser vi sket og tydeliggjr
at det dreier seg om ulike m
al/delm
al.
Hvordan representere kunnskap
Et sentralt problem i oppbygging av kunnskapsbasen er hvorvidt en klarer a lage setninger
som til sammen beskriver alle mulige sammenhenger i verden, og hvordan kunnskapen skal
representeres. Dette henger blant annet sammen med hvor utrykksfult spr
aket en velger er,
og vi redegjr grundigere for problemer rundt dette i 1.3.2.
I valg av ontologi har vi i stor grad fulgt oppskriften i AI . En vanskelighet var hvordan vi
skulle skille mellom situasjoner, eller hvordan vi skulle representere tid. I eksemplene fra AI
flger det med en situasjonsparameter, s, i setningene om verden. Vi tolket denne som en
tidsparameter, t, som kes med 1 for hver ny situasjon.
En utfordring i oppbygging av kb ligger i a uttrykke kompakte regler, det vil si regler som er
generelle nok til a kunne brukes i ere situasjoner. Etter hvert som vi lager nye regler, kan
vi da bruke de grunnleggende reglene vi allerede har laget. V
ar kunnskapsbase er spesialisert
til a h
andtere fakta om klassen av mulige Wumpus-verdener.
1.2 Strategier
1.2.1 Skestrategi
Vi tar her med re kriterier som vi vil vurdere v
art valg av skestrategi etter.
* Kompletthet; vil agenten kunne oppn
a de m
alsetningene den har satt seg for alle brett
som genereres?
* Tidskompleksitet; vil m
alet n
as i endelig tid?
* Romkompleksitet; vil det vre nok minne slik at agenten kommer i m
al?
* Optimalitet; nner agenten den beste og letteste vei a komme i m
al?
I henhod til kriteriene over, kan vi si at v
ar skestrategi ikke oppfyller kompletthets-kriteriet,
det vil si at agenten ikke er garantert a komme i m
al selv om det nnes en mulig vei til gullet.
Problemet er at agenten ikke har tilgang p
a hele sannheten om omgivelsen. Det vil alltid
vre sprsm
al hvor det ikke nnes kategoriske svar og agenten m
a derfor av og til handle i
usikkerhet. For eksempel vil en agent ofte ikke vre i stand til a avgjre hvilken rute av to
som er en brnn. Tidskompleksitet er tilfredsstillbar. Agenten bruker litt tid, men er i stand
til a n
a m
alet, eller gi opp hvis den ikke nner en sikker vei, i endelig tid og unng
a uendelige
looper. N
ar det gjelder romkompleksiteten har vi nok minne slik som systemet ser ut n
a.
Men ved en utvidelse av kunnskapsbasen vil vi kunne f
a problemer. V
ar algoritme oppfyller
ikke kriteriet om optimalt sk, fordi den ikke garanterer den beste og strake veien til m
alet.
Dette skyldes blant annet at agenten utfrer et s
akalt blindt-sk.
1.2.2 Prioritering mellom ulike m
al
Et m
al for agenten er a nne gullet. Et annet m
al er a overleve, det vil si bevege seg i trygge
omr
ader. Et tredje m
al g
ar p
a eektivitet. Vi nsker at agenten ikke skal surre for mye rundt,
men nne gullet raskest mulig. Vi har forskt a sikre at agenten flger denne strategien ved a
formulere at det er best a g
a til trygge uutforskede steder, nest best a g
a til trygge utforskete
steder og tredje best a g
a til utrygge steder. Agenten skal under ingen omstendighet g
a til
steder den vet er ddelige.
Hvor bra agenten lser oppgaven vil avhenge av hvor godt reglene klarer a fange inn det en
nsker a oppn
a. Vi har valgt et minimum av nytteregler som skal til for at agenten klarer
a lse oppgaven i noen av verdenene. Men vi kunne sannsynligvis klart a f
a agenten til a
lse oppgaven raskere eller klart a h
andtere ere verdener ved a utvide reglene, eller kanskje
nmasket dem enn
a mer.
Nytteverdien av en handling er som nevnt bestemt ut fra hvordan vi vurderer konsekvensen
av handlingen. Vi har forskt a holde oss til en vurdering av de beste handlingene (great)
til a vre m
alrettet adferd, de nest beste (good) til a vre trygge handlinger n
ar agenten er
p
a jakt efter gull og m
alrettede handlinger n
ar gullet er funnet og agenten er p
a vei hjem. I
dette ligger ogs
a en del av arsaken til at en ny l blir lastet inn i hukommelsen. \Medium"
handlinger er de aksjonene som er safe, men ikke ndvendigvis i riktig retning. \Risky"
handlinger er handlinger hvis konsekvensene er usikre. De handlinger som medfrer dden
er de karakterisert som \deadly" handlinger.
M
alet om a nne gullet trygt vil ikke vre oppn
aelig innenfor alle typer verdener, noen
ganger kan gullet ligge nede i en brnn. Andre ganger kan det nnes en vei til gullet, men
agenten er ndt til a ta sjanser for a nne det. Dette ga problemer n
ar vi skulle denere
nytten av ulike handlinger. I utgangspunktet skal agenten snu og prve en trygg vei, hvis
veien fram er riskabel. Men hva er riktig a gjre n
ar alle bomsikre veier er utprvd? Vi har
kjrt to agenter med ulik strategi; en \feig" som setter sin egen sikkerhet hyere enn m
alet
om a nne gullet, og en som begynner a ta sjanser n
ar de sikre veiene er utprvd. Den
dristige agenten klarer a nne gullet litt oftere enn den \feige", men s
a har ogs
a den dristige
agenten en hyere ddsrate. Ikke overraskende scoret den \feige" agenten gjennomsnittlig
hyere enn den "dristige" da straen for a d er mye strre en gevinsten ved a nne gullet.
For sjekke ulike strategier opp mot hverandre kan man lage statistikk over hvor bra en agent
gjr det med funksjonen make-statistics. Den kalles med antall ganger man vil at agenten skal
gjennomfre spillet, og en strategi.
Mulige forbedringer av skestrategien
Som nevnt vil agentens yteevne avhenge av hvor godt reglene klarer a fange inn det en
nsker a oppn
a. Vi har ikke gjort noen grundige underskelser av hvilke nytteverdier som vil
fungere best, utover hva vi tror er mest hensiktsmessig, og hva vi har sett fungerer i bestemte
situasjoner, og s
a denere nytteverdiene en gang for alle. Vi vil kunne f
a agenten v
ar til a lse
oppgaven i et strre antall Wumpus-verdener hvis vi jobbet mer med reglene. En m
ate kunne
vrt a tillatt s
akalt stokastisk sk, hvor agenten av og til kunne velge handlinger som ikke
var denert som optimale. Etter a ha kjrt ere agenter gjennom en serie spill kunne en sett
hva som fungerte best, og g
att inn og justert standarden i henhold til hva man hadde funnet
ut. Slik reglene er n
a, kan agenten noen ganger velge tilfeldig mellom jevngode handlinger,
men det er ikke lagt opp til at den skal lre av det.
1.3 Spr
aket, slutningsmekanismen og Prolog
Et viktig sprsm
al i arbeidet med a lage en kunnskapsbasert agent er hvilket spr
ak en skal
velge, for a representere kunnskapen til agenten. Hvilket logisk spr
ak en velger har betydning
for hvilken type slutningsmekanisme en nsker a bruke.
1.3.1 Begrensninger i utsagnslogikk
Vi laget frst en agent som bruker utsagnslogisk spr
ak til a representere kunnskap om verden
og regler i utsagnslogikk til a resonnere om mulige handlinger (funksjonen gold-digger i len
gold-digger.cl). Til dette brukte vi en slutningsmekanisme i utsagnslogikk hentet fra AI. Ved
hjelp av denne klarte agenten a gjre noen f
a trekk i Wumpus-verden. Men det viste seg fort
at utsagnslogikk ikke er uttrykksfullt nok til a h
andtere selv en s
a enkel omgivelse. Fordi
det utsagsnslogiske spr
aket kun best
ar av enkle utsagn, vil en kunnskapsbase med regler om
mulige posisjoner i alle mulige permutasjoner av Wumpus-verden blir alt for stor til a vre
praktisk h
andterlig.
N
ar utsagnslogikken viste seg a ikke strekke til, nsket vi i utgangspunktet a utvide til det
predikatlogiske spr
aket, som i tillegg til utsagn kan representere ting og relasjoner mellom
ting (for mer om representasjon i predikatlogikk, se kapittel 7 i AI). Videre nsket vi a bruke
resolusjon til a resonnere om verden (for mer om bevismetoder i predikatlogikk se kapittel 9 i
AI). Russel/Norvig har laget en skisse for en teorembeviser ved hjelp av resolusjon tilsvarende
OTTER, s. 311 i AI. Men vi kk ikke denne funksjonen til a virke og kom fram til at det ville
bli for mye arbeid og skulle lage en teorembeviser fra grunnen av p
a egen h
and. Vi valgte
derfor a bruke Prolog som spr
ak og slutningsmekanisme istedenfor regulr predikatlogikk.
Prolog tilsvarer ikke helt predikatlogikk, verken i spr
aket eller i slutningsmekanismen, men
vi fant at Prolog allikevel ville tjene v
are form
al for en agent i Wumpus-verden. Prologs
mekanisme for mnsterpassing og unikasjon passer bra til v
art form
al, da sking etter hvilke
handlinger agenten skal foreta skjer ved mnsterpassing og unikasjon. Agenten sender inn
et sprsm
al av typen handling(?variabel tid) til kunnskapsbasen og f
ar tilbake en handling
bundet til ?variabel. N
ar vi hadde valgt Prolog som slutningsmekanisme ga ogs
a det logiske
spr
aket seg selv.
1.3.2 Begrensninger i predikatlogikk
Et problem med bruke predikatlogikk eller Prolog til beskrive en verden hvor ikke alle fakta
er kjent, er at predikatlogikk ikke gir noe rom for tvil. Ting er enten sant eller usant. Dette kan
bli for rigid, selv for en s
a enkel omgivelse som Wumpus-verden. Noe som er bra i situasjon n,
gitt visse kriterier, er ikke ndvendigvis bra i situasjon m gitt de samme kriteriene. Dermed
blir det vanskelig a gi generelle regler, som er sanne eller gale i alle situasjoner. For eksempel
beskrev vi frst regler som sa: pkt 1: Det er bra a g
a fram, hvis agenten ikke har gullet, ruten
rett fram er trygg og hun ikke har beskt den fr. Hvis ruten foran er utrygg er det bra a
snu. Disse reglene holder i mange situasjoner. Men i noen tilfeller kan reglene f
a agentene til
a g
a fram og tilbake mellom to utrygge ruter. I enkelte av spillene er agenten ndt til a ta
sjanser for a klare a nne gullet. Men hvordan skal skille mellom situasjoner n
ar det er lurt a
snu, og n
ar det er p
a tide a ta en sjanse? Vi lste dette ved a si at agenten skulle ta en sjanse,
eventuelt gi seg hvis ruten den siste beskte var blitt beskt mer enn en gang. Sannsynligvis
vil vi kunne nne ere spesielle situasjoner som krever egne regler. Vi kan risikere a f
a en
veldig stor kunnskapsbase dersom vi skal fange inn alle mulige situasjoner, og da nrmer vi
oss problemet ved utsagnslogikk. For en agent i Wumpus-verden er disse problemene til a
leve med, men for mer komplekse omgivelser, hvor alle fakta ikke er tilgjengelig for agenten,
vil en kanskje trenge en noe mer eksibel h
andtering av hva som er rett og galt.
1.3.3 Skille mellom fakta og deres representasjon
Vi skiller mellom den fysiske omgivelsen og agentens representasjon av fakta om verden.
Representasjon av fakta tar det logiske spr
aket og slutningsmekanismen, Prolog, seg av.
Metodene og brettet tilhrer den fysiske delen av verden. Funksjonen implement-action i la
actions.cl operer i grenseland mellom det logiske og det fysiske spr
aket; den f
ar en handling
fra slutningsmekanismen og oppdaterer den fysiske verden. Funksjonen tell i la prolog-till.cl
oppdaterer agentens representasjon av verden.
1.3.4 Forskjeller mellom Prolog og predikatlogikk
Programmering i Prolog ligner ganske mye p
a predikatlogikk b
ade i syntaks og bevismetode.
Et prolog-system er basert p
a en teorembeviser for Horn-klausuler som bruker prinsippet om
resolusjon. Men Prolog gir ikke full predikatlogikk. Blant annet har negasjon en litt annen
betydning i Prolog enn i predikatlogikk. Prolog likestiller det at noe ikke kan bevises med at
det er usant, fordi det antar at den vet alt som er sant. Videre kan en ikke uttrykke disjunksjon helt p
a samme m
ate som i predikatlogikk Prolog har ogs
a problemer med a representere
eksistenskvantorer. Valg av Prolog som slutningsmekanisme legger fringer p
a syntaksen,
fordi Prolog bare aksepterer Horn-klausuler. Hver setning enten er en atomr setning eller
en implikasjon uten negerte antecedencer og med en atomr konsekvent. Klausuler i Prolog skrives dessuten "motsatt vei" av predikatlogikk, med konsekventen p
a venstre side av
implikasjonspila. I oppbyggingen av reglene har vi i stor grad basert oss p
a forslagene i AI,
s. 203 - 211. Mange av reglene var noks
a greie a oversette, ved a snu p
a dem. Men enkelte
regler var vanskelig a oversette p
a grunn av Prologs problemer med a uttrykke negasjon og
eksistens, slik de flgende eksemplene viser.
1.3.5 Problemer med eksistens
Siden eksistenskvantorene ikke lar seg oversette direkte, m
atte vi i uttrykk med eksistens,
nne et tilnrmet uttrykk som best mulig bevarte meningen i det opprinnelige uttrykket.
Et eksempel er regelen som skal hjelpe agenten
til aW
slutte hvor monsteret er
V
l 1; sS melly (l 1)
l 2At(W umpus; l 2; s)
(l2 = l1 Adj acent(l1; l2))))
Denne lar seg ikke oversette direkte til prolog, men vi klarer likevel a uttrykke det vi nsker.
Vi vil at agenten skal kunne resonnere seg fram til at monsteret er i en bestemt rute, enten
fordi hun har beskt naborutene og fant at de luktet vondt, eller fordi hun ut i fra tidligere
erfaringer kan slutte at det bare er en mulig rute monsteret kan vre p
a. Dette gjorde vi
ved a dele opp i tre regler:
8
)9
(<- (not-wumpus ?location)
(and (adjacent ?location ?neighbour)
(visited ?neighbour)
(not (smelly ?neighbour))))
ii
(<- (at 'Wumpus ?location) (not (wall ?location))
(and (adjacent ?location ?neighbour)
(smelly ?neighbour)
(and (locationtoward ?neighbour 0 ?L1)
(or (lisp (equal ?L1 ?location))
(wall ?L1)
(not-wumpus ?L1)))
(and (locationtoward ?neighbour 90 ?L2)
(or (lisp (equal ?L2 ?location))
(wall ?L2)
(not-wumpus ?L2)))
(and (locationtoward ?neighbour 180 ?L3)
(or (lisp (equal ?L3 ?location))
(wall ?L3)
(not-wumpus ?L3)))
(and (locationtoward ?neighbour 270 ?L4)
(or (lisp (equal ?L4 ?location))
(wall ?L4)
(not-wumpus ?L4)))) (cut))
iii
(<- (at 'Wumpus ?location) (not (wall ?location))
(and
(and (locationtoward ?location 0 ?l1)
(or (smelly ?l1)
(wall ?l1)))
(and (locationtoward ?location 90 ?l2)
(or (smelly ?l2)
(wall ?l2)))
(and (locationtoward ?location 180 ?l3)
(or (smelly ?l3)
(wall ?l3)))
(and (locationtoward ?location 270 ?l4)
(or (smelly ?l4)
(wall ?l4)))))
Regel ii sier at flgende kriterier m
a vre oppfylt for a kunne slutte at Wumpusen er i
en bestemt rute: Det nnes en naborute som lukter vondt og alle naborutene til naboruta
(naboene til naboen), er enten den samme som ruta vi spr etter, en vegg, eller vi vet at det
ikke er en Wumpus der.
1.3.6 Problemer med negasjon
Prolog kan ikke representere at noe ikke er tilfelle. Det vil si du kan ikke ha en regel av
typen:
(<- (not (at (wumpus, l1, t))))
Denne mangelen ga ogs
a noe problemer da vi skulle uttrykke reglene om hvor Wumpusen
er. Som nevnt nsket vi i regel ii a ha med som kriterium at monsteret ikke skulle vre p
a
en rute. Men hvis vi skrev noe ala:
at(wumpus, l, result(a, s)):- cond1
.
.
not(at(wumpus, neighnours(neighbour))).
kk vi en selvrefererende regel som ble g
aende i evig lkke. For a kunne uttykke at monsteret
ikke var et bestemt sted laget vi derfor regelen:
(<- (not-wumpus ?location)
(and (adjacent ?location ?neighbour)
(visited ?neighbour)
(not (smelly ?neighbour))))
For mer om forholdet mellom Prolog og predikatlogikk, se Clocksin og Mellish (1987) (s. 221
- 242), Bratko (1990) (s. 63, 64), Norvig (1992) (s. 465 - 468), Russel og Norvig (1995) (s.
304 - 308).
1.3.7 Eektivisering av sk
For
a f
a skingen i Prolog til
a g
a litt fortere har vi gjort noen grep som begrenser skerommet.
I noen av reglene som vi vet bare ang
ar et bestemt individ som for eksempel denne:
(<- (at 'dumpy ?location ?s1)
(or (and (is ?s0 (- ?s1 1))
(action 'forward ?s0)
(locationahead 'dumpy ?location ?s0)
(not (wall ?location)))
(and (is ?s0 (- ?s1 1))
(action ?a ?s0)
(not (lisp (eq ?a 'forward)))
(at 'dumpy ?location ?s0))))
Her har vi valgt a la regelen snakke om konstanten 'dumpy (navnet p
a agenten), i stedet
for en mer generell variant, som gjelder for alle. Dette er ogs
a fordi det er forskjellige regler
for hvorvidt 'dumpy er et sted og hvorvidt 'wumpus eller en brnn er et sted. Med denne
avgrensingen slipper vi at programmet prver a instansiere alle regler som begynner med at,
n
ar den skal nne ut om agenten er et sted.
Videre har vi valgt a oppdatere lokalisering og orientering til agenten etter hver handling i
spill-lkka, med funksjonen tell-rst i la prolog-till.cl. N
ar vi ikke gjorde det ville Prolog
gjr det samme skene hver eneste gang. N
ar den skulle nne ut om en handling var lur i tid
n, ville den frst ske seg ned til hvor agenten var i tid 0 og deretter instansiere tilstander for
hvert tidspunkt fram til tid n. En annen eektivisering er funksjonen push-rule, som pusher
reglene frst i listen slik at prolog ikke trenger a lete seg ned til bunnen for a f
a tak i siste
regel som er lagt til regelbasen.
1.4 Aktuelle utvidelser av applikasjonen
Spillet Wumpus World er s
a og si blottet for Ægheter ala det a kunne g
a til nye niv
a (level)
eller ke vanskelighetsgraden og sette nye delm
al. Slike ideer kan man f.eks hente fra et
hvilket som helst Play Station-spill. Vi nner det irrelevant a utvide spillet p
a slike m
ater.
Derfor inneholder denne seksjonen forslag til vidreutvikling av metoder og teknikker.
1.4.1 Omgivelsen
N
ar vi har f
att slutningsmekanismen p
a plass i denne enkle omgivelsen, kan en se for seg
mulige utvidelser av omgivelsen, som vil gjre den mer kompleks. En ser ganske fort at utvidelser i omgivelsen ofte vil kreve endringer i agentens kunnskapsbase og slutningsmekansime.
For eksempel kan en forholdsvis enkel m
ate a gjre omgivelsen ikke-deterministisk p
a vre
a la monsteret Wumpus, ytte p
a seg. Persepsjon av lukt sammen med tidligere erfaringer
ville da ikke vre nok til a slutte hvor Wumpusen er, og agenten f
ar behov for a kunne si
noe om sannsyligheten for at Wumpusen er p
a ulike steder. I en ikke-episodisk omgivelse
vil agenten m
atte ta hensyn til hele sitt handlingsforlp og persepsjonsregister. Den har da
mulighet til a planlegge. En ikke-episodisk utvidelse av Wumpus World vil g
a p
a bekostning
av rom-kompleksiteten til skestrategien. Hadde vi tillatt et ukjent antall monstre bevege seg
i rommet, ville agenten f
att en ikke-statisk verden a forholde seg til. Neste avsnitt omhandler
blant annet konsekvenser en ikke-statisk omgivelse ville ha f
att for agenten.
1.4.2 Agenten
En relevant utvidelse av agent-type ville vre a lage en desisjons-agent. En desisjons-agent
er en agent som foretar beregninger av sannsynligheter og benytter utility-teori. Dette innebrer at agenten n
a m
a oppdatere, kontinuerlig, sannsynligheten for hvordan den tror
verden (omgivelsen) er. Med en ikke-statisk omgivelse (som vi f
ar n
ar f.eks monstret beveger
seg rundt i omgivelsen) vil en desisjons-agent kunne planlegge og dermed oppdatere forbindelsen mellom handlinger og sannynligheter for hvordan verden blir. En slik agent vil velge
handlinger med maksimal nytte.
H
andtering av usikkerhet
Som nevnt f
ar vi ikke til a lage en komplett skestrategi for agenten, fordi den ikke har
tilgang til hele sannheten om omgivelsen. Det vil alltid vre sprsm
al hvor det ikke nnes
kategoriske svar og agenten m
a derfor av og til handle i usikkerhet. I de este tilfeller i
Wumpus-verden vil sannsynligheten for at noe er tilfelle vre 50/50, s
a en trenger ikke en
egen teori for a h
andtere usikkerhet. Men innen et omr
ade som medisin, vil predikatlogikk
alene ikke strekke til som slutningsmekansime.
Hvis vi skulle utvidet agenten til a h
andtere usikkerhet ville det f
a konsekvenser for valg av
logisk spr
ak, og hvordan vi representerer agentens kunnskap. Vi nsker ikke lenger setninger
som sier at noe enten er sant eller galt.
Sannsynlighetsteori er en metode for a knytte usikkerhet/sannsynlighet til regelbaserte systemer. Innenfor sannsynlighetsteori snakker en om b
ade prinsipiell uvitenhet; en kjenner ikke
alle fakta om et domene, og usikkerhet som skyldes "latskap"; det er for mye arbeid og liste
opp hele mengden av antecedencer og konsekvenser som trengs for a sikre en regel uten unntak. Sannsynlighet gir en m
ate a summere usikkerheten som skyldes latskap og uvitenhet,
(s. 417 AI).
I henhold til sannsynlighetsteori kan en agent regne ut sannsynligheten av noe gitt noe
annet, forutsatt at den kjenner til fakta om hvor ofte noe forekommer og hvor ofte noe annet
forekommer sammen med noe. Dette kalles betinget sannsynlighet.
P(A|B) = p(A ^ B)/p(B)
Kommunikasjon med andre agenter
Det er ogs
a mulig a lage en kommunikasjons-agent som snakker (spr og forteller) med andre
agenter via hverandres kunnskapsbaser.
1.4.3 Kunnskapsbasen
En kunne tenke seg at kunnskapsbasen ble gjort mer generell til
a h
andtere liknende verdener,
ved en enda nere inndeling av fakta. For eksempel kunne man denere en egen kategori av
hindere som agenten skal unng
a, hvor Wumpus og brnn begge er objekter av typen hinder.
Kapittel 2
Teknisk dokumentasjon
2.1 Getting started
Vi hadde problemer med ske-teknikkene som gjorde et Franz Allegro CL til tider ikke
klarte a kjre hele spillet helt igjennom. Det viste seg imidlertid at Macintosh CL klarte a
h
andtere disse problemene, slik at hvis du kjrer systemet p
a MCL vil du vre garantert
at applikasjonen ikke krsjer. Derfor vil du nedenfor nne tre beskrivelser for a kunne kjre
applikasjonen fra plattformermene Unix, Microsoft Windows og Macintosh. (Se seksjon 2.9.2
for nrmere beskrivelse av optimerings-tiltakene vi far foretatt.) Vi anbefaler at systemet
testes ut i Windows- og Mac-implementasjonene fordi agenten tross alt er, til tider, i stand
til a n
a delm
al som a nne gullet, og man f
ar muligheten til a teste ut defsystem, som er en
implementasjons-avhengig feature.
P
a disketten nner du en mappe for hver av de tre plattformene. Felles for alle applikasjonene
er at system-len system.cl inneholder de riktige path'ene (dirigert til disketten), og er den
eneste la som trener a load'es manuelt.
Kjring via Allegro CL p
a Dec Vi starter systemet ved a bruke riktig pakke. Dette
kan man gjre med top-level kommadoen
:package user
Deretter loader du la system.cl. Kaller du n
a p
a (compile-wumpus) i listener vil systemet
kompilere alle lene angitt i defsystem (se seksjon 2.2), og alle de kompilerte lene vil loades.
Systemet er n
a klar for a dumpes. Dette gjr du med funksjonen (dumplisp :name "dumpy.dxl"). Fra n
a av kan du starte lispen med et Wumpus World-image: lisp -I dumpy.dxl.
Dermed holder det n
a med a kalle p
a (wumpus-world) for a starte spillet. (Se seksjon 1.3.7
for nrmere beskrivelse av image.)
Kjring via Allegro CL Windows Kjrer du systemet fra ACL for Microsoft Windows,
laster du inn len system.cl, kaller funksjonen [ved frste gangs kjring av spillet] (comilewumpus) og deretter holder det med a kalle (wumpus-world). Vr oppmerksom p
a at n
ar
du kompilerer lene for frste gang vil Allegro entre debugger. Du skal da dobbelt-klikke p
a
den verste linjen som sier \set the function denition of name compiler:tail-call-self-mergeswitch anyway." for a kompilere alle lene.
19
N
ar du f
ar feilmelingen \ Error: Stack overow (signal 1000) [condition type: synchronousoperating-system-signal]" kan du godt forske a tvinge lispen til vidre kjring, ved a dobbeltklikke p
a \continue computation". Vi har funnet at det g
ar an a presse lispen til a fortsette
sket. I len kjrings-ex.txt i \Wumpus-Windows"-mappen nner du et kjringseksempel der
agenten oppn
ar hovedm
alet.
Kjring via Macintosh CL Filene kompileres med compile-wumpus, og spillet startes
med wumpus-world i la system.cl, som du nner p
a disketten i mappa Wumpu-system.
2.2 Defsystem
Allegro Common Lisp har en innebygget feature kalt defsystem. Dette er en feature som gir
utviklere av store applikasjoner meget god kontroll p
a kompilering og load'ing av ler. Man
kan bl.a dirigere ler til a kompileres eller/og loades parallelt eller sekvesielt. I tillegg gir
defsystem oss mulighet til a se/analysere hvilke ler som avhenger av andre. Vi har brukt
defsystem for a ha kontroll med kompilering og loading av lene vi bruker i spillet. Filene er
gruppert og tillagt navn med relevans for den modulene de tilhrer. P
a denne m
aten unng
ar
vi problemer som at en funksjon ikke kan kompileres fordi den bruker en annen funksjon som
enn
a ikke er kompilert. I len \system.cl" nner du defsystem til Wumpus World. Funksjonen
compile-wumpus utfrer de ndvendige kallene for at lene i applikasjonen skal kompileres og
loades. Vi ser at dette gjres p
a en lett og elegant m
ate.1 Tross alle fordelene er defsystem et
system som gir oss kompabilitets-problemer siden applikasjonen forelpig kun er gjennomkjrbar p
a MCL og ikke i Allegro (se seksjon 2.1).
2.3 Agenten
Vi har tre viktige kontroll-funksjoner rundt agentens hjerne; selve agenten-funksjonen kgbagent, update-agent og implement-action. Disse funksjonene nner du i hhv kb-agent.lisp,
utilities.cl og actions.cl. Vi betrakter den frste funksjonen i tillegg til kunnskapsbasen og
slutningemekanismen (prolog) som agentens hjerne.Update-agent og implement-action benner seg i grenselandet mellom agentens hjerne og den fysiske verden siden dette er funksjoner
som hhv tar i mot persepsjoner fra agentens sensorer i tillegg til a legge disse agent-objektets
slot'er, og trigger agentens forsk p
a handling. Update-agent kalles i oppstart-funksjonen
wumpus-world og i implement-action . I start-funksjonen kalles den fordi agenten har et behov for a bli oppdatert i det hun blir \fdt" inn i spill-brettet (omgivelsen). Hun trenger
a oppdatere sine persepsjoner (alts
a setf'er persepsjonsvektoren til a inneholde persepsjonspredikatene som benner seg p
a ruten), i tillegg til
a vite om det er en Wumpus p
a start-ruten.
Er Wumpus p
a start-ruten skal ikke agenten g
a vidre, men i stedet skal livet termineres.
Update-agent setter tilstanden til agenten.
Dog ser det ut til at det er en bug i Franz' ACL fordi det virker som at funksjonen compile-system
ignorerer key-word'et :silent, og dette pa tross av at det ikke er noen andre \key word argumenter" som
overskriver :silent t.
1
Funksjonen kgb-agent er selve agenten som har sine del- og hovedm
al. Det er en loop i denne
funksjonen som g
ar til agenten n
ar sitt hovedm
al, gir opp letingen eller dr. I innmaten
av kgb-agent er det funksjonen make-percept-sentence-prol som oppdaterer kunnskapsbasen
med persepsjonene agenten sanser. Deretter fanger agenten opp forslag til handling returnert
av funksjonen make-action-query. Vi betrakter kodesnutten (setf action (make-action-query
time)) som en del av viljen til agenten. make-action-sentence forteller kunnskapsbasen om
handlingen som foretas. S
a funksjonen kgb-agent kan betraktes som den delen av hjernen
som legger ting til hukommelsen og henter ut beslutningene om valg av handling.
Funksjonen implement-action er det leddet som knytter verden, de faktiske handlingene
og fysiske lover, og agenten sammen. Den er, som sagt, en slags grenseland-funksjon fordi
den tar inn agentens vilje som argument, mens den b
ade sender impulser som stimulerer
aksjonene (metodene) og formidler informasjon til brukeren (observatren) om hva som skjer.
Vi betrakter metodene som fenomener i verden som avgjr om handlingene kan utfres eller
ikke. Vi tenkte frst p
a metodene som handlinger utfrt av eektorer, men fant at det ikke
gir mening a snakke om eektorer siden det er en virtuell agent vi har med a gjre, og det bl.a
er de fysiske lover og fenomener i verden som avgjr om en fysisk handling er gjennomfrbar.
S
a funksjonen trigger handlingene, og disse handlingene ligger i omgivelsen, utenfor agenten.
Lrebokas presentasjon av agenter er at de returner en handling etter a ha r
adfrt seg med
kunnskapsbasen. V
ar agent returnerer ikke en handling man den kaller en funksjon som tar
seg av de tingene. Dermed vil v
ar agent loope til den dr, gir opp eller n
ar m
alet. Dette er
fordi vi betrakter agenten som en person som selv styrer sin kontinuitet av handlinger. For oss
s
a ser det ut som at forfatterne mener at agenten skal settes igang av noen utenforstande,
noe annet enn sin egen vilje. xme
2.4 Omgivelsen
Den visuelle representasjonen for oss som observatrer er spill-brettet. Det er funksjonen
print-board som tar seg av utskrivingenn av brettet. I len pretty-printing.cl nner du de
hjelpefunksjonene som print-board bruker. Alle rutene er objekter som kan inneholde predikater (sanseinntrykk) og andre objekter som monster og agenter. Print-board henter alts
a ut
nye verdier av objektene for hver gang den blir kalt. For en nrmere beskrivelse av typene
nner du i seksjon 2.6
2.5 Kunnskapsbasen
Til a representere kunnskaper om verden, bruker vi Paul Grahams implementasjon av Prolog
i Lisp, fra Graham (1994) /refsubsec:di-prlog-pred. Vi har modisert noe p
a koden med ider
fra Norvig, for a kunne bruke noen hjelpefunksjoner og for a kunne samle alle instansieringer
av variable i et sk, i en liste. Makroen \<-", som du nner i len on-lisp/prolog-till.cl, legger
reglene i regelbasen *rules* (se dokumentasjonen til Paul Graham \On Lisp" for nrmere
beskrivelse).
2.6 Typer og metoder
Vi har valgt CLOS fordi det ligger nrt a tenke p
a (eller kategorisere) ting som ulike typer
av objekter. Filen wumpus-types.cl inneholder de globale variablene og alle klassene som er
opprettet i systemet. Vi har en klasse for objektene som benner seg i spillet, gold og arrow
(som er subklasser av object), vi har en agent klasse med player og wumpus som subklasser.
Square er en klasse med wall som subklasse og en open-square som subklasser square, med
subsubklasse pit.
Filen actions.cl inneholder de metodene p
a klassene som spillet gjr bruk av. Disse metodene er faktiske handlinger som agenten utfrer. Metodene trigges av dispatch-funksjonen
implement-action.
2.7 Kommunikasjon mellom agenten, KB og brukeren
Det er to funksjoner som kommuniserer med brukeren; det ene er agent-funksjonen selv: kgbagent, som forteller hva hun sanser, og den andre er implement-action som holder brukeren
oppdatert p
a hva som skjer i tillegg til a trigge handlings-metodene og skrive ut spill-brettet.
2.8 Miscellaneous
Koordinatsystemene. Representasjonen av koordinatene til spill-brettet i array'et og
i kunnskapsbasen er forskjellige. Aref bruker det kartesiske koordinatsystemet. Spill-brettet
representeres ogs
a som et 2-dimensjonalt kartesisk koordinatsystem, men skiller seg fra arrayrepresentasjonen ved at det 2-dimensjonale array'et er rotert 90 grader \clockwise". Derfor
er f.eks koordinatene til agentens startposisjon, *start*, i array'et listen '(4 1), mens den
samme posisjonen i det visuelle spill-brettet '(1 1). Dette er mulig fordi vi har et skille
mellom det fysiske og logiske spr
aket (jfr seksjon ??). Vi valgte a ikke abstrahere aref for a
bruke den rotasjonen vi er vant med (dvs x-aksen peker mot st og y-aksen peker nordover,
hvis koordinatsystem vi har brukt under den visuelle representasjonen brettet) selv om vi
lett kunne gjort det med mappings-funksjoner som ser ut ala:
(defun map-to-cartesian (i s)
"returns the cartesian cooridinates by rotate
the coord-system 90 degrees ``counter-clockwise''"
(let ((x s)
(y (- (+ 1 *row-length*) i)))
(list x y)))
(defun map-from-cartesian (x y)
"returns the coordinates according to Common Lisp arrays,
rotating the cartesian 90 degrees clockwise"
(let ((i (- (+ 1 *row-length*) y))
(s x))
(list i s)))
Statistikk. I len stat-lisp.cl inneholder funksjonen make-statistics og infrastruktur for to
agenter ulike kvaliteter. Man kan for morroskyld se hvilken av disse agenten som gjor det
best p
a spill-brettet tatt i betrakting deres ulike egenskaper.
2.9 Eektivisering og optimering
Prolog-implementasjon i Lisp vi benytter som slutningsmekanisme bruker ganske lang tid.
Muligens ville Prolog-kompilatoren til Norvig i PAIP vrt raskere. Denne har vi imidlertid
heller ikke f
att til a fungere. Prolog-versjonen i On Lisp brukte Line Bergem under eksamen
i SLI 330, s
a denne visste vi fungerte. Prolog-versjonen til Graham best
ar av mindre og kode
enn Norvigs, og den er derfor lettere og forst
a. Iflge Graham (On Lisp, s. 346 og 347) er
hans versjon en kompilator p
a et vis, den oversetter regler til Lisp funksjoner Og Common
Lisp oversetter til maskinkode. Men den er ikke en full Prolog-kompilator, fordi kompilering
gjres av en Lisp-kompilator som ser etter optimering av Lisp og ikke av Prolog.
Da vi tok i bruk Paul Grahams kode fra On Lisp visste vi ikke at det var ndvendig
a optimere
rekursive funksjoner til hale-rekursive. Vi kk noen feil-meldinger fra ACL om at stacken
var full. Underveis i debug-ingen foretok vi en rekke optimerings- og eektiviseringstiltak
for a kunne forst
a hva den overnevnte feilen l
a i, og hva vi kunne gjre for a overvinne slike
feil. Det viste seg at et kall p
a (gc) ikke ville hjelpe siden garbage-collector ikke opererer
p
a stack'en, men p
a heap'en. Derfor var en kning av heap'en ikke noen lsning for v
art
stack-problem. Vi har likevel kt heap-size med en million bytes for kjring p
a Dec-stasjon.
Vi testet systemet p
a Macintosh og fant at MCL (Macintosh Common LISP) ikke har de
problemer med stack overow som ACL har fordi MCL alltid optimerer hale-kall. Vi har sett
at MCL gc'er hele tiden. (Se seksjon 2.1 for beskrivelse av hvordan applikasjonen kjres p
a
Macintosh).
I de flgende avsnittene skal vi ta for oss de eektiviserings- og optimerings-tiltakene vi har
foretatt i Wumpus World. Seksjon 1.3.7 viser vi hvordan vi bygger et image for unix-versjonen
av applikasjonen, og seksjon 2.9.2 omhandler v
are optimerings-forsk.
2.9.1 Eektiviserings-tiltak
Eektivisering p
a DEC. Et av eektiviserings-tiltakene vi har foretatt er a bygge et
image for systemet. N
ar et slik image er bygget, kan man dumpe lisp'en. Dette gjr at n
ar
vi starter systemet med det allerede dumpede imaget, slipper vi a kompilere og loade alle de
lene systemet bruker.
Med fuksjonen (som du ogs
a nner i len system.cl;
(build-lisp-image "wumpus.dxl"
:include-compiler t
:c-heap-size 167108864
:lisp-heap-size 167108864)
bygger vi et image "wumpus.dxl" med kt heap-size b
ade c-heap'en og lisp-heap'en. Utfrer
vi en (dumplisp :name "dumpy.cl") etter at systemets kompilerte ler er loadet, slipper vi a
loade og kompilere ler ved neste oppstart av systemet. Vi kaller da p
a lisp'en med lisp: lisp
-I dumpy.dxl
Eektivisering p
a MAC og Windows Ved a kompilere lene og laste inn disse vil
systemet kjre raskere enn n
ar man kjrer kilde-len fordi i siste tilfelle vil interpreteren
oppfre seg som den aldri har sett funksjonene fr.
2.9.2 Optimerings-tiltak
Optimering av hale-rekursive kall Vi hadde store problemer med a fa Allegro Common
Lisp til a kjre spillet v
art. Programmet knelte allerede n
ar agenten hadde gjort svrt f
a
handliner p
a grunn av flgende melding
Error: Stack overflow (signal 1000)
[condition type: synchronous-operating-system-signal]
Vi skjnte at stacken ikke ble poppet, men visste ikke hvorfor. Ved grundigere lesning i On
Lisp-boken til Graham (s. 396), fant vi at kontinuasjonsmakrne, som brukes i hans Lispimplementasjon av Prolog, avhenger sterkt av optimalisering av hale-kall, for at det ikke skal
g
a tom for plass p
a stacken. Vi gjorde en del forsk p
a
a f
a Allegro til a optimere hale-kall, og
nedenfor beskriver vi optimerings-funksjonene. Funksjonene comp:tail-call-self-merge-switch
og comp:tail-call-non-self-merge-switch vil, i flge ACL-manualen, optimerimere rekursive
funksjoner til halerekursive (under gitte omstendigheter), som vi vet er mye mer eektive
n
ar antall rekursive kall blir veldig stort.
Funsjonene som her setf'es nner du i system-len
(setf comp:tail-call-self-merge-switch
#'(lambda (safety speed debug space)
(declaim (optimize (safety 1)
(speed 3)
(debug 1)
(space 3))))
comp:tail-call-non-self-merge-switch
#'(lambda (safety speed debug space)
(declaim (optimize (safety 1)
(speed 3)
(debug 1)
(space 3)))))
Mye arbeid skulle til for a f
a koden til a kjre, men etter at vi fant funksjonen peepholeoptimize-switch, og skrudde den p
a var agenten i stand til a g
a opptil 11 steg, og dette ser
ut til a vre avhengig av belastningen lispen utsettes for n
ar et sk etter beste handling m
a
ta i betraktning om agenten sanser noe i de ulike rommene hun beveger seg i.
comp:peephole-optimize-switch
#'(lambda (safety speed debug space)
(declaim (optimize (safety 1)
(speed 2)
(debug 1)
(space 3)))))
peephole-optimize-switch nnes i compiler-pakken og srger for at undvendige og overdige
instruksjoner fjernes.
Tillegg A
Wumpus World |kildekode
A.1 wumpus-types.cl
;; ---------------------- globale variable ---------------------------(defvar *board* nil)
(defparameter *start* '(4 1))
(defconstant *row-length* 4)
;; ---------------------- klasser og objekter -------------------------(defclass object ()
((name :accessor name :initarg :obj-name :initform nil)))
(defclass gold (object)
((name :accessor name :initarg :obj-name :initform "gold")
(predicate :accessor predicate :initform 'glitter)))
(defclass arrow (object)
((name :accessor name :initarg :obj-name :initform "arrow")))
(defclass agent ()
((name :accessor name :initarg :ag-name :initform nil)
(alive :accessor alive :initform t)))
(defclass player (agent)
((facing :accessor facing :initform 'east)
(possesions :accessor possesions
:initform (list (make-instance 'arrow)))
(percepts :accessor percepts
:initform (make-array 5 :initial-element 'none))))
(defclass wumpus (agent)
27
((name :accessor name :initform "wumpus")))
(defclass square () ())
(defclass wall (square) ())
(defclass open-square (square)
((agents :accessor agents :initarg sq-agents :initform nil)
(contents :accessor contents :initarg sq-contents :initform nil)
(predicates :accessor predicates :initarg sq-predicates :initform nil)))
(defclass pit (open-square) ())
A.2 kb-agent.lisp
(defun kgb-agent (agent)
"Define an action-value knowledge-based agent."
(let ((points 0)
(time 0)
(action (gensym "?")))
(loop until (or (not (alive agent))
(eq action 'give-up))
do
(let ((percept (percepts agent)))
(tell (make-percept-sentence-prol percept time))
(format t "~2& My perceptions at time ")
(display-universal-time)
(format t "are/is ~{~a, ~}
and the number in my action sequence is ~a.
I'm facing ~a. ~&"
(list-perceptions percept) time (facing agent))
(gc)
(setf action (make-action-query time))
(implement-action agent action)
(when (eq action 'grab) (change-strategy agent))
(cond ((eq action 'climb) (setf points (+ points 1000))
(loop-finish))
(:else (decf points)))
(tell (make-action-sentence `',action time))
(incf time)
(let ((location (make-location-query time))
(orientation (make-orientation-query time)))
(tell-first `(at 'dumpy ,location ,time))
(tell-first `(orientation 'dumpy ,orientation ,time)))
(when (not (alive agent)) (setf points (- points 10000))
(loop-finish)))
finally (return points))))
A.3 system.cl
(defsystem :wumpus-world
(:pretty-name "An agent killing the Wumpus"
:default-pathname #p"A:/Wumpus-Windows/"
:default-package :wumpus
:default-file-type "cl")
(:module-group "optimize"
(:serial "Wumpus-system/optimizing"))
(:serial
(:module-group "wumpus-types"
(:serial
"Wumpus-system/wumpus-types"
"Wumpus-system/kb-agent"))
(:module-group "graphics"
(:serial
"Wumpus-system/pretty-printing")
(:in-order-to (:compile)
(:compile "wumpus-types")))
(:module-group "utilities"
(:parallel
"Wumpus-system/init"
"Wumpus-system/utilities"
"Wumpus-system/abstractions"))
(:module-group "actions"
(:serial "Wumpus-system/actions"))
(:module-group "prolog-tools"
(:parallel
"onlisp/prolog-till"
"onlisp/onprolog3")
(:compile-satisfies-load t))
(:module-group "knowledge"
(:serial
"Wumpus-system/wumpus-rules"
"Wumpus-system/action-value"
"Wumpus-system/new-values"))))
(defun compile-wumpus ()
"compile-function for the Wumpus World.
Only used before dumping the image."
(compile-system :wumpus-world :silent t :recompile t))
(defun wumpus-world ()
"start function for the Wumpus World"
(setf *board* (initboard 6))
(clear-db)
(load #p"A:/Wumpus-Windows/Wumpus-system/action-value.fasl")
(load #p"A:/Wumpus-Windows/Wumpus-system/wumpus-rules.fasl")
(let* ((coord (find-in-array 'player 1 1 *row-length*))
(start-square (aref *board* (x-coord coord) (y-coord coord))))
(update-agent dumpy start-square)
(format t " ~2& [Live data follows..] ~2&")
(print-board)
(kgb-agent dumpy)))
(defun change-strategy (agent)
(let* ((coordinates (find-in-array 'player 1 1 *row-length*))
(location (aref *board* (x-coord coordinates) (y-coord coordinates))))
(if (equal *start* location)
(implement-action 'climb)
(progn
(clear-predicates 'great)
(clear-predicates 'good)
(clear-predicates 'medium)
(load #p"A:/Wumpus-Windows/Wumpus-system/new-values.fasl")))))
(defun c () (compile-wumpus))
(defun w () (wumpus-world))
;;;(show-system :wumpus-world)
A.4 optimizing.cl
(build-lisp-image "wumpus.dxl"
:include-compiler t
:c-heap-size 167108864
:lisp-heap-size 167108864)
(defpackage "wumpus-game"
(:nicknames "wumpus")
(:use "EXCL" "USER" "CLOS" "DEFSYSTEM")
(:implementation-packages "DEFSYSTEM" "USER"))
(setf comp:tail-call-self-merge-switch
#'(lambda (safety speed debug space)
(declaim (optimize (safety 1)
(speed 2)
(debug 1)
(space 3))))
comp:tail-call-non-self-merge-switch
#'(lambda (safety speed debug space)
(declaim (optimize (safety 1)
(speed 2)
(debug 1)
(space 3))))
comp:peephole-optimize-switch
#'(lambda (safety speed debug space)
(declaim (optimize (safety 1)
(speed 2)
(debug 1)
(space 3)))))
(ensure-generic-function 'comp:tail-call-self-merge-switch
:environment 'compile-time)
;;Error: Attempt to make a function definition for the name
;;compiler:tail-call-self-merge-switch.
;;This name is in the COMPILER package and defining it is
;;a violation for portable programs.
;;The package COMPILER has package-definition-lock set,
;;which causes the system to signal this violation.
;;[condition type: package-locked-error]
A.5 actions.cl
(defmethod shoot ((ag player))
(let ((arrow (find-type 'arrow (possesions ag))))
(when arrow
(setf (possesions ag) (remove arrow (possesions ag)))
(let* ((dir (facing ag))
(coord (find-in-array 'player 1 1 *row-length*))
(new-coord (next-coord dir (x-coord coord) (y-coord coord))))
(find-target ag dir (x-coord new-coord) (y-coord new-coord))))))
(defun find-target (agent dir i s)
(let ((square (aref *board* i s)))
(when (not (typep square 'wall))
(let ((monster (find-type 'wumpus (contents square)))) ;evt Wumpus
(if monster
(kill agent monster)
(let ((new-coord (next-coord dir i s)))
(find-target agent dir
(x-coord new-coord)(y-coord new-coord))))))))
(defmethod kill ((ag1 player) (ag2 wumpus))
"ag1 kills ag2 and updates the play-board "
(let* ((coord (find-in-array 'player 1 1 *row-length*))
(square (aref *board* (x-coord coord) (y-coord coord))))
(remove ag2 (contents square))
(setf (scream (percepts ag1)) 'scream)
(setf (alive ag2) nil)))
(defmethod go-forward ((ag player))
(let* ((coord (find-in-array 'player 1 1 *row-length*))
(old-square (aref *board* (x-coord coord) (y-coord coord)))
(dir (facing ag))
(next-square (next-square dir (x-coord coord) (y-coord coord))))
(unless (typep next-square 'wall)
(push ag (contents next-square))
(setf (contents old-square) (remove ag (contents old-square))))))
(defmethod go-forward ((ag player))
(let* ((coord (find-in-array 'player 1 1 *row-length*))
(dir (facing ag))
(old-square (aref *board* (x-coord coord) (y-coord coord)))
(next-square (next-square dir (x-coord coord) (y-coord coord))))
(unless (typep next-square 'wall)
(push ag (contents next-square))
(setf (contents old-square) (remove ag (contents old-square))))))
(defmethod turn-right ((ag player))
"oppdaterer agentens retning (slot'en facing) naar han roterer mot hoeyre."
(case (facing ag)
(north (setf (facing ag) 'east))
(south (setf (facing ag) 'west))
(east (setf (facing ag) 'south))
(west (setf (facing ag) 'north))))
(defmethod turn-left ((ag player))
"oppdaterer agentens retning (slot'en facing) naar han roterer mot venstre."
(case (facing ag)
(north (setf (facing ag) 'west))
(south (setf (facing ag) 'east))
(east (setf (facing ag) 'north))
(west (setf (facing ag) 'south))))
(defmethod grab ((ag player) object)
(let* ((coord (find-in-array 'player 1 1 *row-length*))
(square (aref *board* (x-coord coord) (y-coord coord)))
(obj (find-type object (contents square))))
(when obj
(push obj (possesions ag))
(setf
(contents square) (remove obj (contents square))
(predicates square) (remove (predicate obj) (predicates square))))))
(defmethod climb ((ag player))
(let ((start-square
(aref *board* (x-coord *start*) (y-coord *start*))))
(setf (contents start-square)
(remove ag (contents start-square)))
(clear-db)))
(defun implement-action (agent action)
(let* ((coord (find-in-array 'player 1 1 *row-length*))
(square (aref *board* (x-coord coord) (y-coord coord)))
(monster (find-type 'wumpus (contents square)))
(direction (facing agent))
(next-square (next-square direction (x-coord coord) (y-coord coord))))
(ccase action
(left (turn-left agent)
(format t "~& (Your agent is turning left.) ~2&")
(print-board))
(right (turn-right agent)
(format t "~& (Your agent is turning right.) ~2&")
(print-board))
(forward (format t "~& (Your agent is walking forward.) ~2&")
(cond ((member 'bump (list-perceptions (percepts agent)))
(format t " ( ..she is bumping her head onto the wall!) ~2&"))
((typep next-square 'pit)
(format t " (Your agent fell into the Pit.) ~&"))
((and monster (alive wumpus))
(format t " (Your agent is killed by Wumpi.) ~&")))
(go-forward agent)
(update-agent agent next-square)
(print-board))
(shoot (format t " ~& (Your agent is trying to shoot the Wumpus..)~%")
(if (find-type 'arrow (possesions agent))
(progn
(shoot agent)
(if (alive wumpus) (format t " (She missed.. sorry!) ~&")
(format t " (She killed it!) ~2&")))
(format t " (Sorry, she is out of arrows.) ~&"))
(print-board))
(climb (format t "~& (She is climbing out of this world..)
Congratulation! Your agent has now reached her goal.
In the new version of the game,
you can climb to the next level.
Until then, BYE! ~2&")
(climb agent)
(print-board)
(return-from implement-action))
(give-up (format t "~& Your agent is a looser! ~%"))
(grab (grab agent 'gold)
(format t " She is grabbing the gold..
Yes! Your agent has it, and is changing strategy, to go home! ~2&")
(print-board)))))
A.6 action-value.cl
;;; nytteverdier paa konsekvensen av handlingene.
;;; deadly og risky (og shoot) gjelder uansett,
;;; resten er avhengig om agenten har gull eller ikke.
(<- (risky 'forward ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (deadly 'forward ?time))
(not (ok ?ahead))) (cut))
(<- (deadly 'forward ?time) (and (at 'dumpy ?location ?time)
(loacationahead 'dumpy ?ahead ?time)
(or (pit ?ahead)
(at 'Wumpus ?ahead)
(not (dead 'Wumpus)))) (cut))
(<- (great 'shoot ?time) (and (holding 'arrow)
(at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(at 'Wumpus ?ahead)
(and (right-of 'dumpy ?location-right ?time)
(or (wall ?location-right)
(not (ok ?location-right))
(visited ?location-right)))
(and (left-of 'dumpy ?location-left ?time)
(or (wall ?location-left)
(not (ok ?location-left))
(visited ?location-left)))))
;; hvis valget staar mellom aa snu, og aa skyte aa satse paa aa treffe wumpusen,
;; er det lurest aa skyte
(<- (great 'shoot ?time) (and (holding 'arrow)
(at 'dumpy ?location ?time)
(smelly ?location)
(previously-visited 'dumpy ?prev ?pt ?time)
(entered ?prev ?pt ?ent)
(second-visit ?prev ?ent)))
;; skyte er likestilt aa snu seg, hvis agenten har kommet til et sted det lukter
(<- (medium 'shoot ?time) (and (holding 'arrow)
(at 'dumpy ?location ?time)
(smelly ?location)
(locationahead 'dumpy ?ahead ?time)
(not (visited ?ahead))))
(<- (great 'grab ?time) (and (at 'gold ?location ?time)
(not (holding 'gold))))
(<- (good 'forward ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (wall ?ahead))
(not (visited ?ahead))
(ok ?ahead)))
(<- (medium 'forward ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (wall ?ahead))
(visited ?ahead)))
(<- (medium 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (ok ?ahead))
(previously ?time ?previous-time)
(not (action 'right ?previous-time))
(not (action 'shoot ?previous-time))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))))
(<- (good 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(wall ?ahead)
(previously ?time ?previous-time)
(not (action 'right ?previous-time))
(not (action 'shoot ?previous-time))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))
(not (visited ?location-left))))
(<- (medium 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(wall ?ahead)
(previously ?time ?previous-time)
(not (action 'right ?previous-time))
(not (action 'shoot ?previous-time))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))
(visited ?location-left)))
(<- (good 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(visited ?ahead)
(previously ?time ?previous-time)
(not (action 'right ?previous-time))
(not (action 'shoot ?previous-time))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))
(not (visited ?location-left))
(ok ?location-left)))
(<- (medium 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (ok ?ahead))
(previously ?time ?previous-time)
(not (action 'left ?previous-time))
(not (action 'shoot ?previous-time))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))))
(<- (good 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(wall ?ahead)
(previously ?time ?previous-time)
(not (action 'left ?previous-time))
(not (action 'shoot ?previous-time))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))
(not (visited ?location-right))))
(<- (medium 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(wall ?ahead)
(previously ?time ?previous-time)
(not (action 'left ?previous-time))
(not (action 'shoot ?previous-time))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))
(visited ?location-right)))
(<- (good 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(visited ?ahead)
(previously ?time ?previous-time)
(not (action 'left ?previous-time))
(not (action 'shoot ?previous-time))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))
(not (visited ?location-right))
(ok ?location-right)))
(<- (good 'forward ?time) (and (at 'dumpy ?location ?time)
(risky 'forward ?time)
(previously-visited 'dumpy ?prev ?pt ?time)
(entered ?prev ?pt ?ent)
(second-visit ?prev ?ent)))
(<- (good 'give-up ?time) (and (at 'dumpy ?location ?time)
(deadly 'forward ?time)
(previously-visited 'dumpy ?prev ?pt ?time)
(entered ?prev ?pt ?ent)
(second-visit ?prev ?ent)))
A.7 wumpus-rules.cl
;;; Kunnskapsbasen
;;; fakta om Wumpus-verden
;; setning om tid
(<- (previously ?s1 ?s2) (is ?s2 (- ?s1 1)) (cut))
;;; holding, holder rede paa om 'dumpy holder et objekt til enhver tid
(<- (holding ?object) (and (at ?object ?location ?s)
(action 'grab ?s) (at 'dumpy ?location ?s)))
(<- (holding 'arrow) (not (action 'shoot _)))
;; setninger om lokalisering
(<- (at 'dumpy (1 1) 0) (cut))
(<- (orientation 'dumpy 0 0) (cut))
;;;locationtoward, finner neste rute mhp retning
(<- (locationtoward (?x ?y) 270 (?ut1 ?ut2)) (and (is ?ut1 ?x) (is ?ut2 (- ?y 1))))
(<- (locationtoward (?x ?y) 0 (?ut1 ?ut2)) (and (is ?ut1 (+ ?x 1)) (is ?ut2 ?y)))
(<- (locationtoward (?x ?y) 180 (?ut1 ?ut2))(and (is ?ut1 (- ?x 1)) (is ?ut2 ?y)))
(<- (locationtoward (?x ?y) 90 (?ut1 ?ut2)) (and (is ?ut1 ?x) (is ?ut2 (+ ?y 1))))
;;; adjacent finner omliggende ruter.
(<- (adjacent ?l1 ?l2) (locationtoward ?l1 ?o ?l2))
(<- (locationahead ?agent ?ut2 ?s) (and (at ?agent ?ut1 ?s)
(orientation ?agent ?o ?s)
(locationtoward ?ut1 ?o ?ut2)
(cut)))
(<- (wall (?x ?y)) (or (lisp (< ?x 1)) (lisp (> ?x *row-length*))
(lisp (< ?y 1)) (lisp (> ?y *row-length*))))
(<- (not-forward ?action ?s) (and (action ?action ?s)
(or (lisp (equal ?action 'left))
(lisp (equal ?action 'right))
(lisp (equal ?action 'shoot))
(lisp (equal ?action 'grab))
(lisp (equal ?action 'give-up)))))
(<- (at 'dumpy ?location ?s1) (and (action 'forward ?s0)
(is ?s1 (+ ?s0 1))
(locationahead 'dumpy ?location ?s0)
(not (wall ?location))))
(<- (at 'dumpy ?location ?s1) (and (not-forward ?action ?s0)
(is ?s1 (+ ?s0 1))
(at 'dumpy ?location ?s0)))
(<- (entered ?l ?s ?e) (at 'dumpy ?l ?s) (is ?s0 (- ?s 1))
(not (at 'dumpy ?l ?s0)) (is ?e ?s) (cut))
(<- (entered ?l ?s ?e) (is ?s0 (- ?s 1)) (entered ?l ?s0 ?e))
(<- (homewards (?x1 ?y1) (?x2 ?y2))
(and (lisp (<= ?x2 ?x1)) (lisp (<= ?y2 ?y1))))
(<- (orientation ?agent ?x 0) (cut) (fail)) ;nulltest (maa stoppe paa 0).
(<- (orientation ?agent ?o1 ?s1) (and (previously ?s1 ?s0)
(action 'left ?s0)
(orientation ?agent ?o0 ?s0)
(is ?o1 (mod (+ ?o0 90) 360))
(cut)))
(<- (orientation ?agent ?o1 ?s1) (and (previously ?s1 ?s0)
(action 'right ?s0)
(orientation ?agent ?o0 ?s0)
(is ?o1 (mod (- ?o0 90) 360))
(cut)))
(<- (orientation ?agent ?o1 ?s1) (and (previously ?s1 ?s0)
(not (action 'right ?s0))
(not (action 'left ?s0))
(orientation ?agent ?o1 ?s0)
(cut)))
(<- (left-of ?agent ?neighbour ?time)
(and (at ?agent ?location ?time)
(orientation ?agent ?degrees ?time)
(is ?degrees1 (mod (+ ?degrees 90) 360))
(locationtoward ?location ?degrees1 ?neighbour)))
(<- (right-of ?agent ?neighbour ?time)
(and (at ?agent ?location ?time)
(orientation ?agent ?degrees ?time)
(is ?degrees1 (mod (- ?degrees 90) 360))
(locationtoward ?location ?degrees1 ?neighbour)))
(<- (opposit-dir ?dir ?opp-dir) (is ?opp-dir (mod (+ ?dir 180) 360)))
(<- (back-of ?agent ?behind ?time)
(and (at ?agent ?location ?time)
(orientation ?agent ?o ?time)
(opposit-dir ?o ?opp-dir)
(locationtoward ?location ?opp-dir ?behind)))
(<- (visited ?location) (at 'dumpy ?location ?time))
(<- (visited-before ?location -1) (cut) (fail))
(<- (visited-before ?location ?time)
(is ?prev (- ?time 1))
(at 'dumpy ?location ?prev) (cut))
(<- (visited-before ?location ?time)
(is ?prev (- ?time 1))
(visited-before ?location ?prev))
;; second sier fra om en agent besker en rute for andre gang
(<- (second-visit ?location ?enter-time)
(visited-before ?location ?enter-time)
(is ?time (- ?enter-time 1))
(or (and (locationtoward ?location 0 ?l1)
(at 'dumpy ?l1 ?time)
(orientation 'dumpy 180 ?time)
(action 'forward ?time))
(and (locationtoward ?location 90 ?l1)
(at 'dumpy ?l1 ?time)
(orientation 'dumpy 270 ?time)
(action 'forward ?time))
(and (locationtoward ?location 180 ?l1)
(at 'dumpy ?l1 ?time)
(orientation 'dumpy 0 ?time)
(action 'forward ?time))
(and (locationtoward ?location 270 ?l1)
(at 'dumpy ?l1 ?time)
(orientation 'dumpy 90 ?time)
(action 'forward ?time))))
(<- (previously-visited ?agent ?location
(<- (previously-visited ?agent ?location
(previously ?time ?previous-time)
(action 'forward ?previous-time)
(at ?agent ?location ?previous-time)
(<- (previously-visited ?agent ?location
(previously ?time ?previous-time)
(previously-visited ?agent ?location
;; skjulte egenskaper ved verden
?previous-time 0) (cut) (fail))
?previous-time ?time)
(cut))
?prev ?time)
?prev ?previous-time))
(<- (smelly ?location) (and (percept ('stench _ _ _ _) ?s)
(at 'dumpy ?location ?s)
(cut)))
(<- (breezy ?location) (and (percept (_ 'breeze _ _ _) ?s)
(at 'dumpy ?location ?s)
(cut)))
(<- (glittery ?location ?s) (and (percept (_ _ 'glitter _ _) ?s)
(at 'dumpy ?location ?s)
(cut)))
(<- (bumpy ?location) (and (percept (_ _ _ 'bump _) ?s)
(at 'dumpy ?location ?s)
(cut)))
(<- (noisy ?location) (and (percept (_ _ _ _ 'scream) ?s)
(at 'dumpy ?location ?s)
(cut)))
(<- (at 'gold ?location ?s) (glittery ?location ?s))
(<- (dead 'Wumpus) (percept (_ _ _ _ 'scream) ?s))
(<- (not-wumpus ?location) (and (adjacent ?location ?neighbour)
(visited ?neighbour)
(not (smelly ?neighbour))))
;;;wumpus er i samme rute til enhver tid
(<- (at 'Wumpus ?location) (not (wall ?location))
(and (adjacent ?location ?neighbour)
(smelly ?neighbour)
(and (locationtoward ?neighbour 0 ?L1)
(or (lisp (equal ?L1 ?location))
(wall ?L1)
(not-wumpus ?L1)))
(and (locationtoward ?neighbour 90 ?L2)
(or (lisp (equal ?L2 ?location))
(wall ?L2)
(not-wumpus ?L2)))
(and (locationtoward ?neighbour 180 ?L3)
(or (lisp (equal ?L3 ?location))
(wall ?L3)
(not-wumpus ?L3)))
(and (locationtoward ?neighbour 270 ?L4)
(or (lisp (equal ?L4 ?location))
(wall ?L4)
(not-wumpus ?L4)))) (cut))
(<- (at 'Wumpus ?location) (not (wall ?location))
(and
(and (locationtoward ?location 0 ?l1)
(or (smelly ?l1)
(wall ?l1)))
(and (locationtoward ?location 90 ?l2)
(or (smelly ?l2)
(wall ?l2)))
(and (locationtoward ?location 180 ?l3)
(or (smelly ?l3)
(wall ?l3)))
(and (locationtoward ?location 270 ?l4)
(or (smelly ?l4)
(wall ?l4)))))
(<- (not-pit ?location) (and (adjacent ?location ?neighbour)
(visited ?neighbour)
(not (breezy ?neighbour))))
(<- (pit ?location) (and (adjacent ?location ?neigbour)
(breezy ?neighbour)
(and (locationtoward ?neighbour 0 ?l1)
(or (lisp (equal ?l1 ?location))
(wall ?l1)
(not-pit ?l1)))
(and (locationtoward ?neighbour 90 ?l2)
(or (lisp (equal ?l2 ?location))
(wall ?l2)
(not-pit ?l2)))
(and (locationtoward ?neighbour 180 ?l3)
(or (lisp (equal ?l3 ?location))
(wall ?l3)
(not-pit ?l3)))
(and (locationtoward ?neighbour 270 ?l4)
(or (lisp (equal ?l4 ?location))
(wall ?l4)
(not-pit ?l4)))))
(<- (pit ?location)
(and
(and (locationtoward ?location 0 ?l1)
(or (breezy ?l1)
(wall ?l1)))
(and (locationtoward ?location 90 ?l2)
(or (breezy ?l2)
(wall ?l2)))
(and (locationtoward ?location 180 ?l3)
(or (breezy ?l3)
(wall ?l3)))
(and (locationtoward ?location 270 ?l4)
(or (breezy ?l4)
(wall ?l4)))))
(<- (ok ?location) (and (not-pit ?location)
(or (not-wumpus ?location)
(dead 'Wumpus))) (cut))
(<- (ok ?location) (visited ?location))
;; denne brukes ikke
(<- (possible-dead-end ?l ?time)
(and (at 'dumpy ?l ?time)
(entered ?l ?time ?ent)
(left-of 'dumpy ?left ?ent)
(or (wall ?left)
(not (ok ?left)))
(right-of 'dumpy ?right ?ent)
(or (wall ?right)
(not (ok ?right)))
(locationahead 'dumpy ?ahead ?ent)
(or (wall ?ahead)
(not (ok ?ahead)))) (cut))
(<- (possible-dead-end ?l ?time)
(and
(at 'dumpy ?l ?time)
(previously-visited 'dumpy ?prev ?pt ?time)
(entered ?prev ?pt ?ent)
(possible-dead-end ?prev ?ent)
(is ?act-time (+ ?pt 1))
(or (and (left-of 'dumpy ?left ?act-time) (or (wall ?left) (visited ?left))
(or (and (locationahead 'dumpy ?ahead ?act-time)
(or (wall ?ahead) (visited ?ahead)))
(and (right-of 'dumpy ?right ?act-time)
(or (wall ?right) (visited ?right)))))
(and (locationahead 'dumpy ?ahead ?act-time)
(or (wall ?ahead) (visited ?ahead))
(right-of 'dumpy ?right ?act-time)
(or (wall ?right) (visited ?right))))))
A.8 new-values.cl
;; naar agenten har funnet gullet maa hun skifte strategi
(<- (great 'climb ?time) (at 'dumpy (1 1) ?time))
(<- (good 'forward ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(homewards ?location ?ahead)
(not (wall ?ahead))
(ok ?ahead)))
(<- (medium 'forward ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (homewards ?location ?ahead))
(not (wall ?ahead))
(ok ?ahead)))
(<- (good 'left ?time) (and (at 'dumpy _ ?time)
(or (orientation 'dumpy 90 ?time)
(orientation 'dumpy 180 ?time))
(left-of 'dumpy ?left ?time)
(ok ?left)
(not (good 'forward ?time))))
(<- (medium 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (ok ?ahead))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))))
(<- (good 'right ?time) (and (at 'dumpy _ ?time)
(or (orientation 'dumpy 0 ?time)
(orientation 'dumpy 270 ?time))
(right-of 'dumpy ?right ?time)
(ok ?right)
(not (good 'forward ?time))))
(<- (medium 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (ok ?ahead))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))))
A.9 chicke-value.cl
;;; nytteverdier paa konsekvensen av handlingene.
;;; deadly og risky (og shoot) gjelder uansett,
;;; resten er avhengig om agenten har gull eller ikke.
(<- (risky 'forward ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (deadly 'forward ?time))
(not (ok ?ahead))) (cut))
(<- (deadly 'forward ?time) (and (at 'dumpy ?location ?time)
(loacationahead 'dumpy ?ahead ?time)
(or (pit ?ahead)
(at 'Wumpus ?ahead)
(not (dead 'Wumpus)))) (cut))
(<- (great 'shoot ?time) (and (holding 'arrow)
(at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(at 'Wumpus ?ahead)
(and (right-of 'dumpy ?location-right ?time)
(or (wall ?location-right)
(not (ok ?location-right))
(visited ?location-right)))
(and (left-of 'dumpy ?location-left ?time)
(or (wall ?location-left)
(not (ok ?location-left))
(visited ?location-left)))))
(<- (great 'shoot ?time) (and (holding 'arrow)
(at 'dumpy ?location ?time)
(smelly ?location)
(previously-visited 'dumpy ?prev ?pt ?time)
(entered ?prev ?pt ?ent)
(second-visit ?prev ?ent)))
(<- (medium 'shoot ?time) (and (holding 'arrow)
(at 'dumpy ?location ?time)
(smelly ?location)
(locationahead 'dumpy ?ahead ?time)
(not (visited ?ahead))))
(<- (great 'grab ?time) (and (at 'gold ?location ?time)
(not (holding 'gold))))
(<- (good 'forward ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (wall ?ahead))
(not (visited ?ahead))
(ok ?ahead)))
(<- (medium 'forward ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (wall ?ahead))
(visited ?ahead)))
(<- (medium 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (ok ?ahead))
(previously ?time ?previous-time)
(not (action 'right ?previous-time))
(not (action 'shoot ?previous-time))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))))
(<- (good 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(wall ?ahead)
(previously ?time ?previous-time)
(not (action 'right ?previous-time))
(not (action 'shoot ?previous-time))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))
(not (visited ?location-left))))
(<- (medium 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(wall ?ahead)
(previously ?time ?previous-time)
(not (action 'right ?previous-time))
(not (action 'shoot ?previous-time))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))
(visited ?location-left)))
(<- (good 'left ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(visited ?ahead)
(previously ?time ?previous-time)
(not (action 'right ?previous-time))
(not (action 'shoot ?previous-time))
(left-of 'dumpy ?location-left ?time)
(not (wall ?location-left))
(not (visited ?location-left))
(ok ?location-left)))
(<- (medium 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(not (ok ?ahead))
(previously ?time ?previous-time)
(not (action 'left ?previous-time))
(not (action 'shoot ?previous-time))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))))
(<- (good 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(wall ?ahead)
(previously ?time ?previous-time)
(not (action 'left ?previous-time))
(not (action 'shoot ?previous-time))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))
(not (visited ?location-right))))
(<- (medium 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(wall ?ahead)
(previously ?time ?previous-time)
(not (action 'left ?previous-time))
(not (action 'shoot ?previous-time))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))
(visited ?location-right)))
(<- (good 'right ?time) (and (at 'dumpy ?location ?time)
(locationahead 'dumpy ?ahead ?time)
(visited ?ahead)
(previously ?time ?previous-time)
(not (action 'left ?previous-time))
(not (action 'shoot ?previous-time))
(right-of 'dumpy ?location-right ?time)
(not (wall ?location-right))
(not (visited ?location-right))
(ok ?location-right)))
(<- (good 'give-up ?time) (and (at 'dumpy ?location ?time)
(risky 'forward ?time)
(previously-visited 'dumpy ?prev ?pt ?time)
(entered ?prev ?pt ?ent)
(second-visit ?prev ?ent)))
A.10 abstractions.cl
(defun x-coord (pos)
"Plukker ut x koordinaten"
(first pos))
(defun y-coord (pos)
"Plukker ut y-kooordinaten"
(second pos))
(defun stench (percepts)
"Plukker ut stench-persepsjonen"
(svref percepts 0))
(defun (setf stench) (val vec)
"Setter persepsjonen stench paa riktig plass i vektoren"
(setf (svref vec 0) val))
(defun perceived-stench (percepts)
"Tester om persepsjon er stench"
(eq (stench percepts) 'stench))
(defun breeze (percepts)
"Plukker ut breeze-persepsjonen"
(svref percepts 1))
(defun (setf breeze) (val vec)
"Setter persepsjonen breeze paa riktig plass i vektoren"
(setf (svref vec 1) val))
(defun perceived-breeze (percepts)
"Tester om persepsjon er breeze"
(eq (breeze percepts) 'breeze))
(defun glitter (percepts)
"Plukker ut glitter-persepsjonen"
(svref percepts 2))
(defun (setf glitter) (val vec)
"Setter persepsjonen glitter paa riktig plass i vektoren"
(setf (svref vec 2) val))
(defun perceived-glitter (percepts)
"Tester om persepsjon er glitter"
(eq (glitter percepts) 'glitter))
(defun bump (percepts)
"Plukker ut bump-persepsjonen"
(svref percepts 3))
(defun (setf bump) (val vec)
"Setter persepsjonen bump paa riktig plass i vektoren"
(setf (svref vec 3) val))
(defun perceived-bump (percepts)
"Tester om persepsjon er bump"
(eq (bump percepts) 'bump))
(defun scream (percepts)
"Plukker ut screem-persepsjonen"
(svref percepts 4))
(defun (setf scream) (val vec)
"Setter persepsjonen screem paa riktig plass i vektoren"
(setf (svref vec 4) val))
(defun perceived-scream (percepts)
"Tester om persepsjon er screem"
(eq (scream percepts) 'scream))
(defun find-coordinates-of-player ()
(find-in-array 'player 1 1 *row-length*))
(defun map-to-cartesian (i s)
"returns the cartesian cooridinates by rotate
the coord-system 90 degrees"
(let ((x s)
(y (- (+ 1 *row-length*) i)))
(list x y)))
(defun map-from-cartesian (x y)
"returns the coordinates according to Common Lisp arrays,
rotating the cartesian 270 degrees"
(let ((i (- (+ 1 *row-length*) y))
(s x))
(list i s)))
A.11 utilities.cl
(defun find-type (type list)
(find-if (lambda (x)
(typep x type)) list))
(defun find-in-vec (x i s max)
(cond ((> s max) nil)
((find-type x (contents (aref *board* i s))) (list i s))
(t
(find-in-vec x i (+ s 1) max))))
(defun find-in-array (x i s max)
(cond ((> i max) nil)
((find-in-vec x i s max))
(t
(find-in-array x (+ i 1) s max))))
(defun next-coord (dir i s)
(case dir
(north (list (- i 1) s))
(south (list (+ i 1) s))
(west (list i (- s 1)))
(east (list i (+ s 1)))
(t "feil retningsangivelse til next-coord; foelg himmelretningen")))
(defun next-square (dir i s)
(let ((new-coord (next-coord dir i s)))
(aref *board* (first new-coord) (second new-coord))))
(defun neighbours (i s)
(list
(next-coord 'west i s)
(next-coord 'north i s)
(next-coord 'east i s)
(next-coord 'south i s)))
(defun mark-neighbours (board i s predicate)
(dolist (obj (neighbours i s))
(let ((square (aref board (x-coord obj) (y-coord obj))))
(when (and (not (typep square 'wall))
(not (member predicate (predicates square))))
(setf (predicates square)
(cons predicate (predicates square)))))))
(defun probably ()
(= 0 (random 5)))
(defun random-square (n)
(list (+ 1 (random n)) (+ 1 (random n))))
(defun place-randomly (n)
(let ((square (random-square n)))
(if (equal square *start*)
(place-randomly n)
square)))
(defun fill-randomly (array)
(let* ((dim (array-dimensions array))
(ver (- (first dim) 2))
(hor (- (second dim) 2)))
(do ((i 1 (+ i 1)))
((= i ver))
(dotimes (j ver array)
(when (and (probably) (not (and (= i (x-coord *start*))
(= (+ j 1) (y-coord *start*)))))
(setf (aref array i (+ j 1)) (make-instance 'pit))
(mark-neighbours array i (+ j 1) 'breeze))))))
(defun initialize-perceptions (agent)
"Setter tre av persepsjonene til objektet _agent_ til _none_ "
(setf
(scream (percepts agent)) 'none
(stench (percepts agent)) 'none
(breeze (percepts agent)) 'none
(glitter (percepts agent)) 'none))
(defmethod update-agent ((ag player) (sq open-square))
"Oppdaterer agenten hvis den skulle paa noen maate doe.
Setter agentens persepsjoner til none (initialize-perceptions arg)
for derefter aa sette agentens persepsjonsvektor til aa inneholde
de predikatene som eksisterer paa ruten."
(let ((wumpus (find-type 'wumpus (contents sq))))
(cond ((or (typep sq 'pit)
(and wumpus (alive wumpus)))
(setf (alive ag) nil))
(t (initialize-perceptions ag)
(let ((predicates (predicates sq)))
(loop
for predicate in predicates do
(case predicate
(scream (setf (scream (percepts ag)) 'scream))
(stench (setf (stench (percepts ag)) 'stench))
(breeze (setf (breeze (percepts ag)) 'breeze))
(glitter (setf (glitter (percepts ag)) 'glitter)))))))))
(defun list-perceptions (percept-vector)
(loop
for elm across percept-vector
when (not (equal elm 'none))
collect elm into perceptions
finally (return (if (null perceptions) '(none)
perceptions))))
(defun display-universal-time ()
(multiple-value-bind (sec min hour day mth year)
(decode-universal-time (get-universal-time))
(format t " ~a:~a:~a (~a-~a-~a) "hour min sec year mth day)))
A.12 init.cl
(defun initboard (n)
(setf dumpy (make-instance 'player :ag-name "Dumpy"))
(setf wumpus (make-instance 'wumpus :ag-name "Wumpus"))
(let* ((board (make-array `(,n ,n) :initial-element nil))
(board-len (- n 2))
(wump-square (place-randomly board-len))
(gold-square (place-randomly board-len)))
(do ((i 0 (+ i 1)))
((= i n))
(setf
(aref board 0 i) (make-instance 'wall)
(aref
(aref
(aref
(do
board i 0) (make-instance 'wall)
board (- n 1) i) (make-instance 'wall)
board i (- n 1)) (make-instance 'wall)))
((i 1 (+ i 1)))
((> i board-len))
(dotimes (j board-len)
(setf (aref board i (+ j 1)) (make-instance 'open-square))))
(fill-randomly board)
(setf
(contents (aref board (first wump-square) (second wump-square)))
(cons wumpus
(contents (aref board (first wump-square) (second wump-square))))
(contents (aref board (first gold-square) (second gold-square)))
(cons (make-instance 'gold)
(contents (aref board (first gold-square) (second gold-square))))
(predicates (aref board (first gold-square)(second gold-square)))
(cons 'glitter (predicates (aref board (first gold-square) (second gold-square))))
(contents (aref board (first *start*) (second *start*)))
(cons dumpy (contents (aref board (first *start*) (second *start*)))))
(mark-neighbours board (first wump-square) (second wump-square) 'stench)
(update-agent dumpy (aref board (x-coord *start*) (y-coord *start*)))
board))
A.13 pretty-printing.cl
;;; -------------------------- utskriftsprosedyrer ---------------------------(defun skriv-blanke (n)
(dotimes (i n)
(format t "~a" #\space)))
(defun midtstill-ord (ord tot)
(let* ((len (length ord))
(rest (- tot len)))
(if (> (mod rest 2) 0)
(let ((before (floor (/ rest 2))))
(format t "|")
(skriv-blanke before)
(format t "~a" ord)
(skriv-blanke (+ before 1)))
(let ((before (/ rest 2)))
(format t "|")
(skriv-blanke before)
(format t "~a" ord)
(skriv-blanke before)))))
(defun blank-square ()
(format t "| ~9,A" #\space))
(defun print-board ()
(let ((contents nil)
(predicates nil))
(print-line)
(let ((len (array-dimension *board* 0)))
(do ((i 0 (+ i 1)))
((= i len))
(format t "~1%")
(dotimes (j len)
(let ((square (aref *board* i j)))
(typecase square
(wall (midtstill-ord "wall" 10))
(square
(progn
(if (typep square 'pit)
(midtstill-ord "pit" 10)
(blank-square))
(when (predicates square)
(setf predicates
(append predicates (make-alist (predicates square) j))))
(when (contents square)
(setf contents
(append contents (make-alist (contents square) j)))))))))
(terpri)
(when (not (null contents))
(midtstill-ord "wall" 10)
(print-restlist contents)
(setf contents nil))
(when (not (null predicates))
(midtstill-ord "wall" 10)
(print-restlist predicates)
(setf predicates nil))
(print-line)))))
(defun plasser-ord (ord n)
(dotimes (i (- n 1))
(blank-square))
(midtstill-ord ord 10))
(defun print-rest (a-list)
(print-r 0 a-list))
(defun print-r (s-pos a-list)
(if (null a-list)
(skriv-n-blanke (- s-pos 1))
(let* ((start (first a-list))
(word (car start))
(n-pos (cdr start)))
(plasser-ord (lag-streng word) (- n-pos s-pos))
(print-r n-pos (cdr a-list)))))
(defun lag-streng (obj)
(typecase obj
(symbol (string-downcase (string obj)))
(t (let ((name (name obj)))
(cond ((equal name "Dumpy")
(let ((orientation (facing dumpy)))
(case orientation
(north (concatenate 'string "Dumpy " "'|`"))
(south (concatenate 'string "Dumpy " " \|/"))
(west (concatenate 'string "Dumpy " "<-"))
(east (concatenate 'string "Dumpy " "->")))))
((equal name "Wumpus")
(if (alive wumpus) name
(concatenate 'string "Wumpus " "+")))
(t
name))))))
(defun skriv-n-blanke (n)
(dotimes (i (- *row-length* n))
(blank-square))
(terpri))
(defun print-line ()
(format t "~a" (make-string 70 :initial-element #\_)))
(defun print-restlist (a-list)
(let ((new-list (count-and-divide a-list)))
(defun print-list (list)
(if (null list) nil
(progn
(print-rest (car list))
(if (not (null (cdr list)))
(midtstill-ord "wall" 10))
(print-list (cdr list)))))
(print-list new-list)))
(defun make-alist (list n)
(mapcar (lambda (x)
(cons x n)) list))
(defun count-and-divide (a-list)
(if
(null a-list) nil
(let* ((forrige (first a-list))
(pos (cdr forrige))
(new-list nil))
(defun divide (old-pos list)
(let* ((start (first list))
(new-pos (cdr start)))
(cond
((null list) (reverse new-list))
((eql new-pos old-pos)
(setf a-list (remove start a-list))
(push start new-list)
(divide new-pos (cdr list)))
(t
(divide new-pos (cdr list))))))
(let ((divided-list (divide pos (cdr a-list))))
(if (null divided-list) (list a-list)
(cons a-list (count-and-divide divided-list)))))))
A.14 gold-digger.cl
(defun gold-digger (dumpy)
(let ((files (directory
#p"D:/Private/SLI-370/Wumpus/Go/wumpus-1999-10-20/Go/*.cl*")))
(loop for file in files do (load file))
(setf *test* (initboard 6))
(setf *board* *test*)
(print-board)
(when (alive dumpy)
(loop (format t " ~& WUMPUS > ")
(let ((action (read)))
(case action
(go-forward (implement-action dumpy action)
(if (alive dumpy) (print-board)
(return-from nil)))
((turn-left turn-right)
(implement-action dumpy action)
(format t " Your agent is heading ~A ~% " (facing dumpy)))
(grab (if (grab dumpy 'gold)
(format t " Your agent is in possesion of ~A ~%"
(possesions dumpy))
(format t " Sorry Mac, no need for goldfever here!~%")))
(shoot (shoot dumpy)
(if (alive Wumpy)
(format t " Your agent is now in possesion of ~A ~%"
(possesions dumpy))
(format t " Your agent got the big Wumpy! ~%")))
(heading? (format t " Your agent is heading ~A ~% "
(facing dumpy)))
(possesions? (if (and (alive Wumpy)
(eq nil (possesions dumpy)))
(format t " Your agent is now in possesion of ~A, ~%
and yet the big Wumpy isn't dead! ~%"
(possesions dumpy))
(format t " Your agent is now in possesion of ~A .~%"
(possesions dumpy))))
(show-board (print-board))
(alive? (if (alive dumpy)
(format t " Hey kid! Cheer up!~%")
(format t " Argh, you blew it, cowboy!~%")))
(perceptions? (format t " Your agent percives ~A~% "
(percepts dumpy)))
(help (format t " Valide kommandoer er go-forward, turn-left,
turn-right,~%
shoot, grab, heading?,~%
perceptions?, possesions?, show-board~%
help, and q. ~%"))
(q (return-from nil))
(otherwise
(format t " What!? No command named ~A. ~& WUMPUS >" action))))))))
A.15 prolog-till.cl
;; noen hjelpefunskjoner til Prolog, hentet fra eller lagd ut i fra ideer hos Norvig,
;; Paradigms of Artificial Intelligence
(defvar *db-predicates* nil
"a list of all predicates stored in the database.")
(defun get-clauses (pred) (get pred 'clauses))
;Norvig
(defun predic (relation) (first relation))
;Norvig
(defun clause-head (clause) (first clause))
(defun clause-body (clause) (rest clause))
;Norvig
;Norvig
(defun clear-rules ()
(setf *rules* nil))
(defun clear-db ()
(dolist (pred *db-predicates*)
(clear-predicate pred))
(setf *db-predicates* nil)
(clear-rules))
(defun clear-predicate (predicate)
"remove the clauses for a single predicate."
(setf (get predicate 'clauses) nil))
;Norvig
(defun remove-predicates (predicate)
"fjerner funksjonene som tilhrer et predikat fra *rules*"
(dolist (pred (get predicate 'clauses))
(setf *rules* (delete pred *rules* :test #'equal))))
(defun clear-predicates (predicate)
;OBS vr klar over at denne ogs fjerner fakta som begynner p pred,
;ikke bare regler
(remove-predicates predicate)
(clear-predicate predicate))
(defmacro <- (con &rest ant)
(let ((ant (if (= (length ant) 1)
(car ant)
`(and ,@ant)))
(pred (predic con)))
`(let ((rules ,(rule-fn (rep_ ant) (rep_ con))))
(conc1f *db-predicates* ',pred)
(conc1f (get ',pred 'clauses) rules)
(length (conc1f *rules* rules)))))
(defun make-action-query (time)
(car (or (ask-pattern `(great ?a ,time))
(ask-pattern `(good ?a ,time))
(ask-pattern `(medium ?a ,time))
(ask-pattern `(risky ?a ,time)))))
(defun make-location-query (time)
(car (ask-pattern `(at 'dumpy ?l ,time))))
(defun make-orientation-query (time)
(car (ask-pattern `(orientation 'dumpy ?l ,time))))
(defun make-action-sentence (action time)
`(action ,action ,time))
(defun make-percept-sentence-prol (percepts time)
(let ((percept-list (list
`',(stench percepts)
`',(breeze percepts)
`',(glitter percepts)
`',(bump percepts)
`',(scream percepts))))
`(percept ,percept-list ,time)))
(defun random-elt (list)
(let* ((len (length list))
(number (random len)))
(nth number list)))
(defun ask-pattern (query)
(let ((noe (bag-of query)))
(if noe (random-elt noe) nil)))
(defun tell (percepts)
(eval `(<- ,percepts)))
(defun tell-first (fact)
(eval `(push-rule ,fact (cut))))
(defmacro push-rule (con &rest ant)
(let ((ant (if (= (length ant) 1)
(car ant)
`(and ,@ant)))
(pred (predic con)))
`(let ((rules ,(rule-fn (rep_ ant) (rep_ con))))
(conc2f *db-predicates* ',pred)
(conc2f (get ',pred 'clauses) rules)
(length (conc2f *rules* rules)))))
(define-modify-macro conc2f (obj)
;legger til obj foran
(lambda (place obj)
(nconc (list obj) place)))
A.16 onprolog3.lisp
;;; Sources from Paul Graham's _On Lisp: Advanced Techniques for
;;; Common Lisp_, Prentice Hall, 1994.
;
;
;
;
;
;
;
;
;
;
;
The code in this file was mechanically extracted from the TeX
source files of On Lisp. Some operators are multiply defined,
as they were in the book. Usually this means just that you get
an upwardly compatible version 2 of whatever it is. Note, though,
that if you load this whole file you get:
1. the cltl1 versions of alrec and atrec.
2. varsym? defined as needed by the Prolog compiler. So if you
want to use e.g. match with variables that begin with question
marks, comment out the final definition of varsym?
If you have questions or comments about this code, or you want
something I didn't include, send mail to onlisp@das.harvard.edu.
;; krever prolog-till
(defmacro aif (test-form then-form &optional else-form)
`(let ((it ,test-form))
(if it ,then-form ,else-form)))
(defmacro aif2 (test &optional then else)
(let ((win (gensym)))
`(multiple-value-bind (it ,win) ,test
(if (or it ,win) ,then ,else))))
(defmacro acond2 (&rest clauses)
(if (null clauses)
nil
(let ((cl1 (car clauses))
(val (gensym))
(win (gensym)))
`(multiple-value-bind (,val ,win) ,(car cl1)
(if (or ,val ,win)
(let ((it ,val)) ,@(cdr cl1))
(acond2 ,@(cdr clauses)))))))
(define-modify-macro conc1f (obj)
(lambda (place obj)
(nconc place (list obj))))
(defmacro with-gensyms (syms &body body)
`(let ,(mapcar #'(lambda (s)
`(,s (gensym)))
syms)
,@body))
(defun match (x y &optional binds)
(acond2
((or (eql x y) (eql x '_) (eql y '_)) (values binds t))
((binding x binds) (match it y binds))
((binding y binds) (match x it binds))
((varsym? x) (values (cons (cons x y) binds) t))
((varsym? y) (values (cons (cons y x) binds) t))
((and (consp x) (consp y) (match (car x) (car y) binds))
(match (cdr x) (cdr y) it))
(t (values nil nil))))
(defun binding (x binds)
(labels ((recbind (x binds)
(aif (assoc x binds)
(or (recbind (cdr it) binds)
it))))
(let ((b (recbind x binds)))
(values (cdr b) b))))
(defun vars-in (expr &optional (atom? #'atom))
(if (funcall atom? expr)
(if (var? expr) (list expr))
(union (vars-in (car expr) atom?)
(vars-in (cdr expr) atom?))))
(defun var? (x)
(and (symbolp x) (eq (char (symbol-name x) 0) #\?)))
(defun simple? (x) (or (atom x) (eq (car x) 'quote)))
(setq *cont* #'identity)
(defmacro =lambda (parms &body body)
`#'(lambda (*cont* ,@parms) ,@body))
(defmacro =defun (name parms &body body)
(let ((f (intern (concatenate 'string
"=" (symbol-name name)))))
`(progn
(defmacro ,name ,parms
`(,',f *cont* ,,@parms))
(defun ,f (*cont* ,@parms) ,@body))))
(defmacro =bind (parms expr &body body)
`(let ((*cont* #'(lambda ,parms ,@body))) ,expr))
(defmacro =values (&rest retvals)
`(funcall *cont* ,@retvals))
(defmacro =funcall (fn &rest args)
`(funcall ,fn *cont* ,@args))
(defmacro =apply (fn &rest args)
`(apply ,fn *cont* ,@args))
(defparameter *paths* nil)
(defconstant failsym '@)
(defmacro choose (&rest choices)
(if choices
`(progn
,@(mapcar #'(lambda (c)
`(push #'(lambda () ,c) *paths*))
(reverse (cdr choices)))
,(car choices))
'(fail)))
(defmacro choose-bind (var choices &body body)
`(cb #'(lambda (,var) ,@body) ,choices))
(defun cb (fn choices)
(if choices
(progn
(if (cdr choices)
(push #'(lambda () (cb fn (cdr choices)))
*paths*))
(funcall fn (car choices)))
(fail)))
(defun fail ()
(if *paths*
(funcall (pop *paths*))
failsym))
(defun rep_ (x)
(if (atom x)
(if (eq x '_) (gensym "?") x)
(cons (rep_ (car x)) (rep_ (cdr x)))))
(defun fullbind (x b)
(cond ((varsym? x) (aif2 (binding x b)
(fullbind it b)
(gensym)))
((atom x) x)
(t (cons (fullbind (car x) b)
(fullbind (cdr x) b)))))
(defun varsym? (x)
(and (symbolp x) (not (symbol-package x))))
(defun form (pat)
(if (simple? pat)
pat
`(cons ,(form (car pat)) ,(form (cdr pat)))))
(defvar *rules* nil)
;;;(defmacro <- (con &rest ant)
;;;
;;; (let ((ant (if (= (length ant) 1)
;;;
;;;
(car ant)
;;;
;;;
`(and ,@ant))))
;;;
;;;
`(length (conc1f *rules*
;;;
;;;
,(rule-fn (rep_ ant) (rep_ con))))))
(defun rule-fn (ant con)
(with-gensyms (val win fact binds paths)
`(=lambda (,fact ,binds ,paths)
(with-gensyms ,(vars-in (list ant con) #'simple?)
(multiple-value-bind
(,val ,win)
(match ,fact
(list ',(car con)
,@(mapcar #'form (cdr con)))
,binds)
(if ,win
,(gen-query ant val paths)
(fail)))))))
;
;
;;;(defmacro with-inference (query &rest body)
;;;
;;; (let ((vars (vars-in query #'simple?)) (gb (gensym)))
;;;
;;;
`(with-gensyms ,vars
;;;
;;;
(setq *paths* nil)
;;;
;;;
(=bind (,gb) ,(gen-query (rep_ query) nil '*paths*) ;
;;;
;;;
(let ,(mapcar #'(lambda (v)
;;;
;;;
`(,v (fullbind ,v ,gb)))
;;;
;;;
;;;
;;;
;;;
;;;
vars)
,@body)
(fail)))))
(defun gen-query (expr binds paths)
(case (car expr)
(and (gen-and (cdr expr) binds paths))
(or (gen-or (cdr expr) binds paths))
(not (gen-not (cadr expr) binds paths))
(lisp (gen-lisp (cadr expr) binds))
(is (gen-is (cadr expr) (third expr) binds))
(cut `(progn (setq *paths* ,paths)
(=values ,binds)))
(t
`(prove (list ',(car expr)
,@(mapcar #'form (cdr expr)))
,binds *paths*))))
;
(=defun prove (query binds paths)
(choose-bind r *rules*
(=funcall r query binds paths)))
;
;
;
;
;
;
;
;
;
;
(defun gen-and (clauses binds paths)
;
(if (null clauses)
`(=values ,binds)
(let ((gb (gensym)))
`(=bind (,gb) ,(gen-query (car clauses) binds paths);
,(gen-and (cdr clauses) gb paths)))))
;
(defun gen-or (clauses binds paths)
`(choose
,@(mapcar #'(lambda (c) (gen-query c binds paths))
clauses)))
;
(defun gen-not (expr binds paths)
(let ((gpaths (gensym)))
`(let ((,gpaths *paths*))
(setq *paths* nil)
(choose (=bind (b) ,(gen-query expr binds paths)
(setq *paths* ,gpaths)
(fail))
(progn
(setq *paths* ,gpaths)
;
;
;
(=values ,binds))))))
(defmacro with-binds (binds expr)
`(let ,(mapcar #'(lambda (v) `(,v (fullbind ,v ,binds)))
(vars-in expr))
,expr))
(defun gen-lisp (expr binds)
`(if (with-binds ,binds ,expr)
(=values ,binds)
(fail)))
(defun gen-is (expr1 expr2 binds)
`(aif2 (match ,expr1 (with-binds ,binds ,expr2) ,binds)
(=values it)
(fail)))
; This code is copyright 1993 by Paul Graham, but anyone who wants
; to use the code in any nonprofit activity, or distribute free
; verbatim copies (including this notice), is encouraged to do so.
Tillegg B
Kjringseksempel
> (w)
; Fast loading A:\Wumpus-Windows\Wumpus-system\action-value.fasl
; Fast loading A:\Wumpus-Windows\Wumpus-system\wumpus-rules.fasl
[Live data follows..]
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
| wall | pit
|
| pit
| pit
| wall
| wall |
| breeze | breeze |
|
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | breeze |
| breeze | breeze |
______________________________________________________________________
| wall |
|
| pit
|
| wall
| wall |
| breeze | stench | breeze |
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | Dumpy -> | gold | Wumpus |
|
| wall |
| stench | breeze | stench |
| wall |
| glitter |
|
|
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
My perceptions at time 21:31:36 (1999-11-28) are/is none,
and the number in my action sequence is 0.
I'm facing east.
(Your agent is walking forward.)
67
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
| wall | pit
|
| pit
| pit
| wall
| wall |
| breeze | breeze |
|
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | breeze |
| breeze | breeze |
______________________________________________________________________
| wall |
|
| pit
|
| wall
| wall |
| breeze | stench | breeze |
______________________________________________________________________
| wall |
|
|
|
| wall
| wall |
| Dumpy -> | Wumpus |
|
| wall |
| gold |
|
|
| wall |
| stench | breeze | stench |
| wall |
| glitter |
|
|
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
My perceptions at time 21:31:43 (1999-11-28) are/is stench, glitter,
and the number in my action sequence is 1.
I'm facing east.
She is grabbing the gold..
Yes! Your agent has it, and is changing strategy, to go home!
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
| wall | pit
|
| pit
| pit
| wall
| wall |
| breeze | breeze |
|
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | breeze |
| breeze | breeze |
______________________________________________________________________
| wall |
|
| pit
|
| wall
| wall |
| breeze | stench | breeze |
______________________________________________________________________
| wall |
|
|
|
| wall
| wall |
| Dumpy -> | Wumpus |
|
| wall |
| stench | breeze | stench |
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
; Fast loading A:\Wumpus-Windows\Wumpus-system\new-values.fasl
My perceptions at time 21:32:21 (1999-11-28) are/is stench, glitter,
and the number in my action sequence is 2.
I'm facing east.
(Your agent is turning right.)
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
| wall | pit
|
| pit
| pit
| wall
| wall |
| breeze | breeze |
|
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | breeze |
| breeze | breeze |
______________________________________________________________________
| wall |
|
| pit
|
| wall
| wall |
| breeze | stench | breeze |
______________________________________________________________________
| wall |
|
|
|
| wall
| wall |
|Dumpy |/ | Wumpus |
|
| wall |
| stench | breeze | stench |
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
My perceptions at time 21:32:23 (1999-11-28) are/is stench, glitter,
and the number in my action sequence is 3.
I'm facing south.
(Your agent is turning right.)
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
| wall | pit
|
| pit
| pit
| wall
| wall |
| breeze | breeze |
|
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | breeze |
| breeze | breeze |
______________________________________________________________________
| wall |
|
| pit
|
| wall
| wall |
| breeze | stench | breeze |
______________________________________________________________________
| wall |
|
|
|
| wall
| wall |
| Dumpy <- | Wumpus |
|
| wall |
| stench | breeze | stench |
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
My perceptions at time 21:32:24 (1999-11-28) are/is stench, glitter,
and the number in my action sequence is 4.
I'm facing west.
(Your agent is walking forward.)
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
| wall | pit
|
| pit
| pit
| wall
| wall |
| breeze | breeze |
|
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | breeze |
| breeze | breeze |
______________________________________________________________________
| wall |
|
| pit
|
| wall
| wall |
| breeze | stench | breeze |
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | Dumpy <- |
| Wumpus |
|
| wall |
| stench | breeze | stench |
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
My perceptions at time 21:33:44 (1999-11-28) are/is none,
and the number in my action sequence is 5.
I'm facing west.
(She is climbing out of this world..)
Congratulation! Your agent has now reached her goal.
In the new version of the game,
you can climb to the next level.
Until then, BYE!
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
| wall | pit
|
| pit
| pit
| wall
| wall |
| breeze | breeze |
|
______________________________________________________________________
| wall |
|
|
|
| wall
| wall | breeze |
| breeze | breeze |
______________________________________________________________________
| wall |
|
| pit
|
| wall
| wall |
| breeze | stench | breeze |
______________________________________________________________________
| wall |
|
|
|
| wall
| wall |
|
| Wumpus |
|
| wall |
| stench | breeze | stench |
______________________________________________________________________
| wall | wall | wall | wall | wall | wall
______________________________________________________________________
995
>
Bibliogra
Bratko, I. (1990). Prolog - Programming for Articial Intelligence. Addison-Wesley Publishers.
Clocksin, W. F. og Mellish, C. S. (1987). Programming in Prolog. Springer-Verlag.
Graham, P. (1994). On Lisp, Advanced Techniques for Common Lisp. Prentice-Hall.
Norvig, P. (1992). Paradigms of Articial Intelligence Programming. Morgan kaufmann
Publishers.
Russel, S. og Norvig, P. (1995). Articial Intelligence, A Modern Approach. Prentice Hall.
73
Download