Automatic Ship Design for the AI

Programmers discuss here anything related to FreeOrion programming. Primarily for the developers to discuss.

Moderator: Committer

Message
Author
Morlic
AI Contributor
Posts: 296
Joined: Tue Feb 17, 2015 11:54 am

Automatic Ship Design for the AI

#1 Post by Morlic »

As of the current state, the shipdesigns for the AI must be entered manually. The following patch automates this process for military ships (and adds 2 new troop ships).

Heuristic:
I) check which of the hulls are available for the empire based on tech - manual selection of combat-suitable hulls
II) find the maximum weapon level, standard armor level (i.e. without need of ressources), tank, engine, shields
III) Use only weapons and armor plates in external slots and fill all of these
IV) Use only engine parts, fuel tanks (or none of these) in the internal slots
V) For each available hulls, make all combinations of the following traits:
1. weapon count: 1/4 - 2/3 of the available slots
2. Shield - yes/no?
3. Fill all inner slots with either fuel tanks or improved engines

Yet to do:
-add core slots
-add ressource-based armor
-change heuristic for end-game ships to reduce number of combinations (must have shields, narrow down interval of weapon count)
-delete outdated designs (is there an interface available for this?)
-make restrictions for the lower difficulties (is this really a good idea to have this here anyway? Imo this should be controlled by the tech route the AI at lower difficulties takes)

Possible extensions in the future:
-write heuristic for other ship classes
-Directly calculate the "optimum" setup based on some parameters (i.e. attack-structure-cost ratio, desired internal parts, speed etc.pp) which might be passed and updated dependend on the current situation the AI is in (e.g. facing enemy with MSS through ruins, need more fuel to reach enemy planet, ...). Then only create the best designs for each Hull (possibly even only shipyard/Ressource).
Before doing so, however, the AI's capability of understanding the ressource system, tactical value of speed/fuel and of course also shield-value vs. increased cost should be improved. How does one evaluate the Organic-Structure gain correctly? Etc. pp., so at the moment just adding more designs than needed to be evaluated elsewhere.
Would-be-nice-but-I'm-too-stupid:
-Parse hull info from .txt file once, then store it somewhere. Evaluate usefulness for each task to obtain a hull-list suitable for each ShipType.
-the same for the ship parts.

As part of this patch, each combat hull also receives a new unique name (obviously free to change).
The generated name of the design is finally given by:

[H]-[W]x[nw]-[A][sl]-[nt]

where:
[H] - Class name based on the hull (e.g. "Griffon" for Organic Hull, "Lynx" for standard hull)
[W] - determined by the used weapon, e.g. "L4" for Laser level 4.
[nw] - number of weapon slots used in the design
[A] - determined by used armor, e.h. "Z" for Zortrium plate
[sl] - used shield level, e.g. "0" for no shield, "2" for deflector shield
[nt] - number of fuel tanks used in the design

So we (currently) end up with names like "Comet-L4x1-Z1-1", "Griffon-L4x1-Z0-0" etc. I think the initial part is ok but maybe a better encoding for the internal parts might be nice.


I am aware of the fact that the additional functions I added should probably be moved to a seperate .py file where all kind of these functions should be stored. However, I would like to discuss the general structure of the file ProductionAI.py.
I would suggest to actually move all the addXDesign() to a seperate file. The rating of the designs should probably be moved also to either this file or another one. ProductionAI.py would completely focus on the decision-making part, i.e. what to produce right now from the available options. I suppose for this purpose it only makes sense to move all functions but spentPP() and generateProductionOrders().
The latter one is quite a monster at the moment and I suppose it would be helpful to split this function into multiple. I would go as far as to move all the implementing code to new functions and have generateProductionOrders() be merely a collection of function calls such as

Code: Select all

QueueShipYards()
QueueUniqueBuildings()
QueueShips()
SortQueueByPriority()
which then again are divided further into ColonyShips etc. pp. until we finally arrive at the implementation level which is as abstract and generalized as possible. For example all the checking and looping whether the building is already built repeats. The additional, building-specific conditions would then finally be implemented in its own function and then passed as a function pointer.


