Buyer requirements now use helper methods and control flow to increase
readability and compactness.
The main benefit of this is no longer having to declare intermediate variables directly.
This is a work-in-progress, as some buyers have complex formulae that
necessitate more work or additional helper methods to refactor.
Amalgamy, antiquity, menace, and implausibility are now clamped to be
non-negative. This simplifies a number of calculations, eliminates a few
insiduous calculation errors, and reflects the actual game.
This change impacts the output of the program, which previously showed
negative values even though they weren't actually possible.
Declaration requirements now use helper methods and generator
expressions to increase readability and compactness.
Requirements are ordered and grouped by quantity.
The comments on declaration requirements have been removed, as the new
pattern is far easier to read.
This method allows a series of constraints to be applied all at once
using the same enforcement literal, which can substantially improve
readability and writability.
The replacement method, BoolExpression, accepts a
BoundedLinearExpression directly, and uses memoization to reuse Boolean
variables. This technique is unsuitable for other methods, as
constraints need to be applied separately, but in this case it is fine.
The new method is much easier to understand, and far easier to read at
call sites.
Variable names are generated from the expression, rather than being
explicitly specified.
The new subclass, BoneMarketModel, overrides CpModel's methods with
improvements such as default parameters and support for enforcement
literals.
This should allow substantial improvements to the readability of the
solver in the future.
In addition, various lists have been replaced with tuples where
appropriate.
The Adulterine Castle has an option that yields four Withered Tentacles
for just one action.
Cost.WARBLER_SKELETON has been removed, as it is no longer used by
anything.
Inline string expressions are far easier to read, particularly for
complicated strings like the skeleton printer's output.
Care has been taken to ensure that no behavior has been changed in the
process.
Action is now a frozen data class.
All properties of Action now have type hints, and __slots__ are used
for properties without default values (that is, name).
It is possible to skip tails while some are already present. The wiki
had the old name when this was added to the solver, but it has since
been corrected.
This section outlines explicit conformance to Semantic Versioning 2.0.0,
and outlines the public API.
It also introduces a tag pattern for determining whether the solver
reflects the desired state of Fallen London.
The Investment-Minded Ambassador yields 80% of their former secondary
revenue, while the Tentacled Entrepreneur and Teller of Terrors yield
400% of theirs.
Zoological Mania's bonus is now saved upon skeleton declaration,
and used when calculating results rather than being added to value
directly.
Not all buyers benefit from the bonus, so this change better reflects
the actual game.
A crash caused by failing to specify Zoological Mania has been fixed.
Vake skulls now have diminishing returns beyond the first skull.
Menace calculation has been reorganized to accomodate the change.
Vake skulls are no longer capped, as the new scaling has been fully
implemented.
Vake skulls now have scaling implausibility, which is calculated using a
partial sum formula.
Implausibility calculation has been reorganized to accomodate the
change.
Vake skulls now have diminishing returns beyond the first skull, which
are calculated using a partial sum formula similar to joint addition.
Value calculation has been reorganized to accomodate the change.
This option lists enumeration identifiers, along with their string forms
for clarity's sake. This makes it much easier to blacklist things
without reading the source code.
A note about listing has been added to the Blacklisting section of the
README.
A dedicated action has been created for the list command.
This bug would have caused an error if BlacklistAction were used with a
different nargs.
The "verbose" argument no longer has a default specified. Instead, the
code that checks it supplies a default for itself.
The action for "--verbose" has been changed to BooleanOptionalAction,
which adds a negative version that may be useful for overriding
configuration files.
Balmoral Woods costs now take achievable quantities of Time Remaining in
the Woods into account.
Volumes of Collated Research are now acquired using the Übergoat statue
at the Hurlers.
Trembling Amber is now acquired using the Rubbery Men opportunity card.
Configuration files allow common arguments like --shadowy-level and
--blacklist to be saved and referenced rather being typed out each time.
ArgumentParser has been subclassed to allow more freedom when parsing
configuration files.
Blacklisting uses a dedicated action to parse arguments into enumeration
members.
Choices are not provided for this option, as it would utterly overwhelm
the help interface. This means that errors may not be as helpful,
however.
The README has been updated with a small section on blacklisting, how to
do it, and why you may wish to do it.
Options that were previously commented out are now enabled, since the
user can simply blacklist them instead.
EnumAction was erasing nargs before passing it to the superclass
initializer, which broke handling for arguments with consecutive values.
The help text for --desired-buyer has been updated to reflect that you
actually can specify multiple values with a single declaration now.
All scripts are now contained in a package named "bonemarketsolver".
The command-line interface has been moved to __main__.py.
The solver script has been moved to solve.py.
Relative module imports are now used where appropriate.
The invocation method of the CLI has changed: instead of running Python
itself, you can now use "pipenv run bone_market_solver".
The README has been updated to reflect the new usage method.