<commit_before>
#include "../Flare.h"
#include "FlareTurret.h"
#include "FlareSpacecraft.h"
#include "FlareShell.h"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

UFlareTurret::UFlareTurret(const class FObjectInitializer& PCIP)
	: Super(PCIP)
	, TurretComponent(NULL)
	, BarrelComponent(NULL)
{
	HasFlickeringLights = false;
}

/*----------------------------------------------------
	Gameplay
----------------------------------------------------*/

void UFlareTurret::Initialize(const FFlareSpacecraftComponentSave* Data, UFlareCompany* Company, AFlareSpacecraftPawn* OwnerShip, bool IsInMenu)
{
	Super::Initialize(Data, Company, OwnerShip, IsInMenu);
	AimDirection = FVector::ZeroVector;

	// Initialize pilot
	Pilot = NewObject<UFlareTurretPilot>(this, UFlareTurretPilot::StaticClass());
	Pilot->Initialize(&(Data->Pilot), Company, this);
}

void UFlareTurret::SetupFiringEffects()
{
	if (FiringEffect == NULL && FiringEffectTemplate)
	{
		FiringEffects.Empty();

		for (int32 i = 0; i < ComponentDescription->WeaponCharacteristics.GunCharacteristics.GunCount; i++)
		{
			// Create the effect
			UParticleSystemComponent* TempFiringEffect = UGameplayStatics::SpawnEmitterAttached(
				FiringEffectTemplate,
				this,
				NAME_None,
				GetMuzzleLocation(i),
				GetComponentRotation(),
				EAttachLocation::KeepWorldPosition,
				false);

			// Additional setup
			TempFiringEffect->DeactivateSystem();
			TempFiringEffect->SetTickGroup(ETickingGroup::TG_PostPhysics);
			FiringEffects.Add(TempFiringEffect);
		}
	}
}

void UFlareTurret::SetupComponentMesh()
{
	Super::SetupComponentMesh();

	// Turret Mesh
	if (Spacecraft && ComponentDescription && ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMesh)
	{

		TurretComponent = NewObject<UFlareSpacecraftSubComponent>(this, UFlareSpacecraftSubComponent::StaticClass(), TEXT("TurretMesh"));
		 if (TurretComponent)
		 {
			TurretComponent->SetParentSpacecraftComponent(this);
			TurretComponent->RegisterComponent();
			TurretComponent->AttachTo(this);
			TurretComponent->SetStaticMesh(ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMesh);
			TurretComponent->SetMaterial(0, ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMesh->GetMaterial(0));
			TurretComponent->Initialize(NULL, PlayerCompany, Spacecraft, false);
			Spacecraft->AddOwnedComponent(TurretComponent);
		}
	}

	// Barrel Mesh
	if (Spacecraft && ComponentDescription && ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMesh)
	{

		BarrelComponent = NewObject<UFlareSpacecraftSubComponent>(this, UFlareSpacecraftSubComponent::StaticClass() , TEXT("BarrelMesh"));
		 if (BarrelComponent)
		 {
			 BarrelComponent->SetParentSpacecraftComponent(this);
			BarrelComponent->RegisterComponent();
			if (TurretComponent)
			{
				BarrelComponent->AttachTo(TurretComponent, FName("Axis"));
			}
			else
			{
				BarrelComponent->AttachTo(this);
			}
			BarrelComponent->SetStaticMesh(ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMesh);
			BarrelComponent->SetMaterial(0, ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMesh->GetMaterial(0));
			Spacecraft->AddOwnedComponent(BarrelComponent);
		}
	}
}

void UFlareTurret::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{

	if (Spacecraft->GetDamageSystem()->IsAlive() && Pilot)
	{

		Pilot->TickPilot(DeltaTime);
		//FLOGV("Pilot exist WantFire %d", Pilot->IsWantFire());
		if (Pilot->IsWantFire())
		{
			StartFire();
		}
		else
		{
			StopFire();
		}
		AimDirection = Pilot->GetTargetAimAxis();
		//FLOGV("Pilot AimDirection %s", *AimDirection.ToString());
	}

	if (Spacecraft->GetDamageSystem()->IsAlive() && GetUsableRatio() > 0)
	{

		if (TurretComponent && ComponentDescription)
		{

			float TargetTurretAngle = 0;
			if (AimDirection != FVector::ZeroVector)
			{
				FVector LocalTurretAimDirection = GetComponentToWorld().GetRotation().Inverse().RotateVector(AimDirection);
				TargetTurretAngle = FMath::UnwindDegrees(FMath::RadiansToDegrees(FMath::Atan2(LocalTurretAimDirection.Y, LocalTurretAimDirection.X)));
			}

			// Clamp movements
			TargetTurretAngle = FMath::Clamp(TargetTurretAngle, ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMinAngle, ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMaxAngle);

			float UsableTurretVelocity = GetUsableRatio() * ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretAngularVelocity;

			float TurretAngleDiff = FMath::UnwindDegrees(TargetTurretAngle - ShipComponentData.Turret.TurretAngle);

			if (FMath::Abs(TurretAngleDiff) <= UsableTurretVelocity * DeltaTime)
			{
				ShipComponentData.Turret.TurretAngle = TargetTurretAngle;
			}
			else if (TurretAngleDiff < 0)
			{
				ShipComponentData.Turret.TurretAngle -= UsableTurretVelocity * DeltaTime;
			}
			else
			{
				ShipComponentData.Turret.TurretAngle += UsableTurretVelocity * DeltaTime;
			}

			TurretComponent->SetRelativeRotation(FRotator(0, ShipComponentData.Turret.TurretAngle, 0));
		}

		if (BarrelComponent)
		{

			float TargetBarrelAngle = 15;

			if (AimDirection != FVector::ZeroVector)
			{
				FVector LocalBarrelAimDirection;
				if (TurretComponent)
				{
					LocalBarrelAimDirection = TurretComponent->GetComponentToWorld().GetRotation().Inverse().RotateVector(AimDirection);
				}
				else
				{
					LocalBarrelAimDirection = GetComponentToWorld().GetRotation().Inverse().RotateVector(AimDirection);
				}

				TargetBarrelAngle = FMath::UnwindDegrees(FMath::RadiansToDegrees(FMath::Atan2(LocalBarrelAimDirection.Z, LocalBarrelAimDirection.X)));
			}

			// Clamp movements
			TargetBarrelAngle = FMath::Clamp(TargetBarrelAngle, GetMinLimitAtAngle(ShipComponentData.Turret.TurretAngle), ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMaxAngle);

			// TODO Add ship specific bound

			float UsableBarrelsVelocity = GetUsableRatio() * ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretAngularVelocity;
			float BarrelAngleDiff = FMath::UnwindDegrees(TargetBarrelAngle - ShipComponentData.Turret.BarrelsAngle);

			if (FMath::Abs(BarrelAngleDiff) <= UsableBarrelsVelocity * DeltaTime) {
				ShipComponentData.Turret.BarrelsAngle = TargetBarrelAngle;
			} else if (BarrelAngleDiff < 0) {
				ShipComponentData.Turret.BarrelsAngle -= UsableBarrelsVelocity * DeltaTime;
			} else {
				ShipComponentData.Turret.BarrelsAngle += UsableBarrelsVelocity * DeltaTime;
			}
			BarrelComponent->SetRelativeRotation(FRotator(ShipComponentData.Turret.BarrelsAngle, 0, 0));

		}
	}

	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

}

FVector UFlareTurret::GetFireAxis() const
{
	if (BarrelComponent)
	{
		return BarrelComponent->GetComponentRotation().RotateVector(FVector(1, 0, 0));
	}
	else if (TurretComponent)
	{
		return TurretComponent->GetComponentRotation().RotateVector(FVector(1, 0, 0));
	}
	else
	{
		return Super::GetFireAxis();
	}
}

FVector UFlareTurret::GetIdleAxis() const
{
	// Ship front
	return Spacecraft->Airframe->GetComponentRotation().RotateVector(FVector(1, 0, 0));
}

FVector UFlareTurret::GetMuzzleLocation(int GunIndex) const
{
	const UStaticMeshComponent* GunComponent = this;
	if (BarrelComponent)
	{
		GunComponent = BarrelComponent;
	}
	else if (TurretComponent)
	{
		GunComponent = TurretComponent;
	}

	if (ComponentDescription->WeaponCharacteristics.GunCharacteristics.GunCount <= 1)
	{
		return GunComponent->GetSocketLocation(FName("Muzzle"));
	}
	else
	{
		return GunComponent->GetSocketLocation(FName(*(FString("Muzzle") + FString::FromInt(GunIndex))));
	}
}

FVector UFlareTurret::GetTurretBaseLocation() const
{
	if (BarrelComponent)
	{
		return BarrelComponent->GetComponentLocation();
	}
	else if (TurretComponent)
	{
		return TurretComponent->GetComponentLocation();
	}
	return GetComponentLocation();
}

bool UFlareTurret::IsSafeToFire(int GunIndex) const
{
	FVector FiringLocation = GetMuzzleLocation(GunIndex);
	FVector FiringDirection = GetFireAxis();
	FVector TargetLocation = FiringLocation + FiringDirection * 100000;

	FHitResult HitResult(ForceInit);
	if (Trace(FiringLocation, TargetLocation, HitResult))
	{
		if (HitResult.Actor.IsValid() && HitResult.Actor == Spacecraft)
		{
			FLOG("!!!!!!!!!Not safe to fire !");
			return false;
		}
	}
	return true;
}

bool UFlareTurret::Trace(const FVector& Start, const FVector& End, FHitResult& HitOut) const
{
	FCollisionQueryParams TraceParams(FName(TEXT("Shell Trace")), true, NULL);
	TraceParams.bTraceComplex = true;
	//TraceParams.bTraceAsyncScene = true;
	TraceParams.bReturnPhysicalMaterial = false;

	//Re-initialize hit info
	HitOut = FHitResult(ForceInit);

	ECollisionChannel CollisionChannel = (ECollisionChannel) (ECC_WorldStatic | ECC_WorldDynamic | ECC_Pawn);

	//Trace!
	GetWorld()->LineTraceSingleByChannel(
		HitOut,		//result
		Start,	//start
		End , //end
		CollisionChannel, //collision channel
		TraceParams
	);

	//Hit any Actor?
	return (HitOut.GetActor() != NULL) ;
}

bool UFlareTurret::IsReacheableAxis(FVector TargetAxis) const
{
	float TargetTurretAngle = 0;
	if (TurretComponent && ComponentDescription)
	{

		FVector LocalTurretAimDirection = GetComponentToWorld().GetRotation().Inverse().RotateVector(TargetAxis);
		TargetTurretAngle = FMath::UnwindDegrees(FMath::RadiansToDegrees(FMath::Atan2(LocalTurretAimDirection.Y, LocalTurretAimDirection.X)));

		if (TargetTurretAngle > ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMaxAngle
				|| TargetTurretAngle < ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMinAngle)
		{
			return false;
		}
	}

	if (BarrelComponent && ComponentDescription)
	{

		FVector LocalBarrelAimDirection;
		if (TurretComponent)
		{
			LocalBarrelAimDirection = TurretComponent->GetComponentToWorld().GetRotation().Inverse().RotateVector(TargetAxis);
		}
		else
		{
			LocalBarrelAimDirection = GetComponentToWorld().GetRotation().Inverse().RotateVector(TargetAxis);
		}

		float TargetBarrelAngle = FMath::UnwindDegrees(FMath::RadiansToDegrees(FMath::Atan2(LocalBarrelAimDirection.Z, LocalBarrelAimDirection.X)));
		if (TargetBarrelAngle > ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMaxAngle
				|| TargetBarrelAngle < GetMinLimitAtAngle(TargetTurretAngle))
		{
			return false;
		}

	}
	return true;
}

