Dialog - Een programmeertaal voor dialogen.

ArticleCategory:

Software Development

AuthorImage:

Philipp Gühring

TranslationInfo:

original in de Philipp Gühring 

en to nl Tom Uijldert

AboutTheAuthor:

Philipp heeft net zijn examens gedaan bij de HTL Wiener Neustadt, een HTS voor EDP (Electronic Data Processing). Daarom heeft hij nu tijd voor zijn software ontwikkelgroep genaamd Futureware 2001. Hij is een fan van Linux en een actief lid van de Linux User Group Austria.

Abstract:

Dialog is een programmeertaal, speciaal voor dialogen met de gebruiker. Het werd gebruikt in de handelscursus Würstelstand. Dit artikel beschrijft de ontwikkeling van Dialog en zijn toepassingen.

ArticleIllustration:

Josi, één van de klanten

ArticleBody:

Inleiding

Würstelstand is een handelssimulatie spel in het Duits, waarbij de speler een hotdog kraam moet bestieren. Het contact met de klanten werd daarbij bijna een adventure game. Juist voor dit klantencontact heb ik de taal Dialog ontwikkeld, die aan de volgende wensen moest voldoen:

Toen ik telefoongesprekken moest implementeren, heb ik het principe van het dialoog algoritme gebruikt en dit verbeterd. De speler bepaalt wat de figuur Leni, de eigenaar van het hotdog kraampje, doet middels het meerkeuze systeem. De klanten worden door de computer gespeeld. Doel van de speler is om klanten adviezen te geven, ze iets te verkopen en om een praatje met ze te maken. Klanten melden zich automatisch aan wanneer ze hongerig zijn en even de tijd hebben. Tevens heeft de speler de mogelijkheid om zelf actief te wezen en om diverse nummers op zijn telefoon te bellen.

De taal Dialog

De dialogen worden opgeslagen in ASCII tekstbestanden en worden regel voor regel geïnterpreteerd, hoewel het is toegestaan om op ieder moment naar andere regels te springen. We gebruiken een eenvoudige editor voor het creëren van de dialogen. De naam van het bestand is naam.BAT (bijvoorbeeld HALE.BAT). Als de speler (Leni) iets zegt:
Leni: Tekst
Leni: Goedemorgen meneer! 
      Wat kan ik voor U doen?
Leni: Kijk toch eens naar die jeugd!
      Het is toch wat!
Leni zegt wat
Kijk toch eens naar die jeugd! Het is toch wat!
Uit je bed gevallen?
Klant zegt wat
Twee broodjes Frankfurter en een Coke. Schiet eens op, ouwe man!
Wanneer de tegenspeler iets zegt (Kunde is klant in het Duits, Telefon is telefoon):
Kunde: Tekst
Kunde: Twee broodjes Frankfurter en een Coke.
       Schiet eens op, ouwe man!
Telefon: Futureware 2001, Philipp Gühring.
         Wat is er van uw dienst?

Iedere dialoog eindigt met:

Ende
(Ende is einde in het Duits).

Een eenvoudig voorbeeld:
Leni: Morgen, meneer! Wat is er van uw dienst?
Kunde: Goedemorgen! Een Käsekrainer alstublieft!
Leni: Momentje.
Leni: Alstublieft.
Kunde: Bedankt. Dag!
Leni: Dag!
Ende

Regels waar je naar toe kunt springen worden aangegeven met een dubbele punt (:) aan het begin van de regel waarna de naam van de regel volgt waarnaar kan worden gesprongen. Er kan naar de regel toe worden gesprongen met het commando Sprung (Sprung is springen in het Duits):

:Target
//Voorbeeld sprongopdracht volgt:
Sprung Target

