Game Console

Programming Manual

version 15

0. Introduction

Those who liked creating scripts for the bot know that the kind of games you can write with a bot is rather limited as you can only display text lines on the chat to make for example a quizz, a scrabble, a dice game, ...

With this game console, which is in fact an animated window similar to a gameboy, we offer a much larger set of possibilities to create applications :

1. How to write a console application

Start by downloading the console kit here : console.zip

This zip file contains :


To create an application, you need to write a script (for example program.txt) and then, in Windows Explorer, with the mouse, drag and drop program.txt onto the program run.exe

The script program.txt will then be compiled and converted into an executable program program.run of very small size (< 63K) that can be imported directly in the chat without causing slowdowns (see chapter 9 how the bot can start a console application). A file program.lis is also generated with a program listing. It can be viewed in case of errors during execution.

The script language is the same as the one used for the bot (see annex 6 for a description of the script language and annex 7 for a script language tutorial).

Commands and programming environment of the console are described in the following chapters.


2. The Console Window

The console window has a maximum size of 640 x 480.

If your application will be integrated into the chat, you should not use this size otherwise there won't be any space left for text or webcams, especially for users who have a low screen resolution !

The command screen allows to specify what window size you wish to use.

screen (width, height);
  • change size of console window.
  • maximum size is 640 x 480.
  • this command is mandatory at the start of the program to create a window otherwise you won't see anything !
  • you can use this command several times in the course of the program to modify the size of the window.
  • a size of 0 x 0 will make the window disappear from the chat, the program will however continue running.

Example:

proc main ()
{
  screen (160, 16);        // set the screen in 160 x 16
  print ("Bonjour !");     // say bonjour
  sync ();                 // display on screen
  sleep (5000);            // wait 5 seconds
}

The command justify allows to justify the console window on the left, middle or right, top or bottom of the chat screen.

justify (n);
  • allows to justify the console window on the chat screen.
  • for n : 0 = top left, 1 = top middle, 2 = top right, 3 = bottom left, 4 = bottom middle, 5 = bottom right.
  • by default, we justify top left.


3. Text Mode

By default, the text window is made of 40 columns and 30 lines (columns are numbered from 0 to 39 and lines from 0 to 29).

If you're doing tests you will see that there are 2 additional hidden columns on the right and 2 additionnal hidden lines at the bottom : they are used to prepare text and to make it appear slowly using scrolling.

Here are the text mode commands :

font (width, height);
  • change the font size, which changes also the number of columns and lines.
  • The default font size is 16 x 16.
  • Only the values 8, 16 or 32 are allowed !
  • Here are the most common sizes :

        font    columns    lines   hidden columns   hidden lines
       =======  ========  ======  ================  ==============
        8 x  8     80       60           4                4
       16 x 16     40       30           2                2
       32 x 32     20       15           1                1
    
        8 x 16     80       30           4                2
        8 x 32     80       15           4                1
           ...
    

print ("text");
  • displays text on screen.
sync ();
  • waits 1/60 seconds then sends the console screen to the graphic card.
  • This command is the most important of all because without it nothing gets displayed !
  • Each time you have done a series of print and you want it to get displayed you have to do a sync();
ink (color);
  • selects a text writing color (see list of colors in annex 2).
paper (couleur);
  • selects a background color (see list of colors in annex 2).
at (C,L);
  • moves the cursor (where you write with print) to column C, line L.
nl ();
  • starts a new line.
scroll (L, X, Y);
  • allows a horizontal/vertical/oblique scrolling of one or several lines.
    L : line
    X : scroll_x 0 to 32
    Y : scroll_y 0 to 32
  • You can only scroll full text lines.
blit (C1, L1, nb_cols, nb_lines, C2, L2);
  • allows to move a bloc of text (C1, L1) to (C2, L2)
    C1 : column start
    L1 : line start
    nb_cols : nb of columns of the bloc
    nb_lines : nb of lines of the bloc
    C2 : final column
    L2 : final line
  • see annex 3 for examples
fill (C, L, nb_cols, nb_lines, code);
  • fills a text bloc starting at (L, L) with a code. C : column start
    L : line start
    nb_cols : nb of columns of the bloc
    nb_lines : nb of lines of the bloc
    code : see list of codes in annex 1.
  • for ex: to erase the screen: paper(15); fill (0,0, 42, 32, 32);
  • see annex 3 for examples



// Example:

proc main()
{
  screen (640, 200);

  ink (56);     // write in dark blue
  paper (190);  // light blue background
  font (8, 8);

  // erase all window (80 columns, 60 lines)
  // so that the blue background is visible.
  fill (0, 0, 80, 60, 32);         // 32 = code of character blank

  print ("Bonjour !  Comment allez-vous !");
  nl ();
  nl ();

  print ("Quel beau temps aujourd'hui !");
  nl ();

  at (20, 10);     // go to column 20, line 10.
  ink (23);        // red writing
  print ("Oué !");

  sync();
  sleep (10000);
}



4. the mouse

mouse (X, Y, B);
  • this commande fills the variables :
    X, Y : position of the mouse
    B : button state (0 = not pushed, 1 = pushed)
  • if X=0 and Y=0, the mouse is in the upper left window corner.
    if X=639 and Y=479, the mouse is in the bottom right window corner.
    if X=-32000 and Y=-32000, the mouse is outside the window.
  • be careful, on the chat the position (X,Y) can be outside the window or even become negative.

// Example:

proc main()
{
  var x, y, b;

  screen (640, 200);

  for (;;)
  {
    mouse (x, y, b);
    at (0,0);
    print ("x=" + str$(x) + "  y=" + str$(y) + " b=" + str$(b) + "                   ");
    sync();
  }
}


5. Print character codes on the screen

256 character codes are predefined (see table in annex 1).

To print for example the character of code 1 (a smiley), use :
   print (chr$(1));
to print the codes 1, 2 and 3, use :

    print (chr$(1));  print (chr$(2));  print (chr$(3));
or better :

    print (chr$(1) + chr$(2) + chr$(3));
or still better :

    print (chr$(1,2,3));

5.1. Create your own character font

If you don't like the previous characters, vous can create your own !

On the images below : Each character uses only 8 bytes of memory.


// Example:

image mes_lettres (8 * 8)
{
  "  XXXX  "
  " XX  XX "
  " XX  XX "
  " XXXXXX "
  " XX  XX "
  " XX  XX "
  " XX  XX "
  "        "

  " XXXX   "
  " XX  XX "
  " XX  XX "
  " XXXXXX "
  " XX  XX "
  " XX  XX "
  " XXXXX  "
  "        "

  "  XXX   "
  " XX  XX "
  " XX     "
  " XX     "
  " XX     "
  " XX  XX "
  "  XXXX  "
  "        "
}

proc main ()
{
  screen (640, 480);

  // define characters 65 to 67 (A to C)
  define_font (65, 67, mes_lettres);

  // try our new characters
  print ("ABC");

  sync();

  // wait 10 secondes
  sleep (10000);
}

5.2. Create high quality characters

To obtain a better quality font, you can draw the character using 16 x 16 pixels.

Note that it's possible to create characters in 8 x 8, 16 x 16 or 32 x 32, or even a mixture of these sizes (8 x 16, 16 x 8, ..).

In 16x16, each character uses 32 bytes of memory,
in 32x32, each character uses 128 bytes of memory.

Avoid wasting memory unecessarily.


// Example:

image ma_lettre (16 * 16)
{
  "     XXXXXXX    "
  "   XXXXXXXXXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "   XXXXXXXXXX   "
  "   XXXXXXXXXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "   XXX    XXX   "
  "                "
}

proc main ()
{
  screen (640, 480);

  // define character 65 (A)
  define_font (65, 65, ma_lettre);

  // trying our new character
  print ("A");

  sync();

  // wait 10 seconds
  sleep (10000);
}

5.3. Create 4-color characters

Until now each character was made of 2 colors(ink et paper). It's possible to draw characters with 2 additional colors, they take then twice as much memory.

On the example below : Each 8x8 character in 4 colors uses 16 bytes of memory.


// Example:

image mon_A (8 * 8, 4 colors)
{
  "  XXXX1 "
  " XX1 XX1"
  " XX1 XX1"
  " XXXXXX1"
  " XX2 XX2"
  " XX2 XX2"
  " XX2 XX2"
  "        "
}

data ma_palette
{
  24  40        // my 2 palette colors
}

proc main ()
{
  screen (640, 480);

  // define character 65 (A)
  define_font (65, 65, mon_A, ma_palette);

  // let's try our new character
  print ("A");

  sync();
  sleep (10000);
}

5.4. Create 16-color characters

You can increase the number of colors til 16, each 16-color character in 8x8 uses then 32 bytes of memory !

The main use is to be able to create a background image like creating a puzzle, by reusing several times the same pieces.

On the picture below :

// Example:

image mon_A (8 * 8, 16 colors)
{
  "abXXXX1b"
  "aXX1cXX1"
  "aXX1dXX1"
  "aXXXXXX1"
  "aXX2eXX2"
  "aXX2eXX2"
  "aXX2eXX2"
  "aaaaaaaa"
}

data ma_palette
{
  24 40 15 0 7 46 78 35 90 126 12 3 15 8  // my 14 palette colors
}

proc main ()
{
  screen (640, 480);

  // redefine the character 65 (A)
  define_font (65, 65, mon_A, ma_palette);

  // try our new character
  print ("A");

  sync();
  sleep (10000);
}

5.5. Creating 256-color characters

Finally, you can increase the number of colors til 256, each 8x8 character in 256 colors will then use 64 bytes of memory.

On the example balow :

// Example:

image mon_A (8 * 8, 256 colors)
{
  "0101010101010101"
  "01            01"
  "01            01"
  "0101010101010101"
  "01            01"
  "01            01"
  "01            01"
  "01            01"
}


