Man Linux: Main Page and Category List

NAME

       Cual - Cuyo Animation Language

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

       On the other hand this man page aims at being a complete description of
       how to write levels for cuyo. But 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

       The level description is organized  in  sections.  There  is  a  global
       section  and  every level has its own section, which is a subsection of
       the global section.  It is common practice to place  each  level  in  a
       separate  file,  which then basically starts by opening its section and
       ends by closing it.

       A section is defined by name = {contents}.  name is the name of the new
       section  and  contents  contains  the  definitions that pertain to that
       section. This is a sequence of definitions of the form  name  =  stuff.
       Here  stuff can be {contents} as above, or it can be a single datum, or
       it can be a comma-separated list of data. Inside such a list,  datum  *
       number can be used as a shorthand for datum, ..., datum, i.e. a number-
       fold repetition of datum. A  datum  can  be  an  identifier,  a  string
       (enclosed  by  ’"’),  a  word,  or  a  number.  In  place  of  a number
       <expression> can be used, where expression is an  arbitrary  expression
       made  up from literal numbers, previously defined numeric data, and the
       operators +, -, *, / and %.

       Definitions can also depend on versions. See section VERSIONING  below.

       Apart  from  definitions,  a  section can also contain cual definitions
       (see below). These have to be enclosed in << and >>.

       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 12.5 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.]

LEVEL DATA

   String valued data
       name   The name of the level.  This appears in the list  of  levels  as
              well as in the level intro.

       description
              This  is  an  optional  further  description of the level in its
              intro.

       author The name of the level author(s) for credit at the beginning of a
              level.

   Identifier valued data
       bgpic  Background  picture (file name). If too small, placed at bottom.
              Defaults to none.

       toppic Appearance of the top border coming down (file name).   Defaults
              to none.

   Number valued data
       numexplode
              The size that a group of blobs has to reach in order to explode.
              This is only the level-wide  default.  Each  kind  can  override
              this.   Whether  the  group  does  explode is also controlled by
              behaviour.  See section VARIABLES AND CONSTANTS for details.

       toptime
              Time the border takes to come down, in  number  of  game  steps.
              Each  game  step  lasts  80ms. The default value is 50 (i.e. one
              pixel every four seconds).

       topoverlap
              Placement  of  toppic  relative  to  the  actual  border.   More
              precisely,  number  of pixels the lower border of the picture is
              below the actual border.  Defaults to the height of the picture.

       topstop
              When  the  border  comes down at the end of the level, number of
              pixels it should stop before the bottom. Set this  to  the  same
              value  as  topoverlap  if  you  want your toppic to be comletely
              visible at the end.  Defaults to 0.

       chaingrass
              If set to 1, chain reactions are neccessary to kill  the  grass.
              Defaults  to  0.   More  precisely, chaingrass only controls the
              default for behaviour for grass blobs.   See  section  VARIABLES
              AND CONSTANTS for details.

       mirror If set to 1, the level appears upside-down.  Defaults to 0.

       neighbours
              Determines  in  which  directions  the blobs can connect to each
              other in order to form  groups.  This  is  only  the  level-wide
              default.  Each kind can override this. See section VARIABLES AND
              CONSTANTS for values.  Defaults to neighbours_rect.

       randomgreys
              The time between two randomly  appearing  greys  in  game  steps
              (80ms).  Use -1 for none at all, which is the default.

       nogreyprob
              The  probability  that a grey does not appear.  See greyprob and
              colourprob in section KIND DATA for details.  The default is  0.

       aiu_color,          aiu_grass,         aiu_grey,         aiu_two_above,
       aiu_monochromic_vertical, aiu_height
              Parameters   for   the   AI-Player  utility  function.   Default
              respectively to <10*(number of kinds)>, 20,  10,  <aiu_color/2>,
              <aiu_color>, and 10.

   Colour valued data
       (A colour is an RGB triple of numbers between 0 and 255)

       bgcolor
              The background colour. Defaults to white.

       textcolor
              Colour   of  any  text.  This  includes  the  beginning-of-level
              information, message()s, and score. Defaults to a certain  shade
              of dark grey.

       topcolor
              The  colour of the top border comming down (where not determined
              by toppic).  Defaults to a certain shade of light grey.

   Other data
       startdist
              Distribution of blobs at the beginning of the level.   It  is  a
              list of strings, the format of which is described in the section
              STARTDIST.

       pics, greypic, startpic, emptypic
              Lists of kinds. These can be either file names referring to  the
              picture  to  be  used,  or declarations of kinds that have to be
              defined later on.  The different keywords (e.g. pics,  emptypic)
              define different defaults.  In fact, only the first three may be
              real lists, emptypic is limited to exactly one entry.  In  these
              lists,  it  is  advisable  to  use * whenever possible.  Besides
              being shorter to write, it also speeds up loading of  the  level
              and  cuts  down  memory  usage.   This is because cuyo does some
              initializations only once for each entry with multiplier.

              The intentions of these lists are normal blob kinds  resp.  grey
              blob  kind  resp.   grass blob kind resp. nothing-blob. However,
              the only differences between pics, greypic and startpic are  the
              default  values  for  behaviour, colourprob, goalprob, greyprob,
              versions and distkey (see there).  All  of  these  can  also  be
              overridden  individually.   Also,  the  default  drawing code is
              different.  (The default drawing code for startpic does not draw
              connections.)

       kind   Each kind can have its own section.  See KIND DATA below for the
              entries of that section.

