by Philipp Gühring About the author: Philipp has just passed the A-Levels at the HTL Wiener Neustadt, a higher technical school for EDP. So now he has got time for his software-development group, called Futureware 2001. He is a Linux fan and an active member of the Linux User Group Austria Content:
|
Abstract:
Dialog is a programming language, which is for dialogs with the user. It was used in the trading-simulation Würstelstand. This article describes the development of Dialog and its applications.
The dialogs are stored in Ascii text files, and are interpreted line by line,
although it is possible to advance to a further chosen line at any time.
We used to create them with a simple text editor.
The filename is Name.BAT (e.g.: HALE.BAT)
When the player(Leni) says something automatically:
Leni: Text Leni: Good morning, Sir! What can I get you? Leni: Look at these youngsters! Unbelievable! | Look at these youngsters! Unbelievable! Did you fell out of the bed? |
Two Frankfurter with bread and two Coke. Come on, get going, old man! |
When the conversation partner says something:
(Kunde is customer in German, Telefon is telephone in German)
Kunde: Text Kunde: Two Frankfurter with bread and Coke. Come on, get going, old man! Telefon: Futureware 2001, Philipp Gühring. What can I do for you? |
Every normal dialog ends with
Ende. (Ende is end in german)
An easy example: |
Leni: Good morning, Sir! What would you like? Kunde: Good day! A Käsekrainer please! Leni: Just a moment. Leni: Here you are. Kunde: Thanks a lot. Bye! Leni: Bye! Ende |
Jump targets are defined by a colon at the beginning of a line, after which the name of the jump target itself follows. You can jump to the targets with the command Sprung (Sprung is jump in German):
:Target //Jump example follows: Sprung Target
| What does the interpreter do with this example? First he finds the command Leni: and outputs the text 1. Then there is a comment in the next line (First we do this), which will be ignored. In the following line there is the command Sprung. The interpreter searches through the whole dialog for the target MENU_0, finds it a few lines below, and jumps there. Then there is a comment again (I am back!). And the last command is Leni:, which prints 3 on the screen. So in the end he skipped the command Leni: 2 in the example , and Leni does not say 2. |
As we have seen, a line can:
// This is a comment ************************************** *Like this, one can make comments too* **************************************Comments must not be in the same line as commands:
Leni: I don't unterstand nothing anymore. // NO COMMENTThe interpreter will recognise I don't unterstand nothing anymore. // NO COMMENT as the text to be output!
|
Dialog invents the following system: The system maintains a list, into which the entries are inserted,
which are the answering possibilities the user will have.
When the time has come, the menu will be displayed on the screen.
Now he can choose, and then the interpreter jumps to the part of the program, which handles the chosen entry.
Firstly you insert the entries with the commands NEU and ALT into the list. Both commands are followed by the jump target and the text of the entry. The text can be a very long line, as the system breaks the lines up automatically. With the command MENÜ the whole list gets displayed, and the user can choose an entry. |
Neu buy,A hot one, as usual, ok? Neu work,How is it going at work? Neu language,Are you still attending the language course at WIFI? Neu family,How is your family doing? Neu weather,Are you enjoying this weather? MenüWith this type the player has the possibility to play through all the entries one after the other. The choices are reusable. The entries which were not chosen remain in the list, and can be chosen at a later stage. So, let's choose work from the above example:
:work Leni: How is it going at work? Kunde: Too much to do, as always. MenüAs mentioned, only the chosen line gets extinguished. At the following menu remain these topics:
Kunde: How many would you like? Alt some, 10 Pieces Alt more, 20 Pieces Alt most, 100 Pieces Menü :some //We continue here, when the user chose 10 pieces :more ... :most ...As it doesn't make sense to leave the chosen entries any longer in the list, all the entries should be automatically deleted after to the choice of the user. If for example the user chose 20 pieces, the interpreter jumps to the target more:
:more Kunde: Are you sure? Leni: Yes, I want 20 Pieces. Kunde: How soon do you need them? Alt 1, Tomorrow Alt 2, The day after tomorrow Alt 3, Sometimes MenüAnd finally one can combine the two types:
Kunde: Remember the good old days. Alt Memory,Yeah, I just rememberd when, ... MENÜ
List 0 is recommended for options. List 1 is for the general topics, for example family, work, leisure, food, ... If one wants to talk about work for example, and there are other topics within that subject of work, one chooses list 2. We have got one example in the dialogue of Hale. In case one should need more lists than those three one needs to change the constant in the sourcecode of the interpreter.
LISTE 0 LISTE 1 LISTE 2Obviously all entries of all lists remain in their lists in this process. The commands like NEU, ALT, MENÜ, LÖSCHEN always relate to the current list.
Neu Memory,§Yeah, I just rememberd when, ...The list 0 was after the menu automatically deleted. It was therefore only useful for options, not for topics.
I recommend now to look at the examples HALE.BAT and PETER.BAT, where we used the lists exceedingly.
LÖSCHEN targetdeletes every entry of the current list, which points to target. For example:
LÖSCHEN familiyTo delete all entries of the current list, one adds an asterisk:
LÖSCHEN *(If desired, one can add regular-expression support ;-)
Menü shows all entries of the actual list, and allows the user to choose amongst them. After this the chosen entry and all added options (inserted with ALT) will be deleted. Finally the interpreter jumps to the target accordingly. In case of only one entry in the list, it's understood that this entry is the choice and therefore no multiple choice menu is presented. If there is no entry in the list, or if the target can't be found, the interpreter will continue after MENÜ with the next line.
1 | Event; | //event number (look at texte.h) | |
2 | geliefert; | //S | //0-10 how many tenths will be deliverd |
3 | wtag; | //day of the week | |
4 | tag; | //day of the month | |
5 | monat; | //month | |
6 | jahr; | //year | |
7 | Datum; | //serial day (1.1.1997 = 0) | |
8 | wetter; | //today's weather | |
9 | konto; | //S | //bank account |
10 | kapital; | //S | //cash |
11 | ausgaben; | //S | //today's expenses |
12 | einnahmen; | //S | //today's income |
13 | sterne; | //S | //quality rating of the hot-dog stand(0-5 stars) |
14 | wverkauf; | //number of products sold this week | |
15 | weinnahmen; | //weekly income | |
16 | wausgaben; | //weekly expenses | |
17 | 0; | //S | //new income/expense (triggerd by the dialog) |
18 | Nachrichtenserie; | //which news series (0=Elch,1=...) | |
19 | Nachricht; | //which news in the current series (0=1.Tag,1=2...) | |
20 | LottoNr[0]; | //how many Lottery numbers are used(0-6) | |
21 | LottoErgebnis[0]; | //how many Lottery numbers were right | |
22 | LottoGewinn[LottoErgebnis[0]]; | //how much Leni won | |
23 | S.Image; | //S | //Leni's image |
24 | S.Override; | //S | //Overriding-Event |
25 | S.wverkauf[1]; | //products sold last week | |
26 | S.weinnahmen[1]; | //last weeks income | |
27 | S.wausgaben[1]; | //last weeks expenses | |
28 | S.wverkauf[2]; | //products sold two weeks ago | |
29 | S.weinnahmen[2]; | //income two weeks ago | |
30 | S.wausgaben[2]; | //expenses two weeks ago | |
31 | S.NOverride; | //S | //tomorrows overriding event |
32 | S.wetter_bericht; | //which weather forecast | |
33 | Gesamtwert(); | //total value of the hot-dog stand | |
34 | Wetterbericht[S.wetter_bericht].Ereignis; | //Which weather event | |
35 | Tageszeit; | //daytime in minutes | |
70..79 | Lagermenge | //stocks | |
80..89 | Verkaufspreis | //S | //price of product |
90..99 | Kaufmenge | //S | //amount of order |
batch.cpp |
// Customer: Peter Hinzing // // Usage of the registers //[100] How often he was here //[101] Pocket money //[102] Several events //[103] Random number: order //[104] Random number: answer to order //[105] Different dialogs: Work on the 5th day //[106] Deal //[107] The game starts, after having been chosen //[108] Game.stake.type //[109] Game.stake.quantity //[110] Game.choose.Peter //[111] Game.choose.Leni //[112] Activation of the Hobby //[113] Activation of the Home //[114] Dialog about Würstelstand //[115] total stock coke //[116] too much ?************************* //* not yet done |
[200]: Leni can go to the immigration office with Hale [201]: Leni read the dog's wanted circular [202]: Leni had played Stein-Schere-Papier with Peter! (evil!)
How can I trigger Events?
Aktion expression // activating Cheats: Aktion 3 // activating the event, which was calculated into register 100: Aktion [100]What can you do with these Events? Here is a part of the Event list from Würstelstand:
0 | Error/Never | Event 0 is caught and left unhandled |
1 | Initialising | is triggerd at the beginning and activates many products, customers, ... |
2 | End | should be triggerd at the end of the game |
3 | activating FW-Cheat | Who coded this?!? |
4 | deactivating FW-Cheat | Keep this secret! |
5 | Leni.competition.activating newspaper | Leni's image is good enough -> activating newspaper article about the upcoming contest |
6 | Leni.competition.Zeitung->TelefonNr | Newspaper article activates the telephone number to join the contest |
7 | Leni.competition.deactivating TelNr | After having phoned and sorted everything out, the phone number gets deactivated |
8 | deactivating Hale | Hale deactivates himself, because Leni offended him. |
9 | Hale recommends Josi | Hale activates Josi as soon as having talked about it, (Smalltalk is important!) |
10 | deactivating Josi | Josi deactivates himself |
11 | deactivating Peter | Peter deaktiviert sich selbst |
12 | Sepp Nachricht without Leni aktivieren | Sepp offers illegal production, Leni refuses, the whole thing comes in the open and public. |
13 | Sepp Nachricht with Leni aktivieren | Leni agrees to the illegal production, problems follow |
14 | lost game | The postman Gottfried initiates the end of the game |
15 | won game | Gottfried realizes the value of the hot-dog stand, and Leni wins |
16 | Hale.news article Asyl activate | Leni talked to Hale about his family, which initiated the newspaper article about the right of asylum. |
17 | Hale.news article->Telefonnr activate | The newspaper show the telephonnumber, which can be used now |
18 | Hale->Zeitungsbericht->Telefonnr deactivating | The conversation deactivates the phone number |
19 | Hale->Familie activating | Hale's family reveices asylum |
20 | activating the spy | Leni should have been recommended a detective, but this has never been put into practice. |
33 | New products 1 (New supplier) | This event extends the product range |
100 | won contest | Leni won the contest, the customers can talk about it, ... |
101 | losts contest | |
102 | Lotteryprice | Leni won in the Lottery |
Rechne [100]: 20 + [30] * 10The content of the register 30, multiplied by 10, added to 20 is stored into the register 100.
The following mathematical operations are possible:
Operation | Notation | Example | Solution | |
Klammern | (a) | (10+20)*30 | 900 | |
Register | [a] | [20] | The contents of the register 20 | |
Multiplication | a*b | 3*4 | 12 | |
Division | a/b | 10/5 | 2 | |
Rest | a%b | 10%3 | 1 | |
Addition | a+b | 1+1 | 2 | |
Subtraction | a-b | 1-1 | 0 | |
Zuweisung | [a]:b | [10]:20 | Schreibt in Stelle 10 den Wert 20 | |
Vergleiche | a?b | Ja(1) oder Nein(0) | ||
Ist gleich | a=b | 10=20 | Nein(0) | |
Kleiner | a<b | 10<20 | Ja(1) | |
Größer | a>b | [10]>[20] | ||
AND | a&b | 1=1 & 2=2 | Wenn 1 gleich 1 ist UND 2 gleich 2 ist | |
OR | a|b | 1=1 | 2=2 | Wenn 1 gleich 1 ist ODER 2 gleich 2 ist | |
Random number | a Z b | 1 Z 6 | Returns a random number between 1 and 6 |
Comparisons result in numbers: 1 for TRUE and 0 FALSE/WRONG. These can also be written in the register. Spaces in expressions ( 10 + 20 ) are allowed, but not neccesary (10+10).
The biggest challenge was the development of the mathematical evaluator, which is now capabel to process the expressions like the following:
Assumption: [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 ]:7Solution: [6]:7 The value 7 is written into the register 6.
Wenn condition thenone can make comparisons. e.g.:
Wenn [100+1]>10 Kunde: The number in the register 101 is bigger than 10 ! Wenn 1>1 Kunde: ERROR!If the condition is true, the interpreter proceeds in the next line, otherwise he skips one line. This is implemented in the way that the following line is skipped if the condition is false. This can be used in connection with jumps:
Wenn [102]<10 Sprung SMALLER Wenn [102]=10 Sprung EQUAL Wenn [102]>10 Sprung BIGGER ... :SMALLER ... :EQUAL ... :BIGGER
BILD expression(Bild is picture in German) If for example
Bild 5is mentioned in the HALE.BAT, then it HALE5.DAT (a special picture format) is shown. A mouse click is expected and the dialog can proceed.
// comment: | COMMAND REFERENCE |
Kunde: text | The customer says something |
Tel: text | Conversation partner says something |
Leni: text | Leni says something |
:target | Target where the interpreter can jump to |
Liste number | Makes a list the current list |
Löschen * | Deletes all entries of the current list |
Löschen target | Deletes all entries of the current list, which point to target |
Aktion number | Triggers Events |
Ende | Ends the dialog |
Bild number | Shows the picture with the filename NameNumber.dat |
Sprung target | Jumps to the target |
Neu target,Text | Inserts new topic into the current list |
Alt target,Text | Inserts new choice into the current list |
Menü | Show the menu, let the user choose, ... |
Wenn condition | Comparison (see next lines) |
//then | If true, the interpreter proceeds in the next line |
//else | If false, the interpreter skips one line |
Rechne expression | Calculates expressions into a register |
Bild expression | Show pictures, waits for mouse click |
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]); } |
Webpages maintained by the LinuxFocus Editor team
© Philipp Gühring LinuxFocus 1999 |
1999-09-04, generated by lfparser version 0.7