Initial take on crafting algo Mk.III

This commit is contained in:
Andrew Miner
2016-09-25 13:14:42 -07:00
parent c0472b268d
commit 7377559f7b
35 changed files with 1660 additions and 1776 deletions
@@ -5,39 +5,154 @@
# All rights reserved.
#
fixtures = require './fixtures.test'
PlanBuilder = require './plan_builder'
fixtures = require './fixtures'
Inventory = require './inventory'
PlanBuilder = require './plan_builder'
ResourcesEvaluator = require './resources_evaluator'
########################################################################################################################
describe 'plan_builder.coffee', ->
describe.only "PlanBuilder", ->
printPlan = (plan)->
return '' unless plan?
return ((s.recipe.slug.replace(/^.*>.*>/, '') for s in plan.steps;;)).join ' > '
beforeEach ->
@planner = new PlanBuilder new ResourcesEvaluator
@mod = fixtures.createMod()
@want = new Inventory
@have = new Inventory
it 'generates an empty plan for a gatherable item', ->
plans = fixtures.makePlans [1, 'test__oak_wood']
describe "for a gatherable item, creates a plan that", ->
plans.length.should.equal 1
plans[0].length.should.equal 0
beforeEach ->
@oakWood = fixtures.configureOakWood @mod
@want.add @oakWood, 2
@plan = @planner.createPlan @want
it 'can find a multi-step plan', ->
plans = fixtures.makePlans [1, 'test__lever']
it "has no steps at all", ->
@plan.steps.length.should.equal 0
printPlan(plans[0]).should.equal '4 test__oak_planks > 4 test__stick > test__lever'
plans.length.should.equal 1
it "demands the item itself as the input", ->
@plan.need.toString(full:true).should.equal "2 Oak Wood"
it 'can find multiple plans', ->
plans = fixtures.makePlans [1, 'test__iron_ingot']
it "produces the item as the result", ->
@plan.make.toString(full:true).should.equal "2 Oak Wood"
printPlan(plans[0]).should.equal '8 test__charcoal > 8 test__iron_ingot'
printPlan(plans[1]).should.equal '8 test__iron_ingot'
plans.length.should.equal 2
describe "for a single item with a one-step recipe, it creates a plan that", ->
it 'ignores invalid plans', ->
plans = fixtures.makePlans [1, 'test__copper_block']
beforeEach ->
@oakPlank = fixtures.configureOakPlank @mod
@want.add @oakPlank, 63
@plan = @planner.createPlan @want
printPlan(plans[0]).should.equal '8 test__copper_ingot > test__copper_block'
printPlan(plans[1]).should.equal '8 test__charcoal > 8 test__copper_ingot > test__copper_block'
plans.length.should.equal 2
it "has the recipe as the only step", ->
@plan.steps.length.should.equal 1
@plan.steps[0].recipe.output.item.displayName.should.equal "Oak Planks"
it "demands the right inputs", ->
@plan.need.toString(full:true).should.equal "16 Oak Wood"
it "produces the right results", ->
@plan.make.toString(full:true).should.equal "64 Oak Planks"
describe "for a single item with a complex recipe, it creates a plan that", ->
beforeEach ->
@ironSword = fixtures.configureIronSword @mod
@want.add @ironSword, 2
@plan = @planner.createPlan @want
it "has the right steps", ->
@plan.steps.length.should.equal 4
@plan.steps[0].recipe.output.item.displayName.should.equal "Iron Ingot"
@plan.steps[1].recipe.output.item.displayName.should.equal "Oak Planks"
@plan.steps[2].recipe.output.item.displayName.should.equal "Stick"
@plan.steps[3].recipe.output.item.displayName.should.equal "Iron Sword"
it "demands the right inputs", ->
@plan.need.toString(full:true).should.equal "1 Coal, 8 Iron Ore, 1 Oak Wood"
it "produces the right results", ->
@plan.make.toString(full:true).should.equal "4 Iron Ingot, 2 Iron Sword, 2 Oak Planks, 2 Stick"
describe "for multiple items with complex recipes, it creates a plan that", ->
beforeEach ->
@ironSword = fixtures.configureIronSword @mod
@ironShovel = fixtures.configureIronShovel @mod
@want.add @ironSword, 3
@want.add @ironShovel, 3
@plan = @planner.createPlan @want
it "has consolidated the common steps", ->
(step.recipe.output.item.displayName for step in @plan.steps).should.eql [
"Iron Ingot", "Oak Planks", "Stick", "Iron Sword", "Iron Shovel"
]
it "requires the correct repetitions for each step", ->
(step.count for step in @plan.steps).should.eql [ 2, 2, 3, 3, 3 ]
it "demands the right inputs", ->
@plan.need.toString(full:true).should.equal "2 Coal, 16 Iron Ore, 2 Oak Wood"
it "produces the right results", ->
@plan.make.toString(full:true).should.equal(
"7 Iron Ingot, 3 Iron Shovel, 3 Iron Sword, 2 Oak Planks, 3 Stick"
)
describe "for an item which has a recursive recipe, it creates a plan that", ->
beforeEach ->
@ironBlock = fixtures.configureIronBlock @mod
@want.add @ironBlock, 4
@plan = @planner.createPlan @want
it "avoids the recursive options", ->
(step.recipe.output.item.displayName for step in @plan.steps).should.eql [
"Iron Ingot", "Iron Block"
]
it "requires the correct repetitions for each step", ->
(step.count for step in @plan.steps).should.eql [ 5, 4 ]
it "demands the right inputs", ->
@plan.need.toString(full:true).should.equal "5 Coal, 40 Iron Ore"
it "produces the right results", ->
@plan.make.toString(full:true).should.equal(
"4 Iron Block, 4 Iron Ingot"
)
describe "when making enormous quantities of something simple", ->
beforeEach ->
@oakPlank = fixtures.configureOakPlank @mod
@want.add @oakPlank, Number.MAX_VALUE / 2
@start = Date.now()
@plan = @planner.createPlan @want
@duration = Date.now() - @start
it "doesn't take forever to create the plan", ->
@duration.should.be.lessThan 10
describe "when making an item which can be made with and without a tool, for a", ->
beforeEach ->
@oakPlank = fixtures.configureOakPlank @mod
@saw = fixtures.configureSaw @mod
describe "small batch, the plan", ->
beforeEach ->
@want.add @oakPlank, 2
@plan = @planner.createPlan @want
it "avoids the expensive tool", ->
(step.recipe.needsTools for step in @plan.steps).should.eql [ false ]
describe "large batch, the plan", ->
beforeEach ->
@want.add @oakPlank, 2048
@plan = @planner.createPlan @want
it "uses the tool for efficiency", ->
(step.recipe.needsTools for step in @plan.steps).should.eql [ true ]