KIND DATA

       numexplode, neighbours
              Defining these data in the  section  of  a  kind  overrides  the
              level-wide  value  for  the  kind.  See section LEVEL DATA for a
              description of these data.

       pics   A list of file names of pictures to be used for this kind.   The
              nth entry can later be accessed in cual with pos=n-1.

       colourprob
              The probability that this kind appears as one of the two steered
              falling blobs.  More precisely, this is  a  nonnegative  integer
              weight.   For  determining  the actual probability, the value is
              divided by the sum of the colourprobs of all  kinds.   This  sum
              must  be  positive.   The  default  is 1 for kinds declared with
              pics= and 0 for all other kinds.  The probability is  also  used
              for + in startdist.  For more details see section STARTDIST.

       goalprob
              This affects the semantics of * in startdist in the same way, as
              colourprob does for +.  The default is 1 for kinds declared with
              startpic= and 0 for all other kinds.

       greyprob
              The  probability that this kind appears as a grey blob.  This is
              similar to colourprob, but there is a difference: For  greyprob,
              nogreyprob is included in the sum, so that it might happen, that
              no blob appears at all.  There is a notable difference between a
              positive  nogreyprob  and  a  positive greyprob in kind nothing,
              when several lines of grey blobs appear:  In  the  latter  case,
              empty  blobs  appear in the wall of greys, making holes.  In the
              former case, the  wall  is  made  less  high.  Usually  this  is
              preferable.   The  default is 1 for kinds declared with greypic=
              and 0 for all other kinds.  The value also affects the semantics
              of  - in startdist.  In this case, nogreyprob is not included in
              the sum.

       versions
              At the creation of a blob, its version variable is  initialized.
              Usually,  it  is  chosen  at  random  from  0 to versions-1, but
              startdist provides the possibility to specify it  exactly.   See
              section  STARTDIST  for  details.   The  default is 52 for kinds
              declared with startpic and 1 for all other kinds.

       distkey
              An alphanumerical key, which is used in  startdist  to  identify
              this  kind  of  blob.   The default is A for kinds declared with
              startpic  and  undefined  for  all  other  kinds.   See  section
              STARTDIST for details.