PS: I'm having more of a scientific programming background (and non-python) so I'm used to write code relatively quick and dirty just to see if it works and then give the algorithm to a real programmer who then implements it "correctly" in accordance to language specific style guidelines, implementation specific speed etc. pp.
So while I'm trying my best, feel free to point out any issues in the coding style or any horrible non-python stuff I do.

/Edit: Outdated patch removed
Last edited by Morlic on Fri Mar 06, 2015 11:45 pm, edited 1 time in total.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Dilvish
AI Lead and Programmer Emeritus
Posts: 4768
Joined: Sat Sep 22, 2012 6:25 pm

Re: Automatic Ship Design for the AI

#2 Post by Dilvish »

Let me start by noting that it's most excellent to have another contributor working on the AI! :D

It might not be until the weekend that I have a chance to review your code with any thoroughness, but let me go ahead and respond to some of your questions/comments & point out some additional things to keep in mind. Actually, I see I'm quite short on time to even just respond, so I'll just point out a few quick things you might want to start looking at:

This is a very welcome area of advancement. I think you had asked something about what other info could be queried from the interface. This kind of thing is specified by the boost::python wrapper code in the toplevel "python" folder. One of the recent related code changes is that the hull slots can now be queried directly from a hull type (added at Cjkjvfnby's request, I'm not entirely sure if he'll be thrilled or chagrined that you have beat him to the punch with this :lol: ). That is the "slots" property of a HullType, returning a vector of ShipSlotType.

You mentioned the idea of calculating an optimum design based on assessment of weapons & shields, etc. It wasn't clear if you were aware of the code already in place for that kind of assessment-- the ProductionAI.getBestShipRatings routine uses ratings info calculated in AIState to assess the various designs. This currently takes into account things like weapons, shields, structure and the most commonly encountered enemy stats. I think I added a tiny contribution for speed in some cases, but mostly it's just the primary stats currently. The whole rating system is rather experimental/subjective and probably needs some tweaking, and someday we expect to build a framework to more objectively assess and refine the ratings used.

As far as refactoring generateProductionOrders() goes, Cjkjvfnby had recently posted about doing just that, so I think it is at least nominally in the works.

One thing to keep in mind is that your code appears to assume that an empire will have a single best weapon, shield, armor, etc. I would agree that the situation with our current content is very close to that, but probably not close enough to assume it is strictly true even with the current content. That will be a more complicated discussion, though, so I'll have to come back to that later, along with everything else I haven't touched on yet.

To wrap up for now, let me reiterate that I think this patch is a great start on revamping the AI ship design approach-- thanks for getting involved and I look forward to our continued collaboration.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

Morlic
AI Contributor
Posts: 296
Joined: Tue Feb 17, 2015 11:54 am

Re: Automatic Ship Design for the AI

#3 Post by Morlic »

Ok, I guess it makes sense to wait on a statement of Cjkjvfnby and his thoughts and plans on this before I continue to work on this then.

Anyway, the code I posted is merely a start. About the getBestShipRatings() - if I am not mistaken this deals only with existing shipDesigns, i.e. it chooses the "best" buildable design from the existing list. As a consequence, I can not directly use this function to guide the design development. This is why I try to add a number of possible designs that are then later rated by this function in the general decision process. This does however come with the problem that many unneeded designs are created. The final number of shipDesigns in the endgame may be in the order of some thousands without removal of older, unused designs which therefore seems kind of needed in this approach as this may lead to noticeable performance drops late in the game (although the AI in its current state takes ages to reach such a point if ever).

The "ideal" case would be that the rating process takes place before the shipdesign is created. This would then reduce the number of stored ShipDesigns greatly. However, I did not find anything in the current implementation that allows me to do it - all functions I found require the shipDesign at some point.
So I see two choices :
1) Create many unneeded shipdesigns that will never be built but that are needed to find the best design with getBestShipRatings() as in the code I posted. The more designs are stored, the slower it becomes to look for the best design. It might slow down other things as well, I have no idea yet how this stuff is handled in the C++ part, e.g. updating the server, building stuff etc.

