Nekromanti OOP & RPG

Troberg

Sinister eater
Joined
27 Jun 2001
Messages
17,659
"Nya insikter i rollspelskonstruktion" eller "Hur man blir en fullfjädrad programmerare på fem minuter"

Inom programmeringen så har man de senaste 15-20 åren haft OOP, dvs objektorienterad programmering som buzzword. Som alla bra buzzwords så är det mycket fluff och marknadsföringstomgångsprat, men det finns också en solid kärna som är användbar. Lyssnar man på försäljarna så är den lösningen på alla problem med socker på, i praktiken är den bara ett sätt att strukturera sitt program. Det underlättar, men det är inte magiskt.

Varför pladdrar jag om programmering?

Jo, för att filosofin kan tillföra något till sättet att strukturera rollspel.

Först en turbointroduktion till OOP:

Tanken är att man, istället för att som traditionellt där programmet styr flödet i en viss ordning, har fristående objekt som interagerar med varandra. Ett objekt kan vara olika saker, det kan vara en färg, en fil, ett Word-dokument, en knapp eller något annat. De kan också ha hierarkier, till exempel så är ett Word-dokument också en fil.

Skulle man bygga upp en ordbehandlare från ett OOP-perspektiv (det här är ett exempel, ingen skulle göra på det här sättet på riktigt, men principen håller) så skulle man göra något i stil med att man börjar med ett teckenobjekt. Detta är ett enda tecken, vilket man kan applicera på andra objekt, tex en skärm eller en skrivare. Man kan också applicera andra objekt på teckenobjektet, tex färg, storlek och stiltyp. Detta objekt använder man sedan för att för att skapa ett nytt objekt, som ärver alla dess egenskaper och möjligheter, men som kan hantera flera tecken. Detta objekt ärver man sedan vidare in i ett sidobjekt och så vidare.

För att räknas som OO så brukar fyra krav ställas på ett språk:

- Inheritance (Arv)
Arv innebär att jag utifrån ett grundobjekt kan skapa nya objekt som har dess egenskaper, men som utökar det på något sätt. Ett Word-dokument ärver egenskaperna från en fil, och får då automatiskt all funktionalitet och alla egenskaper en fil har. Dokumentet behöver inte själv hålla rätt på hur filen kan döpas om, skickas via mail, läsas från disk, uppge sin storlek och sånt, det får det genom att tala om att det ärver från fil. Dock är dokumentet mer än en godtycklig fil, det har kompletterats med en massa saker för att beskriva en textmängd, diagram och annat pynt.
Ett mycket konkret exempel. Om jag köper en packe printerpapper, lägger dem i hålslaget och hålslår dem så kan man säga att objektet HålslagetPapper ärver Papper, dvs det är ett Papper, men med vissa tillägg.
Ett sätt att utgå från tidigare arbeten och bygga vidare på det andra gjort, samt att dela in lösningen i behändiga bitar helt enkelt. Kan beskrivas som "Är av typen..., fast med...".

- Encapsulation (Inkapsling)
En av mina favoriter. I grund och botten handlar inkapsling om att lägga kunskap på burk. Man kan dölja den interna konstruktionen för den som brukar ett objekt, till exempel så behöver inte vår Word-objekts-programmerare ha en aning om hur en fil egentligen ligger lagrad i olika block utspridda över en eller flera diskar, det har Fil-objekts-programmeraren löst åt honom och kapslat in det så att han slipper hantera det. Ungefär som att man inte behöver veta något om hur en startmotor är lindad eller vilka legeringar som används i ett tändstift för att vrida om tändningsnyckeln i en bil.
Ett sätt att leverera enkla, färdiga lösningar som står på egna ben. Kan beskrivas som "Tar hand om problemet...".

- Polymorphism (Mångfacetteradhet?)
Polymorphism är ett lite klurigare begrepp. Det hela bottnar i att ett objekt kan ha flera olika användningsområden som kan kräva att det visar lite olika beteenden. Låt oss återigen exemplifiera med bilar. Vad är en bil och vilka ansikten ska den visa utåt? Tja, den ska kunna förflytta en förare, så vi måste ha ett interface för föraren, i form av ett säte, styrdon och instrumentering. Den ska också kunna transportera passagerare, men de ska inte kunna styra så där räcker ett säte. För att kunna transportera last behöver den ha ett lastutrymme. För att passa mot vägen behöver den hjul. Och så vidare. Beroende på vem jag är (förare, passagerar, last, väg, mekaniker, bensinpump och så vidare) så ska jag se olika ansikten på bilen. Polymorphism ger också olika objekt möjlighet att bete sig på samma sätt. En människa har kanske interfacet äta vilket en robot inte har, men båda har interfacet greppa.
Ett sätt att ge flexibilitet i brukandet av ett objekt. Kan beskrivas som "Kan se ut som..." eller "Kan utföra operationen...".

- Operator overloading (Interaktionsflexibilitet)
Den här brukar vara den svåraste att förklara. Den handlar om att kunna definiera om hur objekt interagerar med varandra. För siffror är det redan definierat, 1+1=2 osv, men man måste ofta kunna tala om vad exempelvis röd+svart är, sant+falskt och så vidare. I vissa fall kan det finnas olika definitioner. Är skadad>halvdöd? Kanske för en människa, kanske inte för en robot.
Ett sätt att definierar hur olika objekt interagerar. Kan beskrivas som "Kan interagera med ... enligt...".

(Jag har medvetet undvikit att krångla till det genom att undvika att peta i distinktionen klass/objekt, eftersom den dels tenderar att vara svår att greppa för ickeprogrammerare, dels inte riktigt är relevant i sammanhanget.)

OK, vad innebär då det här i rollspelstermer?

Vi går genom ovanstående lista igen, denna gång så pratar vi om hur mekanismerna kan brukas i rollspel:

- Inheritance (Arv)
Arv används väldigt mycket i rollspel. Enklaste exemplet är i den mest grundläggande konstruktionen av alla, karaktärer. Karaktär är ett objekt. Detta ärvs av objekt som Barbar, Magiker och så vidare, vilka sedan ärvs av objekten SpelarKaraktär och SpelledarKaraktär. Dessa objekt i sin tur ärvs av objektet Tryggtorkel. Så man kan alltså säga att Tryggtorkel är en SpelarKaraktär, vilken är en Barbar, vilken i sin tur är en Karaktär.
Är inte det här då bara en jädra massa snack och överanalysrerande som inte ger något?
Nej, vi har faktiskt fått något. Genom att vi talar om att Tryggtorkel är en SpelarKaraktär så får han automatiskt hela paketet med regler och sånt som en SpelarKaraktären får. Genom att SpelarKaraktären är en Barbar så får vi hela Barbar regeluppsättning och framför allt så får vi genom att Barbaren är en Karaktär hela paketet regler som gäller för karaktärer.
Andra exempel är när man har en enkel grundkärna för reglerna, men med avancerade frivilliga regler. Om möjligt så bör man då lägga upp det enligt en liknande princip, dvs att man behåller arvet från de enkla reglerna oförändrat, men utökar dem med nya möjligheter. På så sätt påverkas inte ursprungsreglerna, eftersom de avancerade reglerna fortfarande är de enkla, men med lite påbyggnad.
Ytterligare ett exempel är sådant som grundegenskap, färdighet, fördelar, vapen och så vidare. Så längt som det är möjligt så ska alla fördelar ärva från samma grundobjekt, Fördel, och bara lägga till det som de behöver. Man ska ska undvika att bygga upp parallella mekansimer för samma sak. Visst, Vapen kanske behöver ärvas ner i underobjekten Närstridsvapen och Avståndsvapen, men så mycket som möjligt i regelmängden bör ligga i Vapen.

- Encapsulation (Inkapsling)
Här handlar det främst om två olika saker.
Först så bör man avgränsa olika objekt från varandra. Varje koppling mellan dem är en komplikation som måste hanteras och som kan gå fel. I de fall man måste koppla ihop dem så görs det via tydliga, väldokumenterade anslutningspunkter. Vi accepterar inte att att behöva öppna stereon för att löda fast högtalarkablarna direkt på kretskorter utan vi använder de dokumentarade och standardiserade uttagen på utsidan. På samma sätt så bör man undvika att göra regelmekanismer som är inne och påtar in de interna mekanismerna i andra regler. Man gör exempelvis en spell som delar ut skada som skadesystemet förväntar sig den, man gör den inte så att den är inne och petar i mekanismerna som styr hur man tar skada. Det viktiga är att för varje korsberoende fundera på om det verkligen är motiverat. Ger det så mycket att det är värt besväret för spelledaren att lära sig regeln, att administrera den och risken för problem då man ändrar i andra änden av beroendet? Är det verkligen viktigt nog för att motivera sin existens?
Den andra, vilken rent formellt antagligen är att tänja lite på begreppet, är att kapsla in krångligheterna i rätt skede. Om beräkningar krävs, gör dem i första hand när karaktären skapas, i andra hand när det inte är bråttom och först i tredje hand när man vill ha resultat direkt. Jag har själv "lånat" ett koncept i Generica där man i strid bara får reda på de stridsmässiga effekterna av skador. Hur mycket hindrar det mig? Kan jag fortfarande slåss? Först efter striden, när saker lugnat ned sig, tar man reda på hur illa skadorna verkligen är.

- Polymorphism (Mångfacetteradhet?)
Polymorphism i rollspel handlar huvudsakligen om att konsekvent använda samma mekanismer. Visst, ett slag mot en grundegenskap, ett färdighetsslag, en attack, ett turslag eller något annat slag kan operera på helt olika objekt och under olika omständigheter. Det innebär inte att de inte kan använda samma mekanism. Om man tittar på gamla AD&D så var det en katastrof i detta avseende, med olika slag för attacker, färdigheter, saves, magi, grundegenskaper och så vidare. Se till att de bitar som spelare och spelledare måste interagera med så långt som möjligt visar samma ansikte utåt. Ha så få mekanismer som möjligt, gör dem så enkla som möjligt och gör dem så lika som möjligt även om det opererar på helt olika objekt.

- Operator overloading (Interaktionsflexibilitet)
Den här är kanske den svåraste att se nyttan av i rollspelssammanhang, även om den poppar upp i vissa spel. GURPS första edition hade regler för hur man räknade om plusmodifikationer på skada till tärningar (tex blev en skada på 1D6+8 omräknad till 3D6+2 (om jag minns rätt)), D&D har det med sina dubbel skada-regler och sånt (x2 + x2 blir x3 om jag minns rätt), Vamprie och Ars Magica har det i sina skadesystem.
Jag skulle dock kunna tänka mig att detta tänkande kan användas i andra sammanhang, exempelvis kan ett magisystem ha regler för att luft+illusionism=buktaleri och så vidare.
Ska man se nyttan av det här så måste man nog tänja lite på begreppet. Man bör helt enkelt försöka göra systemet på ett sådant sätt att allt passar ihop med varannat. Saker och ting ska vara tillräckligt lika och förhållanden mellan dem tillräckligt väldokumenterade för att man ska kunna bygga ihop saker mer eller mindre ad hoc, utan att behöva ändra grundsystemet.

Summering:

Vad kan vi då vinna med det här? Kommer våra spel att bli helt revulotionerande?

Nej, antagligen kommer det inte att vara världsomvälvande, men genom att tänka strukturerat på detta sätt så får man spel som är enklare att lära sig och att spela. Vi sparar arbete, både för författaren och för brukaren. Framför allt så undviker vi att göra helt onödiga misstag som kan undvikas och som leder till onödigt krångel. Vi gör system som är enklare att modifiera, eftersom varje mekanism står på egna ben. Vi får en struktur i tanke som förhoppningsvis återspeglas i spelet och som gör det tydligare och begripligare. Vi får flexibilitet och stabilitet. Vi får system med robusta delar som hänger ihop med tydliga anslutningar och lagom glappassning för att vara tillförlitlig.