Voorbeeld
...
Leni: 1
//Eerst doen we dit
SPRUNG MENU_0
//Tot straks!
...
//Deze commando's worden niet uitgevoerd
Leni: 2
:MENU_0
//Ben ik weer!
Leni: 3
Wat doet de interpretator met dit voorbeeld? Allereerst ziet hij het commando Leni: en voert de tekst uit 1. De volgende regel bevat commentaar (Eerst doen we dit) wat wordt overgeslagen. De volgende regel bevat de opdracht Sprung. De interpretator gaat nu op zoek door de gehele dialoog naar een regel met de naam MENU_0, vindt deze een paar regels verderop en springt er heen. Vervolgens meer commentaar (Ben ik weer) en het laatste commando is Leni:, die het getal 3 op het scherm zet. Uiteindelijk is dus de opdracht Leni: 2 overgeslagen en zal Leni dus geen 2 zeggen.

Zoals we hebben kunnen zien kan een regel:

Commentaar wordt aangegeven met ; (puntkomma), // (twee schuine strepen), spatie, * (asterisk). Dit is er ter verbetering van het begrip en als documentatie van de dialoog en wordt daarom door de interpretator overgeslagen. Bijvoorbeeld:
// Dit is commentaar
**************************************
*Zo kun je ook commentaar maken      *
**************************************
Commentaar kan niet op dezelfde regel als commando's voor komen.
Leni: Ik begrijp niks meer.  // GEEN COMMENTAAR
De interpretator zal Ik begrijp niks meer. // GEEN COMMENTAAR herkennen als zijnde de tekst die op de uitvoer moet komen!

Het meerkeuze systeem

Meerkeuze
  • Voor wie werk je?
  • Vind je mijn kraampje leuk?
  • Wat kan ik voor je doen?
Dialog heeft het volgende systeem: het houdt een lijst bij die door de gebruiker wordt aangeleverd waarin de mogelijke antwoorden staan vermeld. Op het moment van uitvoeren zal een menu op het scherm worden getoond. De speler kan nu kiezen en het systeem zal naar het gedeelte springen wat die keuze afhandelt.

Allereerst worden lijstelementen ingevoegd met behulp van de commando's NEU en ALT. Beide opdrachten worden gevolgd door de naam van de regel, waarnaar moet worden gesprongen, en de tekst voor deze keuze. De tekst kan iedere grootte hebben, het systeem zal deze automatisch netjes opmaken. Met de opdracht MENÜ wordt de gehele lijst getoond en de speler kan nu een keuze maken.



Er zijn drie soorten keuzemogelijkheden:

Onderwerpen, afhankelijk van de context

Dit type is bruikbaar voor discussies:
Neu buy,Warme hotdog, zoals altijd?
Neu work,Hoe gaat het op het werk?
Neu language,Doe je nog steeds die taalcursus bij WIFI?
Neu family,Hoe gaat het met het gezin?
Neu weather,Mooi weertje, niet?
Menü
Hiermee is de speler in staat om alle keuzes af te lopen, één voor één. De keuzes zijn herbruikbaar. De niet gekozen elementen blijven in de lijst staan en kunnen op een later tijdstip alsnog worden gekozen. Laten we werk kiezen uit bovenstaand menu.
:work
Leni: Hoe gaat het op het werk?
Kunde: Druk, druk, druk, zoals altijd.
Menü
Zoals gezegd, wordt alleen de betreffende keuze weergegeven. Het menu heeft dan nog de volgende onderwerpen: Hoe dan ook, er zijn nog twee soorten keuzemogelijkheden.

Opties, afhankelijk van de context

Kunde: Hoeveel wilt U er?
Alt some, 10 Stuks
Alt more, 20 Stuks
Alt most, 100 Stuks
Menü

:some
//Hier gaan we verder bij een keuze van 10 stuks

:more
...

:most
...
Omdat het geen zin heeft om de opties nog langer te handhaven na het maken van de keuze, wordt de rest van het menu automatisch weggegooid. Wanneer de speler bijvoorbeeld 20 stuks kiest, zal de interpretator naar de regel more springen.
:more
Kunde: Zeker weten?
Leni: Ja, ik wil er 20.
Kunde: Hoe snel moet U ze hebben?
Alt 1, Morgen
Alt 2, Overmorgen
Alt 3, Een keer
Menü
Als laatste is er nog een combinatie van de twee soorten.