2) Write a new assessment function that does not require a shipDesign, i.e. it must have access to all the hull and part stats. Only the most suitable design is then created and used. It probably makes sense to write a dynamic lookup of hull/part stats from the .txt files before going this way. Once this is done, the rewriting of the assessment functions should not be too hard. Finally, it comes down to an optimization problem for the given target function. Again nothing too complicated which probably can be relatively easy and quickly be solved to at least a very good approximation without going through all the possible combinations.

Well, as said - I'm waiting for Cjkjvfnby's perspective on the whole thing first, given he is working on this stuff already. I'll be looking more into the code in the meantime and maybe find some other playing field I'm interested in that is not being worked on currently.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Cjkjvfnby
AI Contributor
Posts: 539
Joined: Tue Jun 24, 2014 9:55 pm

Re: Automatic Ship Design for the AI

#4 Post by Cjkjvfnby »

Morlic wrote:Ok, I guess it makes sense to wait on a statement of Cjkjvfnby and his thoughts and plans on this before I continue to work on this then.
Welcome!

Feel free to continue.

I try to understand what happens in AI code. It is great knot. I try to untie it to independent modules. Don't wait for me :)

Some recommendation about coding:
  • install PyCharm community edition. It is good IDE for python. It also helps with python coding style.
  • put this code to you python path (project dir, but not to AI folder) https://gist.githubusercontent.com/Cjkj ... terface.py You will have autocomplete in IDE.
  • patch from this thread can be useful if you like to check some code in interactive mode.
  • check command arguments to game executable (--ai-path, --resource-dir, --load, --auto-advance-n-turns, --auto-quit)
Feel free to move code to separate modules. Don't forget to add comment to functions.

What OS do you use? Do you checkout from svn or git?
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Dilvish
AI Lead and Programmer Emeritus
Posts: 4768
Joined: Sat Sep 22, 2012 6:25 pm

Re: Automatic Ship Design for the AI

#5 Post by Dilvish »

Morlic wrote:About the getBestShipRatings() - if I am not mistaken this deals only with existing shipDesigns, i.e. it chooses the "best" buildable design from the existing list. As a consequence, I can not directly use this function to guide the design development.
That's why I mentioned it used ratings info calculated in AIState. The key rating info is calculated by AIState.adjust_stats_vs_enemy, no design needed:

Code: Select all

   def adjust_stats_vs_enemy(self, ship_stats, enemy_stats=None ):
        """rate a ship w/r/t a particular enemy, adjusts ship_stats in place
            ship_stats: {'attacks':attacks, 'structure': str, 'shields': sh } 
            enemy stats: None or [ (num1, estats1), (num2, estats2), ]
            estats: {'attacks':attacks, 'shields': sh , structure:str} 
            attacks: {dmg1:count1, dmg2:count2 }
            """
One of the important steps in between getBestShipRatings() and adjust_stats_vs_enemy() is to adjust the basic stats for species bonuses/maluses. We'll probably want to consider both base stats and potential adjusted stats when decided what ship designs to register for consideration during the production cycle.
The final number of shipDesigns in the endgame may be in the order of some thousands without removal of older, unused designs which therefore seems kind of needed in this approach as this may lead to noticeable performance drops late in the game (although the AI in its current state takes ages to reach such a point if ever).
Hopefully it won't need to get so high as that. You wouldn't notice a performance drop now, though, because the AI currently caps how many designs it will consider, relying on a rough ordering of proxy-strengths determined by reverse lookup from the design name, and stopping after considering 200 designs if the most recent one is less than 10% as good as the best so far. Your naming augmentation isn't currently compatible with this, but could be adjusted or perhaps we can work out a better way to manage the designs. In the meantime, if you're testing out your code be sure to look for the line

Code: Select all

            if (try_counter > 200) and (costRating < 0.1* bestCostRating):
and adjust the 200 up to a few thousand or something or probably only a fraction of your designs would actually be getting considered by the AI.

Code: Select all

2) Write a new assessment function that does not require a shipDesign, i.e. it must have access to all the hull and part stats. Only the most suitable design is then created and used. It probably makes sense to write a dynamic lookup of hull/part stats from the .txt files before going this way. Once this is done, the rewriting of the assessment functions should not be too hard.
As noted above, the basic rating function is already available. Rather than reading part stats directly from the text files you should query their values directly from the respective PartType using the foai interface. Those values are fine now for weapons and armor; for shields I've just been using hardcoded values because of some quirks regarding their nominal capacity, but that is about to be fixed up (the actual coding is finished I think, just needing a bit of rework on the content scripts).

