Kaos
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.
For the Haskell source code (currently still under significant development), visit the project page on Google Code.
For an easy testing and using of kaos visit lifandi.ccdevnet.org/index.php/KAOS-IDE (down), a Kaos editor (an geany modification).
KAOS_HOWTO with examples.
An DEMO how to use kaos, with metaroom,monitor,plant,weather... (down, demo formerly at lifandi.ccdevnet.org/index.php/DEMO1)
Contents
Syntax
![]() More information may be available in the talk page. |
Kaos borrows its syntax primarily from the C family of languages.
Comments are the same as c,c++ one line to end // multiline /* ..... */
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 { agent it = newsimple (2, 21, 47494, "rubber ball", 1, 7, 5000); it.attributes = 214; it.behaviour = 0; it.acceleration = 5; it.elasticity = 25; it.move(6100,9200); } script (2, 21, 47494,1) {agent a=owner;numeric y; y=a.YVelocity-20 ; a.velocity(y,0); } remove { enum (3, 21, 47494) {|p| p.kill();} } -------------------------------------------- This is the output file test.k.cos: new: simp 2 21 47494 "rubber ball" 1 7 5000 attr 214 bhvr 0 accg 5 elas 25 mvto 6100 9200 scrp 2 21 47494 1 targ ownr setv VA00 vely subv VA00 20 velo VA00 0 endm rscr enum 3 21 47494 kill targ next
Additionally, if you only need a single install block, you can simply place its code in the top level:
print("Hello, world!\n");
Macros
At the top level, you may define macros like so:
macro rvalue(numeric arg1, agent arg2, string arg3 = "default value") returning numeric { ... } macro set lvalue(...) { ... } macro iterator loopconstruct(...) { ... }
The returning keyword sets the return type, and is valid only on rvalue macros. Macros using this can set their return value by writing to the return variable like so:
define plusone(numeric v) returning numeric { _return = v + 1; }
lvalue macros are passed their new value as their first argument, eg:
define set printme(numeric v) { print(v); } install { printme() = 42; }
Iterator macros are called with a block of code, and may invoke it by calling the yield function, optionally passing it values:
define iterator(numeric) loop(numeric times) { numeric index = 0; do { index = index + 1; _yield(index); } until(index >= times) } install { loop(10) { |i| print ("Loop number "); print(i); print("\n"); } }
Macros cannot recurse, nor can they call macros which have not been defined before them. You can also use a block of code:
define poke(agent obj) { obj.XVelocity = obj.XVelocity + 5; };
When the macro has no arguments, the parenthesis may be omitted:
define numeric 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 string 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:
First at the top
ovar numeric age_of_agent[1];
then in scripts
agent a; a.age_of_agent=a.age_of_agent+1;
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: ", getRandom(1, 6), "\n");
Some functions work on objects:
ownr.kill;
Kaos automatically takes care of TARG, so you can do things like:
agent a; a.behaviour = pointer.attributes + owner.XVelocity;;
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:
numeric foo; foo = 42; print ("foo = ", foo); // prints 42 { print(foo); // 42 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 for (x = 42; x > 24; x = x - 1) { # ... }
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_.