Inte stora skillnader, men många små steg i rätt riktning.

Någon som hängde med?
 

Ost

Warrior
Joined
1 Nov 2001
Messages
200
Location
Linköping
Väldigt mycket ord hördu. :gremwink: Jag tror att jag har fattat galoppen. Jag har dock en invändning i nuläget, fler kanske kommer.

Stycket om operatoröverladdning kändes väldigt krystat. Operatoröverladdning är ju i grund och botten inget mer än en förkortning av ett längre skrivsätt, som må vara snyggt men kan ställa till en del förvirring. En klassisk invändning mot operatoröverladdning är väl också att de kan ge skenbar likhet mellan två disparata objekt. Har man tidigare lärt sig att objekt A är av typ 1 och objekt B är av typ 2, så ser man helt att man vill skapa ett objekt C = A + B. Det är lätt att bli lite förvirrad, om man inte vet just hur operatorn arbetar, vilken typ den returnerar och hur den behandlar innehållet i A och B. Överladdade operatorer är inte alltid intuitiva, även om de är praktiska. OOP-förespråkare hävdar väl att det bara är idioter som blir förvirrade av detta, men i alla fall.

Vad ville jag säga med det här? Jo, att jag har svårt att applicera den tanken på rollspel. Att som du säger bygga ett system där "allt passar ihop med vartannat", tror jag är mer åt en utopi än något som är praktiskt genomförbart. Och även om det skulle vara det senare, så tror jag att genom att markera vissa avsnitts relativa oberoenden (kontra att i alla lägen försöka pressa fram uniformitet) så kan man lättare skapa sig en överskådlig bild av systemet, för man kommer intuitivt associera dess speciella "egenhet" med just det avsnittet, och ha svårare för att blanda ihop det med något annat.

Om två sidor i en bok handlar om olika saker, är det lättare att förstå ATT det är olika saker som står OM de ex. har olika färg. För mig känns det som att det då också blir lättare att relatera till de olika avsnitten i olika sammanhang, och kanske också att lära sig dem. Detta betyder inte att de två sidorna inte har någonting alls med varandra att göra, det kan de visst ha. Jag tror bara att det intuitiva, eller ja, lärandet om man så vill, underlättas om allt inte sammanblandas till en enda grå massa av likformighet. Att saker och ting hör samman kan man betona ändå, men på ett försiktigare sätt än operatoröverladdning.

Nu kanske du säger att du vill skapa ett system där man inte alls behöver betona olikheter, för det blir inga problem, det ska inte spela någon roll - en operator ska kunna användas genomgående, så man behöver inte alls göra en sida blå och en röd. Och att faran med tydliga markeringar mellan avsnitt är att sambanden förbises. Jag är varse om den problematiken men jag tycker den är bättre än alternativet - för om behovet av orientering i ett system skulle uppstå, hur går man tillväga om allt bara är en grå massa av skenbara likheter? Jag tror att behovet uppkommer hur man än gör, för i vår vardag så agerar vi ofta sekventiellt, det är intuitivt mer rätt än ett objektorienterat synsätt. Vår vardag, och även våra rollspel, är byggda av tanken att vi GÖR någonting, vi genomgår någon form av process med början och slut. Boken börjar med en introduktion och slutar med en epilog. En strid kan börja med en initiativfas och sluta med ett dödsslag. Vi vill börja någonstans, vi vill sluta någonstans, inte ha ett jätteträd av objekt att titta på. Mitt tänkande kanske inte är progressivt för fem öre, jag är väl en sån där gnällig bakåtsträvare som OOP-folk hatar... men jag kan inte hjälpa att jag tycker det känns mer "rätt".

Men sedan är jag en sådan som tycker att "mind-maps" är fullkomligt värdelösa också.

Sådär. Jag vet att jag kommer få äta upp vartenda ord... :gremsuck:
 

Troberg

Sinister eater
Joined
27 Jun 2001
Messages
17,659
Stycket om operatoröverladdning kändes väldigt krystat.
Jag vet, det var det som var svårast att applicera på rollspel.

Operatoröverladdning är ju i grund och botten inget mer än en förkortning av ett längre skrivsätt, som må vara snyggt men kan ställa till en del förvirring. En klassisk invändning mot operatoröverladdning är väl också att de kan ge skenbar likhet mellan två disparata objekt. Har man tidigare lärt sig att objekt A är av typ 1 och objekt B är av typ 2, så ser man helt att man vill skapa ett objekt C = A + B. Det är lätt att bli lite förvirrad, om man inte vet just hur operatorn arbetar, vilken typ den returnerar och hur den behandlar innehållet i A och B. Överladdade operatorer är inte alltid intuitiva, även om de är praktiska. OOP-förespråkare hävdar väl att det bara är idioter som blir förvirrade av detta, men i alla fall.
Jo, jag vet att många inte gillar det, men jag håller inte med dem av samma anledning som jag inte är rädd för makron. Man får räkna med att folk har vett att använda dem med omdöme och ofta är de enormt kraftfulla. Jag har gjort program där jag overloadat mätdygn, där varje mätdygn innehåller en komplex struktur med över 10 000 värden. Att kunna skriva sådant som Medeldygn=(Dygn1 + Dygn2 + Dygn3)/3 är en stor lättnad...