static inline int PositiveModulo(int i, int n)
{
	return (i % n + n) % n;
}

float UFlareTurret::GetMinLimitAtAngle(float Angle) const
{
	float BarrelsMinAngle = ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMinAngle;

	//Fine Local slot check
	for (int32 i = 0; i < Spacecraft->GetDescription()->TurretSlots.Num(); i++)
	{
		// TODO optimize and store that in cache
		if (Spacecraft->GetDescription()->TurretSlots[i].SlotIdentifier == ShipComponentData.ShipSlotIdentifier)
		{
			int LimitStepCount = Spacecraft->GetDescription()->TurretSlots[i].TurretBarrelsAngleLimit.Num();

			if (LimitStepCount > 0)
			{
				float StepAngle = 360.f / (float) LimitStepCount;

				float AngleInStep = Angle / StepAngle;
				int NearestStep = FMath::FloorToInt(AngleInStep + 0.5f);
				int SecondNearestStep;
				if (AngleInStep > NearestStep)
				{
					SecondNearestStep = NearestStep+1;
				}
				else
				{
					SecondNearestStep = NearestStep-1;
				}

				float Ratio = FMath::Abs(Angle - NearestStep * StepAngle) /  StepAngle;

				float LocalMin = Spacecraft->GetDescription()->TurretSlots[i].TurretBarrelsAngleLimit[PositiveModulo(NearestStep, LimitStepCount)] * (1.f - Ratio)
									+ Spacecraft->GetDescription()->TurretSlots[i].TurretBarrelsAngleLimit[PositiveModulo(SecondNearestStep,LimitStepCount)] * Ratio;

				BarrelsMinAngle = FMath::Max(BarrelsMinAngle, LocalMin);
			}
		}

	}
	return BarrelsMinAngle;
}

void UFlareTurret::GetBoundingSphere(FVector& Location, float& SphereRadius)
{
	Super::GetBoundingSphere(Location, SphereRadius);
	if (TurretComponent || BarrelComponent)
	{
		SphereRadius = 0;
	}
}

void UFlareTurret::ShowFiringEffects(int GunIndex)
{
	if (FiringEffects[GunIndex])
	{
		FiringEffects[GunIndex]->ActivateSystem();
	}
}
<commit_msg>Don't rotate turret in presentation mode<commit_after>
#include "../Flare.h"
#include "FlareTurret.h"
#include "FlareSpacecraft.h"
#include "FlareShell.h"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

UFlareTurret::UFlareTurret(const class FObjectInitializer& PCIP)
	: Super(PCIP)
	, TurretComponent(NULL)
	, BarrelComponent(NULL)
{
	HasFlickeringLights = false;
}

/*----------------------------------------------------
	Gameplay
----------------------------------------------------*/

void UFlareTurret::Initialize(const FFlareSpacecraftComponentSave* Data, UFlareCompany* Company, AFlareSpacecraftPawn* OwnerShip, bool IsInMenu)
{
	Super::Initialize(Data, Company, OwnerShip, IsInMenu);
	AimDirection = FVector::ZeroVector;

	// Initialize pilot
	Pilot = NewObject<UFlareTurretPilot>(this, UFlareTurretPilot::StaticClass());
	Pilot->Initialize(&(Data->Pilot), Company, this);
}

void UFlareTurret::SetupFiringEffects()
{
	if (FiringEffect == NULL && FiringEffectTemplate)
	{
		FiringEffects.Empty();

		for (int32 i = 0; i < ComponentDescription->WeaponCharacteristics.GunCharacteristics.GunCount; i++)
		{
			// Create the effect
			UParticleSystemComponent* TempFiringEffect = UGameplayStatics::SpawnEmitterAttached(
				FiringEffectTemplate,
				this,
				NAME_None,
				GetMuzzleLocation(i),
				GetComponentRotation(),
				EAttachLocation::KeepWorldPosition,
				false);

			// Additional setup
			TempFiringEffect->DeactivateSystem();
			TempFiringEffect->SetTickGroup(ETickingGroup::TG_PostPhysics);
			FiringEffects.Add(TempFiringEffect);
		}
	}
}

void UFlareTurret::SetupComponentMesh()
{
	Super::SetupComponentMesh();

	// Turret Mesh
	if (Spacecraft && ComponentDescription && ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMesh)
	{

		TurretComponent = NewObject<UFlareSpacecraftSubComponent>(this, UFlareSpacecraftSubComponent::StaticClass(), TEXT("TurretMesh"));
		 if (TurretComponent)
		 {
			TurretComponent->SetParentSpacecraftComponent(this);
			TurretComponent->RegisterComponent();
			TurretComponent->AttachTo(this);
			TurretComponent->SetStaticMesh(ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMesh);
			TurretComponent->SetMaterial(0, ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMesh->GetMaterial(0));
			TurretComponent->Initialize(NULL, PlayerCompany, Spacecraft, false);
			Spacecraft->AddOwnedComponent(TurretComponent);
		}
	}

	// Barrel Mesh
	if (Spacecraft && ComponentDescription && ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMesh)
	{

		BarrelComponent = NewObject<UFlareSpacecraftSubComponent>(this, UFlareSpacecraftSubComponent::StaticClass() , TEXT("BarrelMesh"));
		 if (BarrelComponent)
		 {
			 BarrelComponent->SetParentSpacecraftComponent(this);
			BarrelComponent->RegisterComponent();
			if (TurretComponent)
			{
				BarrelComponent->AttachTo(TurretComponent, FName("Axis"));
			}
			else
			{
				BarrelComponent->AttachTo(this);
			}
			BarrelComponent->SetStaticMesh(ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMesh);
			BarrelComponent->SetMaterial(0, ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMesh->GetMaterial(0));
			Spacecraft->AddOwnedComponent(BarrelComponent);
		}
	}
}

void UFlareTurret::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{

	if (Spacecraft->GetDamageSystem()->IsAlive() && Pilot)
	{

		Pilot->TickPilot(DeltaTime);
		//FLOGV("Pilot exist WantFire %d", Pilot->IsWantFire());
		if (Pilot->IsWantFire())
		{
			StartFire();
		}
		else
		{
			StopFire();
		}
		AimDirection = Pilot->GetTargetAimAxis();
		//FLOGV("Pilot AimDirection %s", *AimDirection.ToString());
	}

	if (Spacecraft->GetDamageSystem()->IsAlive() && GetUsableRatio() > 0)
	{

		if (TurretComponent && ComponentDescription)
		{

			float TargetTurretAngle = 0;
			if (AimDirection != FVector::ZeroVector)
			{
				FVector LocalTurretAimDirection = GetComponentToWorld().GetRotation().Inverse().RotateVector(AimDirection);
				TargetTurretAngle = FMath::UnwindDegrees(FMath::RadiansToDegrees(FMath::Atan2(LocalTurretAimDirection.Y, LocalTurretAimDirection.X)));
			}

			// Clamp movements
			TargetTurretAngle = FMath::Clamp(TargetTurretAngle, ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMinAngle, ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMaxAngle);

			float UsableTurretVelocity = GetUsableRatio() * ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretAngularVelocity;

			float TurretAngleDiff = FMath::UnwindDegrees(TargetTurretAngle - ShipComponentData.Turret.TurretAngle);

			if (FMath::Abs(TurretAngleDiff) <= UsableTurretVelocity * DeltaTime)
			{
				ShipComponentData.Turret.TurretAngle = TargetTurretAngle;
			}
			else if (TurretAngleDiff < 0)
			{
				ShipComponentData.Turret.TurretAngle -= UsableTurretVelocity * DeltaTime;
			}
			else
			{
				ShipComponentData.Turret.TurretAngle += UsableTurretVelocity * DeltaTime;
			}

			TurretComponent->SetRelativeRotation(FRotator(0, ShipComponentData.Turret.TurretAngle, 0));
		}

		if (BarrelComponent)
		{

			float TargetBarrelAngle = 15;

			if (AimDirection != FVector::ZeroVector)
			{
				FVector LocalBarrelAimDirection;
				if (TurretComponent)
				{
					LocalBarrelAimDirection = TurretComponent->GetComponentToWorld().GetRotation().Inverse().RotateVector(AimDirection);
				}
				else
				{
					LocalBarrelAimDirection = GetComponentToWorld().GetRotation().Inverse().RotateVector(AimDirection);
				}

				TargetBarrelAngle = FMath::UnwindDegrees(FMath::RadiansToDegrees(FMath::Atan2(LocalBarrelAimDirection.Z, LocalBarrelAimDirection.X)));
			}

			// Clamp movements
			TargetBarrelAngle = FMath::Clamp(TargetBarrelAngle, GetMinLimitAtAngle(ShipComponentData.Turret.TurretAngle), ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMaxAngle);

			// TODO Add ship specific bound

			float UsableBarrelsVelocity = GetUsableRatio() * ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretAngularVelocity;
			float BarrelAngleDiff = FMath::UnwindDegrees(TargetBarrelAngle - ShipComponentData.Turret.BarrelsAngle);

			if (FMath::Abs(BarrelAngleDiff) <= UsableBarrelsVelocity * DeltaTime) {
				ShipComponentData.Turret.BarrelsAngle = TargetBarrelAngle;
			} else if (BarrelAngleDiff < 0) {
				ShipComponentData.Turret.BarrelsAngle -= UsableBarrelsVelocity * DeltaTime;
			} else {
				ShipComponentData.Turret.BarrelsAngle += UsableBarrelsVelocity * DeltaTime;
			}
			BarrelComponent->SetRelativeRotation(FRotator(ShipComponentData.Turret.BarrelsAngle, 0, 0));

		}
	}

	if(Spacecraft->IsPresentationMode())
	{
		TurretComponent->SetRelativeRotation(FRotator(0, 0, 0));
		BarrelComponent->SetRelativeRotation(FRotator(15, 0, 0));
	}

	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

}

FVector UFlareTurret::GetFireAxis() const
{
	if (BarrelComponent)
	{
		return BarrelComponent->GetComponentRotation().RotateVector(FVector(1, 0, 0));
	}
	else if (TurretComponent)
	{
		return TurretComponent->GetComponentRotation().RotateVector(FVector(1, 0, 0));
	}
	else
	{
		return Super::GetFireAxis();
	}
}

FVector UFlareTurret::GetIdleAxis() const
{
	// Ship front
	return Spacecraft->Airframe->GetComponentRotation().RotateVector(FVector(1, 0, 0));
}

FVector UFlareTurret::GetMuzzleLocation(int GunIndex) const
{
	const UStaticMeshComponent* GunComponent = this;
	if (BarrelComponent)
	{
		GunComponent = BarrelComponent;
	}
	else if (TurretComponent)
	{
		GunComponent = TurretComponent;
	}

	if (ComponentDescription->WeaponCharacteristics.GunCharacteristics.GunCount <= 1)
	{
		return GunComponent->GetSocketLocation(FName("Muzzle"));
	}
	else
	{
		return GunComponent->GetSocketLocation(FName(*(FString("Muzzle") + FString::FromInt(GunIndex))));
	}
}

FVector UFlareTurret::GetTurretBaseLocation() const
{
	if (BarrelComponent)
	{
		return BarrelComponent->GetComponentLocation();
	}
	else if (TurretComponent)
	{
		return TurretComponent->GetComponentLocation();
	}
	return GetComponentLocation();
}

bool UFlareTurret::IsSafeToFire(int GunIndex) const
{
	FVector FiringLocation = GetMuzzleLocation(GunIndex);
	FVector FiringDirection = GetFireAxis();
	FVector TargetLocation = FiringLocation + FiringDirection * 100000;

	FHitResult HitResult(ForceInit);
	if (Trace(FiringLocation, TargetLocation, HitResult))
	{
		if (HitResult.Actor.IsValid() && HitResult.Actor == Spacecraft)
		{
			FLOG("!!!!!!!!!Not safe to fire !");
			return false;
		}
	}
	return true;
}