CUAL 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 [: reapply]], varname2 [= def2 [: reapply]], ... ;
              Defines  variables  with  default  values.   If  no  default  is
              specified,  zero  is  used.  See section VARIABLES AND CONSTANTS
              about the meaning of the default value and the optional suffix :
              reapply.

       default varname1 = def1 [: reapply], varname2 = def2 [: reapply], ... ;
              Changes  the  default for already defined variables.  Again, the
              suffix : reapply is optional.  This  is  useful  to  give  to  a
              single kind a different default for a variable than to the other
              kinds.  Also, the default of a system variable  can  be  changed
              this way.

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
              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 VARIABLES AND CONSTANTS).

       *@(position)
              Like *, but draws the icon at some other position.  This drawing
              is performed after all drawing by *.  (See section VARIABLES AND
              CONSTANTS for more details about @.)

       @(position)*
              Like *, but draws the icon at some other position.  This drawing
              is  performed  before  all drawing by *.  (See section 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".
              For  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.  The else-arrow may only  be  omitted,  if
              the  if-arrow is "->".  Then the else-arrow also is "->".
              (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.

       sound(Filename)
              Plays the given sound file.

       You can also omit the code completely.  Then, of course, it does
       not do anything.  This can be useful as part of ,-sequences.

       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
       (listed here in order of increasing precedence):

       ||                     Boolean or
       &&                     Boolean and
       ==, !=, <, >, <=, >=   Comparison
       ==..                   A special comparison
       !                      Boolean not
       +, -                   Add, substract
       :                      Special operator
       *, /, %                Multiply, divide, modulo
       &, |, .+, .-           Bitwise and, bitwise or, setting of bits (same as bitwise or), unsetting of bits
       -                      Unary minus
       .                      Testing of bits (a.b is the same as a&b != 0)

       / and % work  mathematically  correct  and  do  not  make  funny
       changes   when   the   sign  of  the  numerator  changes.   More
       specifically, if b is positive, then a/b is the largest  integer
       n  such  that n*b<=a.  If b is negative, then a/b is the largest
       integer n such that n*b>=a. In both  cases  a%b  is  such,  that
       (a/b)*b+a%b = a. Examples:

       13/5=2       13%5=3
       -13/5=-3     -13%5=2
       13/-5=-3     13/-5=-2
       -13/-5=2     -13%-5=-3

       The following are the special operators:

       expr1 == expr2 .. expr3
              Is  true, if expr1 lies between expr2 and expr3.  You may
              also omit one of expr2 and expr3.   (Then,  it  does  the
              same  as  <=  resp.  >=.)   The  precedence  implies that
              x==y==2..3 is the same as  x==(y==2..3)  and  is  neither
              (x==y)==2..3  nor  x==(y==2)..3.  Note that this operator
              might change in the future. (I  plan  to  make  something
              like "expr in set" in Pascal.)

       expr1 : expr2
              Is true (that is, 1) with probability expr1/expr2

       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  and  "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.

              For an empty blob the semantics is slightly different: If
              in  some  direction  there  is  no neighbour, because the
              field ends there, the entry in the neighbour sequence  is
              1  nevertheless.   So for an empty blob 1???0??? is true,
              iff the blob above this blob does not exist or  is  empty
              as  well,  and the blob below this blob exists and is not
              empty.

              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  VARIABLES
              AND CONSTANTS for details.)

       The following functions exist:

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

       gcd(expr1, expr2)
              Returns the greatest common divisor of expr1 and expr2

VARIABLES AND CONSTANTS

       The following kinds of variables and constants exist:

       —  User defined variables (see section CUAL DEFINITIONS). At the
          start of the level (or at the creation of the blob) the value
          is  the  default  value  you  provided.   If you supplied the
          default with : reapply, whenever a blob’s kind  changes,  the
          value  of  the variable is also set to the default of the new
          kind.  There is a subtlety: This  only  happens  if  the  new
          value of kind is in fact different from the old one.

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

       —  User  defined  constants.  These  are defined in the main .ld
          part, not in cual (not inside << >>).

       —  System 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@@(x, y; side)
         varname@@(x; side)
         varname@@(; side)
         varname@(dx, dy; side)
         varname@(dx; side)
         varname@()

       If x and y are given, these are absolute coordinates in the grid
       of blops, that is the variable  is  taken  from  the  blob  with
       loc_x=x and loc_y=y (see under The system variables).  If only x
       is given, it specifies one of the two blobs that  are  currently
       falling.  If there is only one such blob left, because the other
       one got stuck on some tower, the remaining blob’s coordinate  is
       0.  Otherwise one of the two has coordinate 0, the other 1.  The
       value x is interpreted modulo 2.

       In the @ variants, the coordinates are relative to  the  current
       blob.  The variant @@(; side) refers to the semiglobal blob, the
       variant @() to the global blob (See section  THE  GLOBAL  BLOB).
       The  extra part ; side is optional and specifies the side of the
       game. This is only meaningful in  two-player  mode.   side  =  <
       specifies  the  left player, side = > the right player, side = =
       the player to which the current blob pertains, and side = !  the
       other  player.  @() and @@() can also be given as @ respectively
       @@.

       This can be done for both, reading  and  writing  variables.  It
       also works for system variables (but not for constants).

       In  hex  mode levels, for odd dx, dy should be a "half integer",
       that is a number ending in ".5". This is the only place in  Cual
       where  non-integers  appear.  Especially, ".5" is not allowed in
       composite expressions.  Therefore, also  integer  dy  is  always
       allowed.  If a half-integer is expected and an integer is given,
       it is assumed to be rounded to above, that is 5 then  represents
       4.5 and -5 represents -5.5.

       Caution: With mirror=1 the absolute and the relative coordinates
       use different coordinate systems. Handle with extreme care.

       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 @ or @@ 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 @ or @@, 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 current 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 current 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.  If default
          values depend on the kind, the default pertaining to the blob
          executing the code is used.  This may change in the future.

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

       [Add explanation of time slices; roughly:
          @-access of variables in reality don’t access  the  value  at
          the  beginning/end  of  the game step, but of the time slice.
          The call of the main procedure of all blobs  happens  in  the
          same  time  slice,  but  each other kind of event has its own
          time slice.]

   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 three things:

              —  Expressions like "001???01" test the neighbour pattern
                 at the beginning of the current step. So the change of
                 the variable kind will not be reflected.

              —  In the current step, the program to draw the blob  has
                 already  been  invoked  (it  might even be 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.

              —  Defaults  of  the  new  kind  that are declared with :
                 reapply are applied.  This happens at  the  same  time
                 that  kind  changed,  but  only  if  the  new  kind is
                 different from the old one.

       version
              Is assigned a hopefully distinctive value at  the  blob’s
              creation.  See versions in section KIND DATA for details.

       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. These 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.

       behaviour
              This  is  a  bit field.  Refer to The Constants below for
              the   meaningful   of   its   bits.    The   default   is
              calculate_size+explodes_on_size    for    normal   blobs,
              explodes_on_explosion+explodes_on_chainreaction for  grey
              blobs,      0      for     the     empty     blob     and
              goalblob+explodes_on_explosion+explodes_on_chainreaction
              or   goalblob+explodes_on_chainreaction   (depending   on
              whether chaingrass is set) for grass blobs.

       falling_speed, falling_fast_speed
              These variables are only used in  the  semiglobal  blobs.
              They  define  the  vertical  speed of the steered falling
              blobs.  The unit is pixels per game step.   The  defaults
              are 6 and 32.

   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_xx, loc_yy
              The  absolute coordinates of the blob in pixels.  This is
              not  always  the   same   as   loc_x*32   and   loc_y*32,
              particularly for the steered falling blobs.

       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 to 8); 0 else.

              Currently,  there  is one exception: if the explosion has
              been triggered by the  explode  command,  then  exploding
              will  have value 1 only after the current game step [more
              precisely: time slice; fix that].  Reason:  when  reading
              exploding@(x,y),  we  maybe don’t know yet that the other
              blob calls explode.

   The Constants:
       Constants for behaviour:

       goalblob
              Set goalblob 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.

       calculate_size
              When this bit is set, size will be regularly  updated  to
              the sum of weight in the connected component.

       explodes_on_size
              When  this  bit  is  set, a connected component explodes,
              when it has size>=numexplode.

       explodes_on_explosion, explodes_on_chainreaction
              When these bits are set, the blob  explodes  whenever  an
              explosion,   that   was  triggered  by  explodes_on_size,
              happens in its neighbourhood.   explodes_on_chainreaction
              refers  to  those  triggering  explosions,  that  are the
              second   or   later   part   of   a    chain    reaction.
              explodes_on_explosion refers to the other ones.

       Constants for kind:

       <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
              kind = aKind.  See kind under The  system  variables  for
              the side-effects of setting kind.

              Sometimes  it  is  neccessary  to  perform  arithmetic on
              kinds, for example when several have been declared  using
              the  *  multiplier.   The  values  of  the  constants are
              succesive in the order, in  which  the  kinds  have  been
              declared.  When  a  name is used several times, the first
              use defines the value. Example:

                startpic = apple, orange
                pics = orange, pear, apple * 3, banana
                greypic = pineapple

              This initializes 2 kinds with the defaults for  startpic,
              6  kinds  with the defaults for pics, and 1 kind with the
              defaults for greypic.  The value of the  constant  orange
              is 1 more than that of apple, pear is 2 more than orange,
              banana is 4 more than pear and pineapple is 1  more  than
              banana.   We  do  not  specify what these values actually
              are.

              This constant also exists for the empty kind, if one  has
              been  declared  using  emptypic. In this case the value’s
              relation to the other values is not specified at all.

       global, semiglobal
              Denote the kind of the global,  respectively  semiglobal,
              blob.

       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.

       Constants for neighbours:

       neighbours_rect
              A blob connects up, down, left, and right.  This  is  the
              default.

       neighbours_diagonal
              A blob connects diagonally.

       neighbours_hex6
              When  used  in  the  level-wide neighbours, this sets hex
              mode.  A blob connects  up,  down,  left  with  a  slight
              upwards  shift, left with a slight downwards shift, right
              with a slight upwards shift,  and  right  with  a  slight
              downwards shift.

       neighbours_hex4
              When  used  in  the  level-wide neighbours, this sets hex
              mode.  A blob connects left with a slight upwards  shift,
              left  with  a slight downwards shift, right with a slight
              upwards shift, and right with a slight downwards shift.

       neighbours_knight
              A blob connects in knight moves (Two forward and then one
              sideways.   Forward  is  one  of up, down, left or right.
              Sideways is perpendicular to forward.  This makes a total
              of eight directions.).

       neighbours_eight
              Combines neighbours_rect with neighbours_diagonal.

       neighbours_3D
              A  more  obscure mode created especially for 3d.ld.  When
              used in the level-wide neighbours, this sets hex mode.  A
              blob  connects  up,  down, two (but not one) to the left,
              and two to the right.  In even columns it  also  connects
              right  with  a  slight  upwards shift.  In odd columns it
              also connects left with a slight downwards shift.

       neighbours_none
              A blob does not connect at all.

       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

       Miscellanious constants:

       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)