Vad ville jag säga med det här? Jo, att jag har svårt att applicera den tanken på rollspel. Att som du säger bygga ett system där "allt passar ihop med vartannat", tror jag är mer åt en utopi än något som är praktiskt genomförbart. Och även om det skulle vara det senare, så tror jag att genom att markera vissa avsnitts relativa oberoenden (kontra att i alla lägen försöka pressa fram uniformitet) så kan man lättare skapa sig en överskådlig bild av systemet, för man kommer intuitivt associera dess speciella "egenhet" med just det avsnittet, och ha svårare för att blanda ihop det med något annat.
Om två sidor i en bok handlar om olika saker, är det lättare att förstå ATT det är olika saker som står OM de ex. har olika färg. För mig känns det som att det då också blir lättare att relatera till de olika avsnitten i olika sammanhang, och kanske också att lära sig dem. Detta betyder inte att de två sidorna inte har någonting alls med varandra att göra, det kan de visst ha. Jag tror bara att det intuitiva, eller ja, lärandet om man så vill, underlättas om allt inte sammanblandas till en enda grå massa av likformighet. Att saker och ting hör samman kan man betona ändå, men på ett försiktigare sätt än operatoröverladdning.
Nu kanske du säger att du vill skapa ett system där man inte alls behöver betona olikheter, för det blir inga problem, det ska inte spela någon roll - en operator ska kunna användas genomgående, så man behöver inte alls göra en sida blå och en röd. Och att faran med tydliga markeringar mellan avsnitt är att sambanden förbises. Jag är varse om den problematiken men jag tycker den är bättre än alternativet - för om behovet av orientering i ett system skulle uppstå, hur går man tillväga om allt bara är en grå massa av skenbara likheter? Jag tror att behovet uppkommer hur man än gör, för i vår vardag så agerar vi ofta sekventiellt, det är intuitivt mer rätt än ett objektorienterat synsätt. Vår vardag, och även våra rollspel, är byggda av tanken att vi GÖR någonting, vi genomgår någon form av process med början och slut. Boken börjar med en introduktion och slutar med en epilog. En strid kan börja med en initiativfas och sluta med ett dödsslag. Vi vill börja någonstans, vi vill sluta någonstans, inte ha ett jätteträd av objekt att titta på. Mitt tänkande kanske inte är progressivt för fem öre, jag är väl en sån där gnällig bakåtsträvare som OOP-folk hatar... men jag kan inte hjälpa att jag tycker det känns mer "rätt".
Jag pratar egentligen inte om hur det ska se ut textmässigt eller layoutmässigt. Jag pratar om sådant som kan vara bra att ha i bakhuvudet när man strukturerar upp den logiska utformningen av reglerna.

Men sedan är jag en sådan som tycker att "mind-maps" är fullkomligt värdelösa också.
Jag också, de är skräp. Det finns ett perfekt sätt att strukturera information och det är en indenterad lista. Allt annat är i bästa fall näst bäst.
 

Ost

Warrior
Joined
1 Nov 2001
Messages
200
Location
Linköping
Jag pratar egentligen inte om hur det ska se ut textmässigt eller layoutmässigt. Jag pratar om sådant som kan vara bra att ha i bakhuvudet när man strukturerar upp den logiska utformningen av reglerna.
Jag pratar egentligen inte heller om text eller layout, men det var det närmaste jag kunde komma för att exemplifiera mitt tänkande och försöka förklara känslan som grodde i mig när jag läste vad du skrivit. Inte helt lyckat, jag vet.

Men förutom stycket om operatoröverladdning så är jag med på vad du säger, det är inte så tokigt sätt att se på saken när man ska skapa ett rollspel. Fast det är nog lättare att sätta sig in i för de som har sysslat med OOP "på riktigt" - som du och, i betydligt mindre mån (hobbyprogrammering + 1 års datavetenskapliga studier), jag.
 

Troberg

Sinister eater
Joined
27 Jun 2001
Messages
17,659
Men förutom stycket om operatoröverladdning så är jag med på vad du säger, det är inte så tokigt sätt att se på saken när man ska skapa ett rollspel.
Kul att höra. Jag ska i ärlighetens namn erkänna att jag inte hade någon aning om vart jag var på väg när jag började skriva. Det var ett intressant ämne som jag tyckte förtjänade att utforskas, så jag dök in med huvudet före och såg vad det blev av det.

Med andra ord, räkna inte med att allt är genomtänkt i detalj.

Fast det är nog lättare att sätta sig in i för de som har sysslat med OOP "på riktigt" - som du och, i betydligt mindre mån (hobbyprogrammering + 1 års datavetenskapliga studier), jag.
Jo, det var därför jag försökte mig på en kort populärintroduktion till OOP för de vanliga dödliga.
 

Snow

Swashbuckler
Joined
17 May 2000
Messages
2,617
Location
Klippan
Jag vet inte om jag är skadad från objektorientering (jag pular inte bara med excel, jag programmerar på riktigt också) men det mesta du säger tänker jag redan på när jag gör regler.

Det mest användbara tycker jag är inkapsling och interface. Man har ett skadesystem där man kan stoppa in skada på ett enkelt sätt. Och genom ett annat hål stoppar man in rollpersonen. Och ut trillar en dröse effekter och beskrivningar. Handlingsslaget har en effektutgång som kan kopplas till magisystemet, eller skadesystemet. Saker är som små lådor beskrivna isolerat med in och utgånger som kan kopplas till andra lådor. "Och effekten från handlingen kan du använda när du beräknar skada". Detta strävar jag alltid efter när jag skriver saker, kanske för att jag är van vid det från andra håll, som sagt.

Ärvning ser jag mest som att man strukturerar upp själva framställningen av reglerna, inte hur reglerna faktiskt fungerar. Man generaliserar saker för att beskriva regler för dem och sedan beskriver man regler för specialfallen. Grundegenskaper köps kanske på samma sätt som egenskaper och för och nackdelar, men sen går reglerna isär. Man hade kunnat skriva separata regler för grundegenskaper och färdigheter, men det blev mer lättförståeligt att ha gemensamma köpregler och sen dela på det. Och detta är ju bra.

