I'm making a little game in unity and right now I'm trying to build the quest system.
This game is going to be a simulation, so there's a huge amount of different data classes / systems the quests are going to have to interact with.
I can just make a bunch of utility classes... or even make a fake "database" to handle data calls... but that's inelegant.
Surely there's gotta be a way where I can just denote actual code from a string?
Example:
String questText = Hello player.getFullName();, how are you?
questResults<String>[1] = player.inventory.add(GameObjectBuilder.Create(new WhateverObject()));
I am using Unity's ScriptableObject to make quests, so that I can fill in text data via the editor rather than do it on IDE side (especially since unity doesn't support interpolated & composite strings as far as I know).
I know Java has an API called "Reflection" which from what I understand does something like this, but I was never able to fully wrap my head around it.
So how do I convert elements from a string into runnable code?
If that is possible, will that cause preformance issues with an indefinate amount of objects that might be encountering scripts that need to be converted?
Are there any other alternative methods that achieve a similar goal? (this one is just a curiosity)
As an alternative method, you can use a keyword that you search for and replace, rather than write the actual code directly into your string. I would suggest using this approach as it's cleaner to read and easier to maintain. I have used this approach in a similar system.
It works well if there is only a small number of possibilities that you will need to resolve (or you don't mind adding 'handlers' for all keywords., you can include a sort of keyword in your text, that you can pass through a method before using it.
For example..
Hello {PLAYER_NAME}, how are you? - this is the raw string.
public string ParseQuestText(string input)
{
if(input.contains("{PLAYER_NAME}")
input.Replace("{PLAYER_NAME}",player.getFullName());
/Add other replacers here
return input;
}
Related
I am wanting to create a 'dictionary' of strings, however I have only ever learned how to use strings to reference what I want in a dictionary. I want something with more auto-correct (as typos can happen in a large table of strings), which is why I want to know how to hard-code. (The value of the strings will be retrieved from a text file, like JSON).
I notice that Microsoft uses some type of hard-coding in their String Resource File.
So instead of doing:
string result = strings["Hello"];
I wish to do this:
string result = strings.Hello;
The only thing I can think of is to use some external tool that creates an enum/struct script with the values from the text file. Is there a better option, perhaps one built into .NET?
Edit: I think 'strongly-typed' would be a better description over 'hard-coded'.
Edit 2: Thanks for all the comments and answers. By the looks of it, some code-gen is required to fufil this result. I wonder if there's already any tools out there that do this for you (I tried looking but my terminology may be lacking). It doesn't seem too difficult to create this tool.
There are compiletime constants and runtime constants.
Your wish for Autocrrection/Intellisense support requires a compile time constants. Those are the only ones Intellisence, Syntax Highlighting and the Compiler double check for you.
But your requriement of having the values generated from a 3rd party textfile, indicates either a runtime constant or some automatic code generation. Runtime constants would take away the Editor support. While Code generation would run into issue with the Editor only having a old copy of the file. And a high risk of breaking tons of code if a string in that one file changes.
So your two requirements are inherently at odds. You need to have your cake and eat it too.
Perhaps my primitve solution to the Enum/ToString() problem might help you?
Enumeration are for most parts groups of constants, and integer ones by default. With added type checks on assignments. That makes them a good way around Primitive Obsession. You reference a value from the group like you would any constant, readonly static field or readonly property. (There is other advantages like Flags, but I doubt they mater here).
While Enums have a string you could use for display and input parsing - the one you use in sourcecode - that one is absolutely not suited for display. By default they are all-caps and you would need to support Localisation down the line. My primitive Solution was a translation layer. I add a Dictionary<someEnum, String> SomeEnumStringRepresentation. This dictionary can be generated and even changed at runtime:
I need to display any specific value, it is SomeEnumLocalisation[someEnum]. I could add a default behavior to just ToString() the compiler representation of the Enum.
I need to parse a user input? Itterate over the values until you find a match, if not throw a ParseException.
I get to use compile time checks. Without having to deal with the very inmutable compile side strings anywhere else. Or with my code side strings changing all the time.
i am not quit understand what out put you want , bu I am just throwing an idea to here - how about to extend the class string and add your own methods to it ? so when you use strings.Hello it will return what you wanted?
example :
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods
I'm new to coding. I have some experience years ago with other languages, but I'm essentially starting fresh with C#. I'm trying to make a series of logic-driven random generators that will help me with my writing. The part about it being logic-driven is the kick in the pants. I've got an HTML/Javascript version working but I want to do it in C# and I'm stuck.
Essentially, the generator will randomly generate the first trait of whatever it is that I'm making. For example, maybe I'm running my random creature generator and the "Creature Type" is "Avian" (Birdlike). Based on THAT result, other features and traits would randomly generate. For example, it wouldn't say that the skin type is "membrane" for an Avian creature. If the creature has pointed teeth, it wouldn't show up with a diet of "vegetarian".
I was able to make a very basic random generator, however, I'm not sure this is the best way to go about it. Should I make this a List? An Array? Something else? Everything that I've searched online is explaining how to build a random number generator, which isn't what I need, or it's a simple list with no dependency logic built in. Aside from having an idea of what it should do, I don't know enough C# to get it. I'm not even sure I'm searching google with the right terms.
Thanks in advance.
All right, let's go step-by-step.
Based on THAT result, other features and traits would randomly generate.
OK, so you need a function: ISet<T> Choices(T instance); responsible for providing a set (i.e. list with no duplicated elements and internal implementation optimised for checks like bool Contains(T instance)) of next possible options. The options provided must take into consideration the essence of given T instance and provide only valid options such that predator won't be a vegetarian.
Then you need T AnyOf(IEnumerable<T> options) function that randonly picks up any element contained within a given IEnumerable<T>. Obviously, it gonna model non-determenism.
Eventually, you have to match those such that they form a chain T Generate() that is self-sufficient to make a fresh valid instance.
Please note, generally you'll deal with different T's. There is no implicit assumption that all of them are interrelated. It's up to you to model your instances richly enough to be able to apply the sketch I drew above.
Good luck.
Need assistance in structuring my code with design patterns.
So I have a single method in service class that looks like this. The constructor loads a json file into a List<Option> of Option class instances. Finally when the service method is called it does some logic to find the Option match based on the parameter values and returns a new instance of 'Tool' class with the configured "options".
public Tool BestOptionFinderService.FindBestMatch(string value 1, int value2, int value3, .. bool value20, etc...) {..}
I'm not sure if I a "service" class is correct for this versus a "factory" or something else. I would appreciate your thoughts and suggestions on how you would design your code for this problem or similar.
I would say, having single method with ~20 params is awful by itself, without even considering OOP patterns. Let's try to do better; more than that, let's try not to reinvent the wheel.
Important yet obvious observation: whatever matching logic one has, any object either matches or nor, and never both. Thus it makes sense to stick with Boolean algebra and signatures like predicate: t -> bool or bool Predicate<T>(T obj). The other thing we know about predicates, is that one can easily reduce arbitrary two into a single one: there are different ways to do it, however you're obviously interested in the and or && operator.
Thus, instead of having 20 parameters, you could have had twenty different simple, clear, self-describing predicates, later on "reduced" into a single instance. Linq.Aggregate() could help you out to not only beautify your code, but make it parallel (if necessary) as well. Then you could map your input to an sufficient (it's up to you to decide whether you do need more, or don't) number of flags, representing a "fitness" of a particular object you're examining.
Such an approach would indeed be better because:
1) You stick to well-known Boolean algebra,
1.A) which, actually, forms a monoid under various operation, including and, which, in turn, makes it
1.B) easily distributable over any computation cluster
1.C) compact, expressive, self-explanatory.
2) Your code tells much more story: simple predicates are easy to read, maintain, unit-test and refactor, which is never the case for 20-params methods.
3) You clearly separate your primitives from a compositions - more complex structures, built up from somewhat known primitives. That's the way math goes and thus the only known reliable, proven by thousands of years way to tackle down the complexity and not get enslaved by it at some point.
4) There are more advantages, but I tired to type ;)
I am wonder, you have some part of code you need to do in, for example, every method.
I know everyone have another "style" of programming and everyone prefer another ways how to do something.
But for example i am writing now some adapter on some class (settings of web camera) where I can set for example color mode, exposure, gain, etc. In EVERY method (settings change) i need:
1) stop camera
2) set parameter !! this is only one step where will be another code !!
3) create camera instance again
4) start camera
I see in here 2 ways how to do that:
1) probably "ugly" written copy&paste code
StopCam();
_wCamDev.Gain=20; // COMMANDS TO SET DEFINED PARAMETER, FOR EXAMPLE GAIN
CreateCam();
StartCam();
this code you can have in every method and change only the second row (_wCamDev.Gain=20;).
It would be pretty sure what this code is doing for another programmers, easlier for understanding after 2 years what those sequences are doing. But on the another hand, this code is not written right (atleast for me) because of multiple copy&paste code.
2) You can use something like "generic function in parameter" and you can have something like:
public void refreshCam(Func<T,out>){
StopCam();
CHANGE_PARAMS_BY_GEN_FUNCTION;
CreateCam();
StartCam();
}
The generic called function will set the parameter and you can have a little bit harder code for understanding, but no multiple sequences (copy&paste code) and you can easy in every method call this one refreshCam() with your params and you can specify them in other methods.
What "code" can you prefer? Why? Is there some another (better) way how to do that?
Is it even possible to send generic function by parameter?
I think it is the most important by adapter design-patern how to write it right.
You might consider implementing the Template Method Pattern. You create a base class that does all the general work (in some DoIt method) and delegates the setting of the gain to a abstract method (SetGain) that needs to be implemented by all the subclasses.
This might look a bit like overkill, but if you choose the names of the subclasses well, it might be more clear what the code is supposed to do.
In a modern language like C# this pattern could very well be implemented using a lambda or a delegate or Func<> as #X.L.Ant suggested.
I recently began to start using functions to make casting easier on my fingers for one instance I had something like this
((Dictionary<string,string>)value).Add(foo);
and converted it to a tiny little helper function so I can do this
ToDictionary(value).Add(foo);
Is this against the coding standards?
Also, what about simpler examples? For example in my scripting engine I've considered making things like this
((StringVariable)arg).Value="foo";
be
ToStringVar(arg).Value="foo";
I really just dislike how inorder to cast a value and instantly get a property from it you must enclose it in double parentheses. I have a feeling the last one is much worse than the first one though
Ignoring for a moment that you may actually need to do this casting - which I personally doubt - if you really just want to "save your fingers", you can use a using statement to shorten the name of your generic types.
At the top of your file, with all the other usings:
using ShorterType = Dictionary<string, Dictionary<int, List<Dictionary<OtherType, ThisIsRidiculous>>>>;
I don't think so. You've also done something nice in that it's a bit easier to read and see what's going on. Glib (in C) provides casting macros for their classes, so this isn't a new concept. Just don't go overkill trying to save your fingers.
In general, I would consider this to be code smell. In most situations where the type of casting you describe is necessary, you could get the same behavior by proper use of interfaces (Java) or virtual inheritance (C++) in addition to generics/templates. It is much safer to leave that responsibility of managing types to the compiler than attempting to manage it yourself.
Without additional context, it is hard to say about the example you have included. There are certainly situations in which the type of casting you describe is unavoidable; but they're the exception rather than the rule. For example, the type of casting (and the associated helper functions/macros) you're describing extremely common-place in generic C libraries.