void C4Team::RecheckColor(C4TeamList &rForList)
{
	// number of times trying new player colors
	const int32_t C4MaxTeamColorChangeTries = 100;
	if (!dwClr)
	{
		const int defTeamColorCount = 10;
		DWORD defTeamColorRGB[defTeamColorCount] = { 0xF40000, 0x00C800, 0xFCF41C, 0x2020FF, // red, green, yellow, blue,
		    0xC48444, 0xFFFFFF, 0x848484, 0xFF00EF, // brown, white, grey, pink,
		    0x00FFFF, 0x784830
		                                           }; // cyan, dk brown
		// no color assigned yet: Generate by team ID
		if (iID >=1 && iID <=defTeamColorCount)
		{
			// default colors
			dwClr = defTeamColorRGB[iID-1] | 0xff000000;
		}
		else
		{
			// find a new, unused color
			for (int32_t iTry=1; iTry<C4MaxTeamColorChangeTries; ++iTry)
			{
				dwClr = GenerateRandomPlayerColor(iTry);
				int32_t iIdx=0; C4Team *pTeam; bool fOK=true;
				while ((pTeam = rForList.GetTeamByIndex(iIdx++)))
					if (pTeam != this)
						if (IsColorConflict(pTeam->GetColor(), dwClr))
						{
							fOK=false;
							break;
						}
				// color is fine?
				if (fOK) return;
				// it's not; try next color
			}
			// Giving up: Use last generated color
		}
	}
}
void C4PlayerInfoListAttributeConflictResolver::ResolveInInfo()
{
	// trial-loop for assignment of new player colors/names
	int32_t iTries = 0;
	// original/alternate conflict evaluated once only
	fOriginalConflict = false;
	fAlternateConflict = (eAttr == C4PlayerInfo::PLRATT_Name) || !pResolveInfo->GetAlternateColor(); // mark as conflict if there is no alternate color/name
	for (;;)
	{
		// check against all other player infos, and given info, too (may be redundant)
		fCurrentConflict = false;
		pLowPrioOriginalConflictPacket = pLowPrioAlternateConflictPacket = nullptr;
		MarkConflicts(rPriCheckList, !iTries);
		// check secondary list, too. But only for colors, not for names, because secondary list is Restore list
		// and colors are retained in restore while names are always taken from new joins
		if (eAttr != C4PlayerInfo::PLRATT_Name) MarkConflicts(rSecCheckList, !iTries);
		// and mark conflicts in additional packet that' sbeen passed
		if (pSecPacket) MarkConflicts(*pSecPacket, !iTries);
		// color conflict resolving
		if (eAttr == C4PlayerInfo::PLRATT_Color)
		{
			// original color free but not used?
			if (!iTries)
			{
				if (pResolveInfo->GetColor() != pResolveInfo->GetOriginalColor())
				{
					if (!fOriginalConflict)
					{
						// revert to original color!
						pResolveInfo->SetColor(pResolveInfo->GetOriginalColor());
						// in case a lower priority packet was blocking the attribute, re-check that packet
						// note that the may readd the current resolve packet, but the conflict will occur with the
						// lower priority packet in the next loop
						if (pLowPrioOriginalConflictPacket) ReaddInfoForCheck(pLowPrioOriginalConflictPacket);
						// done with this player (breaking the trial-loop)
						break;
					}
					// neither original nor alternate color used but alternate color free?
					else if (pResolveInfo->GetColor() != pResolveInfo->GetAlternateColor() && !fAlternateConflict)
					{
						// revert to alternate
						pResolveInfo->SetColor(pResolveInfo->GetAlternateColor());
						if (pLowPrioAlternateConflictPacket) ReaddInfoForCheck(pLowPrioAlternateConflictPacket);
						// done with this player (breaking the trial-loop)
						break;
					}
				}
			}
			// conflict found?
			if (!fCurrentConflict)
				// done with this player, then - break the trial-loop
				break;
			// try to get a new, unused player color
			uint32_t dwNewClr;
			if (++iTries > C4MaxPlayerColorChangeTries)
			{
				LogF(LoadResStr("IDS_PRC_NOREPLPLRCLR"), pResolveInfo->GetName() ? pResolveInfo->GetName() : "<NONAME>");
				// since there's a conflict anyway, change to original
				pResolveInfo->SetColor(pResolveInfo->GetOriginalColor());
				break;
			}
			else
				dwNewClr = GenerateRandomPlayerColor(iTries);
			pResolveInfo->SetColor(dwNewClr);
		}
		else // if (eAttr == PLRATT_Name)
		{
			// name conflict resolving
			// original name free but not used?
			if (!SEqualNoCase(pResolveInfo->GetName(), pResolveInfo->GetOriginalName()))
				if (!fOriginalConflict)
				{
					// revert to original name!
					pResolveInfo->SetForcedName(nullptr);
					if (pLowPrioOriginalConflictPacket) ReaddInfoForCheck(pLowPrioOriginalConflictPacket);
					// done with this player (breaking the trial-loop)
					break;
				}
			// conflict found?
			if (!fCurrentConflict)
				// done with this player, then - break the trial-loop
				break;
			// generate new name by appending an index
			if (++iTries > C4MaxPlayerNameChangeTries) break;
			pResolveInfo->SetForcedName(FormatString("%s (%d)", pResolveInfo->GetOriginalName(), iTries+1).getData());
		}
	}
}