bool UFlareTurret::Trace(const FVector& Start, const FVector& End, FHitResult& HitOut) const
{
	FCollisionQueryParams TraceParams(FName(TEXT("Shell Trace")), true, NULL);
	TraceParams.bTraceComplex = true;
	//TraceParams.bTraceAsyncScene = true;
	TraceParams.bReturnPhysicalMaterial = false;

	//Re-initialize hit info
	HitOut = FHitResult(ForceInit);

	ECollisionChannel CollisionChannel = (ECollisionChannel) (ECC_WorldStatic | ECC_WorldDynamic | ECC_Pawn);

	//Trace!
	GetWorld()->LineTraceSingleByChannel(
		HitOut,		//result
		Start,	//start
		End , //end
		CollisionChannel, //collision channel
		TraceParams
	);

	//Hit any Actor?
	return (HitOut.GetActor() != NULL) ;
}

bool UFlareTurret::IsReacheableAxis(FVector TargetAxis) const
{
	float TargetTurretAngle = 0;
	if (TurretComponent && ComponentDescription)
	{

		FVector LocalTurretAimDirection = GetComponentToWorld().GetRotation().Inverse().RotateVector(TargetAxis);
		TargetTurretAngle = FMath::UnwindDegrees(FMath::RadiansToDegrees(FMath::Atan2(LocalTurretAimDirection.Y, LocalTurretAimDirection.X)));

		if (TargetTurretAngle > ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMaxAngle
				|| TargetTurretAngle < ComponentDescription->WeaponCharacteristics.TurretCharacteristics.TurretMinAngle)
		{
			return false;
		}
	}

	if (BarrelComponent && ComponentDescription)
	{

		FVector LocalBarrelAimDirection;
		if (TurretComponent)
		{
			LocalBarrelAimDirection = TurretComponent->GetComponentToWorld().GetRotation().Inverse().RotateVector(TargetAxis);
		}
		else
		{
			LocalBarrelAimDirection = GetComponentToWorld().GetRotation().Inverse().RotateVector(TargetAxis);
		}

		float TargetBarrelAngle = FMath::UnwindDegrees(FMath::RadiansToDegrees(FMath::Atan2(LocalBarrelAimDirection.Z, LocalBarrelAimDirection.X)));
		if (TargetBarrelAngle > ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMaxAngle
				|| TargetBarrelAngle < GetMinLimitAtAngle(TargetTurretAngle))
		{
			return false;
		}

	}
	return true;
}

static inline int PositiveModulo(int i, int n)
{
	return (i % n + n) % n;
}

float UFlareTurret::GetMinLimitAtAngle(float Angle) const
{
	float BarrelsMinAngle = ComponentDescription->WeaponCharacteristics.TurretCharacteristics.BarrelsMinAngle;

	//Fine Local slot check
	for (int32 i = 0; i < Spacecraft->GetDescription()->TurretSlots.Num(); i++)
	{
		// TODO optimize and store that in cache
		if (Spacecraft->GetDescription()->TurretSlots[i].SlotIdentifier == ShipComponentData.ShipSlotIdentifier)
		{
			int LimitStepCount = Spacecraft->GetDescription()->TurretSlots[i].TurretBarrelsAngleLimit.Num();

			if (LimitStepCount > 0)
			{
				float StepAngle = 360.f / (float) LimitStepCount;

				float AngleInStep = Angle / StepAngle;
				int NearestStep = FMath::FloorToInt(AngleInStep + 0.5f);
				int SecondNearestStep;
				if (AngleInStep > NearestStep)
				{
					SecondNearestStep = NearestStep+1;
				}
				else
				{
					SecondNearestStep = NearestStep-1;
				}

				float Ratio = FMath::Abs(Angle - NearestStep * StepAngle) /  StepAngle;

				float LocalMin = Spacecraft->GetDescription()->TurretSlots[i].TurretBarrelsAngleLimit[PositiveModulo(NearestStep, LimitStepCount)] * (1.f - Ratio)
									+ Spacecraft->GetDescription()->TurretSlots[i].TurretBarrelsAngleLimit[PositiveModulo(SecondNearestStep,LimitStepCount)] * Ratio;

				BarrelsMinAngle = FMath::Max(BarrelsMinAngle, LocalMin);
			}
		}

	}
	return BarrelsMinAngle;
}

void UFlareTurret::GetBoundingSphere(FVector& Location, float& SphereRadius)
{
	Super::GetBoundingSphere(Location, SphereRadius);
	if (TurretComponent || BarrelComponent)
	{
		SphereRadius = 0;
	}
}

void UFlareTurret::ShowFiringEffects(int GunIndex)
{
	if (FiringEffects[GunIndex])
	{
		FiringEffects[GunIndex]->ActivateSystem();
	}
}
<|endoftext|>


<commit_before>#ifdef __EMSCRIPTEN__

#include <babylon/asio/asio.h>
#include <babylon/core/logging.h>
#include <babylon/misc/string_tools.h>
#include <iostream>
#include <emscripten.h>
#include <unordered_map>
#include <thread>
#include <chrono>
#include <sstream>

namespace BABYLON {
namespace asio {

namespace
{

static std::string ArrayBufferToString(const ArrayBuffer & dataUint8)
{
  std::string dataString;
  dataString.resize(dataUint8.size());
  for (size_t i = 0; i < dataUint8.size(); ++i)
    dataString[i] = static_cast<char>(dataUint8[i]);
  dataString = BABYLON::StringTools::replace(dataString, "\r\n", "\n");
  return dataString;
}

struct DownloadInfo
{
  std::string url;
  std::function<void(const ArrayBuffer& data)> onSuccessFunction;
  std::function<void(const std::string& message)> onErrorFunction;
};

using DownloadId = int;

std::unordered_map<DownloadId, DownloadInfo> gDownloadInfos;

DownloadId storeDownloadInfo(
  const std::string &url,
  std::function<void(const ArrayBuffer& data)> onSuccessFunction,
  std::function<void(const std::string& message)> onErrorFunction)
{
  static int id = 0;
  ++id;
  DownloadInfo info {url, onSuccessFunction, onErrorFunction};
  gDownloadInfos[id] = info;
  return id;
}

DownloadInfo consumeDownloadInfo(DownloadId id)
{
  if (gDownloadInfos.find(id) == gDownloadInfos.end()) {
    std::stringstream msg;
    msg << "consumeDownloadInfo bad id:" << id <<  " gDownloadInfos size=" << gDownloadInfos.size();
    BABYLON_LOG_ERROR("asio_emscripten", msg.str().c_str(), "");
    throw std::runtime_error(msg.str().c_str());
  }
  DownloadInfo r = gDownloadInfos.at(id);
  gDownloadInfos.erase(id);
  return r;
}

// See https://emscripten.org/docs/api_reference/emscripten.h.html#c.emscripten_async_wget_data
void babylon_emscripten_onLoad(void *arg_downloadId, void *bufferData, int bufferSize)
{
  uint8_t* bufferDataAsUint8 = static_cast<uint8_t *>(bufferData);
  ArrayBuffer arrayBuffer(bufferDataAsUint8, bufferDataAsUint8 + bufferSize); // this makes a copy

  DownloadInfo info = consumeDownloadInfo((DownloadId)arg_downloadId);
  BABYLON_LOG_DEBUG("babylon_emscripten_onLoad", info.url.c_str(), " Success!");
  info.onSuccessFunction(arrayBuffer);
}

void babylon_emscripten_onError(void *arg_downloadId)
{
  DownloadInfo info = consumeDownloadInfo((DownloadId)arg_downloadId);
  std::string errorMessage = std::string("Error while downloading ") + info.url;
  BABYLON_LOG_DEBUG("babylon_emscripten_onError", info.url.c_str(), " Failure!");
  info.onErrorFunction(errorMessage);
}

static std::string BaseUrl() {
  return "./emscripten_http_assets/assets/";
}

} // anonymous namespace

void set_HACK_DISABLE_ASYNC(bool v)
{
  BABYLON_LOG_WARN("asio", "set_HACK_DISABLE_ASYNC does not work under emscripten", "");
}

void LoadUrlAsync_Text(
  const std::string& url,
  const std::function<void(const std::string& data)>& onSuccessFunction,
  const OnErrorFunction& onErrorFunction,
  const OnProgressFunction& onProgressFunction
)
{
  std::string fullUrl = BaseUrl() + url;
  auto onSuccessFunctionArrayBuffer = [onSuccessFunction](const ArrayBuffer& dataUint8) {
    onSuccessFunction(ArrayBufferToString(dataUint8));
  };
  auto downloadId = storeDownloadInfo(fullUrl.c_str(), onSuccessFunctionArrayBuffer, onErrorFunction);
  emscripten_async_wget_data(fullUrl.c_str(), (void*)downloadId, babylon_emscripten_onLoad, babylon_emscripten_onError);
}

void LoadUrlAsync_Binary(
  const std::string& url,
  const std::function<void(const ArrayBuffer& data)>& onSuccessFunction,
  const OnErrorFunction& onErrorFunction,
  const OnProgressFunction& onProgressFunction
)
{
  std::string fullUrl = BaseUrl() + url;
  auto downloadId = storeDownloadInfo(fullUrl.c_str(), onSuccessFunction, onErrorFunction);
  emscripten_async_wget_data(fullUrl.c_str(), (void*)downloadId, babylon_emscripten_onLoad, babylon_emscripten_onError);
}

// Call this in the app's main loop: it will run the callbacks synchronously
// after the io completion
void HeartBeat_Sync()
{
}

void Service_WaitAll_Sync()
{
  using namespace std::literals;
  while(!gDownloadInfos.empty())
    std::this_thread::sleep_for(30ms);
}

BABYLON_SHARED_EXPORT void Service_Stop()
{
}

bool HasRemainingTasks()
{
  return !gDownloadInfos.empty();
}

} // namespace asio
} // namespace BABYLON

#endif //#ifdef __EMSCRIPTEN__
<commit_msg>asio_emscripten: correct / wait<commit_after>#ifdef __EMSCRIPTEN__

#include <babylon/asio/asio.h>
#include <babylon/core/logging.h>
#include <babylon/misc/string_tools.h>
#include <iostream>
#include <emscripten.h>
#include <unordered_map>
#include <thread>
#include <chrono>
#include <sstream>

