Skip to content

Commit

Permalink
Merge branch 'master' into packaging
Browse files Browse the repository at this point in the history
  • Loading branch information
jonpas committed Jan 21, 2018
2 parents 2cd73e4 + 9c7019b commit 933254f
Show file tree
Hide file tree
Showing 15 changed files with 293 additions and 27 deletions.
Binary file modified Content/EmptierThanVoid/UI/HUD/WBP_GameUI_ShipStatus.uasset
Binary file not shown.
Binary file modified Content/EmptierThanVoid/UI/HUD/WPB_ActionDeathLogEntry.uasset
Binary file not shown.
Binary file modified Content/EmptierThanVoid/UI/HUD/WPB_ActionLogEntry.uasset
Binary file not shown.
144 changes: 144 additions & 0 deletions Source/ETV/ETVAI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright (C) Team13. All rights reserved.

#include "ETVAI.h"
#include "ETVGameModeBase.h"
#include "ETVActionTarget_Fire.h"
#include "ETVActionTarget_Move.h"

// TODO Returns duplicate objects of all the ships on the board for AI to calculate the next move
TArray<AETVShip*> GetBoardStateClone(TArray<AETVShip*> BoardState)
{
TArray<AETVShip*> Clones;
for(auto ShipRef : BoardState)
{
// Check for class?

// Cast and create clone

// Get clone's reference

// Push reference to clones

}
return Clones;
}

// TODO Calculates maximum score and the coresponding board state if the given ship makes a move
TArray<AETVShip*> GetNextBoardStateAndScore(TArray<AETVShip*> BoardState, int32 ShipIndex, TArray<TArray<int32>> &MoveInstructions)
{
return TArray<AETVShip*>();
}

// TODO Returns the 5 best moves for the given boardState
TArray<TArray<AETVShip*>> GetTop5Moves(TArray<AETVShip*> BoardState, TArray<TArray<int32>> &MoveInstructions)
{
return TArray<TArray<AETVShip*>>();
}


UETVAI::UETVAI()
{

}
// TODO Better Implementation
TArray<int32> UETVAI::GetMove(TArray<AETVShip*> Ships)
{
TArray<int32> MoveInstructions;

// Get gamemode
AETVGameModeBase* GameMode = Cast<AETVGameModeBase>(Ships[0]->GetWorld()->GetAuthGameMode());

int32 MostImportantPlayerShip = -1;
int32 MostImportantAIShip = -1;
int32 RandomAIShip = -1;
// Find most important ships
int index = 0;
for (auto ShipReference : Ships)
{
// AI Ship
if (ShipReference->IsEnemy())
{
if (MostImportantAIShip != -1)
{
// This will always be the capital
if (ShipReference->GetScore() > Ships[MostImportantAIShip]->GetScore())
{
MostImportantAIShip = index;
}
}
else
{
MostImportantAIShip = index;
RandomAIShip = index;
}
// 1/8 chance
if (FMath::RandBool() && FMath::RandBool() && FMath::RandBool())
{
RandomAIShip = index;
}
}
else if (GameMode->IsTileVisible(ShipReference->GetTilePosition(), EETVShipType::EnemyShip) == true)
{
if (MostImportantPlayerShip != -1)
{
if (ShipReference->GetScore() > Ships[MostImportantPlayerShip]->GetScore())
{
MostImportantPlayerShip = index;
}
}
else
{
MostImportantPlayerShip = index;
}
}
++index;
}
// Does AI see enemy ship
if (MostImportantPlayerShip != -1)
{
int jndex = 0;
// If possible try and attack
for (auto ShipReference : Ships)
{
if (ShipReference->IsEnemy())
{
// Currently fire laser is always 0 and torpedo is 1 on fighters
int ActionIndex = 0;
if(ShipReference->GetShipClass() == "Fighter" || ShipReference->GetShipClass() == "Capital")
ActionIndex = 1;
UETVActionTarget_Fire* Laser = Cast<UETVActionTarget_Fire>(ShipReference->GetActions()[ActionIndex]);
// TODO - Add check if torped avaliable
Laser->SetTarget(Ships[MostImportantPlayerShip], Ships[MostImportantPlayerShip]->GetX(), Ships[MostImportantPlayerShip]->GetY());
if (Laser->CanPerform())
{
MoveInstructions.SetNum(4);
MoveInstructions[0] = (Ships[MostImportantPlayerShip]->GetScore());
MoveInstructions[1] = (jndex);
MoveInstructions[2] = (ActionIndex);
MoveInstructions[3] = (MostImportantPlayerShip);
return MoveInstructions;
}
}
++jndex;
}
}
// We we didn't find enemy ship or we can't attack it
// We move a ship randomly
// TODO Add checker if we can heal most important ship
UETVActionTarget_Move* MoveAction = Cast<UETVActionTarget_Move>(Ships[RandomAIShip]->GetActions().Last(0));
int x = -1;
int y = -1;
while (!MoveAction->CanPerform())
{
x = Ships[RandomAIShip]->GetTilePosition().X + FMath::RandRange(1, Ships[RandomAIShip]->GetMoveRange());
y = Ships[RandomAIShip]->GetTilePosition().Y + FMath::RandRange(1, Ships[RandomAIShip]->GetMoveRange());
MoveAction->SetTarget(GameMode->GetTileMapActor(), x, y);
}
MoveInstructions.SetNum(5);
MoveInstructions[0] = (Ships[RandomAIShip]->GetScore());
MoveInstructions[1] = (RandomAIShip);
MoveInstructions[2] = (Ships[RandomAIShip]->GetActions().Num()-1);
MoveInstructions[3] = (x);
MoveInstructions[4] = (y);
return MoveInstructions;
};
49 changes: 49 additions & 0 deletions Source/ETV/ETVAI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (C) Team13. All rights reserved.

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "ETVShip.h"
#include "ETVAI.generated.h"

