Eksamen SLI 230 Bakerst ligger to sider med oversikt over standardprosedyrer og spesialformer i Scheme, samt oversikt over prosedyrer fra Simply Scheme og en enkel oversikt over konvertering mellom datatyper i Scheme. Det kan tenkes at du trenger annet enn det som er oppgitt i oversikten, at du er usikker på rekkefølgen på argumenter til prosedyrer, eller at oppgaveteksten er uklar på enkelte punkter. Gjør dine egne presiseringer og definisjoner der det trengs. Gjør rede for disse før du bruker dem. Det er ikke tillatt med andre hjelpemidler enn de to sidene som er vedlagt oppgavesettet. Oppgave 1 Følgende funksjoner er definert og brukes i oppgaven: (define g (lambda (x) (and g x))) (define h (lambda x 2)) (define ping-pong (lambda (ping pong) (let ((ping pong) (pong ping)) (ping (pong ping) pong)))) a. Regn ut verdiene av følgende uttrykk. Vis utregningene ved opptegning av omgivelser. (g 1) (h 1) (g g) (h h) ((ping-pong g (lambda (x y) (y x))) (h g) (g h)) b. Vi bytter ut LAMBDA i alle definisjonene over med DYNAMIC-LAMBDA. Er det noen av uttrykkene i oppgave a som nå lar seg regne ut? Er det noen som ikke lar seg regne ut? Gi korte forklaringer. 2
Oppgave 2 Vi skal se på memoisering av prosedyrer og strømmer. a. Bruk ca. 1 side for å greie ut om: Grunnprinsippene i memoisering av argumentløse prosedyrer. Hvordan opbevares resultatet av å applisere prosedyren? Grunnprinsippene i memoisering av prosedyrer med ett eller flere argumenter. Hvordan oppbevares resultatet? Grunnprinsippene med strømmer. Hva skiller en memoisert strøm fra en ikkememoisert strøm? b. En strøm kan konstrueres ved å lage en eller annen prosedyre r som genererer data for strømmer og en eller annen rekursiv prosedyre g som bruker r for å generere strømmen n. Et slikt program er definert under: (define r (lambda (n) (+ n 1))) (define g (lambda (n) (cons n (lambda () (g (r n )))))) (define n (g 0)) I programmet er det 3 prosedyrer. Beskriv effekten av å memoisere r. Beskriv effekten av å memoisere g. Beskriv effekten av å memoisere den anonyme prosedyren i g. c. Lag en prosedyre (list->stream l) som produserer en strøm fra en liste. d. Lag en prosedyre (stream->list str) som produserer en liste fra en strøm. Forutsett endelige strømmer som input til prosedyren. e. Vi skal lage en prosedyre (stream-cdr! str) som brukes ved konsumering av strømmer, og som gradvis omgjør strømmer til lister. For eksempel, gitt strømmen nat av naturlige tall 0,1,2,3,4,... definert på vanlig måte. Følgende kjøringseksempel viser bruken av stream-cdr!: > nat (0. #<procedure>) > (stream-cdr! nat) (1. #<procedure>) > nat (0 1. #<procedure>) > (stream-cdr! (stream-cdr! nat)) (2. #<procedure>) > nat (0 1 2. #<procedure>) > (stream-cdr! nat) (1 2. #<procedure>) 3
Oppgave 3: Spillutvikling Vi skal hjelpe til med utviklingen av et nytt dataspill der spillerne kjemper mot hverandre ved hjelp av monstre de kontrollerer. Vår oppgave er å modellere spillere, monstre og noen av hendelsene i spillet. Selve administreringen og kontrolleringen av hele spillet er det noen andre som programmerer. Les hele oppgaven før du begynner å programmere. Spillets grunnprinsipper Hver spiller tildeles et antall liv på begynnelsen av et spill. Spillerens mål er å bevare flest mulig av sine egne liv samtidig som motstanderne mister liv. Spillerne kjemper med hverandre ved hjelp av monstrene de kontrollerer. Underveis i spillet vil spillerne motta beskjeder om at det er deres tur til å angripe, at de blir angrepet, og om de mister liv. Spillere representeres ved spiller-objekter. Hvert monster har en del egenskaper, som skal representeres v.hj.a. monsterobjekter. Mengden av monstere en spiller kontrollerer representeres med monstersamling-objekter. Spillerne kan dirigere sine monstre til å angripe andre spillere samt bruke dem til å forsvare seg med. Sentralt i dette er monstrenes angrepsstyrke og forsvarsstyrke, som begge representeres med heltall. Alle monstre har et navn og tilhører enten fargen blå eller grønn. Alle monstre kontrolleres av en og bare en spiller. Et monster kan være i en av fire tilstander: inaktiv, i angrep, i forsvar eller død. Bare inaktive monstre kan endre tilstand for å angripe eller forsvare. a. Du skal skrive prosedyrer som genererer slike objekter. Det må finnes muligheter for å gi beskjeder om å hente ut og å endre verdiene for alle felter i de ulike objekttypene. Skriv prosedyren (lag-monster navn angrep forsvar farge). Et monster må kunne bytte til en annen av de fire tilstandene. Et monster må kunne få sin initielle forsvarsstyrke gjenopprettet (se monsterkamper lenger ned). Skriv prosedyren (lag-monster-samling monstre). Det må finnes beskjeder for å legge til et nytt monster og for å få ut alle monstrene. Skriv prosedyren (lag-spiller navn liv monstre). Det må finnes beskjeder for å velge ut et inaktivt monster, sette det i forsvar og returnere det til den sentrale kontrollenheten. Tilsvarende må det finnes beskjed for å velge et inaktivt monster til angrep. I spillet vil en sentral kontrollenhet sørge for å tildele spillerne hver sin unike monster-samling ved oppstart. Monsterkamper Kamper mellom monstre vil alltid foregå monster mot monster. Utfallet av en monsterkamp vil alltid være at enten begge dør, det ene dør, eller begge overlever. Utkommet avhenger av monstrenes angrepsstyrke og forsvarstyrke. Angrepsstyrke brukes for å tildele motstanderen skade, og forsvarsstyrke er et mål på hvor mye et monster tåler. Skade som blir til overs etter en monsterkamp tildeles spiller. Etter en monsterkamp, får de overlevende monsterene igjen sin initielle forsvarsstyrke. 4
Reglene for monsterkamper er som følger: Angriperen tildeler forsvareren like mye skade som angriperen har angrepsstyrke. Forsvareren tildeler angriperen like mye skade som forsvareren har angrepsstyrke. Hvis et av monsterene får redusert sin forsvarsstyrke til 0 eller mindre etter å ha blitt tildelt skade, dør monsteret. Resterende skade går direkte på spilleren som kontrollerte det nå døde monsteret. Spilleren mister et liv pr. skade som tildeles på denne måten. Et eksempel illustrerer dette. Spiller 1 har 15 liv og kontrollerer Pyrosaur (en liten, ildsprutende dinosaur) med angrepsstyrke 2 og forsvarsstyrke 1. Spiller 2 har 10 liv og kontrollerer en Giant Slime Rat (en kjempestor, rimelig ekkel rotte) med angrepsstyrke 2 og forsvarsstyrke 3). Spiller 1 angriper spiller 2: Pyrosauren tildeler Giant Slime Rat 2 i skade. Giant Slime Rat responderer ved å gi Pyrosauren 2 i skade. Pyrosauren dør, spiller 1 mister ett liv og har nå 14 liv. Giant Slime Rat overlever og spiller 2 mister ingen liv. Etter at kampen er over, får Giant Slime Rat igjen 3 i forsvarsstyrke. b. Du skal skrive prosedyren som sørger for administrering av monsterkamper. (utkjemp-monsterkamp! angriper angreps-monster forsvarer forsvars-monster) lar to spillere kjempe mot hverandre med monstre etter reglene over. Forheksing av spillet Et testpanel tester spillet, og tilbakemeldingene er klare: Spillet er altfor kjedelig! Ingenting uventet skjer, det kunne like godt være helautomatisert. Dette er dårlige nyheter. Vi blir innkalt til et krisemøte der det besluttes at noe må gjøres. Det må komme inn mer tilfeldigheter i spillet. Vårt forslag er å implementere forhekselser som kastes inn i spillet på tilfeldige tidspunkter. En forhekselse kan f.eks. si at alle døde, grønne monstre vekkes til live igjen eller at alle ikke-døde monstre får 1 i skade. Sistnevnte fører til at alle monstre med forsvarstyrke 1 dør. Forhekselser gjelder for samlinger av monstre. En forhekselse modelleres med et forhekselse-objekt. Forhekselser består av tre deler: Et utvalgskriterium for å velge hvilke monstre som muligens kan bli forhekset, et bestemmelseskriterium som velger ut hvilke monstre av disse som skal bli forhekset, og en handling som utfører selve forhekselsen. c. Lag prosedyren (lag-forhekselse navn utvalg velg handling). d. Lag forhekselsen Alle døde, grønne monstre vekkes til live igjen. e. Lag forhekselsen Det minste monsteret en spiller kontrollerer dør. 5
Forhekselsene skal gjelde for enkeltspillere eller alle spillere. Det er den sentrale kontrollenheten i spillet som bestemmer hvilke forhekselser som skal gjelde og når de skal kastes inn i spillet. Men vi trenger en prosedyre for å spre forhekselser på de forskjellige monstersamlingene i spillet. f. Lag prosedyren forheks-spill som tar inn en forhekselse og et vilkårlig antall spiller-objekter, og forhekser disse spillernes monster-samlinger. 6
Oversikt over prosedyrer og konverteringer Prosedyrer fra simply.scm skrevet med kursiv, standard- prosedyrer med vanlig font. Words and sentences appearances before? butfirst (bf) butlast (bl) count empty? equal? first item last member? quote sentences (se) sentence? word word? Lists append assoc car cdr c...r cons filter for-each length list list? list-ref map member null? reduce Trees children datum make-node Arithmetic + - * / < <= = > >= abs ceiling cos even? Expt floor integer? log max min number? odd? quotient random remainder round sin sqrt True and false and boolean? cond if not or Variables define let Vectors list->vector make-vector vector vector? vector-length vector->list vector-ref vector-set! Procedures apply lambda procedure? Higher-Order Procedures accumulate every filter for-each keep map reduce repeated Control begin error load trace untrace Input/Output align display newline read read-line read-string show show-line write Files and Ports close-all-ports close-input-port close-output-port eof-object? open-input-file open-output-file 7
Konverteringesprosedyrer har navn på formen type1->type2. symbol number string list vector integer char exact inexact 8