Provided by: cuyo_1.8.6-1_i386 bug

NAME

       Cual - Cuyo Animation Language

       Cual is the main language used to describe the animations in cuyo. It’s
       the stuff between the << >> brackets in  the  level  description  files
       (xxx.ld).

       This  man page is not a complete description of how to write levels for
       cuyo; it only describes Cual. And it’s still under  construction.   See
       the  file  "example.ld"  to  get  an  idea of how the rest of the level
       description  works.  There’s  also  a  bit  of  example  Cual  code  in
       "example.ld". And of course, all the existing levels are examples.

       Note  that  Cual  is  probably still very buggy. It has almost not been
       tested.  (The existing levels work, but  that’s  all.)  So  if  strange
       things   happen   and   you’re  sure  it’s  not  your  fault,  tell  me
       (cuyo@karimmi.de).

HOW IT WORKS

       Each blob has its own (main) Cual procedure which does the drawing  and
       the  animation  stuff.  The  procedure  only depends on the kind of the
       blob, that is, it is the same for blobs of the same kind. However  each
       blob has its own instance of the variables.

       In  every game step, the procedure of each of the blobs is called once.
       (There are 10 game steps per second.) It has  to  draw  the  blob  each
       time,  even  if  nothing  has  changed.  (However,  there’s an internal
       routine in cuyo which checks if the same is drawn as in the  last  step
       and which then supresses the drawing.)

       There  may  be other procedures associated to a kind of blob, which are
       executed at special events, for example when a falling blob lands.   In
       contrast to the main procedure, these event handlers are not allowed to
       draw anything. See section "event handlers" for a list of the  existing
       events.

       The name of the main procedure of a blob (the one which draws the blob)
       is the name of the kind of the blob. Normally, that name  is  the  word
       listed after pics= entry in the .ld file; but if that "word" contains a
       dot, only the part before the dot  makes  up  the  name.  (E.  g.  with
       pics=redblob.xpm,greenblob.xpm,    the    names   are   "redblob"   and
       "greenblob".)

       The name of an event  handler  procedure  is  the  name  of  the  kind,
       followed by a dot, followed by the event name. (E.g. "redblob.land" for
       the landing event of the redblob from above.)

       [Explain the default procedures.]

DEFINITIONS

       Inside << >>, variable and procedure definitions are expected.

       procname = code ;
              Defines a "procedure". The next section describes how code looks
              like.
              Example:
              redblob = {
                schema16; 0*;
                1; A,B,C; *;
              };

       var varname1 = def1, varname2 = def2, ... ;
              Defines variables with default values.  The default value can be
              omitted (together with the "=" before  it).  Then,  the  default
              value  is zero.  See section about variables and constants about
              the meaning of the default value.

