private void DiffuseAcrossEdge(
            DiffusionEdge edge,
            NativeList <float> sourceAmounts,
            NativeList <float> targetAmounts
            )
        {
            var nodeA = nodes[edge.nodeAIndex];
            var nodeB = nodes[edge.nodeBIndex];

            var diffusionConstant = customSymbols.diffusionConstantRuntimeGlobalMultiplier * (nodeA.diffusionConstant + nodeB.diffusionConstant) / 2f;

            for (
                int resource = 0;
                resource < nodeA.totalResourceTypes && resource < nodeB.totalResourceTypes;
                resource++)
            {
                var oldNodeAValue = sourceAmounts[nodeA.indexInTempAmountList + resource];
                var nodeAValueCap = nodeMaxCapacities[nodeA.indexInTempAmountList + resource];

                var oldNodeBValue = sourceAmounts[nodeB.indexInTempAmountList + resource];
                var nodeBValueCap = nodeMaxCapacities[nodeB.indexInTempAmountList + resource];

                var aToBTransferredAmount = diffusionConstant * (oldNodeBValue - oldNodeAValue);

                if (aToBTransferredAmount == 0)
                {
                    continue;
                }
                if (aToBTransferredAmount < 0 && oldNodeBValue >= nodeBValueCap)
                {
                    // the direction of flow is towards node B, and also node B is above its value cap. skip updating the resource on this connection completely.
                    continue;
                }
                if (aToBTransferredAmount > 0 && oldNodeAValue >= nodeAValueCap)
                {
                    // the direction of flow is towards node A, and also node A is above its value cap. skip updating the resource on this connection completely.
                    continue;
                }

                targetAmounts[nodeA.indexInTempAmountList + resource] += aToBTransferredAmount;
                targetAmounts[nodeB.indexInTempAmountList + resource] -= aToBTransferredAmount;
            }
        }
Example #2
0
        private void ExtractEdgesAndNodes()
        {
            var branchSymbolParentStack = new TmpNativeStack <BranchEvent>(5);
            var currentNodeParent       = -1;

            for (int symbolIndex = 0; symbolIndex < inPlaceSymbols.Length; symbolIndex++)
            {
                var symbol = inPlaceSymbols[symbolIndex];
                if (symbol == customSymbols.diffusionNode)
                {
                    if (currentNodeParent >= 0)
                    {
                        var newEdge = new DiffusionEdge
                        {
                            nodeAIndex = currentNodeParent,
                            nodeBIndex = working.nodes.Length
                        };
                        working.allEdges.Add(newEdge);
                    }
                    currentNodeParent = working.nodes.Length;

                    var nodeParams = inPlaceSymbols.parameters[symbolIndex];

                    var newNode = new DiffusionNode
                    {
                        indexInTarget    = symbolIndex,
                        targetParameters = nodeParams,

                        indexInTempAmountList = working.nodeAmountsListA.Length,

                        totalResourceTypes = (nodeParams.length - 1) / 2,
                        diffusionConstant  = inPlaceSymbols.parameters[nodeParams, 0],
                    };
                    newNode.targetParameters.length = nodeParams.length;
                    working.nodes.Add(newNode);

                    for (int resourceType = 0; resourceType < newNode.totalResourceTypes; resourceType++)
                    {
                        var currentAmount = inPlaceSymbols.parameters[nodeParams, resourceType * 2 + 1];
                        var maxCapacity   = inPlaceSymbols.parameters[nodeParams, resourceType * 2 + 1 + 1];
                        working.nodeAmountsListA.Add(currentAmount);
                        working.nodeAmountsListB.Add(0);
                        working.nodeMaxCapacities.Add(maxCapacity);
                    }
                }
                else if (symbol == customSymbols.diffusionAmount)
                {
                    var modifiedNode     = working.nodes[currentNodeParent];
                    var amountParameters = inPlaceSymbols.parameters[symbolIndex];
                    inPlaceSymbols.parameters[symbolIndex] = new JaggedIndexing
                    {
                        index  = amountParameters.index,
                        length = 0
                    };
                    if (currentNodeParent < 0)
                    {
                        // problem: the amount will dissapear
                        continue;
                    }
                    for (int resourceType = 0; resourceType < modifiedNode.totalResourceTypes && resourceType < amountParameters.length; resourceType++)
                    {
                        working.nodeAmountsListA[modifiedNode.indexInTempAmountList + resourceType] += inPlaceSymbols.parameters[amountParameters, resourceType];
                    }
                }
                else if (symbol == customSymbols.branchOpenSymbol)
                {
                    branchSymbolParentStack.Push(new BranchEvent
                    {
                        openBranchSymbolIndex = symbolIndex,
                        currentNodeParent     = currentNodeParent
                    });
                }
                else if (symbol == customSymbols.branchCloseSymbol)
                {
                    if (branchSymbolParentStack.Count <= 0)
                    {
                        // uh oh. idk how this is happening but it is. probably related to the volumetric destruction and autophagy.
                        break;
                    }
                    var lastBranchState = branchSymbolParentStack.Pop();
                    currentNodeParent = lastBranchState.currentNodeParent;
                }
            }
        }