namespace BABYLON {
namespace asio {

namespace
{

static std::string ArrayBufferToString(const ArrayBuffer & dataUint8)
{
  std::string dataString;
  dataString.resize(dataUint8.size());
  for (size_t i = 0; i < dataUint8.size(); ++i)
    dataString[i] = static_cast<char>(dataUint8[i]);
  dataString = BABYLON::StringTools::replace(dataString, "\r\n", "\n");
  return dataString;
}

struct DownloadInfo
{
  std::string url;
  std::function<void(const ArrayBuffer& data)> onSuccessFunction;
  std::function<void(const std::string& message)> onErrorFunction;
};

using DownloadId = int;

std::unordered_map<DownloadId, DownloadInfo> gDownloadInfos;

DownloadId storeDownloadInfo(
  const std::string &url,
  std::function<void(const ArrayBuffer& data)> onSuccessFunction,
  std::function<void(const std::string& message)> onErrorFunction)
{
  static int id = 0;
  ++id;
  DownloadInfo info {url, onSuccessFunction, onErrorFunction};
  gDownloadInfos[id] = info;
  return id;
}

DownloadInfo consumeDownloadInfo(DownloadId id)
{
  if (gDownloadInfos.find(id) == gDownloadInfos.end()) {
    std::stringstream msg;
    msg << "consumeDownloadInfo bad id:" << id <<  " gDownloadInfos size=" << gDownloadInfos.size();
    BABYLON_LOG_ERROR("asio_emscripten", msg.str().c_str(), "");
    throw std::runtime_error(msg.str().c_str());
  }
  DownloadInfo r = gDownloadInfos.at(id);
  gDownloadInfos.erase(id);
  return r;
}

// See https://emscripten.org/docs/api_reference/emscripten.h.html#c.emscripten_async_wget_data
void babylon_emscripten_onLoad(void *arg_downloadId, void *bufferData, int bufferSize)
{
  uint8_t* bufferDataAsUint8 = static_cast<uint8_t *>(bufferData);
  ArrayBuffer arrayBuffer(bufferDataAsUint8, bufferDataAsUint8 + bufferSize); // this makes a copy

  DownloadInfo info = consumeDownloadInfo((DownloadId)arg_downloadId);
  BABYLON_LOG_DEBUG("babylon_emscripten_onLoad", info.url.c_str(), " Success!");
  info.onSuccessFunction(arrayBuffer);
}

void babylon_emscripten_onError(void *arg_downloadId)
{
  DownloadInfo info = consumeDownloadInfo((DownloadId)arg_downloadId);
  std::string errorMessage = std::string("Error while downloading ") + info.url;
  BABYLON_LOG_DEBUG("babylon_emscripten_onError", info.url.c_str(), " Failure!");
  info.onErrorFunction(errorMessage);
}

static std::string BaseUrl() {
  return "./emscripten_http_assets/assets/";
}

} // anonymous namespace

void push_HACK_DISABLE_ASYNC()
{
  BABYLON_LOG_WARN("asio", "push_HACK_DISABLE_ASYNC does not work under emscripten", "");
}
void pop_HACK_DISABLE_ASYNC()
{
  BABYLON_LOG_WARN("asio", "pop_HACK_DISABLE_ASYNC does not work under emscripten", "");
}

void LoadUrlAsync_Text(
  const std::string& url,
  const std::function<void(const std::string& data)>& onSuccessFunction,
  const OnErrorFunction& onErrorFunction,
  const OnProgressFunction& onProgressFunction
)
{
  std::string fullUrl = BaseUrl() + url;
  auto onSuccessFunctionArrayBuffer = [onSuccessFunction](const ArrayBuffer& dataUint8) {
    onSuccessFunction(ArrayBufferToString(dataUint8));
  };
  auto downloadId = storeDownloadInfo(fullUrl.c_str(), onSuccessFunctionArrayBuffer, onErrorFunction);
  emscripten_async_wget_data(fullUrl.c_str(), (void*)downloadId, babylon_emscripten_onLoad, babylon_emscripten_onError);
}

void LoadUrlAsync_Binary(
  const std::string& url,
  const std::function<void(const ArrayBuffer& data)>& onSuccessFunction,
  const OnErrorFunction& onErrorFunction,
  const OnProgressFunction& onProgressFunction
)
{
  std::string fullUrl = BaseUrl() + url;
  auto downloadId = storeDownloadInfo(fullUrl.c_str(), onSuccessFunction, onErrorFunction);
  emscripten_async_wget_data(fullUrl.c_str(), (void*)downloadId, babylon_emscripten_onLoad, babylon_emscripten_onError);
}

// Call this in the app's main loop: it will run the callbacks synchronously
// after the io completion
void HeartBeat_Sync()
{
}

void Service_WaitAll_Sync()
{
  using namespace std::literals;
  while(!gDownloadInfos.empty())
    std::this_thread::sleep_for(30ms);
}

BABYLON_SHARED_EXPORT void Service_Stop()
{
}

bool HasRemainingTasks()
{
  return !gDownloadInfos.empty();
}

} // namespace asio
} // namespace BABYLON

#endif //#ifdef __EMSCRIPTEN__
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/delegates/flex/whitelisted_flex_ops.h"

#include <set>

namespace tflite {
namespace flex {

bool IsWhitelistedFlexOp(const std::string& tensorflow_op_name) {
  static const std::set<std::string>* whitelisted_flex_ops =
      new std::set<std::string>({
          "Abort",
          "Abs",
          "Add",
          "AddN",
          "AddV2",
          "All",
          "Any",
          "ApplyAdadelta",
          "ApplyAdagrad",
          "ApplyAdagradDA",
          "ApplyAdam",
          "ApplyAdaMax",
          "ApplyAddSign",
          "ApplyCenteredRMSProp",
          "ApplyFtrl",
          "ApplyFtrlV2",
          "ApplyGradientDescent",
          "ApplyMomentum",
          "ApplyPowerSign",
          "ApplyProximalAdagrad",
          "ApplyProximalGradientDescent",
          "ApplyRMSProp",
          "ApproximateEqual",
          "_Arg",
          "ArgMax",
          "ArgMin",
          "_ArrayToList",
          "Assert",
          "Assign",
          "AssignAdd",
          "AssignSub",
          "AudioSpectrogram",
          "AvgPool",
          "AvgPool3D",
          "AvgPoolGrad",
          "BatchMatMul",
          "BatchMatMulV2",
          "BatchNormWithGlobalNormalization",
          "BatchNormWithGlobalNormalizationGrad",
          "BatchToSpace",
          "BatchToSpaceND",
          "BiasAdd",
          "BiasAddGrad",
          "BiasAddV1",
          "BroadcastArgs",
          "BroadcastGradientArgs",
          "BroadcastTo",
          "Cast",
          "Ceil",
          "CheckNumerics",
          "ComplexAbs",
          "Concat",
          "ConcatOffset",
          "ConcatV2",
          "ConjugateTranspose",
          "Const",
          "ControlTrigger",
          "Conv2D",
          "Conv2DBackpropFilter",
          "Conv2DBackpropInput",
          "Conv3D",
          "Cos",
          "Cosh",
          "CropAndResize",
          "CropAndResizeGradBoxes",
          "CropAndResizeGradImage",
          "CTCBeamSearchDecoder",
          "CTCGreedyDecoder",
          "DataFormatDimMap",
          "DataFormatVecPermute",
          "DebugGradientIdentity",
          "DebugGradientRefIdentity",
          "DecodeBmp",
          "DecodeWav",
          "DeleteSessionTensor",
          "DepthToSpace",
          "DepthwiseConv2dNative",
          "Dequantize",
          "DestroyTemporaryVariable",
          "Div",
          "DivNoNan",
          "DynamicPartition",
          "DynamicStitch",
          "Einsum",
          "Elu",
          "EluGrad",
          "EncodeWav",
          "EnsureShape",
          "Enter",
          "Equal",
          "Erf",
          "Exit",
          "Exp",
          "ExpandDims",
          "FakeQuantWithMinMaxArgs",
          "FakeQuantWithMinMaxArgsGradient",
          "FakeQuantWithMinMaxVars",
          "FakeQuantWithMinMaxVarsGradient",
          "FakeQuantWithMinMaxVarsPerChannel",
          "FakeQuantWithMinMaxVarsPerChannelGradient",
          "FakeQueue",
          "FFT",
          "FFT2D",
          "FFT3D",
          "FIFOQueue",
          "FIFOQueueV2",
          "Fill",
          "Floor",
          "FloorDiv",
          "FloorMod",
          "FusedBatchNorm",
          "FusedBatchNormGrad",
          "FusedBatchNormGradV2",
          "FusedBatchNormV2",
          "FusedBatchNormV3",
          "FusedPadConv2D",
          "FusedResizeAndPadConv2D",
          "Gather",
          "GatherNd",
          "GatherV2",
          "GetSessionHandle",
          "GetSessionHandleV2",
          "GetSessionTensor",
          "Greater",
          "GreaterEqual",
          "_HostCast",
          "_HostRecv",
          "_HostSend",
          "Identity",
          "IdentityN",
          "IFFT",
          "IFFT2D",
          "IFFT3D",
          "IRFFT",
          "IRFFT2D",
          "IRFFT3D",
          "ImmutableConst",
          "InTopK",
          "InTopKV2",
          "Inv",
          "InvertPermutation",
          "InvGrad",
          "IsFinite",
          "IsNan",
          "IsVariableInitialized",
          "LeakyRelu",
          "LeakyReluGrad",
          "Less",
          "LessEqual",
          "LinSpace",
          "ListDiff",
          "_ListToArray",
          "Log",
          "LogicalAnd",
          "LogicalNot",
          "LogicalOr",
          "LogSoftmax",
          "LoopCond",
          "LRN",
          "MatMul",
          "MatrixDiag",
          "MatrixDiagV2",
          "MatrixDiagV3",
          "MatrixSetDiag",
          "MatrixSetDiagV2",
          "MatrixSetDiagV3",
          "Max",
          "Maximum",
          "MaxPool",
          "MaxPool3D",
          "MaxPoolGrad",
          "MaxPoolGradGrad",
          "MaxPoolGradGradV2",
          "MaxPoolGradV2",
          "MaxPoolGradWithArgmax",
          "MaxPoolV2",
          "MaxPoolWithArgmax",
          "Mean",
          "Merge",
          "MergeV2Checkpoints",
          "Mfcc",
          "Min",
          "Minimum",
          "MirrorPad",
          "MirrorPadGrad",
          "Mul",
          "MulNoNan",
          "Multinomial",
          "Neg",
          "NextIteration",
          "NonMaxSuppression",
          "NonMaxSuppressionV2",
          "NonMaxSuppressionV3",
          "NonMaxSuppressionV4",
          "NonMaxSuppressionWithOverlaps",
          "NoOp",
          "NotEqual",
          "OneHot",
          "OnesLike",
          "Pack",
          "Pad",
          "PaddingFIFOQueue",
          "PaddingFIFOQueueV2",
          "PadV2",
          "ParallelDynamicStitch",
          "ParseExample",
          "ParseSequenceExample",
          "ParseSingleExample",
          "ParseSingleSequenceExample",
          "Placeholder",
          "PlaceholderV2",
          "PlaceholderWithDefault",
          "Pow",
          "PreventGradient",
          "Print",
          "PrintV2",
          "Prod",
          "QuantizedAdd",
          "QuantizedAvgPool",
          "QuantizedBatchNormWithGlobalNormalization",
          "QuantizedBiasAdd",
          "QuantizedConcat",
          "QuantizedConv2D",
          "QuantizedInstanceNorm",
          "QuantizedMatMul",
          "QuantizedMaxPool",
          "QuantizedMul",
          "QuantizeDownAndShrinkRange",
          "QuantizedRelu",
          "QuantizedRelu6",
          "QuantizedReshape",
          "QuantizedResizeBilinear",
          "QuantizeV2",
          "QueueClose",
          "QueueCloseV2",
          "QueueDequeue",
          "QueueDequeueMany",
          "QueueDequeueManyV2",
          "QueueDequeueUpTo",
          "QueueDequeueUpToV2",
          "QueueDequeueV2",
          "QueueEnqueue",
          "QueueEnqueueMany",
          "QueueEnqueueManyV2",
          "QueueEnqueueV2",
          "QueueIsClosed",
          "QueueIsClosedV2",
          "QueueSize",
          "QueueSizeV2",
          "RandomGamma",
          "RandomStandardNormal",
          "RandomUniform",
          "RandomUniformInt",
          "Range",
          "Rank",
          "RealDiv",
          "Reciprocal",
          "ReciprocalGrad",
          "_Recv",
          "RefEnter",
          "RefExit",
          "RefIdentity",
          "RefMerge",
          "RefNextIteration",
          "RefSelect",
          "RefSwitch",
          "Relu",
          "Relu6",
          "Relu6Grad",
          "ReluGrad",
          "RemoteCall",
          "RequantizationRange",
          "Requantize",
          "Reshape",
          "ResizeBilinear",
          "ResizeBilinearGrad",
          "ResizeNearestNeighbor",
          "ResizeNearestNeighborGrad",
          "ResourceApplyAdadelta",
          "ResourceApplyAdagrad",
          "ResourceApplyAdagradDA",
          "ResourceApplyAdam",
          "ResourceApplyAdaMax",
          "ResourceApplyAddSign",
          "ResourceApplyCenteredRMSProp",
          "ResourceApplyFtrl",
          "ResourceApplyFtrlV2",
          "ResourceApplyGradientDescent",
          "ResourceApplyMomentum",
          "ResourceApplyPowerSign",
          "ResourceApplyProximalAdagrad",
          "ResourceApplyProximalGradientDescent",
          "ResourceApplyRMSProp",
          "ResourceSparseApplyAdadelta",
          "ResourceSparseApplyAdagrad",
          "ResourceSparseApplyAdagradDA",
          "ResourceSparseApplyCenteredRMSProp",
          "ResourceSparseApplyFtrl",
          "ResourceSparseApplyFtrlV2",
          "ResourceSparseApplyMomentum",
          "ResourceSparseApplyProximalAdagrad",
          "ResourceSparseApplyProximalGradientDescent",
          "ResourceSparseApplyRMSProp",
          "ResourceStridedSliceAssign",
          "Restore",
          "RestoreSlice",
          "RestoreV2",
          "_Retval",
          "Reverse",
          "ReverseSequence",
          "ReverseV2",
          "RFFT",
          "RFFT2D",
          "RFFT3D",
          "Round",
          "Rsqrt",
          "RsqrtGrad",
          "Save",
          "SaveSlices",
          "SaveV2",
          "ScatterNd",
          "SegmentMax",
          "SegmentMean",
          "SegmentMin",
          "SegmentProd",
          "SegmentSum",
          "Select",
          "Selu",
          "SeluGrad",
          "_Send",
          "Shape",
          "ShapeN",
          "ShardedFilename",
          "ShardedFilespec",
          "Sigmoid",
          "SigmoidGrad",
          "Sign",
          "Sin",
          "Sinh",
          "Size",
          "Slice",
          "Softmax",
          "SoftmaxCrossEntropyWithLogits",
          "Softplus",
          "SoftplusGrad",
          "Softsign",
          "SoftsignGrad",
          "SpaceToBatch",
          "SpaceToBatchND",
          "SpaceToDepth",
          "SparseApplyAdadelta",
          "SparseApplyAdagrad",
          "SparseApplyAdagradDA",
          "SparseApplyCenteredRMSProp",
          "SparseApplyFtrl",
          "SparseApplyFtrlV2",
          "SparseApplyMomentum",
          "SparseApplyProximalAdagrad",
          "SparseApplyProximalGradientDescent",
          "SparseApplyRMSProp",
          "SparseFillEmptyRows",
          "SparseFillEmptyRowsGrad",
          "SparseReshape",
          "SparseSegmentMean",
          "SparseSegmentMeanGrad",
          "SparseSegmentMeanWithNumSegments",
          "SparseSegmentSqrtN",
          "SparseSegmentSqrtNGrad",
          "SparseSegmentSqrtNWithNumSegments",
          "SparseSegmentSum",
          "SparseSegmentSumWithNumSegments",
          "SparseToDense",
          "Split",
          "SplitV",
          "Sqrt",
          "SqrtGrad",
          "Square",
          "SquaredDifference",
          "Squeeze",
          "Stack",
          "StackClose",
          "StackCloseV2",
          "StackPop",
          "StackPopV2",
          "StackPush",
          "StackPushV2",
          "StackV2",
          "StopGradient",
          "StridedSlice",
          "StridedSliceAssign",
          "StridedSliceGrad",
          "StringJoin",
          "Sub",
          "Sum",
          "Switch",
          "SymbolicGradient",
          "Tan",
          "Tanh",
          "TanhGrad",
          "TemporaryVariable",
          "TensorArray",
          "TensorArrayClose",
          "TensorArrayCloseV2",
          "TensorArrayCloseV3",
          "TensorArrayConcat",
          "TensorArrayConcatV2",
          "TensorArrayConcatV3",
          "TensorArrayGather",
          "TensorArrayGatherV2",
          "TensorArrayGatherV3",
          "TensorArrayGrad",
          "TensorArrayGradV2",
          "TensorArrayGradV3",
          "TensorArrayGradWithShape",
          "TensorArrayPack",
          "TensorArrayRead",
          "TensorArrayReadV2",
          "TensorArrayReadV3",
          "TensorArrayScatter",
          "TensorArrayScatterV2",
          "TensorArrayScatterV3",
          "TensorArraySize",
          "TensorArraySizeV2",
          "TensorArraySizeV3",
          "TensorArraySplit",
          "TensorArraySplitV2",
          "TensorArraySplitV3",
          "TensorArrayUnpack",
          "TensorArrayV2",
          "TensorArrayV3",
          "TensorArrayWrite",
          "TensorArrayWriteV2",
          "TensorArrayWriteV3",
          "Tile",
          "TileGrad",
          "Timestamp",
          "TopK",
          "TopKV2",
          "Transpose",
          "TruncateDiv",
          "TruncatedNormal",
          "Unique",
          "UniqueV2",
          "UniqueWithCounts",
          "UniqueWithCountsV2",
          "Unpack",
          "UnsortedSegmentMax",
          "UnsortedSegmentMin",
          "UnsortedSegmentProd",
          "UnsortedSegmentSum",
          "Variable",
          "VariableV2",
          "Where",
          "Xdivy",
          "Xlogy",
          "ZerosLike",
      });
  return whitelisted_flex_ops->find(tensorflow_op_name) !=
         whitelisted_flex_ops->end();
}

}  // namespace flex
}  // namespace tflite
<commit_msg>Add `tf.empty` into whitelisted flex op.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/delegates/flex/whitelisted_flex_ops.h"

