Welcome to the Creatures Wiki! Log in and join the community.

Kaos

From Creatures Wiki
Revision as of 15:43, 27 August 2005 by 217.155.181.162 (talk) (tsk)
Jump to navigation Jump to search

Kaos is a high level language designed by bdonlan to make writing agents easier. The Kaos compiler then translates this high level language into CAOS. Currently, it is still in an early stage of development, but is already capable of automatically compiling complex expressions involving the use of TARG and such attributes as BHVR.

Syntax

Kaos borrows its syntax primarily from the C family of languages.

The overall structure of a Kaos file is a series of install, remove, and/or agent blocks. Here is an example of all of them:

install {
    atomic {
        object it;
        it = newsimp(2, 21, 47494, "rubber ball", 1, 7, 5000);
        it.attr = 214;
        it.bhvr = 0;
        it.accg = 5;
        it.elas = 25;
        it.mvsf(6100,9200);
    }
}
agent (2, 21, 47494) {
    script 1 {
        ownr.vely = ownr.vely - 20;
    }
}
remove {
    enum thing (3, 21, 47494) {
        kill(thing);
    }
}

Additionally, if you only need a single install block, you can simply place its code in the top level:

print("Hello, world!\n");

Macros can also be defined for common expressions:

define foo(bar, baz) = bar + (baz * norn[bar]);

You can also use a block of code:

define poke(obj) = { obj.velx = obj.velx + 5; };

When the macro has no arguments, the parenthesis may be omitted:

define pi = 3.14;
install { 
  print("Two pies are ", pi * 2, "\n");
}

Macro definitions must be done in the toplevel of a script using install, agent, and/or remove blocks; something like this is (currently) forbidden:

define hello = "Hello world!";
print(hello);

Expressions

Kaos expressions may use the standard arithmetic operators *, /, +, -, with the normal precedence and associativity:

print("The Answer is: ", 40 + 2, "\n");

OVxx variables may be accessed with the [] operator:

norn[42] = pntr;

There are also a set of primitive functions for accessing CAOS opcodes such as RAND and the OUT* functions. They have a syntax like the following:

print("And the die roll is: ", rand(1, 6), "\n");

Some functions work on objects:

ownr.kill;

Objects also have a set of predefined attributes, such as:

norn.bhvr = 12345;
pntr[47] = norn.bhvr;

Kaos automatically takes care of TARG, so you can do things like:

norn.bhvr = pntr[47].attr + ownr.velx;

This compiles to:

  targ avar pntr 47
  setv va00 attr
   targ ownr
  addv va00 velx
  targ norn
  bhvr va00

Variables

Local variables are declared with a statement like one of the following:

number fortytwo = 42;
object maria = norn;
string yum = "pizza";

Once a variable has been declared, it can be accessed simply with its name. Assignment is done with the = operator:

number meaningoflife;
meaningoflife = 42;
print("The Answer is: ", meaningoflife, "\n");
meaningoflife = meaningoflife * 2;
print("Twice the answer equals ", meaningoflife, "\n");

Variables are lexically scoped to the curly-braces-delimited block they are declared in. It is possible to mask them, like so:

number foo;
foo = 42;
print ("foo = ", foo); # prints 42
{
  print(foo); # 42
  number foo;
  foo = 24;
  print(foo); # 24
}
print(foo); # 42

Global (GAME and EAME) variables may be accessed in two ways. They can be aliased to a named lexical variable:

# GAME variable
game number "engine_debug_keys" keys;
keys = 1;

# EAME variable
engine string "engine_clone_upon_import" clone;
clone = 1;

Or they may be accessed with a function:

game("engine_debug_keys") = 1;
engine("engine_clone_upon_import") = 1;

The former method should be preferred, as it tells the Kaos compiler what the type of the variable is, avoiding costly and complex runtime checks. However, if the name of the variable is computed at runtime, use of the function form is unavoidable.

Conditional statements

The Kaos if statement looks something like this:

if foo == bar {
  print("baz");
} else {
  print("quux");
}

The conditional statements can be built out of the operators ==, !=, <=, >=, <, and >. These all work on two expressions. In addition, if you simply put a bare expression where a conditional is expected, it will be interpreted as (expression) != 0.

In addition to comparing expressions, you can merge the results of the comparison with the && (and) and || (or) operators, as well as negating a conditional by prefixing a !. For internal reasons, while using parenthesis is allowed in a conditional, it is not recommended on the right side of an && or || as the resulting CAOS will be inefficient.

Note that unlike many other languages, Kaos conditional expressions do not short-circuit - all subexpressions will always be evaluated.

Looping constructs

Do...while and do...until loops are supported with the following syntax:

do {
  # code
} while condition

do {
  # code
} until condition

do {
  # code
} forever

Note that at this time there is no way to escape a do { ... } forever loop. It is primarily included for completeness.

In addition there is the enum loop, with the following syntax:

enum variable (family, genus, species) {
  # code
}

In this, variable is assigned the value of each agent with the specified classifier (0 being accepted as a wildcard for any field).

Compiler

The initial implementation of Kaos was as a perl compiler, but since then bd_ found Haskell, and now the currently actively developed implementation of Kaos is the Haskell implementation. Currently there is no public release; if you are interested in testing it please contact bd_.