UFUNCTION(BlueprintCallable, Category = "Bees")
static void DiscoverSpecies(UBeeGenetic *bee);
UFUNCTION(BlueprintCallable, Category = "Bees")
static int32 DiscoveredCount();
UFUNCTION(BlueprintCallable, Category = "Bees")
static FBeeColors getBeeColors(TEnumAsByte<Species> species);
};
#include "BeeGenetic.h"
const float COMB_AMOUNT_PER_MINUTE = 0.5f;
// Sets default values for this component's properties
UBeeGenetic::UBeeGenetic()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = false;
// ...
}
// Called when the game starts
void UBeeGenetic::BeginPlay()
{
Super::BeginPlay();
// ...
}
void UBeeGenetic::Init(TEnumAsByte<Species> main, TEnumAsByte<Species> sec, int32 speed, int32 fertility)
{
Main = main;
Sec = sec;
Speed = speed;
Fertility = fertility;
}
// Called every frame
void UBeeGenetic::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// ...
}
int32 UBeeGenetic::GetSpeedValue()
{
int32 count = 0;
int32 mask = 1;
for (int i = 0; i < 8; ++i)
{
if (mask & Speed)
++count;
mask <<= 1;
}
return count;
}
int32 UBeeGenetic::GetFertiliryValue()
{
int32 count = 0;
int32 maskMain = 1;
int32 maskSec = 2;
for (int i = 0; i < 5; ++i)
{
if (maskMain & Fertility || maskSec & Fertility)
++count;
maskMain <<= 2;
maskSec <<= 2;
}
return count;
}
int32 UBeeGenetic::GetRadiusValue()
{
int32 count = 0;
int32 maskMain = 1;
int32 maskSec = 2;
for (int i = 0; i < 3; ++i)
{
if (maskMain & Radius || maskSec & Radius)
++count;
maskMain <<= 2;
maskSec <<= 2;
}
return count;
}
UBeeGenetic *UBeeGenetic::Construct(TEnumAsByte<Species> main, TEnumAsByte<Species> sec, int32 speed, int32 fertility)
{
UBeeGenetic *bee = NewObject<UBeeGenetic>();
bee->Init(main, sec, speed, fertility);
return bee;
}
//TODO: move this to helper functions
const int32 SPEED_GENS_COUNT = 8;
const int32 FERTILITRY_GENS_COUNT = 10;
static bool get_bit(int32 num, int32 pos)
{
return (num >> pos) & 1U;
}
static FString get_gens_str(int32 gen, int32 gens_count)
{
FString out;
for (int i = 0; i < gens_count; ++i)
{
out += get_bit(gen, i) ? "1" : "0";
if (i % 2 == 1)
out += " ";
}
return out;
}
FString UBeeGenetic::GetInfoBee()
{
FString out = GetInfoSpecies();
out += ": " + GetInfoSpeed() + "; " + GetInfoFertility();
return out;
}
FString UBeeGenetic::GetInfoSpecies()
{
FString out;
FString mainName = UEnum::GetValueAsString(Main);
FString secName = UEnum::GetValueAsString(Sec);
if (mainName.Equals(secName))
out = mainName;
else
out = mainName + "-" + secName;
out += " bee";
return out;
}
FString UBeeGenetic::GetInfoSpeed()
{
return FString::Printf(TEXT("Speed %d %s"), GetSpeedValue(), *get_gens_str(Speed, SPEED_GENS_COUNT));
}
FString UBeeGenetic::GetInfoFertility()
{
return FString::Printf(TEXT("Fertility %d %s"), GetFertiliryValue(), *get_gens_str(Fertility, FERTILITRY_GENS_COUNT));
}
bool UBeeGenetic::GetGenSpeedValue(int32 index)
{
return get_bit(Speed, index) == 1;
}
bool UBeeGenetic::GetGenFertilityValue(int32 index)
{
return get_bit(Fertility, index) == 1;
}
int32 UBeeGenetic::GetProductivitySpeed()
{
int32 out = 0;
float speedCoeff = *SpeedCoeff.Find(GetSpeedValue());
out += *CombCostByTier.Find(*Tiers.FindKey(Main)) * speedCoeff;
if (Main != Sec)
{
out += *CombCostByTier.Find(*Tiers.FindKey(Sec)) * speedCoeff;
out *= 0.5f;
}
return out * COMB_AMOUNT_PER_MINUTE;
}
UBeeGenetic *UBeeGenetic::CreateMeadowBee()
{
return Construct(Species::Meadow, Species::Meadow, 15, 15);
}
UBeeGenetic *UBeeGenetic::CreateForestBee()
{
return Construct(Species::Forest, Species::Forest, 51, 51);
}
UBeeGenetic *UBeeGenetic::CreateRiverBee()
{
return Construct(Species::River, Species::River, 60, 60);
}
bool UBeeGenetic::IsDiscoveredSpecies(TEnumAsByte<Species> species)
{
return DiscoveredSpecies[species];
}
FString UBeeGenetic::GetSpeciesString(TEnumAsByte<Species> species)
{
return StaticEnum<Species>()->GetValueAsString(species);
}
void UBeeGenetic::DiscoverSpecies(UBeeGenetic *bee)
{
if (bee)
{
DiscoveredSpecies[bee->Main] = true;
DiscoveredSpecies[bee->Sec] = true;
}
}
int32 UBeeGenetic::DiscoveredCount()
{
int32 count = 0;
for (const auto [key, value] : DiscoveredSpecies)
{
if (value)
{
++count;
}
}
return count;
}
FBeeColors UBeeGenetic::getBeeColors(TEnumAsByte<Species> species)
{
return SpeciesColors[species];
}
Приложение Б
Исходный код файлов InheritMutationLibrary.h и InheritMutationLibrary.cpp
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "BeeGenetic.h"
#include "InheritMutationLibrary.generated.h"
/**
*
*/
UCLASS()
class BEEKEEPERVR_API UInheritMutationLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable, Category = "Bees")
static UBeeGenetic *Inherit(const UBeeGenetic *p1, const UBeeGenetic *p2);
UFUNCTION(BlueprintCallable, Category = "Bees")
static UBeeGenetic *CopyBeeProps(const UBeeGenetic *from);
};
#include "InheritMutationLibrary.h"
#include "Math/UnrealMathUtility.h"
#include "Containers/Map.h"
const float MUTATION_GEN_CHANCE = 0.05f;
const float MUTATION_SPECIES_CHANCE = 0.4f;
const float MUTATION_SPECIES_CHANCE_PARENTS_EQUAL = 0.1f;
const float MUTATION_TIER_DOWN_TWO_CHANCE = 0.1f;
const float MUTATION_TIER_DOWN_ONE_CHANCE = 0.3f;
const float MUTATION_TIER_NO_CHANGE_CHANCE = 0.7f;
const float MUTATION_TIER_UP_ONE_CHANCE = 0.9f;
const float MUTATION_TIER_UP_TWO_CHANCE = 1.0f;
const int32 SPEED_GENS_COUNT = 8;
const int32 FERTILITRY_GENS_COUNT = 10;
static bool random(float less)
{
return FMath::FRandRange(0.f, 1.f) < less;
}
//https://stackoverflow.com/questions/47981/how-do-i-set-clear-and-toggle-a-single-bit
static void set_bit(int32 &num, int32 pos)
{
num |= 1UL << pos;
}