VERSIONING

       Sometimes  it  is  neccessary  to  define   a   level   slightly
       differently  for  different purposes. For example you might need
       to decrease  numexplode  for  the  two-player  version  lest  it
       becomes  unplayable.  The  difficulty  settings from cuyo’s main
       menu provide another exmaple.

       This is done by qualifiing a definition  with  the  versions  it
       should apply to.  It is best explained by an example:

         numexplode = 8
         numexplode[2] = 6
         numexplode[1,hard] = 10

       This  specifies,  that  normally numexplode should be 8. In two-
       player mode it should be 6. In one-player hard mode it should be
       10.  Here  the  specifiers "2" for two-player mode, "1" for one-
       player mode and "hard" for  hard  mode  are  used.   Along  with
       "easy" for easy mode these are all the specifiers that cuyo uses
       by itself.

       Additionally, you can make up and use your own  specifiers.   In
       order  for  them  to  take effect, though, you have to give cuyo
       additional information about the current version. This  is  done
       on the command line using the --version option. For example

         cuyo --version=hard,de

       Specifies  both  hard  version (you can change that in the menu)
       and version "de", which is not predefined (although many  levels
       use it to select German text).

       There are several constraints to be observed:

       —  All  versions  of  a definition must be made before the first
          use of the thing defined. As  sometimes  it  is  not  obvious
          where  the defined thing is used (for example startpic uses a
          previous greypic by assigning successive numbers  to  kinds),
          it is best to group all these versions into one block.

       —  A  given  version  also  applies  to  every  more specialized
          version, for which no  definition  is  given.  In  the  above
          example,  numexplode  is set to 6 in two-player hard mode and
          in two-player easy mode as well.

          All resulting conflicts must be resolved. For example, if you
          make  a  definition for [2] and one for [hard], you must also
          make  a  definition  for  [2,hard]  (or,  equivalently,   for
          [hard,2]),  because  otherwise it would be ambiguous which of
          the two former should apply in two-player hard mode.

       —  Cuyo  knows,  that  easy  and  hard   exclude   each   other.
          Consequently,  it  is unneccessary (and indeed prohibited) to
          give an [easy,hard]  definition,  even  if  both  [easy]  and
          [hard] are given.  The same holds for 1 and 2.

       —  Furthermore,  cuyo  knows, that 1 and 2 are exhaustive: There
          is no mode which is  neither  single-player  nor  two-player.
          (The human-versus-AI mode counts as two-player as far as cual
          is concerned.)  Therefore, if there are definitions for both,
          it  is  unneccessary,  (and  again  illegal) also to define a
          version without any of both.   For  example,  if  [1,de]  and
          [2,de]  are  given,  [de] must be omitted. Alternatively, you
          could of course give [1,de] and [de] or [de] and [de,2].

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  consisting  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 AND CONSTANTS on
       how  to  access  them.   Note  that  the  global  blob is always
       executed before any of the normal blobs.

       There are also semiglobal blobs. There is one for  each  player.
       These are programmed with semiglobal=code.