Context, veranderen van onderwerp

We hebben hiermee nog een andere subtiele mogelijkheid gecreëerd. Als een onderwerp met de gesprekspartner is besproken maar men nog wel wat te vertellen heeft, kan men op het onderwerp doorgaan of van onderwerp veranderen. Als het onderwerp wijzigt wordt de context voor de andere keuze onzinnig. Men kan dus van onderwerp veranderen of bij het onderwerp blijven. In Dialog is dit als volgt geïmplementeerd: de keuze verschijnt normaal in het menu, samen met ander onderwerpen. Alle opties die bij de keuze horen zullen worden verwijderd. Alle andere, niet gekozen, onderwerpen blijven staan.
Kunde: Ach, die goeie ouwe tijd.
Alt Memory,Jazeker, ik kan me nog herinneren dat ...
MENÜ

Implementatie

Je vraagt je waarschijnlijk af hoe dit alles nu is gerealiseerd. En opgemerkt dat het onderscheid ligt in het gebruik van NEU en ALT. Als een keuze met NEU in de lijst wordt gezet dan blijft de keuze staan, behalve als dát de keuze is. Als het met behulp van ALT gedaan is wordt het automatisch na de keuze verwijderd, of dit nu het gekozene is of niet.

Meerdere lijsten

Wat gebeurt er nu als er een keuze moet worden gemaakt over een onderwerp maar men wil geen andere onderwerpen laten zien in het menu? Hiervoor heb ik niet één maar drie lijsttypen aangemaakt.

List 0 is te gebruiken voor opties. List 1 is voor algemene onderwerpen als gezin, werk, ontspanning etc... Als men bijvoorbeeld over het werk wil praten en er meerdere onderwerpen zijn binnen het begrip werk, dan gebruikt men List 2. We hebben een voorbeeld in de HALE-dialoog. Indien men meer lijsten nodig heeft dan de drie die hier zijn genoemd dan moet er een constante in de code worden veranderd.

Hoe de diverse lijsten te gebruiken?

List 1 is normaal gesproken de huidige lijst. Met het commando LISTE kan een andere lijst als huidige worden gedefinieerd.
LISTE 0
LISTE 1
LISTE 2
Uiteraard blijven alle keuzes in deze lijsten bij dit proces. Opdrachten als NEU, ALT, MENÜ en LÖSCHEN slaan altijd op de huidige lijst.

Voorbeeld meerdere lijsten

Veronderstel de volgende keuzes: De gebruiker kiest Gezin en de gesprekspartner vraagt: "Heb je soms problemen met je gezin?". De speler krijgt nu de keuze: Nadat de speler echter het onderwerp heeft bepaald, blijven de keuzen Werk, Eten en Dag staan, terwijl dit geen valide keuzen meer zijn na de vraag of er soms problemen zijn. De resterende keuzes moeten dus uit zijn geschakeld (weg arceren) zolang er geen antwoord op de vraag is.
Dit gaat dan als volgt; we zetten de gespreksonderwerpen in List 1 en voordat we antwoorden in de lijst zetten, schakelen we om naar List 2 (LISTE 2) en we voegen de antwoorden toe: en aktiveren het menu met MENÜ.
Hier kan de gebruiker kiezen tussen Ja en Nee, de rest is weggearceerd. Na het bespreken van het gezin, kunnen we terug naar List 1 (LISTE 1).
Hierin staan nog steeds de overige onderwerpen die we kunnen aktiveren met MENÜ.
De gespreksonderwerpen worden nu weer normaal getoond en daaruit kan vervolgens worden gekozen.

Dialog oude stijl

In oudere versies van Dialog, gebruikt voor Würstelstand, werden keuzemogelijkheden anders behandeld: in plaats van het gebruik van ALT werd er een paragraaf toegevoegd aan de opdracht NEU:
Neu Memory,Jazeker, ik kan me nog herinneren dat ...
Lijst 0 werd automatisch na het menu weggegooid en was daarom alleen bruikbaar voor opties, niet voor onderwerpen.

