• We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.
I'm in Sweden and to me it says you posted 01:25 in the night ;). (Sweden is in the Central European time zone.) Assuming we round that time off to 01:40, it means you are 6 hours after me. I guess I'd have to stay up a bit late, and you would be able to talk to me in the early evening. However, as you say messaging in real time is not really necessary, but I think it enhances a feeling of responsability. Then again, it is more hard to present complete ideas in mIRC than in the forums or in email because one is expected to reply quickly.
 
Chaingun said:
I'm in Sweden and to me it says you posted 01:25 in the night ;). (Sweden is in the Central European time zone.) Assuming we round that time off to 01:40, it means you are 6 hours after me. I guess I'd have to stay up a bit late, and you would be able to talk to me in the early evening. However, as you say messaging in real time is not really necessary, but I think it enhances a feeling of responsability. Then again, it is more hard to present complete ideas in mIRC than in the forums or in email because one is expected to reply quickly.

This'll be fine then.

How about I put together what I'll say on the official thread to start it and then email it to you two?

- MVSN
 
That would be fine with me. I am currently busy, but tomorrow after the maths test I should have time again.

Hehe I think I'll make a go at designing a pseudo-loader for .EUG files in C++. If it works it should not be too hard to change the general structure to Java. The reason I want this code going is so that we can start to output valid .EUG files in a very short period of time.
 
Last edited:
I have now studied the most general file format of the .EUG files. This does not only apply to the .EUG files, but also to the event files, AI and POP files. It is entirely in what context the file is read which determines how the data gets interpreted. The format can at its simplest be described with the following:

Once '#' appears on a line, the rest of that line is discarded (that is until a new line character is detected).

