Page 1 of 1

route3patrolAI

Posted: Sat Nov 15, 2008 8:54 am
by Commander McLane
Suggestion for a small addition to the default AIs:

Police ships (and hunters) can have either route1patrolAI (the default), which lets them patrol between planet and witchpoint, or route2patrolAI (I'm not sure out of my head, though, whether they actually get this one), which lets them patrol between planet and sun.

What's missing? -- Right, a patrol between witchpoint and sun, which is the common route for sunskimming. No police protection whatsoever on this dangerous route! (I stumbled across this recently, when I looked into sunskimmers.oxp; there is police added between witchpoint and sun, but they will wander off immediatly, because their default route1patrolAI lets them go to the planet.

So I suggest a route3patrolAI for the route between witchpoint and sun, and this should be added to the basic game. For any police/hunter with route1patrolAI who has arrived at the witchpoint, there should be a chance (like 1/3 or 1/4) that he switches to route3patrolAI and starts patroling the sunskimmers' route. Same for any police/hunter who has arrived at the sun with route2patrolAI. And same again for those with route3patrolAI who have arrived at either of their end-points. So the patrol area of police ships and hunters would become the full triangle of main routes.

Obviously this would require the respective changes in the existing patrol AIs as well.

What do you think? A desirable improvement?

Posted: Sat Nov 15, 2008 9:48 am
by Captain Tylor
makes sence to me

Re: route3patrolAI

Posted: Sat Nov 15, 2008 11:59 am
by Eric Walch
Commander McLane wrote:
So I suggest a route3patrolAI for the route between witchpoint and sun, and this should be added to the basic game. For any police/hunter with route1patrolAI who has arrived at the witchpoint, there should be a chance (like 1/3 or 1/4) that he switches to route3patrolAI and starts patroling the sunskimmers' route. Same for any police/hunter who has arrived at the sun with route2patrolAI. And same again for those with route3patrolAI who have arrived at either of their end-points. So the patrol area of police ships and hunters would become the full triangle of main routes.
I suggest to put this in an external oxp rather than Oolite itself. To move all the ships on those routes takes processor time for areas the player hardly visits. With an oxp you add it when on a faster computer. Best thing would be to add it to sunskimmers.oxp.
But with a JS script. With that you can just pick ships with role "police" out of the total ship pool, and than change their AI to a new one. Better than creating like_ships in shipdata. Same as I do with deep_space_pirates. Get plain pirates from the big pirate pool and give them a custom AI script with JS.

Posted: Sat Nov 15, 2008 4:52 pm
by drew
Shouldn't be difficult. I made a modified version of routepatrolAI for my tianve.oxp (pulsar - planet route)

Cheers,

Drew.

Posted: Mon Nov 17, 2008 6:53 am
by Commander McLane
Okay, I think I'll have a chat with Doc Nil about whether this should go into sunskimmers, or should become an OXP of its own.

Posted: Wed Nov 19, 2008 8:28 am
by Commander McLane
Turns out a route3patrolAI isn't needed after all. A clever switching between route1patrolAI (HEAD_FOR_WITCHPOINT, regardless whether the ship is coming from planet or sun) and route2patrolAI (HEAD_FOR_SUN, regardless whether the ship is coming from planet or witchpoint) does the trick, and the ships go full circle. :)

There are, however, some points left:
  1. As police ships don't use injectors normally, a full circle takes an awful lot of time. And most of the time the police will be far away from the player. Oolite is of course non-player-centred, so this isn't a problem as such. However, an OXP with a full-circle-patrol police would have to add additional police ships, as the routes which are to be patrolled are now at least three times as long as just the planet-witchpoint route.
  2. Together with the Oolite-bug already discovered by Eric, which causes all the traffic meant for the planet-sun route to be spawned someplace else altogether, there is another problem which makes it likely that the old route2patrolAI never worked at all. Police ships (Vipers) usually don't have Heat Shields. The AI, however, lets them fly so close to the sun (sun-skimming distance) that they actually never reach their turning-point. They explode from overheating way before their destination. Which means that ever since police ships went with route2patrolAI, their first patrol to the sun was guaranteed to be their last. A true never-come-back mission. Brave (and stupid) GalCops! :shocked:
The first issue can be addressed by a script, of course, adding more police according to the government level.

The second issue can be addressed as well. For the moment I am experimenting with the desired range of the HEAD_FOR_SUN-state. If I make it bigger, the ships will turn earlier and not get into a dangerously close distance to the sun. The other thing is to give all in-system police ships heat shields by default. I think it is sensible that ships that are supposed to patrol next to the sun get a proper shielding, don't you?

Posted: Wed Nov 19, 2008 9:11 am
by Eric Walch
McLane wrote:
The AI, however, lets them fly so close to the sun (sun-skimming distance) that they actually never reach their turning-point. They explode from overheating way before their destination.
There is an easy fix for this. In the next buoyRepair release there will also be escorted ships heading for the sun. The mother has heat shielding but i draw the escorts from the pool of escorts which normally have no heat shielding.
As a luck Oolite 1.71 starts to give an aegis-planet warning, also for the sun. (Like the one that was always given for the main planet). Now I park the escorts at this point and let the mother sunskim. When back the escorts start following their mother. It works well. (Not tested if it still works with the new 1.72. )
So you can let the vipers turn on this message rather than proceed to the sunskim coordinates. (You can look in the grsFuelshipAI.plist of the WIP version you have)

Posted: Wed Nov 19, 2008 9:26 am
by Commander McLane
So the idea is to use the AEGIS_CLOSE_TO_PLANET as turning point, instead of waiting for DESIRED_RANGE_ACHIEVED?

That's nice. Will try it out. Also saves me from the trouble that, when there was an obstacle and the AI comes back from goToWaypointAI, it gets a DESIRED_RANGE_ACHIEVED too early. (Edit: Could get rid of that by inserting a RESTARTED into HEAD_FOR_SUN in route2patrolAI, which sets the sunSkimCoordinates like in the ENTER-state.)

Just for your interest: Currently my AIs look like this: route1patrolAI isn't changed except for the small bugfix with OUTBOUND_LOOT, and adding two additional _DECISION-stated at the endpoints:

Code: Select all

{
    GLOBAL = {ENTER = ("setStateTo: HEAD_FOR_WITCHPOINT"); }; 
    "HEAD_FOR_PLANET" = {
        "ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
        ATTACKED = (setTargetToPrimaryAggressor, groupAttackTarget); 
        "COURSE_OK" = ("setSpeedFactorTo: 0.8", performFlyToRangeFromDestination); 
        "DESIRED_RANGE_ACHIEVED" = ("setStateTo: PLANET_DECISION"); 
        "DOCKING_REQUESTED" = ("setAITo: receiveDockingAI.plist"); 
        ENTER = (setCourseToPlanet, "setDesiredRangeTo: 50000.0", checkCourseToDestination); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INCOMING_MISSILE" = (
            fightOrFleeMissile, 
            setTargetToPrimaryAggressor, 
            deployEscorts, 
            "setStateTo: INBOUND_LOOT", 
            groupAttackTarget
        ); 
        "OFFENCE_COMMITTED" = (
            setTargetToFoundTarget, 
            "markTargetForOffence: 7", 
            deployEscorts, 
            groupAttackTarget
        ); 
        "TARGET_FOUND" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
        UPDATE = (
            setCourseToPlanet, 
            "setDesiredRangeTo: 50000.0", 
            checkCourseToDestination, 
            scanForOffenders, 
            "pauseAI: 10.0"
        ); 
        "WAYPOINT_SET" = ("setAITo: gotoWaypointAI.plist"); 
    }; 
    "HEAD_FOR_WITCHPOINT" = {
        "ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
        ATTACKED = (setTargetToPrimaryAggressor, groupAttackTarget); 
        "COURSE_OK" = ("setSpeedFactorTo: 0.8", performFlyToRangeFromDestination); 
        "DESIRED_RANGE_ACHIEVED" = ("setStateTo: WITCHPOINT_DECISION"); 
        "DOCKING_REQUESTED" = ("setAITo: receiveDockingAI.plist"); 
        ENTER = (setCourseToWitchpoint, checkCourseToDestination); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INCOMING_MISSILE" = (
            fightOrFleeMissile, 
            setTargetToPrimaryAggressor, 
            deployEscorts, 
            "setStateTo: OUTBOUND_LOOT", 
            groupAttackTarget
        ); 
        "OFFENCE_COMMITTED" = (
            setTargetToFoundTarget, 
            "markTargetForOffence: 7", 
            deployEscorts, 
            groupAttackTarget
        ); 
        "TARGET_FOUND" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
        UPDATE = (
            setCourseToWitchpoint, 
            checkCourseToDestination, 
            scanForOffenders, 
            "pauseAI: 10.0"
        ); 
        "WAYPOINT_SET" = ("setAITo: gotoWaypointAI.plist"); 
    }; 
    "HYPER_OUT" = {UPDATE = (performHyperSpaceExit); }; 
    "INBOUND_CHECK" = {
        ENTER = (scanForOffenders, checkForNormalSpace); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INTERSTELLAR_SPACE" = ("setSpeedFactorTo: 1.0", "pauseAI: 15.0", "setStateTo: HYPER_OUT"); 
        "NORMAL_SPACE" = ("setStateTo: HEAD_FOR_PLANET"); 
        "OFFENCE_COMMITTED" = (
            setTargetToFoundTarget, 
            "markTargetForOffence: 7", 
            deployEscorts, 
            groupAttackTarget
        ); 
        RESTARTED = ("setStateTo: INBOUND_LOOT"); 
        "TARGET_FOUND" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
    }; 
    "INBOUND_LOOT" = {
        ATTACKED = (setTargetToPrimaryAggressor, groupAttackTarget); 
        "DOCKING_REQUESTED" = ("setSpeedFactorTo: 0.0", "setAITo: receivingDockingAI.plist"); 
        ENTER = ("setSpeedTo: 0.0", performIdle); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INCOMING_MISSILE" = (
            fightOrFleeMissile, 
            setTargetToPrimaryAggressor, 
            deployEscorts, 
            groupAttackTarget
        ); 
        "NOTHING_FOUND" = ("setStateTo: INBOUND_CHECK"); 
        "TARGET_FOUND" = (setTargetToFoundTarget, "setAITo: collectLootAI.plist"); 
        UPDATE = (scanForLoot, "pauseAI: 10.0"); 
    }; 
    "OUTBOUND_CHECK" = {
        ENTER = (scanForOffenders, checkForNormalSpace); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INTERSTELLAR_SPACE" = ("setSpeedFactorTo: 1.0", "pauseAI: 15.0", "setStateTo: HYPER_OUT"); 
        "NORMAL_SPACE" = ("setStateTo: HEAD_FOR_WITCHPOINT"); 
        "OFFENCE_COMMITTED" = (
            setTargetToFoundTarget, 
            "markTargetForOffence: 7", 
            deployEscorts, 
            groupAttackTarget
        ); 
        RESTARTED = ("setStateTo: OUTBOUND_LOOT"); 
        "TARGET_FOUND" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
    }; 
    "OUTBOUND_LOOT" = {
        ATTACKED = (setTargetToPrimaryAggressor, groupAttackTarget); 
        "DOCKING_REQUESTED" = ("setSpeedFactorTo: 0.0", "setAITo: receivingDockingAI.plist"); 
        ENTER = ("setSpeedTo: 0.0", performIdle); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INCOMING_MISSILE" = (
            fightOrFleeMissile, 
            setTargetToPrimaryAggressor, 
            deployEscorts, 
            groupAttackTarget
        ); 
        "NOTHING_FOUND" = ("setStateTo: OUTBOUND_CHECK"); 
        "TARGET_FOUND" = (setTargetToFoundTarget, "setAITo: collectLootAI.plist"); 
        UPDATE = (scanForLoot, "pauseAI: 10.0"); 
    }; 
    "PLANET_DECISION" = {
        ENTER = ("rollD: 3"); 
        "ROLL_1" = ("setStateTo: HEAD_FOR_WITCHPOINT"); 
        "ROLL_2" = ("setStateTo: HEAD_FOR_WITCHPOINT"); 
        "ROLL_3" = ("switchAITo: route2patrolAI.plist"); 
    }; 
    "WITCHPOINT_DECISION" = {
        ENTER = ("rollD: 3"); 
        "ROLL_1" = ("setStateTo: HEAD_FOR_PLANET"); 
        "ROLL_2" = ("setStateTo: HEAD_FOR_PLANET"); 
        "ROLL_3" = ("switchAITo: route2patrolAI.plist"); 
    }; 