Het is aan te bevelen om te kijken naar de voorbeelden HALE.BAT en PETER.BAT, waar veel gebruikt wordt gemaakt van lijsten.

LÖSCHEN target
Gooit alle elementen uit de lijst weg die naar target verwijzen. Bijvoorbeeld:
LÖSCHEN familiy
Om de gehele lijst te verwijderen gebruikt men de asterisk:
LÖSCHEN *
(Indien er behoefte bestaat, kan men hier ondersteuning voor reguliere expressies inbouwen ;-).

Menü laat alle elementen uit de lijst zien en geeft gelegenheid tot het maken van een keuze. Hierna wordt de keuze, met alle toegevoegde opties (ingebracht met ALT), uit de lijst verwijderd. Als laatste springt de interpretator naar de aangegeven regel. Als er slechts één element als keuzemogelijkheid is, heeft het programma door dat dit de enige keuze is en wordt er dus geen menu gepresenteerd. Als de lijst leeg is of de aangegeven regel niet bestaat, zal de regel direct na het menu worden uitgevoerd.

Interfaces

Hoe kan de dialoog reageren op zijn omgeving, deze beïnvloeden en data uitwisselen met andere dialogen?

Geheugen/Registers

Bij Würstelstand heeft iedere dialoog toegang tot 256 registers. Ieder register bevat een getal tussen -2 miljard en +2 miljard. De 256 registers zijn verdeeld in drie delen:

Systeem registers

De eerste 100 registers (0 tot 99) zijn gereserveerd door het systeem: de waarden worden ingeladen voordat met de dialoog wordt begonnen, zodat kan worden gereageerd op de omgeving. Alle registers die zijn aangegeven met //S worden onderzocht na het einde van de dialoog. Dat is de invloed van het gesprek. Hier is de lijst van systeem registers van Würstelstand:
1Event; //Het nummer van de gebeurtenis (kijk in texte.h).
2geliefert;//S//0-10, hoeveel tienden zijn geleverd
3wtag; ////dag van de week
4tag; //dag van de maand
5monat; //maand
6jahr; //jaar
7Datum; //serienummer van de dag (1.1.1997 = 0)
8wetter; //het weer van vandaag
9konto;//S//banksaldo
10kapital;//S//cash
11ausgaben;//S//uitgaven van vandaag
12einnahmen;//S//inkomsten van vandaag
13sterne;//S//kwaliteit van de hotdog kraam (0-5 sterren)
14wverkauf; //aantal verkocht deze week
15weinnahmen; //wekelijks inkomen
16wausgaben; //wekelijkse uitgaven
170;//S//nieuwe inkomsten/uitgaven (ingebracht door de dialoog)
18Nachrichtenserie; //welke serie nieuwsberichten (0=iedere, 1=...)
19Nachricht; //welk nieuwsfeit uit de huidige serie (0=1ste dag, 1=2...)
20LottoNr[0]; //Hoeveel loten worden gebruikt (0-6)
21LottoErgebnis[0]; //Hoeveel loten hebben gewonnen
22LottoGewinn[LottoErgebnis[0]]; //Hoeveel Leni won
23S.Image;//S//Portret van Leni
24S.Override;//S//Interrumperende gebeurtenis
25S.wverkauf[1]; //Vorige week verkochte producten
26S.weinnahmen[1]; //Inkomsten van vorige week
27S.wausgaben[1]; //Uitgaven van vorige week
28S.wverkauf[2]; //Twee weken geleden verkochte producten
29S.weinnahmen[2]; //Inkomsten van twee weken geleden
30S.wausgaben[2]; //Uitgaven van twee weken geleden
31S.NOverride;//S//Interrumperende gebeurtenis voor morgen
32S.wetter_bericht; //Welk weerbericht
33Gesamtwert(); //Totale waarde van de kraam
34Wetterbericht[S.wetter_bericht].Ereignis; //Welk weertype
35Tageszeit; //tijd van de dag in minuten
70..79Lagermenge //aandelen
80..89Verkaufspreis//S//prijs van het product
90..99Kaufmenge//S//aantal in bestelling

