Hi guys, Simple question I am working on a L-system. And I saw some examples of using Dictionaries for storing rules. I am trying to make it work with separate Rule class. It is easy to iterate through Dictionary but I can't figure out how to loop through all the rules (as my rules in List)? to get my L system work correctly? Thank you Code (CSharp): using System.Text; using System.Collections; using System.Collections.Generic; using UnityEngine; public class SimpleLSystem : MonoBehaviour { public string axiom; public Rule[] rules; [Range(0,5)] public int iterations; private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { Generate(); } } private void Generate() { string currentString = axiom; StringBuilder sb = new StringBuilder(); for (int i = 0; i < iterations; i++) { foreach (var c in currentString) { if (c == rule.predecessor) { sb.Append(rule.successor); } else { sb.Append(c); } } currentString = sb.ToString(); Debug.Log("Generation " + i + ": " + currentString); sb = new StringBuilder(); } } }
you iterate through dictionaries with foreach, and the element you get is a special construct called KeyValuePair. it's a struct that has two properties, Key and Value. Code (csharp): foreach(var item in myDictionary) { if(item.Key == someKey) Debug.Log(item.Value); } foreach is usable because dictionaries implement IEnumerable the order with dictionaries isn't specified so you cannot rely on any particular ordering also make sure you don't modify the dictionary inside the foreach loop, because it's explicitly forbidden that's the usage out of box, obviously you can extend their featureset, or save the modifications and then apply them outside the foreach loop etc.
Hi @orionsyndrome Yep I know how to do it with dictionary. I was wondering to use a custom Class Rule which holds two variables. And use it instead. But can't figure out how to iterate though it. Not in terms of syntax it terms of logic... Current code works with only one rule... but if I have 2 or 3 ? I need to iterate though each rule.predes Code (CSharp): private void Generate() { string currentString = axiom; StringBuilder sb = new StringBuilder(); for (int i = 0; i < iterations; i++) // iteration { foreach (var c in currentString) // iteration through characters in string { if (c == rule.predecessor) // rule.predecessor is from rule class { sb.Append(rule.successor); } else { sb.Append(c); } } currentString = sb.ToString(); Debug.Log("Generation " + i + ": " + currentString); sb = new StringBuilder(); }
I see. Okay I need a bit more of explanation. What is the exact structure you're having? In the original code you had rules as an array, how a dictionary fits into that? I thought you were going to replace it or something. Can't bother learning about L-systems in depth, though I know what they are. If you explain the structure precisely, I can work out this class for you.
Yes it would be possible to use a Dictionary for simple L-Systems. However if you want to have parametric or conditional replacement rules you could have multiple rules which match the same symbol but might differ in the parametric condition. Yes you said you want a simple L-System so you could use a dictionary. However you don't have to. Dictionaries are great since they can make the lookup faster if you have many rules. However in most cases you don't have many rules. Dictionaries are not automatically faster in all cases. Especially when you deal with single letters or short words. So you can simply iterate through all your rules in order to find a match. Something like this: Code (CSharp): foreach (var c in currentString) // iteration through characters in string { Rule foundRule = null; foreach(var rule in rules) { if (c == rule.predecessor) { foundRule = rule; break; } } if (foundRule != null) sb.Append(foundRule.successor); else sb.Append(c); } I've written a general purpose parametric string based L-system for a UnityAnswers question some years ago. The code is on github (MIT license). The LSystem itself isn't the most complicated thing about this. The LogicExpressionParser is way longer ^^. Note my L-System does not support context sensitive replacement rules. So more advanced systems could specify certain replacement rules based on what symbols preceed or follow the actual symbol you're currently working on. A bit like what regex allows you to do.
Thank you. Ok I am not using dictionaries. I have one custom class Rule (see attached) and I create a list of Rules. I have a Generate method which iterates through current character in string and if this character is == to rule.predecessor (A) it will change it to rule.successor (AB). (A becomes AB). This is a basic logic. And it work only if I have one rule. I want to incorporate my Rules list to go through all rules. Say I have rule[0] A becomes AB and rule[1] B becomes A
Hi @Bunny83 Thank you. Got it. It is exactly what I was trying to do. Probably spent to much time thinking about it. Thanks for the link as well. I am planning to use this L-System to build simple road network and land blocks in between. Was thinking about approach that was described here: https://gamedev.stackexchange.com/questions/86234/using-l-systems-to-procedurally-generate-cities Still have no idea how to make it ... will start with simple switch statement