/**
* Class that contains all the logic for the AI in the game
* It passes move instructions to the game mode in a form of An Array of int32 Arrays, where ints represent ship indexes,
* action indexesm coordinates or traget ship indexes and the board state if this move is used, 1 array of this ints represents 1 posssible move
* --------------------------------------------
* 0: Score
* 1: Ship index
* 2: Action index
* 3: Target ship index/X coordinate
* 4: Y coordinate
* --------------------------------------------
* If array returned contains 4 ints it can be deduced that the last int represnts an index for the target ship else it represents the X coordinate
* of the board
* --------------------------------------------
* Ai will look a certain amount of turns into the future, predict the best moves and choose the move that will
* lead to the best outcome in set amount of turns
* --------------------------------------------
* It currently does not work like this.
* Problems to solve: Dynamic Deep Copying of actors or support for dummy properties in actors that AI can use to calculate board states.
* --------------------------------------------
* AI currently atack the highes priority target of enemy, heals the ship with highest priority on his sie or moves a ship randomly
* --------------------------------------------
*/
UCLASS()
class ETV_API UETVAI : public UObject
{
GENERATED_BODY()

public:
// Sets default values for this actor's properties
UETVAI();


public:
// Returns the move AI will make this turn depending on the given board state
TArray<int32> GetMove(TArray<AETVShip*> Ships);



};
3 changes: 2 additions & 1 deletion Source/ETV/ETVAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ void UETVAction::OnEndPerform()
AETVGameModeBase* GameMode = Cast<AETVGameModeBase>(GetWorld()->GetAuthGameMode());
GameMode->UpdateVisibleTiles(EETVShipType::PlayerShip);

if (bEndsTurn)
// End turn if action automatically ends it and turn is not AI controlled (AI automatically goes to next turn)
if (bEndsTurn && !GameMode->IsCurrentTurnAI())
{
// TODO Delay this until all effects are done
GameMode->EndTurn();
Expand Down
4 changes: 2 additions & 2 deletions Source/ETV/ETVActionTarget_Fire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ bool UETVActionTarget_Fire::CanPerform()
return true;
}

// Check if enemy
// Check if enemy (not of same side, for AI compatibility)
AETVShip* SelectedShip = Cast<AETVShip>(SelectedTarget); // Required type is ship (checked in parent) so casting is safe
return SelectedShip->IsEnemy();
return SelectedShip->GetType() != OwnerShip->GetType();
}