Dialoog registers

De volgende 100 registers (100 tot 199) zijn gereserveerd voor elke dialoog. Ze worden op nul gezet bij de start van het spel en behouden hun waarde binnen de dialoog gedurende het spel. Waardes worden opgeslagen in "...savegames..." en kunnen alleen via hun dialoog worden bereikt. Het systeem noch andere dialogen kunnen de registers lezen of veranderen. Aan het begin van de dialoog moet worden vastgelegd welke dialoogregisters moeten worden gebruikt en waarvoor.

batch.cpp
// Klant: Peter Hinzing 
// 
// Gebruik van de registers
//[100] Hoe vaak hij hier was
//[101] Zakgeld
//[102] Diverse gebeurtenissen
//[103] Willekeurig nummer: bestelling
//[104] Willekeurig nummer: antwoord op bestelling
//[105] Andere dialogen: werken op de 5de dag
//[106] Ok
//[107] Start van het spel, na verkiezing
//[108] Game.stake.type
//[109] Game.stake.quantity
//[110] Game.choose.Peter
//[111] Game.choose.Leni
//[112] Hobby geactiveerd
//[113] Thuis geactiveerd
//[114] Dialoog over Würstelstand
//[115] Hoeveelheid Coke
//[116] Te veel?*************************
//* Nog te doen

In register [100] wordt vastgelegd hoe vaak Peter een bezoek heeft gebracht aan het hotdog kraampje. Bij het eerste bezoek stelt hij zichzelf voor. Bij zijn tiende bezoek is hij wat meer op zijn gemak en minder formeel. In [101] heeft hij zelfs controle over zijn wisselgeld, ...

Gedeeld geheugen

De laatste 56 registers (dit kunnen er meer zijn, het exacte aantal is niet belangrijk) is gedeeld geheugen tussen alle dialogen. Dit betekent dat alle dialogen deze registers kunnen benaderen en dat alle dialogen hetzelfde geheugen zien. Er moet dus een centraal aanspreekpunt zijn waar alle toegang tot de registers wordt geregeld. De volgende drie registers werden gebruikt bij de dialogen van Würstelstand (zie ook daten.h):
[200]: Leni kan naar Immigratie met Hale
[201]: Leni leest de "Wanted"-poster
[202]: Leni heeft "Steen-Schaar-Papier" gespeeld met Peter! (Stout!)

Gebeurtenissen

We hebben een toevalssysteem ontwikkeld voor Würstelstand. Ieder gebeuren heeft een uniek nummer, geco�rdineerd vanuit een centraal bestand. Dit kan de volgende dingen tot gevolg hebben: Hoe gaat dit allemaal in zijn werk?
Voor de nieuwe producten, telefoongesprekken en evenementen hoef je alleen maar het nummer als begin- en eindwaarde in te vullen in het juiste bestand.

Hoe kan ik dit laten gebeuren?