proc main ()
{
  screen (640, 480);

  // redefine character 65 (A)
  define_font (65, 65, mon_A);

  // try our new character
  print ("A");

  sync();
  sleep (10000);
}

5.6. Resetting the default font

To cancel your previous characters and reset the default font :

  // reset the default for characters 65 to 67 (A to C)
  define_font (65, 67);


6. Sprites

Sprites are moveable graphic objects. They allow the creation of avatars, missiles or any other animated object.

Numbers

A maximum of 128 sprites having numbers from 0 to 127 are available.

Priority

Sprites have a diplay priority : when two sprites overlap on the screen, then the sprite with the smaller number will hide the other one (sprite 1 in front of sprite 2, sprite 2 in front of sprite 3, etc ..). All sprites are displayed in front of the background text.

Image

The executables image_converter.exe and image_converter_256.exe from the .zip that you downloaded allow, when drag & dropping a gif file on them, to convert the image in an image format that can be directly exploited in a script (see command sprite_image and the example below)

image_converter.exe allow to convert an image of 2, 4 or 16 colors, whereas image_converter_256.exe always creates 256-color image formats.


Here are the commands to control sprites :

sprite_on (number_sprite, 0 ou 1);
  • enables(1) ou disables(0) the sprite.
  • At the start all sprites are disabled.
  • to enable sprite 5, try: sprite_on (5, 1); to disable it, try : sprite_on (5, 0);
sprite_pos (number_sprite, position_x, position_y);
  • moves the sprite on the screen.
  • X et Y specify the upper left corner of the sprite image.
  • X varies between 0 and 639, Y between 0 and 479.
    You can however go outside these limits and even use negative coordinates (for ex: -20) to display a sprite partly outside the screen.
sprite_image (number_sprite, image);
ou
sprite_image (number_sprite, image, palette);
  • specifies the sprite image
  • contrarily to character fonts, the image of a sprite is not limited to 8x8 or 16x16 sizes. You can specify any size with however a maximum of 248 x 248.
  • images of 2, 4, 16 or 256 colors are possible like for character fonts.
  • the palette is mandatory for images having 4 or 16 colors.
  • changing the image of a sprite with the command sprite_image allows animations.
  • see below for an example
sprite_color (number_sprite, color);
  • specify the color X of a sprite image
  • the X color of a sprite image can be changed anytime, the other colors (1, 2, ..) are fixed, unless the image is changed of course.

Example

// Example of sprite moved with the mouse :

image balle (15 * 15, 4 colors)
{
  "     XXXXXX    "
  "   XX11111XX   "
  "  XX1111111XX  "
  " XX112222211XX "
  " XX112222211XX "
  "XX11222222211XX"
  "XX11222222211XX"
  "XX11222222211XX"
  "XX11222222211XX"
  "XX11222222211XX"
  " XX112222211XX "
  " XX112222211XX "
  "  XX1111111XX  "
  "   XX111111XX  "
  "     XXXXXX    "
}

data couleur_balle
{
  24 56   // rouge & bleu
}

proc main ()
{
  var x, y, b;

  screen (640, 480);

  // enable sprite 5
  sprite_on (5, 1);

  // pick image of sprite 5
  sprite_image (5, balle, couleur_balle);

  // pick color X on sprite image
  sprite_color (5, 0);    // noir

  for (;;)
  {
    mouse (x, y, b);

    // positions the sprite on screen
    sprite_pos (5, x, y);

    sync ();
  }
}


sprite_zoom (number_sprite, zoom_x, zoom_y);
  • allow enlarging or shrinking the size of a sprite
  • zoom values between -8 and +8 are allowed :
    
             zoom        enlargment
             ----      --------------
               0             none
               1             X 2
               2             X 4
               3             X 8
               4             X 16
               5             X 32
               6             X 64
               7             X 128
               8             X 256
    
    
             zoom         shrinking
             ----        ---------
               0             none
              -1             div 2
              -2             div 4
              -3             div 8
              -4             div 16
              -5             div 32
              -6             div 64
              -7             div 128
              -8             div 256
    
  • To double the height of sprite 5, type : sprite_zoom (5, 0, 1);
    To double the width of sprite 5, type : sprite_zoom (5, 1, 0);
    To double the height and width of sprite 5, type sprite_zoom (5, 1, 1);
c = sprite_collision (number_sprite);
  • allows testing if a sprite overlaps another sprite or if a sprite overlaps a character code or a color larger than 207.
  • the command sprite_collision must be used after the command sync() because it detects collisions that occured during the last command sync().
  • sprite_collision(n) returns 0 (zéro) if the sprite didn't overlap.
  • sprite_collision(n) returns the value of the largest sprite that overlapped with it. However it ignores any overlap with a sprite of smaller sprite number !
        Example:
           n = sprite_collision(2);
           if (n > 0)
             print ("collision between sprite 2 and sprite " + str$(n));
    
  • if you create a sprite with 1 player and 100 ennemies, you better give the player the smallest sprite number because sprite_collision detects only collisions with sprite numbers larger than itself !
  • sprite_collision allows also to detect collisions with a character code from the text background, provided this character code was displayed with a color larger than 207 !
    In annex 2 you can see that only the colors 0 to 207 are defined by default. You can however define additional the colors 208 to 255 with the command define_color described here after.
  • By creating a background where the forbidden area is colored in a color (for example 208), you can easily detect if a player sprite touched this area. sprite_collision will then return the background color that the sprite touched (here for example 208).
define_color (color, R, G, B);
  • color : color number to define (0 to 255)
    R : quantity of red (0 to 255)
    G : quantity of green (0 to 255)
    B : quantity of blue (0 to 255)


7. data lists

Data lists allow the storage of long lists of values that the program can read when it wishes. These lists can contain graphic codes, music notes, or any other information.

Authorized values in data lists are : The command peek is used to read these lists :

// Example :

data mes_valeurs
{
  2 5 12 10 250 0      // here is a list of 6 values (the values must be between 0 and 255)
}


proc main ()
{
  var n, i;

  screen (640, 480);


  n = peek (mes_valeurs);       // n is 2
  n = peek (mes_valeurs + 1);   // n is 5
  n = peek (mes_valeurs + 2);   // n is 10
  n = peek (mes_valeurs + 3);   // n is 250
  n = peek (mes_valeurs + 4);   // n is 0


  // To read all these values easily you can write a loop :

  for (i=0; ; i++)
  {
    n = peek(mes_valeurs + i);
    if (n == 0)              // value 0 indicates the end
      break;                 // break allows leaving the "for" loop

    print (str$(n));
    nl ();
  }

  for (;;)
    sync ();
}


The command poke, to be used carefully, allows modifying a value of the list.

  poke (mes_valeurs + 1, 6);    // will replace the value 5 hereabove by 6.

Be careful however not to leave the bounds of the list, otherwise you would overwrite a value in memory further on in the program.

7.1. Dynamic Images

With the command poke, it's possible to modify a picture while the console program runs. For this, you need first to understand the structure of an image in memory.

image mon_image (3 * 2, 256 colors)
{
  "010203"
  "030104"
}

Images are stored in memory in 2 parts. First, there's a 4-byte header that contains :
- width     = 3  : image width (rounded up if less than 256 couleurs)
- height    = 2  : image height
- nb_bits   = 8  : number of bits used to store a pixel
- unused    = 0  : always zero.
The image pixels are stored just after the header in a format dependant on the number of colors used.

The easiest case is the 256-color image : here a pixel uses one byte (nb_bits = 8).

For other number of colors, a pixel uses (width x height x nb_bits / 8) bytes.

With the command poke, it's possible to modify one of these bytes. For example, to change the color of the first image pixel to color 7 :

  poke (mon_image + 4, 7);     // we add 4 to skip the header



8. The synthesizer

The synthesizer allows playing melodies or sounds (shooting, explosions, ..) in your applications.

You have 4 independant voices (1 to 4), an oscillator that can generate predefined waves forms (triangle, sawtooth, pulse, noise, sinusoïdal) or your own wave form, an enveloppe generator (adsr), hard-sync and ring-modulation options, and filters (low-band, high-band, pass-band or cutoff-band).

The compiler RUN.EXE can generate a .WAV file (format PCM) with the result of the created sounds. For this, you need to create a shortcut to run.exe (click on RUN.EXE, copy, paste the shortcut) then right-click on the shortcut, properties, and add to the end of the target field just after run.exe : program.txt -wav=test.wav. When you click then on the shortcut, program.txt will be compiled and executed, and test.wav will be created.

// Here's a simple application that plays a new notes :

data chanson1
{
  70 16  // note MIDI = 70, dur = 16 x 1/64 sec
  69 16  // note MIDI = 69, dur = 16 x 1/64 sec
  67 16  // note MIDI = 67, dur = 16 x 1/64 sec
  65 16  // ...
  67 32
  67 16
   0  0  // indicates the end
}

proc main ()
{
  volume    (1, 255);
  wave      (1, 2);
  adsr      (1, 10, 10, 128, 100, 5);
  song      (1, chanson1);

  for (;;)
    sync ();
}


Here's the list of commands of the synthesizer :

volume (voix, vol)
  • volume setting
  • voix : voice (1 to 4)
  • vol : volume value between 0 and 255.
  • By default, all voices have volume 0 so you hear nothing.
  • example: volume (1, 255); // voice 1 at maximum volume
