Games::Lacuna::Client::Governor - A rudimentary configurable module for automation of colony maintenance
my $client = Games::Lacuna::Client->new( cfg_file => $client_config ); my $governor = Games::Lacuna::Client::Governor->new( $client, $governor_config ); $governor->run();
This module implements a rudimentary configurable automaton for maintaining your colonies. Currently, this means automation of upgrade and recycling tasks, but more is planned. The intent is that the automation should be highly configurable, which of course has a cost of a complex configuration file.
This script makes an effort to do its own crude caching of building data in order to minimize the number of RPC calls per invocation. In order to build its cache on first run, this script will call ->view() on every building in your empire. This is expensive. However, after the first run, you can expect the script to run between 1-5 calls per colony. In my tests the script currently makes about 10-20 calls per invocation for an empire with 4 colonies. Running on an hourly cron job, this is acceptable for me.
The building data for any particular building does get refreshed from the server if the script thinks it looks fishy, for example, if it doesn't have any data for it, or if the building's level has changed from what is in the cache.
This module has absolutely no tests associated with it. Use at your own risk. I'm only trying to be helpful. Be kind, please rewind. Etc. Etc.
I depend on Hash::Merge and List::MoreUtils to make the magic happen. Please provide them. I also depend on Games::Lacuna::Client (of course), and Games::Lacuna::Client::PrettyPrint, which was published to this distribution at the same time as me.
Takes exactly 2 arguments, the client object built by Games::Lacuna::Client->new, and a path to a YAML configuration file, described in the "CONFIGURATION FILE" section below.
Runs the governor script according to configuration. Note: old behavior which permitted an argument to force a scan of all buildings has been removed as superfluous and wasteful.
It's a multi-level data structure. See examples/governor.yml.
This is a directory which must be writeable to you. I will write my building cache data here.
This is the maximum permitted age of the cache file, in seconds, before a refresh is required. Note the age of the cache file is updated with each run, so this value may be set high enough that a refresh is never forced. Refreshes are pulled on a per-building basis.
If this is true, Governor goes through the motions but does not actually trigger any actions (such as upgrades, recycling jobs, or pushes). The output shows the actions as they would have taken place. Enabling dry_run disables keepalive behavior.
This is the window of time, in seconds, to try to keep the governor alive if more actions are possible. Basically, if any governed colony's build queue will be empty before the keepalive window expires, the script will not terminate, but will instead sleep and wait for that build queue to empty before once again governing that colony. Setting this to 0 will effectively disable this behavior.
This is the maximum time, in hours, that a push should take (one-way) to be considered a valid candidate. This can be used to prevent pushes between very distant colonies. If not defined, there is no restriction.
This is a proportion, i.e. 0.5 for 50%. It indicates the minimum amount of used cargo space to require before a ship will be sent on a push. E.g., if set to 0.25, a ship must be at least 25% full of its maximum cargo capacity or it will not be considered eligible for a push.
If defined, ship names must match this substring (case-insensitive) to be eligible to be used for pushes. This is an easy to to tell the governor which ships it can utilize.
Not all of the 'verbosity' keys are currently implemented. If any are true, messages of that type are output to standard output.
Messages notifying you that some action has taken place.
Outputs a construction report for each colony (not yet implemented)
Messages which are informational in nature. One level above trace.
Outputs a production report for each colony (not yet implemented)
Outputs a colony resource push analysis (not yet implemented)
Outputs a storage report for each colony (not yet implemented)
Outputs a resource summary for each colony
Too much time on my hands. Outputs an ASCII version of the planet surface map.
Outputs detailed information during various activities.
Outputs an available upgrade report when analyzing upgrades.
Messages that an exceptional condition has been detected.
See "COLONY-SPECIFIC CONFIGURATION". Yes, a 'colony' key should literally exist and contain further hashes.
The next level beneath the 'colony' key should name (by name!) each colony on which the governor should operate, and provide configuration for it. If a _default_ key exists (underscores before and after), this will be applied to all existent colonies unless overridden by colony-specific settings.
(Not yet implemented). Allow downgrading buildings if negative production levels are causing problems. True or false.
A number of hours, decimals allowed.
If the script detects that you will exceed your storage capacity for any given resource in less than this amount of time, a "storage crisis" condition is triggered which forces storage upgrades for your resources.
If the script detects that your amount of this resource will drop to zero in less than this amount of time, a "production crisis" condition is triggered which forces production upgrades for those resources.
If this is true for any particular colony which would otherwise be governed, the governor will skip this colony and perform no actions.
If defined, buildings whose class name appear in this list will never be upgraded by the governor. Classnames are, for example, "MiningMinistry" or "Fusion".
If true, the Planetary Command Center is considered a regular storage building and will be upgraded along with others if storage is needed. Otherwise, it will be ignored for purposes of storage upgrades.
This is a list of identifiers for each of the actions the governor will perform. They are performed in the order specified. Currently implemented values include:
production_crisis, storage_crisis, resource_upgrades, production_upgrades, storage_upgrades, recycling, pushes, ship_report
Note: resource_upgrades performs both a production_upgrades and storage_upgrades priority.
To be implemented are:
repairs, construction, other_upgrades
Note: See the Games::Lacuna::Governor namespace for plugins. Most plugins can be activated by simply including their names in the priority list.
See RESOURCE PROFILE CONFIGURATION below. Is this getting complicated yet? It's really not. Okay, I lie. Maybe it is. I don't know anymore, my brain is a little fried.
Not yet implemented. Will permit deviations from the production profile to pass without action.
Not yet implemented. Will permit deviations from the storage profile to pass without action.
If true, recycling jobs will be triggered even if net waste production on this colony is negative. The default is that this does not happen.
If defined, the governor will reserve this many spots at the end of the build queue for human action (that's you).
This is a string identifier defining how the governor will select which upgrade to perform when an upgrade is desired. One of eight possible values:
The candidate building with the highest building level is selected.
The candidate building which is most effective and producing or storing the resource in question (i.e., does it most) is selected.
The candidate building which will cost the most in terms of resources + waste produced is selected.
The candidate building which will take the longest amount of time to upgrade is selected.
Other way around.
Okay, so this thing looks at your resource profile, as stored under the 'profile' key, to decide how your resources should be managed. If a _default_ key exists here, its settings will apply to all resources (including waste and happiness) unless overridden by more specific settings. Note that storage-related configuration is ignored for happiness. Otherwise, the keys beneath 'profile' are the names of your resources:
food, ore, water, energy, waste, happiness
Attempt to reserve this amount of this resource after any potential builds. Unless this is a crisis, we don't do any upgrades that will bring the resource below this amount in storage.
This is a funny one. This is compared against the 'production' profile setting for all other resources. If, proportionately, we are falling short, this resource is marked for a production upgrade. For example, if all resources were set to production:1, then it would try to make your production of everything per hour (including waste and happiness) the same. If you had all at 1 except for Ore at 3, it would try to produce 3 times more ore than everything else. And so forth.
Like production (above), but for storage. If this is not present, the production value use used instead.
Resources above this level are considered eligible for pushing to more needy colonies. Also used as the amount to leave behind when pushing away due to an overload. This is a proportion between 0 and 1 interpreted as this amount times your capacity.
Resources above this level are considered "overloaded" and will be given priority for pushes to other colonies where space is available. The amount to be shipped away is everything higher than push_above, see above. This is a proportion between 0 and 1 interpreted as this amount times your capacity.
Resources below this level trigger a push request from colonies where this resource is available. This is a proportion between 0 and 1 interpreted as this amount times your capacity.
When a push is requested, the amount we would like to receive is calculated to be enough to bring the amount of resource up to this level. This is a proportion between 0 and 1 interpreted as this amount times your capacity.
For ore and food, you can specify additional parameters for pushing. Keys beneath this are specific types of resource, such as 'anthracite' beneath 'ore', and 'apples' beneath 'food'. You can also use the _default_ key beneath here. For example:
food: specifics: _default_: push_above: 500
Would specify that you want to keep at least 500 of each individual type of food on hand.
If you want to accumulate a specific amount of a specific resource, you can specify that using this option. If you just want to accumulate as much as possible of a specific resource, set this to something obscenely high.
This functions like the regular push_above, but is a scalar amount, rather than a proportion of capacity. I.e., 500 means 500.
Only relevant for waste. If above this level, trigger a recycling job (if possible).
Only relevant for waste. When recycling, leave this amount of waste in storage. I.e., don't recycle it all.
Only relevant for waste. Sets a preference for what we want to recycle waste into. Can be one of:
Always recycle the full amount into this resource
Always split the amount evenly between the three types
Pick whichever resource will take the most time before it fills storage
Pick whichever resource will take the least time before emptying
Pick whichever we have the least in storage
Pick whichever we produce least of
Games::Lacuna::Client, by Steffen Mueller on which this module is dependent.
Of course also, the Lacuna Expanse API docs themselves at http://us1.lacunaexpanse.com/api.
Also, in examples, you've got the example config file in governor.yml, and the example script in governor.pl.
Adam Bellaire, <firstname.lastname@example.org>
Copyright (C) 2010 by Steffen Mueller
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available.