Copyright (C) 1996-2001 Kim Rutherford, Michael Norrish
The Cheth Guide is copyright (C) 1996-2001 Kim Rutherford, Michael Norrish
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
Cheth is copyright (C) 1992--2001 Simon McAuliffe, Michael Norrish and Kim Rutherford.
It can be distributed only under the terms of the GNU Public License, a copy of which is provied with the cheth distribution.
Cheth was written by
S.McAuliffe@dtsp.co.nz>,
Michael.Norrish@cl.cam.ac.uk> and
kmr@sanger.ac.uk>
Most of the recent work has been done by Kim and Michael.
The following is an incomplete list of other people who have contributed code, ideas or who didn't laugh when told about Cheth. All are or were staff or students at Victoria University of Welligton.
robert@comp.vuw.ac.nz>
jules@clearview.co.nz>
Cheth is a game. It has direct ancestors in games such as Core Wars and C Robots but aims to present the game player with a much greater flexibility. Cheth has a number of features that, so far as we know, set it apart from other games (such as those mentioned above):
Cheth came about one day in 1992 (!) when Robert Biddle came into the third year lab at Victoria University of Wellington, and told Sai and Michael about a dream he had had which involved playing a game of chess, where the pieces on the board had programs of their own. The dream was actually quite a nightmare, because it was very hard to debug the pieces to do the right thing. We decided that we should implement a system to allow people to do exactly this.
We very quickly decided to change some facets of the original idea. In particular, we decided that the game shouldn't just be chess, but should be more of a war-game, and we also decided that Lisp shoudn't be the only programming language.
The first version of Cheth was based around a fairly simple world, with a specially designed form of Robot chip being emulated "underneath the hood". This was an elegant (but unrealistic) language known as puce-code.
Credit for Cheth's name must go to David Wallace. He suggested it as the obvious name for a game that was at that stage going to be all about playing chess with Lisp programs.
This is the result of running cheth with the --help option:
cheth [OPTION]... [LONG OPTION]... [ROBOT FILE]... These are the most useful options: -x use X to display the state of the game -d turn on low level debugging -D NUM set the debug level to NUM -r NUM set the random seed to NUM -f FILE configure cheth from FILE -h, --help show all options You must supply at least two robots The following long options are available: (options are shown with their default values) --armour_size_factor[=5] --attack_cost[=1] --attack_cycle[=2] --base_size[=100] --biomass_burn_factor[=2] --biomass_growth_time[=20000] --board_size[=32] --burn_biomass_cost[=0] --burn_biomass_cycle[=30] --burn_petro_cost[=0] --burn_petro_cycle[=30] --cell_biomass_damage[=100] --cell_biomass_fractalness[=900] --cell_biomass_max[=999] --cell_biomass_min[=0] --cell_dirt_damage[=10] --cell_dirt_fractalness[=500] --cell_dirt_max[=100] --cell_dirt_min[=0] --cell_fertility_damage[=20] --cell_fertility_fractalness[=900] --cell_fertility_max[=100] --cell_fertility_min[=0] --cell_impedance_damage[=0] --cell_impedance_fractalness[=900] --cell_impedance_max[=100] --cell_impedance_min[=0] --cell_iron_damage[=2] --cell_iron_fractalness[=900] --cell_iron_max[=9] --cell_iron_min[=0] --cell_petro_damage[=10] --cell_petro_fractalness[=2] --cell_petro_max[=0] --cell_petro_min[=0] --cell_raw_iron_fractalness[=800] --cell_raw_iron_max[=999] --cell_raw_iron_min[=33] --cell_raw_petro_fractalness[=800] --cell_raw_petro_max[=99] --cell_raw_petro_min[=33] --cell_raw_silicon_fractalness[=800] --cell_raw_silicon_max[=999] --cell_raw_silicon_min[=33] --cell_silicon_damage[=5] --cell_silicon_fractalness[=900] --cell_silicon_max[=9] --cell_silicon_min[=0] --cell_water_damage[=10] --cell_water_fractalness[=0] --cell_water_max[=0] --cell_water_min[=0] --create_robot_cost[=1] --create_robot_cycle[=50] --cycle_cost[=1] --damage_radius_ratio[=500] --detonate_cost[=1] --detonate_cycle[=1] --display_angle[=30] --display_size[=32] --drop_armour_cost[=1] --drop_armour_cycle[=5] --drop_biomass_cost[=1] --drop_biomass_cycle[=5] --drop_dirt_cost[=1] --drop_dirt_cycle[=5] --drop_iron_cost[=1] --drop_iron_cycle[=5] --drop_memory_cost[=1] --drop_memory_cycle[=5] --drop_petro_cost[=1] --drop_petro_cycle[=5] --drop_robot_cost[=1] --drop_robot_cycle[=5] --drop_silicon_cost[=-1000] --drop_silicon_cycle[=5] --drop_water_cost[=1] --drop_water_cycle[=5] --extract_iron_cost[=10] --extract_iron_cycle[=30] --extract_petro_cost[=10] --extract_petro_cycle[=30] --extract_silicon_cost[=-100] --extract_silicon_cycle[=30] --get_code_info_cost[=0] --get_code_info_cycle[=1] --give_armour_cost[=-10] --give_armour_cycle[=3] --give_biomass_cost[=-10] --give_biomass_cycle[=3] --give_capacity_cost[=-10] --give_capacity_cycle[=3] --give_dirt_cost[=-10] --give_dirt_cycle[=3] --give_energy_cost[=-10] --give_energy_cycle[=3] --give_iron_cost[=-10] --give_iron_cycle[=3] --give_memory_cost[=-10] --give_memory_cycle[=3] --give_petro_cost[=-10] --give_petro_cycle[=3] --give_silicon_cost[=-10] --give_silicon_cycle[=3] --give_water_cost[=-10] --give_water_cycle[=3] --initial_ability[=1] --look_cost[=1] --look_cycle[=3] --make_armour_cost[=10] --make_armour_cycle[=30] --make_capacity_cost[=10] --make_capacity_cycle[=30] --make_memory_cost[=10] --make_memory_cycle[=30] --max_drop_height[=20] --mem_move_team_cost[=20] --memmove_cost[=1] --memmove_cycle[=3] --message_size[=16] --move_cost[=1] --move_cycle[=1] --network_port[=2525] --oldest_age[=100000] --petro_burn_factor[=10] --piece_initial_armour[=100] --piece_initial_biomass[=0] --piece_initial_capacity[=100000] --piece_initial_dirt[=0] --piece_initial_energy[=10000] --piece_initial_iron[=0] --piece_initial_memory[=50000] --piece_initial_petro[=0] --piece_initial_silicon[=0] --piece_initial_water[=0] --radar_cost[=1] --radar_cycle[=9] --reboot_cost[=1] --reboot_cycle[=1] --scan_cost[=1] --scan_cycle[=3] --scanpassenger_cost[=1] --scanpassenger_cycle[=3] --shield_run_cost[=1] --take_armour_cost[=1] --take_armour_cycle[=10] --take_biomass_cost[=-100] --take_biomass_cycle[=10] --take_dirt_cost[=1] --take_dirt_cycle[=10] --take_iron_cost[=1] --take_iron_cycle[=10] --take_memory_cost[=1] --take_memory_cycle[=10] --take_petro_cost[=1] --take_petro_cycle[=10] --take_robot_cost[=1] --take_robot_cycle[=10] --take_silicon_cost[=-1000] --take_silicon_cycle[=10] --take_water_cost[=1] --take_water_cycle[=10] --teleport_cost[=1] --teleport_cycle_base_param[=1] --teleport_cycle_mult_param[=2] --timer_cost[=1] --transmit_cost[=1] --transmit_cycle[=3] --write_long_cost[=0] --write_long_cycle[=1] --write_slong_cost[=0] --write_slong_cycle[=1] --write_string_cost[=0] --write_string_cycle[=1]
System calls normally have two options a cost and a cycle. For example
timer() has --timer_cost which is the energy cost of starting
the timer and --timer_cycle which is the number of cycles it takes to
start the timer.
System calls that take resources as parameters (such as take) have two parameters for each possible resource so that costs of operating on different resources can be set individually.
Each of the robots file arguments can either be a netbsd-m68k executable or a directory of netbsd-m68k executables. You can use a directory to
Robots are deliberately left under-specified in terms of their physical appearance. This is a matter for graphical client implementors to decide. As far as the core of the game is concerned, robots are machines with a few simple characteristics. Most of the following characteristics are actually also resources (see section Resources).
make system
call and the iron resource.
SHIELD_RUN_COST multiplied by the shield level. A
shield at level n reduces all damage events it incurs by n
points.
To interact with the world around it, the code running inside a robot is able to make system calls. These can make robots perform actions visible in the world around them, such as moving or attacking, or give back the robot information about that world.
Robots written in C can use the wrapper functions in robot_syscalls.h to avoid the low-level code calling procedure documented below. Here is an example of a robot that uses the teleport system call to escape from danger:
#include "robot.h"
void proximity_alarm(void)
{
write_string("Eeek!");
teleport(get_hr_misc_random(), get_hr_misc_random());
}
int main(void)
{
set_hr_misc_prox_range(1);
set_hr_int_move(proximity_alarm);
set_hr_misc_random(4);
while(1);
}
In addition, the standard C library provided to all robots includes calls that wrap up some of the ways in which robots can get information about themselves through "hardware registers".
System calls are fairly tedious for a robot to set up, as the following discussion will illustrate, but the time spent doing so will still be fairly insignificant in comparison to the time spent executing the system call. After all, system calls involve interaction with the real world in one way or another, and this quite reasonably takes much longer than the operation of the simulated CPU.
All the communication necessary for system calls happens in a special
part of memory with addresses between 0x80000000 and
0x90000000. Both system call parameters and results are stored
in this region. Here, memory becomes "long-addressable" rather than
byte addressable. In other words, all of the addresses become addresses
for 32 bit values, rather than 8 bit values.
The address 0x80000000 is used to specify which system call the
robot wishes to initiate. A robot writes the number of the system call
to this address, and the system then reads the parameters for that call
from the appropriate locations in the rest of system call area of
memory. The system calls are numbered from zero up, as per the order
given in the file syscall-info.
The locations of the parameter slots for given calls and the numbers of the system calls are available to assembly programmers as #defines. For example these are the defines for the move system call:
#define SYSCALL_MOVE_NUM 0 #define SYSCALL_SYNC_MOVE_NUM 0x80000000 #define SYSCALL_MOVE_ARGS 0x80000001
The high bit of the system call number is reserved so that the robot can
indicate whether or not the call should be executed synchronously or
asynchronously. With the high-bit off, the call is made asynchronously.
In either case, when the call finishes, the return code from the system
call is available in the hardware register HR_SYSRET_NAME, where
NAME is the name of the call.
C programmers can make system calls by including the header file
robot_syscalls.h. Names for the synchronous versions of the
calls are as given below (see section System call listing), while names for
asynchronous calls are preceded by the string async_. Other
languages may use other conventions. In C, the return code hardware
register is automatically examined and returned as the result of the
call, so the programmer need not be concerned with this aspect of the
system.
If making a call asynchronously, there are two extra facets of system
calls that need to be understood. First, system calls are grouped into
various categories, and no more than one call can be in progress from
each category. An attempt to issue a call in a category where another
call is already running will fail. This failure is detectable by
reading the address 0x80000000 after the call is made. This
address will contain a one if the call was valid, and a zero if not.
Assuming a call is not already in progress in the category in question,
a call "event" is dispatched, which will eventually result in an
attempt to perform the call. When the call returns, the robot receives
an interrupt corresponding to the call. The symbolic name of this
interrupt is INT_SYS_NAME, where NAME is the name of the
system call. After this point, the hardware register containing the
call's return code will contain the appropriate value.
The directions are:
System calls can sometimes extend the six standard directions with various negative numbers to refer to other robots. There are listed here:
The following is an automatically generated list of all the system calls available to a robot:
move (const long direction)
Move one hex in the given direction.
Cost: MOVE_COST * impedance / ability.
Cycles: MOVE_CYCLE.
Implementation status: OK
teleport (const long x_rel, const long y_rel)
Teleport to the relative coordinate (x_rel,y_rel).
Cost: distance * TELEPORT_COST / ability.
Cycles: TELEPORT_CYCLE_BASE_PARAM + TELEPORT_CYCLE_MULT_PARAM *
distance.
Implementation status: OK
look (const long x_rel, const long y_rel, Address address)
Read into address the information about the cell relative distance
(x_rel,y_rel) away.
Cost: LOOK_COST * distance / ability.
Cycles: LOOK_CYCLE.
Implementation status: OK
scan (const long x_rel, const long y_rel, const unsigned long energy, Address address)
Read into *address the information about the piece in the cell
relative distance (x_rel,y_rel) away. The data placed at
*address is a struct PieceInfo. Use energy units
of energy. More energy makes the scan more accurate.
Cost: SCAN_COST * distance^2 / ability.
Cycles: SCAN_CYCLE
Implementation status: OK
scanpassenger (const unsigned long position, Address address)
Read into *address the information about the piece in position
position in the passenger list of this piece. The data placed at
*address is a struct PieceInfo.
Cost: SCAN_COST * distance^2 / ability.
Cycles: SCAN_CYCLE
Implementation status: OK
radar (const long start, const long finish, const long distance, Address address, const long count)
Scans around the piece for other pieces which are within
radius. Scan from direction start to direction
finish. The coordinates of pieces found are stored as
integer pairs in *address, with a maximum of count
pairs. If count is negative then a maximum of -count
will be returned, but robots on the same team will be ignored. The
number actually found is returned, or -1 on error. The number found
may be bigger than count, but no more than count pieces will
be recorded in the address given.
Cost: RADAR_COST * width * radius^2 / ability.
Implementation status: OK
attack (const long x, const long y, const unsigned long energy, const unsigned long radius)
Attack the hex at the relative coordinate (x_rel,y_rel). Use
energy units of energy in the attack. The attack is more precise and
powerful if radius, x or y is smaller or energy
is bigger.
Implementation status: OK
give (const long direction, const unsigned int item, const long quantity)
Transfer quantity of item from this robot to the robot
at the cheth direction direction (note the first passenger is
direction -2). The call will fail if there is no robot in
direction (returns NO_ROBOT). Specifying a negative quantity
will transfer all but that much of the specified resource. The
amount transferred is returned. It may be less than the amount
specified if there is not enough room in the destination robot or if
the giver has less of the resource than expected. (In these cases,
as much as possible is given.)
Implementation status: OK
drop (const long direction, const long item, const long quantity)
Drop quantity of item into the cell given by
direction. Drop into current cell if direction is =
THIS_CELL or -1. If quantity is negative drop all but
-quantity. Return code is amount actually dropped. This may
be less than the quantity parameter if there is less resource
in the robot than that much. (In this case, as much as possible is
dropped.)
For example drop (THIS_CELL, ITEM_DIRT, get_dirt ()); will
drop all the dirt the robot is carrying into the cell the robot is
currently in.
Implementation status: Presumed OK
take (const long direction, const long item, const long quantity)
Take quantity of item from the cell given by
direction. Take from the current cell if direction is
= -1. If quantity is negative take all but -quantity.
If item is ITEM_ROBOT then the quantity is
actually an index into the passenger list, with 0 being the first
passenger.
Returns the quantity of the item that was actually taken; this is relevant if the the quantity was negative or if the robot specifies more than it is possible to take, for whatever reason. The call causes the robot to take as much as possible, given the constraints of capacity and availability. The call may still fail due to lack of energy though.
Implementation status: OK
extract (const unsigned long item, const unsigned long maxquantity)
Try and extract up to maxquantity of item from the
robot's current heap of (carried) dirt. Returns the amount actually
extracted.
Implementation status: Presumed OK
make (const unsigned long item, const unsigned long quantity)
Processes resources, creating new derived ones. The item
parameter specifies the item that is to be constructed. Examples of
constructable resources include armour and memory. The construction
of 1 unit of item may require multiple units of multiple
other resources. If any resource is not present in sufficient
quantities, NO_RESOURCE is returned.
Implementation status: Presumed OK
burn (const unsigned long item, const long quantity)
Burns burnable resources, creating energy. If quantity is
negative, then burn all but -quantity many units of the
burnable resource. (If the item to be burnt is not burnable,
BAD_ARG is returned.) If the amount to be burnt is more than
the robot possesses, then all that the robot has is burnt.
The call returns the amount of energy created.
Implementation status: Presumed OK
transmit (const unsigned long signal_strength, Address msg)
Transmits the message given (the second argument, as a pointer) with
strength signal_strength. This latter affects both how far
the message will carry, and the strength with which it will be
received. The stronger the strength at receipt, the more chance
there is that this message will override others that might be
competing with it.
Implementation status: OK
memmove (const long from_whom, const Address srcadr, const long to_whom, const Address destadr, const long len)
Allows contents of robots memory to be shifted about, using the standard convention for direction to identify specific robots, and the addresses to specify which bits of memory to move. If an attempt to move memory causes an exception then the robot whose memory has been badly used will still blow up.
Implementation status: OK
create_robot (const Address pieceinfo)
Create a new robot and make it a passenger of this robot. The arg
pieceinfo is the address of a PieceStruct (defined in
robot_piece_struct.h). The structure defines the abilities of the
new robot, it's shell number and the name of the robot code to copy into the
new robot.
The most important field in the pieceinfo structure is name, which
must point to a NULL terminated char* or must be NULL. The
name should be the name of one of the robot object code (executables)
for this team. If there is no object code with the given name
create_robot will return BAD_ARG. If the name is NULL
then the first object code (alphabetically) will be used.
You need to call give to add resources to the new robot and then call
drop with a direction other than -1 or THIS_CELL.
The return code is a unique integer identifer for the robot.
Implementation status: OK
timer (const long time, const long userdata)
This system call does nothing but return the value userdata, and
takes time pings to do it.
Implementation status: Presumed OK
detonate ()
Self-destruct this robot and burn all the resources (uranium, biomass etc.) it is carrying.
Implementation status: OK
reboot (const Address robot_name)
Robot this robot using the robot code given by the argument. If the
argument is null the current code is reused. This call can only fail
if the robot_name is incorrect. In that case BAD_ARG is returned.
Implementation status: In progress
write_string (const Address stringaddr)
Print the string at stringaddr to the stdout stream of the cheth
process. This system call is provided to help with the debugging of
robots.
Implementation status: OK
write_long (const long number)
Print number to the stdout stream of the cheth process. This system
call is provided to help with the debugging of robots.
Implementation status: OK
write_slong (const Address stringaddr, const long number)
Prints the string at stringaddr followed by number.
This call is provided to help with the debugging of robots.
Implementation status: OK
This listing was generated automatically:
ATTACK
DAMAGE
ENERGY
hr_misc_energy_alarm.
ARMOUR
hr_misc_armour_alarm.
MOVE
BROADCAST
MSG_LOST
DROPPED
MEMORY_GAIN
Just as in the real world, the most important resource, and the one into some of the others will ultimately decay is energy. The other resources are more concrete: iron, silcon, dirt, etc.
take piles
of dirt, and then use the extract system calls to pull the things
they want out of the piles of dirt. A possibly incomplete list of
dirt-bound resources is:
make system call.
The following is an automatically generated list of all the resources in the game:
Energy gives power to a robot and its weapons. It is needed for
every system call. Robots can warn themselves if their energy drops
too low by setting an interrupt handler for the INT_ENERGY
interrupt. They must also set the hr_misc_energy_alarm
hardware register to specify the energy level below which they want
the interrupt to fire.
Armour protects a robot from damage by other robots, but the amount will decrease with each hit.
The carrying capacity of this robot. This resource has two
associated hardware registers: hr_misc_free_capacity and
hr_misc_robot_size. Note that the initial capacity of a
piece will be at least enough to hold all the inital resources of
the piece.
The amount of memory this piece has. The robot may be using less than this amount. If the robot causes its memory total to become less than the amount to memory that it booted with (by giving it away and/or dropping it), the robot reboots.
Fertility is not so much a resource as an attribute of cells in the
game world. Cell fertility is a measure of how fast bio-mass
regrows in that cell. Cell attributes such as fertility can be
discovered by robots using the look system call
(see section System call listing).
Impedance is another attribute of cells. It is a measure of how difficult moving into the cell will be because of features of the terrain.
Silicon is a dirt-bound resource, that must typically be
extract-ed from the ground. It is used to make memory.
Iron is a dirt-bound resource, that must typically be
extract-ed from the ground. It is used to make armour, and
to add capacity to a robot.
Bio-mass is a renewable resource that tends to cover pretty much all of the game world's cells, though to varying extents. It is a fairly low-intensity energy source that robots can readily harvest and burn.
Petrol is a dirt-bound energy source for robots that is burnt for energy.
The robot "resource" is an artifact of the implementation.
Currently water is disabled and never appears.
Dirt is the resource that makes up the ground beneath the robots'
"feet". It can be dug up (using the take system call), and
then useful minerals can be extracted from it.
Jump to: a - b - c - d - e - f - i - m - p - r - s - w
This document was generated on 15 July 2001 using texi2html 1.56k.