Overloading känns inte så nyttigt för mer än några få specialfall. (jag kanske bara upprepar vad Ost säger men men)... det är ju bara att man skriver Luft+illusionism istället för Luft kombinerat med Illusionism. Eller?
 

Troberg

Sinister eater
Joined
27 Jun 2001
Messages
17,659
Ärvning ser jag mest som att man strukturerar upp själva framställningen av reglerna, inte hur reglerna faktiskt fungerar. Man generaliserar saker för att beskriva regler för dem och sedan beskriver man regler för specialfallen. Grundegenskaper köps kanske på samma sätt som egenskaper och för och nackdelar, men sen går reglerna isär. Man hade kunnat skriva separata regler för grundegenskaper och färdigheter, men det blev mer lättförståeligt att ha gemensamma köpregler och sen dela på det. Och detta är ju bra.
Jo, jag skulle nog säga det som att det här är ett område där man redan har mycket av tänkandet i sollspelen redan, även om man inte är van vid att kalla det så. Det är i vilket fall en bra mekanism för återanvändning, vilket alltid är bra för att hålla regelmängden och komplexiteten nere.

Overloading känns inte så nyttigt för mer än några få specialfall. (jag kanske bara upprepar vad Ost säger men men)... det är ju bara att man skriver Luft+illusionism istället för Luft kombinerat med Illusionism. Eller?
Jo, men man kan ju faktiskt om man vill bygga upp en hel matematik runt exempelvis magi. Vad är eld+illusionism-luft (det vill säga en magiker som använder eld och illusionism som motarbetas av luftmagi)?
 

Rising

Vila i frid
Joined
15 Aug 2001
Messages
12,763
Location
End of the green line
Först: Jag är en usel programmerare och varje gång jag måste använda objektorienterade program så går det åt helvete. Jag fattar helt enkelt inte; jag måste typ kunna följa programmet "med fingret" rad för rad i mitt huvud för att kunna göra saker. Jag hörde någon säga att sådana som jag aldrig kan lära oss bli riktiga programmerare; vi har blivit besudlade.

För egen del så kan jag inte annat göra än att hålla med.

Jag hajjar exempelvis inget när folk gör exempel med bilar och säten och sånt. Problemet för mig, som tydligen inte kan tänka objektorienterat, är att jag ser allt med perspektivet "när" något görs, samt "vad" något gör.

Det här med arv, exempelvis. Du skriver att en individuell rollperson ärver saker som "barbar" och "alv". Jag tänker då så här: "ahaa! poängen med arv är alltså om jag ändrar vad det innebär att vara alv och barbar; då ändras alla rollpersoner som ärvt attributen "alv" respektive "barbar"; jag behöver bara ändra på ett ställe för att alla rollpersoner som ärver alv och barbar ska ändras!" Men det är ju sällan sant i rollspelen. Tvärtom är det ofta så att "barbar" bara betyder något när man väl genererar sin rollperson. Alla gamla barbarer kommer vara oförändrade även när man ändrar vad det innebär att vara en barbar.

Så det är inget arv i mina ögon, jag som inte kan tänka objektorienterat. För mig är hela prylen med "barbarer" något som jag placerat tidigt i min programmeringskod; innan min mainloop.

NÄR något skall ske, det är alltså i fokus för mig.

Samma sak med enkapsulation. Du tar ett exempel med en besvärjelse som gör skada på en gång, enligt huvudreglerna, och en annan besvärjelse som ändrar sättet man tar skada på. Du gillar inte det andra sättet eftersom det påverkar huvudreglerna, men i mina ögon är dess fel att dess svar på frågan "när?" inte är "nu!" utan "från och med nu"; det senare är betydligt krångligare i vanlig programmering (och även svårare att administrera i rollspel).

Jag har inget principiellt problem med en regel som ändrar något i huvudreglerna så länge det bara påverkar någonting "nu". Besvärjelsen "rost" i gamla DoD är ett bra exempel; som ursprungligen hade räckvidden "beröring" fastän magiker ju inte enligt grundreglerna får ha kontakt med järn. Jag tycker det var enkelt att administrera ändå (det enda problemet var väl att motivera hur det kunde gå till och hur det fungerade i världen; men regelmässigt hade jag inget problem med det)

Så jag fattar nog inte. Så som jag upplevt objektorienterad programmering (men jag är alltså en totaln00b) så är poängen att man ska kunna göra många olika saker samtidigt; alltså att man ska kunna skicka en grej till en del av programmet medan en annan grej sysslar med annat (om vi talar om spelprogrammering så är det väl mest att man exempelvis kan programmera en Lakitu som då och då kastar ut en spiksköldpadda, och så får varje spiksköldpadda vara ett objekt som i sig har programmeringsintruktioner om att dö när de får en eldboll på sig eller att döda Mario om han hoppar på dem. Jag hatar den inställningen till programmering också, eftersom jag vill kunna bestämma och ha översikt över NÄR programmet undersöker om någon av Marios eldbollar träffar en viss spiksköldpadda. När dessa instruktioner är skilda från min mainloop så kan alltid konstiga saker inträffa, bara för att instruktionerna råkar ske i fel ordning). Om jag skulle göra ett objektorienterat rollspel så skulle det typ funka så att en spelare slog fram skadan, gav en instruktion åt motståndarspelaren att beräkna deflektion och absorbtion medan en tredje deltagare beräknade skademodifikationer och två andra deltagare väntade på instruktioner så att de kunde få börja beräkna trauma och om det skedde några kritiska skador. Och det skulle låta ungefär så här "10 skada!" "Okej, han svimmar av chocken!" "Nä, vänta, rustningen absorberar 4 poäng." "Jaha, sex skada på en svimmad varelse, det modifieras med x2 upp till 12." "Han dör." "Men vänta nu, om vi hade gjort det här i en annan ordning så hade vi ju fått ett helt annat resultat" "Ja, men Rising suger på objektorienterade program, så det går som det går..."

