Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign upCraft in the dark #14416
Conversation
sparr
added some commits
Dec 3, 2015
sparr
reviewed
Dec 13, 2015
| @@ -127,6 +131,7 @@ | |||
| "reversible": true, | |||
| "autolearn": true, | |||
| "decomp_learn": 0, | |||
| "flags": ["BLIND_EASY"], | |||
| "components": [ | |||
| [ | |||
| [ "modularvest", 1 ] | |||
This comment has been minimized.
This comment has been minimized.
sparr
Dec 13, 2015
Author
Member
the above recipes are just sliding plates in and out of pockets in the vest. seems very easy to do with your eyes closed.
sparr
reviewed
Dec 13, 2015
| @@ -407,7 +407,7 @@ classes = { | |||
| { name = "cough", rval = nil, args = { "bool", "int" } }, | |||
| { name = "cough", rval = nil, args = { } }, | |||
| { name = "craft", rval = nil, args = { } }, | |||
| { name = "crafting_allowed", rval = "bool", args = { } }, | |||
| { name = "crafting_allowed", rval = "bool", args = { "string" } }, | |||
This comment has been minimized.
This comment has been minimized.
sparr
Dec 13, 2015
Author
Member
I don't think any existing lua code uses this function. I considered removing it, but decided to make it work.
sparr
reviewed
Dec 13, 2015
| bool player::crafting_allowed() | ||
| bool player::crafting_allowed(const std::string rec_name) { | ||
| return crafting_allowed(*recipe_dict[rec_name]); | ||
| } |
This comment has been minimized.
This comment has been minimized.
sparr
Dec 13, 2015
Author
Member
this overload allows the lua binding to crafting_allowed() to work with a string parameter. I wasn't able to figure out how/if it would be possible to inform the lua interface about the recipe type.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
sparr
Dec 13, 2015
Author
Member
@Coolthulhu thanks, I missed that. I've been trying to be better about that. Having fixed it... I hate one-character changes to player.h that require me to recompile the whole damn game :/
sparr
reviewed
Dec 13, 2015
|
|
||
| return (int)total_time; | ||
| } | ||
|
|
||
| bool recipe::has_flag(const std::string &flag_name) const | ||
| { | ||
| return flags.count(flag_name); |
This comment has been minimized.
This comment has been minimized.
sparr
Dec 13, 2015
Author
Member
.count() is the appropriate way to check for membership in a std::set, oddly enough.
BevapDin
reviewed
Dec 13, 2015
| @@ -69,6 +69,8 @@ struct recipe { | |||
| bool hidden; | |||
| }; | |||
| std::vector<bookdata_t> booksets; | |||
| std::set<std::string> flags; | |||
This comment has been minimized.
This comment has been minimized.
BevapDin
Dec 13, 2015
Contributor
Why not add two proper bools to the class? That would not only be faster, but also safer regarding spelling mistakes (one might accidentally check for a "BLINDEASY" flag).
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Dec 13, 2015
Contributor
If we're going that way, it could be a float instead. That way it could be more granular than just BLIND_EASY/HARD.
This comment has been minimized.
This comment has been minimized.
sparr
Dec 13, 2015
Author
Member
Adding two bools or a float makes this too single-purpose. I anticipate adding more flags to recipes in the future. An array of strings is how flags are handled in every other object type we deal with. @kevingranade said he was "leaning toward a flag".
This comment has been minimized.
This comment has been minimized.
BevapDin
Dec 13, 2015
Contributor
Adding two bools or a float makes this too single-purpose.
The flags only have one purpose to start with. Why make it needlessly generic? If someone later needs generic flags (not named at compile time), they can implement it at that point.
I anticipate adding more flags to recipes in the future.
Fine. But those flag most likely require changes to the code anyway, adding another member and the code to load it from JSON doesn't matter much.
An array of strings is how flags are handled in every other object type we deal with.
The project used to store raw enums in the saves, that wasn't a good approach, but it was commonly used, so I'm leaning towards storing flags as set of strings being cargo cult. Besides: there are several instances where it's done differently: monster type flags use a bitset, which is essentially a vector of bools. Several other types have bool members that act as flags.
he was "leaning toward a flag".
A member bool flag; is a flag.
This comment has been minimized.
This comment has been minimized.
sparr
Dec 13, 2015
Author
Member
the monster type flags as a bitset is only an internal represenation. they are still an array of strings in the monster definition (the json). they were promoted to a bitset for efficiency reasons, iirc.
Please don't respond to my short quote from kevin, got read the actual linked discussion where it is in context.
This comment has been minimized.
This comment has been minimized.
kevingranade
Dec 14, 2015
Member
The reason to use a bitset instead of a set of strings is if the code doing the lookup is performance critical, but this requires the code to maintain a mapping of strings to numeric values, so it should only be done if necessary.
This comment has been minimized.
This comment has been minimized.
If both require the same skill level and only differ by crafting speed, they aren't really different. |
This comment has been minimized.
This comment has been minimized.
|
@Coolthulhu Do you think perhaps _EASY should have a lower skill penalty in addition to not having a speed penalty? |
This comment has been minimized.
This comment has been minimized.
|
Speed penalty should be there, but skill penalty seems quite tough early on (when it matters the most). I'd change it to just speed penalty for easy, but speed and skill penalty for hard. |
This comment has been minimized.
This comment has been minimized.
|
The very first filter I applied when choosing recipes was to exclude anything that requires a tool ("tools" or "qualities" in the json). That means no stick sharpening or water boiling. That might have been too strong of a filter, but kevin suggested we start small and expand the whitelist later. Just a speed penalty for easy seems... not like what I had in mind. There are definitely things that I'm good at that I can do just as fast with my eyes closed. Maybe easy and hard both have a speed penalty, but the penalty falls off with extra skill faster for easy? so at skill+0 they are both 25% speed, at skill+2 easy is 100% speed and hard is 50% speed, and you have to get all the way to skill+6 for hard to be 100% speed. |
This comment has been minimized.
This comment has been minimized.
|
I've modified what BLIND_EASY and BLIND_HARD mean. BLIND_EASY allows crafting in the dark with no extra skill. There's a speed penalty, down to 25% speed in pitch black, with no extra skill. +2 skill eliminates the penalty. BLIND_HARD requires 2 extra skill to craft in the dark. There's a speed penalty, down to 25% speed in pitch black, with the minimum 2 extra skill. +8 skill eliminates the penalty. @Coolthulhu how does that sound? |
Coolthulhu
reviewed
Dec 13, 2015
| // 100% speed in well lit area at skill+2 | ||
| // 25% speed in pitch black at skill+2 | ||
| // skill+8 removes speed penalty | ||
| return 1.0f - (darkness / (7.0f/0.75f)) * std::max(0, 8 - exceeds_recipe_requirements(rec)) / 6.0f; |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
sparr
Dec 13, 2015
Author
Member
maybe I should move that line out to a helper, since it's used in both conditions with different constants. would be easier to document/explain there.
This comment has been minimized.
This comment has been minimized.
|
Looks OK, but I still think it would be much better to split it into per-item values. That way there could be no penalty for stuff like cooking meat, boiling water on hotplate (it just sits there, no action required) or for turning bandana into a blindfold. |
This comment has been minimized.
This comment has been minimized.
|
I think providing an int and a float gives too much flexibility and too little consistency. I don't want to see a thousand different combinations of values there for different items added by different people. This goes with a discussion I was having with @kevingranade recently about auditing and simplifying skill checks in general. There are way too many distinct kinds of skill/stat checks in the game already. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
There seems to be a slight confusion: I'm not against flags, I'm against implementing them as big old chunk of What exactly do you gain by storing them as set of strings instead of dedicated bool members? Using members has advantages:
For example: somebody may implement a new item type feature and may choose to use the flag "CHARGE" to trigger this feature. But that flag is already used by the charger gun, so charger guns automatically have the new feature and all items with the new feature are automatically chargers guns. With generic flag sets, the conflict can only be detected at run time by carefully testing the item. With bool members, one would get this at compile time, or even earlier while adding the new member. I'm also not opposed to loading this from a JSON array (and not from several JSON members), in fact this might even be better as it allows checking of the provided flags: for( auto &f : jobj.get_flags( "flags" ) ) {
if( f == "a" ) {
obj.a = true;
} else if( f == "b" ) {
...
} else {
jobj.throw_error( "unknown flag: " + f );
}
}Adding new flags only requires adding two new lines here: } else if( f == "new_flag" ) {
obj.new_flag = true;and a declaration in the class. Neither this PR, nor the linked one requires a generic Btw. and totally unrelated: you need to document the new flags and their meaning in doc/JSON_INFO.md. |
This comment has been minimized.
This comment has been minimized.
Less pollution of the struct. The ability to add new flags without modifying the C++ code at all. We don't currently have much in the way of complex lua mods, but hopefully we will some day. Consistency with all of the other data types that store sets of flags. AFAIK they all started as a set of strings, and that's why the json get_tags function exists. Unless I'm mistaken, the way flags have worked in this project is they start as a set of strings, then string mapped to ints with an enum, then a bitfield, as the list of flags gets longer and/or the performance of the functions becomes more important. |
sparr
added some commits
Dec 14, 2015
sparr
changed the title
Craft in the dark [WIP][CR]
Craft in the dark
Dec 17, 2015
kevingranade
reviewed
Dec 18, 2015
| @@ -231,7 +263,8 @@ void player::craft() | |||
| int batch_size = 0; | |||
| const recipe *rec = select_crafting_recipe( batch_size ); | |||
| if (rec) { | |||
| if ( crafting_allowed() ) { | |||
| if ( crafting_allowed( *rec ) ) | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
sparr
Dec 18, 2015
Author
Member
because I can't figure out a reasonable process to astyle just one block of code. when I run astyle on a block, the rules work differently than running it on the whole file, and when I run it on the whole file it takes forever to cherry pick my block for committing.
This comment has been minimized.
This comment has been minimized.
kevingranade
via email
Dec 19, 2015
Member
sparr
added some commits
Dec 18, 2015
This comment has been minimized.
This comment has been minimized.
|
What's happening with this pr? I'd love to be able to sensibly craft some
|
This comment has been minimized.
This comment has been minimized.
|
Mostly just me being on vacation, I'm looking into merging it now. |
kevingranade
merged commit 4049aef
into
CleverRaven:master
Jan 6, 2016
1 check failed
This comment has been minimized.
This comment has been minimized.
|
"1 check failed" That looks ominous... Enjoy your vacation, don't worry about us, man. |
This comment has been minimized.
This comment has been minimized.
|
It was just some merge conflicts :)
|
sparr commentedDec 13, 2015
I added the ability to have flags in recipes. Since there are so few, it's just a
std::setfor now. If we start having a lot of them, they can get refactored like all the other entity flags have.I added two new flags to recipes,
BLIND_EASYandBLIND_HARD. Either indicates that it is possible to craft an item in the dark (or blind). Both require a skill level of difficulty+2. The latter indicates a slowdown in crafting speed, from 100% speed at just-light-enough to 33% speed in pitch black. The same applies to disassembly.I added the flags to many recipes. I tried to make sensible decisions about things that seemed like to be trivial or slow to do in the dark.
I modified the crafting gui so that the "can craft?" indicator in the top right redraws as you select different recipes, so some will say "too dark" and some "yes". There's also a new "slow" indicator for
BLIND_HARDrecipes in low light. Also the middle column of the gui has a "Dark crafting?" row with options "Easy" "Hard" "Impossible".I modified a number of crafting and disassembly checks that previously used
fine_detail_vision_mod()so they now uselighting_craft_speed_multiplier(), which should directly mimic their craftability.I modified fine_detail_vision_mod() to return a wider range. The previous behavior was not as useful, mis-documented, and malformed. I do not believe any existing uses of this function will be impacted by this change.
I changed a few crafting functions to refer to specific recipes, due to the above changes' reliance on the skill/difficulty of each recipe.
I've tried to test this in as many ways as I can, but some quirks in the crafting interface and recipe dictionary make it slow going without being able to use the debug menu to learn recipes. Further playtesting is required before this patch can be merged.
closes #14285
closes #14287