#include <set>

namespace tflite {
namespace flex {

bool IsWhitelistedFlexOp(const std::string& tensorflow_op_name) {
  static const std::set<std::string>* whitelisted_flex_ops =
      new std::set<std::string>({
          "Abort",
          "Abs",
          "Add",
          "AddN",
          "AddV2",
          "All",
          "Any",
          "ApplyAdadelta",
          "ApplyAdagrad",
          "ApplyAdagradDA",
          "ApplyAdam",
          "ApplyAdaMax",
          "ApplyAddSign",
          "ApplyCenteredRMSProp",
          "ApplyFtrl",
          "ApplyFtrlV2",
          "ApplyGradientDescent",
          "ApplyMomentum",
          "ApplyPowerSign",
          "ApplyProximalAdagrad",
          "ApplyProximalGradientDescent",
          "ApplyRMSProp",
          "ApproximateEqual",
          "_Arg",
          "ArgMax",
          "ArgMin",
          "_ArrayToList",
          "Assert",
          "Assign",
          "AssignAdd",
          "AssignSub",
          "AudioSpectrogram",
          "AvgPool",
          "AvgPool3D",
          "AvgPoolGrad",
          "BatchMatMul",
          "BatchMatMulV2",
          "BatchNormWithGlobalNormalization",
          "BatchNormWithGlobalNormalizationGrad",
          "BatchToSpace",
          "BatchToSpaceND",
          "BiasAdd",
          "BiasAddGrad",
          "BiasAddV1",
          "BroadcastArgs",
          "BroadcastGradientArgs",
          "BroadcastTo",
          "Cast",
          "Ceil",
          "CheckNumerics",
          "ComplexAbs",
          "Concat",
          "ConcatOffset",
          "ConcatV2",
          "ConjugateTranspose",
          "Const",
          "ControlTrigger",
          "Conv2D",
          "Conv2DBackpropFilter",
          "Conv2DBackpropInput",
          "Conv3D",
          "Cos",
          "Cosh",
          "CropAndResize",
          "CropAndResizeGradBoxes",
          "CropAndResizeGradImage",
          "CTCBeamSearchDecoder",
          "CTCGreedyDecoder",
          "DataFormatDimMap",
          "DataFormatVecPermute",
          "DebugGradientIdentity",
          "DebugGradientRefIdentity",
          "DecodeBmp",
          "DecodeWav",
          "DeleteSessionTensor",
          "DepthToSpace",
          "DepthwiseConv2dNative",
          "Dequantize",
          "DestroyTemporaryVariable",
          "Div",
          "DivNoNan",
          "DynamicPartition",
          "DynamicStitch",
          "Einsum",
          "Elu",
          "EluGrad",
          "Empty",
          "EncodeWav",
          "EnsureShape",
          "Enter",
          "Equal",
          "Erf",
          "Exit",
          "Exp",
          "ExpandDims",
          "FakeQuantWithMinMaxArgs",
          "FakeQuantWithMinMaxArgsGradient",
          "FakeQuantWithMinMaxVars",
          "FakeQuantWithMinMaxVarsGradient",
          "FakeQuantWithMinMaxVarsPerChannel",
          "FakeQuantWithMinMaxVarsPerChannelGradient",
          "FakeQueue",
          "FFT",
          "FFT2D",
          "FFT3D",
          "FIFOQueue",
          "FIFOQueueV2",
          "Fill",
          "Floor",
          "FloorDiv",
          "FloorMod",
          "FusedBatchNorm",
          "FusedBatchNormGrad",
          "FusedBatchNormGradV2",
          "FusedBatchNormV2",
          "FusedBatchNormV3",
          "FusedPadConv2D",
          "FusedResizeAndPadConv2D",
          "Gather",
          "GatherNd",
          "GatherV2",
          "GetSessionHandle",
          "GetSessionHandleV2",
          "GetSessionTensor",
          "Greater",
          "GreaterEqual",
          "_HostCast",
          "_HostRecv",
          "_HostSend",
          "Identity",
          "IdentityN",
          "IFFT",
          "IFFT2D",
          "IFFT3D",
          "IRFFT",
          "IRFFT2D",
          "IRFFT3D",
          "ImmutableConst",
          "InTopK",
          "InTopKV2",
          "Inv",
          "InvertPermutation",
          "InvGrad",
          "IsFinite",
          "IsNan",
          "IsVariableInitialized",
          "LeakyRelu",
          "LeakyReluGrad",
          "Less",
          "LessEqual",
          "LinSpace",
          "ListDiff",
          "_ListToArray",
          "Log",
          "LogicalAnd",
          "LogicalNot",
          "LogicalOr",
          "LogSoftmax",
          "LoopCond",
          "LRN",
          "MatMul",
          "MatrixDiag",
          "MatrixDiagV2",
          "MatrixDiagV3",
          "MatrixSetDiag",
          "MatrixSetDiagV2",
          "MatrixSetDiagV3",
          "Max",
          "Maximum",
          "MaxPool",
          "MaxPool3D",
          "MaxPoolGrad",
          "MaxPoolGradGrad",
          "MaxPoolGradGradV2",
          "MaxPoolGradV2",
          "MaxPoolGradWithArgmax",
          "MaxPoolV2",
          "MaxPoolWithArgmax",
          "Mean",
          "Merge",
          "MergeV2Checkpoints",
          "Mfcc",
          "Min",
          "Minimum",
          "MirrorPad",
          "MirrorPadGrad",
          "Mul",
          "MulNoNan",
          "Multinomial",
          "Neg",
          "NextIteration",
          "NonMaxSuppression",
          "NonMaxSuppressionV2",
          "NonMaxSuppressionV3",
          "NonMaxSuppressionV4",
          "NonMaxSuppressionWithOverlaps",
          "NoOp",
          "NotEqual",
          "OneHot",
          "OnesLike",
          "Pack",
          "Pad",
          "PaddingFIFOQueue",
          "PaddingFIFOQueueV2",
          "PadV2",
          "ParallelDynamicStitch",
          "ParseExample",
          "ParseSequenceExample",
          "ParseSingleExample",
          "ParseSingleSequenceExample",
          "Placeholder",
          "PlaceholderV2",
          "PlaceholderWithDefault",
          "Pow",
          "PreventGradient",
          "Print",
          "PrintV2",
          "Prod",
          "QuantizedAdd",
          "QuantizedAvgPool",
          "QuantizedBatchNormWithGlobalNormalization",
          "QuantizedBiasAdd",
          "QuantizedConcat",
          "QuantizedConv2D",
          "QuantizedInstanceNorm",
          "QuantizedMatMul",
          "QuantizedMaxPool",
          "QuantizedMul",
          "QuantizeDownAndShrinkRange",
          "QuantizedRelu",
          "QuantizedRelu6",
          "QuantizedReshape",
          "QuantizedResizeBilinear",
          "QuantizeV2",
          "QueueClose",
          "QueueCloseV2",
          "QueueDequeue",
          "QueueDequeueMany",
          "QueueDequeueManyV2",
          "QueueDequeueUpTo",
          "QueueDequeueUpToV2",
          "QueueDequeueV2",
          "QueueEnqueue",
          "QueueEnqueueMany",
          "QueueEnqueueManyV2",
          "QueueEnqueueV2",
          "QueueIsClosed",
          "QueueIsClosedV2",
          "QueueSize",
          "QueueSizeV2",
          "RandomGamma",
          "RandomStandardNormal",
          "RandomUniform",
          "RandomUniformInt",
          "Range",
          "Rank",
          "RealDiv",
          "Reciprocal",
          "ReciprocalGrad",
          "_Recv",
          "RefEnter",
          "RefExit",
          "RefIdentity",
          "RefMerge",
          "RefNextIteration",
          "RefSelect",
          "RefSwitch",
          "Relu",
          "Relu6",
          "Relu6Grad",
          "ReluGrad",
          "RemoteCall",
          "RequantizationRange",
          "Requantize",
          "Reshape",
          "ResizeBilinear",
          "ResizeBilinearGrad",
          "ResizeNearestNeighbor",
          "ResizeNearestNeighborGrad",
          "ResourceApplyAdadelta",
          "ResourceApplyAdagrad",
          "ResourceApplyAdagradDA",
          "ResourceApplyAdam",
          "ResourceApplyAdaMax",
          "ResourceApplyAddSign",
          "ResourceApplyCenteredRMSProp",
          "ResourceApplyFtrl",
          "ResourceApplyFtrlV2",
          "ResourceApplyGradientDescent",
          "ResourceApplyMomentum",
          "ResourceApplyPowerSign",
          "ResourceApplyProximalAdagrad",
          "ResourceApplyProximalGradientDescent",
          "ResourceApplyRMSProp",
          "ResourceSparseApplyAdadelta",
          "ResourceSparseApplyAdagrad",
          "ResourceSparseApplyAdagradDA",
          "ResourceSparseApplyCenteredRMSProp",
          "ResourceSparseApplyFtrl",
          "ResourceSparseApplyFtrlV2",
          "ResourceSparseApplyMomentum",
          "ResourceSparseApplyProximalAdagrad",
          "ResourceSparseApplyProximalGradientDescent",
          "ResourceSparseApplyRMSProp",
          "ResourceStridedSliceAssign",
          "Restore",
          "RestoreSlice",
          "RestoreV2",
          "_Retval",
          "Reverse",
          "ReverseSequence",
          "ReverseV2",
          "RFFT",
          "RFFT2D",
          "RFFT3D",
          "Round",
          "Rsqrt",
          "RsqrtGrad",
          "Save",
          "SaveSlices",
          "SaveV2",
          "ScatterNd",
          "SegmentMax",
          "SegmentMean",
          "SegmentMin",
          "SegmentProd",
          "SegmentSum",
          "Select",
          "Selu",
          "SeluGrad",
          "_Send",
          "Shape",
          "ShapeN",
          "ShardedFilename",
          "ShardedFilespec",
          "Sigmoid",
          "SigmoidGrad",
          "Sign",
          "Sin",
          "Sinh",
          "Size",
          "Slice",
          "Softmax",
          "SoftmaxCrossEntropyWithLogits",
          "Softplus",
          "SoftplusGrad",
          "Softsign",
          "SoftsignGrad",
          "SpaceToBatch",
          "SpaceToBatchND",
          "SpaceToDepth",
          "SparseApplyAdadelta",
          "SparseApplyAdagrad",
          "SparseApplyAdagradDA",
          "SparseApplyCenteredRMSProp",
          "SparseApplyFtrl",
          "SparseApplyFtrlV2",
          "SparseApplyMomentum",
          "SparseApplyProximalAdagrad",
          "SparseApplyProximalGradientDescent",
          "SparseApplyRMSProp",
          "SparseFillEmptyRows",
          "SparseFillEmptyRowsGrad",
          "SparseReshape",
          "SparseSegmentMean",
          "SparseSegmentMeanGrad",
          "SparseSegmentMeanWithNumSegments",
          "SparseSegmentSqrtN",
          "SparseSegmentSqrtNGrad",
          "SparseSegmentSqrtNWithNumSegments",
          "SparseSegmentSum",
          "SparseSegmentSumWithNumSegments",
          "SparseToDense",
          "Split",
          "SplitV",
          "Sqrt",
          "SqrtGrad",
          "Square",
          "SquaredDifference",
          "Squeeze",
          "Stack",
          "StackClose",
          "StackCloseV2",
          "StackPop",
          "StackPopV2",
          "StackPush",
          "StackPushV2",
          "StackV2",
          "StopGradient",
          "StridedSlice",
          "StridedSliceAssign",
          "StridedSliceGrad",
          "StringJoin",
          "Sub",
          "Sum",
          "Switch",
          "SymbolicGradient",
          "Tan",
          "Tanh",
          "TanhGrad",
          "TemporaryVariable",
          "TensorArray",
          "TensorArrayClose",
          "TensorArrayCloseV2",
          "TensorArrayCloseV3",
          "TensorArrayConcat",
          "TensorArrayConcatV2",
          "TensorArrayConcatV3",
          "TensorArrayGather",
          "TensorArrayGatherV2",
          "TensorArrayGatherV3",
          "TensorArrayGrad",
          "TensorArrayGradV2",
          "TensorArrayGradV3",
          "TensorArrayGradWithShape",
          "TensorArrayPack",
          "TensorArrayRead",
          "TensorArrayReadV2",
          "TensorArrayReadV3",
          "TensorArrayScatter",
          "TensorArrayScatterV2",
          "TensorArrayScatterV3",
          "TensorArraySize",
          "TensorArraySizeV2",
          "TensorArraySizeV3",
          "TensorArraySplit",
          "TensorArraySplitV2",
          "TensorArraySplitV3",
          "TensorArrayUnpack",
          "TensorArrayV2",
          "TensorArrayV3",
          "TensorArrayWrite",
          "TensorArrayWriteV2",
          "TensorArrayWriteV3",
          "Tile",
          "TileGrad",
          "Timestamp",
          "TopK",
          "TopKV2",
          "Transpose",
          "TruncateDiv",
          "TruncatedNormal",
          "Unique",
          "UniqueV2",
          "UniqueWithCounts",
          "UniqueWithCountsV2",
          "Unpack",
          "UnsortedSegmentMax",
          "UnsortedSegmentMin",
          "UnsortedSegmentProd",
          "UnsortedSegmentSum",
          "Variable",
          "VariableV2",
          "Where",
          "Xdivy",
          "Xlogy",
          "ZerosLike",
      });
  return whitelisted_flex_ops->find(tensorflow_op_name) !=
         whitelisted_flex_ops->end();
}

}  // namespace flex
}  // namespace tflite
<|endoftext|>