Eller så har jag inte fattat någonting. Det blir iaf fel varje gång jag försöker. Är jag bortom räddning?
 

Troberg

Sinister eater
Joined
27 Jun 2001
Messages
17,659
Först: Jag är en usel programmerare och varje gång jag måste använda objektorienterade program så går det åt helvete. Jag fattar helt enkelt inte; jag måste typ kunna följa programmet "med fingret" rad för rad i mitt huvud för att kunna göra saker. Jag hörde någon säga att sådana som jag aldrig kan lära oss bli riktiga programmerare; vi har blivit besudlade.
Jag tror att du kan lära dig det, jag var lika totaltkörd från början efter att ha haft en lärare som exemplifierade med kungliga elefanter. Insikten kommer, som vanligt, oftast först när man börjar se att det man kan inte räcker till och man börjar se andra lösningar som passar in i ett nytt mönster som det lossnar.

Det enklaste är oftast att se på klasserna som Type (i Basic) eller Struct (i C) on steroids. Om du inte testat dem så är det ett sätt att göra komplexa variabler, tex:

<pre>
Type Monster
Typ as string
Namn as string
Hitpoints as integer
Skada as integer
End Type </pre>



På så sätt kan man sedan göra saker som:

<pre>
Dim otäcking as Monster
otäcking.Namn="Troberg" </pre>



OK, där har vi paketerat data på ett behändigt sätt. Sedan vill man ha en ny typ av monster med nya egenskaper. Istället för att skriva om hela köret där uppe och dubblera all kod man skrivit som bruka Monster så ändrar man till något i stil med följande:

<pre>
Class Monster
Typ as string
Namn as string
Hitpoints as integer
Skada as integer
End Class

Class PerverstMonster
Inherits Monster
Perversion as string
End Class </pre>



Genom att göra om Type till Class så kan vi alltså ärva den. Vi kan fortfarande betrakta ett PerverstMonster som ett Monster, men det har även en extra egenskap, Perversion. Vi kan alltså skriva:

<pre>
Dim pervert as PerverteratMonster
pervert.Namn="Rising"
pervert.Perversion="..." </pre>



Vi kan också använda en Class som mer än ren datalagring. Den kan också innehålla körbar kod. Exempel:

<pre>
Class Monster
Typ as string
Namn as string
Hitpoints as integer
Skada as integer

Function BliSkadad(HP as integer) as string
Hitpoints-=HP
return "Ouch, lägg av med det där för fan!"
End Function
End Class

Class PerverstMonster
Inherits Monster
Perversion as string

Shadows Function BliSkadad(HP as integer) as string
Hitpoints-=HP
return "Oh yeah, snälla mer!"
End Function
End Class </pre>



Denna kod kan sedan anropas med (förutsatt att vi deklarerat variabler enligt ovan):

<pre>
otäcking.BliSkadad(10)
pervert.BliSkadad(10) </pre>



Här ser vi många bra saker. Vi kan avlasta den anropande koden från mycket formalia genom att låta varje objekt själv hålla reda på hur det ska reagera på olika omständigheter. Vi har kapslat in logiken om hur skada fungerar för monstret så att den som anropar bara behöver veta att han gör skada. I det här exemplet är det ju enkelt, men om det är mer komplexa saker som ska göras, typ kontrollera om man dog av smällen, emaila en beställning av en gravsten och så vidare så gör det definitivt den anropande koden renare. Vi kan också se hur man vid arv kan ändra beteendet hos objektet, PerverteratMonster reagerar inte på samma sätt som Monster, men de svarar fortfarande på samma anrop och samma kod kan användas för att anropa dem.

Med andra ord, när jag anropar något i PerverteratMonster så kör den i första hand det som finns där, i andra hand, om inte PerverteratMonster har något, går den upp till basklassen Monster och kör koden där.

Det kan ta ett tag att greppa hur man hoppar runt i koden, men börjar man i såna här enkla exempel så brukar det funka bra.

Det här med arv, exempelvis. Du skriver att en individuell rollperson ärver saker som "barbar" och "alv". Jag tänker då så här: "ahaa! poängen med arv är alltså om jag ändrar vad det innebär att vara alv och barbar; då ändras alla rollpersoner som ärvt attributen "alv" respektive "barbar"; jag behöver bara ändra på ett ställe för att alla rollpersoner som ärver alv och barbar ska ändras!" Men det är ju sällan sant i rollspelen. Tvärtom är det ofta så att "barbar" bara betyder något när man väl genererar sin rollperson. Alla gamla barbarer kommer vara oförändrade även när man ändrar vad det innebär att vara en barbar.
Jag håller med om att den historikhanterande biten inte kommer med automatik i OOP, något jag som ställt till det för en del som inte fattat att man måste hantera det själv och därmed kört projekt helt i botten.

Jag tror att du snarare ska tänka i termer, speciellt kring rollspel, där man har en packe regler som gäller för alla i begreppet Karaktär. De motsvarar Typ, Namn, Hitpoints, Skada, BliSkadad i exemplet ovan. När man sedan gör en Barbar, vilken ärver från Karaktär, så får man möjligheten att lägga till och ändra saker i dessa regler. Barbaren kanske bara tar halv skada i BliSkadad och har dessutom möjligheten att lägga till nya regler och egenskaper som tex HöftSkynkesSkitighet.

Vi ska dock inte glömma att det vi ändrar här är klassen, det vill säga mallen för hur barbarer ser ut. Instansen, det vill säga en enstaka variabel av typen Barbar lever ju till viss del ett eget liv.

Jag har inget principiellt problem med en regel som ändrar något i huvudreglerna så länge det bara påverkar någonting "nu".
Nej, jag tror missförstår lite. Med inkapsling menar jag att man inte går in och petar på insidan i andra regler. I exemplet ovan så får inte anropande kod gå in och pilla med returvärdet från BliSkadad. Det är intern logik. På samma sätt så bör man när man skriver regler från början tänka på vilka justerskruvar de ska ha och hur man ska interagera med dem. Dessa ska man sedan hålla sig till och inte gå in och tjuvkoppla in regler under huven på regelpaketet eftersom det gör reglerna krångliga att följa och överblicka.

