I am working on a video game called Tibia and I pretty much got the basic things of the game server, but now I need to be able to develop actions or so scripting, but very simplified nothing fancy or difficult, I don't like messy things.
Currently the community of this video game have achieved access to original files of it's scripting environment and it's like this:
Collision, IsCreature (Obj2) -> Teleport(Player,[47,14,1])
The scripting or syntax parser from this closed-source environment uses is a simple token based class, which looks for tokens and reads accordingly based on code.
Tokens are as follows:
A-Z = IDENTIFIER
0-9 = NUMBER
" = STRING
Anythig else = SYMBOL
And it's used like follows:
// This is a sample to use with the code below:
// USERNAME = "ROBERT"
//
nextToken(); // Looks for next token type
if (token == IDENTIFIER) {
readSymbol(); // This reads =
readString(); // This reads text inside "
}
What it basically does is loop in a char* array and look for tokens, I hope this is easy to understand.
What I am looking to achieve is a way to organize in my C++ code the functions with parameters given in the script file, like if I have this on a script file:
// Conditions -> Actions
IsPosition([10,20,7]) -> TeleportPlayer(Player,[25,10,30])
Know a way to gather this function with it's parameters to use in my game world environment? Like after I read this script file save the particular conditions and actions to check somewhere else on my code if the conditions accomplish and then do the following actions? Like check if the player is standing in Position and then teleport the player (which is what is written in the script file)
Related
I have an application that invokes callback function when a certain action is performed on the application.
Inside this callback function, I would like to invoke a Parser (a command line parser for instance).
This Parser would be running in a while loop and exits and comes back to the callback only when the user uses the command 'quit' on the command line.
Inside the while loop, the user always has access to the command line. Based on the user input on the command line, the Parser takes a unique action. For instance, it will set a variable and it goes to a database like so:
command-line>a 100
command-line>
Here the parameter a in DB would be set to 100.
I want to model the Parser using Object-Oriented Design. Which Design Pattern can I use in this case?
First and foremost, most design patterns are obsoleted by the introduction of first-class functions. What you need is a dispatch table of names to actions, which is basically the Command pattern.
Assuming the following definitions:
using Tokens = std::vector<std::string>;
using Action = std::function<void(const Tokens&)>;
Tokens read_and_tokenize_line();
void larger_command(const Tokens&);
std::map<std::string, Action> dispatch_table = {
{"a", [&](const Tokens& tokens){ my_database->set("a", tokens[1]); }},
{"larger_command", &larger_command},
};
You could write your core loop as follows:
while (true) {
auto tokens = read_and_tokenize_line();
if (tokens[0] == "quit")
break;
if (auto it = dispatch_table.find(tokens[0]); it != dispatch_table.end()) {
it->second(tokens);
} else {
std::cerr << "command " << tokens[0] << " not known" << std::endl;
}
}
The main problem you have is that your parser run in a while loop and that will obviously block your UI. I assume this issue is the (unstated) problem you are trying to solve.
First, there exist parsers that don't need to run in a while loop. bison can generate such parsers when in push mode. By using this kind of parser you can still rely on your main GUI event loop and feed the parser with tokens inside a callback without blocking.
Then, if you are writing yourself a recursive-descent parser, you can generate a parser that will interrupt itself and save its state each time it needs some input. This is going to be very tricky as you have to save the whole state of the parser including its stack. The way to do it is to use an explicit stack (or many stacks, one for each operand type) for all functions and rewrite the function calls as a big loop inside a switch statement. This is (very) hard and not maintainable. You can start by reading this article (which deals with a simpler version of the problem).
Finally, you can use a background thread to host your parser's while loop. Send data to the parser using a pipe or a queue with a semaphore (if you can customize the input method). The issue here is that this background thread will (probably) not be able to update the UI because most framework are not thread-safe. So you will need a mechanism to send back information from the parser to the main UI thread (something like PostMessage.
References
Bison - push-parser interface, GNU, https://www.gnu.org/software/bison/manual/html_node/Push-Parser-Function.html
Coroutines in C, Simon Tatham, https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
Win32 API - PostMessage, Microsoft, https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagea
I've written my own access layer to a game engine. There is a GameLoop which gets called every frame which lets me process my own code. I'm able to do specific things and to check if these things happened. In a very basic way it could look like this:
void cycle()
{
//set a specific value
Engine::setText("Hello World");
//read the value
std::string text = Engine::getText();
}
I want to test if my Engine-layer is working by writing automated tests. I have some experience in using the Boost Unittest Framework for simple comparison tests like this.
The problem is, that some things I want the engine to do are just processed after the call to cycle(). So calling Engine::getText() directly after Engine::setText(...) would return an empty string. If I would wait until the next call of cycle() the right value would be returned.
I now am wondering how I should write my tests if it is not possible to process them in the same cycle. Are there any best practices? Is it possible to use the "traditional testing" approach given by Boost Unittest Framework in such an environment? Are there perhaps other frameworks aimed at such a specialised case?
I'm using C++ for everything here, but I could imagine that there are answers unrelated to the programming language.
UPDATE:
It is not possible to access the Engine outside of cycle()
In your example above, std::string text = Engine::getText(); is the code you want to remember from one cycle but execute in the next. You can save it for later execution. For example - using C++11 you could use a lambda to wrap the test into a simple function specified inline.
There are two options with you:
If the library that you have can be used synchronously or using c++11 futures like facility (which can indicate the readyness of the result) then in your test case you can do something as below
void testcycle()
{
//set a specific value
Engine::setText("Hello World");
while (!Engine::isResultReady());
//read the value
assert(Engine::getText() == "WHATEVERVALUEYOUEXPECT");
}
If you dont have the above the best you can do have a timeout (this is not a good option though because you may have spurious failures):
void testcycle()
{
//set a specific value
Engine::setText("Hello World");
while (Engine::getText() != "WHATEVERVALUEYOUEXPECT") {
wait(1 millisec);
if (total_wait_time > 1 sec) // you can put whatever max time
assert(0);
}
}
I'm making a simple graphics engine in C++, using Visual C++ and DirectX, and I'm testing out different map layouts.
Currently, I construct "maps" by simply making a C++ source file and start writing:
SHADOWENGINE ShadowEngine(&settings);
SPRITE_SETTINGS sset;
MODEL_SETTINGS mset;
sset.Name = "Sprite1";
sset.Pivot = TOPLEFT;
sset.Source = "sprite1.png";
sset.Type = STATIC;
sset.Movable = true;
sset.SoundSet = "sprite1.wav"
ShadowEngine->Sprites->Load(sset);
sset.Name = "Sprite2"
sset.Source = "sprite2.png";
sset.Parent = "Sprite1";
sset.Type = ANIMATED;
sset.Frames = 16;
sset.Interval = 1000;
sset.Position = D3DXVECTOR(0.0f, (ShadowEngine->Resolution->Height/2), 0.0f);
ShadowEngine->Sprites->Load(sset);
mset.Source = "character.sx";
mset.Collision = false;
mset.Type = DYNAMIC;
ShadowEngine->Models->Load(mset);
//Etc..
What I'd like to be able to do, is to create map files that are instead loaded into the engine, without having to write them into the executable. That way, I can make changes to the maps without having to recompile every damn time.
SHADOWENGINE ShadowEngine(&settings);
ShadowEngine->InitializeMap("Map1.sm");
The only way I can think of is to make it read the file as text and then just parse the information, but it sounds like such a hassle.
Am I thinking the wrong way?
What should I do?
Wouldn't mind an explanation on how others do it, like Warcraft III, Starcraft, Age of Empires, Heroes of Might and Magic...
Would really appreciate some help on this one.
You are not thinking the wrong way, loading your map data is definitely desirable. The most common prebuilt solutions are Protocol Buffers and Lua. If you don't already know Lua I would use protocol buffers, as it directly solves your problem, whereas Lua is a scripting language which is flexible enough to do what you need done.
Some people write their data as XML, but this is only a partial solution as XML is just a markup language. After loading the XML you'll have a DOM tree to parse.
Google's CPP Protobuf Tutorial
I need to put scriptable NPC in my currect game project.
The project itself is developed in C++ language.
I will using Luabind to bind lua and c++.
I need to call NPC function when certain NPC clicked or timer to do something is activated.
Currently I stuck between 2 NPC script design.
Using a kind of npcname_action to differentiate every NPC.
This is kind of troublesome to give name to every different NPC.
I'm still thinking how to implement this in my project.
Example:
HotelBellboy12_Click() { .. }
HotelBellboy12_TimerAction() { .. }
Using name of function.
Every npc have it own lua file.
I'm thinking to load script into memory and when needed will be loaded into luaState using luaL_loadbuffer
Example:
OnClick() { .. }
OnTimerAction() { .. }
Which one is better and why?
You could use another design.
Take advantage of the fact that table keys and values can be any type.
Let's say npc is a table containing all NPC's. Its keys are NPC' names and its values are another table. This other table keys are the actions, and its values are the function for this actions.
So, if you want bob to jump when clicked on, and alice to cry after a timer, simply do :
npc.bob.click = function () jump() end
npc.alice.timer = function () cry() end
I've done something like this before and I used something similar to your #2 option. When the map loads I load a configuration Lua file containing all the NPC data; among that is the name of the script file used for the NPC.
When I need to load the NPC in the game I compile the Lua file. NPC's can use a 'model' NPC type to dictate most of the common behavior (for example a Merchant type or a Commoner type) which is specified in the NPC configuration. These model types provide all the basic functionality such as providing a trade window when clicked. The specific NPC's use functions like OnClick() to override their model and provide custom handlers.
This worked pretty well for me, although it ends up being a large volume of scripts if your game gets large.
I have a class that processes a 2 xml files and produces a text file.
I would like to write a bunch of unit / integration tests that can individually pass or fail for this class that do the following:
For input A and B, generate the output.
Compare the contents of the generated file to the contents expected output
When the actual contents differ from the expected contents, fail and display some useful information about the differences.
Below is the prototype for the class along with my first stab at unit tests.
Is there a pattern I should be using for this sort of testing, or do people tend to write zillions of TestX() functions?
Is there a better way to coax text-file differences from NUnit? Should I embed a textfile diff algorithm?
class ReportGenerator
{
string Generate(string inputPathA, string inputPathB)
{
//do stuff
}
}
[TextFixture]
public class ReportGeneratorTests
{
static Diff(string pathToExpectedResult, string pathToActualResult)
{
using (StreamReader rs1 = File.OpenText(pathToExpectedResult))
{
using (StreamReader rs2 = File.OpenText(pathToActualResult))
{
string actualContents = rs2.ReadToEnd();
string expectedContents = rs1.ReadToEnd();
//this works, but the output could be a LOT more useful.
Assert.AreEqual(expectedContents, actualContents);
}
}
}
static TestGenerate(string pathToInputA, string pathToInputB, string pathToExpectedResult)
{
ReportGenerator obj = new ReportGenerator();
string pathToResult = obj.Generate(pathToInputA, pathToInputB);
Diff(pathToExpectedResult, pathToResult);
}
[Test]
public void TestX()
{
TestGenerate("x1.xml", "x2.xml", "x-expected.txt");
}
[Test]
public void TestY()
{
TestGenerate("y1.xml", "y2.xml", "y-expected.txt");
}
//etc...
}
Update
I'm not interested in testing the diff functionality. I just want to use it to produce more readable failures.
As for the multiple tests with different data, use the NUnit RowTest extension:
using NUnit.Framework.Extensions;
[RowTest]
[Row("x1.xml", "x2.xml", "x-expected.xml")]
[Row("y1.xml", "y2.xml", "y-expected.xml")]
public void TestGenerate(string pathToInputA, string pathToInputB, string pathToExpectedResult)
{
ReportGenerator obj = new ReportGenerator();
string pathToResult = obj.Generate(pathToInputA, pathToInputB);
Diff(pathToExpectedResult, pathToResult);
}
You are probably asking for the testing against "gold" data. I don't know if there is specific term for this kind of testing accepted world-wide, but this is how we do it.
Create base fixture class. It basically has "void DoTest(string fileName)", which will read specific file into memory, execute abstract transformation method "string Transform(string text)", then read fileName.gold from the same place and compare transformed text with what was expected. If content is different, it throws exception. Exception thrown contains line number of the first difference as well as text of expected and actual line. As text is stable, this is usually enough information to spot the problem right away. Be sure to mark lines with "Expected:" and "Actual:", or you will be guessing forever which is which when looking at test results.
Then, you will have specific test fixtures, where you implement Transform method which does right job, and then have tests which look like this:
[Test] public void TestX() { DoTest("X"); }
[Test] public void TestY() { DoTest("Y"); }
Name of the failed test will instantly tell you what is broken. Of course, you can use row testing to group similar tests. Having separate tests also helps in a number of situations like ignoring tests, communicating tests to colleagues and so on. It is not a big deal to create a snippet which will create test for you in a second, you will spend much more time preparing data.
Then you will also need some test data and a way your base fixture will find it, be sure to set up rules about it for the project. If test fails, dump actual output to the file near the gold, and erase it if test pass. This way you can use diff tool when needed. When there is no gold data found, test fails with appropriate message, but actual output is written anyway, so you can check that it is correct and copy it to become "gold".
I would probably write a single unit test that contains a loop. Inside the loop, I'd read 2 xml files and a diff file, and then diff the xml files (without writing it to disk) and compare it to the diff file read from disk. The files would be numbered, e.g. a1.xml, b1.xml, diff1.txt ; a2.xml, b2.xml, diff2.txt ; a3.xml, b3.xml, diff3.txt, etc., and the loop stops when it doesn't find the next number.
Then, you can write new tests just by adding new text files.
Rather than call .AreEqual you could parse the two input streams yourself, keep a count of line and column and compare the contents. As soon as you find a difference, you can generate a message like...
Line 32 Column 12 - Found 'x' when 'y' was expected
You could optionally enhance that by displaying multiple lines of output
Difference at Line 32 Column 12, first difference shown
A = this is a txst
B = this is a tests
Note, as a rule, I'd generally only generate through my code one of the two streams you have. The other I'd grab from a test/text file, having verified by eye or other method that the data contained is correct!
I would probably use XmlReader to iterate through the files and compare them. When I hit a difference I would display an XPath to the location where the files are different.
PS: But in reality it was always enough for me to just do a simple read of the whole file to a string and compare the two strings. For the reporting it is enough to see that the test failed. Then when I do the debugging I usually diff the files using Araxis Merge to see where exactly I have issues.