Jump to content

CnCNet Forums

Search In
  • More options...
Find results that contain...
Find results in...
CCHyper

Introducing RedAlert++

Recommended Posts

It would allow you to serialize the current game state in a format similar to the one used for initial map loading

Not really. That format doesn't have any support for vehicles in motion situated in a certain specific position in between two cells. Not to mention their currently executing command and its specific properties. The nesting of such objects doesn't make it suited for ini format. XML, maybe, but not ini. :dry:

 

It is just that, some internal classes will not be exactly the same size,

Hmm. I think Dynasty solved that by adding extra object information as actual extra information while keeping the original object structure intact, so any extra info (for example, build queue per producing building) could be saved separately. What kind of things are you changing?

 

and/or will not use the same storage type.

You mentioned that. Why exactly are you changing it?

Share this post


Link to post
Share on other sites
and/or will not use the same storage type.

You mentioned that. Why exactly are you changing it?

 

Red Alert uses bitfields to pack all boolean values, this is a optimisation that the Watcom compiler did at the time, and something that is not longer done (as we don't have the constraints they at the time).

 

Second, is that the enumerations where packed depending on the size of the largest entry, so where UNIT_NONE would equal "-1" 32bit integer in our codebase, Red Alert stores this is a "-1" 8bit char. This causes more headaches that you would think. The same goes for some structures too, but this was intentional and no longer applies to us.

Share this post


Link to post
Share on other sites

Ah, heh. I guess modern compilers are more mindful of the difference between different int types.

Share this post


Link to post
Share on other sites

Ah, heh. I guess modern compilers are more mindful of the difference between different int types.

I don't see how this is relevant. It's quite obvious that what CCHyper describes is an optimization (not just one, but two) in favour of size, talk about memory footprint, over speed.

 

BTW, the MSVC compiler supported explicitly deriving enums from arbitrary integral types, since I can think of. So does C++11.

 

The underlying type of an enumeration is an integral type that can represent all the enumerator values defined in the enumeration. It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.

 

Share this post


Link to post
Share on other sites

Compiler optimizations should, by definition, have no impact on written code, though. The only reason I can see for it affecting stuff is if the game just plain dumps objects from memory straight to file, and the objects in mem happen to have these optimizations.

Share this post


Link to post
Share on other sites

Well, it's not really affecting anything, now is it. There's a default integer for literals which is always signed and in my case 32 bits.

 

So, you might be a little surprised, but:

0xffffffff == (char)-1 // true
(unsigned)0xffffffff == (char)-1 // true
~0 == (char)-1 // true
-1 == (char)-1 // true

All of these assumptions, are true, which to me is not surprising, at all. Since you're always comparing -1 with -1.

 

However, you can't assume that this is also true:

0xffffffff == (unsigned char)-1 // false

Because it is not. You're comparing -1 with 0xff (255) here.

 

Share this post


Link to post
Share on other sites

Compiler optimizations should, by definition, have no impact on written code, though. The only reason I can see for it affecting stuff is if the game just plain dumps objects from memory straight to file, and the objects in mem happen to have these optimizations.

 

Which is exactly what it looks like the game does. OpenDUNE went out of their way to use bitfields for some stuff to ensure the serialised format was the same from what I can tell, but that just makes the code harder to read and maintain IMO. Lets forget this focus on the save game formats as we are a bit off implementing the serialisation routines for objects yet. We may come up with a slightly nicer on disk binary format than just dump everything, but at the end of the day it still won't support the old saves out of the box.

Share this post


Link to post
Share on other sites
It would allow you to serialize the current game state in a format similar to the one used for initial map loading
Not really. That format doesn't have any support for vehicles in motion situated in a certain specific position in between two cells. Not to mention their currently executing command and its specific properties.
Oh, you'd definitely have to add in serialization information for those situations, but you could still use an extended version of the map loading format. From my understanding, a vehicle can't be in more than one cell at once, regardless of it's actual position on the map, so storing both a reference to it's current cell and a global map position or a X/Y offset in leptons from the current cell could both work.
The nesting of such objects doesn't make it suited for ini format. XML, maybe, but not ini. :dry:
You can fake it with lists to other sections or by having a section that contains comma or semicolon separated values, but I agree that INI isn't as well suited to serializing a game state as other markup languages. I mainly suggested INI for the high code reuse it would allow. (Personally, my favorite markup language is a custom one I made, based off of the Universal Doom Map Format and ZDoom's DECORATE format, but I doubt it would get much adoption over YAML.)