wave (voix, forme_d'onde)
  • réglage de la forme d'onde
  • voix : voice (1 to 4)
  • forme_d'onde : (0=silence, 1=triangle, 2=sawtooth, 3=pulse, 4=noise, 5=sinusoïdal, or your own wave form)
  • triangle : flute
    sawtooth : trumpet
    pulse : engine noise, sirene
    noise : explosion, shooting
    sinusoïdal : soft melodious sound
  • for the pulse wave form, you can also use the command pulse, see below.

  • Instead of a predefined wave form, you can also use your own wave form.
    For this, you need to have a very small .WAV PCM file with an example wave form (the .WAV cannot contain more than 65536 samples of a wave, the graphic of this wave must start in the middle (value 0), evolve til the maximum, come back to the minimum, and rise again to the middle).

    Drag the .WAV file onto the program wave-converter.exe of the toolkit to obtain the data of the wave form to integrate to the script. Give a name to the data (for example data piano) and call the command wave by giving this parameter, thus: wave(1,piano);

    To obtain a richer sound you can use a file containing several successive waves but only a number of waves that is a power of 2 (thus 1, 2, 4, 8, 16,.. waves are possible). If you specify several waves you need to change the 1st line of data (wavelengths) to specify the number of waves.
adsr (voix, attack, decay, sustain_volume, release, pause)
  • setting the envelope adsr (enables choosing a music instrument)
  • voix : voice (1 to 4)
  • When hitting the key of a piano, the sound goes through 5 phases during which the volume changes : attack, decay, sustain, release, pause.
  • attack : duration (0 to 65535 msec) for the note to achieve its maximum volume (fast for a piano, slow for a violin)
  • decay : duration (0 to 65535 msec) for the note to come down to its intermediate volume.
  • sustain_volume : intermediate volume (0 to 255).
  • release : duration (0 to 65535 msec) that the note takes to fall to volume zero.
  • pause : silent duration (0 to 65535 msec) between the end of a note and the start of the next one.
freq (voix, frequence)
  • setting frequency (pitch) of a note (grave ou aigu)
  • voix : voice (1 to 4)
  • frequence : the values between 1 (grave) and 65535 (aigu) cover the frequencies between 0.23 Hz and 15625 Hz.
  • to compute a frequency value from a frequency in Hz, multiply by 4.194304 (example: 440 Hz x 4.194304 = 1845)
  • a frequency of 0 cuts off the sound.
  • modifying the frequency while a note is played yields interesting effects (trémolo, fire sirene).
duration (voix, duree)
  • setting of the duration of the note during the 'sustain' phase
  • voix : voice (1 to 4)
  • duree : duration (0 to 65535 msec) during which the note stays at its intermediate volume 'sustain'.
    a value of -1 means infinite duration.
play (voix)
  • start playing a note
  • voix : voice (1 to 4)
  • before playing a note, you need to set : volume, wave, adsr, freq and duration.
n = note (voix)
  • allows to know the phase the synthesizer is in
  • voix : voice (1 to 4)
  • returns the following values :
  • 1 = attack
  • 2 = decay
  • 3 = sustain
  • 4 = release
  • 5 = pause
  • 0 = note is finished.
  • to test if a note is finished (before playing the next), you can wait like this :
      while (note(1) != 0)    // while note of voice 1 is not finished
        sleep (0);            // wait
      
midi (voix, note_midi, duree_midi)
  • allows to play a note (this command combines in fact in one the commands freq, duration and play)
  • voix : voice (1 to 4)
  • note_midi : MIDI note (0 to 130) (0 = 8.17 Hz, 69 = 440 Hz, 127 = 12543 Hz).
  • duree_midi : duration of MIDI note in 1/64 seconds (64 = 1 sec, 32 = 1/2 sec, 16 = 1/4 sec, ..)
song (voix, zone_data)
  • allows to play an entire melody (this command combines in fact in one the commands midi and note, and repeats this for each note)
  • voix : voice (1 to 4)
  • zone_data : melody to play, encoded in MIDI format (see example above).
  • This command only starts the melody, which means that the script program can do other things, for example display texts or sprites while the melody continues to play. Moreover, you can play multi-voice melodies by starting a song command on each voice.
  • You can test with the command note() if the melody is finished, note() returns then zero.
pulse (voix, width)
  • sets the width of the pulse wave
  • voix : voice (1 to 4)
  • width : a value between 0 (inaudible) and 32768 (square wave).
hard_sync (voix, cut_freq)
  • produces the hard-sync effect that consist in cutting brutally the end of a wave form (sound of a mosquito).
  • voix : voice (1 to 4)
  • cut_freq : a frequency smaller than the one chosen for freq.
ring_mod (voix, ring_freq)
  • produce the ring modulation effect that consist in adding non-harmoniques sounds (sound of a gong).
  • voix : voice (1 to 4)
  • ring_freq : a frequency smaller than the one chosen for freq.
  • ring modulation works only for a triangle wave form (voir commande wave).

// demo : hard sync and ring modulation

proc main ()
{
  var i;

  // demo 1 : hard sync

  volume    (1, 255);
  wave      (1, 1);
  adsr      (1, 3000, 2400, 0, 0, 0);
  freq      (1, 6556);
  hard_sync (1, 1835);

  duration (1, 5400);
  play(1);
  while (note(1))
    ;

  hard_sync (1, 0);


  // demo 2 : Gong (with ring modulation)

  volume   (1, 255);
  wave     (1, 1);
  adsr     (1, 0, 1500, 0, 0, 0);
  freq     (1, 13112);
  duration (1, 900);
  ring_mod (1, 1966);

  for (i=0; i<4; i++)
  {
    play(1);
    while (note(1))
      ;
  }

  for (;;)
    sync();
}

filter (voix, type, cut_freq)
ou
filter (voix, type, cut_freq, resonance)
  • filter un son
  • voix : voice (1 to 4)
  • type : type of filter :
    0 = none
    1 = low-pass (lets through frequencies smaller than cut_freq, reduces the others by 12 dB/octave)
    2 = high-pass (lets through frequencies larger than cut_freq, reduces the others by 12 dB/octave)
    3 = band-pass (lets through frequencies near cut_freq, reduces the others by 6 dB/octave)
    4 = cutband-pass (reduces the frequencies near to cut_freq by 6 dB, lets through the others)
  • cut_freq : frequency of the filter.
  • resonance : amplification of the cut_freq frequency (between -50 dB and +50 dB, normal = 0).
  • using the filter on a noise wave form allows interesting effects.
  • modifying cut_freq while another note is played results in the interesting effets (start of rocket).
c = async ();
  • sends the console screen to the graphic card without waiting 1/60 seconds.
  • This command is similar to sync(), but it returns a value 0 or 1.
  • async returns 1 if it has not finished sending the screen to the graphic card, this means you will have to do another async later to end the job.
  • async returns 0 when it has finished sending the screen to the graphic card.
  • async allows avoiding the 1/60 second pause, which is necessary for example when you want to play a series of notes on the synthesizer. You can call the command async as often as you want, and as soon as it returns zero you know you can move graphic objects (text, sprites, ..).
sleep (duree);
  • This command waits the given time.
  • duree : in milliseconds (1/1000 seconds).



// Example: simple synthesizer

proc main ()
{
  var x, y, b, n;


  screen (640, 480);
  font (8, 8);


  // draw keys

  paper (89);

  for (y=0; y<11; y++)
  {
    for (x=0; x<12; x++)
    {
      n = x + y*12;
      if (n > 128)
        break;

      at (x*5, y*5);
      print ("   ");
      at (x*5, y*5+1);
      print ("   ");
      at (x*5, y*5+2);
      print ("   ");

      at (x*5+(n<10)+(n<100), y*5+1);
      print (str$(n));
    }
  }
  sync ();


  // define an instrument

  volume    (1, 255);
  wave      (1, 2);
  adsr      (1, 0, 0, 255, 0, 0);


  // play when you click

  for (;;)
  {
    mouse (x, y, b);
    if (b)
    {
      n = (x/8/5) + (y/8/5)*12;
      if (n >= 0 && n <= 128)
        midi (1, n, 0);
    }
  }
}


9. Communication with the chat bot

This chapter describes the commands that allow a console application to interact with the chat bot.

Let's start with a simple example : you wrote a console script program.txt, you compiled it into program.run, and now you would like to run it on the chat. Only a bot can start a console script (using the command console_run), so you need first to write a script for the bot.

Be careful: don't mix console scripts (that start with proc main) and bot scripts (that start with proc event) !

Here's an example of bot script (bot-script.txt) to be put in the bot's script folder :

// bot-script.txt (this is the BOT script)

proc event (session_key, userid$, sex$, has_photo, age, is_away,
            admin, cam_on, is_bot, toc_capab, signature$,
            action, is_myself, line$)
{
  if (action == 0 && pos(line$, "!test") > 0)
    console_run (session_key, "program.run");    // starts the console
}

Copy this bot script in the bot's script folder, add also your console application program.run. If you type !test on the bot, it will start the console application on your screen !

This is of course a minimal example. It is possible for example to start the console application on other chat screen than yours (you need only specify a different session_key) or more interesting : to exchange messages between the bot and console applications that run on all chatters in the room.

You use the following commands for that : (be careful: don't mix bot commands and console commands !)


BOT Command :
console_run (session_key, "ping-pong.run");
  • allow the bot to start a console application.
  • session_key : the unique number of the chatter where the console will be started.

BOT Command :
console_send (session_key, phrase$);
  • allows the bot to send a string to the console it started.
  • session_key : unique number of the chatter where the console runs.
  • attention: the length of string (phrase$) cannot exceed 4095 characters !
  • example: console_send (session_key, "it works !");
  • the console will be able to read the string using the commands bot_message_arrived() and bot_message(), see below.

CONSOLE Command :
b = bot_message_arrived();
  • enables the console to test if the bot sent it a message.
  • b will receive 1 if the bot has sent it a message, otherwise b will receive 0.
  • to read the message, see the command bot_message below.

CONSOLE Command :
bot_message(m$);
  • receives the message that the bot sent it and puts it in m$
  • if the bot didn't send anything, the function waits until the bot sends it a message.
  • the message has a maximum length of 4095 characters.

CONSOLE Command :
bot_event(message$);
  • enables the console to send a message to the bot.
  • attention: the length of string (message$) cannot exceed 4095 characters !
  • the bot will receive an event with action 702, and the message will be in line$, see the example below.


Example:


// bot-script.txt (this is the BOT script)

proc event (session_key, userid$, sex$, has_photo, age, is_away,
            admin, cam_on, is_bot, toc_capab, signature$,
            action, is_myself, line$)
{
  if (action == 128)
    bubble ("Welcome in the room, type !jeu ..");

  if (action == 0 && pos(line$, "!jeu") > 0)
  {
    console_run (session_key, "jeu.run");       // starts console
    console_send (session_key, "ça marche !");  // send message to console
    console_send (session_key, "excellent !");
  }

  if (action == 702)   // console sent us a message in line$
  {
    print ("action 702 : " + line$);  // display the message
  }
}



// jeu.txt (this is the CONSOLE application)

proc main()
{
  var m$;

  screen (640, 256);

  for (;;)
  {
    if (bot_message_arrived())  // bot sent us a message
    {
      bot_message (m$);   // read the message

      print (m$);         // print the message
      sync ();

      bot_event ("my answer is : " + m$);    // send back an answer to the bot
    }
  }
}



9.1. Transfer a banner from the bot to the console


BOT Function :
s$ = sprite_image$ (pseudo$, width, height);
  • allows the bot to convert the image-banner of a chatteur into a 256-color image in format "sprite" for the console.
  • width cannot exceed 248, height cannot exceed 248, width x height cannot exceed 4091.
  • the length of string (s$) cannot exceed 4095.
  • the computed string (s$) can contain any byte values in range 0 to 255, it depends on the color of the banner.
Example:

s$ = sprite_image$ (pseudo$, 168, 21);

will convert the bannière in a string of maximum 4+(168*21) bytes. This string is composed of a 4-byte header (width, height, nbr bits per pixel, and zero), followed by 21 times 168 bytes. Each byte represents the color of a pixel. (see chapter 7.1. Dynamic Images).

Width and Height are maximum sizes :
- if the pseudo$ is larger than 168 x 21, the image will be cut.
- if the pseudo$ is smaller than 168 x 21, the computed string will be shorter.


Example: transfer of a banner to the console

// script.txt

proc event (session_key, userid$, sex$, has_photo, age, is_away,
            admin, cam_on, is_bot, toc_capab, signature$,
            action, is_myself, line$)
{

  if (action == 127 || action == 128)
  {
    console_run (session_key, "banner.run");
    console_send (session_key, sprite_image$(userid$, 168, 21));
  }
}


// bannner.txt  (console application)

image banner1 (168 * 21, 256 colors)
{
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
  "                                                                                                                                                                                                                                                                                                                                                "
}

proc main ()
{
  var m$, length, i;

  screen (640, 120);
  paper (14);
  fill (0, 0, 40, 40, 32);
  sync();

  for (;;)
  {
    if (bot_message_arrived ())
    {
      bot_message(m$);

      // copies the string m$ into image banner1
      length = len(m$);
      for (i=0; i<length; i++)
        poke (banner1 + i, asc(m$,i+1));

      sprite_on (1, 1);
      sprite_pos (1, 0, 0);
      sprite_image (1, banner1);

      sync();
    }
  }
}




Annex 1 : Liste of displayable character codes




Annex 2 : List of colors

You have 13 base colors at your disposal : grey, red, green, blue, yellow, cyan, pink, orange, neutral green, purple, acid green, sky blue et carmine red. Each of these colors can be displayed in 16 gradations (from the darkest to the lightest). Here's a summary table of all colors :
  0 to  15 : 0=black, 1-14=grey, 15=white
 16 to  31 : red (from the darkest to the lightest)
 32 to  47 : green (from the darkest to the lightest)
 48 to  63 : blue    ...
 64 to  79 : yellow
 80 to  95 : cyan (green/blue)
 96 to 111 : pink
112 to 127 : brown/orange
128 to 143 : neutral green
144 to 159 : purple
160 to 175 : acid apple green
176 to 191 : sky blue
192 to 207 : carmine red
For example: to have an average red, pick a color between 16 and 31 : 23.




Annex 3 : Understanding scrolling

  Horizontal Scrolling 
  ====================
  to scroll line L horizontally 8 pixels left
  (what will display half of the right-hand hidden column),
  try:

  scroll (L, 8, 0);

  You can scroll a maximum of 32 pixel. To go further, you need to combine,
  with the command blit.


  Vertical Scrolling
  ==================
  Vertical scroll is harder to understand than horizontal scrolling.
  Don't forget you can only scroll full lines.
  Imagine you wanna scroll smoothly down the lines 5 to 7 of the screen.

  To prepare a hidden line that will be used to make appear text smoothly,
  execute first a command scroll on all lines, from
  line 5 til the bottom of the screen (line 31) :

    for (l=5; l<=31; l++)
      scroll (l, 0, 16);

  The effect will be that all lines will be offset,
  the content of line 6 will be displayed at the line 5 !


  Scroll then the lines 5 to 7 slowly to the bottom, with :

    for (s=15; s>=0; s--)
    {
      scroll (5, 0, s);
      scroll (6, 0, s);
      scroll (7, 0, s);

      for (t=0; t<10; t++)   // wait 1/6 sec.
        sync ();
    }

  Finally, you need to copy line 5 to line 6,
  line 6 to line 7, and line 7 to line 8
  by :

    blit (0, 5,    // from column 0, line 5
          42, 3,   // move 42 columns, 3 lines
          0, 6);   // to column 0, line 6.

  Note that line 8, although not part of the window,
  is used as hidden line !

  If you wanna display text on any line below the scroll window,
  you need to add 1 to the line !

          at (0, 9);
          print ("just below the scroll window !");

  Finally, here's a complete example :


proc main ()
{
  var y, s, t, n, l;

  screen (640, 480);


  // display a text on all lines ..

  for (y=0; y<32; y++)
  {
    at (0, y);
    print ("This is line " + str$(y));
  }


  // preparation : offset all lines
  // starting from line 5 til bottom of the screen.

  for (l=5; l<32; l++)
    scroll (l, 0, 16);


  // to scroll lines 5 to 7 down ..

  for (;;)
  {
    // display new text on line 5

    at (0,5);
    n++;
    print ("this is test line number " + str$(n));


    // scroll 16 pixel (height of a line)

    for (s=15; s>=0; s--)
    {
      scroll (5, 0, s);
      scroll (6, 0, s);
      scroll (7, 0, s);

      for (t=0; t<10; t++)   // wait 1/6 sec.
        sync ();
    }

    // move down the 3 lines
    blit (0, 5,    // from column 0, line 5
          42, 3,   // move 42 columns, 3 lines
          0, 6);   // to column 0, line 6.
  }

}


Annex 4 : Breakout game with sprites, collisions and sound


// casse_brique.txt

image balle (6 * 6)
{
  " XXXX "
  "XXXXXX"
  "XXXXXX"
  "XXXXXX"
  "XXXXXX"
  " XXXX "
}

image raquette (1 * 8)
{
  "X"
  "X"
  "X"
  "X"
  "X"
  "X"
  "X"
  "X"
}

image brique (12 * 5, 4 colors)
{
  "111111111111"
  "1XXXXXXXXXX1"
  "1XXXXXXXXXX1"
  "1XXXXXXXXXX1"
  "111111111111"
}

data brique_color
{
  0  // bord de la brique : noir
}

data colors   // 6 couleurs de brique
{
  88 72 40 120 24 136
}


proc main ()
{
  var max_x, max_y;
  var x, y, b;                // souris
  var rx, ry, rlen;           // coordonnée et longueur raquette
  var bx, by, dx, dy, speed;  // coordonnées & direction balle
  var score, vies, i, quit, briques;
  var col[100];

  max_x = 640;
  max_y = 200;
  screen (max_x, max_y);

  volume (1, 255);
  wave (1, 1);
  adsr (1, 0, 0, 128, 0, 0);

  // raquette
  sprite_on    (0, 1);
  sprite_image (0, raquette);
  sprite_color (0, 24);   // raquette rouge

  sprite_zoom  (0, 3, 3);
  rlen = 64;

  // balle
  sprite_on (1, 1);
  sprite_image (1, balle);

  // 60 briques
  for (i=2; i<62; i++)
  {
    sprite_on (i, 1);
    sprite_image (i, brique, brique_color);
    sprite_pos (i, ((i-2) % 10) * 55, 20 + ((i-2) / 10) * 30);
    col[i] = i % 6;
    sprite_color (i, peek(colors + col[i]));
    sprite_zoom (i, 2, 2);
    briques++;
  }

  // position initiale de la raquette
  rx = max_x - 64;
  ry = max_y / 2;

  // position initiale de la balle
  bx = random (0, max_x / 10);
  by = 0;

  // vitesse de déplacement de la balle
  speed = 2;
  dx = speed;
  dy = speed * 2;

  vies = 3;
  at (25, 0);
  print (dup$(chr$(1) + " ",vies) + dup$("  ", 3));

  quit = 0;
  for (;;)
  {
    if (quit || briques==0)
      break;

    // déplacer la raquette
    mouse (x, y, b);
    if (y >= -rlen && y < max_y + rlen)
      ry = y - rlen/2 + 8;
    sprite_pos (0, rx, ry);

    // déplacer la balle
    bx += dx;
    by += dy;
    sprite_pos (1, bx, by);

    // vérifier si la balle a touché le bord
    if (bx < 0)
    {
      dx = abs(dx);
      midi (1, 75, 12);
    }
    if (by < 0)
    {
      dy = abs(dy);
      midi (1, 75, 12);
    }
    if (by >= max_y-8)
    {
      dy = -abs(dy);
      midi (1, 75, 12);
    }
    if (bx > max_x)
    {
      vies--;
      at (25, 0);
      print (dup$(chr$(1) + " ",vies) + dup$("  ", 3));

      bx = random (0, max_x / 10);
      by = 0;
      dx = speed;
      dy = speed;

      if (vies <= 0)
        quit = 1;
    }

    // afficher tout
    sync ();

    // après sync, détecter les collisions entre balle et raquette
    if (sprite_collision (0) == 1)   // raquette(sprite 0) a été touché par la balle(sprite 1)
    {
      dx = -abs(dx);

      if (by + 3 <= ry + rlen/4)
      {
        dy = -2*speed;
      }
      else if (by + 3 >= ry + rlen*3/4)
      {
        dy = +2*speed;
      }
      else
      {
        if (dy < 0)
          dy = -speed;
        else
          dy = +speed;
      }
 
      midi (1, 70, 2);
    }

    // après sync, détecter les collisions entre balle et brique
    i = sprite_collision (1);

    if (i >= 2)     // balle(sprite 1) a été touchée par brique i
    {
      dy = -dy;   // changer la trajectoire

      if (col[i] > 0)
      {
        col[i]--;
        sprite_color (i, peek(colors + col[i]));
      }
      else
      {
        sprite_on (i, 0);   // éteindre le sprite brique touché
        briques--;
      }

      midi (1, 80, 2);

      score++;
      at (12, 0);
      print ("SCORE " + str$(score));
    }
  }

  at (9, 4);
  if (briques)
  {
    print (" G A M E   O V E R");
    bot_event ("PERDU");
  }
  else
  {
    print ("well done, Champion !");
    bot_event ("GAGNE");
  }
  for (i=0; i<180; i++)
    sync();
}


Annex 5 : Démo "Samuro presents"


// la démo "Samuro présente"


proc centrer (ligne, texte$)
{
  at ((40 - len(texte$))/2, ligne);
  print (texte$);
}


proc presente ()
{
  var u, t;

  for (u=0; u<=30; u++)
  {
    if (u <= 15)
      ink (15-u);
    else
      ink (u-15);

    centrer (10, "Samuro présente ..."); 

    for (t=0; t<10; t++)
      sync ();
  }
}


proc demo1 ()
{
  var u, x;

  paper(191);
  fill (0, 0, 44, 34, 32);

  ink (38);
  centrer (12, "Une nouvelle console de jeu ...");
  sync ();

  for (u=0; u<4; u++)
  {
    for (x=0; x<32; x++)
    {
      scroll (12, x, 0);
      sync ();
    }

    for (x=32; x>0; x--)
    {
      scroll (12, x, 0);
      sync ();
    }
  }

  for (x=0; x<80; x++)
  {
    blit (0, 12, 80, 1, 1, 12);
    sync ();
  }

  paper(15);
  fill (0, 0, 44, 34, 32);
}



proc colors ()
{
  var col;

  for (col=0; col<208; col++)
  {
    paper (col);
    fill (0, 0, 44, 34, 32);
    sync ();
  }

  paper(15);
  fill (0, 0, 44, 34, 32);   // 32 = espace vide
}



proc charset ()
{
  var x, y, t;

  ink (0);
  centrer (1, "Les symboles");
  centrer (2, "============");

  for (y=0; y<16; y++)
  {
    at (0, y+5);
    print (str$(y*16));

    for (x=0; x<16; x++)
    {
      at (x+5, y+5);
      print (chr$(x+16*y));
    }
  }
  for (t=0; t<240; t++)
    sync ();
}


proc balle ()
{
  var x, y, u, dx, dy, high_y;

  x = 0;
  y = 0;

  dx = 1;
  dy = 1;

  high_y = 29;

  ink (22);
  for (u=0; u<1500; u++)
  {
    if (u > 1000)
      ink (random(0, 255));

    at (x, y);
    print (chr$(145));

    sync ();

    if (u < 1000)
    {
      at (x, y);    
      print (" ");
    }

    x += dx;
    y += dy;

    if (x == 0 || x == 39)
      dx = -dx;

    if (y == 0 || y == high_y)
      dy = -dy;

    if (u == 1000)
    {
      screen (640, 480);
      high_y = 29;
    }
    else if (u > 200 && u < 1000 && y == 0 && high_y > 2)
    {
      screen (640, high_y*16);
      high_y--;
    }
  }

  ink (0);
}


proc demo2 ()
{
  var u, t, a, x, y;

  ink (56);
  centrer (0, "Voilà, c'est déjà fini !");

  for (y=0; y<60; y++)
    scroll (y, 0, 8);

  for (t=0; t<40; t++)
  {
    for (a=16; a>=0; a--)
    {
      for (y=0; y<60; y++)
        scroll (y, 0, a);
      sync ();
    }

    blit (0, 0, 80, 60, 0, 1);   // line down

    if (t == 0)
    {
      centrer (0, "                         ");
    }

    if (t == 10)
    {
      centrer (2, " oui, c'était court, je sais ...  ");
    }
  }
}


proc the_end ()
{
  var t;
  ink (0);
  paper (24);
  centrer (19, "             ");
  centrer (20, "  The End !  ");
  centrer (21, "             ");
  for (t=0; t<180; t++)
    sync ();
}


proc reduire ()
{
  var x, y, u, t;

  x = 640;
  y = 480;
  for (u=0; u<8; u++)
  {
    screen (x, y);
    for (t=0; t<30; t++)
      sync ();
    x = x / 2;
    y = y / 2;
  }
}

proc main ()
{
  screen (640, 480);

  colors ();

  presente ();
  demo1 ();
  charset ();
  balle ();
  demo2 ();
  the_end ();
  reduire ();
}



Annex 6 : the script language


Elements of the script language
===============================

Data
====

The script language can handle 2 types of data :

1) integer numbers :

        9  -62  136  0xFFD2

Values must be between -2147483647 and +2147483647
The number 0xFFD2 is in hexadecimal format (base 16 instead of the usual base 10).


2) character strings :

       ""   "Bonjour"  "Oui:p"

