aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorEugene Sandulenko2016-05-19 22:30:56 +0200
committerEugene Sandulenko2016-05-22 00:45:03 +0200
commit9d60209a33d2eab4075662e9ed4f1e9215c719a2 (patch)
tree21f3398b5d64a292df3332113f2e51a0b4dbe49b /engines
parent4ed193b51e62891fca2c79b2195aacb83c9b65fb (diff)
downloadscummvm-rg350-9d60209a33d2eab4075662e9ed4f1e9215c719a2.tar.gz
scummvm-rg350-9d60209a33d2eab4075662e9ed4f1e9215c719a2.tar.bz2
scummvm-rg350-9d60209a33d2eab4075662e9ed4f1e9215c719a2.zip
SCUMM HE: Initial stub for Moonbase AI
Diffstat (limited to 'engines')
-rw-r--r--engines/scumm/he/moonbase/ai_defenseunit.cpp759
-rw-r--r--engines/scumm/he/moonbase/ai_defenseunit.h190
-rw-r--r--engines/scumm/he/moonbase/ai_main.h188
-rw-r--r--engines/scumm/he/moonbase/ai_node.h106
-rw-r--r--engines/scumm/he/moonbase/ai_tree.h78
-rw-r--r--engines/scumm/he/moonbase/moonbase.h4
-rw-r--r--engines/scumm/module.mk1
7 files changed, 1324 insertions, 2 deletions
diff --git a/engines/scumm/he/moonbase/ai_defenseunit.cpp b/engines/scumm/he/moonbase/ai_defenseunit.cpp
new file mode 100644
index 0000000000..1312752fef
--- /dev/null
+++ b/engines/scumm/he/moonbase/ai_defenseunit.cpp
@@ -0,0 +1,759 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/rect.h"
+#include "common/util.h"
+#include "scumm/scumm.h"
+#include "scumm/he/moonbase/ai_defenseunit.h"
+#include "scumm/he/moonbase/ai_main.h"
+
+namespace Scumm {
+
+DefenseUnit::DefenseUnit() {
+ m_state = DUS_ON;
+}
+
+DefenseUnit::DefenseUnit(DefenseUnit *inUnit) {
+ m_ID = inUnit->getID();
+ m_pos.x = inUnit->getPosX();
+ m_pos.y = inUnit->getPosY();
+ m_distanceTo = inUnit->getDistanceTo();
+ m_state = inUnit->getState();
+ m_radius = inUnit->getRadius();
+ m_armor = inUnit->getArmor();
+}
+
+DefenseUnit::~DefenseUnit() {
+}
+
+Common::Point *AntiAirUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ float ratio;
+ int radius;
+ Common::Point *targetPos = new Common::Point;
+
+ if (!distance) distance = 1;
+
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CLUSTER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CRAWLER:
+ radius = getRadius();
+
+ if ((distance < radius) || (getState() == DUS_OFF)) {
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ } else {
+ ratio = MAX(0, (getRadius() / distance));
+ targetPos->x = getPosX() - ratio * (getPosX() - sourceX);
+ targetPos->y = getPosY() - ratio * (getPosY() - sourceY);
+ }
+
+ break;
+
+ case ITEM_EMP:
+ if (getRadius() + 215 > distance) { //emp radius
+ double x1 = static_cast<double>(sourceX);
+ double y1 = static_cast<double>(sourceY);
+ double x2 = static_cast<double>(getPosX());
+ double y2 = static_cast<double>(getPosY());
+ double r1 = static_cast<double>(215);
+ double r2 = static_cast<double>(getRadius() + 3);
+ double d = static_cast<double>(distance);
+
+ //formulae for calculating one point of intersection of two circles
+ float root = sqrt((((r1 + r2) * (r1 + r2)) - (d * d)) * ((d * d) - ((r2 - r1) * (r2 - r1))));
+ int x = ((x1 + x2) / 2) + ((x2 - x1) * (r1 * r1 - r2 * r2)) / (2 * d * d) + ((y2 - y1) / (2 * d * d)) * root;
+ int y = ((y1 + y2) / 2) + ((y2 - y1) * (r1 * r1 - r2 * r2)) / (2 * d * d) - ((x2 - x1) / (2 * d * d)) * root;
+
+ targetPos->x = x;
+ targetPos->y = y;
+ } else {
+ ratio = 1 - (getRadius() / static_cast<float>(distance - 20));
+ targetPos->x = sourceX + ratio * (getPosX() - sourceX);
+ targetPos->y = sourceY + ratio * (getPosY() - sourceY);
+ }
+
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+
+ return targetPos;
+}
+
+int AntiAirUnit::selectWeapon(int index) {
+ switch (index) {
+ case 0:
+ return ITEM_CLUSTER;
+ break;
+
+ case 1:
+ return ITEM_EMP;
+ break;
+
+ case 2:
+ if (getState() == DUS_OFF) {
+ if (GetPlayerEnergy() > 6) {
+ if (!_vm->_rnd.getRandomNumber(3)) {
+ return ITEM_VIRUS;
+ }
+ }
+
+ if (GetPlayerEnergy() > 2) {
+ if (!_vm->_rnd.getRandomNumber(1)) {
+ return ITEM_SPIKE;
+ }
+ }
+
+ return ITEM_BOMB;
+ }
+
+ return ITEM_CLUSTER;
+ break;
+
+ default:
+ return ITEM_CLUSTER;
+ break;
+ }
+}
+
+Common::Point *ShieldUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ float ratio;
+ Common::Point *targetPos = new Common::Point;
+
+ if (getState() == DUS_OFF) {
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ } else {
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CLUSTER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CRAWLER:
+ ratio = MAX(0.0, 1.0 - (static_cast<float>(getRadius()) / static_cast<float>(distance - 20)));
+ {
+ int maxX = GetMaxX();
+ int maxY = GetMaxY();
+ int thisX = (static_cast<int>(sourceX + ratio * (getPosX() - sourceX)) + maxX) % maxX;
+ int thisY = (static_cast<int>(sourceY + ratio * (getPosY() - sourceY)) + maxY) % maxY;
+ targetPos->x = thisX;
+ targetPos->y = thisY;
+ }
+ break;
+
+ case ITEM_EMP:
+ if (getRadius() + 215 > distance) { //emp radius
+ double x1 = static_cast<double>(sourceX);
+ double y1 = static_cast<double>(sourceY);
+ double x2 = static_cast<double>(getPosX());
+ double y2 = static_cast<double>(getPosY());
+ double r1 = static_cast<double>(215);
+ double r2 = static_cast<double>(getRadius() + 10);
+ double d = static_cast<double>(distance);
+
+ //formulae for calculating one point of intersection of two circles
+ float root = sqrt((((r1 + r2) * (r1 + r2)) - (d * d)) * ((d * d) - ((r2 - r1) * (r2 - r1))));
+ int x = ((x1 + x2) / 2) + ((x2 - x1) * (r1 * r1 - r2 * r2)) / (2 * d * d) + ((y2 - y1) / (2 * d * d)) * root;
+ int y = ((y1 + y2) / 2) + ((y2 - y1) * (r1 * r1 - r2 * r2)) / (2 * d * d) - ((x2 - x1) / (2 * d * d)) * root;
+
+ targetPos->x = x;
+ targetPos->y = y;
+ } else {
+ ratio = 1 - (getRadius() / static_cast<float>(distance - 20));
+ targetPos->x = sourceX + ratio * (getPosX() - sourceX);
+ targetPos->y = sourceY + ratio * (getPosY() - sourceY);
+ }
+
+ if (distance < getRadius()) {
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ }
+
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+ }
+
+ return targetPos;
+}
+
+int ShieldUnit::selectWeapon(int index) {
+ warning("Shield weapon select");
+
+ int myUnit = GetClosestUnit(getPosX(), getPosY(), GetMaxX(), GetCurrentPlayer(), 1, BUILDING_MAIN_BASE, 1, 0);
+ int dist = GetDistance(getPosX(), getPosY(), GetHubX(myUnit), GetHubY(myUnit));
+
+ if ((dist < (getRadius() - 20)) && (dist > 90)) {
+ return ITEM_SPIKE;
+ }
+
+ switch (index) {
+ case 0:
+ if (getState() == DUS_OFF) {
+ if (GetPlayerEnergy() < 3) {
+ return ITEM_BOMB;
+ } else {
+ return ITEM_SPIKE;
+ }
+ }
+
+ return ITEM_EMP;
+ break;
+
+ case 1:
+ if (dist < getRadius() + 150) {
+ return ITEM_EMP;
+ } else {
+ return ITEM_CRAWLER;
+ }
+
+ break;
+
+ default:
+ return ITEM_EMP;
+ break;
+ }
+}
+
+Common::Point *MineUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ float ratio;
+ Common::Point *targetPos = new Common::Point;
+
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CLUSTER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_EMP:
+ ratio = 1 - (getRadius() / static_cast<float>(distance - 20));
+ targetPos->x = sourceX + ratio * (getPosX() - sourceX);
+ targetPos->y = sourceY + ratio * (getPosY() - sourceY);
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+
+ return targetPos;
+}
+
+int MineUnit::selectWeapon(int index) {
+ int myUnit = GetClosestUnit(getPosX(), getPosY(), GetMaxX(), GetCurrentPlayer(), 1, 0, 0, 0);
+ int x = getPosX();
+ int y = getPosY();
+
+ int dist = GetDistance(x, y, GetHubX(myUnit), GetHubY(myUnit));
+
+ if ((getState() == DUS_ON) && (dist < 110)) {
+ return ITEM_EMP;
+ } else {
+ return ITEM_BOMB;
+ }
+}
+
+
+Common::Point *HubUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ Common::Point *targetPos = new Common::Point;
+
+ if (!distance) distance = 1;
+
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CLUSTER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CRAWLER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+
+ return targetPos;
+}
+
+int HubUnit::selectWeapon(int index) {
+ warning("Hub weapon select");
+
+ int energy = GetPlayerEnergy();
+
+ if (energy > 6) {
+ //possibly choose crawler
+ if (GetBuildingWorth(getID()) > 21) {
+ return ITEM_CRAWLER;
+ }
+ }
+
+ //choose betw/ bomb and cluster
+ if (GetBuildingArmor(getID()) < 1.5) {
+ return ITEM_CLUSTER;
+ }
+
+ if (energy > 2) {
+ if (!_vm->_rnd.getRandomNumber(3)) {
+ return ITEM_SPIKE;
+ }
+
+ if (!_vm->_rnd.getRandomNumber(4)) {
+ return ITEM_GUIDED;
+ }
+
+ if (!_vm->_rnd.getRandomNumber(4)) {
+ return ITEM_MINE;
+ }
+
+ if (!_vm->_rnd.getRandomNumber(9)) {
+ return ITEM_EMP;
+ }
+ }
+
+ return ITEM_BOMB;
+}
+
+
+Common::Point *TowerUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ Common::Point *targetPos = new Common::Point;
+
+ if (!distance) distance = 1;
+
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_SPIKE:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+
+ return targetPos;
+}
+
+int TowerUnit::selectWeapon(int index) {
+ switch (index) {
+ case 0:
+ return ITEM_SPIKE;
+ break;
+
+ default:
+ return ITEM_SPIKE;
+ break;
+ }
+}
+
+
+Common::Point *BridgeUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ Common::Point *targetPos = new Common::Point;
+
+ if (!distance) distance = 1;
+
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CLUSTER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+
+ return targetPos;
+}
+
+int BridgeUnit::selectWeapon(int index) {
+ switch (index) {
+ case 0:
+ return ITEM_BOMB;
+ break;
+
+ case 1:
+ return ITEM_CLUSTER;
+ break;
+
+ default:
+ return ITEM_BOMB;
+ break;
+ }
+}
+
+
+Common::Point *EnergyUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ Common::Point *targetPos = new Common::Point;
+
+ if (!distance) distance = 1;
+
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CLUSTER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CRAWLER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+
+ return targetPos;
+}
+
+int EnergyUnit::selectWeapon(int index) {
+ warning("Energy weapon select");
+
+ int energy = GetPlayerEnergy();
+
+ if (energy > 6) {
+ //possibly choose crawler
+ if (GetBuildingWorth(getID()) > 21) {
+ return ITEM_CRAWLER;
+ }
+ }
+
+ //choose betw/ bomb and cluster
+ if (GetBuildingArmor(getID()) < 1.5) {
+ return ITEM_CLUSTER;
+ }
+
+ if (energy > 2) {
+ if (!_vm->_rnd.getRandomNumber(3)) {
+ return ITEM_EMP;
+ }
+ }
+
+ return ITEM_BOMB;
+}
+
+Common::Point *OffenseUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ Common::Point *targetPos = new Common::Point;
+
+ if (!distance) distance = 1;
+
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CLUSTER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CRAWLER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+
+ return targetPos;
+}
+
+int OffenseUnit::selectWeapon(int index) {
+ warning("Offense weapon select");
+
+ int energy = GetPlayerEnergy();
+
+ if (energy > 6) {
+ //possibly choose crawler
+ if (GetBuildingWorth(getID()) > 21) {
+ return ITEM_CRAWLER;
+ }
+ }
+
+ //choose betw/ bomb and cluster
+ if (GetBuildingArmor(getID()) < 1.5) {
+ return ITEM_CLUSTER;
+ }
+
+ return ITEM_BOMB;
+}
+
+Common::Point *CrawlerUnit::createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) {
+ Common::Point *targetPos = new Common::Point;
+
+ if (!distance)
+ distance = 1;
+
+ switch (weaponType) {
+ case ITEM_BOMB:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CLUSTER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ case ITEM_CRAWLER:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+
+ default:
+ targetPos->x = getPosX();
+ targetPos->y = getPosY();
+ break;
+ }
+
+ return targetPos;
+}
+
+int CrawlerUnit::selectWeapon(int index) {
+ warning("Crawler weapon select");
+ int myUnit = GetClosestUnit(getPosX(), getPosY(), GetMaxX(), GetCurrentPlayer(), 1, 0, 0, 0);
+ int dist = GetDistance(GetHubX(myUnit), GetHubY(myUnit), getPosX(), getPosY());
+
+ int x = getPosX();
+ int y = getPosY();
+ int energy = GetPlayerEnergy();
+ int terrain = GetTerrain(x, y);
+
+ if (terrain != TERRAIN_TYPE_WATER) {
+ if ((energy > 2) && (dist < 220)) {
+ return ITEM_RECLAIMER;
+ } else {
+ return ITEM_BOMB;
+ }
+ } else {
+ if (energy > 6) {
+ return ITEM_CRAWLER;
+ }
+
+ if (energy > 2) {
+ if (_vm->_rnd.getRandomNumber(1)) {
+ return ITEM_MINE;
+ } else {
+ return ITEM_TIME_EXPIRED;
+ }
+ }
+ }
+
+ return SKIP_TURN;
+}
+
+AntiAirUnit::AntiAirUnit() {
+ setRadius(190);
+ setArmor(3);
+ setCost(1);
+}
+
+ShieldUnit::ShieldUnit() {
+ setRadius(170);
+ setArmor(3);
+ setCost(7);
+}
+
+MineUnit::MineUnit() {
+ setRadius(80);
+ setArmor(1);
+ setCost(3);
+}
+
+HubUnit::HubUnit() {
+ setRadius(1);
+ setArmor(5);
+ setCost(7);
+}
+
+TowerUnit::TowerUnit() {
+ setRadius(1);
+ setArmor(3);
+ setCost(1);
+}
+
+BridgeUnit::BridgeUnit() {
+ setRadius(1);
+ setArmor(3);
+ setCost(1);
+}
+
+EnergyUnit::EnergyUnit() {
+ setRadius(1);
+ setArmor(5);
+ setCost(7);
+}
+
+OffenseUnit::OffenseUnit() {
+ setRadius(1);
+ setArmor(3);
+ setCost(7);
+}
+
+CrawlerUnit::CrawlerUnit() {
+ setRadius(1);
+ setArmor(3);
+ setCost(7);
+}
+
+AntiAirUnit::AntiAirUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+
+}
+
+ShieldUnit::ShieldUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+}
+
+MineUnit::MineUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+}
+
+HubUnit::HubUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+}
+
+TowerUnit::TowerUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+}
+
+BridgeUnit::BridgeUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+}
+
+EnergyUnit::EnergyUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+}
+
+OffenseUnit::OffenseUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+}
+
+CrawlerUnit::CrawlerUnit(DefenseUnit *inUnit) : DefenseUnit(inUnit) {
+ setID(inUnit->getID());
+ setPos(inUnit->getPosX(), inUnit->getPosY());
+ setDistanceTo(inUnit->getDistanceTo());
+ setState(inUnit->getState());
+ setRadius(inUnit->getRadius());
+ setArmor(inUnit->getArmor());
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/moonbase/ai_defenseunit.h b/engines/scumm/he/moonbase/ai_defenseunit.h
new file mode 100644
index 0000000000..bc4c79a6b5
--- /dev/null
+++ b/engines/scumm/he/moonbase/ai_defenseunit.h
@@ -0,0 +1,190 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCUMM_HE_MOONBASE_AI_DEFENCEUNIT_H
+#define SCUMM_HE_MOONBASE_AI_DEFENCEUNIT_H
+
+namespace Scumm {
+
+enum {
+ DUT_ANTI_AIR = 1,
+ DUT_SHIELD = 2,
+ DUT_MINE = 3,
+ DUT_HUB = 4,
+ DUT_TOWER = 5,
+ DUT_BRIDGE = 6,
+ DUT_ENERGY = 7,
+ DUT_OFFENSE = 8,
+ DUT_CRAWLER = 9
+};
+
+enum {
+ DUS_ON = 1,
+ DUS_OFF = 2,
+ DUS_DESTROYED = 3
+};
+
+class DefenseUnit {
+private:
+ int m_ID;
+ Common::Point m_pos;
+ int m_distanceTo;
+ int m_state;
+ int m_radius;
+ int m_armor;
+ int m_cost;
+
+public:
+ DefenseUnit();
+ DefenseUnit(DefenseUnit *inUnit);
+
+ virtual ~DefenseUnit();
+
+ void setID(int id) { m_ID = id; }
+ void setDistanceTo(int distanceTo) { m_distanceTo = distanceTo; }
+ void setState(int state) { m_state = state; }
+ void setRadius(int radius) { m_radius = radius; }
+ void setArmor(int armor) { m_armor = armor; }
+ void setDamage(int damage) { m_armor -= damage; }
+ void setPos(int x, int y) {
+ m_pos.x = x;
+ m_pos.y = y;
+ }
+ void setCost(int cost) { m_cost = cost; }
+
+ int getID() const { return m_ID; }
+ int getDistanceTo() const { return m_distanceTo; }
+ int getState() const { return m_state; }
+ int getRadius() const { return m_radius; }
+ int getArmor() const { return m_armor; }
+ int getPosX() const { return m_pos.x; }
+ int getPosY() const { return m_pos.y; }
+ int getCost() const { return m_cost; }
+
+ virtual int getType() const = 0;
+
+ virtual Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) = 0;
+ virtual int selectWeapon(int index) = 0;
+};
+
+class AntiAirUnit : public DefenseUnit {
+private:
+
+public:
+ AntiAirUnit();
+ AntiAirUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_ANTI_AIR; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+class ShieldUnit : public DefenseUnit {
+private:
+
+public:
+ ShieldUnit();
+ ShieldUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_SHIELD; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+class MineUnit : public DefenseUnit {
+private:
+
+public:
+ MineUnit();
+ MineUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_MINE; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+class HubUnit : public DefenseUnit {
+private:
+
+public:
+ HubUnit();
+ HubUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_HUB; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+class TowerUnit : public DefenseUnit {
+private:
+
+public:
+ TowerUnit();
+ TowerUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_TOWER; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+class BridgeUnit : public DefenseUnit {
+private:
+
+public:
+ BridgeUnit();
+ BridgeUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_BRIDGE; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+class EnergyUnit : public DefenseUnit {
+private:
+
+public:
+ EnergyUnit();
+ EnergyUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_ENERGY; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+class OffenseUnit : public DefenseUnit {
+private:
+
+public:
+ OffenseUnit();
+ OffenseUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_OFFENSE; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+class CrawlerUnit : public DefenseUnit {
+private:
+
+public:
+ CrawlerUnit();
+ CrawlerUnit(DefenseUnit *inUnit);
+ int getType() const { return DUT_CRAWLER; }
+ Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY);
+ int selectWeapon(int index);
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/he/moonbase/ai_main.h b/engines/scumm/he/moonbase/ai_main.h
new file mode 100644
index 0000000000..ca85ff1811
--- /dev/null
+++ b/engines/scumm/he/moonbase/ai_main.h
@@ -0,0 +1,188 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCUMM_HE_MOONBASE_AI_MAIN_H
+#define SCUMM_HE_MOONBASE_AI_MAIN_H
+
+#include "scumm/he/moonbase/ai_tree.h"
+
+namespace Scumm {
+
+extern ScummEngine *_vm;
+
+typedef Common::List<int>::iterator intVecItr;
+
+enum {
+ TERRAIN_TYPE_GOOD = 0,
+ TERRAIN_TYPE_SLOPE = 1,
+ TERRAIN_TYPE_WATER = 2,
+ MAX_MEMORY = 3
+};
+
+enum {
+ ITEM_BOMB = 0,
+ ITEM_CLUSTER = 1,
+ ITEM_REPAIR = 2,
+ ITEM_ANTIAIR = 3,
+ ITEM_BRIDGE = 4,
+ ITEM_TOWER = 5,
+ ITEM_GUIDED = 6,
+ ITEM_EMP = 7,
+ ITEM_SPIKE = 8,
+ ITEM_RECLAIMER = 9,
+ ITEM_BALLOON = 10,
+ ITEM_MINE = 11,
+ ITEM_CRAWLER = 12,
+ ITEM_VIRUS = 13,
+ ITEM_ENERGY = 14,
+ ITEM_SHIELD = 15,
+ ITEM_OFFENSE = 16,
+ ITEM_HUB = 17,
+ ITEM_TIME_EXPIRED = 18,
+ SKIP_TURN = -999
+};
+
+enum BuildingTypes {
+ BUILDING_ENERGY_COLLECTOR = 3,
+ BUILDING_MAIN_BASE = 4,
+ BUILDING_BRIDGE = 5,
+ BUILDING_TOWER = 6,
+ BUILDING_EXPLOSIVE_MINE = 7,
+ BUILDING_SHIELD = 8,
+ BUILDING_ANTI_AIR = 9,
+ BUILDING_OFFENSIVE_LAUNCHER = 10,
+ BUILDING_BALLOON = 11,
+ BUILDING_CRAWLER = 12
+};
+
+enum {
+ ENERGY_POOL_X = 45,
+ ENERGY_POOL_Y = 46,
+ ENERGY_POOL_UNITS_ON = 47,
+
+ MIN_DIST = 108
+};
+
+static int energyHogType = 0;
+
+void ResetAI();
+void CleanUpAI();
+void SetAIType(const int paramCount, const int *params);
+int MasterControlProgram(const int paramCount, const int *params);
+
+int ChooseBehavior();
+int ChooseTarget(int behavior);
+
+Tree *InitApproachTarget(int targetX, int targetY, Node **retNode);
+int *ApproachTarget(Tree *myTree, int &x, int &y, Node **currentNode);
+Tree *InitAcquireTarget(int targetX, int targetY, Node **retNode);
+int *AcquireTarget(int targetX, int targetY);
+int *AcquireTarget(int targetX, int targetY, Tree *myTree, int &errorCode);
+int *OffendTarget(int &targetX, int &targetY, int index);
+int *DefendTarget(int &targetX, int &targetY, int index);
+int *EnergizeTarget(int &targetX, int &targetY, int index);
+
+int GetClosestUnit(int x, int y, int radius, int player, int alignment, int unitType, int checkUnitEnabled);
+int GetClosestUnit(int x, int y, int radius, int player, int alignment, int unitType, int checkUnitEnabled, int minDist);
+
+int GetDistance(int originX, int originY, int endX, int endY);
+int GetAngle(int originX, int originY, int endX, int endY);
+int GetAngle(int originX, int originY, int endX, int endY, int noWrapFlag);
+int GetTerrain(int x, int y);
+int GetHubX(int hub);
+int GetHubY(int hub);
+int GetMaxX();
+int GetMaxY();
+int GetCurrentPlayer();
+int GetMaxPower();
+int GetMinPower();
+int GetTerrainSquareSize();
+int GetBuildingOwner(int building);
+int GetBuildingState(int building);
+int GetBuildingType(int building);
+int GetBuildingArmor(int building);
+int GetBuildingWorth(int building);
+void DebugBreak();
+int GetEnergyPoolsArray();
+int GetCoordinateVisibility(int x, int y, int playerNum);
+int GetUnitVisibility(int unit, int playerNum);
+int GetEnergyPoolVisibility(int pool, int playerNum);
+int GetNumberOfPools();
+int GetNumberOfPlayers();
+int GetPlayerEnergy();
+int GetPlayerMaxTime();
+int GetWindXSpeed();
+int GetWindYSpeed();
+int GetTotalWindSpeed();
+int GetWindXSpeedMax();
+int GetWindYSpeedMax();
+int GetBigXSize();
+int GetBigYSize();
+int GetEnergyPoolWidth(int pool);
+int GetBuildingMaxArmor(int building);
+int GetTimerValue(int timerNum);
+int GetLastAttacked(int &x, int &y);
+int PrintDebugTimer(int max, int timerVal);
+int GetPlayerTeam(int player);
+int GetBuildingTeam(int building);
+int GetFOW();
+int GetAnimSpeed();
+int GetBuildingStackPtr();
+int GetTurnCounter();
+
+int GetGroundAltitude(int x, int y);
+int CheckForCordOverlap(int xStart, int yStart, int affectRadius, int simulateFlag);
+int CheckForAngleOverlap(int unit, int angle);
+int EstimateNextRoundEnergy(int player);
+int CheckForUnitOverlap(int x, int y, int radius, int ignoredUnit);
+int CheckForEnergySquare(int x, int y);
+int AIChat();
+
+
+int SimulateBuildingLaunch(int x, int y, int power, int angle, int numSteps, int isEnergy);
+int SimulateWeaponLaunch(int x, int y, int power, int angle, int numSteps);
+int FakeSimulateWeaponLaunch(int x, int y, int power, int angle);
+
+int GetPowerAngleFromPoint(int originX, int originY, int endX, int endY, int threshold, int olFlag);
+int GetPowerAngleFromPoint(int originX, int originY, int endX, int endY, int threshold);
+int CheckIfWaterState(int x, int y);
+int CheckIfWaterSquare(int x, int y);
+int GetUnitsWithinRadius(int x, int y, int radius);
+int GetLandingPoint(int x, int y, int power, int angle);
+int GetEnemyUnitsVisible(int playerNum);
+
+float degToRad(float degrees);
+void MACRO_LimitLocation(int &a, int &b, int c, int d);
+int energyPoolSize(int pool);
+int GetMaxCollectors(int pool);
+
+int TempChooseBehavior();
+int TempChooseTarget(int behavior);
+
+int GetEnergyHogType();
+
+extern Common::List<int> lastXCoord[];
+extern Common::List<int> lastYCoord[];
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/he/moonbase/ai_node.h b/engines/scumm/he/moonbase/ai_node.h
new file mode 100644
index 0000000000..87b6b96ebb
--- /dev/null
+++ b/engines/scumm/he/moonbase/ai_node.h
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCUMM_HE_MOONBASE_AI_NODE_H
+#define SCUMM_HE_MOONBASE_AI_NODE_H
+
+#include "common/list.h"
+
+namespace Scumm {
+
+const float SUCCESS = -1;
+const float FAILURE = 1e20;
+
+class IContainedObject {
+private:
+ int objID;
+ float valueG;
+
+protected:
+ virtual float getG() const { return valueG; }
+ virtual float calcH() { return 0; }
+
+
+public:
+ IContainedObject() { valueG = 0; }
+ IContainedObject(float inG) { valueG = inG; }
+ IContainedObject(IContainedObject &sourceContainedObject);
+ virtual ~IContainedObject() {}
+
+ virtual IContainedObject *duplicate() = 0;
+
+ void setValueG(float inG) { valueG = inG; }
+ float getValueG() { return valueG; }
+
+ int getObjID() const { return objID; }
+ void setObjID(int inputObjID) { objID = inputObjID; }
+
+ virtual int numChildrenToGen() = 0;
+ virtual IContainedObject *createChildObj(int index, int &completionFlag) = 0;
+
+ virtual int checkSuccess() = 0;
+ virtual float calcT() { return getG(); }
+
+ float returnG() const { return getG(); }
+};
+
+class Node {
+private:
+ Node *pParent;
+ Common::List<Node *> vpChildren;
+
+ int m_depth;
+ static int m_nodeCount;
+
+ IContainedObject *pContents;
+
+public:
+ Node();
+ Node(Node *sourceNode);
+ ~Node();
+
+ void setParent(Node *parentPtr) { pParent = parentPtr; }
+ Node *getParent() const { return pParent; }
+
+ void setDepth(int depth) { m_depth = depth; }
+ int getDepth() const { return m_depth; }
+
+ static int getNodeCount() { return m_nodeCount; }
+
+ void setContainedObject(IContainedObject *pValue) { pContents = pValue; }
+ IContainedObject *getContainedObject() { return pContents; }
+
+ Common::List<Node *> getChildren() const { return vpChildren; }
+ int generateChildren();
+ int generateNextChild();
+ Node *popChild();
+
+ float getObjectT() { return pContents->calcT(); }
+
+ Node *getFirstStep();
+
+ void printPath();
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/he/moonbase/ai_tree.h b/engines/scumm/he/moonbase/ai_tree.h
new file mode 100644
index 0000000000..c76d03c541
--- /dev/null
+++ b/engines/scumm/he/moonbase/ai_tree.h
@@ -0,0 +1,78 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCUMM_HE_MOONBASE_AI_TREE_H
+#define SCUMM_HE_MOONBASE_AI_TREE_H
+
+#include "scumm/he/moonbase/ai_node.h"
+
+namespace Scumm {
+
+//typedef std::multimap< float, Node *, std::less<float> > fnpMMap;
+
+const int MAX_DEPTH = 100;
+const int MAX_NODES = 1000000;
+
+class Tree {
+private:
+ Node *pBaseNode;
+
+ int m_maxDepth;
+ int m_maxNodes;
+
+ int currentChildIndex;
+ unsigned long m_startTime;
+
+ //fnpMMap m_currentMap;
+ Node *m_currentNode;
+
+public:
+ Tree();
+ Tree(IContainedObject *contents);
+ Tree(IContainedObject *contents, int maxDepth);
+ Tree(IContainedObject *contents, int maxDepth, int maxNodes);
+ Tree(const Tree *sourceTree);
+ ~Tree();
+
+ void duplicateTree(Node *sourceNode, Node *destNode);
+
+ Node *GetBaseNode() const { return pBaseNode; }
+ void setMaxDepth(int maxDepth) { m_maxDepth = maxDepth; }
+ int getMaxDepth() const { return m_maxDepth; }
+
+ void setMaxNodes(int maxNodes) { m_maxNodes = maxNodes; }
+ int getMaxNodes() const { return m_maxNodes; }
+
+ void setStartTime(unsigned long sTime) { m_startTime = sTime; }
+ unsigned long getStartTime() const { return m_startTime; }
+
+ Node *aStarSearch();
+
+ Node *aStarSearch_singlePassInit();
+ Node *aStarSearch_singlePass(Node **currentNode);
+
+ int IsBaseNode(Node *thisNode);
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/he/moonbase/moonbase.h b/engines/scumm/he/moonbase/moonbase.h
index e82ae0164f..0b47ba6dc3 100644
--- a/engines/scumm/he/moonbase/moonbase.h
+++ b/engines/scumm/he/moonbase/moonbase.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SCUMM_HE_MOONBASE_H
-#define SCUMM_HE_MOONBASE_H
+#ifndef SCUMM_HE_MOONBASE_MOONBASE_H
+#define SCUMM_HE_MOONBASE_MOONBASE_H
#ifdef ENABLE_HE
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index c56ef7e5f4..f1551b2bd2 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -139,6 +139,7 @@ MODULE_OBJS += \
he/logic/moonbase_logic.o \
he/logic/puttrace.o \
he/logic/soccer.o \
+ he/moonbase/ai_defenseunit.o \
he/moonbase/moonbase.o \
he/moonbase/moonbase_fow.o
endif