Om man exempelvis har ett traditionellt "Nöta ner HP-skadesystem" så gör man skador så att de nöter ner HP. Man använder det gränssnitt som skadesystemet exponerar för ändamålet. Lägger man in ett vapen som gör att när man blir skadad så delas man upp i två, hälften så stora personer, ända tills de är så små att de är harmlösa, så skapar kommer det ofelbart att orsaka störningar med massor av andra regler.

Så jag fattar nog inte. Så som jag upplevt objektorienterad programmering (men jag är alltså en totaln00b) så är poängen att man ska kunna göra många olika saker samtidigt; alltså att man ska kunna skicka en grej till en del av programmet medan en annan grej sysslar med annat (om vi talar om spelprogrammering så är det väl mest att man exempelvis kan programmera en Lakitu som då och då kastar ut en spiksköldpadda, och så får varje spiksköldpadda vara ett objekt som i sig har programmeringsintruktioner om att dö när de får en eldboll på sig eller att döda Mario om han hoppar på dem. Jag hatar den inställningen till programmering också, eftersom jag vill kunna bestämma och ha översikt över NÄR programmet undersöker om någon av Marios eldbollar träffar en viss spiksköldpadda. När dessa instruktioner är skilda från min mainloop så kan alltid konstiga saker inträffa, bara för att instruktionerna råkar ske i fel ordning).
Nej, OOP kör en sak åt gången precis som vilken traditionell kod som helst, såvida man inte ger sig på multithreading, precis som vilken traditionell kod som helst.

Skillnaden ligger oftast i att i traditionell programmering så har du din mainloop som i tur och ordning klockar genom de saker du vill göra, medan man i OOP oftast låter händelser styra programmet.

I ett spel har man dock normalt sett en mainloop, även om den inte är en loop utan en händelse som sker X antal gånger per sekund baserat på en timerhändelse (eller egentligen på en skärmsync).
I den säger du åt Lakitu att nu har det gått en tick till, så gör vad du ska. Kastar han ut en spiksköldpadda så läggs den till listan över spikskölpaddor.
När Lakitu är klar med det så kommer du tillbaka till den anropande koden och säger i tur och ordning till spiksköldpaddorna att göra sin grej.
Sedan kollar du vilken knapp spelaren tryckt och talar om det för Mario så att han kan göra sin grej.
Sedan kollar du listan över monster, är den tom så har Mario rensat banan och det är dags att visa segersekvensen, är han död växlar man till dödssekvensen.

Något i stil med (pseudokod):

<pre>
Sub Timer()
Lakitu.DoStuff()
For Each Spiksköldpadda in Monsterlista
SpikSköldpadda.DoStuff()
Next
Mario.DoStuff(knappar)
If Mario.IsDead() then
DödsSekvens()
Elseif MonsterLista.Count=0
SegerSekvens()
Endif
End Sub
</pre>




Man kommer alltså inte vidare till spiksköldpaddorna förrän Lakitu är klar, och man tittar inte vad Mario gör förrän spiksköldpaddorna är klara osv. Det körs inte samtidigt om man inte jobbar häcken av för att lägga det i olika trådar, vilket i princip aldrig används i spel (Även om vi nog kommer att se mer av det med de nya multicore/hyperthreading-processorerna eftersom det är ända sättet att skrämma ut lite prestanda ur skräpet. Jäkla fattigmansmultiprocessorripoff.).

Edit:

Man kan ju naturligtvis göra det på traditionellt sätt och lyfta ut koden i funktioner som manioulerar datastrukturer, då skulle den se ut något i stil med:

<pre>
Sub Timer()
DoLakitu()
For Each Spiksköldpadda in Monsterlista
DoSpikSköldpadda()
Next
DoMario(knappar)
If MarioIsDead then
DödsSekvens()
Elseif MonsterLista.Count=0
SegerSekvens()
Endif
End Sub
</pre>



Ingen större skillnad här alltså, men en enorm skillnad i kodstruktur eftersom varje objekt står på egna ben och innehåller den kod som berör det. Var sak på sin plats alltså, allt som har med Lakity att göra ligger i Lakitu-klassen, inte utspridd i ett antal hanteringsfunktioner.

Objektorientering är egentligen inget som ändrar någonting i stort, det är bara ett sätt att organisera koden. Det här är ett vanligt missförstånd, många tror att det är något magiskt. C++ är egentligen inte ens ett programmeringsspråk, det är bara en precompiler som gör om lite makron till C-kod som sedan kompileras. Man kan alltså formellt sett skriva C++ i vanlig C genom att skriva motsvarande kod som precompilern skulle genererat.

Allt är bara olika notationer för arbetsorders för datorn. Varken mer eller mindre.

Edit: Alla likheter med verkliga personer är tillfälliga och namnen är fingerade i vilket fall.
 

Herr Brownswick

Veteran
Joined
28 Aug 2001
Messages
59
Location
Onorrland
C++ är egentligen inte ens ett programmeringsspråk, det är bara en precompiler som gör om lite makron till C-kod som sedan kompileras
Något som var sant tidigare i historien, men C++kompilatorer idag går sällan via C. Men det är en kompileringsteknik som används av åtskilliga programmeringsspråk för att på ett enkelt sätt vara enkla att sprida till olika plattformar, plus att C-kompilatorer är mycket kraftfulla. Trots det är C++ per definition ett programmeringspråk, precis som bland annat Objective-C och Cyclone, Beta, CLU och Self; som alla använder C-kompilatorer idag för att skapa exekverbar kod. Äkta C++kompilatorer har funnits i många många år.
 

