Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
CUAL(6)				 Games Manual			       CUAL(6)

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  de-
       scription  works.   There's  also  a bit	of example Cual	code in	"exam-
       ple.ld".	 And of	course,	all the	existing levels	are examples.

       Note that Cual is probably still	very buggy.  So	if strange things hap-
       pen 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 sec-
       tion 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 sepa-
       rate 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 sec-
       tion.   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  (en-
       closed 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  rou-
       tine  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 "green-
       blob".)

       The name	of an event handler procedure is the name of  the  kind,  fol-
       lowed  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 in-
	      tro.

       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.

       explosionpic
	      Appearance of the	explosions (file name).	 Has a default.

   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  be-
	      haviour.	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 pre-
	      cisely, number of	pixels the lower border	of the picture is  be-
	      low 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 vis-
	      ible at the end.	Defaults to 0.

       chaingrass
	      Must  be	0 or 1.	 If set	to 1, chain reactions are necessary 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 Must be 0	or 1.  If set to 1,  the  level	 appears  upside-down.
	      Defaults to 0.

       randomfallpos
	      Must  be 0 or 1.	If set to 1, the initial fall position is ran-
	      domized horizontally.  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 de-
	      fault.  Each kind	can override this.  See	section	VARIABLES  AND
	      CONSTANTS	for values.  Defaults to neighbours_rect.

       hexflip
	      In  hex mode, determines whether the even	or the odd columns are
	      shifted upwards.	By default (hexflip = 0), the odd columns  are
	      shifted. 1 means:	shift even columns of player 1;	2 means: shift
	      even  columns  of	 player	2; 3 means: shift even columns of both
	      players.

       randomgreys
	      The expected 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_verti-
       cal, aiu_height
	      Parameters for the AI player's utility  function.	  Default  re-
	      spectively  to  <10*(number  of  kinds)>,	20, 10,	<aiu_color/2>,
	      <aiu_color>, and 10.  See	section	THE AI	UTILITY	 FUNCTION  for
	      details.

   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	infor-
	      mation,  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 de-
	      fined 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  be-
	      ing shorter to write, it also speeds up loading of the level and
	      cuts down	memory usage.  This is because cuyo does some initial-
	      izations 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 dif-
	      ferent.  (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 de-
	      scription	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 file=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	start-
	      dist provides the	possibility to specify it exactly.   See  sec-
	      tion STARTDIST for details.  The default is 1.

       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	START-
	      DIST 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	speci-
	      fied, zero is used.  See section VARIABLES AND  CONSTANTS	 about
	      the meaning of the default value and the optional	suffix : reap-
	      ply.

       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  sin-
	      gle  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.  How-
	      ever, 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  de-
	      fined.   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	AMPER-
	      SAND-CALL.)

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

       varname = expr
	      Sets the variable.  See section VARIABLES	AND CONSTANTS for  de-
	      tails.

       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 dif-
	      ferent 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 vari-
	      able qu (see section VARIABLES AND CONSTANTS).

       *@(position)
	      Like *, but draws	the icon at some other position.  This drawing
	      is performed after all drawing by	*.  If *@ is used from several
	      blobs,  the  further  order  of drawing is not specified.	 It is
	      guaranteed, however, that	at any given time this	order  is  the
	      same  for	 all  positions.  (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 *.  If	@* is used  from  sev-
	      eral  blobs,  the	further	order of drawing is not	specified.  It
	      is guaranteed, however, that at any given	time this order	is the
	      same for all positions.  (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 BUS-
	      IENESS.  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.  This is equivalent to setting it
	      to true.

       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.

       lose   The players immediately lose the level.

       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 posi-
       tive, then a/b is the largest integer n such that n*b<=a.  If b is neg-
       ative, 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 se-
	      quence 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,	start-
	      ing 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 de-
	  fault	value you provided.  If	you supplied the default with :	 reap-
	  ply,	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  spe-
	  cial 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 ac-
       cess 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 spec-
       ifies  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 co-
       ordinate	0, the other 1.

       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-in-
       tegers  appear.	 Especially,  ".5" is not allowed in composite expres-
       sions.  Therefore, also integer dy is always allowed.  If a  half-inte-
       ger 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 vari-
	  able	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.	State-
       ments  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  be-
	  ginning/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 val-
	      ues  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 cre-
	      ation.  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.)

       weight When  calculate_size is set in behaviour,	size will be regularly
	      updated to the sum of weight in the  connected  component.   The
	      default is 1.

       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 mean-
	      ingful  of  its  bits.   The   default   is   calculate_size+ex-
	      plodes_on_size   for   normal  blobs,  explodes_on_explosion+ex-
	      plodes_on_chainreaction for grey blobs,  floats  for  the	 empty
	      blob  and	 goalblob+explodes_on_explosion+explodes_on_chainreac-
	      tion 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 de-
	      fine 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
       time   The number of time steps since the level was started.

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

       basekind
	      The  value of the	constant generated for the name	of the kind of
	      the blop.	 Example:

		pics = orange, pear, apple * 3,	banana,	apple

	      Here, all	four kinds apple have the same value for basekind, and
	      this value is apple.

       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 al-
	      ways 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 or it is	a preview of a falling
	      blob.  (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.

       informational
	      True,  if	 the  blob is one of the info-blobs at the side	of the
	      game area.  In this sense, the previews  of  the	falling	 blobs
	      also count as info-blobs.

       players
	      The number of players.

       exploding
	      When the blob is exploding, the position in the explosion	anima-
	      tion (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 neighbour-
	      hood.   explodes_on_chainreaction	refers to those	triggering ex-
	      plosions that are	the second or later part of a chain  reaction.
	      explodes_on_explosion refers to the other	ones.

       floats When  this bit is	set, the blob keeps its	vertical position even
	      if there is an empty blob	below.	This bit has no	effect on  the
	      steered falling blobs.

       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 necessary	to perform arithmetic  on  kinds,  for
	      example  when several have been declared using the * multiplier.
	      The values of the	constants are  successive  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_horizontal
	      A	blob connects left and right.

       neighbours_vertical
	      A	blob connects up and down.

       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 side-
	      ways.  Forward is	one of up, down, left or right.	  Sideways  is
	      perpendicular  to	 forward.   This makes a total of eight	direc-
	      tions.).

       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 down-
	      wards 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  con-
	      necting in the given directions.	XX can be U, D,	L, R (horizon-
	      tal  and	vertical);  UL,	 UR, DL, DR (diagonal);	UUL, UUR, DDL,
	      DDR, LLU,	LLD, RRU, RRD (knight);	F, B (3d)

VERSIONING
       Sometimes it is necessary 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 example.

       This is done by qualifiing a definition with the	versions it should ap-
       ply 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
       predefined  specifiers  intended	for levels.  Additionally (and for in-
       ternal purposes), there are specifiers for the level tracks: main, all,
       game, extreme, nofx, weird, and contrib.

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

	 cuyo --version=hard,geek

       Specifies  both hard version (you can change that in the	menu) and ver-
       sion "geek", which is not predefined.

       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 as-
	  signing 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	defin-
	  ition	 for [2,hard] (or, equivalently, for [hard,2]),	because	other-
	  wise 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 unnecessary (and indeed prohibited) to give an [easy,hard]	defin-
	  ition, even if both [easy] and [hard]	are given.  The	same holds for
	  1 and	2, and for level tracks.

       -- Furthermore, cuyo knows that 1 and 2 are  exhaustive:	 There	is  no
	  mode which is	neither	single-player nor two-player.  (The human-ver-
	  sus-AI  mode	counts	as  two-player	as  far	as cual	is concerned.)
	  Therefore, if	there are definitions for  both,  it  is  unnecessary,
	  (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].  The level track specifiers are exhaustive as	well.

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 ap-
       pears 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 consist-
       ing of icons B, C, D and	E is started.  With a normal arrow ("->")  af-
       ter  the	 "1:100", after	the step in which B has	been drawn, the	proba-
       bility would be 99/100 that A is	drawn again.  But with the double  ar-
       row,  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 they are rotated.

       land   Is called	when the steered blob lands (just after	it landed).

       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_up Is  called  when	a  player got a	row from the other side, after
	      everything is finished and just after the	loc_y of all blobs has
	      been decreased by	1.  Is only called for	the  semiglobal	 blob,
	      though.

       row_down
	      Is  called  when	a player gives a row to	the other side,	before
	      anything visible happens,	but just after the loc_y of all	 blobs
	      has  been	 increased  by	1.   Is	only called for	the semiglobal
	      blob, though.

       keyleft,	keyright, keyturn, keyfall
	      Are called when the player presses the left, right, turn or fall
	      key.  Are	only called for	the  steered  falling  blobs  and  the
	      semiglobal  blob,	though.	 (Note that, in	contrast to turn, key-
	      turn is called even if the steered blob cannot be	rotated	due to
	      some obstacles, and also if there	is no steered blob.)

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.  More precisely, the steered blobs already come into  life  when
       they  appear  as	 the  preview.	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  gen-
       eral 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 ex-
       actly 10	or exactly 20 characters, except the last  which  is  special.
       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 dis-
	      tkey 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 ver-
	      sion=4, the character "a"	denotes	an orange with version=12, and
	      the character "8"	does not denote	anything (and hence  is	 ille-
	      gal).

       %      An  info	blop  with the version set according to	the level-wide
	      neighbours.

       &      An info blop with	the version set	according  to  the  level-wide
	      chaingrass.

       The  last line may have length 4, 8, 10,	or 20.	If it has length 10 or
       20, it is just a	normal line as above.  Otherwise it describes the  in-
       formational  blops  next	 to the	field.	In case	of length 4, the first
       entry describes the blop	which depicts the number of greys.  The	second
       entry describes the blop	which depicts the number of grass blops.   The
       third  entry  describes	the blop which depicts connection information.
       The fourth entry	describes the blop whoch depicts  chaingrass  informa-
       tion.   In  case	of length 8, the above holds for the left player.  The
       remaining 4 entries then	describe the same for the right	player,	but in
       reversed	order.	The default is "-*%&&%*-" (or equivalently "-*%&").

       As seen above, startdist	can reference 62 kind/version combinations di-
       rectly (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.	 Lead-
       ing 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  dif-
       ferent 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 com-
	  ing 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	defin-
       ing 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 ex-
       amples:

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

THE AI UTILITY FUNCTION
       When  deciding  how  to	place the steered falling blobs, the AI	player
       tries to	maximize a certain utility function.  Its value	is the sum  of
       the values for both steered falling blobs plus aiu_monochromic_vertical
       in  case	both blobs have	the same color and they	get placed vertically.
       The value for a single blob is the sum of the following:

       -- For each new neighbour of blob, the neighbour	utility.

       -- aiu_two_above, if the	blob is	two above a blob of same kind.

       -- aiu_height*20/(the blob's y coordinate).

       The neighbour utility for a single new blob and a single	one of its new
       neighbours is the sum of	the following:

       -- aiu_color, if	the neighbour has the same kind	as the blob.

       -- aiu_grass, if	the neighbour fulfills behaviour.goalblob.

       -- aiu_grey, if the neighbour fulfills behaviour.explodes_on_explosion.

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.

				  2014-10-25			       CUAL(6)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=cual&sektion=6&manpath=FreeBSD+Ports+15.0.quarterly>

home | help