Skip to content

Commit

Permalink
Prioritise craft recipes
Browse files Browse the repository at this point in the history
When multiple recipes are applicable, the recipes are prioritised in this order:
toolrepair < shapeless with groups < shapeless < shaped with groups < shaped
For cooking and fuel, items are prioritised over item groups
  • Loading branch information
HybridDog authored and SmallJoker committed May 20, 2019
1 parent 1604b94 commit 12e3d3d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 15 deletions.
54 changes: 39 additions & 15 deletions src/craftdef.cpp
Expand Up @@ -432,7 +432,13 @@ void CraftDefinitionShaped::initHash(IGameDef *gamedef)
break;
}
}
hash_type = has_group ? CRAFT_HASH_TYPE_COUNT : CRAFT_HASH_TYPE_ITEM_NAMES;
if (has_group) {
hash_type = CRAFT_HASH_TYPE_COUNT;
priority = SHAPED_AND_GROUPS;
} else {
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
priority = SHAPED;
}
}

std::string CraftDefinitionShaped::dump() const
Expand Down Expand Up @@ -543,7 +549,13 @@ void CraftDefinitionShapeless::initHash(IGameDef *gamedef)
break;
}
}
hash_type = has_group ? CRAFT_HASH_TYPE_COUNT : CRAFT_HASH_TYPE_ITEM_NAMES;
if (has_group) {
hash_type = CRAFT_HASH_TYPE_COUNT;
priority = SHAPELESS_AND_GROUPS;
} else {
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
priority = SHAPELESS;
}
}

std::string CraftDefinitionShapeless::dump() const
Expand Down Expand Up @@ -723,10 +735,13 @@ void CraftDefinitionCooking::initHash(IGameDef *gamedef)
hash_inited = true;
recipe_name = craftGetItemName(recipe, gamedef);

if (isGroupRecipeStr(recipe_name))
if (isGroupRecipeStr(recipe_name)) {
hash_type = CRAFT_HASH_TYPE_COUNT;
else
priority = SHAPELESS_AND_GROUPS;
} else {
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
priority = SHAPELESS;
}
}

std::string CraftDefinitionCooking::dump() const
Expand Down Expand Up @@ -813,10 +828,13 @@ void CraftDefinitionFuel::initHash(IGameDef *gamedef)
hash_inited = true;
recipe_name = craftGetItemName(recipe, gamedef);

if (isGroupRecipeStr(recipe_name))
if (isGroupRecipeStr(recipe_name)) {
hash_type = CRAFT_HASH_TYPE_COUNT;
else
priority = SHAPELESS_AND_GROUPS;
} else {
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
priority = SHAPELESS;
}
}

std::string CraftDefinitionFuel::dump() const
Expand Down Expand Up @@ -867,7 +885,11 @@ class CCraftDefManager: public IWritableCraftDefManager
input_names = craftGetItemNames(input.items, gamedef);
std::sort(input_names.begin(), input_names.end());

// Try hash types with increasing collision rate, and return if found.
// Try hash types with increasing collision rate
// while remembering the latest, highest priority recipe.
CraftDefinition::RecipePriority priority_best =
CraftDefinition::NO_RECIPE;
CraftDefinition *def_best = nullptr;
for (int type = 0; type <= craft_hash_type_max; type++) {
u64 hash = getHashForGrid((CraftHashType) type, input_names);

Expand All @@ -890,7 +912,9 @@ class CCraftDefManager: public IWritableCraftDefManager
/*errorstream << "Checking " << input.dump() << std::endl
<< " against " << def->dump() << std::endl;*/

if (def->check(input, gamedef)) {
CraftDefinition::RecipePriority priority = def->getPriority();
if (priority > priority_best
&& def->check(input, gamedef)) {
// Check if the crafted node/item exists
CraftOutput out = def->getOutput(input, gamedef);
ItemStack is;
Expand All @@ -901,17 +925,17 @@ class CCraftDefManager: public IWritableCraftDefManager
continue;
}

// Get output, then decrement input (if requested)
output = out;

if (decrementInput)
def->decrementInput(input, output_replacement, gamedef);
/*errorstream << "Check RETURNS TRUE" << std::endl;*/
return true;
priority_best = priority;
def_best = def;
}
}
}
return false;
if (priority_best == CraftDefinition::NO_RECIPE)
return false;
if (decrementInput)
def_best->decrementInput(input, output_replacement, gamedef);
return true;
}

virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
Expand Down
23 changes: 23 additions & 0 deletions src/craftdef.h
Expand Up @@ -132,6 +132,23 @@ struct CraftReplacements
class CraftDefinition
{
public:
/*
Craft recipe priorities, from low to high
Recipes are searched from latest to first.
If a recipe with higher priority than a previous found one is
encountered, it is selected instead.
*/
enum RecipePriority
{
NO_RECIPE,
TOOLREPAIR,
SHAPELESS_AND_GROUPS,
SHAPELESS,
SHAPED_AND_GROUPS,
SHAPED,
};

CraftDefinition() = default;
virtual ~CraftDefinition() = default;

Expand All @@ -140,6 +157,10 @@ class CraftDefinition

// Checks whether the recipe is applicable
virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
RecipePriority getPriority() const
{
return priority;
}
// Returns the output structure, meaning depends on crafting method
// The implementation can assume that check(input) returns true
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
Expand All @@ -162,6 +183,7 @@ class CraftDefinition

protected:
CraftHashType hash_type;
RecipePriority priority;
};

/*
Expand Down Expand Up @@ -283,6 +305,7 @@ class CraftDefinitionToolRepair: public CraftDefinition
virtual void initHash(IGameDef *gamedef)
{
hash_type = CRAFT_HASH_TYPE_COUNT;
priority = TOOLREPAIR;
}

virtual std::string dump() const;
Expand Down

0 comments on commit 12e3d3d

Please sign in to comment.