Page 1 of 2

Thargoid behaviour

Posted: Thu Sep 06, 2007 7:22 am
by Eric Walch
Arexack_Heretic wrote in his readme file for Thorgorn_Treat (releasedate: 22/08/2006):
A small difficulty with scanForThargoid/scanForNonThargoid leads to thargoid-on-thargid agression, hopefully this can be resolved soon. For now I am using multiple copies of the thargoid warship, instead of thargoid(%) to affect frequencies of appearance.
It does not need solving, but the "scanForNonThargoid" just works different than one would expect.

I looked into the sourcecode and saw that it scans all ships within scanner range and filters out those with "SCANCLASS_CARGO", those that are docked and those of with the role starts with "tharg".


And that last is important, it does not look at the "SCANCLASS_THARGOID". Why Giles did it this way is only guessing. Maybe he introduces the scannclass_thargoid after he wrote this part of the program. Or maybe he wanted to introduce the possibility that normal ships could take sides of the thargoids and thargoid ships take the side of the humans. With this mechanisms you could create a normal ship that is not attacked by thargoids as long as the role starts with "tharg".

In the case of "Thorgorn_Treat" most roles start with "tharg" but not all as the name "Thorgon" already suggests.

Also the command "scanForThargoid" doen not look for scannclass but looks only at the role "thargoid". This is more selective than just looking at the prefix "tharg" and will omit more ships in "Thorgorn_Treat " and also the thargoid_carrier.

I already updated the eliteWiki AI-page about these commands.

Posted: Thu Sep 06, 2007 3:34 pm
by JensAyton
I beg to differ. It does need solving.

This is part of a set of bugs that arise from the rather problematic way that roles are handled. For instance, scanForThargoid and various other methods check role string equality (i.e., the entire roles string must be “thargoid” to match), some code checks for substrings, other code checks for prefixes. This all needs to be standardised and unified into a separate object that allows for role checking, getting lists of roles etc. I have the outline for this in my head. There probably ought to be a bug ticket.

Posted: Thu Sep 06, 2007 4:50 pm
by Eric Walch
I beg to differ. It does need solving.
I didn't say it was OK now, I just wanted to give how scanForNonThargoid works in version 1.65. It was just written to accommodate the internal Targoid mission and nothing more. But it can be used if the scripter knows how and what it scans.

The command scanForThargoid checks only for the role thargoid as you say. It does in fact the same as "scanForShipWithRole: targoid". I think it is only used by the targlets to check if they are still in the neighborhood of a mothership. (Not necessarily the one they were launched from)
For an external script it is now impossible to add a thargoid ship with its own role that is found with scanForThargoid. In my opinion this routine should check for scannClass targoid. If one only needs the role thargoid one could always use the scanForShipWithRole.

Posted: Fri Sep 07, 2007 9:09 am
by Commander McLane
Ahruman has also pointed out that scanForNearestShipWithRole: (sic!) in itself is a problematic method, because it checks for role string equality. And this is very bad, because most of the ships in the game have more than one role. Or to be precise: They have been given role-strings with more than one word. That means e.g. that scanForNearestShipWithRole: pirate wouldn't find a single of the original ships. They all can be pirates, yes, but their role-strings look like this:

Code: Select all

hunter pirate trader hermit-ship sunskim-trader oolite-cobra3-alternate

(taken from the cobra3-alternate)
This ship won't be found by scanForNearestShipWithRole: hunter, it won't be found by scanForNearestShipWithRole: trader, it won't be found by scanForNearestShipWithRole: hermit-ship or any of it's roles. The only way to find it is with scanForNearestShipWithRole: hunter pirate trader hermit-ship sunskim-trader oolite-cobra3-alternate, because the complete string has to be exactly the same. And of course a scan like this won't find the python next to the cobra.