Example #3
0
        private void ExtractEdgesAndNodes()
        {
            var branchSymbolParentStack = new TmpNativeStack <BranchEvent>(5);
            var currentNodeParent       = -1;

            for (int symbolIndex = 0; symbolIndex < sourceData.Length; symbolIndex++)
            {
                var symbol = sourceData[symbolIndex];
                if (symbol == customSymbols.diffusionNode)
                {
                    if (currentNodeParent >= 0)
                    {
                        var newEdge = new DiffusionEdge
                        {
                            nodeAIndex = currentNodeParent,
                            nodeBIndex = working.nodes.Length
                        };
                        working.allEdges.Add(newEdge);
                    }
                    currentNodeParent = working.nodes.Length;

                    var nodeParams    = sourceData.parameters[symbolIndex];
                    var nodeSingleton = matchSingletonData[symbolIndex];

                    var newNode = new DiffusionNode
                    {
                        indexInTarget    = nodeSingleton.replacementSymbolIndexing.index,
                        targetParameters = nodeSingleton.replacementParameterIndexing,

                        indexInTempAmountList = working.nodeAmountsListA.Length,

                        totalResourceTypes = (nodeParams.length - 1) / 2,
                        diffusionConstant  = sourceData.parameters[nodeParams, 0],
                    };
                    newNode.targetParameters.length = nodeParams.length;
                    working.nodes.Add(newNode);

                    for (int resourceType = 0; resourceType < newNode.totalResourceTypes; resourceType++)
                    {
                        var currentAmount = sourceData.parameters[nodeParams, resourceType * 2 + 1];
                        var maxCapacity   = sourceData.parameters[nodeParams, resourceType * 2 + 1 + 1];
                        working.nodeAmountsListA.Add(currentAmount);
                        working.nodeAmountsListB.Add(0);
                        working.nodeMaxCapacities.Add(maxCapacity);
                    }
                }
                else if (symbol == customSymbols.diffusionAmount)
                {
                    var modifiedNode     = working.nodes[currentNodeParent];
                    var amountParameters = sourceData.parameters[symbolIndex];
                    if (amountParameters.length == 0)
                    {
                        // the amount has no parameters left. removal will be happening via regular update
                        continue;
                    }

                    // clear out the parameters in the target string, and write the symbol over
                    var nodeSingleton = matchSingletonData[symbolIndex];
                    targetData.parameters[nodeSingleton.replacementSymbolIndexing.index] = new JaggedIndexing
                    {
                        index  = nodeSingleton.replacementParameterIndexing.index,
                        length = 0
                    };
                    targetData[nodeSingleton.replacementSymbolIndexing.index] = customSymbols.diffusionAmount;
                    if (currentNodeParent < 0)
                    {
                        // problem: the amount will dissapear
                        continue;
                    }
                    for (int resourceType = 0; resourceType < modifiedNode.totalResourceTypes && resourceType < amountParameters.length; resourceType++)
                    {
                        working.nodeAmountsListA[modifiedNode.indexInTempAmountList + resourceType] += sourceData.parameters[amountParameters, resourceType];
                    }
                }
                else if (symbol == customSymbols.branchOpenSymbol)
                {
                    branchSymbolParentStack.Push(new BranchEvent
                    {
                        openBranchSymbolIndex = symbolIndex,
                        currentNodeParent     = currentNodeParent
                    });
                }
                else if (symbol == customSymbols.branchCloseSymbol)
                {
                    var lastBranchState = branchSymbolParentStack.Pop();
                    currentNodeParent = lastBranchState.currentNodeParent;
                }
            }
        }