Skip to content

Commit

Permalink
seperated some unloading code
Browse files Browse the repository at this point in the history
  • Loading branch information
Robosturm committed Oct 22, 2023
1 parent d1c2865 commit e205113
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 118 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,8 @@ set(${PROJECT_NAME}_SRCS
ai/islandmap.cpp ai/islandmap.h
ai/coreai_predefinedai.cpp
ai/proxyai.cpp ai/proxyai.h
ai/normalai.cpp ai/normalai.h
ai/normalai.cpp ai/normalai.h
ai/transporterselector.h ai/transporterselector.cpp
ai/heavyai/heavyai.cpp ai/heavyai/heavyai.h
ai/heavyai/heavyAiSharedData.h
ai/heavyai/situationevaluator.h ai/heavyai/situationevaluator.cpp
Expand Down
1 change: 0 additions & 1 deletion ai/capturebuildingselector.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <QtTypes>
#include "ai/coreai.h"

class CoreAI;
class GameAction;
using spGameAction = std::shared_ptr<GameAction>;
class QmlVectorUnit;
Expand Down
109 changes: 3 additions & 106 deletions ai/normalai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
NormalAi::NormalAi(GameMap *pMap, const QString &configurationFile, GameEnums::AiTypes aiType, const QString &jsName)
: CoreAI(pMap, aiType, jsName),
m_InfluenceFrontMap(pMap, m_IslandMaps),
m_captureBuildingSelector(*this)
m_captureBuildingSelector(*this),
m_transporterSelector(*this)
{
#ifdef GRAPHICSUPPORT
setObjectName("NormalAi");
Expand Down Expand Up @@ -975,111 +976,7 @@ bool NormalAi::moveToUnloadArea(spGameAction &pAction, MoveUnitData *pUnitData,

bool NormalAi::unloadUnits(spGameAction &pAction, Unit *pUnit, spQmlVectorUnit &pEnemyUnits)
{

Interpreter *pInterpreter = Interpreter::getInstance();
bool unloaded = false;
std::vector<qint32> unloadedUnits;
do
{
unloaded = false;
spMenuData pDataMenu = pAction->getMenuStepData();
if (pDataMenu->validData())
{
QStringList actions = pDataMenu->getActionIDs();
QVector<qint32> unitIDx = pDataMenu->getCostList();
std::vector<QList<QVariant>> unloadFields;
for (qint32 i = 0; i < unitIDx.size() - 1; i++)
{
QString function1 = "getUnloadFields";
QJSValueList args({
JsThis::getJsThis(pAction.get()),
unitIDx[i],
JsThis::getJsThis(m_pMap),
});
QJSValue ret = pInterpreter->doFunction(ACTION_UNLOAD, function1, args);
unloadFields.push_back(ret.toVariant().toList());
}
if (actions.size() > 1)
{
for (qint32 i = 0; i < unloadFields.size(); i++)
{
Unit *pLoadedUnit = pUnit->getLoadedUnit(i);
if (!needsRefuel(pLoadedUnit))
{
if (!GlobalUtils::contains(unloadedUnits, unitIDx[i]))
{
if (unloadFields[i].size() == 1)
{
addMenuItemData(pAction, actions[i], unitIDx[i]);
spMarkedFieldData pFields = pAction->getMarkedFieldStepData();
addSelectedFieldData(pAction, pFields->getPoints()->at(0));
unloaded = true;
unloadedUnits.push_back(unitIDx[i]);
break;
}
else if (unloadFields[i].size() > 0 &&
pUnit->getLoadedUnit(i)->getActionList().contains(ACTION_CAPTURE))
{
auto &fields = unloadFields[i];
for (auto &field : fields)
{
QPoint unloadField = field.toPoint();
Building *pBuilding = m_pMap->getTerrain(unloadField.x(),
unloadField.y())
->getBuilding();
if (pBuilding != nullptr && m_pPlayer->isEnemy(pBuilding->getOwner()))
{
addMenuItemData(pAction, actions[i], unitIDx[i]);
addSelectedFieldData(pAction, unloadField);
unloaded = true;
unloadedUnits.push_back(unitIDx[i]);
break;
}
}
break;
}
}
}
}
if (unloaded == false &&
!needsRefuel(pUnit->getLoadedUnit(0)))
{
qint32 costs = pDataMenu->getCostList()[0];
addMenuItemData(pAction, actions[0], costs);
unloaded = true;
spMarkedFieldData pFields = pAction->getMarkedFieldStepData();
qint32 field = 0;
qint32 bestDistance = std::numeric_limits<qint32>::max();
for (qint32 i = 0; i < pFields->getPoints()->size(); ++i)
{
QPoint unloadPos = pFields->getPoints()->at(i);
qint32 currentBestDistance = std::numeric_limits<qint32>::max();
for (auto &pEnemy : pEnemyUnits->getVector())
{
qint32 distance = GlobalUtils::getDistance(unloadPos, pEnemy->Unit::getPosition());
if (distance < currentBestDistance)
{
currentBestDistance = distance;
}
}
if (currentBestDistance < bestDistance ||
(currentBestDistance == bestDistance && GlobalUtils::randInt(0, 1) == 1))
{
bestDistance = currentBestDistance;
field = i;
}
}
addSelectedFieldData(pAction, pFields->getPoints()->at(field));
}
}
}
else
{
AI_CONSOLE_PRINT("Error invalid menu data received while unloading units", GameConsole::eERROR);
return false;
}
} while (unloaded);
addMenuItemData(pAction, ACTION_WAIT, 0);
m_transporterSelector.prepareUnloadInformation(pAction, pUnit, pEnemyUnits);
m_updatePoints.push_back(pUnit->getPosition());
m_updatePoints.push_back(pAction->getActionTarget());
if (pAction->canBePerformed())
Expand Down
2 changes: 2 additions & 0 deletions ai/normalai.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "ai/coreai.h"
#include "ai/capturebuildingselector.h"
#include "ai/transporterselector.h"

#include "ai/influencefrontmap.h"

Expand Down Expand Up @@ -515,6 +516,7 @@ public slots:
std::vector<ProductionData> m_productionData;
InfluenceFrontMap m_InfluenceFrontMap;
CaptureBuildingSelector m_captureBuildingSelector;
TransporterSelector m_transporterSelector;

double m_notAttackableDamage{25.0f};
double m_midDamage{55.0f};
Expand Down
142 changes: 142 additions & 0 deletions ai/transporterselector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#include "ai/transporterselector.h"

#include "coreengine/interpreter.h"
#include "coreengine/gameconsole.h"

#include "game/gamemap.h"

TransporterSelector::TransporterSelector(CoreAI & owner)
: m_owner(owner)
{
}

void TransporterSelector::prepareUnloadInformation(spGameAction &pAction, Unit *pUnit, spQmlVectorUnit &pEnemyUnits)
{
bool unloaded = false;
std::vector<qint32> unloadedUnits;
do
{
unloaded = false;
spMenuData pDataMenu = pAction->getMenuStepData();
QVector<qint32> unitIDx = pDataMenu->getCostList();
if (pDataMenu->validData())
{
QStringList actions = pDataMenu->getActionIDs();
std::vector<QList<QVariant>> unloadFields = getUnloadFields(pAction, unitIDx, pDataMenu);
if (actions.size() > 1)
{
unloaded = fillUnloadFields(pAction, pUnit, unloadedUnits, unloadFields, unitIDx, actions);
if (unloaded == false)
{
unloaded = fallbackUnload(pAction, pUnit, pEnemyUnits, pDataMenu, actions);
}
}
}
else
{
AI_CONSOLE_PRINT("Error invalid menu data received while unloading units", GameConsole::eERROR);
break;
}
} while (unloaded);
m_owner.addMenuItemData(pAction, CoreAI::ACTION_WAIT, 0);
}

std::vector<QList<QVariant>> TransporterSelector::getUnloadFields(spGameAction &pAction, QVector<qint32> & unitIDx, spMenuData & pDataMenu)
{
Interpreter *pInterpreter = Interpreter::getInstance();
std::vector<QList<QVariant>> unloadFields;
for (qint32 i = 0; i < unitIDx.size() - 1; i++)
{
QString function1 = "getUnloadFields";
QJSValueList args({
JsThis::getJsThis(pAction.get()),
unitIDx[i],
JsThis::getJsThis(m_owner.getMap()),
});
QJSValue ret = pInterpreter->doFunction(CoreAI::ACTION_UNLOAD, function1, args);
unloadFields.push_back(ret.toVariant().toList());
}
return unloadFields;
}

bool TransporterSelector::fillUnloadFields(spGameAction &pAction, Unit *pUnit, std::vector<qint32> & unloadedUnits,
std::vector<QList<QVariant>> & unloadFields, QVector<qint32> & unitIDx,
QStringList & actions)
{
bool unloaded = false;
for (qint32 i = 0; i < unloadFields.size(); i++)
{
Unit *pLoadedUnit = pUnit->getLoadedUnit(i);
if (!m_owner.needsRefuel(pLoadedUnit))
{
if (!GlobalUtils::contains(unloadedUnits, unitIDx[i]))
{
if (unloadFields[i].size() == 1)
{
m_owner.addMenuItemData(pAction, actions[i], unitIDx[i]);
spMarkedFieldData pFields = pAction->getMarkedFieldStepData();
m_owner.addSelectedFieldData(pAction, pFields->getPoints()->at(0));
unloaded = true;
unloadedUnits.push_back(unitIDx[i]);
break;
}
else if (unloadFields[i].size() > 0 &&
pUnit->getLoadedUnit(i)->getActionList().contains(CoreAI::ACTION_CAPTURE))
{
auto &fields = unloadFields[i];
for (auto &field : fields)
{
QPoint unloadField = field.toPoint();
Terrain* pTerrain = m_owner.getMap()->getTerrain(unloadField.x(), unloadField.y());
Building *pBuilding = pTerrain->getBuilding();
if (pBuilding != nullptr && m_owner.getPlayer()->isEnemy(pBuilding->getOwner()))
{
m_owner.addMenuItemData(pAction, actions[i], unitIDx[i]);
m_owner.addSelectedFieldData(pAction, unloadField);
unloaded = true;
unloadedUnits.push_back(unitIDx[i]);
break;
}
}
break;
}
}
}
}
return unloaded;
}

bool TransporterSelector::fallbackUnload(spGameAction &pAction, Unit *pUnit, spQmlVectorUnit &pEnemyUnits, spMenuData & pDataMenu, QStringList & actions)
{
bool unloaded = false;
if (!m_owner.needsRefuel(pUnit->getLoadedUnit(0)))
{
qint32 costs = pDataMenu->getCostList()[0];
m_owner.addMenuItemData(pAction, actions[0], costs);
unloaded = true;
spMarkedFieldData pFields = pAction->getMarkedFieldStepData();
qint32 field = 0;
qint32 bestDistance = std::numeric_limits<qint32>::max();
for (qint32 i = 0; i < pFields->getPoints()->size(); ++i)
{
QPoint unloadPos = pFields->getPoints()->at(i);
qint32 currentBestDistance = std::numeric_limits<qint32>::max();
for (auto &pEnemy : pEnemyUnits->getVector())
{
qint32 distance = GlobalUtils::getDistance(unloadPos, pEnemy->Unit::getPosition());
if (distance < currentBestDistance)
{
currentBestDistance = distance;
}
}
if (currentBestDistance < bestDistance ||
(currentBestDistance == bestDistance && GlobalUtils::randInt(0, 1) == 1))
{
bestDistance = currentBestDistance;
field = i;
}
}
m_owner.addSelectedFieldData(pAction, pFields->getPoints()->at(field));
}
return unloaded;
}
25 changes: 25 additions & 0 deletions ai/transporterselector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <QtTypes>
#include "ai/coreai.h"

class GameAction;
using spGameAction = std::shared_ptr<GameAction>;
class QmlVectorUnit;
using spQmlVectorUnit = std::shared_ptr<QmlVectorUnit>;

class TransporterSelector
{
public:
TransporterSelector(CoreAI & owner);

void prepareUnloadInformation(spGameAction &pAction, Unit *pUnit, spQmlVectorUnit &pEnemyUnits);
private:
bool fillUnloadFields(spGameAction &pAction, Unit *pUnit, std::vector<qint32> & unloadedUnits,
std::vector<QList<QVariant>> & unloadFields, QVector<qint32> & unitIDx, QStringList & actions);
bool fallbackUnload(spGameAction &pAction, Unit *pUnit, spQmlVectorUnit &pEnemyUnits, spMenuData & pDataMenu, QStringList & actions);
std::vector<QList<QVariant>> getUnloadFields(spGameAction &pAction, QVector<qint32> & unitIDx, spMenuData & pDataMenu);
private:
CoreAI & m_owner;
};

6 changes: 3 additions & 3 deletions resources/scripts/cos/co_andy.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ var Constructor = function()
this.superPowerOffBonus = 30;
this.superPowerMovementBonus = 1;

this.powerDefBonus = 10;
this.powerOffBonus = 10;
this.powerDefBonus = 20;
this.powerOffBonus = 20;
this.powerHeal = 2;

this.d2dCoZoneOffBonus = 20;
Expand Down Expand Up @@ -310,4 +310,4 @@ var Constructor = function()
}

Constructor.prototype = CO;
var CO_ANDY = new Constructor();
var CO_ANDY = new Constructor();
14 changes: 7 additions & 7 deletions resources/scripts/cos/co_brenner.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,14 +239,14 @@ var Constructor = function()
this.getLongCODescription = function()
{
var text = qsTr("\nSpecial Unit:\nRepair Tanks\n\nGlobal Effect: \nBrenner's units gain +%0% defence.") +
qsTr("\n\nCO Zone Effect: \nBrenner's units gain +%2% firepower and +%1% defence.");
text = replaceTextArgs(text, [CO_BRENNER.d2dDefBonus, CO_BRENNER.d2dCoZoneDefBonus, CO_BRENNER.d2dCoZoneOffBonus]);
qsTr("\n\nCO Zone Effect: \nBrenner's units gain +%1% firepower and +%2% defence.");
text = replaceTextArgs(text, [CO_BRENNER.d2dDefBonus, CO_BRENNER.d2dCoZoneOffBonus, CO_BRENNER.d2dCoZoneDefBonus]);
return text;
};
this.getPowerDescription = function(co)
{
var text = qsTr("Restores +%0 HP to all of Brenner's units. His units gain +%2% firepower and +%1% defence.");
text = replaceTextArgs(text, [CO_BRENNER.powerHeal, CO_BRENNER.powerDefBonus, CO_BRENNER.powerOffBonus]);
var text = qsTr("Restores +%0 HP to all of Brenner's units. His units gain +%1% firepower and +%2% defence.");
text = replaceTextArgs(text, [CO_BRENNER.powerHeal, CO_BRENNER.powerOffBonus, CO_BRENNER.powerDefBonus]);
return text;
};
this.getPowerName = function(co)
Expand All @@ -255,8 +255,8 @@ var Constructor = function()
};
this.getSuperPowerDescription = function(co)
{
var text = qsTr("Restores +%0 HP to all of Brenner's units. His units gain +%2% firepower and +%1% defence.");
text = replaceTextArgs(text, [CO_BRENNER.superPowerHeal, CO_BRENNER.superPowerDefBonus, CO_BRENNER.powerOffBonus]);
var text = qsTr("Restores +%0 HP to all of Brenner's units. His units gain +%1% firepower and +%2% defence.");
text = replaceTextArgs(text, [CO_BRENNER.superPowerHeal, CO_BRENNER.powerOffBonus, CO_BRENNER.superPowerDefBonus]);
return text;
};
this.getSuperPowerName = function(co)
Expand Down Expand Up @@ -287,4 +287,4 @@ var Constructor = function()
}

Constructor.prototype = CO;
var CO_BRENNER = new Constructor();
var CO_BRENNER = new Constructor();

0 comments on commit e205113

Please sign in to comment.