Major updates to the crafting algo.
* Update crafting algo. to favor highest output recipes for making items, and to be more flexible about trying a variety of recipes if some one recipe doesn't work. * Modify crafting algo. to allow crafting of "gatherable" items. * Update logger to support indent/outdent for clearer formatting * Convert IC2 Forge Hammer / Cutter recipes to treat them as tools
This commit is contained in:
@@ -566,9 +566,9 @@ group: Energy: Transmission
|
||||
|
||||
item: Copper Cable
|
||||
recipe:
|
||||
extras: Cutter
|
||||
input: Copper Plate, Cutter
|
||||
pattern: ... 01. ...
|
||||
tools: Cutter
|
||||
input: Copper Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 2
|
||||
recipe:
|
||||
input: Copper Ingot
|
||||
@@ -607,9 +607,9 @@ group: Energy: Transmission
|
||||
|
||||
item: Gold Cable
|
||||
recipe:
|
||||
extras: Cutter
|
||||
input: Cutter, Gold Plate
|
||||
pattern: ... 10. ...
|
||||
tools: Cutter
|
||||
input: Gold Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 4
|
||||
recipe:
|
||||
input: Gold Ingot
|
||||
@@ -674,9 +674,9 @@ group: Energy: Transmission
|
||||
|
||||
item: Tin Cable
|
||||
recipe:
|
||||
extras: Cutter
|
||||
input: Cutter, Tin Plate
|
||||
pattern: ... 10. ...
|
||||
tools: Cutter
|
||||
input: Tin Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 3
|
||||
recipe:
|
||||
input: Tin Ingot
|
||||
@@ -735,9 +735,9 @@ group: Machine Parts
|
||||
|
||||
item: Bronze Item Casing
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Bronze Plate, Forge Hammer
|
||||
pattern: ... 01. ...
|
||||
tools: Forge Hammer
|
||||
input: Bronze Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 2
|
||||
recipe:
|
||||
input: Bronze Plate
|
||||
@@ -747,9 +747,9 @@ group: Machine Parts
|
||||
|
||||
item: Bronze Plate
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Bronze Ingot, Forge Hammer
|
||||
pattern: ... 01. ...
|
||||
tools: Forge Hammer
|
||||
input: Bronze Ingot
|
||||
pattern: ... .0. ...
|
||||
recipe:
|
||||
input: Bronze Ingot
|
||||
pattern: ... .0. ...
|
||||
@@ -786,9 +786,9 @@ group: Machine Parts
|
||||
|
||||
item: Copper Item Casing
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Copper Plate, Forge Hammer
|
||||
pattern: ... 01. ...
|
||||
tools: Forge Hammer
|
||||
input: Copper Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 2
|
||||
recipe:
|
||||
input: Copper Plate
|
||||
@@ -798,9 +798,9 @@ group: Machine Parts
|
||||
|
||||
item: Copper Plate
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Copper Ingot, Forge Hammer
|
||||
pattern: ... 01. ...
|
||||
tools: Forge Hammer
|
||||
input: Copper Ingot
|
||||
pattern: ... .0. ...
|
||||
recipe:
|
||||
input: Copper Ingot
|
||||
pattern: ... .0. ...
|
||||
@@ -909,9 +909,9 @@ group: Machine Parts
|
||||
|
||||
item: Gold Item Casing
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Forge Hammer, Gold Plate
|
||||
pattern: ... 10. ...
|
||||
tools: Forge Hammer
|
||||
input: Gold Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 2
|
||||
recipe:
|
||||
input: Gold Plate
|
||||
@@ -921,9 +921,9 @@ group: Machine Parts
|
||||
|
||||
item: Gold Plate
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Forge Hammer, Gold Ingot
|
||||
pattern: ... 10. ...
|
||||
tools: Forge Hammer
|
||||
input: Gold Ingot
|
||||
pattern: ... .0. ...
|
||||
recipe:
|
||||
input: Gold Ingot
|
||||
pattern: ... .0. ...
|
||||
@@ -941,9 +941,9 @@ group: Machine Parts
|
||||
|
||||
item: Iron Item Casing
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Forge Hammer, Iron Plate
|
||||
pattern: ... 10. ...
|
||||
tools: Forge Hammer
|
||||
input: Iron Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 2
|
||||
recipe:
|
||||
input: Iron Plate
|
||||
@@ -953,9 +953,9 @@ group: Machine Parts
|
||||
|
||||
item: Iron Plate
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Forge Hammer, Iron Ingot
|
||||
pattern: ... 10. ...
|
||||
tools: Forge Hammer
|
||||
input: Iron Ingot
|
||||
pattern: ... .0. ...
|
||||
recipe:
|
||||
input: Iron Ingot
|
||||
pattern: ... .0. ...
|
||||
@@ -1026,9 +1026,9 @@ group: Machine Parts
|
||||
|
||||
item: Lead Item Casing
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Forge Hammer, Lead Plate
|
||||
pattern: ... 10. ...
|
||||
tools: Forge Hammer
|
||||
input: Lead Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 2
|
||||
recipe:
|
||||
input: Lead Plate
|
||||
@@ -1038,9 +1038,9 @@ group: Machine Parts
|
||||
|
||||
item: Lead Plate
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Forge Hammer, Lead Ingot
|
||||
pattern: ... 10. ...
|
||||
tools: Forge Hammer
|
||||
input: Lead Ingot
|
||||
pattern: ... .0. ...
|
||||
recipe:
|
||||
input: Lead Ingot
|
||||
pattern: ... .0. ...
|
||||
@@ -1230,9 +1230,9 @@ group: Machine Parts
|
||||
|
||||
item: Tin Item Casing
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Forge Hammer, Tin Plate
|
||||
pattern: ... 10. ...
|
||||
tools: Forge Hammer
|
||||
input: Tin Plate
|
||||
pattern: ... .0. ...
|
||||
quantity: 2
|
||||
recipe:
|
||||
input: Tin Plate
|
||||
@@ -1242,9 +1242,9 @@ group: Machine Parts
|
||||
|
||||
item: Tin Plate
|
||||
recipe:
|
||||
extras: Forge Hammer
|
||||
input: Forge Hammer, Tin Ingot
|
||||
pattern: ... 10. ...
|
||||
tools: Forge Hammer
|
||||
input: Tin Ingot
|
||||
pattern: ... .0. ...
|
||||
recipe:
|
||||
input: Tin Ingot
|
||||
pattern: ... .0. ...
|
||||
@@ -1859,31 +1859,6 @@ group: Minerals
|
||||
tools: Furnace
|
||||
|
||||
item: Slag
|
||||
recipe:
|
||||
extras: Reinforced Iron Ingot, Empty Cell
|
||||
input: Compressed Air Cell, Iron Ore
|
||||
pattern: ... .1. .0.
|
||||
tools: Blast Furnace
|
||||
recipe:
|
||||
extras: Reinforced Iron Ingot, Empty Cell
|
||||
input: Compressed Air Cell, Iron Dust
|
||||
pattern: ... .1. .0.
|
||||
tools: Blast Furnace
|
||||
recipe:
|
||||
extras: Reinforced Iron Ingot, Empty Cell
|
||||
input: Compressed Air Cell, Iron Ingot
|
||||
pattern: ... .1. .0.
|
||||
tools: Blast Furnace
|
||||
recipe:
|
||||
extras: Reinforced Iron Ingot, Empty Cell
|
||||
input: Compressed Air Cell, Crushed Iron Ore
|
||||
pattern: ... .1. .0.
|
||||
tools: Blast Furnace
|
||||
recipe:
|
||||
extras: Reinforced Iron Ingot, Empty Cell
|
||||
input: Compressed Air Cell, Purified Crushed Iron Ore
|
||||
pattern: ... .1. .0.
|
||||
tools: Blast Furnace
|
||||
|
||||
item: Steam
|
||||
|
||||
@@ -3135,3 +3110,9 @@ update: Iron Ingot
|
||||
input: Iron Dust, furnace fuel
|
||||
pattern: .0. ... .1.
|
||||
tools: Furnace
|
||||
|
||||
update: Diamond
|
||||
recipe:
|
||||
input: Coal Chunk
|
||||
pattern: ... .0. ...
|
||||
tools: Compressor
|
||||
|
||||
@@ -21,16 +21,23 @@ module.exports = class Logger
|
||||
|
||||
constructor: (options={})->
|
||||
options.level ?= Logger.FATAL
|
||||
@formatText = if options.format? then options.format else "<%= timestamp %> | <%= level %> | <%= message %>"
|
||||
@formatText = options.format
|
||||
@formatText ?= "<%= timestamp %> | <%= level %> | <%= indent %><%= message %>"
|
||||
@level = @_parseLevel options
|
||||
|
||||
@_format = _.template @formatText
|
||||
@_indent = ''
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
indent: ->
|
||||
@_indent += ' '
|
||||
|
||||
log: (level, message)->
|
||||
return unless level.value >= @level.value
|
||||
message = message() if _.isFunction message
|
||||
|
||||
entry = {timestamp:new Date(), level:level, message:message}
|
||||
entry = {timestamp:new Date(), level:level, message:message, indent:@_indent}
|
||||
entry.level ?= @level
|
||||
|
||||
lines = @_formatEntry entry
|
||||
@@ -39,6 +46,9 @@ module.exports = class Logger
|
||||
else
|
||||
console.error(line) for line in lines
|
||||
|
||||
outdent: ->
|
||||
@_indent = @_indent[0...@_indent.length - 4]
|
||||
|
||||
# Log Methods ##################################################################################
|
||||
|
||||
trace: (message)-> @log Logger.TRACE, message
|
||||
@@ -67,6 +77,7 @@ module.exports = class Logger
|
||||
timestamp: "#{entry.timestamp}"
|
||||
level: entry.level.name
|
||||
message: line
|
||||
indent: entry.indent
|
||||
lines.push result.join ''
|
||||
return lines
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ All rights reserved.
|
||||
BaseModel = require './base_model'
|
||||
{Event} = require '../constants'
|
||||
Inventory = require './inventory'
|
||||
ItemSlug = require './item_slug'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -53,14 +54,12 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
@result.addInventory @have
|
||||
|
||||
@steps = {}
|
||||
@_reservedSteps = {}
|
||||
@want.each (stack)=>
|
||||
@_findSteps stack.itemSlug
|
||||
@_findSteps stack.itemSlug, {}, ignoreGatherable:true
|
||||
item = @modPack.findItem stack.itemSlug
|
||||
@need.add item.slug, stack.quantity
|
||||
@_reservedSteps = null
|
||||
|
||||
@steps = _.values @steps
|
||||
@steps = (recipe:recipe for recipeSlug, recipe of @steps)
|
||||
@_resolveNeeds()
|
||||
@_removeExtraSteps()
|
||||
|
||||
@@ -99,38 +98,69 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_addStep: (recipe)->
|
||||
logger.verbose -> "adding step: #{recipe.itemSlug}"
|
||||
@steps[recipe.itemSlug] = recipe:recipe
|
||||
logger.verbose -> "adding step for: #{recipe.slug}"
|
||||
@steps[recipe.slug] = recipe
|
||||
|
||||
_chooseRecipe: (item)->
|
||||
recipes = @modPack.findRecipes item.slug
|
||||
return null unless recipes? and recipes.length > 0
|
||||
return recipes[0]
|
||||
|
||||
_findSteps: (itemSlug)->
|
||||
_findSteps: (itemSlug, parentSteps={})->
|
||||
item = @modPack.findItem itemSlug
|
||||
return unless item?
|
||||
return unless item.isCraftable
|
||||
return if item.isGatherable
|
||||
|
||||
recipe = @_chooseRecipe item
|
||||
ignoreGatherable = @want.hasAtLeast itemSlug, 1
|
||||
if (not item.isGatherable) or ignoreGatherable
|
||||
recipes = @modPack.findRecipes item.slug
|
||||
recipes ?= []
|
||||
|
||||
if parentSteps[item.slug]?
|
||||
logger.verbose -> "found cycle at #{item.slug}"
|
||||
throw new Error 'invalid recipe path'
|
||||
parentSteps[item.slug] = item
|
||||
|
||||
logger.verbose -> "exploring: #{item.slug}"
|
||||
logger.indent()
|
||||
|
||||
currentSteps = _.clone @steps
|
||||
foundValidRecipe = false
|
||||
for i in [0...recipes.length] by 1
|
||||
recipe = recipes[i]
|
||||
logger.verbose -> "trying recipe #{i+1} of #{recipes.length}: #{recipe.slug}"
|
||||
if @steps[recipe.slug]?
|
||||
logger.verbose -> "already accepted this recipe"
|
||||
foundValidRecipe = true
|
||||
break
|
||||
|
||||
try
|
||||
if @includingTools
|
||||
for toolStack in recipe.tools
|
||||
if not @_hasStep toolStack.itemSlug
|
||||
@_findSteps toolStack.itemSlug
|
||||
|
||||
return if @_hasStep item.slug
|
||||
@_reservedSteps[item.slug] = recipe
|
||||
@_findSteps toolStack.itemSlug, parentSteps
|
||||
|
||||
for inputStack in recipe.input
|
||||
@_findSteps inputStack.itemSlug
|
||||
@_findSteps inputStack.itemSlug, parentSteps
|
||||
|
||||
@_addStep recipe
|
||||
foundValidRecipe = true
|
||||
break
|
||||
catch error
|
||||
logger.verbose -> "recipe didn't work out: #{recipe.slug}"
|
||||
if error.message isnt 'invalid recipe path' then throw error
|
||||
@steps = _.clone currentSteps
|
||||
|
||||
delete parentSteps[item.slug]
|
||||
logger.outdent()
|
||||
|
||||
if not (foundValidRecipe or item.isGatherable)
|
||||
logger.verbose -> "could not find a valid recipe for #{item.slug}"
|
||||
throw new Error 'invalid recipe path'
|
||||
|
||||
_hasStep: (itemSlug)->
|
||||
return true if @steps[itemSlug]?
|
||||
return true if @_reservedSteps[itemSlug]?
|
||||
for recipeSlug, recipe of @steps
|
||||
return true if recipe.produces itemSlug
|
||||
return false
|
||||
|
||||
_qualifyItemSlug: (itemSlug)->
|
||||
|
||||
@@ -84,13 +84,9 @@ module.exports = class ModPack extends BaseModel
|
||||
findRecipes: (itemSlug, result=[])->
|
||||
return null unless itemSlug?
|
||||
|
||||
if itemSlug.isQualified
|
||||
mod = @getMod itemSlug.mod
|
||||
if mod? then mod.findRecipes itemSlug, result
|
||||
|
||||
if result.length is 0
|
||||
for mod in @_mods
|
||||
continue unless mod.enabled
|
||||
continue if itemSlug.isQualified and itemSlug.mod isnt mod.slug
|
||||
mod.findRecipes itemSlug, result
|
||||
|
||||
result.sort (a, b)-> Recipe.compareFor a, b, itemSlug
|
||||
|
||||
@@ -7,6 +7,7 @@ All rights reserved.
|
||||
|
||||
BaseModel = require './base_model'
|
||||
Stack = require './stack'
|
||||
StringBuilder = require './string_builder'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -43,7 +44,7 @@ module.exports = class Recipe extends BaseModel
|
||||
aValue = a.getQuantityProducedOf itemSlug
|
||||
bValue = b.getQuantityProducedOf itemSlug
|
||||
if aValue isnt bValue
|
||||
return if aValue < bValue then -1 else +1
|
||||
return if aValue > bValue then -1 else +1
|
||||
|
||||
aValue = a.getInputCount()
|
||||
bValue = b.getInputCount()
|
||||
@@ -102,6 +103,24 @@ module.exports = class Recipe extends BaseModel
|
||||
return true
|
||||
return false
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
getSlug: ->
|
||||
if not @_slug?
|
||||
builder = new StringBuilder
|
||||
builder
|
||||
.loop(@input, delimiter:',', onEach:(b, stack)-> b.push stack.itemSlug.qualified)
|
||||
.onlyIf @tools.length > 0, (b)=>
|
||||
b.push(' + ').loop(@tools, delimiter:',', onEach:(b, stack)-> b.push stack.itemSlug.qualified)
|
||||
.push(' => ')
|
||||
.loop(@output, delimiter:',', onEach:(b, stack)-> b.push stack.itemSlug.qualified)
|
||||
@_slug = builder.toString()
|
||||
|
||||
return @_slug
|
||||
|
||||
Object.defineProperties @prototype,
|
||||
slug: {get:@prototype.getSlug}
|
||||
|
||||
# Object Overrides #############################################################################
|
||||
|
||||
toString: ->
|
||||
|
||||
@@ -45,25 +45,25 @@ describe 'crafting_plan.coffee', ->
|
||||
plan.want.add ItemSlug.slugify 'oak_plank'
|
||||
plan.craft()
|
||||
plan.need.unparse().should.equal 'oak_log'
|
||||
plan.result.unparse().should.equal '4.minecraft__oak_plank'
|
||||
plan.result.unparse().should.equal '4.oak_plank'
|
||||
|
||||
it 'can craft a multi-step recipe', ->
|
||||
plan.want.add ItemSlug.slugify 'crafting_table'
|
||||
plan.craft()
|
||||
plan.need.unparse().should.equal 'oak_log'
|
||||
plan.result.unparse().should.equal 'minecraft__crafting_table'
|
||||
plan.result.unparse().should.equal 'crafting_table'
|
||||
|
||||
it 'can craft a multi-step recipe using tools', ->
|
||||
plan.want.add ItemSlug.slugify 'furnace'
|
||||
plan.craft()
|
||||
plan.need.unparse().should.equal '8.cobblestone'
|
||||
plan.result.unparse().should.equal 'minecraft__furnace'
|
||||
plan.result.unparse().should.equal 'furnace'
|
||||
|
||||
it 'can craft a multi-step recipe re-using tools', ->
|
||||
plan.want.add ItemSlug.slugify 'iron_sword'
|
||||
plan.craft()
|
||||
plan.need.unparse().should.equal '2.furnace_fuel:2.iron_ore:oak_log'
|
||||
plan.result.unparse().should.equal 'minecraft__iron_sword:2.minecraft__oak_plank:3.minecraft__stick'
|
||||
plan.result.unparse().should.equal 'iron_sword:2.oak_plank:3.stick'
|
||||
|
||||
describe 'with building tools', ->
|
||||
|
||||
@@ -72,7 +72,7 @@ describe 'crafting_plan.coffee', ->
|
||||
plan.want.add ItemSlug.slugify 'furnace'
|
||||
plan.craft()
|
||||
plan.need.unparse().should.equal '8.cobblestone:oak_log'
|
||||
plan.result.unparse().should.equal 'minecraft__crafting_table:minecraft__furnace'
|
||||
plan.result.unparse().should.equal 'crafting_table:furnace'
|
||||
|
||||
it 'can craft a multi-step recipe re-using tools', ->
|
||||
plan.includingTools = true
|
||||
@@ -80,5 +80,5 @@ describe 'crafting_plan.coffee', ->
|
||||
plan.craft()
|
||||
|
||||
plan.need.unparse().should.eql '8.cobblestone:2.furnace_fuel:2.iron_ore:2.oak_log'
|
||||
plan.result.unparse().should.equal 'minecraft__crafting_table:minecraft__furnace:' +
|
||||
'minecraft__iron_sword:2.minecraft__oak_plank:3.minecraft__stick'
|
||||
plan.result.unparse().should.equal 'crafting_table:furnace:' +
|
||||
'iron_sword:2.oak_plank:3.stick'
|
||||
|
||||
Reference in New Issue
Block a user