Add blacklist parameter to CLI
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.
This commit is contained in:
parent
dabf0ff4d7
commit
be44c9c489
|
@ -45,6 +45,15 @@ For best results, it is recommended to specify every world quality you can. Depe
|
||||||
|
|
||||||
You do *not* need to specify buyers to use this solver. The solver will try to maximize profit margin for all available buyers if you do not specify any, which may be very useful if you have no particular objective in mind. Specifying multiple buyers will cause the solver to choose from among them.
|
You do *not* need to specify buyers to use this solver. The solver will try to maximize profit margin for all available buyers if you do not specify any, which may be very useful if you have no particular objective in mind. Specifying multiple buyers will cause the solver to choose from among them.
|
||||||
|
|
||||||
|
### Blacklisting
|
||||||
|
|
||||||
|
If you wish to prohibit certain options, you may do so by passing their exact identifiers (e.g. "Skull.VICTIM\_SKULL") to the blacklist.
|
||||||
|
|
||||||
|
You may wish to blacklist options that:
|
||||||
|
* require a Profession, Ambition, or story you do not have
|
||||||
|
* add Exhaustion
|
||||||
|
* you simply don't have a good source for
|
||||||
|
|
||||||
## Caveats
|
## Caveats
|
||||||
|
|
||||||
The solver aims to maximize profit margin, rather than sheer profit. This is because it may be more profitable to make many smaller skeletons than one massive skeleton.
|
The solver aims to maximize profit margin, rather than sheer profit. This is because it may be more profitable to make many smaller skeletons than one massive skeleton.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import argparse
|
import argparse
|
||||||
import curses
|
import curses
|
||||||
|
|
||||||
|
from .objects.blacklistaction import BlacklistAction
|
||||||
from .objects.enumaction import EnumAction
|
from .objects.enumaction import EnumAction
|
||||||
from .solve import *
|
from .solve import *
|
||||||
|
|
||||||
|
@ -85,6 +86,15 @@ skeleton_parameters.add_argument(
|
||||||
dest='maximum_exhaustion'
|
dest='maximum_exhaustion'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
skeleton_parameters.add_argument(
|
||||||
|
"--blacklist",
|
||||||
|
action=BlacklistAction,
|
||||||
|
nargs='+',
|
||||||
|
help="components, options, or buyers that should not be used by the solver",
|
||||||
|
metavar="Enum.MEMBER",
|
||||||
|
dest='blacklist'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
solver_options = parser.add_argument_group(
|
solver_options = parser.add_argument_group(
|
||||||
"solver options",
|
"solver options",
|
||||||
|
|
|
@ -47,14 +47,14 @@ class Skull(Enum):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Adds Exhaustion
|
# Adds Exhaustion
|
||||||
# ENGRAVED_SKULL = Action(
|
ENGRAVED_SKULL = Action(
|
||||||
# "Affix a Custom-Engraved Skull to your (Skeleton Type)",
|
"Affix a Custom-Engraved Skull to your (Skeleton Type)",
|
||||||
# cost = Cost.ACTION.value + Cost.ENGRAVED_SKULL.value,
|
cost = Cost.ACTION.value + Cost.ENGRAVED_SKULL.value,
|
||||||
# value = 10000,
|
value = 10000,
|
||||||
# skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
# skulls = 1,
|
skulls = 1,
|
||||||
# exhaustion = 2
|
exhaustion = 2
|
||||||
# )
|
)
|
||||||
|
|
||||||
EYELESS_SKULL = Action(
|
EYELESS_SKULL = Action(
|
||||||
"Affix an Eyeless Skull to your (Skeleton Type)",
|
"Affix an Eyeless Skull to your (Skeleton Type)",
|
||||||
|
@ -76,13 +76,13 @@ class Skull(Enum):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Seeking the Name of Mr. Eaten
|
# Seeking the Name of Mr. Eaten
|
||||||
# OWN_SKULL = Action(
|
OWN_SKULL = Action(
|
||||||
# "Duplicate your own skull and affix it here",
|
"Duplicate your own skull and affix it here",
|
||||||
# cost = Cost.ACTION.value + 1000*Cost.BONE_FRAGMENT.value,
|
cost = Cost.ACTION.value + 1000*Cost.BONE_FRAGMENT.value,
|
||||||
# value = -250,
|
value = -250,
|
||||||
# skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
# skulls = 1
|
skulls = 1
|
||||||
# )
|
)
|
||||||
|
|
||||||
PENTAGRAMMIC_SKULL = Action(
|
PENTAGRAMMIC_SKULL = Action(
|
||||||
"Affix a Pentagrammic Skull to your (Skeleton Type)",
|
"Affix a Pentagrammic Skull to your (Skeleton Type)",
|
||||||
|
@ -139,13 +139,13 @@ class Skull(Enum):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Licentiate
|
# Licentiate
|
||||||
# VICTIM_SKULL = Action(
|
VICTIM_SKULL = Action(
|
||||||
# "Cap this with a victim’s skull",
|
"Cap this with a victim’s skull",
|
||||||
# cost = Cost.ACTION.value,
|
cost = Cost.ACTION.value,
|
||||||
# value = 250,
|
value = 250,
|
||||||
# skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
# skulls = 1
|
skulls = 1
|
||||||
# )
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.value)
|
return str(self.value)
|
||||||
|
|
|
@ -20,15 +20,15 @@ class Torso(Enum):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Licentiate
|
# Licentiate
|
||||||
# VICTIM_SKELETON = Action(
|
VICTIM_SKELETON = Action(
|
||||||
# "Supply a skeleton of your own",
|
"Supply a skeleton of your own",
|
||||||
# cost = Cost.ACTION.value,
|
cost = Cost.ACTION.value,
|
||||||
# torso_style = 10,
|
torso_style = 10,
|
||||||
# value = 250,
|
value = 250,
|
||||||
# skulls_needed = 1,
|
skulls_needed = 1,
|
||||||
# arms = 2,
|
arms = 2,
|
||||||
# legs = 2
|
legs = 2
|
||||||
# )
|
)
|
||||||
|
|
||||||
HUMAN_RIBCAGE = Action(
|
HUMAN_RIBCAGE = Action(
|
||||||
"Build on the Human Ribcage",
|
"Build on the Human Ribcage",
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
__all__ = ['BlacklistAction']
|
||||||
|
__author__ = "Jeremy Saklad"
|
||||||
|
|
||||||
|
from argparse import Action
|
||||||
|
|
||||||
|
from ..data.adjustments import Adjustment
|
||||||
|
from ..data.appendages import Appendage
|
||||||
|
from ..data.buyers import Buyer
|
||||||
|
from ..data.declarations import Declaration
|
||||||
|
from ..data.embellishments import Embellishment
|
||||||
|
from ..data.skulls import Skull
|
||||||
|
from ..data.torsos import Torso
|
||||||
|
|
||||||
|
def convert_to_enum(value):
|
||||||
|
split = value.split(".", 1)
|
||||||
|
|
||||||
|
enum = globals()[split[0]]
|
||||||
|
return enum[split[1]]
|
||||||
|
|
||||||
|
class BlacklistAction(Action):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
nargs = kwargs.get('nargs')
|
||||||
|
|
||||||
|
super(BlacklistAction, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
self._nargs = nargs
|
||||||
|
|
||||||
|
def __call__(self, parser, namespace, values, option_string=None):
|
||||||
|
if self._nargs is None or self._nargs == '?':
|
||||||
|
# Convert value back into an Enum
|
||||||
|
enum = convert_to_enum(value)
|
||||||
|
|
||||||
|
setattr(namespace, self.dest, enum)
|
||||||
|
else:
|
||||||
|
# Convert values back into Enums
|
||||||
|
enums = [convert_to_enum(value) for value in values]
|
||||||
|
|
||||||
|
items = getattr(namespace, self.dest, list()) + enums
|
||||||
|
setattr(namespace, self.dest, items)
|
Loading…
Reference in New Issue