Rudimentary AI.
This commit is contained in:
parent
1801f82248
commit
ca3f00a924
@ -6,4 +6,5 @@ struct GameFlags{
|
||||
bool limitedBuildOptions=false;
|
||||
bool guideEnabled=false;
|
||||
bool flashMemoryBar=false;
|
||||
int difficulty=1; //0=Easy, 1=Normal, 2=Hard
|
||||
};
|
@ -39,7 +39,7 @@ Fake allies the narrator forgot to switch over
|
||||
Day 9 Sounds/Music/Menus - Timer (Speedrun) Difficulty Selection
|
||||
Ending...Shows Four Seasons of Loneliness boss zoom out...
|
||||
|
||||
Easy Difficulty: AI generate no new resources.
|
||||
Easy Difficulty: AI generate no new resources. Start with 100 of each.
|
||||
Normal Difficulty: AI generates resources at normal rate.
|
||||
Hard Difficulty: AI generates resources at x4 rate.
|
||||
|
||||
@ -154,3 +154,8 @@ Space - Gravity (Ambient 1)
|
||||
1 Glorious Venture (Ending theme?)
|
||||
|
||||
Credits
|
||||
|
||||
|
||||
Finish Scenarios (End condition for the game)
|
||||
Finish up main menu stuff (including credits)
|
||||
AI stuff
|
@ -16,10 +16,11 @@ void Scenario::_Start(){
|
||||
camera.SetTarget(targetPos);
|
||||
missionCompletedTimer=0;
|
||||
transitionToNextLevel=false;
|
||||
setupEasyMode=false;
|
||||
Start();
|
||||
}
|
||||
void Scenario::Start(){};
|
||||
void Scenario::_Update(){
|
||||
void Scenario::_Update(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS){
|
||||
initialWaitTime=std::max(0.f,initialWaitTime-game.GetPGE()->GetElapsedTime());
|
||||
missionFinishWaitTime=std::max(0.f,missionFinishWaitTime-game.GetPGE()->GetElapsedTime());
|
||||
smallTimePass=std::min(1.f,smallTimePass+game.GetPGE()->GetElapsedTime());
|
||||
@ -31,10 +32,139 @@ void Scenario::_Update(){
|
||||
} else {
|
||||
missionCompleted=MissionCompleted();
|
||||
}
|
||||
if(flags.playerInControl){
|
||||
RunAI(enemy_resources,collectionPoints,availableMemory,queuedUnits,SOUNDS);
|
||||
}
|
||||
if(initialWaitTime==0){
|
||||
Update();
|
||||
}
|
||||
};
|
||||
void Scenario::RunAI(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS){
|
||||
if(!setupEasyMode&&flags.difficulty==0){
|
||||
enemy_resources={100,100,100,100,100};
|
||||
}
|
||||
unitBuildTimer=std::max(0.f,unitBuildTimer-game.GetPGE()->GetElapsedTime());
|
||||
//See if there are collectors, if so send memory allocator units towards them.
|
||||
for(auto cp:collectionPoints){
|
||||
if(cp->attachedUnit.expired()){
|
||||
if(cpCheckTimer.count(cp.get())==0||cpCheckTimer[cp.get()]<=0){
|
||||
for(auto&u:units){
|
||||
if(!u->IsFriendly()&&u->IsAllocator()&&u->attachTarget.expired()){
|
||||
//Tell this unit to move towards that collection point.
|
||||
u->SetTargetCollectionPoint(cp,u);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Hasn't been checked recently.
|
||||
cpCheckTimer[cp.get()]=60;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(auto&key:cpCheckTimer){
|
||||
cpCheckTimer[key.first]=std::max(0.0f,game.GetPGE()->GetElapsedTime());
|
||||
}
|
||||
int memoryAllocatorCount=0;
|
||||
for(auto&u:units){
|
||||
if(!u->IsFriendly()&&u->IsAllocator()){
|
||||
memoryAllocatorCount++;
|
||||
}
|
||||
}
|
||||
if(memoryAllocatorCount<3){
|
||||
for(auto&u:units){
|
||||
if(u->IsRAMBank()){
|
||||
AttemptBuild(UnitType::MemoryAllocator,u->GetPos(),MemoryAllocator::resourceCost,enemy_resources,availableMemory,queuedUnits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Randomly turn memory allocators into other units.
|
||||
if(unitBuildTimer==0){
|
||||
for(auto&u:units){
|
||||
if(!u->IsFriendly()&&u->IsAllocator()){
|
||||
std::array<UnitType,10>unitChoiceList={UnitType::LeftShifter,UnitType::LeftShifter,UnitType::RightShifter,UnitType::RightShifter,
|
||||
UnitType::Corrupter,UnitType::MemorySwapper,UnitType::BitRestorer,UnitType::BitRestorer,UnitType::_Platform,UnitType::Corrupter};
|
||||
std::array<std::vector<Memory>,10>unitResourceCostList={LeftShifter::resourceCost,LeftShifter::resourceCost,RightShifter::resourceCost,RightShifter::resourceCost,
|
||||
Corrupter::resourceCost,MemorySwapper::resourceCost,BitRestorer::resourceCost,BitRestorer::resourceCost,_Platform::resourceCost,Corrupter::resourceCost};
|
||||
int randomIndex=rand()%unitChoiceList.size();
|
||||
UnitType buildUnit=unitChoiceList[randomIndex];
|
||||
|
||||
int totalCost=0;
|
||||
for(int i=0;i<5;i++){
|
||||
totalCost+=unitResourceCostList[randomIndex][i].size;
|
||||
}
|
||||
if(totalCost<=availableMemory){
|
||||
#define Build(type) \
|
||||
case UnitType::type:{ \
|
||||
u->SetBuildUnit(8,std::make_shared<type>(game.GetPGE(),u->GetPos(),IMAGES,false),SOUNDS); \
|
||||
}break;
|
||||
switch(buildUnit){
|
||||
Build(LeftShifter)
|
||||
Build(RightShifter)
|
||||
Build(BitRestorer)
|
||||
Build(_Platform)
|
||||
Build(Corrupter)
|
||||
Build(MemorySwapper)
|
||||
}
|
||||
if(enemy_resources.health>0){enemy_resources.health=std::max(0,enemy_resources.health-totalCost);}else
|
||||
if(enemy_resources.atkSpd>0){enemy_resources.atkSpd=std::max(0,enemy_resources.atkSpd-totalCost);}else
|
||||
if(enemy_resources.moveSpd>0){enemy_resources.moveSpd=std::max(0,enemy_resources.moveSpd-totalCost);}else
|
||||
if(enemy_resources.range>0){enemy_resources.range=std::max(0,enemy_resources.range-totalCost);}else
|
||||
{enemy_resources.procedure=std::max(0,enemy_resources.procedure-totalCost);
|
||||
}
|
||||
}
|
||||
}
|
||||
switch(flags.difficulty){
|
||||
case 0:{
|
||||
unitBuildTimer=120;
|
||||
}break;
|
||||
case 1:{
|
||||
unitBuildTimer=60;
|
||||
}break;
|
||||
case 2:{
|
||||
unitBuildTimer=10;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
std::shared_ptr<UnitClass>buildUnit=std::make_shared<UnitClass>(this,u->GetPos(),IMAGES,u->IsFriendly()); \
|
||||
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit),SOUNDS); \
|
||||
*/
|
||||
bool Scenario::AttemptBuild(UnitType unit,vf2d pos,std::vector<Memory>&resourceCost,Resources&enemy_resources,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits){
|
||||
int enemyTotalResources=enemy_resources.atkSpd+enemy_resources.health+enemy_resources.moveSpd+enemy_resources.procedure+enemy_resources.range;
|
||||
int totalCost=0;
|
||||
for(int i=0;i<resourceCost.size();i++){
|
||||
totalCost+=resourceCost[i].size;
|
||||
}
|
||||
if(totalCost>availableMemory)return false;
|
||||
if(enemyTotalResources>=totalCost){
|
||||
if(enemy_resources.health>0){enemy_resources.health=std::max(0,enemy_resources.health-totalCost);}else
|
||||
if(enemy_resources.atkSpd>0){enemy_resources.atkSpd=std::max(0,enemy_resources.atkSpd-totalCost);}else
|
||||
if(enemy_resources.moveSpd>0){enemy_resources.moveSpd=std::max(0,enemy_resources.moveSpd-totalCost);}else
|
||||
if(enemy_resources.range>0){enemy_resources.range=std::max(0,enemy_resources.range-totalCost);}else
|
||||
{enemy_resources.procedure=std::max(0,enemy_resources.procedure-totalCost);}
|
||||
#define TranslateUnit(type) \
|
||||
case UnitType::type:{ \
|
||||
queuedUnits.emplace_back(std::make_shared<type>(game.GetPGE(),pos,IMAGES,false)); \
|
||||
}break;
|
||||
switch(unit){
|
||||
TranslateUnit(MemoryAllocator)
|
||||
TranslateUnit(LeftShifter)
|
||||
TranslateUnit(RightShifter)
|
||||
TranslateUnit(BitRestorer)
|
||||
TranslateUnit(MemorySwapper)
|
||||
TranslateUnit(Corrupter)
|
||||
TranslateUnit(RAMBank)
|
||||
TranslateUnit(MemoryGuard)
|
||||
TranslateUnit(Refresher)
|
||||
TranslateUnit(Turret)
|
||||
TranslateUnit(_Platform)
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Scenario::MissionCompleted(){return false;}
|
||||
void Scenario::Update(){};
|
||||
void Scenario::Draw(){
|
||||
|
@ -14,9 +14,13 @@ public:
|
||||
void _Start();
|
||||
void Draw();
|
||||
virtual void Start();
|
||||
void _Update();
|
||||
void _Update(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS);
|
||||
bool transitionToNextLevel=false;
|
||||
LevelName nextLevel=LevelName::STAGE1;
|
||||
void RunAI(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS);
|
||||
bool setupEasyMode=false;
|
||||
std::map<CollectionPoint*,float>cpCheckTimer;
|
||||
bool AttemptBuild(UnitType unit,vf2d pos,std::vector<Memory>&resourceCost,Resources&enemy_resources,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits);
|
||||
protected:
|
||||
void DisplayBox(std::string text,bool scaryHoodedFigure=false);
|
||||
void SetCameraTarget(vf2d pos,bool instant=false);
|
||||
@ -39,6 +43,7 @@ protected:
|
||||
GameFlags&flags;
|
||||
std::string&objective;
|
||||
TileTransformedView&game;
|
||||
float unitBuildTimer=0;
|
||||
};
|
||||
|
||||
class Stage1:public Scenario{
|
||||
|
@ -33,6 +33,7 @@ struct Marker{
|
||||
};
|
||||
|
||||
struct Unit{
|
||||
friend class Scenario;
|
||||
public:
|
||||
Unit(PixelGameEngine*pge,std::vector<Memory>memory,vf2d pos,float radius,Renderable&img,Pixel targetLineColor,Pixel attackingLineColor,bool friendly=false,bool moveable=true,bool friendlyInteractable=false,bool enemyInteractable=true);
|
||||
virtual~Unit();
|
||||
|
@ -180,6 +180,37 @@ void VirusAttack::InitializeLevelData(){
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Stage 4
|
||||
{
|
||||
//Stage 4 data.
|
||||
LevelName stage=STAGE4;
|
||||
levelData[stage].name=stage;
|
||||
levelData[stage].cameraStart={96,96};
|
||||
levelData[stage].worldZoom={1,1};
|
||||
levelData[stage].size={36,36};
|
||||
levelData[stage].levelColor=DARK_GREEN;
|
||||
levelData[stage].bgm=Sound::GRAVITY;
|
||||
levelData[stage].scenarioIndex=int(stage);
|
||||
levelData[stage].availableMemory=300;
|
||||
levelData[stage].player_starting_resources={3,0,0,0,0};
|
||||
levelData[stage].enemy_starting_resources={3,0,0,0,0};
|
||||
{
|
||||
std::vector<UnitData>&units=levelData[stage].unitPlacement;
|
||||
std::vector<CPData>&collectionPoints=levelData[stage].cpPlacement;
|
||||
|
||||
units.push_back({UnitType::RAMBank,vf2d{4*24,4*24},true});
|
||||
for(int i=0;i<5;i++){
|
||||
units.push_back({UnitType::MemoryAllocator,vf2d{4*24,6*24},true});
|
||||
}
|
||||
|
||||
|
||||
for(int i=0;i<5;i++){
|
||||
units.push_back({UnitType::MemoryAllocator,vf2d{4*24,30*24},false});
|
||||
}
|
||||
units.push_back({UnitType::RAMBank,vf2d{4*24,32*24},false});
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
bool VirusAttack::OnUserCreate(){
|
||||
@ -857,7 +888,7 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
|
||||
if(flashTimer>1){
|
||||
flashTimer--;
|
||||
}
|
||||
SCENARIOS[currentScenario]->_Update();
|
||||
SCENARIOS[currentScenario]->_Update(enemy_resources,collectionPoints,currentLevel->availableMemory-GetTotalUsedMemory(),queuedUnits,SOUNDS);
|
||||
if(SCENARIOS[currentScenario]->transitionToNextLevel){
|
||||
if(SCENARIOS[currentScenario]->nextLevel!=FINISH){
|
||||
levelToLoad=SCENARIOS[currentScenario]->nextLevel;
|
||||
|
Loading…
x
Reference in New Issue
Block a user