Adjust waypoint setting methodology

New script method: ship.patrolReportIn(station)
This commit is contained in:
cim 2013-07-19 20:18:53 +01:00
parent 1811b2a3f7
commit 5ce15389d6
5 changed files with 253 additions and 125 deletions

View File

@ -33,11 +33,11 @@ this.aiStarted = function() {
var ai = new worldScripts["oolite-libPriorityAI"].AILib(this.ship);
ai.setParameter("oolite_flag_listenForDistressCall",true);
ai.setWaypointGenerator(ai.waypointsSpacelanePatrol);
/* Communications currently for debugging purposes. Need to either
* be removed or given a much bigger set of phrases to choose from
* before 1.79 */
ai.setCommunication("oolite_spacelanePatrol","Setting course for the [p1]");
ai.setCommunication("oolite_distressResponseSender","Hold on, [p1]!");
ai.setCommunication("oolite_distressResponseAggressor","[p1]. Cease your attack or be destroyed!");
ai.setCommunication("oolite_beginningAttack","Scan confirms criminal status of [p1]. Commencing attack run");
@ -93,14 +93,14 @@ this.aiStarted = function() {
},
/* Nothing interesting here. Patrol for a bit */
{
condition: ai.conditionHasPatrolRoute,
configuration: ai.configurationSetDestinationFromPatrolRoute,
condition: ai.conditionHasWaypoint,
configuration: ai.configurationSetDestinationToWaypoint,
behaviour: ai.behaviourApproachDestination,
reconsider: 30
},
/* No patrol route set up. Make one */
{
configuration: ai.configurationMakeSpacelanePatrolRoute,
configuration: ai.configurationSetWaypoint,
behaviour: ai.behaviourApproachDestination,
reconsider: 30
}

View File

@ -1,6 +1,6 @@
/*
policeLanePatrolAI.js
policeAI.js
Priority-based AI for police
@ -26,18 +26,31 @@ MA 02110-1301, USA.
"use strict";
this.name = "Oolite Police (lane patrol) AI";
this.name = "Oolite Police AI";
this.version = "1.79";
this.aiStarted = function() {
var ai = new worldScripts["oolite-libPriorityAI"].AILib(this.ship);
ai.setParameter("oolite_flag_listenForDistressCall",true);
ai.setParameter("oolite_flag_markOffenders",true);
if (false) // TODO: some way to determine whether this ship should launch as station patrol
{
ai.setWaypointGenerator(ai.waypointsStationPatrol);
ai.setParameter("oolite_flag_patrolStation",true);
}
else
{
ai.setWaypointGenerator(ai.waypointsSpacelanePatrol);
}
ai.setParameter("oolite_leaderRole","police");
ai.setParameter("oolite_escortRole","wingman");
/* Needs to use existing entries in descriptions.plist */
ai.setCommunication("oolite_markForFines","Attention, [p1]. Your offences will result in a fine if you dock at %H station..");
// TODO: return to base after long patrols
ai.setPriorities([
/* Fight */
{
@ -97,14 +110,14 @@ this.aiStarted = function() {
truebranch: [
/* Nothing interesting here. Patrol for a bit */
{
condition: ai.conditionHasPatrolRoute,
configuration: ai.configurationSetDestinationFromPatrolRoute,
condition: ai.conditionHasWaypoint,
configuration: ai.configurationSetDestinationToWaypoint,
behaviour: ai.behaviourApproachDestination,
reconsider: 30
},
/* No patrol route set up. Make one */
{
configuration: ai.configurationMakeSpacelanePatrolRoute,
configuration: ai.configurationSetWaypoint,
behaviour: ai.behaviourApproachDestination,
reconsider: 30
}

View File

@ -45,6 +45,7 @@ this.AILib = function(ship)
var priorityList = null;
var parameters = {};
var communications = {};
var waypointgenerator = null;
/* Private utility functions. Do not call these from external code */
@ -213,6 +214,18 @@ this.AILib = function(ship)
return null;
}
// set the waypoint generator function
this.setWaypointGenerator = function(value)
{
waypointgenerator = value;
}
this.getWaypointGenerator = function()
{
return waypointgenerator;
}
/* Requests reconsideration of behaviour ahead of schedule. */
this.reconsiderNow = function()
{
@ -679,9 +692,9 @@ this.AILib = function(ship)
return true;
}
this.conditionHasPatrolRoute = function()
this.conditionHasWaypoint = function()
{
return this.getParameter("oolite_patrolRoute") != null;
return this.getParameter("oolite_waypoint") != null;
}
this.conditionHasSelectedStation = function()
@ -1200,13 +1213,22 @@ this.AILib = function(ship)
}
else
{
var patrol = this.getParameter("oolite_patrolRoute");
if (patrol != null && this.ship.destination.distanceTo(patrol) < 1000)
var patrol = this.getParameter("oolite_waypoint");
if (patrol != null && this.ship.destination.distanceTo(patrol) < 1000+this.getParameter("oolite_waypointRange"))
{
// finished patrol to waypoint
// clear route
this.communicate("oolite_waypointReached");
this.setParameter("oolite_patrolRoute",null);
this.setParameter("oolite_waypoint",null);
this.setParameter("oolite_waypointRange",null);
if (this.getParameter("oolite_flag_patrolStation"))
{
var station = this.getParameter("oolite_patrolStation");
if (station != null && station.isStation)
{
this.ship.patrolReportIn(station);
}
}
}
}
this.reconsiderNow();
@ -2011,115 +2033,21 @@ this.AILib = function(ship)
this.ship.desiredSpeed = this.ship.maxSpeed;
}
this.configurationSetDestinationFromPatrolRoute = function()
this.configurationSetWaypoint = function()
{
this.ship.destination = this.getParameter("oolite_patrolRoute");
this.ship.desiredRange = this.getParameter("oolite_patrolRouteRange");
this.ship.desiredSpeed = this.cruiseSpeed();
var gen = this.getWaypointGenerator();
if(gen != null)
{
gen.call(this);
this.configurationSetDestinationToWaypoint();
}
}
this.configurationMakeSpacelanePatrolRoute = function()
this.configurationSetDestinationToWaypoint = function()
{
var p = this.ship.position;
var choice = "";
if (p.magnitude() < 10000)
{
// near witchpoint
if (Math.random() < 0.9)
{
// mostly return to planet
choice = "PLANET";
}
else
{
choice = "SUN";
}
}
else if (p.distanceTo(system.mainPlanet) < system.mainPlanet.radius * 2)
{
// near planet
if (Math.random() < 0.75)
{
// mostly go to witchpoint
choice = "WITCHPOINT";
}
else
{
choice = "SUN";
}
}
else if (p.distanceTo(system.sun) < system.sun.radius * 3)
{
// near sun
if (Math.random() < 0.9)
{
// mostly return to planet
choice = "PLANET";
}
else
{
choice = "SUN";
}
}
else if (p.z < system.mainPlanet.position.z && ((p.x * p.x) + (p.y * p.y)) < system.mainPlanet.radius * 3)
{
// on lane 1
if (Math.random() < 0.5)
{
choice = "PLANET";
}
else
{
choice = "WITCHPOINT";
}
}
else if (p.subtract(system.mainPlanet).dot(p.subtract(system.sun)) < -0.9)
{
// on lane 2
if (Math.random() < 0.5)
{
choice = "PLANET";
}
else
{
choice = "SUN";
}
}
else if (p.dot(system.sun.position) > 0.9)
{
// on lane 3
if (Math.random() < 0.5)
{
choice = "WITCHPOINT";
}
else
{
choice = "SUN";
}
}
else
{
// we're not on any lane. Return to the planet
choice = "PLANET";
}
// having chosen, now set up the next stop on the patrol
switch (choice) {
case "WITCHPOINT":
this.setParameter("oolite_patrolRoute",new Vector3D(0,0,0));
this.setParameter("oolite_patrolRouteRange",7500);
break;
case "PLANET":
this.setParameter("oolite_patrolRoute",system.mainPlanet.position);
this.setParameter("oolite_patrolRouteRange",system.mainPlanet.radius*2);
break;
case "SUN":
this.setParameter("oolite_patrolRoute",system.sun.position);
this.setParameter("oolite_patrolRouteRange",system.sun.radius*2.5);
break;
}
this.communicate("oolite_spacelanePatrol",choice.toLowerCase());
this.configurationSetDestinationFromPatrolRoute();
this.ship.destination = this.getParameter("oolite_waypoint");
this.ship.desiredRange = this.getParameter("oolite_waypointRange");
this.ship.desiredSpeed = this.cruiseSpeed();
}
@ -2405,6 +2333,9 @@ this.AILib = function(ship)
this.ship.desiredSpeed = this.cruiseSpeed();
this.ship.desiredRange = 15000;
this.ship.performFlyToRangeFromDestination();
if (this.getParameter("oolite_flag_patrolStation")) {
this.setParameter("oolite_patrolStation",station);
}
}
handlers.shipWillEnterWormhole = function()
{
@ -2427,6 +2358,15 @@ this.AILib = function(ship)
this.setParameter("oolite_distressSender",sender);
this.reconsiderNow();
}
handlers.offenceCommittedNearby = function(attacker, victim)
{
if (this.getParameter("oolite_flag_markOffenders"))
{
attacker.setBounty(attacker.bounty | 7,"seen by police");
this.addDefenseTarget(attacker);
this.reconsiderNow();
}
}
handlers.playerWillEnterWitchspace = function()
{
var wormhole = this.getParameter("oolite_witchspaceWormhole");
@ -2518,6 +2458,158 @@ this.AILib = function(ship)
}
/* ******************* Waypoint generators *********************** */
/* Waypoint generators. When these are called, they should set up
* the next waypoint for the ship. Ideally ships should either
* reach that waypoint or formally give up on it before asking for
* the next one, but the generator shouldn't assume that unless
* it's one written specifically for a particular AI. */
this.waypointsSpacelanePatrol = function()
{
var p = this.ship.position;
var choice = "";
if (p.magnitude() < 10000)
{
// near witchpoint
if (Math.random() < 0.9)
{
// mostly return to planet
choice = "PLANET";
}
else
{
choice = "SUN";
}
}
else if (p.distanceTo(system.mainPlanet) < system.mainPlanet.radius * 2)
{
// near planet
if (Math.random() < 0.75)
{
// mostly go to witchpoint
choice = "WITCHPOINT";
}
else
{
choice = "SUN";
}
}
else if (p.distanceTo(system.sun) < system.sun.radius * 3)
{
// near sun
if (Math.random() < 0.9)
{
// mostly return to planet
choice = "PLANET";
}
else
{
choice = "SUN";
}
}
else if (p.z < system.mainPlanet.position.z && ((p.x * p.x) + (p.y * p.y)) < system.mainPlanet.radius * 3)
{
// on lane 1
if (Math.random() < 0.5)
{
choice = "PLANET";
}
else
{
choice = "WITCHPOINT";
}
}
else if (p.subtract(system.mainPlanet).dot(p.subtract(system.sun)) < -0.9)
{
// on lane 2
if (Math.random() < 0.5)
{
choice = "PLANET";
}
else
{
choice = "SUN";
}
}
else if (p.dot(system.sun.position) > 0.9)
{
// on lane 3
if (Math.random() < 0.5)
{
choice = "WITCHPOINT";
}
else
{
choice = "SUN";
}
}
else
{
// we're not on any lane. Return to the planet
choice = "PLANET";
}
// having chosen, now set up the next stop on the patrol
switch (choice) {
case "WITCHPOINT":
this.setParameter("oolite_waypoint",new Vector3D(0,0,0));
this.setParameter("oolite_waypointRange",7500);
break;
case "PLANET":
this.setParameter("oolite_waypoint",system.mainPlanet.position);
this.setParameter("oolite_waypointRange",system.mainPlanet.radius*2);
break;
case "SUN":
this.setParameter("oolite_waypoint",system.sun.position);
this.setParameter("oolite_waypointRange",system.sun.radius*2.5);
break;
}
}
this.waypointsStationPatrol = function()
{
var station = this.getParameter("oolite_patrolStation");
if (!station)
{
station = system.mainStation;
if (!station)
{
this.setParameter("oolite_waypoint",new Vector3D(0,0,0));
this.setParameter("oolite_waypointRange",7500);
return;
}
}
var z = station.vectorForward;
var tmp = z.cross(system.sun.position.direction());
var x = z.cross(tmp);
var y = z.cross(x);
// x and y now consistent vectors relative to a rotating station
var waypoints = [
station.position.add(x.multiply(25000)),
station.position.add(y.multiply(25000)),
station.position.add(x.multiply(-25000)),
station.position.add(y.multiply(-25000))
];
var waypoint = waypoints[0];
for (var i=0;i<=3;i++)
{
if (this.ship.position.distanceTo(waypoints[i]) < 500)
{
waypoint = waypoints[(i+1)%4];
break;
}
}
this.setParameter("oolite_waypoint",waypoint);
this.setParameter("oolite_waypointRange",100);
}
}; // end object constructor

View File

@ -12680,12 +12680,6 @@ static BOOL AuthorityPredicate(Entity *entity, void *parameter)
[self sendExpandedMessage:@"[thanks-for-assist]" toShip:rescueShip];
}
[self setThankedShip:rescuer];
// we don't want clean ships that change target from one pirate to the other pirate getting a bounty.
// removed after discussion at http://aegidian.org/bb/viewtopic.php?f=2&t=12151 - CIM
/* if ([switchingShip bounty] > 0 || [rescueShip bounty] == 0)
{
[switchingShip setBounty:[switchingShip bounty] + 5 + (ranrot_rand() & 15) withReason:kOOLegalStatusReasonAttackedInnocent]; // reward
} */
}
}
}