the first character string here above is an empty string.
the maximum length of a string is 8192 characters.


Variables
=========

A variable is a box in the PC's memory that you give a name;
The box can contain a value that can change as the program executes.

There are 2 types of variables :

- those that contain an interger number (example: compteur, i, joueur)

- those that contain a character string (example: fruit$, user$)
  (these always end with a dollar sign '$')


Before using a variable, you need to 'declare' it, which means reserve
memory space for its content, using the command 'var'.

example:

  var compteur;    // will contain a counter
  var user$, t$;   // two string variables
  var fruit$[3];   // a table of 3 strings : fruit$[1], fruit$[2] et fruit$[3]

Variables can be declared,
- at the top of the script,
- at the beginning of a function or procedure.

When they are declared at the top of a script, they keep their value
as long as the script runs; otherwise they are deleted each time
the function or procedure is called.

By default, numeric variables have the value zero, and string variables
contain an empty string.



Procedures and functions
========================

A procedure is a command to which you can give parameters,
for example 'print' to which you give the character string "Bonjour !"
which gives :

  print ("Bonjour !");

A function looks like a procedure, but it also computes a result,
for example 'len' that computes the length of a character string :

  longueur = len ("abc");


The following standard procedures/functions exist :

calender
--------
d$ = now$ ();           // function that computes the date
                        // example: now$() == "2007/01/17 12:23:12"