CODE

       A code fragment can be one of the following:

       { code; code; ...}
              Executes one command after the other.

       code, code, ...
              This is useful for simple animations.  Executes exactly  one  of
              the  commands:  In  the n-th call, the n-th command is executed.
              After the  last  command,  the  first  one  is  executed  again.
              However,  if  one  of  the commands is "busy" (see section about
              busieness), this one will be executed until it stops being busy,
              and only after that, the next command will be executed.

       procname
              Executes  the  procedure  procname,  which  has  to  be  already
              defined. The result is the same as if  the  code  from  procname
              would have been inserted in that place.

       &procname
              Executes the procedure procname; however, every instance of such
              a procname is the same. This concerns busieness and the state of
              an  animation  sequence.  (See sections BUSIENESS and AMPERSAND-
              CALL.)

       busy   Does nothing except being busy. (See section BUSIENESS.)

       varname = expr
              Sets the variable. See section  "VARIABLES  AND  CONSTANTS"  for
              details.

       The same with +=, -=, *=, /=, %=
              Does what you would expect.

       [ varname = expr ] code
              Sets the variable varname to expr, executes code and then resets
              the variable to the old value.

       number A shortcut for "file = number".

       letter A shortcut for "pos =  number",  where  different  letters  mean
              different numbers: A: 0, B: 1, ..., Z: 25, a: 26, ..., z: 51

       *      Draw  the  icon  specified  by the variables kind, file and pos.
              May also draw only a part of  the  icon,  if  specified  by  the
              variable qu (see section about variables and constants).

       *@(x, y)
              Like  *,  but  draws  the  icon  at  relative  coordinates x, y.
              Relative drawing is always performed after  all  other  drawing.
              (See  section  about  variables  and  constants for more details
              about @.)

       if expr if-arrow if-code ;
       if expr if-arrow if-code else [else-arrow] else-code ;
              The arrows can be either "->" or "=>".  If you  use  "->"
              arrows, it does exactly what you would expect.
              If  the  if-arrow  is "=>", then once the expression gets
              true, the if-code will be executed every subsequent  time
              (without testing the condition), as long as it is "busy".
              More details see section BUSIENESS.
              If the else-arrow is "=>", then once the expression  gets
              false,  the  else-code  will be executed every subsequent
              time as long as it is busy.
              If the else-arrow is omitted, "=>"  is  used.  (But  this
              might change in the future.)

       switch {
         expr1 arrow1 code1 ;
         expr2 arrow2 code2 ;
         ...
       }      The arrows can be either "->" or "=>".  Does the same as:
                if expr1 arrow1 code1
                else if expr2 arrow2 code2
                ...
              The last expr may be omitted to get an else part  without
              further condition.

       bonus(expr)
              The player gets expr bonus points.

       message(String)
              The  string is displayed (blinking) on the screen.  To be
              used together with bonus(...).
              Example:
              bonus(50);
              message("You get 50 bonus points");

       explode
              Makes the blob explode. For the next 8 steps or  so,  the
              blob  is  still  what it was before, but the explosion is
              drawn over the graphics. After that, it’s  changed  to  a
              nothing-blob.

       There’s  a  shortcut for drawing: You may omit the ";" between a
       number, a letter and the "*".

EXPRESSIONS

       The only data type in cual is int. Bools are  represented  by  0
       and 1, like in C. (And any number other than 0 is interpreted as
       true, if a boolean is expected.)

       Of course, variables, constants and numbers are expressions, and
       you can use parentheses. There are the following operators:

       The  following operators do exacly the same as in C (listed here
       by precedence):

       ||                     Boolean or
       &&                     Boolean and
       ==, !=, <, >, <=, >=   Comparision
       !                      Boolean not
       +, -                   Add, substract
       *, /, %                Multiply, divide, modulo

       [Insert precedence of special operators.]

       The following special operators exist:

       expr == number1 .. number2
              Is true, if expr lies between the two  numbers.  You  may
              also  omit one of the numbers. (Then, it does the same as
              <= resp. >=.) Note that this operator might change in the
              future.  (I  plan to make something like "expr in set" in
              pascal.)

       number1 : number2
              Is true (that is, 1) with probability number1/number2

       neighbour_pattern
              neighbour_pattern  is  a  sequence  of   six   or   eight
              characters  0,  1 and ?.  It is true if the sequence fits
              to the neighbour sequence of  the  blob.   The  neighbour
              sequence is a string of "0"s and "1"s with a "1" for each
              neighbour of the same  kind,  starting  above  and  going
              clockwise.  This  way,  you  get a string of "0"s an "1"s
              (six or eight, depending on wether this level is  in  hex
              mode).
              Example: 1???0??? is true iff the blob above this blob is
              of the same kind and the blob below it  is  of  different
              kind.
              If  some  blob  changes  its  kind  during  a  step,  the
              expression will still test the neighbours as they were at
              the  beginning  of  the  step.   (See  the  section about
              variables and constants for details.)

       The following functions exist:

       rnd(expr)
              Returns a random value between 0 and expr-1