View File

@ -31,6 +31,7 @@ MA 02110-1301, USA.
#import "ShipEntity.h"
#import "ShipEntityAI.h"
#import "ShipEntityScriptMethods.h"
#import "StationEntity.h"
#import "WormholeEntity.h"
#import "AI.h"
#import "OOStringParsing.h"
@ -75,6 +76,8 @@ static JSBool ShipAbandonShip(JSContext *context, uintN argc, jsval *vp);
static JSBool ShipCanAwardEquipment(JSContext *context, uintN argc, jsval *vp);
static JSBool ShipAwardEquipment(JSContext *context, uintN argc, jsval *vp);
static JSBool ShipRequestHelpFromGroup(JSContext *context, uintN argc, jsval *vp);
static JSBool ShipPatrolReportIn(JSContext *context, uintN argc, jsval *vp);
static JSBool ShipRemoveEquipment(JSContext *context, uintN argc, jsval *vp);
static JSBool ShipRestoreSubEntities(JSContext *context, uintN argc, jsval *vp);
static JSBool ShipEquipmentStatus(JSContext *context, uintN argc, jsval *vp);
@ -436,6 +439,7 @@ static JSFunctionSpec sShipMethods[] =
{ "hasRole", ShipHasRole, 1 },
{ "markTargetForFines", ShipMarkTargetForFines, 0 },
{ "offerToEscort", ShipOfferToEscort, 1 },
{ "patrolReportIn", ShipPatrolReportIn, 1},
{ "performAttack", ShipPerformAttack, 0 },
{ "performCollect", ShipPerformCollect, 0 },
{ "performEscort", ShipPerformEscort, 0 },
@ -2883,6 +2887,31 @@ static JSBool ShipRequestHelpFromGroup(JSContext *context, uintN argc, jsval *vp
}
static JSBool ShipPatrolReportIn(JSContext *context, uintN argc, jsval *vp)
{
OOJS_PROFILE_ENTER
ShipEntity *thisEnt = nil;
ShipEntity *target = nil;
GET_THIS_SHIP(thisEnt);
if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))))
{
OOJSReportBadArguments(context, @"Ship", @"addDefenseTarget", 1U, OOJS_ARGV, nil, @"target");
return NO;
}
if ([target isStation])
{
StationEntity *station = (StationEntity*)station;
[station acceptPatrolReportFrom:thisEnt];
}
OOJS_RETURN_VOID;
OOJS_PROFILE_EXIT
}
static JSBool ShipMarkTargetForFines(JSContext *context, uintN argc, jsval *vp)
{
OOJS_PROFILE_ENTER