d  = weekday (d$);      // returns the week day (1=monday, 7=sunday) corresponding to the date
                        // example: weekday("2007/01/17 12:23:12") == 2

d$ = add_date$ (d$,n);  // returns the date older by n seconds
                        // example: add_date$("2007/01/17 12:23:12", 3600) == "2007/01/17 13:23:12"

n = nb_days_since_1901 (d$);  // returns the nb of days between 1/1/1901 and the given date,
                              // which can be used to compute the nb of days between two dates:
                              // nb_days_since_1901 (date2$) - nb_days_since_1901 (date1$)

numeric
-------
n = random (a,b);       // returns a random number between a and b
                        // example: random(1,50) == 12

n = abs (n);            // returns the absolute value of n
                        // example: abs(-2) == 2

n = sin (angle, M);     // returns the sinus(angle) multiplied by M

n = cos (angle, M);     // returns the cosinus(angle) multiplied by M

angle = atan2 (Y, X);   // returns the angle corresponding to the arc-tangeant of (Y / X)

n = sqrt (n, M);        // returns the square root of n, multiplied by M


character string
----------------
n  = len(s$);           // returns the length of string s$
                        // example: len("abc") == 3

s$ = dup$(s$,N);        // returns the string s$ duplicated N times (with N >= 0)
                        // example: dup$("ab",3) == "ababab"

s$ = chr$(N1,N2,N3,..); // returns a string made of the ascii characters N1,N2,.. concatenated
                        // example: chr$(65,66,67) == "ABC"

c  = asc(s$[,N]);       // returns the ascii code of the Nth character of string s$ (N is 1 if not given)
                        // example: asc("A") == 65
                        // example: asc("ABC",2) == 66

s$ = str$(N);           // returns a string representing the number N
                        // example: str$(23) == "23"

n  = val(s$);           // returns a number represented by the string s$ (the reverse from str$)
                        // example: val("23") == 23

s$ = left$(s$,N);       // returns the N leftmost characters of s$
                        // example: left$("ABCD",2) == "AB"

s$ = right$(s$,N);      // returns the N rightmost characters of s$
                        // example: right$("ABCD",2) == "CD"

s$ = mid$(s$,a,N);      // returns the N characters of s$ starting at the 'a'th
                        // example: mid$("ABCDEF",2,3) == "BCD"

i  = pos(s1$,s2$);      // returns the position of string s2$ in s1$, or 0 if not found
                        // example: pos("ABCDEF","CD") == 3
                        // example: pos("ABCDEF","X") == 0



In addition to the existing procedures and functions described here above,
you can write new ones; here are 3 examples :

// a function that computes the double of n
func double (n)
{
  var resultat;
  resultat = n * 2;
  return resultat;
}

// a function that returns a string made of N minus signs
func tiret$ (n)
{
  return dup$("-", n);
}

// a procedure that prints N minus signs
proc print_tiret (n)
{
  print (tiret$(n));
}


Operators
=========

Operateurs are used for computations, for example:

    2 + 3 * 4

Each operator has a priority, for example * has a higher priority than
+, which means that the example above is equivalent to :

    2 + (3 * 4)

