Trunk discussion / complains

After r3686 I can’t compile the game at all, probably due to issue with unique_ptr

Error	3	error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>'	C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xutility	2089
Error	5	error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>'	C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xutility	2089
Error	7	error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>'	C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xutility	2089
Error	30	error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall EventCondition::EventCondition(struct EventCondition const &)" (__imp_??0EventCondition@@QAE@ABU0@@Z)	E:\Programowanie\VCMI\vcmi\AI\VCAI\Goals.obj
Error	31	error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall EventCondition::~EventCondition(void)" (__imp_??1EventCondition@@QAE@XZ)	E:\Programowanie\VCMI\vcmi\AI\VCAI\Goals.obj
Error	32	error LNK1120: 2 unresolved externals	E:\Programowanie\VCMI\AI\VCAI.dll
Error	37	error LNK2001: unresolved external symbol "__declspec(dllimport) public: class EVictoryLossCheckResult __thiscall EVictoryLossCheckResult::invert(void)" (__imp_?invert@EVictoryLossCheckResult@@QAE?AV1@XZ)	E:\Programowanie\VCMI\vcmi\server\CGameHandler.obj
Error	38	error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall EVictoryLossCheckResult::EVictoryLossCheckResult(class EVictoryLossCheckResult const &)" (__imp_??0EVictoryLossCheckResult@@QAE@ABV0@@Z)	E:\Programowanie\VCMI\vcmi\server\CGameHandler.obj
Error	39	error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall EVictoryLossCheckResult::~EVictoryLossCheckResult(void)" (__imp_??1EVictoryLossCheckResult@@QAE@XZ)	E:\Programowanie\VCMI\vcmi\server\CGameHandler.obj
Error	40	error LNK1120: 3 unresolved externals	E:\Programowanie\VCMI\VCMI_server.exe	1
Error	49	error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall EventCondition::EventCondition(enum EventCondition::EWinLoseType)" (__imp_??0EventCondition@@QAE@W4EWinLoseType@0@@Z)	E:\Programowanie\VCMI\vcmi\client\CPreGame.obj
Error	50	error LNK2001: unresolved external symbol "__declspec(dllimport) public: struct EventCondition & __thiscall EventCondition::operator=(struct EventCondition const &)" (__imp_??4EventCondition@@QAEAAU0@ABU0@@Z)	E:\Programowanie\VCMI\vcmi\client\CPreGame.obj
Error	51	error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall EventCondition::~EventCondition(void)" (__imp_??1EventCondition@@QAE@XZ)	E:\Programowanie\VCMI\vcmi\client\CPreGame.obj
Error	52	error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall EventCondition::EventCondition(struct EventCondition const &)" (__imp_??0EventCondition@@QAE@ABU0@@Z)	E:\Programowanie\VCMI\vcmi\client\CPreGame.obj
Error	53	error LNK1120: 4 unresolved externals	E:\Programowanie\VCMI\VCMI_client.exe	1

In this code (line 77 InputStream)

	std::pair<std::unique_ptr<ui8]>, size_t> readAll()
	{
		std::unique_ptr<ui8]> data(new ui8[getSize()]);

		seek(0);
		size_t readSize = read(data.get(), getSize());
		assert(readSize == getSize());
		UNUSED(readSize);

		return std::make_pair(std::move(data), getSize());
	}

This makes entire engine fail as well :stuck_out_tongue:

That’s weird - some of these symbols are actually present in .cpp’s so they should not trigger this while some are not defined at all like EventCondition destructor so they should be generated by compiler. And all of them are marked as DLL_LINKAGE.

I found two structures not marked as such (will commit) but they are not mentioned in this log at all.

The linker errors are likely irrelevant. The lib fails to build and most probably old lib (from previous compilation) gets linked in.

Figured this out.
When class is marked with DLL_LINKAGE, Visual attempts to instantiade its copy ctor and copy assignment operator. Because CFilesystemList contains a non-copyable field (vector of unique ptr), the default copy-ctor and assignment cause compile error.

The fix is to provide dummy methods like:

	CFilesystemList(CFilesystemList &)
	{
		assert(0); //class is not copyable
	}
	CFilesystemList &operator=(CFilesystemList &)
	{
		assert(0); //class is not copyable
		return *this; 
	}

Ugly.
Or, if we were to target Visual 2013, we could simply =delete them.

A bit more elegant solution would be to make these methods private, so they fail at compile time and not runtime.

Yes, such dummy methods preferably should be private.
Still, it’s good to keep the assert even in private method, since the class might attempt to copy itself (eg. in one of its methods). Private hides it only from the outside.

I have the problem that I need to deep copy an instance of CGHeroInstance. Campaign data with progress is kept in the client and won’t be deleted after playing a scenario. In the campaign data for every completed scenario a list of hero instances/crossover heroes will be stored. When crossover heroes travel to the next scenario they should be deep-copied to not modify original crossover heroes. Otherwise it would be possible to restart the scenario with the heroes state of the current map.

