ZMWSLI0-SL2021-GR11/Projekt/MWSProjekt/Assets/Scripts/LSystemRule.cs

423 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
public class LSystemNodeLiteralVariable : LSystemNodeLiteral
{
public Dictionary<string, int> variableIndex { get; }
public LSystemNodeLiteralVariable(string name, int values_number, Dictionary<string, int> variableIndex) : base(name, values_number)
{
this.variableIndex = variableIndex;
}
}
public class LSystemNodeGenerator : LSystemNode
{
MathExpression[] math_expressions;
public LSystemNodeGenerator(string name, int arguments) : base(new LSystemNodeLiteral(name, arguments))
{
}
public void fillArguments(MathExpression[] math_expressions)
{
this.math_expressions = math_expressions;
}
public LSystemNode eval(float[] values)
{
var literal = new LSystemNodeLiteral(this.literal.name, this.literal.values_number);
for (int i = 0; i < literal.values_number; i++)
{
literal.values[i] = math_expressions[i].eval(values);
}
var result = new LSystemNode(literal);
foreach (LSystemNodeGenerator child in children)
{
var _child = child.eval(values);
_child.parent = result;
result.children.Add(_child);
}
if (mainChild != null)
{
var _mainChild = ((LSystemNodeGenerator)mainChild).eval(values);
_mainChild.parent = result;
result.mainChild = _mainChild;
}
else
{
result.mainChild = null;
}
return result;
}
}
abstract public class LSystemRule
{
abstract public bool is_aplicable(LSystemNode processed_node, String[] ignored);
abstract public LSystemNode rewrite(LSystemNode processed_node, String[] ignored);
}
public class LSystemRuleBasic : LSystemRule
{
LSystemNodeLiteral input;// { get; }
LSystemNode output;
public LSystemRuleBasic(LSystemNodeLiteral input, LSystemNode output)
{
this.input = input;
this.output = output;
}
override public bool is_aplicable(LSystemNode processed_node, String[] ignored)
{
if (processed_node.literal == input)
{
return true;
}
else
{
return false;
}
}
override public LSystemNode rewrite(LSystemNode processed_node, String[] ignored)
{
if (is_aplicable(processed_node, ignored))
{
return output.deep_copy();
}
else
{
return new LSystemNode(processed_node.literal);
}
}
}
public class LSystemRuleParametric : LSystemRule
{
LSystemNodeLiteralVariable predecesor;// { get; }
LSystemNodeGenerator consequent;
MathExpressionComparison[] conditions;
public LSystemRuleParametric(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator consequent)
{
this.predecesor = predecesor;
this.consequent = consequent;
this.conditions = conditions;
}
public override bool is_aplicable(LSystemNode processed_node, String[] ignored)
{
if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number)
{
return false;
}
foreach (var condition in conditions)
{
if (!condition.eval(processed_node.literal.values))
{
return false;
}
}
return true;
}
public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored)
{
if (is_aplicable(processed_node, ignored))
{
return consequent.eval(processed_node.literal.values);
}
else
{
return new LSystemNode(processed_node.literal);
}
}
}
public class LSystemRuleParametricStochastic : LSystemRule
{
protected LSystemNodeLiteralVariable predecesor;// { get; }
protected LSystemNodeGenerator[] consequents;
protected float[] probabilities;
protected MathExpressionComparison[] conditions;
protected System.Random random;
public LSystemRuleParametricStochastic(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator[] consequents, float[] probabilities)
{
this.predecesor = predecesor;
this.consequents = consequents;
this.conditions = conditions;
float probabilities_sum = 0;
foreach (var probability in probabilities) { probabilities_sum += probability; }
float acumulator = 0;
this.probabilities = new float[consequents.Length];
for (int i = 0; i < consequents.Length; i++)
{
var probability = probabilities[i] / probabilities_sum;
this.probabilities[i] = probability + acumulator;
acumulator += probability;
}
random = new System.Random();
}
public LSystemRuleParametricStochastic(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator consequent)
{
this.predecesor = predecesor;
this.consequents = new LSystemNodeGenerator[] { consequent };
this.conditions = conditions;
float probabilities_sum = 0;
probabilities = new float[1] { 1 };
random = new System.Random();
}
public override bool is_aplicable(LSystemNode processed_node, String[] ignored)
{
if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number)
{
return false;
}
foreach (var condition in conditions)
{
if (!condition.eval(processed_node.literal.values))
{
return false;
}
}
return true;
}
public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored)
{
var result = random.NextDouble();
int consequent_index = 0;
for (int i = 0; i < probabilities.Length; i++)
{
if (result < probabilities[i])
{
consequent_index = i;
break;
}
}
if (is_aplicable(processed_node, ignored))
{
return consequents[consequent_index].eval(processed_node.literal.values);
}
else
{
return new LSystemNode(processed_node.literal);
}
}
}
public class LSystemContext
{
public LSystemNodeLiteral parent { get; set; }
public LSystemNodeLiteral[] children { get; set; }
public LSystemNodeLiteral mid { get; set; }
bool isPreceding = false;
bool isSucceeding = false;
public LSystemContext(LSystemNodeLiteral parent, LSystemNodeLiteral[] children)
{
this.parent = parent;
this.children = children;
this.isPreceding = true;
this.isSucceeding = true;
}
public LSystemContext()
{
}
public void setOnlyPreceding(LSystemNodeLiteral parent)
{
this.parent = parent;
this.mid = mid;
this.isPreceding = true;
this.isSucceeding = false;
}
public void setOnlySucceeding(LSystemNodeLiteral[] children)
{
this.children = children;
this.isPreceding = false;
this.isSucceeding = true;
}
void _purgeIgnoredRecursive(LSystemNode node, HashSet<String> ignored, ref List<LSystemNode> results)
{
if (ignored.Contains(node.literal.name))
{
foreach (var child in node.getAllChildren())
{
_purgeIgnoredRecursive(child, ignored, ref results);
}
}
else
{
results.Add(node);
}
}
List<LSystemNode> _purgeIgnored(LSystemNode node, HashSet<String> ignored)
{
List<LSystemNode> results = new List<LSystemNode>();
foreach (var child in node.getAllChildren())
{
_purgeIgnoredRecursive(child, ignored, ref results);
}
return results;
}
public bool isAplicable(LSystemNode node, String[] ignored, out float[] variables)
{
var variables_list = new List<float>();
var currentParent = node.parent;
while (ignored.Contains(currentParent.literal.name))
{
currentParent = currentParent.parent;
}
if (isPreceding && parent != currentParent.literal)
{
variables = new float[0];
return false;
}
if (isPreceding)
{
variables_list.AddRange(currentParent.literal.values);
}
variables_list.AddRange(node.literal.values);
if (isSucceeding)
{
LSystemNodeLiteral childLiteral;
Queue<LSystemNode> ignoredChildren = new Queue<LSystemNode>();
var nodeChildren = _purgeIgnored(node, new HashSet<String>(ignored)).ToArray();
var result = children.Length == nodeChildren.Length;
if (result)
{
for (int i = 0; i < children.Length; i++)
{
if (nodeChildren[i].literal == children[i])
{
variables_list.AddRange(nodeChildren[i].literal.values);
}
else
{
result = false;
break;
}
}
}
//foreach(var child in node.getAllChildren()) {
// if (ignored.Contains(child.literal.name)) {
// ignoredChildren.Enqueue(child);
// }
// if (child.literal == this.child) {
// childLiteral = child.literal;
// result = true;
// variables_list.AddRange(child.literal.values);
// break;
// }
//}
//while (!result && ignoredChildren.Count>0) {
// var ignoredChild = ignoredChildren.Dequeue();
// foreach (var child in ignoredChild.getAllChildren()) {
// if (ignored.Contains(child.literal.name)) {
// ignoredChildren.Enqueue(child);
// }
// if (child.literal == this.child) {
// childLiteral = child.literal;
// result = true;
// variables_list.AddRange(child.literal.values);
// break;
// }
// }
//}
if (!result)
{
variables = new float[0];
return false;
}
}
variables = variables_list.ToArray();
return true;
}
}
public class LSystemRuleParametricStochasticContext : LSystemRuleParametricStochastic
{
LSystemContext context;
public LSystemRuleParametricStochasticContext(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator[] consequents, float[] probabilities, LSystemContext context) : base(predecesor, conditions, consequents, probabilities)
{
this.context = context;
}
public LSystemRuleParametricStochasticContext(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator consequent, LSystemContext context) : base(predecesor, conditions, consequent)
{
this.context = context;
}
public override bool is_aplicable(LSystemNode processed_node, String[] ignored)
{
if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number)
{
return false;
}
var variables = new float[0];
if (!context.isAplicable(processed_node, ignored, out variables))
{
return false;
}
foreach (var condition in conditions)
{
if (!condition.eval(variables))
{
return false;
}
}
return true;
}
bool is_aplicable(LSystemNode processed_node, String[] ignored, out float[] variables)
{
variables = new float[0];
if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number)
{
return false;
}
if (!context.isAplicable(processed_node, ignored, out variables))
{
return false;
}
foreach (var condition in conditions)
{
if (!condition.eval(variables))
{
return false;
}
}
return true;
}
public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored)
{
var result = random.NextDouble();
int consequent_index = 0;
for (int i = 0; i < probabilities.Length; i++)
{
if (result < probabilities[i])
{
consequent_index = i;
break;
}
}
float[] variables;
if (is_aplicable(processed_node, ignored, out variables))
{
return consequents[consequent_index].eval(variables);
}
else
{
return new LSystemNode(processed_node.literal);
}
}
}