Share this post


Link to post
Share on other sites

The nesting of such objects doesn't make it suited for ini format. XML, maybe, but not ini. :dry:

You can fake it with lists to other sections or by having a section that contains comma or semicolon separated values, but I agree that INI isn't as well suited to serializing a game state as other markup languages.

Yeah... I did that kind of stuff with the project files for my .mrf generator. Its ini format... isn't all that pretty. I had to add specific logics into it for cleaning up the detail objects of larger objects :roll:

Share this post


Link to post
Share on other sites

Could we get a little more information on what's the status of this project?

 

What's currently working? Pathfinding, AI state machine, is the campaign playable, etc?

 

When can we expect a first public preview? This year, next year, when Red Alert 4 comes out?

 

Sorry, I'm a little too excited :P

Share this post


Link to post
Share on other sites

Its currently a lot of low level stuff that work correctly, Mix loading, ini parsing, a bunch of boring (from the pov of a player) stuff so far. We have the skeleton of the game classes mapped out, but there is still a lot to do before we have path finding and state machine working.

 

How long did it take for OpenDUNE to get to the point where it was playable? Think that kind of time scale if not longer.

Share this post


Link to post
Share on other sites

Could we get a little more information on what's the status of this project?

 

What's currently working? Pathfinding, AI state machine, is the campaign playable, etc?

 

When can we expect a first public preview? This year, next year, when Red Alert 4 comes out?

 

Sorry, I'm a little too excited :P

 

Just adding to what Blade also mentioned, a lot of the core is ready and waiting for one key element from the low level systems. Once we sign off the low level as being tested and passed, then a lot of the visual features will come into play and allow us to roll out features at a rapid rate. But for now, just like any other project, build the foundations before you worry about the colour of the brick!

 

OpenDUNE was started in '09 IIRC, and made its first playable build two years later. RedAlert++ has been under development for quite some time behind the scenes, and we aim on producing a friendly, accessable and highly extendable engine too. We might make a decision that would add a few months onto the project time, but in the future, this decision will shave a lot of time development in the future in terms of extending and porting the engine across multipule platforms.

Share this post


Link to post
Share on other sites

I've got a nice INI parsing class, somewhere (very speedy and doesn't choke on Westwood INIs).  :heady:

 

A few questions:

  • You say your engine will be flexible. Could it, one day, be made to basically be RA2?
  • Do you guys leverage C++ templates, a lot? Or prefer to go without as much as reasonably possible?
  • Do you guys use .CPP or .CC (hint, hint: CCHyper) file extensions for your source files?

 

I also wanted to repeat my utmost respect for you guys and your endeavor. I especially like your Avatar, CCHyper! Spot on.  :yo:

 

Share this post


Link to post
Share on other sites

I've got a nice INI parsing class, somewhere (very speedy and doesn't choke on Westwood INIs).  :heady:

 

A few questions:

  • You say your engine will be flexible. Could it, one day, be made to basically be RA2?
  • Do you guys leverage C++ templates, a lot? Or prefer to go without as much as reasonably possible?
  • Do you guys use .CPP or .CC (hint, hint: CCHyper) file extensions for your source files?

 

I also wanted to repeat my utmost respect for you guys and your endeavor. I especially like your Avatar, CCHyper! Spot on.  :yo:

 

We have a huge INI engine, and it is very extendable. I do not think there is one of this size public (outside of a AAA company). :D

 

As for your questions;

  1) Of course, if you want to put in the work! ;)

  2) We make use of templates in many cases, a few classes require templates due to the item they are storing.

  3) We use CPP, H and HH for file extensions. HH is used for defines and enumerations of classes where we do not want to include the whole class header.

 

 