<commit_before>#ifndef _CCTAG_MODECONFIG_HPP
#define	_CCTAG_MODECONFIG_HPP

#ifdef DEBUG
#define CCTAG_SERIALIZE
#endif

#endif	/* MODECONFIG_HPP */
<commit_msg>Remove modeConfig.hpp<commit_after><|endoftext|>


<commit_before>// Copyright 2019 DeepMind Technologies Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "open_spiel/algorithms/get_all_states.h"

namespace open_spiel {
namespace algorithms {
namespace {

// Walk a subgame and return all states contained in the subgames. This does
// a recursive tree walk, therefore all valid sequences must have finite number
// of actions. The state collection is key-indexed by the state's string
// representation so that duplicates are not added.
// Requires State::Clone() to be implemented.
// Use with extreme caution!
// Currently not implemented for simultaneous games.
void GetSubgameStates(State* state,
                      std::map<std::string, std::unique_ptr<State>>* all_states,
                      int depth_limit, int depth, bool include_terminals,
                      bool include_chance_states) {
  if (state->IsTerminal()) {
    if (include_terminals) {
      // Include if not already present and then terminate recursion.
      std::string key = state->ToString();
      if (all_states->find(key) == all_states->end()) {
        (*all_states)[key] = state->Clone();
      }
    }
    return;
  }

  if (depth_limit >= 0 && depth > depth_limit) {
    return;
  }

  if (!state->IsChanceNode() || include_chance_states) {
    // Decision node; add only if not already present
    std::string key = state->ToString();
    if (all_states->find(key) == all_states->end()) {
      (*all_states)[key] = state->Clone();
    }
  }

  for (auto action : state->LegalActions()) {
    auto next_state = state->Clone();
    next_state->ApplyAction(action);
    GetSubgameStates(next_state.get(), all_states, depth_limit, depth + 1,
                     include_terminals, include_chance_states);
  }
}

}  // namespace

std::map<std::string, std::unique_ptr<State>> GetAllStates(
    const Game& game, int depth_limit, bool include_terminals,
    bool include_chance_states) {
  // Get the root state.
  std::unique_ptr<State> state = game.NewInitialState();
  std::map<std::string, std::unique_ptr<State>> all_states;

  // Then, do a recursive tree walk to fill up the map.
  GetSubgameStates(state.get(), &all_states, depth_limit, 0, include_terminals,
                   include_chance_states);

  if (all_states.empty()) {
    SpielFatalError("GetSubgameStates returned 0 states!");
  }

  return all_states;
}

}  // namespace algorithms
}  // namespace open_spiel
<commit_msg>get_all_states now also works if state transitions contain loops<commit_after>// Copyright 2019 DeepMind Technologies Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "open_spiel/algorithms/get_all_states.h"

namespace open_spiel {
namespace algorithms {
namespace {

// Walk a subgame and return all states contained in the subgames. This does
// a recursive tree walk, therefore all valid sequences must have finite number
// of actions. The state collection is key-indexed by the state's string
// representation so that duplicates are not added.
// Requires State::Clone() to be implemented.
// Use with extreme caution!
// Currently not implemented for simultaneous games.
void GetSubgameStates(State* state,
                      std::map<std::string, std::unique_ptr<State>>* all_states,
                      int depth_limit, int depth, bool include_terminals,
                      bool include_chance_states) {
  if (state->IsTerminal()) {
    if (include_terminals) {
      // Include if not already present and then terminate recursion.
      std::string key = state->ToString();
      if (all_states->find(key) == all_states->end()) {
        (*all_states)[key] = state->Clone();
      }
    }
    return;
  }

  if (depth_limit >= 0 && depth > depth_limit) {
    return;
  }

  bool explore = true;
  if (!state->IsChanceNode() || include_chance_states) {
    // Decision node; add only if not already present
    std::string key = state->ToString();
    if (all_states->find(key) == all_states->end()) {
      (*all_states)[key] = state->Clone();
    } else {
      explore = false;
    }
  }

  if (explore) {
    for (auto action : state->LegalActions()) {
      auto next_state = state->Clone();
      next_state->ApplyAction(action);
      GetSubgameStates(next_state.get(), all_states, depth_limit, depth + 1,
                      include_terminals, include_chance_states);
    }
  }
}

}  // namespace

std::map<std::string, std::unique_ptr<State>> GetAllStates(
    const Game& game, int depth_limit, bool include_terminals,
    bool include_chance_states) {
  // Get the root state.
  std::unique_ptr<State> state = game.NewInitialState();
  std::map<std::string, std::unique_ptr<State>> all_states;

  // Then, do a recursive tree walk to fill up the map.
  GetSubgameStates(state.get(), &all_states, depth_limit, 0, include_terminals,
                   include_chance_states);

  if (all_states.empty()) {
    SpielFatalError("GetSubgameStates returned 0 states!");
  }

  return all_states;
}

}  // namespace algorithms
}  // namespace open_spiel
<|endoftext|>