Aktion expression
// activating Cheats:
Aktion 3
// de gebeurtenis, berekend in register 100:
Aktion [100]
Wat kun je doen met deze gebeurtenissen? Hier is een deel van deze lijst voor Würstelstand:
0Error/NeverGebeurtenis 0 wordt afgevangen en er gebeurt niets mee
1InitialisingWordt bij de opstart aangeroepen en activeert producten, klanten, ...
2EndWordt aangeroepen bij het einde van het spel
3activating FW-CheatWie heeft dit er in gezet?!?
4deactivating FW-CheatVoor je houden!
5Leni.competition.activating newspaperPortret van Leni is goed genoeg -> activeer krantenartikel over de te houden wedstrijd
6Leni.competition.Zeitung->TelefonNrKrantenartikel geeft het telefoonnummer om je als kandidaat van de wedstrijd aan te melden
7Leni.competition.deactivating TelNrNa aanmelding wordt het telefoonnummer afgesloten
8deactivating HaleHale zet zichzelf op non-actief omdat Leni hem heeft beledigd.
9Hale recommends JosiHale beveelt Josi aan, na er over te hebben gepraat (Smalltalk helpt!)
10deactivating JosiJosi zet zichzelf op non-actief
11deactivating PeterPeter doet hetzelfde
12Sepp Nachricht without Leni aktivierenSepp doet illegale voorstellen, Leni weigert en alles komt in de openbaarheid
13Sepp Nachricht with Leni aktivierenLeni gaat akkoord met de dubieuze voorstellen, problemen volgen
14lost gamePostbode Gottfried maakt een einde aan het spel
15won gameGottfried begrijpt de waarde van de hotdog kraam en Leni wint
16Hale.news article Asyl activateLeni heeft met Hale gepraat over zijn familie, waarvan het gevolg een krantenartikel is over asielrecht.
17Hale.news article->Telefonnr activateDe krant geeft het telefoonnummer dat kan worden gebeld
18Hale->Zeitungsbericht->Telefonnr deactivatingHet gesprek beëindigt het telefoonnummer
19Hale->Familie activatingDe familie van Hale krijgt asiel
20activating the spyLeni had eigenlijk spion moeten zijn maar dat is nooit gebeurd.
33New products 1 (New supplier)Deze gebeurtenis breidt het assortiment uit
100won contestLeni heeft gewonnen, klanten kunnen erover praten
101losts contest
102LotterypriceLeni heeft de loterij gewonnen
Zoals te zien, is de gebeurtenis een zeer krachtig hulpmiddel voor het verloop van het spel.

Berekeningen

Met de opdracht Rechne (bereken in het Duits) kan men expressies berekenen en het resultaat in een register zetten. Bijvoorbeeld:
Rechne [100]: 20 + [30] * 10
De inhoud van register 30, vermenigvuldigd met 10 en daarbij 20 opgeteld, wordt in register 100 opgeslagen.

De volgende berekeningen zijn mogelijk:
OperatieNotatieVoorbeeldOplossing
Haken(a)(10+20)*30900
Register[a][20]De inhoud van register 20
Vermenigvuldiginga*b3*412
Delena/b10/52
Resta%b10%31
Optellena+b1+12
Aftrekkena-b1-10
Toewijzing[a]:b[10]:20Zet in register 10 de waarde 20
Vergelijkingena?bJa(1) of Nee(0)
Gelijk aana=b10=20Nee(0)
Kleinera<b10<20Ja(1)
Grotera>b[10]>[20]
ANDa&b1=1 & 2=2Als 1 gelijk 1 EN 2 gelijk 2
ORa|b1=1 | 2=2Als 1 gelijk 1 OF 2 gelijk 2
Random getala Z b1 Z 6Retourneert een toevallig getal tussen 1 en 6
Vergelijkingen hebben als resultaat een getal: 1 voor TRUE (waar) en 0 voor FALSE (niet waar). Dit kan ook naar het register worden geschreven. Spaties in rekenkundige expressies ( 10 + 20 ) zijn toegestaan maar niet benodigd (10+20).

De grootste uitdaging was de implementatie van de rekenkundige evaluatie, die in staat is tot evaluatie van de volgende expressie:

Aanname: [100]=5, [24]=14, 1Z6=2

[[100]+1]:((1Z6)*([24]>3)+10/2-10%5)
[5    +1]:((2  )*(14  >3)+10/2-10%5)
[6      ]:(2    *(1        )+5   -0   )
[6      ]:(2    *1          +5        )
[6      ]:(7                          )
[6      ]:7
Oplossing: [6]: 7. De waarde 7 wordt in register 6 gezet.

Acties op registers

Met de opdracht Wenn (dit is als in het Duits)
Wenn condition
then
kan men vergelijkingen maken. Bijvoorbeeld:
Wenn [100+1]>10
Kunde: Het getal in register 101 is groter als 10 !
Wenn 1>1
Kunde: ERROR!
Als de vergelijking waar is gaat de interpretator verder met de volgende regel. Zo niet dan wordt een regel overgeslagen. Dit kan samen met sprongopdrachten worden gebruikt.
Wenn [102]<10
Sprung KLEINER
Wenn [102]=10
Sprung GELIJK
Wenn [102]>10
Sprung GROTER
...
:KLEINER
...
:GELIJK
...
:GROTER