VARIABLES AND CONSTANTS

       The following kinds of variables and constants exist:

       - User defined variables (see  section  "Definitions").  At  the
         start  of the level (or at the creation of the blob) the value
         is the default value you provided.

       - System variables. These variables are always defined and  have
         special  meanings,  e.g.  file and pos. Some of them are read-
         only.

       - Constants. Some of them depend on  properties  of  the  level,
         some are really constant.

       Of  each  variable, there’s one instance in each blob. Normally,
       you access the instance in your own blob, but with the following
       syntax, you can access variables of other blops:
         varname@(dx, dy)
       dx  and  dy are relative coordinates. This can be done for both,
       reading  and  writing  variables.  It  also  works  for   system
       variables  (but  not  for  constants).   Be aware that dx and dy
       can’t be expressions; they have to be fixed numbers.

       In hex mode levels, for odd dx, dy has to be a  "half  integer",
       that  is a number ending in ".5". This is the only place in Cual
       where non-integers appear.

       There’s also one global instance of each variable. That one  can
       be acessed by
         variable@
       (without   coordinates).  See  section  "The  Global  Blob"  for
       details.

       Accessing foreign variables is not as easy as it might  look  at
       first  glance;  it  might  easily  introduce a dependence of the
       internal order of execution of the blob codes. For this reason,

       - reading variables with @  always  returns  the  value  of  the
         variable it had at the beginning of the current step, that is,
         before any of the blob codes has been executed.

       - when writing variables with @, the write operation  will  only
         be  executed  at  the  end  of  the  current  step. (The write
         operations are stored in a kind of queue.)

       This is also true if a blob  accesses  its  own  variables  with
       @(0,0).

       The  operators +=, -=, etc.  are also performed in the future if
       the left hand side is an @-variable.  (To be more  precice,  the
       right hand side is calculated instantanousely.)

       For illustration, look at the following six statements:

       1) X += 1
       2) X@(0, 0) += 1
       3) X = X + 1
       4) X = X@(0, 0) + 1
       5) X@(0, 0) = X + 1
       6) X@(0, 0) = X@(0, 0) + 1

       Only 1) and 3) do the same; they simply increment X by 1.
       Statement  4) sets X to one more than it was at the beginning of
       the step.
       Statements 2), 5) and 6) cause the value of X to be  changed  in
       the future (after the actual step): X is set to one more than:
       2)  the  value  of  X  just  before  the  change  (that is, X is
       incremented in the future),
       5) the actual value of X,
       6) the value of X at the beginning of the step.

   Some more details
       - Whenever you try to access a  variable  at  a  location  which
         doesn’t exist, you will get the default value.

       - Changing a variable which doesn’t exist does nothing (and does
         not result in an error).

   The system variables
       file   Specifies the file number from which  to  take  the  icon
              that  is drawn by "*". This variable is reset to 0 before
              the drawing procedure is executed.

       pos    Specifies the position in the file of the  icon  that  is
              drawn  by  "*".  This  variable  is reset to 0 before the
              drawing procedure is executed.

       kind   The kind  of  the  blob.  There  are  constants  for  the
              possible  values  of  this  variable.   If you change the
              kind, you should be aware of two things:
              Expressions like "001???01" test the neighbour pattern at
              the  beginning  of  the actual step. So the change of the
              variable kind will not be reflected.
              In the actual step, the program  to  draw  the  blob  has
              already  been invoked (in fact, the program which changed
              this variable); so in this step, the blob will still look
              like  one  of  the old kind. However, if things are drawn
              after the kind has been changed, icons from the new  kind
              are taken.

       version
              Only  important for the "grass": Is set to the the number
              specified by the letter in the startdist. (A = 0, ...,  z
              = 51).

       qu     Tells  "*"  which part of the icon to draw. It’s possible
              to draw the whole icon, or only one of its quarters. If a
              quarter  is drawn, you may specify independently which of
              the quarters to take and at which position  to  draw  it.
              Use the constants (see below).  This variable is reset to
              "draw all" before the drawing procedure is executed.

       out1, out2
              Set these Variables for debug output. The values will  be
              printed  on  top of the blob. There variable are reset to
              "output  nothing"  before  the   drawing   procedure   is
              executed.  (In  fact, "output nothing" is one special big
              value.)

       inhibit
              Set this variable to a sum of the constants DIR_...; this
              will  inhibit  that  this  blob  connects  into the given
              directions. This is not for  the  graphics  but  for  the
              calculation   of   the   connected   components  and  the
              explosions.

       goalblob
              Set goalblob to 1 if this blob should act like grass: You
              will  have  to  get rid of it to win the level and making
              this blob explode will give more points. Note that  grass
              does not need goalblob = 1 to act like grass.

   The system read-only variables
       turn   Is 1 resp. 2 if the blob is falling and just being turned
              by the user and 0 otherwise.  (1  in  the  first  turning
              step,  2  in  the second one.)  Be aware that if the user
              presses the turn key fast several times,  some  of  these
              steps  may be omitted. (Use the turn event if you want to
              be sure that a program block is executed once  for  every
              turn.)

       connect
              Contains internal data. Will be removed. Probably.

       size   The size of the component of the blob. (That is, how many
              blobs are connected.)

       loc_x, loc_y
              The absolute coordinates of the blob. (0,0)  =  top  left
              corner

       loc_p  The player of the blob (1 or 2)

       falling
              true,  if  the  blob is falling. (Falling in the sense of
              steered by the player. Grey blobs are not falling in that
              sense.)

       falling_fast
              true,  if  the  blob  is  falling fast, that is, the user
              pressed the down key.

       players
              The number of players.

       exploding
              When the blob is exploding, the position in the explosion
              animation (1 - 8); 0 else.

   The Constants:
       Constants for qu:

       Q_ALL  Value for qu, which means "draw the complete picture".

       Q_TL, Q_TR, Q_BL, Q_BR
              Values  for  qu.  "TL"  means draw top-left quarter, etc.
              (See the "*" command in the Code section.)

       Q_SRC_DST
              SRC and DST may be TL, TR, BL, BR. Take quarter  SRC  and
              draw it at position DST

       DIR_XX To  be used with the variable inhibit to prevent the blob
              connecting in the given directions. XX can be U, D, L,  R
              (horizontal  and  vertical);  UL,  UR, DL, DR (diagonal);
              UUL, UUR, DDL, DDR, LLU, LLD, RRU,  RRD  (knight);  F,  B
              (3d)

       Constants for kind and for change:

       <name of kind of blob>
              For each kind of blob, there’s one constant with the name
              of that kind. Use it to check if a blob is of  that  kind
              using  "kind@(x,y)  ==  aKind"  or to change to that kind
              using "change = aKind" These constants do also exist  for
              the grass kind, the grey kind and, if existent, the empty
              kind.

       nothing
              Is the same as the  constant  for  the  empty  kind.   Is
              provided,  because  sometimes,  you  don’t  have an empty
              kind, but you still need to test if a blob is empty.

       outside
              The value of kind if the coordinates are outside  of  the
              game board.

