Files
website/src/client/models/crafting/plan_builder.coffee
T

128 lines
3.7 KiB
CoffeeScript

#
# Crafting Guide - plan_builder.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
CraftingNode = require './crafting_node'
CraftingPlan = require './crafting_plan'
CraftingStep = require './crafting_step'
Inventory = require '../game/inventory'
########################################################################################################################
module.exports = class PlanBuilder
constructor: (rootNode, modPack, options={})->
if not rootNode? then throw new Error 'rootNode is required'
if not modPack? then throw new Error 'modPack is required'
@want = options.want
@have = options.have
@_choiceNodes = []
@_complete = false
@_maxPlanCount = c.limits.maximumPlanCount
@_modPack = modPack
@_plans = []
@_rootNode = rootNode
@_isolateChoiceNodes()
# Public Methods ###############################################################################
producePlans: (maxPlans=null)->
maxPlans = if maxPlans then @plans.length + maxPlans else Number.MAX_VALUE
if @plans.length >= @_maxPlanCount
@_complete = true
while not @complete and (@plans.length < maxPlans)
plan = @_captureCurrentPlan()
if plan?
@plans.push plan
@_incrementChoiceNodes()
return @_plans
# Property Methods #############################################################################
Object.defineProperties @prototype,
complete:
get: -> @_complete
have:
get: -> @_have
set: (have)-> @_have = have or new Inventory
maxPlanCount:
get: -> @_maxPlanCount
set: (value)-> @_maxPlanCount = value
plans:
get: -> @_plans
want:
get: -> @_want
set: (want)-> @_want = want or new Inventory
# Private Methods ##############################################################################
_captureCurrentPlan: ->
toVisit = [@_rootNode]
stepNodes = []
while toVisit.length > 0
node = toVisit.shift()
if node.TYPE is CraftingNode::TYPES.INVENTORY
toVisit.push(c) for c in node.children
else if node.TYPE is CraftingNode::TYPES.ITEM
toVisit.push node.children[0] if node.children.length > 0
else if node.TYPE is CraftingNode::TYPES.RECIPE
stepNodes.push node
toVisit.push(c) for c in node.children
steps = []
seenRecipes = {}
index = stepNodes.length - 1
while index >= 0
node = stepNodes[index]
index -= 1
return null unless node.valid and node.complete
recipeSlug = node.recipe.slug
continue if seenRecipes[recipeSlug]?
seenRecipes[recipeSlug] = true
steps.push new CraftingStep node.recipe, @_modPack
plan = new CraftingPlan @_modPack, @_want, @_have, steps
return plan
_incrementChoiceNodes: ->
if @_choiceNodes.length is 0
@_complete = true
return
index = @_choiceNodes.length - 1
while true
if index is -1
@_complete = true
return
node = @_choiceNodes[index]
node.rotateChildren()
return unless node.rotations % node.children.length is 0
index -= 1
_isolateChoiceNodes: ->
@_rootNode.acceptVisitor
onEnterItemNode: (node)=>
if node.children.length > 1
@_choiceNodes.push node