Since this post takes up a lot of screen space, I'll point out that Cjkjvfnby has also replied above, to be sure you don't overlook that.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

Morlic
AI Contributor
Posts: 296
Joined: Tue Feb 17, 2015 11:54 am

Re: Automatic Ship Design for the AI

#6 Post by Morlic »

Thanks for the comments and advice, I will look into all of that. Especially all the Python-IDE stuff. Should be helpful.

I'm generally running Windows but have a Linux Distribution available should that ever be needed. I check out from SVN.




Regarding the lookup of the ShipPart stats: Forgive me if I annoy you but I still fail to see a working way with the existing interface. I give you my understanding of the matter so far.

The function adjust_stats_vs_enemy() gets the information I am looking for from the parameter "ship_stats" which again are found by calls such as

Code: Select all

            stats = dict(self.get_weighted_design_stats(designID, species_name))
so unfortunately, it uses a designID once again.

Looking at the interface itself, the info once again is of course easily obtained by the shipdesign which I can't use as discussed. So for the PartType itself, we have

Code: Select all

        class_<PartType, noncopyable>("partType", no_init)
            .add_property("name",               make_function(&PartType::Name,              return_value_policy<copy_const_reference>()))
            .add_property("class",              &PartType::Class)
            .def("productionCost",              &PartType::ProductionCost)
            .def("productionTime",              &PartType::ProductionTime)
            .def("canMountInSlotType",          &PartType::CanMountInSlotType)
        ;
        def("getPartType",                      &GetPartType,                               return_value_policy<reference_existing_object>());
In the C++-Implementation I find

Code: Select all

    ShipPartClass           Class() const           { return m_class; }             ///< returns that class of part that this is.
    const PartTypeStats&    Stats() const           { return m_stats; }             ///< returns how good the part is at its function.  might be weapon or shield strength, or cargo hold capacity
So I want to have "stats" (and maybe "class" dependend on the implementation) and then call it like

Code: Select all

 myShipPart = foAI.getPartTyp("PARTNAME")
value = myShipPart.stats
Which appears not to be possible with the current interface. So first of all update the Interface should be updated by adding the line

Code: Select all

 .add_property("stats",              &PartType::Stats)
in order to allow said call. Then I can use this to get the values for all parts and evaluate the final stats (after going through a very similar procedure for the hulls which also do not allow direct access to the stats as of now).

Am I correct in this or is there another, easier way that I fail to see right now? I actually hoped that I did not need to touch any c++ stuff as this computer is probably unable to handle the compiling. Anyway this seems way more reasonable than parsing the .txt, so yeah.
Hopefully it won't need to get so high as that. You wouldn't notice a performance drop now, though, because the AI currently caps how many designs it will consider, relying on a rough ordering of proxy-strengths determined by reverse lookup from the design name, and stopping after considering 200 designs if the most recent one is less than 10% as good as the best so far. Your naming augmentation isn't currently compatible with this, but could be adjusted or perhaps we can work out a better way to manage the designs.
Yeah, I guess since the problem vanishes after using the improved implementation (i.e. first assessing, then saving only the best design), I will not invest more time than increasing the number as of now.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Dilvish
AI Lead and Programmer Emeritus
Posts: 4768
Joined: Sat Sep 22, 2012 6:25 pm

Re: Automatic Ship Design for the AI

#7 Post by Dilvish »

Morlic wrote:Regarding the lookup of the ShipPart stats: Forgive me if I annoy you but I still fail to see a working way with the existing interface.
Yes, my bad. Fixed as of r7958 (with a minor correction to the example in r7959). Also added empire.availableShipParts and empire.availableShipHulls in r7960. For shipPartTypes, I changed the class attribute to partClass (to avoid conflict with the python reserved word), and added attributes for capacity and mountableSlotTypes. For hullTypes, I added attributes for structure, stealth, fuel (fuel capacity), and starlaneSpeed.