BUSIENESS

       (No, not Business ;-)
       Busieness  is  a  concept  to make it easier to implement simple
       animated sequences which are triggered by certain  events.  Each
       code fragment has an internal state which tells if it is busy.

       - Normal statements like assignments are never busy.

       - A  chain  of  commands separated by "," is busy as long as not
         all of the commands have been executed.

       - code1 ; code2 is busy as long as at least  one  of  code1  and
         code2 are busy.

       Here’s an example of how to use busieness for an animation which
       appears at random intervals:

       switch {
         1/100 => {B*, C*, D*, E*};
         -> A*;
       };

       This code fragment normally draws the icon at  position  A  (0).
       But  in  each  step,  with  a probability of 1/100, an animation
       sequence consiting of icons B, C, D and E  is  started.  With  a
       normal arrow ("->") after the "1/100", after the step in which B
       has been drawn, the probability would be 99/100 that A is  drawn
       again.  But  with  the  double arrow, the switch statement won’t
       switch back to A until the animation has terminated.

       (Btw: It doesn’t matter if there’s a "->" or a "=>"  before  the
       "A*"; A* isn’t busy anyway.)

THE GLOBAL BLOB

       Apart from the normal blobs which you can see on screen, there’s
       one global blob (for the whole game, not one for  each  player),
       which,  well, isn’t really a blob, but behaves a bit like it. It
       has its own set of variables, and it can have a program which is
       run  once  every  step.  To  define  such  a global program, use
       "global=code". However, the global variables do  exist  even  if
       you  don’t define global code. See section "Variables" on how to
       access them.  Note that  the  global  blob  is  always  executed
       before any of the normal blobs.

