Make a start on pirate AI (doesn't work yet)
This commit is contained in:
parent
b8da00024b
commit
3e9f6741e7
120
Resources/AIs/pirateAI.js
Normal file
120
Resources/AIs/pirateAI.js
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
|
||||
pirateAI.js
|
||||
|
||||
Priority-based AI for pirates
|
||||
|
||||
Oolite
|
||||
Copyright © 2004-2013 Giles C Williams and contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.name = "Oolite Pirate AI";
|
||||
this.version = "1.79";
|
||||
|
||||
this.aiStarted = function() {
|
||||
var ai = new worldScripts["oolite-libPriorityAI"].AILib(this.ship);
|
||||
|
||||
ai.setParameter("oolite_flag_watchForCargo",true);
|
||||
/* This communication is necessary but needs more variety and moving to descriptions.plist so it can be translated */
|
||||
ai.setCommunication("oolite_piracyAlert","Your cargo or your life, [p1]! Give us [p2] containers and we'll let you go.");
|
||||
|
||||
|
||||
ai.setPriorities([
|
||||
/* Combat */
|
||||
{
|
||||
condition: ai.conditionLosingCombat,
|
||||
behaviour: ai.behaviourFleeCombat,
|
||||
reconsider: 5
|
||||
},
|
||||
{
|
||||
condition: ai.conditionCargoDemandsMet,
|
||||
/* Let them go if they've dropped enough cargo and stop firing back */
|
||||
truebranch: [
|
||||
{
|
||||
condition: ai.conditionInCombat,
|
||||
configuration: ai.configurationAcquireCombatTarget,
|
||||
behaviour: ai.behaviourRepelCurrentTarget,
|
||||
reconsider: 5
|
||||
}
|
||||
],
|
||||
falsebranch: [
|
||||
{
|
||||
condition: ai.conditionInCombat,
|
||||
configuration: ai.configurationAcquireCombatTarget,
|
||||
behaviour: ai.behaviourDestroyCurrentTarget,
|
||||
reconsider: 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
preconfiguration: ai.configurationCheckScanner,
|
||||
condition: ai.conditionScannerContainsSalvage,
|
||||
configuration: ai.configurationAcquireScannedTarget,
|
||||
behaviour: ai.behaviourCollectSalvage,
|
||||
reconsider: 20
|
||||
},
|
||||
/* Stay out of the way of hunters */
|
||||
{
|
||||
condition: ai.conditionScannerContainsHunters,
|
||||
configuration: ai.configurationAcquireScannedTarget,
|
||||
behaviour: ai.behaviourVicinityOfTarget,
|
||||
reconsider: 20
|
||||
},
|
||||
/* Regroup if necessary */
|
||||
{
|
||||
preconfiguration: ai.configurationAppointGroupLeader,
|
||||
condition: ai.conditionGroupIsSeparated,
|
||||
configuration: ai.configurationSetDestinationToGroupLeader,
|
||||
behaviour: ai.behaviourApproachDestination,
|
||||
reconsider: 15
|
||||
},
|
||||
{
|
||||
condition: ai.conditionGroupHasEnoughLoot,
|
||||
/* Find a station to dock at */
|
||||
truebranch: [
|
||||
/* TODO */
|
||||
|
||||
],
|
||||
/* Look for more loot */
|
||||
falsebranch: [
|
||||
{
|
||||
condition: ai.conditionScannerContainsPirateVictims,
|
||||
configuration: ai.configurationAcquireScannedTarget,
|
||||
truebranch: [
|
||||
condition: ai.conditionCombatOddsGood,
|
||||
behaviour: ai.behaviourRobTarget,
|
||||
reconsider: 5
|
||||
]
|
||||
},
|
||||
/* TODO: move to a position on one of the space lanes, preferring lane 1 */
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
// full of loot, but stuck in system and no friendly stations
|
||||
configuration: ai.configurationSetDestinationToWitchpoint,
|
||||
// TODO: behaviour search for wormholes
|
||||
behaviour: ai.behaviourApproachDestination,
|
||||
reconsider: 30
|
||||
}
|
||||
]);
|
||||
|
||||
}
|
@ -39,7 +39,8 @@ this.aiStarted = function() {
|
||||
* before 1.79 */
|
||||
ai.setCommunication("oolite_selectedStation","Heading for [p1]");
|
||||
ai.setCommunication("oolite_selectedWitchspaceDestination","Prepare for witchspace jump to [p1]");
|
||||
ai.setCommunication("oolite_engageWitchspaceDrive","Commencing witchspace countdown");
|
||||
ai.setCommunication("oolite_agreeingToDumpCargo","Take our cargo but please let us go!");
|
||||
|
||||
|
||||
ai.setPriorities([
|
||||
{
|
||||
|
@ -480,6 +480,23 @@ this.AILib = function(ship)
|
||||
});
|
||||
}
|
||||
|
||||
this.conditionScannerContainsHunters = function()
|
||||
{
|
||||
return this.checkScannerWithPredicate(function(s) {
|
||||
return s.primaryRole == "hunter" || s.scanClass == "CLASS_POLICE" || (s.isStation && s.isMainStation);
|
||||
});
|
||||
}
|
||||
|
||||
this.conditionScannerContainsPirateVictims = function()
|
||||
{
|
||||
return this.checkScannerWithPredicate(function(s) {
|
||||
// is a pirate victim
|
||||
// has some cargo on board
|
||||
// hasn't already paid up
|
||||
return s.isPirateVictim && s.cargoSpaceUsed > 0 && (!s.AIScript.oolite_intership || !s.AIScript.oolite_intership.cargodemandpaid);
|
||||
});
|
||||
}
|
||||
|
||||
this.conditionScannerContainsHuntableOffender = function()
|
||||
{
|
||||
return this.checkScannerWithPredicate(function(s) {
|
||||
@ -709,6 +726,109 @@ this.AILib = function(ship)
|
||||
return true;
|
||||
}
|
||||
|
||||
this.conditionCargoDemandsMet = function()
|
||||
{
|
||||
if (!this.getParameter("oolite_flag_watchForCargo"))
|
||||
{
|
||||
log(this.name,"AI '"+this.ship.AIScript.name+"' for ship "+this.ship+" is asking if cargo demands are met but has not set 'oolite_flag_watchForCargo'");
|
||||
return true;
|
||||
}
|
||||
var seen = this.getParameter("oolite_cargoDropped");
|
||||
if (seen != null)
|
||||
{
|
||||
var demand = 0;
|
||||
if (this.group)
|
||||
{
|
||||
if (this.group.leader && this.group.leader.AIScript.oolite_intership && this.group.leader.AIScript.oolite_intership.cargodemanded > 0)
|
||||
{
|
||||
demand = this.group.leader.AIScript.oolite_intership.cargodemanded;
|
||||
}
|
||||
else if (this.group.ships[0].AIScript.oolite_intership && this.group.ships[0].AIScript.oolite_intership.cargodemanded > 0)
|
||||
|
||||
{
|
||||
demand = this.group.ships[0].AIScript.oolite_intership.cargodemanded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.ship.AIScript.oolite_intership.cargodemanded > 0)
|
||||
{
|
||||
demand = this.ship.AIScript.oolite_intership.cargodemanded;
|
||||
}
|
||||
}
|
||||
if (demand == 0)
|
||||
{
|
||||
return false; // no demand made, so it can't have been met
|
||||
}
|
||||
if (demand <= seen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.conditionGroupIsSeparated = function()
|
||||
{
|
||||
if (!this.ship.group || !this.ship.group.leader)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (this.ship.position.distanceTo(this.ship.group.leader) > this.ship.scannerRange);
|
||||
}
|
||||
|
||||
this.conditionCombatOddsGood = function()
|
||||
{
|
||||
// TODO: this should consider what the ships are, somehow
|
||||
var us = 1;
|
||||
if (this.ship.group)
|
||||
{
|
||||
us += this.ship.group.count - 1;
|
||||
}
|
||||
if (this.ship.escortGroup)
|
||||
{
|
||||
us += this.ship.escortGroup.count - 1;
|
||||
}
|
||||
|
||||
var them = 1;
|
||||
if (this.ship.target.group)
|
||||
{
|
||||
them += this.ship.target.group.count - 1;
|
||||
}
|
||||
if (this.ship.target.escortGroup)
|
||||
{
|
||||
them += this.ship.target.escortGroup.count - 1;
|
||||
}
|
||||
return us >= them;
|
||||
}
|
||||
|
||||
this.conditionGroupHasEnoughLoot = function()
|
||||
{
|
||||
var used = 0;
|
||||
var available = 0;
|
||||
if (!this.ship.group)
|
||||
{
|
||||
used = this.ship.cargoSpaceUsed;
|
||||
available = this.ship.cargoSpaceAvailable;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < this.ship.group.ships.length; i++)
|
||||
{
|
||||
used += this.ship.group.ships[i].cargoSpaceUsed;
|
||||
available += this.ship.group.ships[i].cargoSpaceAvailable;
|
||||
}
|
||||
}
|
||||
if (available < used || available == 0)
|
||||
{
|
||||
/* Over half-full. This will do for now. TODO: cutting
|
||||
* losses if group is taking damage, losing ships, running
|
||||
* low on consumables, etc. */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ****************** Behaviour functions ************** */
|
||||
|
||||
/* Behaviours. Behaviours are effectively a state definition,
|
||||
@ -806,6 +926,7 @@ this.AILib = function(ship)
|
||||
this.responsesAddStandard(handlers);
|
||||
handlers.shipScoopedOther = function(other)
|
||||
{
|
||||
this.setParameter("oolite_cargoDropped",null);
|
||||
this.reconsiderNow();
|
||||
}
|
||||
this.setUpHandlers(handlers);
|
||||
@ -1142,11 +1263,74 @@ this.AILib = function(ship)
|
||||
this.behaviourPayOffPirates = function()
|
||||
{
|
||||
this.ship.dumpCargo(this.ship.AIScript.oolite_intership.cargodemand);
|
||||
this.communicate("oolite_agreeingToDumpCargo");
|
||||
delete this.ship.AIScript.oolite_intership.cargodemand;
|
||||
this.ship.AIScript.oolite_intership.cargodemandpaid = true;
|
||||
this.behaviourFleeCombat();
|
||||
}
|
||||
|
||||
this.behaviourLeaveVicinityOfTarget = function()
|
||||
{
|
||||
if (!this.ship.target)
|
||||
{
|
||||
this.reconsiderNow();
|
||||
return;
|
||||
}
|
||||
this.ship.destination = this.ship.target.position;
|
||||
this.ship.desiredRange = 27500;
|
||||
this.ship.desiredSpeed = this.ship.maxSpeed;
|
||||
var handlers = {};
|
||||
this.responsesAddStandard(handlers);
|
||||
this.setUpHandlers(handlers);
|
||||
this.ship.performFlyToRangeFromDestination();
|
||||
}
|
||||
|
||||
this.behaviourRobTarget = function()
|
||||
{
|
||||
var demand = null;
|
||||
if (this.ship.group && this.ship.group.leader)
|
||||
{
|
||||
if (this.ship.group.leader.AIScript.oolite_intership && this.ship.group.leader.AIScript.oolite_intership.cargodemanded)
|
||||
{
|
||||
demand = this.ship.group.leader.AIScript.oolite_intership.cargodemanded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.ship.AIScript.oolite_intership.cargodemanded)
|
||||
{
|
||||
demand = this.ship.AIScript.oolite_intership.cargodemanded;
|
||||
}
|
||||
}
|
||||
if (demand == null)
|
||||
{
|
||||
var hascargo = this.ship.target.cargoSpaceUsed;
|
||||
var discount = hascargo/10; // if we blow them up we likely won't get more than this anyway
|
||||
demand = Math.ceil(discount); // but round it up...
|
||||
|
||||
/* Record our demand with the group leader */
|
||||
if (this.ship.group && this.ship.group.leader)
|
||||
{
|
||||
this.ship.group.leader.AIScript.oolite_intership.cargodemanded = demand;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ship.AIScript.oolite_intership.cargodemanded = demand;
|
||||
}
|
||||
/* Inform the victim of the demand, if possible */
|
||||
if (this.ship.target.AIScript.oolite_intership)
|
||||
{
|
||||
this.ship.target.AIScript.oolite_intership.cargodemand = demand;
|
||||
}
|
||||
this.communicate("oolite_piracyAlert",this.ship.target,demand);
|
||||
this.ship.requestHelpFromGroup();
|
||||
}
|
||||
var handlers = {};
|
||||
this.responsesAddStandard(handlers);
|
||||
this.setUpHandlers(handlers);
|
||||
this.ship.performAttack();
|
||||
}
|
||||
|
||||
this.behaviourReconsider = function()
|
||||
{
|
||||
var handlers = {};
|
||||
@ -1375,6 +1559,20 @@ this.AILib = function(ship)
|
||||
}
|
||||
}
|
||||
|
||||
this.configurationSetDestinationToGroupLeader = function()
|
||||
{
|
||||
if (!this.ship.group || !this.ship.group.leader)
|
||||
{
|
||||
this.ship.destination = this.ship.position;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ship.destination = this.ship.group.leader.position;
|
||||
}
|
||||
this.ship.desiredRange = 2000;
|
||||
this.ship.desiredSpeed = this.ship.maxSpeed;
|
||||
}
|
||||
|
||||
this.configurationSetDestinationFromPatrolRoute = function()
|
||||
{
|
||||
this.ship.destination = this.getParameter("oolite_patrolRoute");
|
||||
@ -1532,6 +1730,14 @@ this.AILib = function(ship)
|
||||
}
|
||||
|
||||
|
||||
this.configurationAppointGroupLeader = function()
|
||||
{
|
||||
if (this.ship.group && !this.ship.group.leader)
|
||||
{
|
||||
this.ship.group.leader = this.ship.group.ships[0];
|
||||
}
|
||||
}
|
||||
|
||||
/* ****************** Response definition functions ************** */
|
||||
|
||||
/* Standard state-machine responses. These set up a set of standard
|
||||
@ -1653,6 +1859,19 @@ this.AILib = function(ship)
|
||||
}
|
||||
}
|
||||
}
|
||||
handlers.cargoDumpedNearby = function(cargo,ship)
|
||||
{
|
||||
if (this.getParameter("oolite_flag_watchForCargo"))
|
||||
{
|
||||
var previously = this.getParameter("oolite_cargoDropped");
|
||||
if (previously == null)
|
||||
{
|
||||
previously = 0;
|
||||
}
|
||||
previously++;
|
||||
this.setParameter("oolite_cargoDropped",previously);
|
||||
}
|
||||
}
|
||||
handlers.approachingPlanetSurface = function()
|
||||
{
|
||||
this.reconsiderNow();
|
||||
|
Loading…
x
Reference in New Issue
Block a user