There is an example use in ProductionAI.py, which gives the following type of output:

Code: Select all

Available Hulls: ['SH_BASIC_MEDIUM', 'SH_BASIC_SMALL', 'SH_COLONY_BASE', 'SH_STANDARD']
Available Ship Parts: ['AR_STD_PLATE', 'CO_COLONY_POD', 'CO_OUTPOST_POD', 'DT_DETECTOR_1', 'FU_BASIC_TANK', 'GT_TROOP_POD', 'SR_WEAPON_1_1']
testhull: SH_BASIC_MEDIUM, structure: 10.0 ; stealth: 5.0 ; slots: ['external', 'external', 'internal']
testpart: SR_WEAPON_2_4, class: shortRange ; capacity: 11.0 ; slottypes: ['external']
So, that should let you get all the info you need to make the ship_stats parameter and get a rating. (Keep in mind the admonition about shields and detectors, though -- their capacity will currently return as a zero.) This info is also useful to know what sequence to put the parts in a design -- even though most commonly it's all the external slots followed by internal slots, I'm pretty sure that in some cases they're a bit jumbled (and certainly could be for new hulls)
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Cjkjvfnby
AI Contributor
Posts: 539
Joined: Tue Jun 24, 2014 9:55 pm

Re: Automatic Ship Design for the AI

#8 Post by Cjkjvfnby »

Scrip that dumps designs to csv. You can open it in excel or google docs spreadsheet.
https://gist.github.com/Cjkjvfnby/301d07be8d7f841fba7a
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Automatic Ship Design for the AI

#9 Post by Geoff the Medio »

Cjkjvfnby wrote:Scrip that dumps designs to csv.
You have "directFireStats" twice in the field names?

User avatar
Cjkjvfnby
AI Contributor
Posts: 539
Joined: Tue Jun 24, 2014 9:55 pm

Re: Automatic Ship Design for the AI

#10 Post by Cjkjvfnby »

Geoff the Medio wrote:
Cjkjvfnby wrote:Scrip that dumps designs to csv.
You have "directFireStats" twice in the field names?
Yes
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

Morlic
AI Contributor
Posts: 296
Joined: Tue Feb 17, 2015 11:54 am

Re: Automatic Ship Design for the AI

#11 Post by Morlic »

There is a missing enum in the interface, patch attached.


I am currently somewhat stuck on a problem I encountered:
Can I somehow check for the resources (or shipyards) that are required to build a part? Currently the AI wants to build all these shiny new things it discovered and doesn't bother with adding new designs for stuff it can actually build... Hardcoding these things is completely out of question.


Oh, I am trying to learn some more python-style stuff. How would I write this piece of code more pythonic?

Code: Select all

availableWeapons = []
for partname in empire.availableShipParts:
    part = fo.getPartType(partname)
    if part.partClass.name == 'ShortRange':
        availableWeapons += part.name
My approach would be something along these lines:

Code: Select all

availableWeapons = [part.name for part in [fo.getPartType(partname) for partname in empire.availableShipParts] if part.partClass.name == 'ShortRange']
Are there better/cleaner/faster ways?
Attachments

[The extension patch has been deactivated and can no longer be displayed.]

If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Automatic Ship Design for the AI

#12 Post by Geoff the Medio »

In C++ "attack" summing code, weapon part classes are PC_SHORT_RANGE, PC_POINT_DEFENSE, PC_MISSILES, and PC_FIGHTERS.

Morlic
AI Contributor
Posts: 296
Joined: Tue Feb 17, 2015 11:54 am

Re: Automatic Ship Design for the AI

#13 Post by Morlic »

Geoff the Medio wrote:In C++ "attack" summing code, weapon part classes are PC_SHORT_RANGE, PC_POINT_DEFENSE, PC_MISSILES, and PC_FIGHTERS.
Ok, I guess it doesn't hurt extending my code to cover all these classes.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Dilvish
AI Lead and Programmer Emeritus
Posts: 4768
Joined: Sat Sep 22, 2012 6:25 pm

Re: Automatic Ship Design for the AI

#14 Post by Dilvish »