And this renders scanForNearestShipWithRole: quite useless if you don't happen to scan for (a) the player or (b) a scripted OXP-ship with one role only. Most of the engine-created ships are simply invisible to this method, as only very few of them have only one single role.

Posted: Fri Sep 07, 2007 12:16 pm
by JensAyton
On further inspection, the system is less broken than it appeared. When a ship is created, its role string is set to the specific role for which it was spawned. However, various bits of code have been written with the assumption that this is not the case, confusing matters.

This also means that if a ship has roles “my-custom-role trader pirate” but is spawned as a pirate, searching for my-custom-role shouldn’t work.

To make it behave more as one would expect, I’m splitting the role concept in two; each ship will have a set of roles, but also a single “primary role” which is the role in which it was created.

scanForNearestShipWithRole: will scan for the primary role. JavaScript scripts will be able to get a list of a ship’s roles and its primary role.

Edit: in most cases, the primary role will be what you want. However, having all roles available could be useful if, say, you have multiple ship types which are traders but belong to a certain faction, or otherwise need to search for a certain subset of traders. The JavaScript model now has attributes roles, roleProbabilities and primaryRole. primaryRole can be changed (but this will not automatically change the scan class, bounty, AI etc.) and the game will contrive to ensure that the current primaryRole is always included in roles.

Searching for thargoids by scan class rather than role makes sense.

Posted: Fri Sep 07, 2007 1:50 pm
by JensAyton
I’m also adding standard tests for common categories of ship, both for internal use and exposed via JavaScript. At this moment, these are:

isPolice: same as scanClass == "CLASS_POLICE" (formerly same as roles == "police" || roles == "interceptor" || roles == "wingman").
isThargoid: same as scanClass == "CLASS_THARGOID".
isTrader: same as primaryRole == "trader" || isPlayer.
isPirate: same as primaryRole == "pirate".

The tests may change if necessary. Having the same test used everywhere is useful. Useful is good.

Posted: Fri Sep 07, 2007 8:45 pm
by davcefai
This may be a silly question but, if the role string is actually a string in memory, could you not look for, for example:

"*irat*" ?

Or even use code from grep to search for "pirate AND sun-skimmer" ?

Posted: Fri Sep 07, 2007 10:36 pm
by JensAyton
You can, but it results in inconsistency because of different tests being used. Also, it turned out that ships created with some methods had the roles string set to a single role, while others kept the entire roles string from the shipdata.plist entry.

Posted: Mon Sep 10, 2007 5:27 pm
by JensAyton
Note: contains preliminary information, etc. I might throw all this out and say “use ship scripts for all your filtering instead.”

New role-related ship AI methods:
  • scanForNearestShipWithPrimaryRole: – new (preferred) name for scanForNearestShipWithRole:.
  • scanForNearestShipHavingRole: – scan based on entire role set rather than primary role.
  • scanForNearestShipWithAnyPrimaryRole: – takes a list of roles (space-separated) and returns the nearest ship with any of them as primary.
  • scanForNearestShipHavingAnyRole: – takes a list of roles (space-separated) and returns the nearest ship with any of them in its role set.
  • scanForNearestShipWithScanClass: – searches for a ship by scan class.
  • scanForNearestShipWithoutPrimaryRole:
  • scanForNearestShipNotHavingRole:
  • scanForNearestShipWithoutAnyPrimaryRole:
  • scanForNearestShipNotHavingAnyRole:
  • scanForNearestShipWithoutScanClass:
Additionally, Eric has pointed out that changing scanForThargoid to look for CLASS_THARGOID rather than (primary) role thargoid changes the behaviour of tharglets, and may have side effects for OXPs, so I’m changing it back. It will thus be equivalent to “scanForNearestShipWithPrimaryRole: thargoid” (and implemented as such), rather than being equivalent to “scanForNearestShipWithScanClass: CLASS_THARGOID”.

