The newest version of the Xpilot-AI bindings for Chicken Scheme has marked differences from the previous version. Code using the old API will have to be changed to fit the new version. This API change was done to make Xpilot-AI more comfortable to work with in a scheme environment.

1. General Functions

These functions allow general control of the Xpilot client application.

function (xpilot . args) → #<void>

Launches the xpilot client with the specified command line arguments. Takes any number and type of arguments and concatenates the result to form a single argument string. Arguments are separated by a space.

; Parses the command line arguments to join the desired server
(xpilot "-join" (car   (command-line-arguments))
        "-port" (cadr  (command-line-arguments))
        "-name" (caddr (command-line-arguments)))
function (xpilot-bg . args) → #<thread>

Analogous to xpilot, with the exception that the xpilot-process in launched in a background thread, allowing the user to enter commands at the repl.

#;1> (xpilot-bg "-join localhost -name Bill")
#<thread>
#;2> (x-pos)
82

See also: xpilot

function (AI_main) → #<void>

Xpilot-AI will call the function AI-main exactly once for every frame of gameplay. Bots are generally written by redefining this function to perform actions based on current conditions.

function (press-key key) → #<void>

Simulates a key press. release-key must be called to complete the key stroke.

;  A ship that tries to fire a laser every
;  frame (if lasers are enabled by server

(define (AI-main)
  (press-key KEY_FIRE_LASER))

Here is a complete list of all the possible keys to press.

  • KEY_DUMMY

  • KEY_LOCK_NEXT

  • KEY_LOCK_PREV

  • KEY_LOCK_CLOSE

  • KEY_CHANGE_HOME

  • KEY_SHIELD

  • KEY_FIRE_SHOT

  • KEY_FIRE_MISSILE

  • KEY_FIRE_TORPEDO

  • KEY_TOGGLE_NUCLEAR

  • KEY_FIRE_HEAT

  • KEY_DROP_MINE

  • KEY_DETACH_MINE

  • KEY_TURN_LEFT

  • KEY_TURN_RIGHT

  • KEY_SELF_DESTRUCT

  • KEY_LOSE_ITEM

  • KEY_PAUSE

  • KEY_TANK_DETACH

  • KEY_TANK_NEXT

  • KEY_TANK_PREV

  • KEY_TOGGLE_VELOCITY

  • KEY_TOGGLE_CLUSTER

  • KEY_SWAP_SETTINGS

  • KEY_REFUEL

  • KEY_CONNECTOR

  • KEY_INCREASE_POWER

  • KEY_DECREASE_POWER

  • KEY_INCREASE_TURNSPEED

  • KEY_DECREASE_TURNSPEED

  • KEY_THRUST

  • KEY_CLOAK

  • KEY_ECM

  • KEY_DROP_BALL

  • KEY_TRANSPORTER

  • KEY_TALK

  • KEY_FIRE_LASER

  • KEY_LOCK_NEXT_CLOSE

  • KEY_TOGGLE_COMPASS

  • KEY_TOGGLE_MINI

  • KEY_TOGGLE_SPREAD

  • KEY_TOGGLE_POWER

  • KEY_TOGGLE_AUTOPILOT

  • KEY_TOGGLE_LASER

  • KEY_EMERGENCY_THRUST

  • KEY_TRACTOR_BEAM

  • KEY_PRESSOR_BEAM

  • KEY_CLEAR_MODIFIERS

  • KEY_LOAD_MODIFIERS_1

  • KEY_LOAD_MODIFIERS_2

  • KEY_LOAD_MODIFIERS_3

  • KEY_LOAD_MODIFIERS_4

  • KEY_SELECT_ITEM

  • KEY_PHASING

  • KEY_REPAIR

  • KEY_TOGGLE_IMPLOSION

  • KEY_REPROGRAM

  • KEY_LOAD_LOCK_1

  • KEY_LOAD_LOCK_2

  • KEY_LOAD_LOCK_3

  • KEY_LOAD_LOCK_4

  • KEY_EMERGENCY_SHIELD

  • KEY_HYPERJUMP

  • KEY_DETONATE_MINES

  • KEY_DEFLECTOR

  • KEY_UNUSED_65

  • KEY_UNUSED_66

  • KEY_UNUSED_67

  • KEY_UNUSED_68

  • KEY_UNUSED_69

  • KEY_UNUSED_70

  • KEY_UNUSED_71

  • NUM_KEYS

  • KEY_MSG_1

  • KEY_MSG_2

  • KEY_MSG_3

  • KEY_MSG_4

  • KEY_MSG_5

  • KEY_MSG_6

  • KEY_MSG_7

  • KEY_MSG_8

  • KEY_MSG_9

  • KEY_MSG_10

  • KEY_MSG_11

  • KEY_MSG_12

  • KEY_MSG_13

  • KEY_MSG_14

  • KEY_MSG_15

  • KEY_MSG_16

  • KEY_MSG_17

  • KEY_MSG_18

  • KEY_MSG_19

  • KEY_MSG_20

  • KEY_ID_MODE

  • KEY_TOGGLE_OWNED_ITEMS

  • KEY_TOGGLE_MESSAGES

  • KEY_POINTER_CONTROL

  • KEY_TOGGLE_RECORD

  • KEY_PRINT_MSGS_STDOUT

  • KEY_TALK_CURSOR_LEFT

  • KEY_TALK_CURSOR_RIGHT

  • KEY_TALK_CURSOR_UP

  • KEY_TALK_CURSOR_DOWN

  • KEY_SWAP_SCALEFACTOR

See also: release-key

function (release-key key) → #<void>

Simulates a key release. Call to release a key pressed by press-key. See [press-key] for a complete list of keys.

See also: press-key

parameter max-turndegrees

SRFI-39 parameter object. Sets the maximum turn for self in degrees per frame.

;; Set the maximum turning speed to 26 degrees per frame
#;1> (max-turn 26)
;; Get the current value of max-turn
#;2> (max-turn)
26

2. Self Control

Functions to control the ship and perform various actions.

function (thrust #!optional bool) → #<void>

Controls the ship’s thrust. When bool has a value of #f, the thrust is inhibited. If bool is true, or the function is called with no arguments, the ship thrusts.

;; a ship that thrusts every frame
(define (AI-main)
  (thrust))
;; Or, more tersely,
(define AI-main thrust)

See Also: turn, shoot, shield

function (turn deg) → #<void>

Turns the ship deg degrees (out of 360). Negative degrees are clockwise, positive degrees are counter-clockwise. The ship will turn no more than the value of (max-turn) and no less than 0 - (max-turn).

; a ship that turns 15 degrees clockwise every frame

(define (AI-main)
  (turn -15))
function (shoot #!optional bool) → #<void>

Fires the ship’s main gun. If bool is #f, firing is inhibited. Otherwise, if bool is true, or is not supplied, the guns are fired.

Note: Servers limit the shot rate and the number of shots, so the ship may not always fire. Use reload to check the number of frames remaining before it is possible to shoot again.

;; a ship that waits until reload before firing
(define (AI-main)
  (shoot (zero? (reload))))
function (shield #!optional bool) → #<void>

Turns the ship’s shield on or off. Use shield? to see the status of the shield.

See also: shield?, turn, thrust, shoot

function (self-destruct #!optional bool) → #<void>

Start the self-destruct sequence. When bool is #f self-destruct is inhibited. Otherwise, if bool is #t or is not supplied, the self-destruct sequence begins.

3. Game state access

Functions that retrieve the values of variables concerning all ships. In general, these functions take any number of arguments. If no arguments are supplied, they return the value corresponding to self’s ship. If n index values are supplied, n values are returned, each corresponding to the respective value of the ship at each index. Note that some values do not apply to both self’s ship and other ships: the argument lists change accordingly.

Other ships are indexed by their position on the screen. The closest ship will always be denoted by index 0, the second closest will be denoted by index 1, and so on.

3.1 Functions for accessing self or ship state

function (id . ships) → id1 id2

Retreive the unique id of a ship, according to the server. This id will not change even if a ship changes its nickname. If no arguments are supplied, self’s id is returned. For each index given as an argument, id will return the server identification number of the ship at the index, or #f if the ship is not on screen.

;; Get self's id
#;1> (id)
3
;; Get closest ship's id
#;2> (id 0)
7
function (alive?) → #t or #f

Returns #t if self is alive. Otherwise returns #f.

function (x-pos . ships) → x1 x2 …

Ships' x positions, where bottom left of map is (0, 0). If no arguments are supplied, self’s x position is returned. If the ship is not on screen, the return value is #f.

See also: radar-x, shot-x

function (y-pos . ships) → y1 y2 …

Ships' y positions, where bottom left of map is (0, 0). If no arguments are supplied, self’s y position is returned. If the ship is not on screen, the return value is #f.

See also: radar-y, shot-y

function (pos . ships) → p1 p2 …

For each ship, return a list whose first element is the x-position of the ship, and whose second element is the y-position of the ship. If the ship is not on screen, return #f. If no arguments are given, self’s position is returned.

function (vel . ships) → v1 v2 …

Ships' velocity in number of pixels moved per frame, or #f if ship is not on screen. If no arguments are supplied, self’s velocity is returned.

See also: track, shot-vel

function (heading . ships) → h1 h2 …

Ships' heading (the direction a ship’s nose is pointing), or #f if ship is not on screen. 0 degrees is to the right and 90 degrees is straight up. If no arguments are supplied, self’s heading is returned.

function (track . ships) → t1 t2 …

Ships' track (direction of movement), or #f if ship is not on screen. 0 is to the right and 90 is straight up. If no arguments are supplied, self’s track is returned.

function (team . ships) → t1 t2 …

Number of ships' team on server, or #f if ship is not on screen. If no arguments are supplied, self’s team number is returned.

;; Check if a ship is friendly
(define (friendly? ship)
  (= (team) (team ship)))

;; Check if a ship is hostile
(define hostile?
  (complement friendly?))

See also: teamplay?

function (life . ships) → l1 l2 …

Ships' remaining lives on server, or #f if ship is not on screen. If no arguments are supplied, self’s remaining lives is returned.

function (shield? . ships) → s1 s2 …

Status of ships' shields. #t if shield is on, #f if shield is off or ship is not on screen. The existance of a ship should be checked first with the function on-screen?.

function (name . ships) → n1 n2 …

Ships' names, or #f if ship is not on screen. If no arguments are supplied, self’s name is returned.

3.2 Functions for accessing self state only

function (score) → score …

Return self’s score as shown on the ranking list.

3.3 Functions for accessing other ships' state

function (on-screen? ship1 . ships) → bool1 bool2 …

Returns #t if ship is on-screen, #f otherwise.

See also: on-radar?

function (accel ship1 . ships) → a1 a2 …

Return ships' accelerations, or #f if ship is not on screen.

See also: vel

function (xdir ship1 . ships) → d1 d2 …

Angle from ship to self.

;; Self always points at nearest on screen ship
(define (AI-main)
  (when (on-screen? 0)
        (turn (anglediff (heading)
                         (xdir 0)))))

(use srfi-1)
;; Get a list of ships that satisfy a predicate
(define (ships pred)
  (filter pred (unfold on-screen?
                       identity add1 0)))

;; Get a list of friendly on-screen ships
(ships friendly?)
;; Get a list of enemy on-screen ships
(ships hostile?)

See also: heading, xdir

function (ship-dist ship1 . ships) → d1 d2 …

Returns distance from self to ship, or #f if ship is not on screen.

See also: xdir

function (aimdir ship1 . ships) → d1 d2 … Calculates the direction self would need to point to hit the ship, according to track and velocity of self and target. Returns #f if ship is not on screen.

;; bot that aims and shoots at nearest ship

(define (AI-main)
  (when (on-screen? 0)
        (turn (anglediff (heading) (aimdir 0)))
        (shoot)))

See also: xdir, heading, anglediff

4. Radar

Functions returning information about other ships on the radar. The ships are sorted from nearest to furthest.

function (radar-x ship1 . ships) → x1 x2 …

Return ships' approximate x positions on radar, or #f if ship is not on radar. Ships are sorted from nearest to farthest.

See also: x-pos

function (radar-y ship1 . ships) → y1 y2 …

Return ships' approximate y positions on radar, or #f if ship is not on radar.

See also: y-pos

function (radar-dist ship1 . ships) → d1 d2 …

Radar ships' distance from self, in pixels (approximate), or #f if ship is not on radar.

function (on-radar? ship1 . ships) → b1 b2 …

Returns #t if ship is on radar, #f otherwise.

function (radar-xdir ship1 . ships) → d1 d2 …

Direction of radar ship from self.

;; self always points at second-nearest radar ship
(define (AI-main)
  (when (on-radar? 1)
        (turn (anglediff (heading)
              (radar-xdir 1)))))

5. Shots

Functions returning information about the shots on the screen.

function (shot-x shot1 . shots) → x1 x2 …

Shots' x positions, or #f if shot is not on screen.

See also: pos-x, shot-y

function (shot-y shot1 . shots) → y1 y2 …

Shots' y positions, or #f if shot is not on screen.

See also: pos-x, shot-x

function (shot-track shot1 . shots) → t1 t2 …

Shots' direction of velocity, or #f if shot is not on screen.

See also: shot-vel, anglediff

function (shot-vel shot1 . shots) → v1 v2 …

Shots' velocity in pixels/frame, or #f if shot is not on screen.

See also: shot-track

function (shot-dist shot1 . shots) → d1 d2 …

Shots' distances from self, or #f if shot is not on screen.

function (shot-imaginary ship1 . ships) → i1 i2 …

Imaginary shots are calculated for every ship on screen. If a ship were to shoot this frame, imaginary bullets tell that shot’s attributes. Returns #f if ship is not on screen.

function (shot-xdir shot1 . shots) → d1 d2 …

Direction of shot from self, or #f if shot is not on the screen.

See also: shot-idir

function (shot-idir shot1 . shots) → d1 d2 …

Direction of location where the shot will be nearest to self, if both self velocity and bullet velocity remain constant. Returns #f if shot is not on screen.

;; self turns away from intercept dir and thrusts

(define (AI-main)
  (when (shot-x 0)
        (turn (anglediff (heading)
                         (angleadd (idir 0) 180)))
        (thrust)))
function (shot-idist shot1 . shots) → d1 d2 …

Number of frames until the nearest intercept will occur, if both self velocity and bullet velocity remain constant. Returns #f if shot is not on screen.

function (shot-alert shot1 . shots) → a1 a2 …

A value derived from idist and itime . An alert between 0 and 30 means that self will probably be killed by the shot, 30 to 120, that it is a dangerous shot and should be avoided, and above 120, it’s not very dangerous. This variable is just for convience, and should probably not be used in more advanced controllers.

6. Walls and Map

Functions to check for walls and to look at map tiles

function (wall-between x1 y1 #!optional x2 y2) → bool, x, y

This function checks for walls in a straight line starting from point (x1, y1) and ending at point (x2, y2). If it finds a wall, it returns the distance in pixels from (x1, y1) to that point, and the x and y position of the point as secondary values. Otherwise, it returns #f. If x2 and y2 are not supplied, then wall-between looks for a wall between self’s position and x1, y1.

;; this checks for a wall 200 pixels
;; in front of the ships track

(define (wall-ahead)
  (wall-between
   (+ (x-pos)
      (* 200 (cos (deg->rad (track)))))
   (+ (y-pos)
      (* 200 (sin (deg->rad (track)))))))

;; Display position of wall ahead of track
(use srfi-11) ; for let-values

(let-values ((wall x y) (wall-ahead))
  (when wall
        (printf "Wall ~A px ahead at (~A,~A)"
                 x y)))
function (tile #!optional x y) → unsigned int

The map consists of tiles which are 35x35 pixels each. Each tile contains information about that spot on the map, and can have multiple values. For instance, a square block tile may have 5 bit flags set; one for each side, and one to indicate it is a wall tile. The possible flags are listed below. Use the bitwise "and" operator to check the tiles for the flags. This function returns the value stored in the tile containing the point (x, y). If x and y are not supplied, self’s position is used.

;; checks to see if the map tile to the right of the player
;; contains a wall of some sort
(when (positive?
       (bitwise-and (tile (+ (pos-x) 20) (pos-y))
                    BLUE_BIT))
      (print "To the right is a wall tile!"))

Here is a list of tile types.

SETUP_SPACE             0
SETUP_FILLED            1
SETUP_FILLED_NO_DRAW    2
SETUP_FUEL              3
SETUP_REC_RU            4
SETUP_REC_RD            5
SETUP_REC_LU            6
SETUP_REC_LD            7
SETUP_ACWISE_GRAV       8
SETUP_CWISE_GRAV        9
SETUP_POS_GRAV          10
SETUP_NEG_GRAV          11
SETUP_WORM_NORMAL       12
SETUP_WORM_IN           13
SETUP_WORM_OUT          14
SETUP_CANNON_UP         15
SETUP_CANNON_RIGHT      16
SETUP_CANNON_DOWN       17
SETUP_CANNON_LEFT       18
SETUP_SPACE_DOT         19
SETUP_TREASURE          20      ;  + team number (10)
SETUP_BASE_LOWEST       30      ;  lowest base number
SETUP_BASE_UP           30      ;  + team number (10)
SETUP_BASE_RIGHT        40      ;  + team number (10)
SETUP_BASE_DOWN         50      ;  + team number (10)
SETUP_BASE_LEFT         60      ;  + team number (10)
SETUP_BASE_HIGHEST      69      ;  highest base number
SETUP_TARGET            70      ;  + team number (10)
SETUP_CHECK             80      ;  + check point number (26)
SETUP_ITEM_CONCENTRATOR 110
SETUP_DECOR_FILLED      111
SETUP_DECOR_RU          112
SETUP_DECOR_RD          113
SETUP_DECOR_LU          114
SETUP_DECOR_LD          115
SETUP_DECOR_DOT_FILLED  116
SETUP_DECOR_DOT_RU      117
SETUP_DECOR_DOT_RD      118
SETUP_DECOR_DOT_LU      119
SETUP_DECOR_DOT_LD      120
SETUP_UP_GRAV           121
SETUP_DOWN_GRAV         122
SETUP_RIGHT_GRAV        123
SETUP_LEFT_GRAV         124
SETUP_ASTEROID_CONCENTRATOR     125

BLUE_UP                 0x01
BLUE_RIGHT              0x02
BLUE_DOWN               0x04
BLUE_LEFT               0x08
BLUE_OPEN               0x10    ;  diagonal botleft -> rightup
BLUE_CLOSED             0x20    ;  diagonal topleft -> rightdown
BLUE_FUEL               0x30    ;  when filled block is fuelstation
BLUE_BELOW              0x40    ;  when triangle is below diagonal
BLUE_BIT                0x80    ;  set when drawn with blue lines

DECOR_LEFT              0x01
DECOR_RIGHT             0x02
DECOR_DOWN              0x04
DECOR_UP                0x08
DECOR_OPEN              0x10
DECOR_CLOSED    0x20
DECOR_BELOW             0x40

See also: tile-set!

function (tile-set! x y val) → #<void>
function (tile-set! val) → #<void>

The map tiles in Xpilot-AI are 32 bits. Only the lowest order bits are used for Xpilot, so the other bits can be set as desired. If an x and y argument are not supplied, the tile containing self’s position is used. Otherwise, the tile containing (x, y) is used.

;; Sets a bit flag on the map tile underneath self

(tile-set! (bitwise-ior (tile) 0x1000))

7. Messages

Write and recieve messages using the player-to-player messaging system in Xpilot

function (talk . messages) → #<void> Say a message through the player-to-player talk system in Xpilot. Arguments may be of any type, and are concatenated together to form a string.

Note: Sometimes xpilot servers kick out players that type too much, or send two messages in on frame. Because of this, if talk is called more than once per frame, it will automatically spread sending the messages over several frames.

;; Writes a message to everyone
(talk "Hello everyone!")

;; Writes a private message to "Jimmy"
(talk "Jimmy: hello I'm at" (pos))

;; Change to team of closest ship
(when (on-screen? 0)
      (talk "/team" (team 0)))
function (msg-to index1 . idx) → m1 m2…

Look at a private message’s "to" field from the player-to-player messaging system. Returns #f if there is no "to" field either because there is no message or it is a public message.

See also: talk, msg-from, msg-body

function (msg-from index1 . idx) → m1 m2…

Look at a message’s "from" field from the player-to-player messaging system. Returns #f if there are no messages.

See also: msg-to, msg-body

function (msg-body index1 . idx) → m1 m2…

Look at a message’s "body" field from the player-to-player messaging system. Returns NULL if there are no messages.

;; cycles through all the messages recieved
;; every frame and prints the body
(use srfi-1)

(define (print-bodies)
   (for-each print
             (unfold msg-body
                     msg-body add1 0)))

See also: talk, msg-to, msg-from

8. HUD

The HUD is the informative box around the self’s ship. These functions access various information from the HUD, like the info about who killed who (Useful for determing kills).

function (HUD-name index1 . idx) → n1 n2…

Look at a HUD slot’s name field. Returns #f if there is no name in that slot.

function (HUD-score index1 . idx) → s1 s2…

Look at a HUD slot’s score field. It is best to check for empty slots using [AIself.HUD.time?] . Returns #f if slot does not exist.

function (HUD-time index1 . idx) → t1 t2…

Number of frames that the HUD message has been on the HUD slot. When a score first appears it will have a value of 0, then increase each frame thereafter until it gets to about 99.

(use srfi-1)

;; Return a list of all HUD messages
(define (HUD-list field)
  (unfold HUD-time field add1 0))

;; Return a list of HUD messages with positive scores
(define (HUD-gains)
  (filter positive?
          (HUD-list HUD-score)))

See also: HUD-score, HUD-name

9. Arithmetic functions

Useful math functions

function (anglediff a1 a2) → a

Returns the smallest angle which angle1 could add to itself to be equal to angle2. This is useful for turning particular directions.

#;1> (anglediff 90 70)
-20
#;2> (anglediff 350 10)
20
function (angleadd a1 . angles) → a

Adds any number of angles together.

#;1> (angleadd 90 70)
160
#;2> (angleadd 350 40 10)
40
function (anglesub a1 . angles) → a

Subtracks any number of angles

function (deg→rad d) → r

Converts a degree angle to radian, which is used in sin, cos, and tan.

function (rad→deg r) → d

Converts a radian angle to degree, which is used in gameplay.