Share this post


Link to post
Share on other sites

Curiosity killed the cat, as they say. I'm sure many would like to see what you've conjured up to date.

 

Could you show us a sneak preview on GitHub? We promise not to laugh, not too much anyway  ;)

 

EDIT: Also, what license will you be using? MIT, GPL, Apache?

Share this post


Link to post
Share on other sites

There are no plans to make any kind of preview of the code, I don't really see what it would accomplish (other than prove we are doing something). The final licence will likely be GPL v2 or later or GPL v3 or later.

Share this post


Link to post
Share on other sites

and/or will not use the same storage type.

You mentioned that. Why exactly are you changing it?

 

Red Alert uses bitfields to pack all boolean values, this is a optimisation that the Watcom compiler did at the time, and something that is not longer done (as we don't have the constraints they at the time).

 

Second, is that the enumerations where packed depending on the size of the largest entry, so where UNIT_NONE would equal "-1" 32bit integer in our codebase, Red Alert stores this is a "-1" 8bit char. This causes more headaches that you would think. The same goes for some structures too, but this was intentional and no longer applies to us.

template<unsigned _Count, typename _Type>
struct BitFlags
{
enum
{
	BitsInSpan = 8,
	NumSpans = (((_Count + (BitsInSpan - 1)) / BitsInSpan))
};

char m_Value[NumSpans];
};

An enum data type can be similar. This would make it easy to access and work with enums and bitflags of variable length.

For example:

enum EMyType
{
MYTYPE_NONE = -1,
MYTYPE_0,
MYTYPE_1,
MYTYPE_2,
MYTYPE_3,
MYTYPE_4
};
typedef BitFlags<5, EMyType> MyTypeBitFlags;

Would result in a  8 bit representation of EMyType. And get the flag with something like

void SetFlag(EMyType value)
{
if (value == MYTYPE_NONE) // -1
{
	return; // or something else you want -1 to do
}
m_Value[value / BitsInSpan] |= (1 << value % BitsInSpan)
}

void RemoveFlag(EMyType value)
{
if (value == MYTYPE_NONE) // -1
{
	return;
}
m_Value[value / BitsInSpan] &= ~(1 << value % BitsInSpan)
}

bool HasFlag(EMyType value)
{
if (value == MYTYPE_NONE)
{
	return false;
}
return m_Value[value / BitsInSpan] & (1 << value % BitsInSpan)
}

 

Pretty much no effort involved in having variable size bit fields.

Share this post


Link to post
Share on other sites

Curiosity killed the cat, as they say. I'm sure many would like to see what you've conjured up to date.

 

Could you show us a sneak preview on GitHub? We promise not to laugh, not too much anyway  ;)

 

EDIT: Also, what license will you be using? MIT, GPL, Apache?

 

I just want to add to Blades reply; We are still in a heavy process of rewriting and testing various parts of the engine. Making the code public at this moment would be detrimental to the project as it is of no use to anyone other than for literary purposes.

 

As soon as we have something that is suitable for publishing we will be creating a public GitHub for RedAlert++, and we promise to keep you updated!

 

 

template<unsigned _Count, typename _Type>
struct BitFlags
{
enum
{
	BitsInSpan = 8,
	NumSpans = (((_Count + (BitsInSpan - 1)) / BitsInSpan))
};

char m_Value[NumSpans];
};

An enum data type can be similar. This would make it easy to access and work with enums and bitflags of variable length.

For example:

enum EMyType
{
MYTYPE_NONE = -1,
MYTYPE_0,
MYTYPE_1,
MYTYPE_2,
MYTYPE_3,
MYTYPE_4
};
typedef BitFlags<5, EMyType> MyTypeBitFlags;

Would result in a  8 bit representation of EMyType. And get the flag with something like

void SetFlag(EMyType value)
{
if (value == MYTYPE_NONE) // -1
{
	return; // or something else you want -1 to do
}
m_Value[value / BitsInSpan] |= (1 << value % BitsInSpan)
}

