# Unreal Code Examples

Basic Integration

{% tabs %}
{% tab title="First Tab" %}

```cpp
void PlayerController::BeginPlay()
{
    Super::BeginPlay();
    	
    World = NewObject<UARCWorld>(this);
    ARCActionSpace = NewObject<UARCActionSpace>(this);
    ARCStateSpace = NewObject<UARCStateSpace>(this);

    Model = UARCBPLibrary::LoadModel(ModelConfig, false);
}

void PlayerController::Tick(float Delta)
{
    Super::Tick(Delta);

    // Create the world representation which we will convert to the state space matrix
    World->InitializeWorld(
        // All world attributes/objects that are relevant for the AI
    );
    
    // Get the state space for the model
    TArray<double> State = ARCStateSpace->GetState(*World);
    
    if (human)
    {
        // Convert the inputs into something the ARC agent can understand
        TMap<FString, bool> Action = ARCActionSpace->ConvertInputToBools(*World);
        
        // Add the observed state and action to the dataset
        Model->Collect(State, Action);
    } else {
        // If ARC agent is controlling, then perform inference
        auto ModelAction = UARCBPLibrary::SelectAction(Model,State);
        
        // Execute the action in-game
        auto Action = ARCActionSpace->ConvertActions(ModelAction);    
    }
}
```

Then at the end of the game, you can send the data you collected to the trainer platform as follows:

```csharp
Model->UploadData();
```

OR

If you have the API access to train in-game, then you can directly train within the game loop as follows:

```csharp
Model->Train();
```

{% endtab %}
{% endtabs %}

State Space

{% tabs %}
{% tab title="First Tab" %}
First we will create the header file

```c
#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "ARCStateSpace.generated.h"

class Pawn;

UCLASS(Blueprintable)
class UARCWorld : public UObject
{
    GENERATED_BODY()

public:
    UARCWorld(const FObjectInitializer& ObjectInitializer);

    TObjectPtr<APawn> LeftPaddlePawn;
    TObjectPtr<AActor> BallActor;

    void InitializeWorld(TObjectPtr<APawn> InLeftPaddlePawn, TObjectPtr<AActor> InBallActor)
    {
        LeftPaddlePawn = InLeftPaddlePawn;
        BallActor = InBallActor;
    }
};

UCLASS(Blueprintable)
class UARCStateSpace : public UObject
{
    GENERATED_BODY()

public:
    UARCStateSpace(const FObjectInitializer& ObjectInitializer);
    static TArray<double> GetState(const UARCWorld& World);
private:
    double Bound(double x);
};
```

Then we will create the C++ file

```cpp
#pragma once

#include "ARCStateSpace.h"

UARCWorld::UARCWorld(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
}

UARCStateSpace::UARCStateSpace(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
}

TArray<double> UARCStateSpace::GetState(const UARCWorld& World)
{
    const double GameAreaHeight = 8.0;
    const double GameAreaWidth = 16.0;

    double LeftPaddleY = World.LeftPaddlePawn->GetActorLocation().Y;
    double BallY = World.BallActor->GetActorLocation().Y;
    double BallX = World.BallActor->GetActorLocation().X;
    FVector BallVel = World.BallActor->GetVelocity();
    
    double AbsolutePaddlePos = (LeftPaddleY / GameAreaHeight) * 2.0;
    double YDist = (BallY - LeftPaddleY) / GameAreaHeight;
    double XDist = Bound((-BallX / GameAreaWidth) * 2.0);
    double XVel = Bound(BallVel.X / 8.0);
    double YVel = Bound(BallVel.Y / 8.0);

    return { AbsolutePaddlePos, YDist, XDist, XVel, YVel };
}

double UARCStateSpace::Bound(double x)
{
    return FMath::Clamp(x, -1.0, 1.0);
}
```

{% endtab %}
{% endtabs %}

Action space

{% tabs %}
{% tab title="First Tab" %}
First we will create the header file

```c
#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "ARCStateSpace.h"
#include "ARCActionSpace.generated.h"

UCLASS(Blueprintable)
class UARCActionSpace : public UObject
{
    GENERATED_BODY()

public:
    UARCActionSpace(const FObjectInitializer& ObjectInitializer);
    TMap<FString, bool> ConvertInputToBools(const UARCWorld& World);
    FVector ConvertActions(TMap<FString, bool> Action);
};
```

Then we will create the C++ file

```cpp
#pragma once

#include "ARCActionSpace.h"

UARCActionSpace::UARCActionSpace(const FObjectInitializer& ObjectInitializer)
{
}

FVector UARCActionSpace::ConvertActions(TMap<FString, bool> Action)
{
    FVector MovementInput = FVector::ZeroVector;
    if (actions["up"])
    {
        MovementInput = FVector(0.0f, 1.0f, 0.0f);
    }
    else if (actions["down"])
    {
        MovementInput = FVector(0.0f, -1.0f, 0.0f);
    }
    return MovementInput;
}

TMap<FString, bool> UARCActionSpace::ConvertInputToBools(const UARCWorld& World)
{
    TMap<FString, bool> Action;
    FVector PaddleVelocity = World.LeftPaddlePawn->GetVelocity();

    Action.Add("up", PaddleVelocity.Y > 0.0f);
    Action.Add("down", PaddleVelocity.Y < 0.0f);
    Action.Add("idle", PaddleVelocity.Y == 0.0f);

    return Action;
}
```

{% endtab %}
{% endtabs %}

Data Collection

```cpp
Model->Collect(State, Action);
```

```cpp
Model->SetCollectionInterval(15); // Collect every 15 frames
```

Model Initialization

```cpp
ModelConfig.ArchitectureId = "my-first-model";
ModelConfig.UserId = "user-id";
ModelConfig.SlotIdx = 0;

Model = UARCBPLibrary::CreateModel(ModelConfig);
```

Inference

<pre class="language-cpp"><code class="lang-cpp"><strong>auto Action = UARCBPLibrary::SelectAction(Model, State);
</strong>
// Sample from the distribution to select an action
auto Probabilities = UARCBPLibrary::GetProbabilities(Model, State);
</code></pre>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.nrnagents.ai/getting-started/unreal-code-examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