EVENT HANDLERS

       The following events exist:

       init   Is  called  only once, when the blob gets into life, 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.

       connect
              Is called when the connection of blobs is recalculated.

       row_up1, row_up2
              Is called when player 1 resp. 2 gets a row from the other
              side.

       row_down1, row_down2
              Is called when player 1 resp. 2 gives a row to the  other
              side.

       keyleft, keyright, keyturn, keyfall
              Is  called  when the player presses the left, right, turn
              or fall key.  Is only  called  for  the  steered  falling
              blobs and the semiglobal blob, though.

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  are  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.

STARTDIST

       The format of the startdist field is rather complicated.  On the
       plus  side,  this means that many things can be done with little
       effort.  We first describe the single-character  format,  which,
       at  the time of this writing, has sufficed for all needs.  After
       that, we describe the general format as an extension.

       Every line of the startdist describes one row of  blobs  in  the
       level’s  initial state.  The lines are aligned to the bottom and
       the topmost lines come first (normal reading order).  Each  line
       must  contain exactly 10 or exactly 20 characters.  In a line of
       length 20 the first 10 characters describe the left player,  the
       second 10 characters describe the right player. A line of length
       10 describes both players.  Hence, each character describes  one
       blob.  The semantics are:

       .      An empty blop.

       +, -, *
              A   blop   chosen  at  random  according  to  colourprob,
              respectively greyprob, respectively goalprob.  The  value
              of nogreyprob has no influence.

       0..9, A..Z, a..z
              These   characters   denote  a  specific  kind.   If  the
              character matches the distkey of some kinds, the first of
              these  is  chosen.   More generally, these characters are
              ordered such that "9" comes  before  "A"  and  "Z"  comes
              before  "a".   In  this order, the maximal distkey, which
              does not come after the character, specifies  the  blob’s
              kind.   The  difference  between  the  character  and the
              distkey then specifies the blob’s version.

              Example 1: In  the  special  case,  where  the  character
              exactly matches a distkey, version is set to 0.

              Example  2:  Suppose  kind  apple has distkey = "A", kind
              orange has distkey = "O" and no further  distkeys  exist.
              Then  the  character "C" denotes an apple with version=2,
              the character "N" denotes an apple with  version=13,  the
              character  "O"  denotes  an  orange  with  version=0, the
              character "S"  denotes  an  orange  with  version=4,  the
              character  "a" denotes an orange with version=12, and the
              character "8" does not  denote  anything  (and  hence  is
              illegal).

       In   this   way,   startdist   can   reference  62  kind/version
       combinations directly (and more at random).  Because this  might
       at  some  time  not  be enough, the multichar extension has been
       introduced.  In this case, each blob is described by  more  than
       one  character.  However, the number of characters per blob must
       be the same for all keys.  Hence, the lengths of startdist lines
       then  must  be  this  number  multiplied  by 10 or by 20.  Every
       multicharacter combination starting with ".", "+", "-",  or  "*"
       is  treated  as  the corresponding character in single-character
       format. All other character combinations are treated as  numbers
       in  base  62  representation.  Here,  "A" to "Z" are digits with
       decimal value 10 to 35, and "a" to "z" are digits  with  decimal
       value  36  to  61.  Leading spaces are allowed instead of zeroes
       (however, the  all-space  string  is  forbidden).   The  maximal
       distkey  which (as a number) is not larger than the number given
       in startdist, specifies the blob’s kind.  The difference between
       the  startdist  number and the distkey then specifies the blob’s
       version.  In the case of multichar  distkeys,  the  default  for
       distkeys of kinds declared by startpic= is 10 in decimal.

       For blops whose kinds are chosen at random (i.e. characters "+",
       "-", "*" in single-character startdists),  cuyo  tries  to  make
       these  as  different  as  possible.   That  means,  by a certain
       heuristic, cuyo minimizes the number of  neighbouring  blobs  of
       the   same  kind.  "Neighbouring",  of  course,  refers  to  the
       neighbours  entry.  inhibit  and  the  calculate_size   bit   of
       behaviour  have no effect (these are mutable during the lifetime
       of blobs, while at the time of startdist processing,  no  blob’s
       lifetime  has  started  yet).  So  the only way to influence the
       unneighbouring (if you really wish to  do  so),  is  by  setting
       neighbours  appropriately.  (Of course, this possibility is even
       more limited, when you intend  to  set  the  calculate_size  bit
       during the blob’s lifetime.)

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.

                                   2008-2-13