and not to :

    (2 + 3) * 4

If the last example is wished, then parentheizes must be used.


Here are the available operators, by decreasing priority :

numeric operators
-----------------
 !     logical NOT
 *     multiplied by
 /     divided by
 %     rest of division
 &     bitwise and
 |     bitwise or
 +     add
 -     subtract
 <=    smaller than or equal to
 >=    larger than or equal to
 ==    equal to
 !=    not equal to
 <     smaller than
 >     larger than
 &&    logical AND
 ||    logical OR

string operators
----------------
 +     concatenate 2 strings
 <=    smaller than or equal to (lexical dictionnary order)
 >=    larger than or equal to
 ==    equal to
 !=    not equal to
 <     smaller than
 >     larger than


example:

  if ("ab" < "abc")
    print ("ab comes before abc in the dictionnary");



Instructions
============

Assignation
-----------
The assignation instruction is used to compute something (on the right)
and then to store the result in the variable (on the left).

  result = a * b + c;          // computes '(a * b) + c' and stores the result in variable 'result'
  line$ = "Hello" + userid$;   // concat "Hello" and userid$ and store in line$
  fruit$[2] = "pomme";         // store the string "pomme" in the box 2 of table fruit$
  ligne$ = "i contains value " + str$(i);
  longueur = len(s$) + 1;

The assignation with incrementation is used to add or subtract
a value to the variable on the left.

  i += 72;             // adds 72 to i
  j -= (b + c);

The simple incrementation is used to add 1 or subtract 1 from a variable:

  i++;       // add 1 to i
  j--;       // subtract 1 from i



if instruction
--------------

The if instruction is used to execute a group of instructions only
if a condition is met.


  // if with a single instruction

  if (i < 10)
    print ("i too small");   // executes the print only if i is smaller than 10



  // if with several instructions
  // note: brackets { } are mandatory when you have several instructions

  if (i < 10)
  {
    print ("i too small");
    print ("try again");
  }



  // "if" with "else" part

  if (i < 10)     // if i smaller than 10
  {
    print ("i too small");
    print ("try again");
  }
  else           // sinon
  {
    print ("i equal or larger than 10 ! yes");
  }



  // "if" with several cascading parts

  if (i < 10)                // if i smaller than 10
  {
    print ("i too small");
    print ("try again");
  }
  else if (i == 10)          // else if i equal to 10
  {
    print ("i equal to 10 ! yes");
  }
  else                       // else (i larger than 10)
  {
    print ("i larger than 10 ! yes");
  }



  // if with complex expressions

  if (i < 10 && j == 3 && a$ == "hello")    // if i < 10 AND j == 3 AND a$ == "Hello"
    print ("yes");

  if (i < 10 || j == 3 || a$ == "hello")    // si i < 10 OR j == 3 OR a$ == "Hello"
    print ("yes");



  // if with empty instruction

  if (i < 10)
    ;          // do nothing
  else
  {
    print ("yes");
  }



FOR instruction
---------------

The FOR instruction allows to repeat the execution a group of instructions
between { } by increasing the value of a variable of each execution.

examples:


  // to print the numbers between 1 and 5 :

  for (i=1; i<=5; i++)
  {
    print (str$(i));
  }

  prints:
    1
    2
    3
    4
    5


  // to print the numbers between 5 and 1 :

  for (i=5; i>=1; i--)
  {
    print (str$(i));
  }

  prints:
    5
    4
    3
    2
    1


WHILE instruction
-----------------

The WHILE instruction allows to repeat the execution a group of instructions
while a given condition is verified.

  // while i <= 10,
  // repeat the instructions between { }

  i = 1;
  while (i <= 10)
  {
    print ("Bonjour");
    i++;
  }


  // walk on a table tab[]
  // until finding the value 6

  var tab[512];

  .......

  i = 0;
  while (i <= 512 && tab[i] != 6)   // while i <= 512 and also tab[i] not equal to 6, increase i
  {
    i++;
  }



break and continue
------------------

  // the 'break' instruction makes you leave the repetition immediately

  for (i=1; i<=6; i++)
  {
    if (i == 3)
      break;
    print (str$(i));
  }

  prints:
    1
    2



  // the 'continue' instruction makes you go to the next execution

  for (i=1; i<=6; i++)
  {
    if (i == 3 || i == 5)   // if i equal to 3 or 5, go the next i
      continue;
    print (str$(i));
  }

  prints:
    1
    2
    4
    6




Annex 7 : Learning the script language


This tutorial will help you writing console scripts for the chat.



Chapter 1 : my first script 
===========================

To create a script, open notepad and write this :


// my first console script

proc main ()
{
  screen (160, 16);        // set screen in 160 x 16
  print ("Bonjour !");     // say hi
  sync ();                 // display on screen
  sleep (5000);            // wait 5 seconds
}


Save it under a name ending with .txt, for example "program.txt".

Then in Windows Explorer, drag and drop
"program.txt" on "run.exe"
(run.exe is in the kit you downloaded at the start).

You're gonna see a window opening itself with the word "Bonjour !"

That's it, you just wrote your first console application !


Chapter 2 : errors
==================

During compilation, the script is fully verified and checked,
what can make syntax errors appear.

For example if you had forgotten the final bracket },
you would have an error message during compilation
that would indicate you exactly the place of the problem:

ERROR: instruction expected
AT LINE: 10 COLUMN: 1
GENERATED AT: 15/07/2008 13:42:00

     1 | 
     2 | // my first console script
     3 | 
     4 | proc main ()
     5 | {
     6 |   screen (160, 16);
     7 |   print ("Bonjour !");
     8 |   sync ();
     9 |   sleep (5000);
    10 |
---------^
***ERROR: instruction expected


You need then only correct the script and try again.



Chapter 3 : style
=================

To void syntax error and ease reading
it's important to have a clear writing style.

Example :


// my 2nd script

proc main ()
{
  var i, j, l$, e;

  screen (640, 480);

  for (j=0; j<16; j++)
  {
    l$ = "";
    for (i=0; i<16; i++)
    {
      e = j*16 + i;
      l$ = l$ + chr$(e);
    }
    print (l$);
    nl();
  }

  sync();
  sleep (5000);
}

You can see in the above example that the lines in brackets { }
are each time indented by 2 blanks. It's a habit you always need to take,
it helps you forgetting brackets !

The following script works fine but it is not advised at all
because it is completely unclear !

Example :

// my 3rd script (non-advised)

proc main ()
{
var i, j, l$, e;
screen (640, 480);
for (j=0; j<16; j++)
{
l$ = "";
for (i=0; i<16; i++)
{
e = j*16 + i;
l$ = l$ + chr$(e);
}
print (l$);
nl();
}
sync();
sleep (5000);
}


When you post a script on a group or on a forum,
use the font "Courier New" because this font
keeps indentations.


the importance of comments
--------------------------

Don't hesitate, to clarify a script, to add lots of comment lines anywhere in your script.
To add a comment you need only start a line with //

These lines are ignored by the compilation.


Example:

// here's my first script
// that i created to animate
// my room.

// Copyright the scripter

proc main ()
{
  screen (160, 16);        // setup screen in 160 x 16

  // the print command will display a text on the chat !
  print ("Salut les amis !");

  sync ();                 // print on screen
  sleep (5000);            // wait 5 seconds
}



Chapter 4 : numeric variables
=============================

A variable is a box in the PC's RAM memory that has a name.
Each variable contains a numeric value between -2147483648 and +2147483647.
This value changes as the program executes.

To create a variable, you need to 'declare' it, which means reserve
memory space for its content, using the command 'var'.


example:

  var compteur;    // i create a counter that contains initially zero



At creation, variables always receive the value zero.



To change the value of a variable, you write an 'assignation'
that looks like this :


example:

  compteur = 2;   // now, compteur has the value 2



To change the value of a variable, you only need giving it
a new value :


example:

  compteur = 5;   // now, compteur has the value 5



You can do computations too. In the following example you can see :
- to the right of the equal sign, the value to compute,
- to the left of the equal sign, the variable where the result of the computation will be stored.


examples:

  compteur = 2 + 5*7;      // now, compteur has the value 37
  compteur = (5 + 4) * 7;  // now, compteur has the value 49
  compteur = -45;          // now, compteur has the value -45
  compteur = 100 - 101;    // now, compteur has the value -1



Here is how to increase the value of a variable by 1 :

example:

  compteur = compteur + 1;     // compute compteur + 1 and store the result in compteur



There exists however an abbreviated way to do the same, the incrementation :

example:

  compteur++;     // increase compteur by 1




Likewise, to reduce a variable by 1, you do a decrementation.


example:

  compteur--;     // reduce compteur by 1




Here's how to increase the value of a variable by 10 :

example:

  compteur = compteur + 10;     // compute compteur + 10 and store the result in compteur



There exists however an abbreviated way to do the same, the assignation with addition :

example:

  compteur += 10;     // increase compteur by 10




Likewise, to reduce a variable by 10 :


example:

  compteur -= 10;     // reduce compteur by 10




Chapter 5 : string variables
============================

There exists a second kind of variables : string variables.

These don't contain numbers but character strings
(letters, digits, punctuation, etc ..).

You can recognize a string variable by the sign dollar ($)
that is added at the end of its name.


example:


  var nom$;        // I create a string variable



To change the value of a string variable, you do an 'assignation'
that looks like this :


example:

  nom$ = "Bonjour";     // now, nom$ has the value "Bonjour"



To change the value of a variable, you need only assign it a new value :


example:

  nom$ = "Bonsoir";      // now, nom$ has the value "Bonsoir"



You can paste several strings together with the operator "+".

example:

  nom$ = "Bon" + "soir";       // now, nom$ has the value "Bonsoir"
  nom$ = nom$ + " mes amis";   // now, nom$ has the value "Bonsoir mes amis"



Attention: the length of a string variable cannot exceed 8192 characters.


At creation, string variables contain an empty string
(thus having 0 characters), which is equivalent to the following example.

example:

  nom$ = "";       // now, nom$ is empty





Chapter 6 : conversions
=======================

You can easily convert a numeric variable into a string variable using the
function str$()


example:

  var compteur, nom$;

  compteur = 12;

  nom$ = str$(compteur);    // now, nom$ contains "12"

  nom$ = "compteur = " + str$(compteur);    // now, nom$ contains "compteur = 12"



Inversely, you can convert a string variable into a numeric variable
using the function val()

example:

  var compteur, nom$;

  nom$ = "12";

  compteur = val (nom$);      // now, compteur equals 12

  compteur = val ("13");      // now, compteur equals 13

  compteur = val ("ab");      // this will cause an error that will stop the script,
                              // because "ab" can't be converted into a numeric value !



Chapter 7 : display on screen
=============================

Displaying text on the chat screen is done using the procedure print()

example:

  print ("Bonjour !");
  print (nom$);



It is not allowed to give print() a numeric variable, for example
this will not work :

example:

  print (compteur);         // error



To display the value of compteur, you have to convert it to string first :

example:

  print (str$(compteur));
  print ("the value of compteur equals " + str$(compteur));




Chapter 8 : tables
==================

Instead of reserving each variable separately, you can reserve
a whole table of variables.

example:

  var compteur[100];       // I create 101 counters



In fact the above example creates the following 101 counters :


  compteur[0]
  compteur[1]
  compteur[2]
  compteur[3]
  ...
  compteur[100]


You can store values in these counters, like this :


example:

  compteur[5] = 12;    // store 12 in counter number 5

  compteur[5]++;       // increase counter 5 by 1

  compteur[i] = 13;    // store 13 in counter i



The last example here above will cause an error if the value of variable 'i'
is outside the range 0 to 100.



Chapter 9 : the IF instruction
==============================

Conditions are used to "test" variables.

You can for example say "if the variable xxx equals 50, do this ..."

But it would be a pity to be able to test only equality !

You'd have to be able to test also if the variable is less than 50,
less or equal to 50, above, above or equal ... 

But don't worry, the script language allows all of this  (you didn't doubt it didn't you)

Before watching how to write a condition of the form "if... else",
it's necessary for you to know 2 or 3 base symbols.
These symbols are mandatory to express conditions. 


Here's a small symbol table you need to know by heart :

  Symbol   Meaning
  ======= =============
     ==    Is Equal to
     >     Is Larger than
     <     Is Smaller than
     >=    Is Larger than or equal to
     <=    Is Smaller than or equal to
     !=    Is different from

Be very careful, there are 2 symbols "==" to test equality.
A common error that beginners do is to write only one = symbol.
I'll talk about it somewhat later.


A simple if
-----------

Let's start now. We're gonna do a simple test that will say to the computer : 

IF the variable has this value
THEN do this

For example, we could test a variable "age" that contains your age.
Let's try this, we're gonna test if you're adult,
meaning if your age is larger or equal to 18 : 

example:

  if (age >= 18)
  {
    print ("You are adult !");
  }


Symbol >= means "Larger or Equal", like we saw it in the previous table. 

If there's only one instruction between brackets, then these become optional.
You can thus write :


example:

  if (age >= 18)
    print ("You are adult !");



If you want to test the previous codes to see how if works,
you will have to put the if inside a main procedure main and not forget to declare
a variable age which will receive the value of our choice.

It's maybe simple for some people but apparently not for all,
so i added this example to help you :


example:

  proc main ()
  {
    var age;

    screen (640, 480);

    age = 20;

    if (age >= 18)
      print ("You are adult !");

    sync ();
    sleep (5000);
  }



Here the variable age equals 20, so the "Vous êtes majeur !" will appear.

Try to change the initial value to see.
Try for example 15 : the condition will be false, and so the "You are adult !" will not be displayed this time.

Use this base source code to test the following examples of this chapter.


A question of style
-------------------

The way you write your brackets seems at first not important,
your program will work as well if you write everything on the same line.

For example :

  if (age >= 18) {  print ("You are adult !"); }

However, even if it's possible to write like this, it is a very bad idea !!
Indeed, writing everything on the same line will make your code unreadable.

If you don't take the habit now to open up your code,
then later when you write much larger programs you will get lost !

So try to present your source code the way I do :
a bracket on a line, then your instructions (preceeded by two blanks
to indent them to the right), then a closing bracket on a line.

There are several good ways of presenting source code.

It doesn't change anything to the working of the final program, it's more a question
of "computer science style" if you like. If you see the code of someone else
that's presented a little differently, it means he's coding with a different style.

The important thing is that the code is readable. 



The "else" part
---------------

Now we know how to do a simple test, let's go a little further :
if the test didn't work (it is false), we will tell the computer
to execute other instructions.

In english, we will write something that looks like this : 

IF the variable's value is this
THEN do this
ELSE do that

You need only add the word else after the closing bracket of the if. 
Little example : 

  if (age >= 18) // If age is larger or equal to 18
  {
    print ("You are adult !");
  }
  else   // Sinon...
  {
    print ("Aw that's bad, you are a teenager !");
  }


Things are rather simple : if the variable age is larger or equal to 18,
you write the message "You are adult !", else you write "Aw that's bad, you are a teenager !".


"else if"
---------

We saw how to do an "if" and an "else".
it's also possible to do a "else if".


In that case, you tell the computer : 

IF the variable's value is this THEN do this
ELSE IF the variable's value is that THEN do that
ELSE do that


Translation:

  if (age >= 18)       // If age is larger or equal to 18
  {
    print ("You are adult !");
  }
  else if (age > 4)    // Else, If age is larger than 4
  {
    print ("Hmm so you're not that young...");
  }
  else                 // Sinon...
  {
    print ("Aga gaa aga gaaa gaaa");   // Baby language, you can't understand ;o)
  }



The computer does things in order :


First, it tests the first if : if the condition is true, then it executes
what's between the first brackets.

Else, it goes to the "else if" and does another test : if this test is true,
then it executes the corresponding instructions between brackets.

Finally, if none of the previous tests worked, it executes the instructions of the "else". 

The "else" and "else if" are not mandatory. To write a condition,
you only need at least an "if" (logical would you say, otherwise there wouldn't be a condition !)

Note that you can write as many "else if" as you want. You can thus write :

IF the variable equals this THEN do this 
ELSE IF the variable equals that THEN do that
ELSE IF the variable equals that THEN do that
ELSE IF the variable equals that THEN do that
ELSE do that


Several conditions at once
--------------------------
It can also be useful to do several tests at once in your if.
For example, you would like to test if the age is larger than 18 AND if age is smaller than 25.
To do that, you will have to use new symbols :


  Symbol   Meaning
  ======  ==========
    &&       AND 
    ||       OR
    !        NOT 


AND Test
--------
If you want to do the test I mentionned above, you will have to write : 


example:

  if (age > 18 && age < 25)

The symbol "&&" means AND.

Our condition would be, in english :

"If age is larger than 18 AND if age is smaller than 25" 


OR Test
-------
To do an OR, you use 2 signs ||. I must admit this sign
isn't easy to write on some keyboards. On an AZERTY keyboard,
you have to do Alt Gr + 6 or Alt Gr + &. 

Imagine we have a stupid program that decides if a person is allowed to
open a bank account. It's well knows that you better not be too young to open
an account (we will say you need to be at least 30) or you better
have your pockets full of money (because then, even if you're age 10, you will
be accepted with open arms)

Our test to know if a customer has the right to open a bank account could be :

  if (age > 30 || money > 100000)
  {
    print ("Welcome to Picsou Banque !");
  }
  else
  {
    print ("Get out of here, misérable !");
  }

This test is valid only if the person is older than 30 years if if she owns more than 100 000 euros.


NOT Test
--------
The last symbol we need to learn is the exclamation mark.
In computer science, the exclamation mark means "No".
You have to put this sign before your condition to tell "if this is NOT true" : 

example:

  if (!(age < 18))

This could be translated as "If the person is NOT a teenager". 
If you had removed "!" it would have meant the opposite : "If the person is a teenager". 


Some errors made by beginners
-----------------------------

Don't forget the two signs ==
-----------------------------

If you want to test if the person has exactly 18 years, you have to write : 

example:

  if (age == 18)
  {
    print ("You just became an adult !");
  }

Don't forget to use 2 "equal" sign in an if, like this: == 


The extra semicolon
-------------------
Another beginner's mistake : put semicolons at the end of a line of an if.
However, an if is a condition, and you put a semicolon only at the end of
an instruction and never of a condition.
The following code will not work as expected because there's a semicolon too much : 

example:

  if (age == 18); // Note the semicolon that should NOT be there
  {
    print ("You just became an adult !");
  }



Booleans, the heart of conditions
---------------------------------
We are now going to enter more in detail in the working of a conditon of the form if... else.
Indeed, conditions work with something called booleans in computer science.

It's a very important concept, so open your ears widely (euh i mean your eyes)


Some little tests to understand well
------------------------------------
In physics, my teacher always had the habit of making us do some little experiences
before introducing a new concept. I will do likewise today.


Here's a very simple source code that i ask you to test : 


example:

  if (1)
  {
    print ("It's true");
  }
  else
  {
    print ("It's false");
  }


Result : 

  It's true


But ??? We didn't put a condition in the if, just a number.
What does it mean, it makes no sense ?

Yes it does, you will understand.
Try another test now by replacing the 1 by 0 : 

example:

  if (0)
  {
    print ("It's true");
  }
  else
  {
    print ("It's false");
  }

Result : 

  It's false


Do other tests now by replacing the 0 by any other number,
like 4, 15, 226, -10, -36 etc... 
What does the program respond you each time ? It responds : "It's true".

Summary of our tests : if you put a 0, the test is considered as false,
and if you put a 1 or any other number, the test is true.


Some explanations
-----------------
In fact, each time you do a test in an if,
the test computes a value 1 if it's true, and 0 if it's false. 

For example : 

  if (age >= 18)

Here, the test you're doing is "age >= 18". 

Let's suppose the age is 23. Then the test is true,
and the computer "remplaces" somehow "age >= 18" by 1.

Then the computer sees (in its head) a  "if (1)".

When the number 1, as we saw, the computer says the condition is true,
so it displays "It's true" ! 

Likewise, if the condition is false, it remplaces age >= 18 by the number 0,
and so the condition is false : the computer reads then the instructions of the "else". 


A test with a variable
----------------------

Try now something else : store the result of your condition into a variable,
as it were an operation (because for the computer it is an operation !).


example:

  var age, majeur;

  age = 20;
 
  majeur = age >= 18;

  print ("majeur equals : " + str$(majeur));



As you saw, the condition age >= 18 results in the number 1 because it is true.
So our variable majeur receives 1, we check that by doing a print
that shows the variable's value. 

Do the same test by changing the example into age = 10; for example. This time, majeur will be 0. 


This variable "majeur" is un boolean !

Remember this : 

A variable which receives the values 0 and 1 is a boolean.


And also this : 

0 = False 
1 = True


To be accurate, 0 = false and all other values are true
(we tested this above).

However, to simplify things we will just use the values 0 and 1, to say if something is false or true. 


Booleans in conditions
----------------------

Often we will do an "if" test on a boolean variable :

example:

  var adult;

  adult = 1;

  if (adult)
  {
    print ("You are adult !");
  }
  else
  {
    print ("You are a teenager !");
  }


As adult equals 1, the condition is true, so it displays "You are adult !". 

That's very practical because the condition is easily read by a human being.
You can see that "if (adult)", can be translated by "if you are an adult".

Tests on booleans are thus easy to read and understand,
provided you gave clear names to your variables
like i tell you since the beginning.

Here's another imaginary test : 


example:

  if (adult && male)


This test mean "If you are an adult AND if you are a male". 
male is here another boolean variable that equals 1 if you are male,
and 0 if you are a female !  Well done, you understood it all !

Boolean help thus to express if something is true or false.
It's very useful, and what i just explained you will help you understand
a lot of things later.


Small question : if we do the test "if (adult == 1)", it works too ?

Sure. But the principle of booleans is to make the condition shorter and more readable.
You have to admit that "if (adult)" is easy to understand, isn't it ?

So remember this : if your variable contains a number,
do a test under the form "if (variable == 1)".
If on the other hand your variable contains a boolean (which is a either
1 or 0 to say false or true), then do a test under the form "if (variable)".

--------------------------------------------------------------------------------

The condition "if... else" that we just saw if the type of condition the most often used. 
There ain't 36 ways to write a condition. The "if... else" can handle all of them.

example:

  if (age == 2)
  {
    print ("Hallo baby !");
  }
  else if (age == 6)
  {
    print ("Hey little !");
  }
  else if (age == 12)
  {
    print ("Hi young boy !");
  }
  else if (age == 16)
  {
    print ("Hi teeny !");
  }
  else if (age == 18)
  {
    print ("Hallo young adult !");
  }
  else if (age == 68)
  {
    print ("Hi daddy !");
  }
  else
  {
    print ("I have no greeting for your age");
  }



--------------------------------------------------------------------------------

Chapter 10 : loops
==================

What's a loop ? 
It's a technique that allows to repeat the same instructions several times.

Like for conditions, there are several ways to write loops.
At the end, it gets to always doing the same thing :
repeat the same instructions a given number of times. 

In all cases, the scheme is the same : 

        <----------
  Instructions     ^
  Instructions     ^
  Instructions     ^
  Instructions     ^
        -----------^


Here's what's happening, in order : 

The computer reads the instructions from top to bottom (as usual).
Then, once arrived at the bottom of the loop, it starts again at the first instruction.
It starts then again reading instructions from top to bottom ... 
... and it starts again at the top of the loop. 


The probleme in this system is that, if it is never stopped,
the computer is able to repeat the instructions for ever !
He's not the kind that complains you know, it will do as it's told ..

And that's where we meet again ... conditions ! 
When you create a loop, you always indicate a condition.

This condition will mean "Repeat the loop while this condition is true".

There are several ways to do it i told you.
Let's see how you write a loop of the "while" form.

--------------------------------------------------------------------------------

The While loop
--------------


Here's how to build a loop of type 'while' : 

example:

  while ( Condition )
  {
      // Instructions to repeat
  }

It's as simple as that.
So you tell the computer "while the condition is true : repeat the instructions between brackets".

It means our loop will repeat a given number of times.
For this, we will create a new variable "compteur" that will contain 0 at the start of the program
and that we will increment as time goes by.

You remember incrementation ?  It means adding 1 to a variable by doing "variable++;". 

Now look carefully at this piece of code and try to understand it : 


example:

  var compteur;

  compteur = 0;

  while (compteur < 5)
  {
    print ("Salut !");
    compteur++;
  }


Result : 

  Salut ! 
  Salut ! 
  Salut ! 
  Salut ! 
  Salut ! 

This code repeat 5 times the display of "Salut !". 

How does it work exactly ?


At the start, you have a variable compteur initialized at 0. So it equals 0 at the start of the program. 

The while loop orders the repetition WHILE compteur is less than 5.
As compteur is 0 at the start, we enter the loop.

We display the word "Salut !" via a print.

We incremente the valeur of the variable compteur, thanks to the instruction "compteur++;".
Compteur had the value 0, now it equals 1.
We arrive at the end of the loop (closing bracket), so we start again at the top,
at the WHILE.

We do again the while test : "Is compteur still less than 5 ?".
Well yes, compteur equals 1  So we start again the instructions of the loop.

And so on ... Compteur will progressively get the values 0, 1, 2, 3, 4, 5.

When compteur equals 5, the condition "compteur < 5" is false.
As the condition is false, we leave the loop.

We could display the variable compteur's value by a print : 

example:

  var compteur;

  compteur = 0;

  while (compteur < 5)
  {
    print ("the variable compteur equals " + str$(compteur));
    compteur++;
  }


the variable compteur equals 0 
the variable compteur equals 1 
the variable compteur equals 2 
the variable compteur equals 3 
the variable compteur equals 4 


That's it, if you understood this, you got it all.
You can now enjoy yourself by increasing the number of loops
try "<10" instead of  "<5".


Watch out for infinite loops
----------------------------
When you create a loop, make sure it can stop some time !
If the condition is always true, your propram will never stop !
 
Here's an example of infinite loop : 

example:

  while (1)
  {
    print ("infinite loop");
  }

Remember the booleans : 1 = true, 0 = false. Here, the condition is always true,
so this program will display "infinite loop" for ever !

To stop such a program you have to close the chat !

So be careful : avoid at all cost falling into an infinite loop. 

--------------------------------------------------------------------------------

The For loop
------------
In theory, the while loop allows to write any loop you like. 
However, it is useful in some cases to have another loop syntax
more "condensed", faster to write.

"For" loops are used very often.
I don't have statistics available, but you should know
you will probably use as many for as while loops, so you will have to be at ease
with these two types of loops. 

As i told you, for loops are just another way to write while loop. 

Here's an example of while loop we saw earlier : 

example:

  var compteur;

  compteur = 0;

  while (compteur < 10)
  {
    print ("Salut !");
    compteur++;
  }


Now here's the equivalent in for loop : 

example:

  var compteur;

  for (compteur = 0 ; compteur < 10 ; compteur++)
  {
    print ("Salut !");
  }



What differences ? 


There are many things between the parentheizes after the "for" (we will detail that below) 
There is no more compteur++; in the loop.

Let's look at what's within parentheizes, because that's where all the interesting
parts of the for loop are. There are 3 condensed instructions,
separed by a semicolon : 

The first one is the initialization : this first instruction is used
to prepare our variable compteur. In our case, we initialize the variable to 0.

The second one is the condition : as for the while loop, it's the condition that says
if the loop must be repeated or not. As long as the condition is true, the for loop continues.

Finally, there's the incrementation : this last instruction is executed at the end
of each loop to update the variable compteur.
In almost all cases you will do an incrémentation, but you can also do
a decrementation (variable--;) or do any other operation
(variable += 2; to advance 2 by 2 for example).

So, as you see, the for loop is nothing else than a condensed while loop.
Know how to use it, you will need it more than once ! 

--------------------------------------------------------------------------------

Chapter 11 : base procedures and functions
==========================================

What's a procedure ?  well for example "print" that you know well.
But there are many more !

You know also two functions : str$ and val, that allow
converting between string and numeric value.

In fact the difference between procedure and function is that a procedure
is a command, whereas a function computes something and returns the result.

We will study some functions to see how it works :


d$ = now$ ();           // function that computes the date
                        // example: now$() == "2007/01/17 12:23:12"

s$ = mid$(s$,a,N);      // returns N characters of s$ starting at the 'a'th
                        // example: mid$("ABCDEF",2,3) == "BCD"

n = random (a,b);       // returns a random number between a and b
                        // example: random(1,50) == 12



The function now$() is simple : it returns the date and time of the PC.
For example you can write.

example:

  var ma_date$;

  ma_date$ = now$();   // put the date in ma_date$

  print (ma_date$);


which will print for example:

  2007/01/17 12:23:12


The function mid$() is very useful for extracting a substring of a string.
For example imagine I wanted to extract only the hour from the date.


example:

  var ma_date$, heure$;

  ma_date$ = now$();   // put the date in ma_date$

  heure$ = mid$ (ma_date$, 12, 2);   // take a copy of date starting at 12the character,
                                     // and copy 2 character
  print (heure$);


which will print for example:

  12


The function random() allow drawing a random number, which is very useful for games.


example:

  var i;

  i = random (1, 100);   // pick a number from 1 to 100 to store in i

  print ("we pick " + str$(i));


In the console documentation, you will find lists of all existing procedures and functions.


back to previous page