Troberg

Sinister eater
Joined
27 Jun 2001
Messages
17,659
Re: OOP & RPG [OT]

Något som var sant tidigare i historien, men C++kompilatorer idag går sällan via C.
Det ändrar ingenting. Det faktum att C++ är så lika traditionell C att det kan implementeras som några makron i C gör att det knappast motiverar att betraktas som ett eget språk.
 

Ost

Warrior
Joined
1 Nov 2001
Messages
200
Location
Linköping
Skojig länk (OOP men inte RPG) [OT]

Jag drog mig till minnes den här länken, som går till vad som torde vara Internets hårdaste OOP-kritiker. 2:a träffen på Google om man söker på "OOP". Den är rätt kul... på ungefär samma sätt som Jack Chicks serier. :gremsmile:

http://www.geocities.com/tablizer/oopbad.htm
 

Herr Brownswick

Veteran
Joined
28 Aug 2001
Messages
59
Location
Onorrland
Re: OOP & RPG [OT]

I sådana fall kan du räkna in alla språk dit. Samtliga sentida konstruktioner (från 50-talet och framåt) går att få fungera i C till och med högfunktionella saker som arv och polymorfism, AOP och metaprotokoll. Så frågan är ju vad du ser som ett programmeringspråk?
 

Olle Linge

Snigel
Joined
23 Oct 2003
Messages
2,882
Location
北極東邊
OT-moderering

Trådstartaren har tagit upp den (imho) intressanta kopplingen till rollspel och hur man kan koppla OOP till att konstruera rollspel. Vilka programmeringsspråk som räknas var har dock inget med rollspel att göra och tas lämpligen någon annanstans.
 

liftarn

Veteran
Joined
28 Dec 2004
Messages
61
Location
Stockholm
Jag vet inte om det kommer tillföra någonting då det är människor som måste köra "programkoden". En variant av iden som jag gillar skarpt är färdighetssystemet i Paranoia. Det var byggt på ett slags arv. Om man var expert på prickskyttegevär blev man automatiskt bra på alla gevär och hygglig på pistol. Det är ju både enklare att administrera och mer relistiskt än om man skulle kunna vara expert på färdigheten "flyga jetplan" men bara ha grundchansen om man satt i ett propellerplan.
 

Troberg

Sinister eater
Joined
27 Jun 2001
Messages
17,659
Jag vet inte om det kommer tillföra någonting då det är människor som måste köra "programkoden".
Jag menar egentligen inte det på det sättet. OOP är inte ett sätt att förenkla för den som kör koden (dvs datorn), tvärtom så ger det kod som är svårare och mindre effektiv för datorn att jobba med. Däremot är det ett sätt att strukturera upp koden för att göra det enklare för den som ska läsa och förstå den, vilket i sin tur gör att man kan göra större program på mindre tid på ett stadigare och mer ordnat sätt, vilket också gör att man tenderar att skriva bättre program.

Detsamma kan förresten sägas om assembler kontra högnivåspråk. Assembler är onekligen effektivare, men koden blir strulig att läsa och programmet tappar fort strukturen, vilket gör att programmeraren börjar göra dåliga beslut som leder till mer ineffektivitet än vad högnivåspråket lägger på.

Se det som tankeverktyg för att organisera saker, ungefär som kom-ihåg-listor eller grafer.
 

liftarn

Veteran
Joined
28 Dec 2004
Messages
61
Location
Stockholm
Nja, OOP är visserligen till hjälp för programmeraren men slutmålet är ändå att skapa kod för datorer. Om det istället är människor som ska köra koden är det inte säkert att det är det mest optimala beroende på att människor och datorer (faktiskt) skiljer sig åt.

Apropå arv så provade jag PlaneShift och där hade man ett intressant system för att skapa en rollperson. Man fick bl.a. ange vad ens föräldrar hette och jobbade med och sedan händelser från barndomen samt vad man själv jobbar mer. Detta ligger sedan till grund för färdigheterna i spelet. t.ex. om ens mamma var berömd svärdsmästare är man antagligen inte helt borta på det även om man själv jobbar som bartender. Om man i barndomen klättrade runt på hustaken fick man samtidigt färdigheter som kan vara bra som vuxen.
 

Magnus_UBBT

Veteran
Joined
28 May 2000
Messages
39
Location
karlstad
Mjo. Ja och nej. Det förutsätter ju att man faktiskt hängt med sina föräldrar, något som inte är givet. Min farsgubbe är skogshuggare, och mamma är sjuksyrra. Jag jobbar inte med endera, och även om jag har en smula underliggande teoretisk kunskap efter att ha pratat med mina föräldrar om vad de gör på dagarna, har jag väldigt begränsad tillämpningsbara kunskaper inom de båda fälten. Säkert mer än någon som har växt upp med andra föräldrar, och andra fält, men det är inte givet att den skillnaden ens är kvantifierbar.

Och även om anlag förs vidare är det inte säkert att ett anlag ger samma effekter i två olika miljöer.

"If you want sperm that produces Nobel Prize winners you should be contacting people like my father, a poor immigrant tailor. What have my sperm given the world? Two guitarists!"

(Biokemisten George Wald, efter att ha tillfrågats om en donation till William Shockleys spermabank för nobelpristagare.)
 

Krille

Super Moderator
Joined
7 Feb 2000
Messages
29,540
Location
Mölndal, Sverige
MMI & RPG

Personligen så tror jag att OOP inte hör hemma i rollspel, utom möjligen i D&D som redan har klasser och arv. Jag tror mer på MMI (Människa-Maskininteraktion).
 

liftarn

Veteran
Joined
28 Dec 2004
Messages
61
Location
Stockholm
Jo, fast om det är en fantasyvärld där ungarna antagligen hänger med föräldrarna på deras jobb från tidig ålder blir det en annan sak än en modern väld där skolan står för merparten av utbildningen.
 
Top