Morlic wrote:I am currently somewhat stuck on a problem I encountered:
Can I somehow check for the resources (or shipyards) that are required to build a part? Currently the AI wants to build all these shiny new things it discovered and doesn't bother with adding new designs for stuff it can actually build... Hardcoding these things is completely out of question.
I don't think there currently a way to directly do what you ask, but I think there is a workable approach 'good enough' at least for now. Long term we'd want the AI to be able to determine such requirements and farther below I'll point out the complications I see and mention a couple possible solutions, but first an immediate solution to the problem.

What we do have is a way to assess if a given Ship Design is currently buildable at a given location. (In the relatively near future I'll expose similar functions for the AI for Hulls and Parts which will slightly simplify the following process but it won't really make a big difference.) This is what the current production code does for the predetermined AI designs. Note that the AI code assesses availability on a ResourceGroup basis -- if the AI empire is blockaded and cut in two, your best ships might not be buildable at any location in one of those halves and you still want to be sure to have designs that could be built in that half (they may still be too poor to actually want to build but that can't be decided without knowing what the possibilities are). First assess the buildability of the hulls, using a near-empty design-- nothing but the hull, at each of the locations. Next, at each location and using a hull buildable at that location (if you choose something like an SH_STANDARD it should work for all potential locations and be fine for all parts except core slot parts), go through all the parts and test a design using that hull with only a single part in it to test if that part is buildable at that location. For now, you could streamline this with the knowledge that the only current parts with specialized location requirements are (I think) a few armors and the colony pods. Intermediate term I might add a way to work a little more directly with the location conditions so that we would first build up the set of unique location conditions required by any of the currently available parts & hulls (the number of unique location conditions will be drastically smaller than the total number of parts and hulls) and then just test those conditions once at each location. So that will give you a list of the respective hulls and parts buildable at each location and then you assess more complex ship designs from the available combinations. So that should reasonably handle the buildability assessment, I think. If anyone has other suggestions or comments please speak up.

For the longer term issue of planning where to construct various Shipyards and related Buildings (and I want to reiterate "longer term", we won't try to deal with this anytime very soon), we could first add tags to ship hulls and parts like are used with species, and then use the "AI_TAG_" approach (as is used with various species characteristics) to denote location requirements. Ultimately I would hope that the AI would be able to more flexibly work directly with Conditions, but, except for the limited manner I mentioned above as a possibility, that is a long way off.

Code: Select all

availableWeapons = [part.name for part in [fo.getPartType(partname) for partname in empire.availableShipParts] if part.partClass.name == 'ShortRange']
Are there better/cleaner/faster ways?
Nothing faster comes to mind immediately, but I would think it better to compare the part.partClass directly rather than its name -- the name is somewhat more at risk of changing even if the essence of the partClass does not.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Cjkjvfnby
AI Contributor
Posts: 539
Joined: Tue Jun 24, 2014 9:55 pm

Re: Automatic Ship Design for the AI

#15 Post by Cjkjvfnby »

If you need to filter, you can 'filter'
Here is couple of examples:

Code: Select all

# 1 way: not hardcode, not ordered
WEAPONS = 'shortRange'


def part_is_weaporn(partname):
    # try-except to avoid missing enum
    try:
        return fo.getPartType(partname).partClass.name == WEAPONS
    except AttributeError as e:
        print 'Error for %s: %s' % (partname, e)
        return False

# get unordered! list of ids for weapons (each lunch will produce different order).
# I don't know how to sort it properly
empire = fo.getEmpire()
print filter(part_is_weaporn, empire.availableShipParts)

# 2 way: hardcoded, ordered
# hardcoded weapon names in reverse order, best are first
WEAPONS_IDS = ['SR_WEAPON_%s_%s' % (level, upgrade) for level in '4321' for upgrade in '4321']

# return weapon ids in same order as in WEAPONS_IDS
print filter(set(empire.availableShipParts).__contains__, WEAPONS_IDS)

# in: {'AR_STD_PLATE', 'CO_COLONY_POD', 'CO_OUTPOST_POD', 'DT_DETECTOR_1', 'FU_BASIC_TANK', 'GT_TROOP_POD', 'SR_WEAPON_1_1'}
# out: ['SR_WEAPON_1_1']
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

Post Reply