route2PatrolAI has basically become a copy of route1patrolAI, so it now uses goToWaypointAI as well, instead of internal WAYPOINT-states:

Code: Select all

{
    GLOBAL = {ENTER = ("setStateTo: HEAD_FOR_SUN"); }; 
    "HEAD_FOR_PLANET" = {
        "ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
        ATTACKED = (setTargetToPrimaryAggressor, groupAttackTarget); 
        "COURSE_OK" = ("setSpeedFactorTo: 0.8", performFlyToRangeFromDestination); 
        "DESIRED_RANGE_ACHIEVED" = ("setStateTo: PLANET_DECISION"); 
        "DOCKING_REQUESTED" = ("setAITo: receiveDockingAI.plist"); 
        ENTER = (setCourseToPlanet, "setDesiredRangeTo: 50000.0", checkCourseToDestination); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INCOMING_MISSILE" = (
            fightOrFleeMissile, 
            setTargetToPrimaryAggressor, 
            deployEscorts, 
            "setStateTo: INBOUND_LOOT", 
            groupAttackTarget
        ); 
        "OFFENCE_COMMITTED" = (
            setTargetToFoundTarget, 
            "markTargetForOffence: 7", 
            deployEscorts, 
            groupAttackTarget
        ); 
        "TARGET_FOUND" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
        UPDATE = (
            setCourseToPlanet, 
            "setDesiredRangeTo: 50000.0", 
            checkCourseToDestination, 
            scanForOffenders, 
            "pauseAI: 10.0"
        ); 
        "WAYPOINT_SET" = ("setAITo: gotoWaypointAI.plist"); 
    }; 
    "HEAD_FOR_SUN" = {
        "ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
        "APPROACH_COORDINATES" = (
            setDestinationFromCoordinates, 
            "setDesiredRangeTo: 125000", 
            checkCourseToDestination
        ); 
        ATTACKED = (setTargetToPrimaryAggressor, groupAttackTarget); 
        "COURSE_OK" = ("setSpeedFactorTo: 0.80", performFlyToRangeFromDestination); 
        "DESIRED_RANGE_ACHIEVED" = ("setStateTo: SUN_DECISION"); 
        "DOCKING_REQUESTED" = ("setAITo: receiveDockingAI.plist"); 
        ENTER = (setSunSkimStartCoordinates); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INCOMING_MISSILE" = (
            fightOrFleeMissile, 
            setTargetToPrimaryAggressor, 
            deployEscorts, 
            "setStateTo: OUTBOUND_LOOT", 
            groupAttackTarget
        ); 
        "OFFENCE_COMMITTED" = (
            setTargetToFoundTarget, 
            "markTargetForOffence: 7", 
            deployEscorts, 
            groupAttackTarget
        ); 
        RESTARTED = (setSunSkimStartCoordinates); 
        "TARGET_FOUND" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
        UPDATE = (checkCourseToDestination, scanForOffenders, "pauseAI: 10.0"); 
        "WAIT_FOR_SUN" = ("pauseAI: 10.0", setSunSkimStartCoordinates); 
        "WAYPOINT_SET" = ("setAITo: gotoWaypointAI.plist"); 
    }; 
    "HYPER_OUT" = {UPDATE = (performHyperSpaceExit); }; 
    "INBOUND_CHECK" = {
        ENTER = (scanForOffenders, checkForNormalSpace); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INTERSTELLAR_SPACE" = ("setSpeedFactorTo: 1.0", "pauseAI: 15.0", "setStateTo: HYPER_OUT"); 
        "NORMAL_SPACE" = ("setStateTo: HEAD_FOR_PLANET"); 
        "OFFENCE_COMMITTED" = (
            setTargetToFoundTarget, 
            "markTargetForOffence: 7", 
            deployEscorts, 
            groupAttackTarget
        ); 
        RESTARTED = ("setStateTo: INBOUND_LOOT"); 
        "TARGET_FOUND" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
    }; 
    "INBOUND_LOOT" = {
        ATTACKED = (setTargetToPrimaryAggressor, groupAttackTarget); 
        "DOCKING_REQUESTED" = ("setSpeedFactorTo: 0.0", "setAITo: receivingDockingAI.plist"); 
        ENTER = ("setSpeedTo: 0.0", performIdle); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INCOMING_MISSILE" = (
            fightOrFleeMissile, 
            setTargetToPrimaryAggressor, 
            deployEscorts, 
            groupAttackTarget
        ); 
        "NOTHING_FOUND" = ("setStateTo: INBOUND_CHECK"); 
        "TARGET_FOUND" = (setTargetToFoundTarget, "setAITo: collectLootAI.plist"); 
        UPDATE = (scanForLoot, "pauseAI: 10.0"); 
    }; 
    "OUTBOUND_CHECK" = {
        ENTER = (scanForOffenders, checkForNormalSpace); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INTERSTELLAR_SPACE" = ("setSpeedFactorTo: 1.0", "pauseAI: 15.0", "setStateTo: HYPER_OUT"); 
        "NORMAL_SPACE" = ("setStateTo: HEAD_FOR_SUN"); 
        "OFFENCE_COMMITTED" = (
            setTargetToFoundTarget, 
            "markTargetForOffence: 7", 
            deployEscorts, 
            groupAttackTarget
        ); 
        RESTARTED = ("setStateTo: OUTBOUND_LOOT"); 
        "TARGET_FOUND" = (setTargetToFoundTarget, deployEscorts, groupAttackTarget); 
    }; 
    "OUTBOUND_LOOT" = {
        ATTACKED = (setTargetToPrimaryAggressor, groupAttackTarget); 
        "DOCKING_REQUESTED" = ("setSpeedFactorTo: 0.0", "setAITo: receivingDockingAI.plist"); 
        ENTER = ("setSpeedTo: 0.0", performIdle); 
        "GROUP_ATTACK_TARGET" = (setTargetToFoundTarget, "setAITo: interceptAI.plist"); 
        "INCOMING_MISSILE" = (
            fightOrFleeMissile, 
            setTargetToPrimaryAggressor, 
            deployEscorts, 
            groupAttackTarget
        ); 
        "NOTHING_FOUND" = ("setStateTo: OUTBOUND_CHECK"); 
        "TARGET_FOUND" = (setTargetToFoundTarget, "setAITo: collectLootAI.plist"); 
        UPDATE = (scanForLoot, "pauseAI: 10.0"); 
    }; 
    "PLANET_DECISION" = {
        ENTER = ("rollD: 2"); 
        "ROLL_1" = ("setStateTo: HEAD_FOR_SUN"); 
        "ROLL_2" = ("switchAITo: route1patrolAI.plist"); 
    }; 
    "SUN_DECISION" = {
        ENTER = ("rollD: 2"); 
        "ROLL_1" = ("setStateTo: HEAD_FOR_PLANET"); 
        "ROLL_2" = ("switchAITo: route1patrolAI.plist"); 
    }; 
}
Of course in the final OXP I still can put all this in only one AI with a different name, and just give that AI to all police ships (and hunters).

Posted: Wed Nov 19, 2008 10:57 am
by Commander McLane
Hm. When is the AEGIS_CLOSE_TO_PLANET-message sent? In my test the police ships on their way to the sun don't seem to receive it. Neither when they pass the point three times the sun's radius, nor at the point twice the sun's radius.

EDIT: Now I followed my police ship all the way back from the sun to the planet. In the HEAD_FOR_PLANET-state of route2patrolAI it did receive a AEGIS_CLOSE_TO_PLANET and AEGIS_CLOSE_TO_MAIN_PLANET. However it did not receive a DESIRED_RANGE_ACHIEVED, and ended accordingly:
[ai.message.receive]: AI route2patrolAI.plist for GalCop Manta Ray 482 in state 'HEAD_FOR_PLANET' receives message 'APPROACHING_SURFACE'
[planet.collide.shipHit]: DEBUG GalCop Manta Ray 482 collided with planet at (-9423.6,4703.4,526979.4)
:? Definitely not what I was up for!