Any number or text of undefined length is read until any delimiters are found. A delimiter is a white space, a tab, a new line, an equal sign, and the '{' and '}' signs. However, the equal sign and the '{' and '}' (that will hereby be incorrectly referred to as "parenthesis"), have special meanings although they do terminate the fields above. Therefore for general separation a space or tab must be used (or a new line if that's preferable). New lines only act as delimiters and do not disturb the general flow of text.

Each .EUG file contains a number of root nodes. That is, everything does not have to start from the same node. A node is defined as something which contains either other nodes or a data element array within it. Its syntax is: "node_name = data_element" or "node_name = { data_element_array/node_names }". A valid name for a node begins with an alphabet character (case does not matter), and may include an underscore character '_'. A name may not include a number or any other character however.

A data element is what is actually used by the game; nodes just tell where the data belong. Data might come in a single piece (when directly following the equal sign after the node), or as a part of an array. Data either is a number, that may include a period decimal sign '.', or a defined or undefined length string. The difference between the two string types is that an undefined length string goes on until a general delimiter is encountered, while a defined length string starts with a quote sign ' " ' and ends with another one. In addition to being declared differently these string types are also used differently in the game engine; UL strings are often (if not always) read and then used as constants that equal other things than the actual text data. DL strings however are used in such a way that the text data they contain are used directly within the engine. As such, UL strings have not been observed as case sensitive, while it often matters to a DL string. A DL string may also contain numbers and any other character until the ' " ' is reached (new lines though are forbidden).

That is about it. I may be wrong about certain details (especially what valid names are for nodes and what characters are valid). It can be easily correct when we learn more about the file format however. Even though everything looks complex it is not so complex that is looks as can be seen above.

Now for the question how I'll implement my test version of this (and how you may implement the Java version). Probably the file itself will have to be represented as an object, which can be saved or loaded from. A loading function would read through the file and create a tree like structure, where each branch would represent a number of nodes or data elements. If only one data element was found, that would mean no parenthesis had been found. A corresponding saving function would then save the contents of this tree to a visually pleasing file with indents for every new level of the tree.

So how would one connect this generic structure to the game data? Well, we could add a validation object (which also could be loaded from a file we've defined ourselves). It would create a pseudo-tree structure with a list of valid nodes and in some cases data elements for each node. A function would then be added either in this object or the file object to check whether the loaded data was valid or not. A clever communication system between both objects would mean that we could look up what node or data element to use for a certain thing we wanted to change in the validation object, and then make the modification with the file object. Of course the different validation objects would have to be created for each game (EU2, Victoria), and different file objects could be created to load different files at the same time.

I find the idea of writing this loader very intriguing, and I'll start tomorrow when my head is no as dizzy as it is now.
 
Chaingun said:
I have now studied the most general file format of the .EUG files. This does not only apply to the .EUG files, but also to the event files, AI and POP files. It is entirely in what context the file is read which determines how the data gets interpreted. The format can at its simplest be described with the following:

Once '#' appears on a line, the rest of that line is discarded (that is until a new line character is detected).

Any number or text of undefined length is read until any delimiters are found. A delimiter is a white space, a tab, a new line, an equal sign, and the '{' and '}' signs. However, the equal sign and the '{' and '}' (that will hereby be incorrectly referred to as "parenthesis"), have special meanings although they do terminate the fields above. Therefore for general separation a space or tab must be used (or a new line if that's preferable). New lines only act as delimiters and do not disturb the general flow of text.

Each .EUG file contains a number of root nodes. That is, everything does not have to start from the same node. A node is defined as something which contains either other nodes or a data element array within it. Its syntax is: "node_name = data_element" or "node_name = { data_element_array/node_names }". A valid name for a node begins with an alphabet character (case does not matter), and may include an underscore character '_'. A name may not include a number or any other character however.

A data element is what is actually used by the game; nodes just tell where the data belong. Data might come in a single piece (when directly following the equal sign after the node), or as a part of an array. Data either is a number, that may include a period decimal sign '.', or a defined or undefined length string. The difference between the two string types is that an undefined length string goes on until a general delimiter is encountered, while a defined length string starts with a quote sign ' " ' and ends with another one. In addition to being declared differently these string types are also used differently in the game engine; UL strings are often (if not always) read and then used as constants that equal other things than the actual text data. DL strings however are used in such a way that the text data they contain are used directly within the engine. As such, UL strings have not been observed as case sensitive, while it often matters to a DL string. A DL string may also contain numbers and any other character until the ' " ' is reached (new lines though are forbidden).

That is about it. I may be wrong about certain details (especially what valid names are for nodes and what characters are valid). It can be easily correct when we learn more about the file format however. Even though everything looks complex it is not so complex that is looks as can be seen above.

Now for the question how I'll implement my test version of this (and how you may implement the Java version). Probably the file itself will have to be represented as an object, which can be saved or loaded from. A loading function would read through the file and create a tree like structure, where each branch would represent a number of nodes or data elements. If only one data element was found, that would mean no parenthesis had been found. A corresponding saving function would then save the contents of this tree to a visually pleasing file with indents for every new level of the tree.

So how would one connect this generic structure to the game data? Well, we could add a validation object (which also could be loaded from a file we've defined ourselves). It would create a pseudo-tree structure with a list of valid nodes and in some cases data elements for each node. A function would then be added either in this object or the file object to check whether the loaded data was valid or not. A clever communication system between both objects would mean that we could look up what node or data element to use for a certain thing we wanted to change in the validation object, and then make the modification with the file object. Of course the different validation objects would have to be created for each game (EU2, Victoria), and different file objects could be created to load different files at the same time.

I find the idea of writing this loader very intriguing, and I'll start tomorrow when my head is no as dizzy as it is now.

Excellent. Yeah, I knew the .eug files would be a problem. I'm taking a look at some of the files now. I'm finally finished my other events for C.O.R.E. so I'm ready to rock!
 
An overview of the general syntax is:

Code:
#Comment
root_node =
{
    child_node = single_data
    child_node =
    {
        array_data1 array_data2 array_data3
    }
    child_node =
    {
        child_node = single_data
        child_node =
        {
            child_node = single_data
            child_node = single_data
        }
    }
    child_node = single_data #Another valid comment
}
root_node = single_data
 
Last edited:
Hehe I'll start with the actual logic of the EUG loader very soon. I am just halted right now because I attempt to actually finish an EU2 World Conquest (even though it's supposed to be easy I want to be able to say I've done it). Unfortunely it takes quite a lot of time with all that micromanagement.
 
Chaingun said:
Hehe I'll start with the actual logic of the EUG loader very soon. I am just halted right now because I attempt to actually finish an EU2 World Conquest (even though it's supposed to be easy I want to be able to say I've done it). Unfortunely it takes quite a lot of time with all that micromanagement.

Sorry guys, I seem to be infected with some sort of virus that is causing me havok. I did today finally achieve a closure to my CORE events for HoI, so hopefully I can be a lot more helpful in the near future :).

- MVSN
 
mvsnconsolegene said:
Sorry guys, I seem to be infected with some sort of virus that is causing me havok. I did today finally achieve a closure to my CORE events for HoI, so hopefully I can be a lot more helpful in the near future :).

- MVSN

Okay guys, let's get started, I know chaingun already has :). I'll send PM to everybody to exactly what they want to do and then...well...let's go!

I think above everything else, the three team leaders FooFighter, Chaingun, and myself will be responsible for the actual loader itself since nobody else seems to be interested.

- MVSN
 
I'm fighting the time issue currently (I'm about to fail HL maths in school so it's quite some work to catch up). As far for the loader goes I've got the shell done, and I've started on the actual loading code.
 
Chaingun said:
I'm fighting the time issue currently (I'm about to fail HL maths in school so it's quite some work to catch up). As far for the loader goes I've got the shell done, and I've started on the actual loading code.

Yeah, I think we all are finding more *REAL* work thrown at us.

Don't worry.

- MVSN
 
Chaingun said:
I'm fighting the time issue currently (I'm about to fail HL maths in school so it's quite some work to catch up). As far for the loader goes I've got the shell done, and I've started on the actual loading code.

Yeah, I think we all are finding more *REAL* work thrown at us.

Don't worry.

- MVSN
 
A combined progress report and a question. Firstly, do you find my coding style below readable? This is important because some poor person will have to study it and convert it to Java. Secondly, I am right now working with the ReadLine() function, which is a real test I tell you.

Currently I have a loop inside ReadLine() that reads all the characters on the line, and now I have two options for reading the elements of the .EUG file: Either a recursive or a state machine approach. If the recursive approach is taken I'll have to create several sub functions to deal with each kind of keyword, the problem with this then is that the type of keyword is not always known before some element after it shows up. A state machine approach however causes a lots of if statements in the reading loop and other complexity.

Code:
bool CFile::Load(std::string filename)
{
    unsigned int error_count;

    //try to open input file
    m_stream.open(filename.c_str(), std::ios::in | std::ios::binary);
    
    //check if file was opened
    if(!m_stream.is_open())
    {
        std::cout << "File error: " << filename <<
            "\nThis file could not be opened for input.\n";
        return false;
    }
    
    //set up some stuff
    m_line = 0;
    error_count = 0;
    m_roots = new Node;
    m_roots->parent = 0;
    m_roots->children_type = c_NODE;
    
    //read one character to start with
    GetNextChar();
    
    //reading loop (per line mainly)
    while(m_look != 0)
    {
        m_line++;
        if(!ReadLine())
            error_count++;
        SkipNewLine();
    }
    
    std::cout << "\nThere were " << error_count <<
        " errors during loading.\n\n";
    
    //close file
    m_stream.close();
    
    return true;
}
 
Last edited:
Ah great the ReadLine() function is soon finished (unless it's harder than expected I should be able to finish file loading this weekend). After that I figured I should try to make some buffered input system, as I'm right now reading one character at a time from file, which is not too efficient with all those function calls. However this is not of such a high priority, and of course the most important thing is that the loader works.

After that I plan to implement the save function. It will probably be many times easier than the loading function, mostly due to the fact it is just to iterate through the tree structure and emit code without any consideration to the previous code emitted. Once this is finished someone should start to consider to convert it to Java since that's what this project will use.
 
Chaingun said:
Ah great the ReadLine() function is soon finished (unless it's harder than expected I should be able to finish file loading this weekend). After that I figured I should try to make some buffered input system, as I'm right now reading one character at a time from file, which is not too efficient with all those function calls. However this is not of such a high priority, and of course the most important thing is that the loader works.

After that I plan to implement the save function. It will probably be many times easier than the loading function, mostly due to the fact it is just to iterate through the tree structure and emit code without any consideration to the previous code emitted. Once this is finished someone should start to consider to convert it to Java since that's what this project will use.

I'm getting to understand it. Don't worry, I can eventually put together anything :).

I suppose I'll be the conversion monkey. With regards to webspace, does anyone have any ideas? I just want to post the province conversions I'm planning.

- MVSN
 
I think we should apply for some free webspace provider, with no respects to commercials etc. The more important thing is whether their connection is stable or not. I have a ~50 MB webspace on my website too, however I do not really want to give away the password for the FTP upload. In the case we'll use it instead you'll have to send me compressed files via email, and even then it's not too good since my email server provider automatically reject files with certain endings. I know .zip is one of these endings, so you'd had to rename it to .111 or something before you sent it.

A few more notes about my implementation. This is the first project I've relied that heavily upon the Standard Template Libarary. Even though the version of the library that comes with DevCPP is quite unimplemented (at least when it comes to the std::string class), it still contains the basic useful functions. For everything else I use legacy C functions (again quite often with the std::string). Another quirk for Java conversion is the fact I in my tree node structure have a std::vector that can be filled with void* pointers to the node's children. These points can point to doubles, std::vectors or other nodes when necessary. I'd say this can cause trouble for Java, since I do not know what similar abilities that language possesses. Else you will have to figure a new way to add child nodes to the tree... :eek:

Unfortunely (or fortunely ;)), I got sick today and as such I was home from school. I have almost finished the reading function by now; it now reads nodes, UL strings and numbers like a charm. The only thing left to add to ReadLine() is support for DL strings.
 
Last edited:
Chaingun said:
I think we should apply for some free webspace provider, with no respects to commercials etc. The more important thing is whether their connection is stable or not. I have a ~50 MB webspace on my website too, however I do not really want to give away the password for the FTP upload. In the case we'll use it instead you'll have to send me compressed files via email, and even then it's not too good since my email server provider automatically reject files with certain endings. I know .zip is one of these endings, so you'd had to rename it to .111 or something before you sent it.

A few more notes about my implementation. This is the first project I've relied that heavily upon the Standard Template Libarary. Even though the version of the library that comes with DevCPP is quite unimplemented (at least when it comes to the std::string class), it still contains the basic useful functions. For everything else I use legacy C functions (again quite often with the std::string). Another quirk for Java conversion is the fact I in my tree node structure have a std::vector that can be filled with void* pointers to the node's children. These points can point to doubles, std::vectors or other nodes when necessary. I'd say this can cause trouble for Java, since I do not know what similar abilities that language possesses. Else you will have to figure a new way to add child nodes to the tree... :eek:

Unfortunely (or fortunely ;)), I got sick today and as such I was home from school. I have almost finished the reading function by now; it now reads nodes, UL strings and numbers like a charm. The only thing left to add to ReadLine() is support for DL strings.

I'm following a lead for webspace as we speak, I'm heading back to Toronto and should hopefully have this resolved by monday.

- MVSN