Plaatjes kijken

BILD expression
(Bild is plaatje in het Duits). Als bijvoorbeeld
Bild 5
wordt genoemd in bestand HALE.BAT dan wordt HALE5.DAT (een speciaal grafisch formaat) weergegeven. Met het klikken van de muis kan men verder gaan met de dialoog.

Commando referentie

Voor een beter overzicht heb ik de volgende referentielijst van commando's gemaakt.
// commentaar:COMMANDO REFERENTIE

Kunde: textDe klant zegt wat
Tel: textGesprekspartner zegt wat
Leni: textLeni zegt wat
:targetDoel waar interpretator naar toe kan springen
Liste numberMaak een lijst de huidige lijst
Löschen *Alle elementen uit de huidige lijst verwijderen
Löschen targetVerwijderd alle elementen uit de huidige lijst die naar target springen
Aktion numberAflopen van gebeurtenissen
EndeEinde van het gesprek
Bild numberLaat het plaatje met naam NameNumber.dat zien
Sprung targetGa naar target
Neu target,TextNieuw element in de huidige lijst
Alt target,TextNieuwe optie in de huidige lijst
MenüLaat menu zien, en de gebruiker kiezen...
Wenn conditionVergelijking (zie verder)
//thenWaar, ga naar de volgende regel
//elseNiet waar, sla een regel over
Rechne expressionBereken waardes en zet ze in een register
Bild expressionToon plaatje, wacht op muis-klik

Nadelen van het meerkeuze systeem

Dialog Maker

Markus Muntaneau heeft een programma ontwikkeld onder Delphi met de naam Dialog Maker waarmee het makkelijker moet worden om dialogen te maken. Helaas is het nooit afgemaakt (er zitten nog steeds wat fouten in) en is daardoor niet zo bruikbaar. Voor ontwikkelaars is het echter nog steeds aan te bevelen om het eens te bekijken.

Programmeertrucs

Het hele Würstelstand project bestaat uit zo'n 10.000 regels C(++) code en aangezien de compilatietijden nog aanvaardbaar waren, is het niet gemodulariseerd (Ok, ik beken ook mijn luiheid in deze). In plaats daarvan heb ik het test-include systeem ontwikkeld: de module wordt geïntegreerd in een C-bestand die zelfstandig executeerbaar is en die tegelijkertijd testfunctionaliteit bevat voor alle routines in de module. Deze code wordt op zijn beurt gedeactiveerd met behulp van een #ifdef wanneer het in de hoofdmodule wordt ingebracht. Zoals hieronder weergegeven, bespaart men op header-bestanden ;-)

batch.cpp
#ifndef _DIALOG_H 
#define _DIALOG_H 
 
#ifndef MAIN_MODULE
  #define DIALOG_TEXT 
  #define DEBUG 
  //Here are the necessary included Header files
  #include <stdio.h>
  //... 
#endif 
 
//Here are the whole dialog routines
//..
S2 Dialog(char *Filename, TYP Array[])
{
  //...
}

#ifndef MAIN_MODULE
 //Here is everything for the test programs
TYP Feld[256]; 
int main(short argc,char *argv[]) 
{ 
  //Testprogram
  Dialog(Filename,Feld);
} 
#endif

wurst.cpp
#define MAIN_MODULE
#include "batch.cpp"
TYP Felder[10][256];
int main(short argc,char *argv[]) 
{ 
  Dialog(Filename,Felder[i]);
}

Afsluitende opmerkingen

De Linuxversie van de Würstelstand-simulatie is te verkrijgen bij Futureware (http://poboxes.com/futureware). De 1.1 versie van Dialog kan hier (dialog-1.1.tar.gz) op worden gehaald.
Bij voldoende belangstelling (via E-mail aan de auteur), zullen vervolgartikelen verschijnen met praktijkvoorbeelden van Dialog.