return false;
Expand Down
4 changes: 4 additions & 0 deletions Source/ETV/ETVCalculator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ void UETVCalculator::CalculateWeaponEffect(AETVShip *User, AETVWeapon *WeaponUse

// Calculate the value of change for this effect
int32 ChangeValue = User->GetMultiplier()*WeaponUsed->GetDMG();
if(ChangeValue < 3)
{
ChangeValue = 3;
}

// Weapon ignores shields
if (WeaponUsed->GetType() == AETVWeapon::DamageHull)
Expand Down
30 changes: 28 additions & 2 deletions Source/ETV/ETVGameModeBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "ETVCalculator.h"
#include "Runtime/Engine/Classes/Engine/UserInterfaceSettings.h"
#include "Runtime/Core/Public/Misc/FileHelper.h"
#include "ETVAI.h"
//#include "DrawDebugHelpers.h" // Uncomment for debug drawing

// Sets default values
Expand All @@ -25,6 +26,9 @@ AETVGameModeBase::AETVGameModeBase()


/* Game Loop */
// Set first turn to player
CurrentTurnSide = EETVShipType::PlayerShip;

// Disable game time (until everything is generated)
ElapsedTime = -1.0f;
CurrentTurn = 0;
Expand Down Expand Up @@ -574,6 +578,7 @@ void AETVGameModeBase::EndTurn()
CurShip->UnconditionallyCloseContextMenu();
}

CurrentTurnSide = EETVShipType::EnemyShip;
CurrentTurnTime = 0.0f;

// Handle turn end
Expand All @@ -594,8 +599,23 @@ void AETVGameModeBase::EndTurn()
}

// Move control to AI
// TODO Call into AI to do its thing
// TODO AI calls NextTurn() when done
UETVAI* AI = NewObject<UETVAI>();
TArray<int32> Instructions = AI->GetMove(Ships);
if (Instructions.Num() == 4)
{
UETVActionTarget* Action = Cast<UETVActionTarget>(Ships[Instructions[1]]->GetActions()[Instructions[2]]);
Action->SetTarget(Ships[Instructions[3]], Ships[Instructions[3]]->GetX(), Ships[Instructions[3]]->GetY());
Action->Perform();
}
else if (Instructions.Num() == 5)
{
UETVActionTarget* Action = Cast<UETVActionTarget>(Ships[Instructions[1]]->GetActions()[Instructions[2]]);
Action->SetTarget(TileMapActor, Instructions[3], Instructions[4]);
Action->Perform();
}

// AI continue to next turn when done
NextTurn();
}
}

Expand All @@ -608,6 +628,7 @@ void AETVGameModeBase::NextTurn()
GetShipListWidget()->Update();

// Apply next turn
CurrentTurnSide = EETVShipType::PlayerShip;
CurrentTurn++;
CurrentTurnTime = static_cast<float>(TurnTime);

Expand Down Expand Up @@ -898,3 +919,8 @@ bool AETVGameModeBase::TileHasShip(int32 x, int32 y)
FPaperTileInfo TileInfo = TileMapComp->GetTile(x, y, EETVTileLayer::Ship);
return TileInfo.TileSet != nullptr;
}

UPaperTileSet* AETVGameModeBase::GetShipSprite(AETVShip* Ship)
{
return TileMapComp->GetTile(Ship->GetX(), Ship->GetY(), EETVTileLayer::Ship).TileSet;
}
13 changes: 12 additions & 1 deletion Source/ETV/ETVGameModeBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class ETV_API AETVGameModeBase : public AGameModeBase


/* Game Loop */
EETVShipType CurrentTurnSide;
TArray<UETVAction*> MultiTurnActions;


Expand Down Expand Up @@ -241,6 +242,10 @@ class ETV_API AETVGameModeBase : public AGameModeBase
UFUNCTION(BlueprintCallable, Category = "ETV Game")
float GetCurrentTurnPercentage();

// Returns if current turn is AI controlled
UFUNCTION(BlueprintCallable, Category = "ETV Game")
bool IsCurrentTurnAI() const { return !bDisableAI && CurrentTurnSide == EETVShipType::EnemyShip; }

// Add multi-turn action for execution in subsequent turns automatically
UFUNCTION(BlueprintCallable, Category = "ETV Game")
void AddMultiTurnAction(UETVAction* Action);
Expand Down Expand Up @@ -320,7 +325,7 @@ class ETV_API AETVGameModeBase : public AGameModeBase
AETVShip* GetLastClickedShip() const { return LastClickedShip; }


/* Get Widgets */
/* Widget and Ship Interaction */
// Get log widget
UFUNCTION(BlueprintCallable, Category = "ETV UI")
UETVActionLogWidget* GetLogWidget() const { return ActionLogClass; }
Expand All @@ -334,6 +339,12 @@ class ETV_API AETVGameModeBase : public AGameModeBase

UFUNCTION()
bool TileHasShip(int32 x, int32 y);

UFUNCTION()
UPaperTileSet* GetShipSprite(AETVShip* Ship);

UFUNCTION()
APaperTileMapActor* GetTileMapActor() const { return TileMapActor; }
};


Expand Down
Loading

0 comments on commit 933254f

Please sign in to comment.