Difference between revisions of "Oolite Javascript Reference: PriorityAI Documentation"

From Elite Wiki
(General Methods)
(Utility functions: update)
Line 810: Line 810:
 
== Utility functions ==
 
== Utility functions ==
  
These functions are provided to make standardised checks easier to write.
+
These functions are provided to make standardised checks easier to write and to wrap certain ship methods to make them easier to work with in the AI controller.
  
 
==== <code>allied</code> ====
 
==== <code>allied</code> ====
 
  function '''allied'''(ship1, ship2) : Boolean
 
  function '''allied'''(ship1, ship2) : Boolean
 
Returns <code>true</code> if the two ships are considered allied, false otherwise. Ships are considered allied if they are in the same group, or if they are escorts of ships in the same group.
 
Returns <code>true</code> if the two ships are considered allied, false otherwise. Ships are considered allied if they are in the same group, or if they are escorts of ships in the same group.
 +
 +
==== <code>broadcastDistressMessage</code> ====
 +
function '''broadcastDistressMessage'''()
 +
Broadcasts a distress message, but with a delay to ensure that [[Oolite_JavaScript_Reference:_Ship#broadcastDistressMessage|ship.broadcastDistressMessage()]] is not called too often.
 +
  
 
==== <code>checkScannerWithPredicate</code> ====
 
==== <code>checkScannerWithPredicate</code> ====
Line 825: Line 830:
 
  function '''cruiseSpeed'''() : Number
 
  function '''cruiseSpeed'''() : Number
 
Returns a suitable speed for the ship to travel at if it is interested in preserving group or escort coherence. Generally this will be 80% of its maximum speed, but it will be slower if other group members or escorts are slower.
 
Returns a suitable speed for the ship to travel at if it is interested in preserving group or escort coherence. Generally this will be 80% of its maximum speed, but it will be slower if other group members or escorts are slower.
 +
 +
==== <code>distance</code> ====
 +
function '''distance'''(position : [[Oolite_JavaScript_Reference:_Vector3D#Vector_Expressions|vectorExpression]])
 +
Returns the distance to the given coordinates. This is more efficient than calling <code>this.ship.position.distanceTo(position)</code>.
 +
 +
==== <code>entityCommsParams</code> ====
 +
function '''entityCommsParams'''(entity : Entity) : Object
 +
Returns an object of communications parameters relating to the given entity. Used internally by [[#communicate|communicate()]] but may be of use elsewhere.
  
 
==== <code>fineThreshold</code> ====
 
==== <code>fineThreshold</code> ====
Line 841: Line 854:
  
 
If no home station can be found, returns <code>null</code>.
 
If no home station can be found, returns <code>null</code>.
 +
 +
==== <code>ignorePlayerFriendlyFire</code> ====
 +
function '''ignorePlayerFriendlyFire'''() : Boolean
 +
Returns <code>true</code> if this ship should ignore friendly fire from the player as they would for a known ally. Note that this function's results will change if called repeatedly, so you should only call it once per instance of friendly fire, and never call it speculatively.
  
 
==== <code>isAggressive</code> ====
 
==== <code>isAggressive</code> ====
 
  function '''isAggressive'''() : Boolean
 
  function '''isAggressive'''() : Boolean
 
Returns <code>true</code> if the ship is an active danger to its current target (approximately: it is in a combat behaviour other than fleeing)
 
Returns <code>true</code> if the ship is an active danger to its current target (approximately: it is in a combat behaviour other than fleeing)
 +
 +
==== <code>isEscaping</code> ====
 +
function '''isEscaping'''() : Boolean
 +
Returns <code>true</code> if the ship is successfully running away from this ship (i.e. it is not attacking, it is travelling faster than this ship can, and it is already outside effective weapons range.
  
 
==== <code>isFighting</code> ====
 
==== <code>isFighting</code> ====
 
  function '''isAggressive'''() : Boolean
 
  function '''isAggressive'''() : Boolean
 
Returns <code>true</code> if the ship is in combat (including fleeing). Similar to <code>ship.hasHostileTarget</code> but works for stations as well.
 
Returns <code>true</code> if the ship is in combat (including fleeing). Similar to <code>ship.hasHostileTarget</code> but works for stations as well.
 +
 +
==== <code>noteDistraction</code> ====
 +
function '''noteDistraction'''(whom : Entity)
 +
If this ship is switching combat targets because another ship distracted it, then call this function just before switching. <code>whom</code> is the entity that this ship will soon switch to attacking. This calls the <code>shipAttackerDistracted</code> event handler on the current target.
 +
 +
==== <code>oddsAssessment</code> ====
 +
function '''oddsAssessment'''() : Number
 +
Carry out an odds assessment of this ship's group versus the target ship's group. This will return a positive number of the ratio between the two values, with a number greater than 1 implying that this ship's group is stronger, and a number less than 1 implying the target's group is stronger. The odds assessment of the target group will omit certain information unless the target is currently in combat. Ships outside of scanner range, whether friendly or hostile, will also be ignored in the assessment.
 +
 +
==== <code>playerRoleAssessment</code> ====
 +
function '''playerRoleAssessment'''() : String
 +
Determines a single perceived role for the player based on [[Oolite_JavaScript_Reference:_Player#roleWeights|player.roleWeights]]. In general, the perception will be the same for all ships in a group. This can then be used with [[Oolite_JavaScript_Reference:_Ship#roleIsInCategory|Ship.roleIsInCategory]] to determine the appropriate response.
 +
 +
==== <code>respondToThargoids</code> ====
 +
function '''respondToThargoids'''(whom : Ship, passon : Boolean) : Boolean
 +
This function causes the ship (and if the <code>passon</code> parameter is set, its group members) to respond to the appearance of the Thargoid ship <code>whom</code>. It will return <code>true</code> if this ship responds, or <code>false</code> if not.
 +
 +
You must ensure that ships responding to a Thargoid as a result of a notification by a group member do not themselves set <code>passon</code> as this may cause an infinite loop.
 +
 +
==== <code>setWitchspaceRouteTo</code> ====
 +
function '''setWitchspaceRouteTo'''(dest : Number)
 +
This function sets the <code>oolite_witchspaceDestination</code> parameter according to the needs of reaching the system with the system ID equal to <code>dest</code>. As this function involves route planning, which is relatively slow, it should be called only rarely. This can then be used to determine whether to refuel or attempt to jump.
 +
 +
==== <code>shipHasRiskyContracts</code> ====
 +
function '''shipHasRiskyContracts'''(ship : Ship) : Boolean
 +
Sometimes returns <code>true</code> (non-deterministically) if the target ship is carrying contracts that someone might want assassinated or destroyed. The chance of returning <code>true</code> increases with the number of risky contracts carried. Currently this will always return <code>false</code> for a non-player ship: you can check these with the <code>oolite-courier</code> role category instead.
 +
 +
==== <code>shipInRoleCategory</code> ====
 +
function '''shipInRoleCategory'''(ship : Ship, category : String) : Boolean
 +
This is a wrapper around <code>Ship.roleIsInCategory</code> which accounts for the player's effective role not being the same as <code>player.ship.primaryRole</code>. You should generally call this instead of calling <code>Ship.roleIsInCategory</code> directly.
 +
 +
==== <code>stationAllegiance</code> ====
 +
function '''stationAllegiance'''(station : Station) : String
 +
Returns <code>station.allegiance</code> for the given station, but if this is null (as it will be for pre-1.79 stations), first sets it using a heuristic calculation.
 +
 +
==== <code>threatAssessment</code> ====
 +
function '''threatAssessment'''(ship : Ship, full : Boolean) : Number
 +
This is a wrapper around <code>[[#_threatAssessment|_threatAssessment]]</code> which is itself a wrapper around <code>[[Oolite_JavaScript_Reference:_Ship#threatAssessment|ship.threatAssessment()]]</code>. The combination of the two ensures that the assessment is correct for the relative combat states of this ship and the ship being assessed, as well as including effects of the player's reputation.
  
 
== Waypoint Generators ==
 
== Waypoint Generators ==

Revision as of 12:42, 6 October 2013

Contents

AILib Constructor and general functions

Constructor

new AILib(ship : Ship) : AILib

Creates a priority AI and attaches it to the specified ship.

Properties

ship

ship : Ship (read-only)

The ship to which the priority AI is attached.

General Methods

Additional methods are described in later sections, sorted by purpose.

applyHandlers

function applyHandlers(handlers : Object)

Deletes any existing event handlers applied to the ship's AI Script by a previous invocation of applyHandlers, and copies the handlers in the argument object to the AI Script. All handlers applied this way run with 'this' equal to the PriorityAIController, not to the AI Script.

clearHandlers

function clearHandlers(handlers : Object)

Deletes any existing event handlers applied to the ship's AI Script by a previous invocation of applyHandlers.

communicate

function communicate(key : String, params : Object, priority : Number)

If the communication "key" has previously been defined for this ship's communications role and personality, retrieves it, calls expandDescription on it, using the parameters in the object (which can either be a dictionary, or a Ship). This message may then broadcast on the public channel, depending on the priority. If the object is a Ship, it will be converted to a dictionary for expandDescription with the following parameters:

  • oolite_entityClass = ship.shipClassName
  • oolite_entityName = ship.shipUniqueName

Other parameters may be added later to this expansion.

The priority can be a number from 1 to 4

  1. Always send this message
  2. Send this message if no messages sent in the last 10 seconds
  3. Send this message if no messages sent or received in the last 10 seconds
  4. Send this message if no messages sent or received in the last 60 seconds

This is used to prevent an overwhelming number of comms messages being sent. While priority 1 is necessary for messages which must be heard by the player, care must be taken to ensure by other means that they cannot be sent repeatedly.

getParameter

function getParameter(key : String) : Value

If a parameter with that key has previously been set, return its value. Otherwise return null. Note that the return value can be of any type, so you must be careful when setting and retrieving parameters to avoid type errors.

getWaypointGenerator

function getWaypointGenerator() : Function

If a waypoint generation function has previously been set, return it.

noteCommsHeard

function noteCommsHeard()

This function is used to reset the timers for priority 3 and 4 communications. The standard event handlers will call this for you, but you may need to call it manually otherwise.

reconsiderIn

function reconsiderIn(delay : Number)

Force a reconsideration of the AI's priority list ahead of schedule, if no request for sooner reconsideration has already been received. delay must be at least 0.1 seconds.

reconsiderNow

function reconsiderNow()

Force a reconsideration of the AI's priority list ahead of schedule.

setCommunicationsRole

function setCommunicationsRole(role : String)

Sets the ship's communications role to the given value. This is then used to vary the communications messages as defined by _setCommunication.

setCommunicationsPersonality

function setCommunicationsPersonality(role : String)

Sets the ship's communications personality to the given value. This is then used to vary the communications messages as defined by _setCommunication.


setParameter

function setParameter(key : String, value : Value)

Set the named parameter to the given value. Values may be of any type. To remove a parameter, use a value of null.

setPriorities

function setPriorities(priorities : Array)

Set the priority list for the AI, and evaluate it. The format of the priority list is described in the next section.

setWaypointGenerator

function setWaypointGenerator(generator : Function)

Sets the AI's Waypoint Generatorswaypoint generator function.

Writing a priority list

The priority list is the core of the priority AI. The list will be reevaluated periodically - either timed, or when events occur - and on each reevaluation it will be searched from top to bottom. When a valid priority is found, searching will stop, and that priority will be executed.

If the parameter "oolite_flag_behaviourLogging" is set with setParameter then verbose information will be written to the log file regarding the processing of the priority list. It is generally advisable to use the debug console to do this for one ship at a time, rather than setting it generally!

Basic structure

The priority list is an array of objects. Each object contains a set of keys and values. The keys are considered in the following order and are all optional.

  • preconfiguration: function run unconditionally if this element of the list is reached.
  • condition: function run unconditionally if this element of the list is reached. If it returns false, the remainder of the object is ignored, and consideration moves to the next list element.
  • notcondition: function run unconditionally if this element of the list is reached. If it returns true, the remainder of the object is ignored, and consideration moves to the next list element.

If neither condition nor notcondition are set, this is treated as if a condition was set and was true.

  • configuration: function run if conditions allow
  • behaviour: function run if conditions allow. If this exists, no further elements of the priority list will be considered.
  • reconsider: A number. If a behaviour is executed, the priority list will next be reconsidered in this many seconds. If this value is absent the priority list will only be considered if an event causes it.
  • truebranch: a priority list array. If there was no behaviour, but the conditions allow one to be run, the truebranch will be evaluated as a priority list. If the truebranch causes a behaviour to be executed, consideration will end here. If the truebranch reaches its end without executing a behaviour, consideration will continue with the next element of the main priority list.
  • falsebranch: a priority list array. This will be executed if the the conditions caused the previous four elements to be skipped.

If evaluation reaches the end of the main priority list without finding a behaviour to execute, an error will be noted in the log. In general the last element of the main priority list should always be unconditional (or have a truebranch and a falsebranch, both of which have an unconditional last element).

Example of simple behaviour: (from thargoid AI)

		{
				preconfiguration: ai.configurationCheckScanner,
				condition: ai.conditionScannerContainsNonThargoid,
				configuration: ai.configurationAcquireScannedTarget,
				behaviour: ai.behaviourDestroyCurrentTarget,
				reconsider: 1
		},

Example of branch usage: (from police AI)

		{
				/* The group leader leads the patrol */
				condition: ai.conditionIsGroupLeader,
				truebranch: [
						/* Nothing interesting here. Patrol for a bit */
						{
								condition: ai.conditionHasWaypoint,
								configuration: ai.configurationSetDestinationToWaypoint,
								behaviour: ai.behaviourApproachDestination,
								reconsider: 30
						},
						/* No patrol route set up. Make one */
						{
								configuration: ai.configurationSetWaypoint,
								behaviour: ai.behaviourApproachDestination,
								reconsider: 30
						}
				],
				/* Other ships in the group will set themselves up
				 * as escorts if possible, or looser followers if
				 * not */
				falsebranch: [
						{
								preconfiguration: ai.configurationEscortGroupLeader,
								condition: ai.conditionIsEscorting,
								behaviour: ai.behaviourEscortMothership,
								reconsider: 30
						},
						/* if we can't set up as an escort */
						{
								behaviour: ai.behaviourFollowGroupLeader,
								reconsider: 15
						}
				]
		}

The AI Library provides a selection of standard condition, configuration and behaviour functions for us in AIs, but you can also write your own.

		/* Ship is unstable and may explode under stress */
		{
				condition: function()
				{
						return Math.random() < 0.01; // 1% chance per evaluation
				}				
				behaviour: function()
				{
						this.ship.explode();
				}
		}

Evaluation context

All condition, configuration and behaviour functions are evaluated in the context of the AI object. The 'this' variable when one of these functions is run therefore points to the priority AI, not to the AI Script.

Note that this.ship is defined and will be equivalent to the this.ship seen by the AI Script. However, if you wish to access properties of the AI Script you must use this.ship.AIScript.property. Properties and methods of the priority AI may be accessed directly, e.g. this.allied(this.ship,this.ship.target).


Behaviour functions

Behaviour functions determine what the ship will do next. They generally begin a particular behaviour, and set up event handlers (generally aided by the response templates) to allow interruption or modification of that behaviour should anything interesting happen.

Behaviour functions take no arguments and return nothing.

General behaviours

Behaviours intended for ships in general. These mostly use responsesAddStandard, and occasionally add others.

behaviourApproachDestination

function behaviourApproachDestination()

Travels from the current position to within desiredRange of destination, avoiding obstacles on the way.

If a waypoint is set in the parameters "oolite_waypoint" and "oolite_waypointRange", it will clear these parameters if when it reaches its destination it is sufficiently close to the waypoint. If the parameter "oolite_flag_patrolStation" is set, and its group leader is a station, it will report in to the station upon reaching the waypoint.

Temporary waypoints needed to avoid obstacles will be stored in the "oolite_waypoints" parameter.

behaviourBecomeInactiveThargon

function behaviourBecomeInactiveThargon()

This behaviour is intended to deactivate thargons and should generally only be used for that purpose. It changes the scan class to CLASS_CARGO, clears the ship's targeting information, brings it to a stop, removes it from its ship groups, and removes it from nearby ship's targeting systems (it can be retargeted).

behaviourCollectSalvage

function behaviourCollectSalvage()

This behaviour attempts to scoop the current target. If it is successful, the "oolite_cargoDropped" parameter recording the number of seen cargo pods will be cleared.

behaviourDestroyCurrentTarget

function behaviourDestroyCurrentTarget()

This behaviour attacks the current target, only stopping when interrupted or when the target is destroyed.

behaviourDockWithStation

function behaviourDockWithStation()

This behaviour docks with the station specified in the parameter "oolite_dockingStation". If the target refuses docking or the ship is too big to dock, the parameter will be cleared.

behaviourEnterWitchspace

function behaviourEnterWitchspace()

This behaviour attempts to enter witchspace. It can do this in several ways:

  • If the parameter "oolite_witchspaceWormhole" is set to an active wormhole, it will try to fly to and use that wormhole.
  • If the parameter "oolite_witchspaceDestination" is set, then it will try to jump to that destination using its own drive. It will wait for its escorts to be launched, and will start spinning up this drive. Calling this behaviour again after 15 seconds will cause it to jump out.
  • Otherwise, it will wait for a wormhole to be suggested by another member of its group, or for the player to create one.

behaviourEscortMothership

function behaviourEscortMothership()

This behaviour performs non-combat escorting of the ship's group leader, in the formation requested by the lead ship.

behaviourFineCurrentTarget

function behaviourFineCurrentTarget()

If the ship has scan class "CLASS_POLICE" and a current target, mark that target for fines when it next docks.

behaviourFleeCombat

function behaviourFleeCombat()

The ship will flee from hostility, in the following order:

  • Cascade explosions (coordinates from the parameter "oolite_cascadeDetected")
  • Its current target, if it can see it
  • Its defense targets, if it can see them

behaviourFollowGroupLeader

function behaviourFollowGroupLeader()

The ship will follow the group leader if there is one, attempting to remain within a few kilometres of it.

behaviourGuardTarget

function behaviourGuardTarget()

The ship will fly to within a few kilometres of its current target. Similar to behaviourFollowGroupLeader but allows following of any ship.

behaviourLandOnPlanet

function behaviourLandOnPlanet()

Lands on the nearest planet. Unlike most behaviours, this one does not include the standard responses, so you should generally wait until the ship is only a few hundred metres above the surface before using it.

behaviourLeaveVicinityOfTarget

function behaviourLeaveVicinityOfTarget()

Moves outside scanner range of the current target. Unlike fleeing, this does not use fuel injectors if they are fitted, and does not cause the ship to appear hostile to its target.

behaviourMineTarget

function behaviourMineTarget()

Attacks the current target with a mining laser to break it into splinters. If the current target is not a rock, this behaviour will be cancelled and the target will be lost.

behaviourOfferToEscort

function behaviourOfferToEscort()

Offers to escort the ship identified by the parameter "oolite_scanResultSpecific". Unless this parameter has been set by the scanner condition conditionScannerContainsShipNeedingEscort this is extremely likely to fail.

To be accepted as an escort, the ship must have the primary role "escort", "wingman" or "EQ_THARGON"

behaviourPayOffPirates

function behaviourPayOffPirates()

If a pirate demand to dump cargo exists, dump that many cargo canisters (or all of them, if fewer), and then switch to behaviourFleeCombat

behaviourReconsider

function behaviourReconsider()

Does nothing except schedule a re-evaluation of the priority list.

behaviourRejoinMothership

function behaviourRejoinMothership()

This behaviour flies to rejoin the mothership, and then escorts it as in behaviourEscortMothership.

behaviourRepelCurrentTarget

function behaviourRepelCurrentTarget()

This behaviour attacks the current target, but will break off the attack (and ask its escorts to do the same) if the target starts fleeing.

behaviourRespondToDistressCall

function behaviourRespondToDistressCall()

If the ship has a valid distress call represented by the parameters "oolite_distressAggressor" and "oolite_distressSender" it will attack the aggressor if it can see it. Otherwise it will fly (with injectors if available) to near the sender, attempting to locate the aggressor.

If the aggressor has a lower bounty than the sender, then the ship will assume that the distress call is "unjust", and attack the sender instead.

behaviourRobTarget

function behaviourRobTarget()

If an existing group demand for cargo is in effect, attack the current target in the hope that it meets it. Demands are stored with the group leader if possible.

If there is no existing demand for cargo, create one based on the cargo capacity of the target ship, the current system government, the cargo capacity of the group, and other factors.

behaviourSunskim

function behaviourSunskim()

Fly along until fuel tanks are full. In general, this behaviour should not be started until sunskimming height is reached (test with conditionReadyToSunskim), and configurationSetDestinationToSunskimEnd should be used to set a safe sunskimming direction.

behaviourTumble

function behaviourTumble()

Start tumbling. Unlike most behaviours, this one does not include the standard responses, so you will need to manually request a reconsideration of priorities if one is needed.


Missile behaviours

Missile behaviours use responsesAddMissile. More discussion of setting missile parameters, ECM response, and detonation can be found there.

behaviourMissileInterceptCoordinates

function behaviourMissileInterceptCoordinates()

Close to the desired missile range (default 25m, or specified by the oolite_missile_proximity key in script info), detonating when reached. The coordinates to close in on are specified in the "oolite_interceptCoordinates". This is used to track missile targets which cloak.

behaviourMissileInterceptTarget

function behaviourMissileInterceptTarget()

Close to the desired missile range (default 25m, or specified by the oolite_missile_proximity key in script info), detonating when reached.

behaviourMissileSelfDestruct

function behaviourMissileSelfDestruct()

Destroys the missile without detonating the payload.


Station behaviours

Station behaviours use responsesAddStation to set up their general handlers, as most standard behaviours are unnecessary or unhelpful for a stationary station.

behaviourStationLaunchDefenseShips

function behaviourStationLaunchDefenseShips()

If the station has a target and the target is aggressive, launches a defense ship if any remain, increases the alert condition to Red, and requests a group attack on the target. Otherwise does nothing.

behaviourStationLaunchMiner

function behaviourStationLaunchMiner()

If the station does not currently have a miner in its ship group, launches one. Also reduces the alert condition by one step.

behaviourStationLaunchPatrol

function behaviourStationLaunchPatrol()

If the station does not currently have a ship in its ship group with the primary role equal to the parameter "oolite_stationPatrolRole", launches one. Also reduces the alert condition by one step.

behaviourStationLaunchSalvager

function behaviourStationLaunchMiner()

Launches a salvager. Also reduces the alert condition by one step.

behaviourStationManageTraffic

function behaviourStationManageTraffic()

The station idles. If the system repopulator has requested launches that this station can fulfil, it may launch a ship.

behaviourStationRespondToDistressCall

function behaviourStationRespondToDistressCall()

Locates the aggressor and sender in the same way as [[#behaviourRespondToDistressCall|behaviourRespondToDistressCall]. If the aggressor is not visible, does nothing, otherwise sets the aggressor as a target, increases alert condition to Red, and launches a defense ship to attack the aggressor.


Condition functions

Condition functions are used to determine whether to execute a priority AI behaviour. They take no arguments and return a Boolean.

Combat conditions

Conditions related to the ship's performance in combat.

conditionCascadeDetected

function conditionCascadeDetected() : Boolean

Returns true if a cascade explosion has been detected recently (as given by the parameter "oolite_cascadeDetected" containing the explosion coordinates).

conditionCombatOddsGood

function conditionCombatOddsGood() : Boolean

The ship's group has good odds of winning combat against the ship's target group. Presently this just carries out a simple headcount, but this will become more sophisticated in future.

conditionInCombat

function conditionInCombat() : Boolean

The ship is currently attacking other ships, or a ship in its group or one of its escorts is.

conditionInCombatWithHostiles

function conditionInCombat() : Boolean

The ship is currently attacking other ships, or a ship in its group or one of its escorts is. Additionally, at least one of the targets of those ships is itself attacking (though not necessarily attacking anything from this ship's group)

conditionLosingCombat

function conditionLosingCombat() : Boolean

The ship is in combat, but is losing. The exact definition of "losing" may vary, and is intended to account for the overall tactical situation.

conditionMothershipInCombat

function conditionMothershipInCombat() : Boolean

This ship's group leader is attacking and/or being attacked. Other ships in the group are not considered. This ship must be able to see its leader's target.

conditionMothershipIsAttacking

function conditionMothershipIsAttacking() : Boolean

This ship's group leader is attacking a target. This ship must be able to see its leader's target.

conditionMothershipIsAttackingHostileTarget

function conditionMothershipIsAttacking() : Boolean

This ship's group leader is attacking a target which is itself attacking something. This ship must be able to see its leader's target.

conditionMothershipUnderAttack

function conditionMothershipUnderAttack() : Boolean

This ship's group leader is currently being targeted. This ship must be able to see the attacker.

Navigation conditions

Conditions related to the ship's surroundings and navigation through the system.

conditionCanWitchspaceOut

function conditionCanWitchspaceOut() : Boolean

The ship has a witchspace drive, and at least one other system is within range with the current fuel supply.

conditionFriendlyStationExists

function conditionFriendlyStationExists() : Boolean

There is at least one friendly station in the system.

conditionFriendlyStationNearby

function conditionFriendlyStationNearby() : Boolean

There is at least one friendly station within scanner range

conditionGroupIsSeparated

function conditionGroupIsSeparated() : Boolean

The ship is in a group and has a group leader, and is out of scanner range of that leader (or out of 2x scanner range if the leader is a station)

conditionHasSelectedPlanet

function conditionHasSelectedPlanet() : Boolean

The ship has a valid planet in the "oolite_selectedPlanet" parameter.

conditionHasSelectedStation

function conditionHasSelectedStation() : Boolean

The ship has a valid planet in the "oolite_selectedStation" parameter.

conditionHomeStationExists

function conditionHomeStationExists() : Boolean

The ship's home station still exists

conditionHomeStationNearby

function conditionHomeStationNearby() : Boolean

The ship's home station is within scanner range.

conditionInInterstellarSpace

function conditionInInterstellarSpace() : Boolean

The ship is currently in interstellar space.

conditionMainPlanetNearby

function conditionMainPlanetNearby() : Boolean

The ship is within 3 radii of the surface of the main planet

conditionNearDestination

function conditionNearDestination() : Boolean

The ship is closer than the desired range to its destination

conditionPlayerNearby

function conditionPlayerNearby() : Boolean

The player's ship is within scanner range.

conditionReadyToSunskim

function conditionReadyToSunskim() : Boolean

The ship is close enough to the sun to scoop fuel.

conditionSelectedStationNearby

function conditionSelectedStationNearby() : Boolean

The ship has a selected station in the "oolite_selectedStation" parameter, and it is within scanner range.

conditionSelectedStationNearMainPlanet

function conditionSelectedStationNearMainPlanet() : Boolean

The ship has a selected station in the "oolite_selectedStation" parameter, and it is within 3 radii of the surface of the main planet.

conditionSunskimPossible

function conditionSunskimPossible() : Boolean

There is a sun, it's not going nova, it hasn't gone nova, the ship has a non-full fuel tank and fuel scoops, and the ship has sufficient heat insulation to skim safely.

Piracy-related conditions

Conditions involved in piratical activities.

conditionCargoDemandsMet

function conditionCargoDemandsMet() : Boolean

Since this ship (or an ally) made a cargo demand, this ship has seen enough cargo dropped to meet that demand.

conditionGroupHasEnoughLoot

function conditionGroupHasEnoughLoot() : Boolean

The group this ship belongs to has obtained enough cargo to call it a day. Currently this happens when cargo space usage is above 50%, but more sophisticated checks are planned involving damage or lost ships, expenditure of consumables, and so on.

conditionPiratesCanBePaidOff

function conditionPiratesCanBePaidOff() : Boolean

Pirates have demanded that this ship dump cargo, and it currently has enough cargo on board to meet that demand.

Scanning conditions

These conditions check the ship's latest scan (configurationCheckScanner) for ships meeting particular requirements. If a ship is found, it will be placed in the "oolite_scanResultsSpecific" parameter, in addition to the condition returning true.

conditionScannerContainsEscapePods

function conditionScannerContainsEscapePods() : Boolean

The scan contains an escape pod travelling slower than this ship's maximum speed, and this ship is able to scoop cargo.

conditionScannerContainsFineableOffender

function conditionScannerContainsFineableOffender() : Boolean

The scan contains a piloted ship with an offender legal status at or below the system threshold (varies with government) that has not already been marked for fines.

conditionScannerContainsFugitive

function conditionScannerContainsFugitive() : Boolean

The scan contains a fugitive ship

conditionScannerContainsHuntableOffender

function conditionScannerContainsHuntableOffender() : Boolean

The scan contains a piloted ship with an offender legal status above the system threshold (varies with government).

conditionScannerContainsHunters

function conditionScannerContainsHunters() : Boolean

The scan contains a ship with role "hunter", or a police ship, or the main station.

conditionScannerContainsMiningOpportunity

function conditionScannerContainsMiningOpportunity() : Boolean

The scan contains a boulder (preferentially) or an asteroid, and the ship has a mining laser, a fuel scoop, and a non-full hold.

conditionScannerContainsNonThargoid

function conditionScannerContainsNonThargoid() : Boolean

The scan contains a ship which is not a Thargoid ship. Rocks and cargo will only be returned if there is nothing more interesting about.

conditionScannerContainsPirateVictims

function conditionScannerContainsPirateVictims() : Boolean

The scan contains a pirate victim (as defined by pirate-victim-roles.plist) which is carrying at least some cargo and has not recently been robbed.

conditionScannerContainsReadyThargoidMothership

function conditionScannerContainsReadyThargoidMothership() : Boolean

The scan contains a thargoid mothership which has the capability to control at least one more thargon.

conditionScannerContainsRocks

function conditionScannerContainsRocks() : Boolean

The scan contains boulders (preferentially) or asteroids.

conditionScannerContainsSalvage

function conditionScannerContainsSalvage() : Boolean

The scan contains cargo which could in theory be scooped.

conditionScannerContainsSalvageForGroup

function conditionScannerContainsSalvageForGroup() : Boolean

The scan contains cargo which could in theory be scooped, and it is travelling slowly enough that at least one of the ships in the group with fuel scoops and cargo space can collect it..

conditionScannerContainsSalvageForMe

function conditionScannerContainsSalvageForMe() : Boolean

The scan contains cargo which can be scooped by this ship (travelling slowly enough, and this ship has scoops and space)

conditionScannerContainsShipNeedingEscort

function conditionScannerContainsShipNeedingEscort() : Boolean

The scan contains a ship which has fewer escorts than its maximum. If the ship is clean, this will only detect other clean ships. If the ship is not clean, this will only detect other non-clean ships.

conditionScannerContainsThargoidMothership

function conditionScannerContainsThargoidMothership() : Boolean

The scan contains a thargoid mothership which has the capability to control thargons. The number of thargons currently being controlled is irrelevant to this scan.

State querying conditions

Conditions related to the state of the ship

conditionAllEscortsInFlight

function conditionAllEscortsInFlight() : Boolean

If the ship has living escorts, then this function returns true only if they are all in normal flight (and not docked, launching, or in a wormhole). If the ship has no escorts then this function also returns true.

conditionCanScoopCargo

function conditionCanScoopCargo() : Boolean

The ship has a working fuel scoop and at least 1 TC of free space in its hold.

conditionCargoIsProfitableHere

function conditionCargoIsProfitableHere() : Boolean

The current contents of the ship's hold can be sold at an above average price at the main station (this is currently determined very approximately - solely asking "is the current system on the right side of the Ind/Agri divide" - rather than checking station prices.

conditionGroupLeaderIsStation

function conditionGroupLeaderIsStation() : Boolean

The ship has a group leader and the group leader is a station.

conditionHasInterceptCoordinates

function conditionHasInterceptCoordinates() : Boolean

The ship has intercept coordinates set in the parameter "oolite_interceptCoordinates". These are used by missiles to home in on a last-known location if the target cloaks.

conditionHasMothership

function conditionHasMothership() : Boolean

The ship has a group leader which is not itself.

conditionHasNonThargoidTarget

function conditionHasNonThargoidTarget() : Boolean

The ship's target is not null, and is not a thargoid ship (by scan class).

conditionHasReceivedDistressCall

function conditionHasReceivedDistressCall() : Boolean

The ship has recently received a distress call. Distress calls expire after 30 seconds, or if the sender is no longer visible, or if the aggressor is dead.

conditionHasTarget

function conditionHasTarget() : Boolean

The ship's target is not null.

conditionHasWaypoint

function conditionHasWaypoint() : Boolean

The ship has a waypoint set by its waypoint generator.

conditionIsActiveThargon

function conditionIsActiveThargon() : Boolean

The ship is a thargon ("EQ_THARGON") and is active.

conditionIsEscorting

function conditionIsEscorting() : Boolean

The ship is currently escorting another ship. Stricter than conditionHasMothership: this also requires this ship to be in the group leader's escort group.

conditionIsGroupLeader

function conditionIsGroupLeader() : Boolean

The ship is in a group and is the leader of the group

conditionMissileOutOfFuel

function conditionMissileOutOfFuel() : Boolean

The ship has travelled beyond the maximum missile range. The default is 30km, but this may be overridden by the oolite_missile_range parameter in the ship's script info.

conditionWitchspaceEntryRequested

function conditionWitchspaceEntryRequested() : Boolean

The ship has been requested to enter a wormhole set in the "oolite_witchspaceWormhole" parameter.

Configuration functions

Configuration functions are usually used to set up parameters needed for a behaviour, though some may be used at the preconfiguration stage to set up parameters for a condition test. They take no arguments and do not return anything.

Destination configurations

These configurations set a destination, a desired range and a desired speed suitable for use with behaviourApproachDestination. Unless otherwise stated, cruiseSpeed will be used as the desired speed.

If they are unable to set a destination, they may set the destination to the ship's current position, or may do nothing. Generally a condition should be used to check that the configuration is sensible.

configurationSetDestinationToNearestFriendlyStation

function configurationSetDestinationToNearestFriendlyStation()

Locates the nearest friendly station, sets the destination to its position and the desired range to 15km.

configurationSetDestinationToHomeStation

function configurationSetDestinationToHomeStation()

Locates the home station, sets the destination to its position and the desired range to 15km.

configurationSetDestinationToGroupLeader

function configurationSetDestinationToGroupLeader()

Locates the group leader, sets the destination to its position and the desired range to 15km. Maximum flight speed is used.

configurationSetDestinationToMainPlanet

function configurationSetDestinationToMainPlanet()

Sets the destination to the main planet's position, and the desired range to 3 radii (i.e. 2 radii from the surface).

configurationSetDestinationToMainStation

function configurationSetDestinationToMainStation()

Sets the destination to the main station's position, and the desired range to 15km

configurationSetDestinationToPirateLurk

function configurationSetDestinationToPirateLurk()

If the parameter "oolite_pirateLurk" is set, then set the destination to that. If currently on a lane, set the destination to the current position. Otherwise, pick a random point on one of the lanes (strongly preferring witchpoint-planet). Once a destination is selected, store it to the parameter "oolite_pirateLurk".

The desired range is 1km.

configurationSetDestinationToSelectedPlanet

function configurationSetDestinationToSelectedPlanet()

Sets the destination to the position of the planet in the parameter "oolite_selectedPlanet", and the desired range to 100m from the surface.

configurationSetDestinationToSelectedStation

function configurationSetDestinationToSelectedStation()

Sets the destination to the position of the station in the parameter "oolite_selectedStation", and the desired range to 15km.

configurationSetDestinationToSunskimEnd

function configurationSetDestinationToSunskimEnd()

Sets the destination to a course parallel to the sun's surface, at a range which should allow the fuel tanks to be completely refilled. The desired range is 0, and the desired speed is maximum speed.

Note: if this function is used above sunskimming height, it will still move parallel to the sun's surface, but this will not be much use.

configurationSetDestinationToSunskimStart

function configurationSetDestinationToSunskimStart()

Sets the destination to the sun's position, and the desired range to sunskimming height.

configurationSetDestinationToWaypoint

function configurationSetDestinationToWaypoint()

If the parameters "oolite_waypoint" and "oolite_waypointRange" are set, use those as the destination and desired range.

configurationSetDestinationToWitchpoint

function configurationSetDestinationToWitchpoint()

Sets the destination to the witchpoint and the range to 10km

configurationSetWaypoint

function configurationSetWaypoint()

If a waypoint generator function has been registered, runs that function to set the "oolite_waypoint" and "oolite_waypointRange" parameters, then sets the destination from those parameters.

Docking configurations

Each of these configurations sets the "oolite_dockingStation" parameter used by behaviourDockWithStation

configurationSetNearbyFriendlyStationForDocking

function configurationSetNearbyFriendlyStationForDocking()

Sets the "oolite_dockingStation" parameter to a friendly station in scanner range, if possible.

configurationSetHomeStationForDocking

function configurationSetHomeStationForDocking()

Sets the "oolite_dockingStation" parameter to the ship's home station.

configurationSetSelectedStationForDocking

function configurationSetHomeStationForDocking()

Sets the "oolite_dockingStation" parameter to the station in the parameter "oolite_selectedStation".

Miscellaneous configurations

configurationAppointGroupLeader

function configurationAppointGroupLeader()

If the ship is in a group but the group has no leader, set one of the ships in the group to be the leader. Witchspace-capable ships will be preferred over those which are not.

If the parameter "oolite_leaderRole" is set, the primary role of the new leader will be changed to that role.

configurationEscortGroupLeader

function configurationEscortGroupLeader()

If the ship is in a group and the group has a leader which is not this ship and the ship is not already escorting the group leader, and the parameter "oolite_escortRole" is set, then attempt to escort the group leader. The ship's primary role will be set to "oolite_escortRole" if the escort attempt is successful, and this role must therefore be a valid escort role.

configurationForgetCargoDemand

function configurationForgetCargoDemand()

If the ship has a cargo demand active (the demand must be stored on this ship, not just on a group member), discard it, and reset the "oolite_cargoDropped" parameter of this ship and all group members to zero.

configurationLeaveEscortGroup

function configurationLeaveEscortGroup()

If the ship is currently escorting another ship, leave the escort group.

Navigation configurations

configurationSelectRandomTradeStation

function configurationSelectRandomTradeStation()

This function places a suitable station in the parameter "oolite_selectedStation". If the ship is clean, then 90% of the time this will be the main station. If the ship is an offender, but has a bounty not greater than the fine threshold, then 50% of the time this will be the main station.

If the main station was not selected at the previous step, a random friendly station will be selected (which may be the main station anyway)

configurationSelectShuttleDestination

function configurationSelectShuttleDestination()

This function selects a random planet or station. The entity selected must be at least 10km from the ship. If any such entities are within 5 times the radius of the main planet from the ship, more distant entities will be ignored.

If the selected entity was a planet, it will be stored in "oolite_selectedPlanet". Otherwise, it will be stored in "oolite_selectedStation".

configurationSelectWitchspaceDestination

function configurationSelectWitchspaceDestination()

If the ship has no witchspace drive, unset the "oolite_witchspaceDestination" parameter. If that parameter is already set, and is not the current system, and the ship has enough fuel to reach that system, do nothing. Otherwise, select a random system in range and place its ID in the "oolite_witchspaceDestination" parameter.

Station configurations

configurationStationReduceAlertLevel

function configurationStationReduceAlertLevel()

Reduce the alert level of the station by one stage if it is not already Green.

configurationStationValidateTarget

function configurationStationValidateTarget()

Check that the station's current target is within scanner range, and discard it if not. This is necessary for stations as unlike ships their low-level behaviour does not generally do this automatically.

Target acquisition configurations

configurationAcquireCombatTarget

function configurationAcquireCombatTarget()

If the ship's target is valid, not cargo and not an ally, keep the current target. Otherwise, promote one defense target to a target. If the ship has no defense targets, check to see if any ships in the group or escort group have a combat target (but do not check their defense targets).

configurationAcquireDefensiveEscortTarget

function configurationAcquireDefensiveEscortTarget()

Search the current group leader's target and defense targets for a visible ship attacking the group leader, and target it if one is found. Otherwise, retain current target.

configurationAcquireHostileCombatTarget

function configurationAcquireHostileCombatTarget()

As configurationAcquireCombatTarget but only targets which are hostile (i.e. would be valid for behaviourRepelTarget) will be selected.

configurationAcquireOffensiveEscortTarget

function configurationAcquireOffensiveEscortTarget()

If this ship's group leader is attacking a target, and this ship can see that target, acquire that target. Otherwise retain current target.

configurationAcquirePlayerAsTarget

function configurationAcquirePlayerAsTarget()

Set this ship's target to the player.

configurationAcquireScannedTarget

function configurationAcquireScannedTarget()

Set this ship's target to the entity in the parameter "oolite_scanResultSpecific". This parameter is set by the checkScannerWithPredicate function, which is usually called from a conditionScannerContains... condition.

configurationCheckScanner

function configurationCheckScanner()

Scans the ship's scanner range, placing a list of detected targets into the "oolite_scanResults" parameter. This is generally called in a preconfiguration before the first use of a conditionScannerContains... condition in the priority list.

If the scanner is particularly full, the list will not contain all visible objects. The current scan limit is 16.

Response definition functions

Response definition functions are used to set up event handlers in the AI script. They take an object as an argument, and add event handlers to that object. They do not return anything as such, but modify their argument.

They are generally used in behaviour functions to set up common responses.

var handlers = {}; // new handler object
this.responsesAddStandard(handlers); // add standard response set
// add a handler for this behaviour
handlers.shipEnteredStationAegis = function(station)
{
  this.ship.beaconCode = null; // stop transmitting
}
this.applyHandlers(handlers);

responsesAddDocking

function responsesAddDocking(handlers : Object)

Provides some additional event handlers for use when docking with a station.

responsesAddEscort

function responsesAddEscort(handlers : Object)

Provides some additional event handlers for use when escorting a ship, and changes the response to in-group help requests.

responsesAddMissile

function responsesAddMissile(handlers : Object)

A standard set of event handlers for missiles, which should be used instead of responsesAddStandard.

A number of script info keys are used to modify the responses.

  • oolite_missile_blastPower, oolite_missile_blastRadius, oolite_missile_blastShaping: If oolite_missile_detonation is not set, the default detonation function calls this.ship.dealEnergyDamage with the defined power, radius, and shaping. If these parameters are not set the defaults are power 170, radius 32.5, and shaping 0.25.
  • oolite_missile_detonation: names a function in the AI script. This function will be called when the missile reaches the desired range from its target or destination. If this function is not set, the oolite_missile_blast* keys are used to set up an explosion.
  • oolite_missile_ecmResponse: names a function in the AI script. This function will be called if the missile detects an ECM pulse. If no function is set, the missile will self destruct.


responsesAddStandard

function responsesAddStandard(handlers : Object)

Sets up standard event handlers to detect and respond to attacks, and to manage other common events. Certain parameter flags are used:

  • oolite_flag_allowPlanetaryLanding: if true, the ship will land on a planet if it receives the approachingPlanetSurface event. Otherwise, it will immediately reconsider its behaviour.
  • oolite_flag_listenForDistressCall: if true, the ship will set the "oolite_distressAggressor", "oolite_distressSender" and "oolite_distressTimestamp" parameters if it receives a distress call.
  • oolite_flag_markOffenders: if true, the ship will apply a small bounty increase to ships it sees committing crimes.
  • oolite_flag_sendsDistressCalls: if true, the ship will send distress calls when attacked.
  • oolite_flag_watchForCargo: if true, the ship will increment the "oolite_cargoDropped" parameter if cargo is dumped nearby.

If multiple standard responses are being applied, this one should be the first one applied.

responsesAddStation

function responsesAddStation(handlers : Object)

A standard set of event handlers for stations, which should be used instead of responsesAddStandard. The "oolite_flag_listenForDistressCall" and "oolite_flag_markOffenders" parameters have the same use as in responsesAddStandard.

Utility functions

These functions are provided to make standardised checks easier to write and to wrap certain ship methods to make them easier to work with in the AI controller.

allied

function allied(ship1, ship2) : Boolean

Returns true if the two ships are considered allied, false otherwise. Ships are considered allied if they are in the same group, or if they are escorts of ships in the same group.

broadcastDistressMessage

function broadcastDistressMessage()

Broadcasts a distress message, but with a delay to ensure that ship.broadcastDistressMessage() is not called too often.


checkScannerWithPredicate

function checkScannerWithPredicate(function) : Boolean

Called after configurationCheckScanner to locate a ship on the scanner matching a particular predicate. The predicate function must take a Ship, and return a Boolean.

If the predicate function matches a ship, the first such match will be stored in the parameter "oolite_scanResultSpecific", and the method will return true. Otherwise the method returns false.

cruiseSpeed

function cruiseSpeed() : Number

Returns a suitable speed for the ship to travel at if it is interested in preserving group or escort coherence. Generally this will be 80% of its maximum speed, but it will be slower if other group members or escorts are slower.

distance

function distance(position : vectorExpression)

Returns the distance to the given coordinates. This is more efficient than calling this.ship.position.distanceTo(position).

entityCommsParams

function entityCommsParams(entity : Entity) : Object

Returns an object of communications parameters relating to the given entity. Used internally by communicate() but may be of use elsewhere.

fineThreshold

function fineThreshold() : Number

The maximum bounty at which an offender should be fined rather than attacked by police ships. (Ships caught redhanded may be attacked regardless of bounty) Varies from system to system.

friendlyStation

function friendlyStation(station) : Boolean

Returns true if the station is friendly to the current ship, false otherwise. The main station is unfriendly to Fugitive ships and Offenders above the current fineThreshold. Other stations are only considered unfriendly to their current combat target.

homeStation

function homeStation() : Boolean

Returns the home station of this ship. If the ship has an owner, and the owner is a station, then that is the home station. Otherwise, the first station in the ship's group is returned.

If no home station can be found, returns null.

ignorePlayerFriendlyFire

function ignorePlayerFriendlyFire() : Boolean

Returns true if this ship should ignore friendly fire from the player as they would for a known ally. Note that this function's results will change if called repeatedly, so you should only call it once per instance of friendly fire, and never call it speculatively.

isAggressive

function isAggressive() : Boolean

Returns true if the ship is an active danger to its current target (approximately: it is in a combat behaviour other than fleeing)

isEscaping

function isEscaping() : Boolean

Returns true if the ship is successfully running away from this ship (i.e. it is not attacking, it is travelling faster than this ship can, and it is already outside effective weapons range.

isFighting

function isAggressive() : Boolean

Returns true if the ship is in combat (including fleeing). Similar to ship.hasHostileTarget but works for stations as well.

noteDistraction

function noteDistraction(whom : Entity)

If this ship is switching combat targets because another ship distracted it, then call this function just before switching. whom is the entity that this ship will soon switch to attacking. This calls the shipAttackerDistracted event handler on the current target.

oddsAssessment

function oddsAssessment() : Number

Carry out an odds assessment of this ship's group versus the target ship's group. This will return a positive number of the ratio between the two values, with a number greater than 1 implying that this ship's group is stronger, and a number less than 1 implying the target's group is stronger. The odds assessment of the target group will omit certain information unless the target is currently in combat. Ships outside of scanner range, whether friendly or hostile, will also be ignored in the assessment.

playerRoleAssessment

function playerRoleAssessment() : String

Determines a single perceived role for the player based on player.roleWeights. In general, the perception will be the same for all ships in a group. This can then be used with Ship.roleIsInCategory to determine the appropriate response.

respondToThargoids

function respondToThargoids(whom : Ship, passon : Boolean) : Boolean

This function causes the ship (and if the passon parameter is set, its group members) to respond to the appearance of the Thargoid ship whom. It will return true if this ship responds, or false if not.

You must ensure that ships responding to a Thargoid as a result of a notification by a group member do not themselves set passon as this may cause an infinite loop.

setWitchspaceRouteTo

function setWitchspaceRouteTo(dest : Number)

This function sets the oolite_witchspaceDestination parameter according to the needs of reaching the system with the system ID equal to dest. As this function involves route planning, which is relatively slow, it should be called only rarely. This can then be used to determine whether to refuel or attempt to jump.

shipHasRiskyContracts

function shipHasRiskyContracts(ship : Ship) : Boolean

Sometimes returns true (non-deterministically) if the target ship is carrying contracts that someone might want assassinated or destroyed. The chance of returning true increases with the number of risky contracts carried. Currently this will always return false for a non-player ship: you can check these with the oolite-courier role category instead.

shipInRoleCategory

function shipInRoleCategory(ship : Ship, category : String) : Boolean

This is a wrapper around Ship.roleIsInCategory which accounts for the player's effective role not being the same as player.ship.primaryRole. You should generally call this instead of calling Ship.roleIsInCategory directly.

stationAllegiance

function stationAllegiance(station : Station) : String

Returns station.allegiance for the given station, but if this is null (as it will be for pre-1.79 stations), first sets it using a heuristic calculation.

threatAssessment

function threatAssessment(ship : Ship, full : Boolean) : Number

This is a wrapper around _threatAssessment which is itself a wrapper around ship.threatAssessment(). The combination of the two ensures that the assessment is correct for the relative combat states of this ship and the ship being assessed, as well as including effects of the player's reputation.

Waypoint Generators

Waypoint generators are used to set patrol or other multipoint routes. When called, they should consider the ship's current position (and possibly other things), and then set the parameters "oolite_waypoint" and "oolite_waypointRange". These functions have no arguments and no return value.

In general, you should only call a waypoint generator if a waypoint is not already set.

waypointsSpacelanePatrol

function waypointsSpacelanePatrol()

If the ship is near the main planet, sun, or witchpoint, pick one of the other two points (biased towards the witchpoint-planet route) and set that as the waypoint. Otherwise, if the ship is on a lane already, pick one end of the lane at random. Otherwise, pick the planet.

Set a waypoint within 7500m of the witchpoint, 2 radii of the centre of the planet, or 2.5 radii of the centre of the sun.

waypointsStationPatrol

function waypointsStationPatrol()

If the ship has a station as its group leader, define waypoints from that station. Otherwise define them from the main station. If there is no main station either, set the witchpoint as the waypoint.

If there is a station, pick four points describing a square of diagonal length 50km centred on the station and lying in the station's xy plane. If the ship is not within 500 metres of any of these points, select one of the points as the waypoint. Otherwise, select the next point around the list as the waypoint.