Code: Select all
WEAPONS = [fo.shipPartClass.shortRange, fo.shipPartClass.missiles, fo.shipPartClass.fighters, fo.shipPartClass.pointDefense]
Code: Select all
return fo.getPartType(partname).partClass in WEAPONS
Moderator: Committer
Code: Select all
WEAPONS = [fo.shipPartClass.shortRange, fo.shipPartClass.missiles, fo.shipPartClass.fighters, fo.shipPartClass.pointDefense]
Code: Select all
return fo.getPartType(partname).partClass in WEAPONS
I think that workaround should do.Dilvish wrote: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.
Makes sense, I will do that.Dilvish wrote: 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.
Cjkjvfnby wrote: If you need to filter, you can 'filter'
I found the "filter" function but read somewhere that "filter" is considered (somewhat) bad Python style and list comprehension would be preferable from a style point of view:Dilvish wrote: I like Cjkjfnby's filter approach #1.
Now obviously the question would be whether or not the expression is considered "simple" or if it is already "complex" considering the fact that it is basically a double list comprehension. The advantage in this approach obviously is that it fits into a single line for a relatively simple task which is rather self-explanatory by context.If the expression is simple enough that it can be expressed with a list comprehension, then the Python community prefers that you use list comprehensions.
Hmm, I suppose the thing that caught my eye the most with the filter # 1 approach was the benefit of using the part_is_weapon() test function, which allows the embedded try:except. FO is still alpha stage and periodically buggy. If empire.availableShipParts somehow gave an invalid partname the plain list comprehension approach would likely crash. Of course, the part_is_weapon() test function could be used in a single-level list comprehension instead of being used with filter(). I'm far from a python style expert myself; what you quoted sounds sensible but let's see what Cjkjvfnby has to say as well, he's a bit more focused on that sort of thing than I am.Morlic wrote:Now obviously the question would be whether or not the expression is considered "simple" or if it is already "complex" considering the fact that it is basically a double list comprehension.
If you have lambda in filter, list comprehension will be better.Morlic wrote:Dilvish wrote: I found the "filter" function but read somewhere that "filter" is considered (somewhat) bad Python style and list comprehension would be preferable from a style point of view:
[The extension patch has been deactivated and can no longer be displayed.]
For combat ships, at least, as we've discussed there is rating evaluation done currently in the AIstate code, and I indicated I thought you ought to use that. Are you meaning you want to relocate that code here? Could you elaborate on just what you mean, and why?Morlic wrote:I would like to never evaluate a design outside of this framework.
It is sounding to me like you mean creation time of the Design. I see ratings as too dynamic to simply calculate at creation and then leave fixed. Ratings (at least combat ratings) depend a lot on the opponent being faced. Right now the AI just has the beginnings of code to deal with this, tracking the enemy designs encountered, choosing one of those as representative of current enemy forces, and rating its own designs in light of that. There are a number of ways that can be further augmented; such as considering the defenses of enemy planets as well as ships, perhaps building a mix of different designs optimized for different types of targets. Those different combat purposes could still be handled as different subclasses in your framework, but I think it highlights he dynamic nature of ratings. Another example would be that the value of armor in troopship ratings should take into account whether or not enemies have researched the various levels of Mine technology (right now the AI just automatically starts using armored troops at later stages, but it would be nice for it to be a more nuanced decision)...So any rating of the design should be directly done at creation time.
Someday (I think in the not too distant future) those parts will indicate their correct base capacity. Trying to determine it from TestDesigns won't really work because the ships actually have to be made to read off the correct values for these types. Also, species can affect the result, and the hull can too (at least currently for detection). I suggest for now you just hardcode it. Species AI tags for detection will also need to be added, as has been done for Weapons, Shields, etc.Any idea on how to read out the effects of the "capacity = 0" part stuff like detectors? I guess I could once again make a workaround using the TestDesigns of these parts which exist anyway for the resource-requirements... Still wondering if there is a more reasonable approach available at the moment.
Yes, I found and at least partially used the code there. Plans are to move anything related to assessing a ship(design) to this new module. First, this is for obvious structuring of the code. If I want to deal with shipdesigns, I want to look at a single module and not at 3 of them.Dilvish wrote:For combat ships, at least, as we've discussed there is rating evaluation done currently in the AIstate code, and I indicated I thought you ought to use that. Are you meaning you want to relocate that code here? Could you elaborate on just what you mean, and why?
I only meant evaluating at design time as right now when building a new ship, the AI rates existing designs, then chooses the best. With the new framework, it should specify its needs, get a design and then work with what it got. If it decides the design is good enough, it says "addDesign()", otherwise it may ask for different design specifications or decide not to build a ship right now. It would not query existing designs.It is sounding to me like you mean creation time of the Design. I see ratings as too dynamic to simply calculate at creation and then leave fixed. Ratings (at least combat ratings) depend a lot on the opponent being faced. Right now the AI just has the beginnings of code to deal with this, tracking the enemy designs encountered, choosing one of those as representative of current enemy forces, and rating its own designs in light of that. There are a number of ways that can be further augmented; such as considering the defenses of enemy planets as well as ships, perhaps building a mix of different designs optimized for different types of targets. Those different combat purposes could still be handled as different subclasses in your framework, but I think it highlights he dynamic nature of ratings. Another example would be that the value of armor in troopship ratings should take into account whether or not enemies have researched the various levels of Mine technology (right now the AI just automatically starts using armored troops at later stages, but it would be nice for it to be a more nuanced decision).
Code: Select all
basicMilitaryDesign = AIShipDesign_Military()
basicMilitaryDesign.updateHull(hullname)
basicMilitaryDesign.updateParts(partnamelist)
basicMilitaryDesign.updateSpecies(speciesname)
rating = basicMilitaryDesign.evaluate()
Code: Select all
enemy = Enemy("shields",4,"averageWeaponStrength",7)
basicMilitaryDesign.updateEnemy(enemy)
Code: Select all
enemy2 = Enemy("mineLevel",2,"TargetPlanet",pid)
troopDesignVsMines = AIShipDesign_Trooper()
troopDesignVsMines.updateEnemy(enemy2)
designID,planetID = getBestDesign(basicTroopDesignVsMines)
Code: Select all
rating = self.troops / self.productionCost
Code: Select all
limitingRequirements = Requirements("minFuel",5,"maxProductionTime",6,"maxProductionCost",PPperTurn*6)
myDesign.updateRequirements(limitingRequirements)
getBestDesign(myDesign)
Sure, now that I see you're structuring this a module focused on all aspects of ShipDesigns, it's is a sensible place for at least the ShipDesigns portion of the ratings code (which is most of it). Keep in mind, you'll also need to adjust the AI state code to the functions in your new module then.Morlic wrote:Plans are to move anything related to assessing a ship(design) to this new module.
Hmm, it sounds like you're using the term 'it' to refer to some portions of the AI but not others, which makes it harder to understand your intent. I am most confident that you mean that the production portion of the AI would request a design from your module without caring whether it was a preexisting design or not. Looking at your code, I see that the ShipDesigns module does not appear to decide at any point whether or not the (hull, parts) combo it recommends corresponds an existing ShipDesign, and instead appears to be leaving that issue to the productions code, which seems a bit odd to me. I would think that this follows the same kind of logic as where to locate the ratings code-- that the ShipDesign module would have the code for actually registering the designs via the freeOrionAIInterface. But I guess there is no rush with that. In the meantime though, having the ProductionAI to call into ShipDesign.AddDesign() where the latter essentially just calls back to ProductionAI.AddDesigns(), seems excessively roundabout.I only meant evaluating at design time as right now when building a new ship, the AI rates existing designs, then chooses the best. With the new framework, it should specify its needs, get a design and then work with what it got. If it decides the design is good enough, it says "addDesign()", otherwise it may ask for different design specifications or decide not to build a ship right now. It would not query existing designs.
This approach of having things like planetID, species, and enemy be attributes of the ShipDesign also catches my eye, as opposed to having them simply be passed in to the rating evaluation function. I guess if you are intending for the ShipDesign objects to be very short lived, simply for the duration of a single production decision, then that might be more efficient, but I guess I'll have to think about it more and see better how you envision this ShipDesign module working with the other modules.Once completed, it should be possible to pass any kind of additional information. For example, we could give information about the enemy (some omnipotent struct/class not yet implemented):Code: Select all
enemy = Enemy("shields",4,"averageWeaponStrength",7) basicMilitaryDesign.updateEnemy(enemy)
Code: Select all
local_hulls = updateTestDesignsForShipHulls(location_id)
updateTestDesignsForShipParts(local_hulls)
Code: Select all
if "%s_%s"%(basename,partname) not in testDesignNames
Code: Select all
if not any ["%s_%s_%s"%(basename,partname, hullname) in testDesignNames for hullname in local_hulls]
Code: Select all
mutual_slot_types = set(part.mountableSlotTypes).intersection(slotlist)
if mutual_slot_types:
slotIndex = slotlist.index(mutual_slot_types[0])
else:
continue
partlist[slotIndex] = part.name
print "Partlist for Test Design %s: "%(designName),partlist
As of he current code state, yes.Dilvish wrote:
Hmm, it sounds like you're using the term 'it' to refer to some portions of the AI but not others, which makes it harder to understand your intent. I am most confident that you mean that the production portion of the AI would request a design from your module without caring whether it was a preexisting design or not.
Yeah, see ToDo list. It is only a very lazy implementation so I can care about other stuff for now and do not have to modify the current ProductionAI code. Of course this functionality is to be moved (or reimplemented) in the ShipDesign module. At least the code has the correct functionality instead of just "pass"Looking at your code, I see that the ShipDesigns module does not appear to decide at any point whether or not the (hull, parts) combo it recommends corresponds an existing ShipDesign, and instead appears to be leaving that issue to the productions code, which seems a bit odd to me. I would think that this follows the same kind of logic as where to locate the ratings code-- that the ShipDesign module would have the code for actually registering the designs via the freeOrionAIInterface. But I guess there is no rush with that. In the meantime though, having the ProductionAI to call into ShipDesign.AddDesign() where the latter essentially just calls back to ProductionAI.AddDesigns(), seems excessively roundabout.
If we make sure that also in the future we will always deal with the design process at one particular place, I guess an approach likeThis approach of having things like planetID, species, and enemy be attributes of the ShipDesign also catches my eye, as opposed to having them simply be passed in to the rating evaluation function. I guess if you are intending for the ShipDesign objects to be very short lived, simply for the duration of a single production decision, then that might be more efficient, but I guess I'll have to think about it more and see better how you envision this ShipDesign module working with the other modules.
Code: Select all
def ratingFunction(self,**kwargs):
planetID,species,enemy,requirements,stuff1,stuff2,stuff3,stuff4 = self.interpret(kwargs)
(...)
Code: Select all
availableHulls = [hull for hull in empire.availableShipHulls if canBuildHullOnPlanet(hull,planetID)]
Code: Select all
shields = [part for part in self.parts if part.partClass in SHIELDS]
if len(shields) == 1:
self.shields = shields[0].capacity
else:
self.shields = 0
It looks to me like the approach I outlined above is totally in line with my previous statement about not assuming there is a single best weapon, shield, armor, etc., partly because this approach checks the issue location-by-location, and partly because it allows for multiple best parts in each category (a max capacity best and a max capacity/cost best, which are not always the same). If you think there is any notable way that the approach fails to identify an important aspect/kind of best part (at least for weapons and armor), then please let's discuss that more. It could be that the extra filtering won't be absolutely needed, but I suspect it's likely to be helpful on many machines.Regarding the redundant parts: We surely can add additional filters. I am not sure we always want to use them (you convinced me previously in this thread about not having a really best weapon etc.).
If you have something you want to propose certainly feel free to post it. Currently the design names have a small bit of functionality in (at least potentially) sorting & filtering designs to be checked. That will probably not be done in this new framework, and so trying to make your proposal compatible with that would probably be wasted effort. Is there any particular reason to rush to change the naming?Cjkjvfnby wrote:If you both don't mind I will make function to create design name/description based on parts and use it for current code.
In any case it need to be done and this can be commited right now without waiting whole framework.