1. General Functions

These functions allow general control of the Xpilot client

(xpilot args) → void

Launches the xpilot client with the specified command line arguments.

/*joins server on localhost:1338 with name "jim"*/

(xpilot "-name jim -join localhost -port 1338");

(AI.xpilot.setargs) → void

Sets the arguments to use when launching xpilot. Use prior to calling .

; joins server on localhost:1338 with name "jim"

(AI.xpilot.setargs "-name jim -join localhost -port 1338")
(AI.xpilot.launch)

(AI.xpilot.launch) → int

Launches the xpilot client. Returns 1 if successful

(AI.setmaxturn degrees) → void

Sets the maximum turn for self in degrees per frame.

(AI.teamplay void) → int

Returns 1 if teamplay is enabled.

(AI.pressKey key) → void

Simulates a key press. AI.releaseKey must be called after to complete the key-stroke.

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

(define (AImain)
  (AI.pressKey KEY_FIRE_LASER)
  (AI.releaseKey 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: [AI.releaseKey]

(AI.releaseKey int key) → void

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

See also: [AI.pressKey]

2. Self Control

Functions to control the ship

(AIself.thrust thrust) → void

Controls the ship’s thrust. 1 to thrust, 0 to not thrust. Resets to not-thrust after every frame.

;  a ship that thrusts every frame

(define (AImain)
  (AIself.thrust 1))

(AIself.turn turn) → void

Turns the ship turn degrees (out of 360). Negative degrees are clockwise, positive counter-clockwise.

; a ship that turns 15 degrees clockwise every frame

(define (AImain)
  (AIself.turn -15))

(AIself.shoot shoot) → void

Makes the ship shoot. 1 to shoot, 0 to not shoot. Servers limit the shot rate and the number of shots, so AIself.shoot(1) will not always cause a shot to be fired. Use [AIself.reload?] to check the number of frames remaining before it is possible to shoot again.

;  a ship that waits until "reload"
;  says it can shoot and then shoots

(define (AImain)
  (if (= (AIself.reload?) 0)
      (AIself.shoot 1)))

(AIself.shield shield) Turns on or off the ship’s shield. Use [AIself.shield?] to see the status of the shield.

;  a ship whose shield is always on

(define (AImain)
  (AIself.shield 1)))

(AIself.destruct) → void

Start or stop the self-destruct sequence.

3. Self Variables

Functions that return values of variables concerning the self ship. [[ AIself.id?]] (AIself.id?) → int:: The id of self’s ship, according to the server.

See Also: [AIship.id?]

(AIself.alive?) → int

1 if self is alive, 0 if not.

(AIself.x?) → int

Self’s x position, where bottom left of map is [0, 0].

(AIself.y?) → int

Self’s y position, where bottom left of map is [0, 0].

(AIself.vel?) → int

Self’s velocity (number of pixels moved per frame).

(AIself.heading?) → int

Self’s heading (direction ship’s nose is pointing). 0 degrees is to the right and 90 degrees is straight up.

(AIself.track?) → int

Self’s track (direction of movement). 0 degrees is to the right and 90 degrees is straight up.

(AIself.mapx?) → int

Self’s x position on radar map, using radar map units.

(AIself.mapy?) → int

Self’s y position on radar map, using radar map units.

(AIself.team?) → int

Number of self’s team on server.

(AIself.life?) → int

Remaining lives on server.

See Also: [AIship.life?]

(AIself.shield?) → int

Returns 1 if shield is up, 0 if shield is down.

(AIself.name?) → string

Returns name of self on server.

See Also: [AIship.name?]

(AIself.score?) → inexact number

Returns score of self as displayed in the rankings See Also: [AIself.HUD.score?]

(AIself.reload?) → int

Number of frames remaining before self is able to shoot. When 0, self is able to shoot.

4. Ships

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

(AIship.x? index) → int

Ship’s x position, where bottom left of map is [0, 0].

(AIship.y? index) → int

Ship’s y position, where bottom left of map is [0, 0].

(AIship.heading? index) → int

Ship’s heading (angle nose is pointing). 0 degrees is to the right, and 90 straight up.

(AIship.track? index) → int

Ship’s track (direction of velocity). 0 degrees is to the right, and 90 straight up.

(AIship.vel? index) → int

Ship’s velocity in pixels/frame.

(AIship.dist? index) → int

Ship’s distance from self, in pixels.

(AIship.id? index) → int

server assigned id of ship

See Also: [AIself.id?]

(AIship.xdir? index) → int

Direction of ship from self. 0 degrees is to the right and 90 upright.

;  Self always points at nearest on screen ship
(define (AImain)
  (if (not (= (AIship.x? 0) -1))
      (AIself.turn (anglediff (AIself.heading?)
                              (AIship.xdir? 0)))))

(define (friendly? idx)
  (= (AIself.team?) (AIship.team? idx)))

(define hostile? (complement friendly?))

(use srfi-1)
;; Get a list of ships that satisfy a predicate
(define (ships pred)
  (filter pred (unfold (o negative? AIship.id?)
                       identity add1 0)))

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

(AIship.shield? index) → int

Returns 1 if ship’s shield is on, 0 if off, or -1 if ship is not on screen

See Also: [AIself.shield]

(AIship.life? index) → int

See Also: [AIself.life?]

(AIship.team? index) → int

See Also: [AIself.team?]

(AIship.reload? index) → int

This is the number of frames remaining before the ship can fire again. This number is just an estimate, and may not always be correct.

(AIship.name?* index) → name

Returns name of ship at index, or "" if ship does not exist.

See Also: [AIself.name?]

(AIship.aimdir? index) → int

Calculates the direction that self would need to point to hit the ship, according to self’s track and velocity, the enemy ship’s track and velocity, and the default bullet’s shotspeed. This is a pretty deadly function. Sometimes it can’t calculate correctly and returns some negative number.

;  bot that aims and shoots at nearest ship

(define (AImain)
  (when (not (= (AIship.x? 0) -1))
        (AIself.turn (anglediff (AIself.heading?)
                                (AIship.aimdir? 0)))
        (AIself.shoot 1)))

5. Radar

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

(AIradar.x? index) → int

Radar ship’s x position (approximate), where bottom left of map is [0, 0].

(AIradar.y? index) → int

Radar ship’s y position (approximate), where bottom left of map is [0, 0].

(AIradar.dist? index) → int

Radar ship’s distance from self, in pixels (approximate).

(AIradar.xdir? index) → int

Direction of radar ship from self. 0 degrees is to the right and 90 upright.

; self always points at second-nearest radar ship
(define (AImain)
  (if (not (= (AIradar.x? 1) -1))
      (AIself.turn (anglediff (AIself.heading?)
                              (AIradar.xdir? 1)))))

(AIradar.enemy? index) → int

Returns 0 if ship on radar is on team, 1 if ship is an enemy, or -1 if ship is not on screen

See Also: [AIship.team?]

6. Shots

Functions returning information about the shots on screen.

(AIshot.x? index) → int

shot’s x position, where bottom left of map is [0, 0].

(AIshot.y? index) → int

shot’s y position, where bottom left of map is [0, 0].

(AIshot.track? index) → int

shot’s track (direction of velocity). 0 degrees is to the right, and 90 straight up.

(AIshot.vel? index) → int

shot’s velocity in pixels/frame.

(AIshot.dist? index) → int

shot’s distance from self, in pixels.

(AIshot.imaginary? index) → int

Imaginary shots are calculated for every ship on screen. If a ship were to shoot this frame, imaginary bullets tell that shots attributes.

See Also: [AIshot.x?]

(AIshot.xdir? index) → int

Direction of shot from self. 0 degrees is to the right and 90 upright.

(AIshot.idir? index) → int

Direction of the location where the shot will be nearest to self, if both self velocity and bullet velocity remain constant. 0 degrees is to the right and 90 upright.

; self turns away from intercept dir and thrusts

(define (AImain)
  (when (not (= (AIshot.x? 0) -1))
        (AIself.turn (anglediff (AIself.heading?)
                                (angleadd (AIshot.idir? 0) 180)))
        (AIself.thrust 1)))

(AIshot.idist? index) → int

Distance to the location where the shot will be nearest to self, if both self velocity and bullet velocity remain constant, in pixels.

(AIshot.itime? index) → int

Number of frames until the nearest intercept will occur, if both self velocity and bullet velocity remain constant.

(AIshot.alert? index) → int

A value derived from [AIshot.idist?] and [AIshot.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.

7. Walls and Map

Functions to check for walls and to look at map tiles

(AI.wallbetween x1 y1 x2 y2) → int

This function checks for walls in a straight line starting from point [x1, y1] to point [x2, y2]. If it finds a wall, it returns the distance (in pixels) from [x1, y1] to that point. If gets to [x2, y2] without finding a wall, it returns -1.

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

(define (wall_N )
  (AI.wallbetween
   (AIself.x?)
   (AIself.y?)
   (+ (AIself.x?)
      (* 200 (cos (rad (AIself.track?)))))
   (+ (AIself.y?)
      (* 200 (sin (rad (AIself.track?)))))))

(AI.wallbetween.x x1 y1 x2 y2) → int

This function checks for walls in a straight line starting from point [x1, y1] to point [x2, y2]. If it finds a wall, it returns the x coordinate of that wall. If gets to [x2, y2] without finding a wall, it returns -1.

(AI.wallbetween.y x1 y1 x2 y2) → int

This function checks for walls in a straight line starting from point [x1, y1] to point [x2, y2]. If it finds a wall, it returns the y coordinate of that wall. If gets to [x2, y2] without finding a wall, it returns -1.

(AImap? map-x map-y) → integer

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. To convert a regular game coordinate to a map coordinate, use [tomap] and [frmap] .

;  checks to see if the map tile to the immediate
;  right of the player contains a wall of some sort

(if (positive?
     (bitwise-and (AImap? (+ (tomap (AIself.x?)) 1)
                         (+ (tomap (AIself.y?)) 1))
                  BLUE_BIT))
    (print "To the right is a wall tile!")
Note:
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

(AImap.set map-x map-y 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.

;  Sets a bit flag on the map tile underneath self

(let ((newtile (AImap? (tomap (AIself.x?)) (tomap (AIself.y?)))))
  (set! newtile (bitwise-ior newtile 0x1000))
  (AImap.set (tomap (AIself.x?)) (tomap (AIself.y?)) newtile))

(tomap pixel-val) → tile-val

Converts a gamplay pixel value to a map value.

(frmap tile-val) → pixel-val

Takes a map value and returns the middle of that map tile, in pixels.

8. Messages

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

(AI.talk message) Say a message through the player-to-player talk system in Xpilot.

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

;  Writes a message to everyone
        (AI.talk "Hello everyone")
;  Writes a private message to a player named "Jimmy"
        (AI.talk "Jimmy: hello I'm at (22, 1004)")
;  Change to team 5
        (AI.talk "/team 5")

(AI.msg.to? index) Look at a private message’s "to" field from the player-to-player messaging system. Returns NULL if there is no "to" field either because there is no message or it is a public message.

(AI.msg.from? index) Look at a message’s "from" field from the player-to-player messaging system. Returns NULL if there are no messages.

(AImsg.body index) 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
(define (print-bodies)
  (do ((i 0 (+ i 1)))
      ((= (length (AImsg.body i)) 0))
    (print (AImsg.body i))))

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

(AIself.HUD.name? index) Look at a HUD slot’s name field. Returns "" if there is no name in that slot.

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

(AIself.HUD.time? index) 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. [AIself.HUD.time?] .

(use srfi-1)

;; Return a list of all HUD messages
(define (HUD-list)
  (unfold (o negative? AIself.HUD.time?)
          identity add1 0))

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

10. Math Functions

Useful math functions

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

(anglediff 90 70) ;-> -20
(anglediff 350 10);->  20

See Also: [angleadd], [rad], [deg]

(angleadd a1 a2) Adds two angles together.

(angleadd 90 70) ; -> 160
(angleadd 350 40); -> 30

See Also: [angleadd], [rad], [deg]

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

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