Posted: Mon Sep 10, 2007 7:58 pm
by Eric Walch
This ship won't be found by scanForNearestShipWithRole: hunter, it won't be found by scanForNearestShipWithRole: trader, it won't be found by scanForNearestShipWithRole: hermit-ship or any of it's roles. The only way to find it is with scanForNearestShipWithRole: hunter pirate trader hermit-ship sunskim-trader oolite-cobra3-alternate, because the complete string has to be exactly the same. And of course a scan like this won't find the python next to the cobra.
I have seen no problem. The firs time I used scanForNearestShipWithRole was in scanForNearestShipWithRole: EQ_QC_MINE. That mine had a role of: energy-bomb EQ_QC_MINE. It did find him.

I made a small test AI that scanned for the role trader and pirate. When I used addShips: trader (or pirate) he found him. When I waited till the system added a trader he also found him. eg. the system added a boaclass-cruiser (with two roles in shipdata: trader sunskim-trader) Still it found him with scanForNearestShipWithRole : trader.

So in most cases it will work. But as Ahruman said: oolite is not consistent with its roles. Sometimes it depends how things are added. And it could be better with secunary roles. So you can adress a whole series of ships in one call. (I had wanted that for some parts of my OXP)

Posted: Tue Sep 11, 2007 5:09 pm
by Eric Walch
isPolice: same as scanClass == "CLASS_POLICE" (formerly same as roles == "police" || roles == "interceptor" || roles == "wingman").
isThargoid: same as scanClass == "CLASS_THARGOID".
isTrader: same as primaryRole == "trader" || isPlayer.
isPirate: same as primaryRole == "pirate".
That looks very promissing. This together with the new scanForRole functions makes it possible to write more precise AI scripts. There is only one important issue not covered with this: The behavior of pirates to traders with a private role added by an OXP. Now the pirate looks for merchantmen. And this are only ships with role player or trader. If I look for example at the ArmoredTransportsType1.OXP or the Transports.OXP than see I excellent crafted ships that are sometimes selected by the system with role trader, but far the most times the are added by a script wit a private role. This way they are neglected by the pirates. This is probably what a trader pilot wants, but not the author. Why else give those ships an escort when they are never attacked. Looking for a secondary role of trader is also risky as some ships start with both roles trader and pirate in their selections list.

I think the easiest and most flexible way is to add a variable in the shipdata.plist. e.g. the boolean "isTrader". If this one is true than the merchantsmen scan should also find this ship. And the shipbuilder can explicitly define if the ship should be attacked by pirates and the like.

Posted: Wed Sep 12, 2007 3:33 pm
by JensAyton
Having thunk about it, an is_trader flag won’t work because of the whole ships-can-have-multiple-roles thing. I’ll add a new plist, pirate-victim-roles.plist, instead; default will be (player, trader, shuttle), and OXPs will be able to extend it the obvious way.

Posted: Thu Sep 13, 2007 7:13 am
by Commander McLane
Ahruman wrote:
default will be (player, trader, shuttle), and OXPs will be able to extend it the obvious way.
As all existing OXPs containing possible pirate-victims would have to be changed--and that is most likely not going to happen--I'd vote for an "extended default", containing all the existing ships. (Of course somebody would have to look into all their shipdata to find out whether they already have the role "trader" or not.)

Posted: Thu Sep 13, 2007 10:08 am
by JensAyton
Volunteers to be “somebody”? (It will also be necessary to work out which roles relate to trader/victim ships, obviously. Don’t want pirates going after thargorns, orbs, navy ships and stations; that’s the point of having a test in scanForRandomMerchantmen to start with.)

Posted: Thu Sep 13, 2007 10:20 am
by Commander McLane
Ahruman wrote:
(It will also be necessary to work out which roles relate to trader/victim ships, obviously.)
Yes, I didn't point that out again, because I thought it to be obvious.

So the complete sentence would be: I'd vote for an "extended default", containing all the existing ships that are possible pirate-victims (or: make sense as pirate-victims).