There are 3 possible solutions:
a) manually write a copy c-tor (error-prone, laborious, code duplication with serialization code)
b) remove d-tor in CGObjectInstance and all subclasses to autom. generate copy-ctor by compiler -> not possible due to objects holding strong ownership of other objects, you can’t copy unique_ptr
c) use serialization code to copy objects: e.g. Util::copyObject(whatever) returns copied instance of whatever -> use loader and saver functionality and cache data in memory (buffer) -> should be simple, stable, no code duplication, not as fast as direct copy but code is in general more important than performance

Just want to let you know, that I added knowledge and spell power into hero strength calculation. (checked with OH3 and hero placeholder handling) I hope that it won’t cause any problems.

It is very difficult to ever evaluate usefulness of spells by AI and ESPECIALLY the usefulness of knowledge. I’m pretty sure it will result in high AI suicide rate, better roll it back.

Not to mention hero strength is used also by core game mechanics, like diplomacy.

For me it seems by far the best approach.

And well… I believe right now saving a CGHeroInstance* to a file and subsequently loading it produces a deep copy.
File IO is a bit too much wasteful for my taste, but if a special serializer is provided that stores an object to an memory buffer (even a crude vector should suffice) then it should be enough.
Implementing new serialzier should be strightforward. Inherit CIser and COser and “override” write/read functions.
Set special features flags in a constructor if needed. (AFAIR defaults should suffice)

Then, something like this should clone hero (or object of virtually any serializable type)

*this << hero
CGHeroInstance *copy;
*this >> copy

Mind that deep copy will also store parts of game rules objects (VLC (like CHero).

Just provide a flag parameter for deciding whether include spell power/knowledge in calculation or not. Or split to it to 3 methods: fightingStrength, magicStrength, totalStrength or sth like this.
Apparently both variants of strength calcualtion are needed in engine.

Is it only me, or the game started to BEEP when certain errors occur? oO

This is unexpected. Is there some way I can reproduce this issue?

BEEP usually happens when ‘\b’ character is written to console output.

Yes, I figured it out. This happens when AI prints some nonsense with caught exception. Not sure how to reproduce yet or why it didn’t happen before.

I don’t know where to write this, but I think it should be OK here. We have a lot of assigned mantis points. Problem is that you really don’t know if someone is currently working on a specific mantis point. I would like to suggest to use assigned to only if it’s in progress by someone.

I have de-assigned a few mantis points, currently I’m working on #1597 and #1643 only. Warmonger, could you disable default assignments? I look into mantis frequently and use filters to find mantis points.

What about priorizing mantis points? I think it would be great if 1 or 2 developers priorize from time to time up to 10 mantis points. Highly priorized mantis points with severity crash/block should be done first, less priorized mantis points with severity minor later for example.

I unassigned RMG from you.

Currently the issue is that no one is doing anything, as it’s end of semester for most of us. Not to mention Ivan who must be really busy with revolution now.

Thanks. Yes, we don’t study anymore… :frowning:

By the way, maybe use AI to evaluate adventure map monsters strength (AI value, fight value)?
Nobody seems to set meaningful values for creatures. And if AI will be clever, let it alone decide what strength creatures before him have.
As for creatures placement on map for guarding purposes (when preparing map), it can be done alone with their level value and/or summary hitpoints.

Eventually, yes, but it’s difficult AND very complex. Also, game engine or interface can’t use AI knowledge.

Teach them.

That’s way too simple, inacurrate and will lead to lack of balance.

Guys, I’ve run vcmi through cppcheck again, there are some things that bother me.
server/CGameHandler.cpp

if ( (s1->tempOwner != player && s1->getStackCount(p1) < s1->getStackCount(p1) )
			|| (s2->tempOwner != player && s2->getStackCount(p2) < s2->getStackCount(p2) ) )
if (s->mainEffectAnim > -1 || (s->id >= 66 || s->id <= 69) || s->id == SpellID::CLONE) //allow summon elementals

I think these are ctrl+c - ctrl+v problems, the second one definitely requires && instead of ||.

launcher/modManager/cmodlistmodel_moc.cpp

case ModFields::STATUS_ENABLED:
		{
			return (mod.getModStatus() & (ModStatus::ENABLED | ModStatus::INSTALLED))
			     < (mod.getModStatus() & (ModStatus::ENABLED | ModStatus::INSTALLED));
		}
		case ModFields::STATUS_UPDATE:
		{
			return (mod.getModStatus() & (ModStatus::UPDATEABLE | ModStatus::INSTALLED))
			     < (mod.getModStatus() & (ModStatus::UPDATEABLE | ModStatus::INSTALLED));
		}

Also not very clear to me.

AI/VCAI/VCAI.cpp

if (newMovement == oldMovement) //means our heroes didn't move or didn't re-assign their goals
			{
				logAi->warnStream() << "Our heroes don't move anymore, exhaustive decomposition failed";
			}
				break;
			if (safeCopy.empty())
				break; //all heroes exhausted their locked goals
			else

Wouldn’t it break after the first break and nothing down this break would be never executed?

Also there are some things like

The struct 'HireHero' defines member variable with name 'player' also defined in its parent struct 'CPackForServer'.

I assume such redefining is useless, tell me if I’m wrong.

Attached report.txt (which is report.xml) for those who’re interested.
report.txt (26.6 KB)