<commit_before>#ifndef database_connection_hpp
#define database_connection_hpp

#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <set>
#include <string>
#include "shared_sql_statement.hpp"
#include "detail/sqlite_dbconn.hpp"

/**
 * Namespace for housing all Sqloxx code. Sqloxx is intended as a
 * thin wrapper around SQLite, to facilitate using SQLite from C++,
 * to facilitate managing the resources required by SQLite using RAII,
 * and to reduce the verbosity required in client code wishing to
 * using the SQLite library. Sqloxx will not necessarily provide
 * much in the way of objected-relational mapping. The intention is
 * that the C++ API of Sqloxx will largely mirror the C API of
 * SQLite, so that Sqloxx could be used easily by anyone who is
 * familiar with SQLite (and with C++).
 *
 * @todo HIGH PRIORITY The API docs sometimes assume throw_on_failure will
 * only ever throw a derivative of SQLiteException; however InvalidConnection
 * is not a derivative of SQLiteException. Fix this.
 */
namespace sqloxx
{

// Forward declaration
namespace detail
{
	class SQLStatement;
}  // namespace detail

/**
 * @class DatabaseConnection
 *
 * Represents a SQLite3 database connection. Class can be extended to provide
 * representations of connections to application-specific databases.
 */
class DatabaseConnection:
	private boost::noncopyable
{
public:

	typedef
		boost::unordered_map
		<	std::string, boost::shared_ptr<detail::SQLStatement>
		>
		StatementCache;

	/**
	 * Initializes SQLite3 and creates a database connection initially
	 * set to null, i.e. not connected to any file.
	 *
	 * @param p_cache_capacity indicates the number of SQLStatements to
	 * be stored in a cache for reuse (via the class SharedSQLStatement)
	 * by the DatabaseConnection instance.
	 *
	 * Initializes SQLite3 and creates a database connection initially
	 * set to null, i.e. not connected to any file.
	 *
	 * @throws SQLiteInitializationError if initialization fails
	 * for any reason.
	 *
	 * Exception safety: strong guarantee.
	 */
	explicit
	DatabaseConnection(StatementCache::size_type p_cache_capacity = 300);

	/**
	 * Exception safety: nothrow guarantee. (Of course, the exception
	 * safety of derived classes will depend on their own destructors.)
	 */
	virtual ~DatabaseConnection();

	/**
	 * @returns true if and only if there is a connection to a valid
	 * database AND detail_id_valid() also returns true. By
	 * default, detail_is_valid() always returns true; however it may
	 * be redefined in derived classes to provide additional checks.
	 *
	 * Exception safety: the base class function
	 * DatabaseConnection::is_valid offers the nothrow guarantee,
	 * however if detail_is_valid is redefined in derived classes, exception
	 * safety will depend on how it is redefined.
	 */
	virtual bool is_valid() const;

	/**
	 * Points the database connection to a specific file
	 * given by \c filename. If the file
	 * does not already exist it is created. Note the SQLite pragma
	 * foreign_keys is always executed immediately the file is opened, to
	 * enable foreign key constraints.
	 *
	 * @todo This should be made to support Unicode filepaths, which
	 * apparently are used on Windows.
	 *
	 * @todo It appears that boost::filesystem::path::string() produces
	 * a GENERIC string (safely passable to SQLite database connection
	 * opening function) in Boost Version 1.42; but that in Version 1.46
	 * this produces a NATIVE string! Currently this function relies on the
	 * behaviour in version 1.42. I should use a macro or something to
	 * make it portable between versions of Boost.
	 *
	 * @param filepath File to connect to. The is in the form of a
	 * \c boost::filesystem::path to facilitate portability.
	 *
	 * @todo Do a full portability test to Windows, especially for cases
	 * involving escape characters and such.
	 *
	 * @throws sqloxx::InvalidFilename if filename is an empty string.
	 *
	 * @throws sqloxx::MultipleConnectionException if already connected to a
	 * database (be it this or another database).
	 *
	 * @throws SQLiteException or an exception derived therefrom (likely, but
	 * not guaranteed, to be SQLiteCantOpen) if for some other reason the
	 * connection cannot be opened.
	 *
	 * Exception safety: appears to offer the basic guarantee,
	 * however this has not been properly tested.
	 */
	void open(boost::filesystem::path const& filepath);

	/**
	 * Executes a string as an SQL command on the database connection.
	 * This should be used only where the developer has complete
	 * control of the string being passed, to prevent SQL injection
	 * attacks. Generally, the functions provided by SQLStatement should
	 * be the preferred means for building and executing SQL statements.
	 *
	 * @throws DatabaseException or some exception inheriting thereof,
	 * whenever
	 * there is any kind of error executing the statement.
	 *
	 * Exception safety: basic guarantee. (Possibly also offers
	 * strong guarantee, but not certain.)
	 */
	void execute_sql(std::string const& str);

	/**
	 * Given the name of a table in the connected database, assuming that
	 * table has a single-column primary key, and assuming that column is
	 * an autoincrementing primary key, this function will return the next
	 * highest key value (the value 1 greater than the highest primary key
	 * so far in the table). This will be the next key assigned by SQLite
	 * for an ordinary insertion into the table (assuming the default
	 * behaviour of SQLite in this regard has not been altered in some way).
	 * This function does NOT check whether the primary
	 * key is in fact autoincrementing, or even whether there is a primary
	 * key, or even whether the table with this name exists. In the event
	 * the next primary key can't be found, a
	 * value of \c KeyType(1) is simply returned. In other words, it is
	 * the caller's responsibility to make sure that table_name does in
	 * fact correspond to a table with an autoincrementing integer
	 * primary key.
	 *
	 * Assumes keys start from 1.
	 *
	 * KeyType should be an integral type, and should also be a type
	 * supported by SQLStatement::extract. If not, behaviour is \e undefined,
	 * although it is expected that compilation will fail where a KeyType
	 * that is not accepted by SQLStatement::extract is provided.
	 *
	 * It is the caller's responsibility to ensure that KeyType is large
	 * enough to accommodate the values that are \e already in the
	 * primary key of the table - otherwise behaviour is undefined.
	 *
	 * This function should not be used if \c table_name is an untrusted
	 * string.
	 *
	 * @param table_name The name of the table
	 *
	 * @returns the next highest primary key for the table, assuming it has
	 * a single-column primary key. Note if there are gaps in the numbering
	 * these are ignored. The returned value is always one greater than the
	 * currently greatest value for the key (but see exceptions).
	 *
	 * @throws sqloxx::TableSizeException if the greatest primary key value
	 * already in the table is the maximum value for \c KeyType, so that
	 * another row could not be inserted without overflow.
	 *
	 * @throws sqloxx::DatabaseException, or a derivative therefrom, may
	 * be thrown if there is some other
	 * error finding the next primary key value. This should not occur except
	 * in the case of a corrupt database, or a memory allocation error
	 * (extremely unlikely), or the database connection being invalid
	 * (including because not yet connected to a database file).
	 */
	template <typename KeyType>
	KeyType next_auto_key(std::string const& table_name);

	/**
	 * Creates table containing integers representing boolean values.
	 * This might be used to provide foreign key constraints for other
	 * tables where we wish a particular column to have boolean values
	 * only.
	 *
	 * The table is called "booleans" and has one column, an integer
	 * primary key field with the heading "representation". There are
	 * two rows, one with 0 in the "representation" column, representing
	 * \e false, and the other with 1, representing \e true.
	 *
	 * Exception safety: strong guarantee.
	 */
	void setup_boolean_table();

	/**
	 * Returns the maximum level of transaction nesting that can be handled
	 * by the DatabaseConnection class.
	 *
	 * Exception safety: nothrow guarantee.
	 */
	static int max_nesting();

	/**
	 * Begins a transaction. Transactions may be nested. Only the
	 * outermost call to begin_transaction causes the "begin transaction"
	 * SQL command to be executed.
	 *
	 * SQL transactions should be controlled either solely through the
	 * methods begin_transaction and end_transaction, \e or solely through
	 * the direct execution of SQL statement strings "begin transaction" and
	 * "end transaction". Mixing the two will result in undefined behaviour.
	 *
	 * @throws TransactionNestingException in the event that the maximum
	 * level of nesting has been reached. The maximum level of nesting is
	 * equal to the value returned by max_nesting().
	 */
	void begin_transaction();

	/**
	 * Ends a transaction. Transactions may be nested. Only the outermost
	 * call to end_transaction causes the "end transaction" SQL command
	 * to be executed.
	 *
	 * See documentation of begin_transaction also.
	 *
	 * @throws TransactionNestingException in the event that there are
	 * more calls to end_transaction than there have been to
	 * begin_transaction.
	 */
	void end_transaction();

	/**
	 * @returns a shared pointer to a SQLStatement. This will
	 * either point to an existing SQLStatement that is cached within
	 * the DatabaseConnection (if a SQLStatement with \c
	 * statement_text has already been created on this DatabaseConnection and
	 * is not being used elsewhere), or
	 * will be a pointer to a newly created and new cached SQLStatement (if a
	 * SQLStatement with \c statement_text has not yet been created on this
	 * DatabaseConnection, or it has been created but is being used
	 * elsewhere).
	 *
	 * This function is only intended to be called by the
	 * constructor of SharedSQLStatement. It should not be called elsewhere.
	 */
	boost::shared_ptr<detail::SQLStatement> provide_sql_statement
	(	std::string const& statement_text
	);

private:

	void unchecked_end_transaction();

	/**
	 * By default this always returns true. However it may be overriden
	 * in derived classes as required.
	 */
	virtual bool detail_is_valid() const;

	boost::shared_ptr<detail::SQLiteDBConn> m_sqlite_dbconn;
	int m_transaction_nesting_level;
	StatementCache m_statement_cache;
	StatementCache::size_type m_cache_capacity;
	static int const s_max_nesting;
};

// FUNCTION TEMPLATE DEFINITIONS AND INLINE FUNCTIONS

inline
bool
DatabaseConnection::is_valid() const
{
	return m_sqlite_dbconn->is_valid() && detail_is_valid();
}

inline
void
DatabaseConnection::open(boost::filesystem::path const& filepath)
{
	m_sqlite_dbconn->open(filepath);
	return;
}

inline
void
DatabaseConnection::execute_sql(std::string const& str)
{
	m_sqlite_dbconn->execute_sql(str);
	return;
}

inline
bool
DatabaseConnection::detail_is_valid() const
{
	return true;
}

template <typename KeyType>
inline
KeyType
DatabaseConnection::next_auto_key(std::string const& table_name)
{

	try
	{
		SharedSQLStatement statement
		(	*this,
			"select seq from sqlite_sequence where name = :p"
		);
		statement.bind(":p", table_name);
		if (!statement.step())
		{
			return 1;
		}
		KeyType const max_key = statement.extract<KeyType>(0);
		if (max_key == std::numeric_limits<KeyType>::max())
		{
			throw TableSizeException
			(	"Key cannot be safely incremented with given type."
			);
		}
		return max_key + 1;
	}
	catch (SQLiteError&)
	{
		// Catches case where there is no sqlite_sequence table
		SharedSQLStatement sequence_finder
		(	*this,
			"select name from sqlite_master where type = 'table' and "
			"name = 'sqlite_sequence';"
		);
		if (!sequence_finder.step())
		{
			return 1;
		}
		throw;
	}
}

inline
int
DatabaseConnection::max_nesting()
{
	return s_max_nesting;
}

inline
void
DatabaseConnection::unchecked_end_transaction()
{
	SharedSQLStatement statement
	(	*this,
		"end"
	);
	statement.step();
	return;
}

}  // namespace sqloxx