EVENT HANDLERS

       The following events exist:

       init   Is  called  only once, when the blob gets into live, just
              before the first time its main drawing routine is called.

       turn   Is  called  for  falling blobs each time the user presses
              the turn key.

       land   Is called when the steered blob lands.

       changeside
              Is called when a blob moves from one player to the other,
              just after the blob has arrived at the new player.

THE LIFE OF A BLOB

       Normal  blobs  come  into  life at the beginning of the game, or
       they fall into life: either as colored  blobs,  steered  by  the
       user,  or as grey blobs.  When a blob moves (by gravitiy or when
       rows go from one player to another), it takes its variables with
       it.  When a blob explodes, it does not stop existing. Rather, it
       transforms  into  an  empty  blob.  That’s  important  for   the
       variables: The empty blob still has all the variables set to the
       values they had before; only its kind is different. Empty  blobs
       are  everywhere  where  there’s  no  other  blob.  (However, the
       falling blobs steered by the  user  is  in  some  sense  "above"
       everything else; there are empty blobs beneath them.)

       The  life  of  empty  blobs  is different from the one of normal
       blobs. Empty blobs are not affected by gravity, and  they  often
       start or stop existing.  For example, when a single grey blob is
       falling down, the empty blob below it stops  existing  when  the
       grey  blob arrives and a new empty blob starts existing when the
       grey blob moves on.  There is only one situation in which  empty
       blobs  move:  When a row moves from one player to the other, and
       everything moves up resp. down, the empty blobs move, too.

WHERE DO I PUT THE CUAL CODE?

       Cual procedures  and  variables  can  be  defined  in  different
       sections of the .ld files:
       -  Outside  of  everything;  that  code is accessible from every
       level coming after that definition.
       - In the section of a level.
       - In the section of a kind.
       This basically does what you expect. However, there’s one  thing
       you  might  want to know: Even if you define a variable inside a
       kind, every blob in that level will have that variable. The only
       effect of defining the variable in the section of a kind is that
       this kind is the only one which can access it.

AMPERSAND-CALL

       To explain a bit what calling a procecure with an & means,  here
       two examples:

       Example 1:
       <<
       myblob = {
         ...
         switch {
           myvar -> { 0A*; 1; A,B,C,D; *; 2A*};
                 -> { 0B*; 1; A,B,C,D; *; 2B*};
         };
       };
       >>

       Example 2:
       <<
       anim = {1; A,B,C,D; *};
       myblob = {
         ...
         switch {
           myvar -> { 0A*; &anim; 2A*};
                 -> { 0B*; &anim; 2B*};
         };
       };
       >>

       The difference between these examples is what happens when myvar
       changes.  In example 1, the animation "A, B, C, D" will  restart
       at  the  beginning  (because  the  two  animations are different
       ones); in example 2, the "same" animation is used in both cases,
       so the animation will simply continue.  (Removing the ampersands
       from example 2 will turn the behaviour to the one of example 1.)

SEE ALSO

       cuyo(6)

BUGS

       Probably a lot. The following are just a few known ones:

       There are several problems with busieness and that stuff.  There
       are several situations in which Cual doesn’t behave in the way I
       would like, and in other situations I don’t know how Cual should
       behave.

       This man-page is still incomplete. And there’s no  man-page  for
       the part of the ld-files which is not Cual.

                                 Sep 10, 2002                          CUAL(6)