void RemoveFlag(EMyType value)
{
if (value == MYTYPE_NONE) // -1
{
	return;
}
m_Value[value / BitsInSpan] &= ~(1 << value % BitsInSpan)
}

bool HasFlag(EMyType value)
{
if (value == MYTYPE_NONE)
{
	return false;
}
return m_Value[value / BitsInSpan] & (1 << value % BitsInSpan)
}

 

Pretty much no effort involved in having variable size bit fields.

 

Thank you for your suggestion. I understand what you are trying to achieve and agree that this is a workable solution. However, as mentioned before, we have decided that we will not be supporting legacy save games as we do not want to restrict the code base for just this feature. This means we can take a more professional approach to the project and create a more customisable engine.

Share this post


Link to post
Share on other sites

Are you guys going to release any RedAlert++ related Christmas gifts this year?

 

Oh and by the way, I don't mean to rush this project, but the original game was released in 1996 and yours still isn't done. /s

Share this post


Link to post
Share on other sites

I don't think we have plans for any sweet merch (unless CCHyper wants to correct me), so no Xmas goodies I'm afraid.

 

The original game had most of the low level stuff done already for C&C. There was the porting to windows and the new ini engine that was added, but we are having to write it all mostly from scratch and are trying to keep it cross platform. In short, don't be a cheeky git, it will be done when its done and be the next best thing to the original code being released :P

Share this post


Link to post
Share on other sites
Are you guys going to release any RedAlert++ related Christmas gifts this year?

I would love to release something for Christmas, perhaps Blade might finish another of hes tools in time, but there is still more of the core engine code we need to complete and playtest, and we cant rush this.

 

Oh and by the way, I don't mean to rush this project, but the original game was released in 1996 and yours still isn't done. /s

I think that most gamers make the assumption that games are simple to code. Added to the fact that we are not using any existing game or graphics engine or core library to work from, I would say we have have excellent progress so far.

 

As i mentioned, there is so much more for us to do with the core game engine. We like to see the engine in 4 parts;

 

Core: This contains all our base core for performing basic functions, this can be timer systems, file I/O, cryptography and algorithms, data buffers and so on. the Core of the engine is required by pretty much Audio, Visual and Game Logic.

 

Audio: Sounds simple enough (sorry...), but a Audio engine that is capable of mixing various levels of audio and at different rates is a consuming task, and the audio engine is in the last of our prioritys as there is no point in having sound if you have no units on the screen! We will be sticking to SDL for audio and will decide if we need to jump to OpenAL if our requirements are too much.

 

Visual: This is pretty much complete, the only remaining task for the graphics engine is making sure it can handle our requirements. Again, we have decided to stick to SDL for audio and will decide if we need to jump to OpenGL if our requirements are too much.

 

Game Logic: This is our biggest task to tackle. Making sure we incorperate the game system and hierarchy so all objects interact as intended. Aswell as the research required by play testing the original so we can brainstorm way of coding a feature. This part takes time, and we have a good idea how want this part of the engine to operate, but we can not play test the features until we know for sure certain other parts work as required (Map loading, Cell drawing etc).

Share this post


Link to post
Share on other sites

The only logic i hope that isn't 100% copied is the horrible path finding. :P

 

Also is the cncnet dev channel down? freenode gives me this ''[17:44] == #cncnet Cannot join channel (+k) - bad key''

Share this post


Link to post
Share on other sites

I never found RA1s path finding really bad. I may not always take the fastest way but is better than TS/RA2.

Share this post


Link to post
Share on other sites

I never found RA1s path finding really bad. I may not always take the fastest way but is better than TS/RA2.

 

I think the only real issue is the "re-routing" effect you get when passing over narrow bridges and things. That is just straight up annoying.

Share this post


Link to post
Share on other sites

I think the only real issue is the "re-routing" effect you get when passing over narrow bridges and things. That is just straight up annoying.

 

Possibly a big reason for WW going for two square wide bridges and fords after TD.

That, and also harv pathfinding. They can only judge distance in a straight line and will go on unimaginable detours around cliffs and rivers.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...