#endif  // database_connection_hpp
<commit_msg>Got rid of unused function DatabaseConnection::detail_is_valid. Was adding complexity to API for no obvious benefit.<commit_after>#ifndef database_connection_hpp
#define database_connection_hpp

#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <set>
#include <string>
#include "shared_sql_statement.hpp"
#include "detail/sqlite_dbconn.hpp"

/**
 * Namespace for housing all Sqloxx code. Sqloxx is intended as a
 * thin wrapper around SQLite, to facilitate using SQLite from C++,
 * to facilitate managing the resources required by SQLite using RAII,
 * and to reduce the verbosity required in client code wishing to
 * using the SQLite library. Sqloxx will not necessarily provide
 * much in the way of objected-relational mapping. The intention is
 * that the C++ API of Sqloxx will largely mirror the C API of
 * SQLite, so that Sqloxx could be used easily by anyone who is
 * familiar with SQLite (and with C++).
 *
 * @todo HIGH PRIORITY The API docs sometimes assume throw_on_failure will
 * only ever throw a derivative of SQLiteException; however InvalidConnection
 * is not a derivative of SQLiteException. Fix this.
 */
namespace sqloxx
{

// Forward declaration
namespace detail
{
	class SQLStatement;
}  // namespace detail

/**
 * @class DatabaseConnection
 *
 * Represents a SQLite3 database connection. Class can be extended to provide
 * representations of connections to application-specific databases.
 */
class DatabaseConnection:
	private boost::noncopyable
{
public:

	typedef
		boost::unordered_map
		<	std::string, boost::shared_ptr<detail::SQLStatement>
		>
		StatementCache;

	/**
	 * Initializes SQLite3 and creates a database connection initially
	 * set to null, i.e. not connected to any file.
	 *
	 * @param p_cache_capacity indicates the number of SQLStatements to
	 * be stored in a cache for reuse (via the class SharedSQLStatement)
	 * by the DatabaseConnection instance.
	 *
	 * Initializes SQLite3 and creates a database connection initially
	 * set to null, i.e. not connected to any file.
	 *
	 * @throws SQLiteInitializationError if initialization fails
	 * for any reason.
	 *
	 * Exception safety: strong guarantee.
	 */
	explicit
	DatabaseConnection(StatementCache::size_type p_cache_capacity = 300);

	/**
	 * Exception safety: nothrow guarantee. (Of course, the exception
	 * safety of derived classes will depend on their own destructors.)
	 */
	virtual ~DatabaseConnection();

	/**
	 * @returns true if and only if there is a connection to a valid
	 * database.
	 *
	 * Exception safety: nothrow guarantee.
	 */
	virtual bool is_valid() const;

	/**
	 * Points the database connection to a specific file
	 * given by \c filename. If the file
	 * does not already exist it is created. Note the SQLite pragma
	 * foreign_keys is always executed immediately the file is opened, to
	 * enable foreign key constraints.
	 *
	 * @todo This should be made to support Unicode filepaths, which
	 * apparently are used on Windows.
	 *
	 * @todo It appears that boost::filesystem::path::string() produces
	 * a GENERIC string (safely passable to SQLite database connection
	 * opening function) in Boost Version 1.42; but that in Version 1.46
	 * this produces a NATIVE string! Currently this function relies on the
	 * behaviour in version 1.42. I should use a macro or something to
	 * make it portable between versions of Boost.
	 *
	 * @param filepath File to connect to. The is in the form of a
	 * \c boost::filesystem::path to facilitate portability.
	 *
	 * @todo Do a full portability test to Windows, especially for cases
	 * involving escape characters and such.
	 *
	 * @throws sqloxx::InvalidFilename if filename is an empty string.
	 *
	 * @throws sqloxx::MultipleConnectionException if already connected to a
	 * database (be it this or another database).
	 *
	 * @throws SQLiteException or an exception derived therefrom (likely, but
	 * not guaranteed, to be SQLiteCantOpen) if for some other reason the
	 * connection cannot be opened.
	 *
	 * Exception safety: appears to offer the basic guarantee,
	 * however this has not been properly tested.
	 */
	void open(boost::filesystem::path const& filepath);

	/**
	 * Executes a string as an SQL command on the database connection.
	 * This should be used only where the developer has complete
	 * control of the string being passed, to prevent SQL injection
	 * attacks. Generally, the functions provided by SQLStatement should
	 * be the preferred means for building and executing SQL statements.
	 *
	 * @throws DatabaseException or some exception inheriting thereof,
	 * whenever
	 * there is any kind of error executing the statement.
	 *
	 * @throws InvalidConnection if the database connection is invalid.
	 *
	 * Exception safety: basic guarantee. (Possibly also offers
	 * strong guarantee, but not certain.)
	 */
	void execute_sql(std::string const& str);

	/**
	 * Given the name of a table in the connected database, assuming that
	 * table has a single-column primary key, and assuming that column is
	 * an autoincrementing primary key, this function will return the next
	 * highest key value (the value 1 greater than the highest primary key
	 * so far in the table). This will be the next key assigned by SQLite
	 * for an ordinary insertion into the table (assuming the default
	 * behaviour of SQLite in this regard has not been altered in some way).
	 * This function does NOT check whether the primary
	 * key is in fact autoincrementing, or even whether there is a primary
	 * key, or even whether the table with this name exists. In the event
	 * the next primary key can't be found, a
	 * value of \c KeyType(1) is simply returned. In other words, it is
	 * the caller's responsibility to make sure that table_name does in
	 * fact correspond to a table with an autoincrementing integer
	 * primary key.
	 *
	 * Assumes keys start from 1.
	 *
	 * KeyType should be an integral type, and should also be a type
	 * supported by SQLStatement::extract. If not, behaviour is \e undefined,
	 * although it is expected that compilation will fail where a KeyType
	 * that is not accepted by SQLStatement::extract is provided.
	 *
	 * It is the caller's responsibility to ensure that KeyType is large
	 * enough to accommodate the values that are \e already in the
	 * primary key of the table - otherwise behaviour is undefined.
	 *
	 * This function should not be used if \c table_name is an untrusted
	 * string.
	 *
	 * @param table_name The name of the table
	 *
	 * @returns the next highest primary key for the table, assuming it has
	 * a single-column primary key. Note if there are gaps in the numbering
	 * these are ignored. The returned value is always one greater than the
	 * currently greatest value for the key (but see exceptions).
	 *
	 * @throws sqloxx::TableSizeException if the greatest primary key value
	 * already in the table is the maximum value for \c KeyType, so that
	 * another row could not be inserted without overflow.
	 *
	 * @throws sqloxx::DatabaseException, or a derivative therefrom, may
	 * be thrown if there is some other
	 * error finding the next primary key value. This should not occur except
	 * in the case of a corrupt database, or a memory allocation error
	 * (extremely unlikely), or the database connection being invalid
	 * (including because not yet connected to a database file).
	 */
	template <typename KeyType>
	KeyType next_auto_key(std::string const& table_name);

	/**
	 * Creates table containing integers representing boolean values.
	 * This might be used to provide foreign key constraints for other
	 * tables where we wish a particular column to have boolean values
	 * only.
	 *
	 * The table is called "booleans" and has one column, an integer
	 * primary key field with the heading "representation". There are
	 * two rows, one with 0 in the "representation" column, representing
	 * \e false, and the other with 1, representing \e true.
	 *
	 * Exception safety: strong guarantee.
	 */
	void setup_boolean_table();

	/**
	 * Returns the maximum level of transaction nesting that can be handled
	 * by the DatabaseConnection class.
	 *
	 * Exception safety: nothrow guarantee.
	 */
	static int max_nesting();

	/**
	 * Begins a transaction. Transactions may be nested. Only the
	 * outermost call to begin_transaction causes the "begin transaction"
	 * SQL command to be executed.
	 *
	 * SQL transactions should be controlled either solely through the
	 * methods begin_transaction and end_transaction, \e or solely through
	 * the direct execution of SQL statement strings "begin transaction" and
	 * "end transaction". Mixing the two will result in undefined behaviour.
	 *
	 * @throws TransactionNestingException in the event that the maximum
	 * level of nesting has been reached. The maximum level of nesting is
	 * equal to the value returned by max_nesting().
	 */
	void begin_transaction();

	/**
	 * Ends a transaction. Transactions may be nested. Only the outermost
	 * call to end_transaction causes the "end transaction" SQL command
	 * to be executed.
	 *
	 * See documentation of begin_transaction also.
	 *
	 * @throws TransactionNestingException in the event that there are
	 * more calls to end_transaction than there have been to
	 * begin_transaction.
	 */
	void end_transaction();

	/**
	 * @returns a shared pointer to a SQLStatement. This will
	 * either point to an existing SQLStatement that is cached within
	 * the DatabaseConnection (if a SQLStatement with \c
	 * statement_text has already been created on this DatabaseConnection and
	 * is not being used elsewhere), or
	 * will be a pointer to a newly created and new cached SQLStatement (if a
	 * SQLStatement with \c statement_text has not yet been created on this
	 * DatabaseConnection, or it has been created but is being used
	 * elsewhere).
	 *
	 * This function is only intended to be called by the
	 * constructor of SharedSQLStatement. It should not be called elsewhere.
	 */
	boost::shared_ptr<detail::SQLStatement> provide_sql_statement
	(	std::string const& statement_text
	);

private:

	void unchecked_end_transaction();

	boost::shared_ptr<detail::SQLiteDBConn> m_sqlite_dbconn;
	int m_transaction_nesting_level;
	StatementCache m_statement_cache;
	StatementCache::size_type m_cache_capacity;
	static int const s_max_nesting;
};

// FUNCTION TEMPLATE DEFINITIONS AND INLINE FUNCTIONS

inline
bool
DatabaseConnection::is_valid() const
{
	return m_sqlite_dbconn->is_valid();
}

inline
void
DatabaseConnection::open(boost::filesystem::path const& filepath)
{
	m_sqlite_dbconn->open(filepath);
	return;
}

inline
void
DatabaseConnection::execute_sql(std::string const& str)
{
	m_sqlite_dbconn->execute_sql(str);
	return;
}

template <typename KeyType>
inline
KeyType
DatabaseConnection::next_auto_key(std::string const& table_name)
{

	try
	{
		SharedSQLStatement statement
		(	*this,
			"select seq from sqlite_sequence where name = :p"
		);
		statement.bind(":p", table_name);
		if (!statement.step())
		{
			return 1;
		}
		KeyType const max_key = statement.extract<KeyType>(0);
		if (max_key == std::numeric_limits<KeyType>::max())
		{
			throw TableSizeException
			(	"Key cannot be safely incremented with given type."
			);
		}
		return max_key + 1;
	}
	catch (SQLiteError&)
	{
		// Catches case where there is no sqlite_sequence table
		SharedSQLStatement sequence_finder
		(	*this,
			"select name from sqlite_master where type = 'table' and "
			"name = 'sqlite_sequence';"
		);
		if (!sequence_finder.step())
		{
			return 1;
		}
		throw;
	}
}

inline
int
DatabaseConnection::max_nesting()
{
	return s_max_nesting;
}

inline
void
DatabaseConnection::unchecked_end_transaction()
{
	SharedSQLStatement statement
	(	*this,
		"end"
	);
	statement.step();
	return;
}

}  // namespace sqloxx

#endif  // database_connection_hpp
<|endoftext|>