Xtapodi
Xtapodi

Reputation: 277

Use and parse a text file in C# to initialize a component based game model

I have a text file that should initialize my objects, which are built around a component based model, it is my first time trying to use a data driven approach and i'm not sure if i am heading in the right direction here.

The file i have currently in mind looks like this

EliteGoblin.txt

@Goblin.txt


[general]
hp += 20
strength = 12
description = "A big menacing goblin"
tacticModifier +=  1.3

[skills]
fireball

Where the @ symbol says which other files to parse at at that point The names in [] correspond with component classes in the code And below them is how to configure them

For example the hp += 20 would increase the value taken from goblin.txt and increase it by 20 etc.

My question is how i should go about parsing this file, is there some sort of parser built in C#?

Could i change the format of my document to match already defined format that already has support in .net?

How do i go about understanding what type is each value? int/float/string

Does this seem a viable solution at all?

Thanks in advance, Xtapodi.

Upvotes: 4

Views: 976

Answers (4)

David Robbins
David Robbins

Reputation: 10046

You might want to check out Sprache, a .net library that can create DSL' s by Autofac creator Nicholas Blumhardt. From the google site:

Sprache is a small library for constructing parsers directly in C# code.

It isn't an "industrial strength" framework - it fits somewhere in between regular expressions and a full-blown toolset like ANTLR.

Usage Unlike most parser-building frameworks, you use Sprache directly from your program code, and don't need to set up any build-time code generation tasks. Sprache itself is a single tiny assembly.

A simple parser might parse a sequence of characters:

// Parse any number of capital 'A's in a row var parseA = Parse.Char('A').AtLeastOnce(); Sprache provides a number of built-in functions that can make bigger parsers from smaller ones, often callable via Linq query comprehensions:

Parser identifier = from leading in Parse.Whitespace.Many() from first in Parse.Letter.Once() from rest in Parse.LetterOrDigit.Many() from trailing in Parse.Whitespace.Many() select new string(first.Concat(rest).ToArray());

var id = identifier.Parse(" abc123 ");

Assert.AreEqual("abc123", id);

The link to the article builds a questionaire that is driven by a simple text file with the following format:

identification  "Personal Details"
[
    name        "Full Name"
    department  "Department"
]

employment      "Current Employer"
[
    name        "Your Employer"
    contact     "Contact Number"
    #months     "Total Months Employed"
]

Upvotes: 2

KalEl
KalEl

Reputation: 9136

There is no builtin function to do exactly what you want to do, but you can easily write it.

    void ParseLine(string charClass, string line) {
        // your code to parse line here...
        Console.WriteLine("{0} : {1}", charClass, line);
    }
    void ParseFile(string fileName) {
        string currentClass = "";
        using (StringReader sr = new StringReader(fileName)) {
            string line = sr.ReadLine();
            if (line[0] == '@') {
                string embeddedFile = line.Substring(1);
                ParseFile(embeddedFile);
            }
            else if (line[0] == '[') {
                currentClass = line.Substring(2, line.Length - 2);
            }
            else ParseLine(currentClass, line);
        }
    }

Upvotes: 1

George Johnston
George Johnston

Reputation: 32258

Drop the flat file and pick up XML. Definately look into XML Serialization. You can simply create all of your objects in C# as classes, serialize them into XML, and reload them into your application without having to worry about parsing a flat file out. Because your objects will act as the schema for your XML, you won't have to worry about casting objects and writing a huge parsing routine, .NET will handle it for you. You will save many moons of headache.

For instance, you could rewrite your class to look like this:

public class Monster
{
     public GeneralInfo General {get; set;}
     public SkillsInfo  Skills {get; set;}
}
public class GeneralInfo
{
  public int Hp {get; set;}
  public string Description {get; set;}
  public double TacticModifier {get; set;}
}
public class SkillsInfo
{
  public string[] SkillTypes {get; set;}
}

...and your XML would get deserialized to something like...

<Monster>
   <General>
       <Hp>20</Hp>
       <Description>A big menacing goblin</Description>
       <TacticModifier>1.3</TacticModifier>
   </General>
   <SkillTypes>
        <SkillType>Fireball</SkillType>
        <SkillType>Water</SkillType>
   </SkillTypes>
</Monster>

..Some of my class names, hierarchy, etc. may be wrong, as I punched this in real quick, but you get the general gist of how serialization will work.

Upvotes: 12

Phil Gan
Phil Gan

Reputation: 2863

What you want to do isn't going to be easy. The statistic inheritance in particular.

So, unless you can find some existing code to leverage, I suggest you start with simpler requirements with a view to adding the more involved functionality later and build up the functionality incrementally.

Upvotes: 0

Related Questions