Initial commit
This commit is contained in:
766
engines/scumm/he/moonbase/ai_defenseunit.cpp
Normal file
766
engines/scumm/he/moonbase/ai_defenseunit.cpp
Normal file
@@ -0,0 +1,766 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/util.h"
|
||||
#include "scumm/he/intern_he.h"
|
||||
#include "scumm/he/moonbase/moonbase.h"
|
||||
#include "scumm/he/moonbase/ai_defenseunit.h"
|
||||
#include "scumm/he/moonbase/ai_main.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
DefenseUnit::DefenseUnit(AI *ai) : _ai(ai) {
|
||||
_state = DUS_ON;
|
||||
|
||||
_id = -1;
|
||||
_distanceTo = 0;
|
||||
_state = 0;
|
||||
_radius = 0;
|
||||
_armor = 0;
|
||||
_cost = 0;
|
||||
}
|
||||
|
||||
DefenseUnit::DefenseUnit(DefenseUnit *inUnit, AI *ai) : _ai(ai) {
|
||||
_id = inUnit->getID();
|
||||
_pos.x = inUnit->getPosX();
|
||||
_pos.y = inUnit->getPosY();
|
||||
_distanceTo = inUnit->getDistanceTo();
|
||||
_state = inUnit->getState();
|
||||
_radius = inUnit->getRadius();
|
||||
_armor = inUnit->getArmor();
|
||||
_cost = inUnit->getCost();
|
||||
}
|
||||
|
||||
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 = (int16)(getPosX() - ratio * (getPosX() - sourceX));
|
||||
targetPos->y = (int16)(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 = (int)(((x1 + x2) / 2) + ((x2 - x1) * (r1 * r1 - r2 * r2)) / (2 * d * d) + ((y2 - y1) / (2 * d * d)) * root);
|
||||
int y = (int)(((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 = (int16)(sourceX + ratio * (getPosX() - sourceX));
|
||||
targetPos->y = (int16)(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 (_ai->getPlayerEnergy() > 6) {
|
||||
if (!_ai->_vm->_rnd.getRandomNumber(3)) {
|
||||
return ITEM_VIRUS;
|
||||
}
|
||||
}
|
||||
|
||||
if (_ai->getPlayerEnergy() > 2) {
|
||||
if (!_ai->_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 = _ai->getMaxX();
|
||||
int maxY = _ai->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 = (int)(((x1 + x2) / 2) + ((x2 - x1) * (r1 * r1 - r2 * r2)) / (2 * d * d) + ((y2 - y1) / (2 * d * d)) * root);
|
||||
int y = (int)(((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 = (int16)(sourceX + ratio * (getPosX() - sourceX));
|
||||
targetPos->y = (int16)(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) {
|
||||
debugC(DEBUG_MOONBASE_AI, "Shield weapon select");
|
||||
|
||||
int myUnit = _ai->getClosestUnit(getPosX(), getPosY(), _ai->getMaxX(), _ai->getCurrentPlayer(), 1, BUILDING_MAIN_BASE, 1, 0);
|
||||
int dist = _ai->getDistance(getPosX(), getPosY(), _ai->getHubX(myUnit), _ai->getHubY(myUnit));
|
||||
|
||||
if ((dist < (getRadius() - 20)) && (dist > 90)) {
|
||||
return ITEM_SPIKE;
|
||||
}
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
if (getState() == DUS_OFF) {
|
||||
if (_ai->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 = (int16)(sourceX + ratio * (getPosX() - sourceX));
|
||||
targetPos->y = (int16)(sourceY + ratio * (getPosY() - sourceY));
|
||||
break;
|
||||
|
||||
default:
|
||||
targetPos->x = getPosX();
|
||||
targetPos->y = getPosY();
|
||||
break;
|
||||
}
|
||||
|
||||
return targetPos;
|
||||
}
|
||||
|
||||
int MineUnit::selectWeapon(int index) {
|
||||
int myUnit = _ai->getClosestUnit(getPosX(), getPosY(), _ai->getMaxX(), _ai->getCurrentPlayer(), 1, 0, 0, 0);
|
||||
int x = getPosX();
|
||||
int y = getPosY();
|
||||
|
||||
int dist = _ai->getDistance(x, y, _ai->getHubX(myUnit), _ai->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) {
|
||||
debugC(DEBUG_MOONBASE_AI, "Hub weapon select");
|
||||
|
||||
int energy = _ai->getPlayerEnergy();
|
||||
|
||||
if (energy > 6) {
|
||||
//possibly choose crawler
|
||||
if (_ai->getBuildingWorth(getID()) > 21) {
|
||||
return ITEM_CRAWLER;
|
||||
}
|
||||
}
|
||||
|
||||
//choose betw/ bomb and cluster
|
||||
if (_ai->getBuildingArmor(getID()) < 1.5) {
|
||||
return ITEM_CLUSTER;
|
||||
}
|
||||
|
||||
if (energy > 2) {
|
||||
if (!_ai->_vm->_rnd.getRandomNumber(3)) {
|
||||
return ITEM_SPIKE;
|
||||
}
|
||||
|
||||
if (!_ai->_vm->_rnd.getRandomNumber(4)) {
|
||||
return ITEM_GUIDED;
|
||||
}
|
||||
|
||||
if (!_ai->_vm->_rnd.getRandomNumber(4)) {
|
||||
return ITEM_MINE;
|
||||
}
|
||||
|
||||
if (!_ai->_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) {
|
||||
debugC(DEBUG_MOONBASE_AI, "Energy weapon select");
|
||||
|
||||
int energy = _ai->getPlayerEnergy();
|
||||
|
||||
if (energy > 6) {
|
||||
//possibly choose crawler
|
||||
if (_ai->getBuildingWorth(getID()) > 21) {
|
||||
return ITEM_CRAWLER;
|
||||
}
|
||||
}
|
||||
|
||||
//choose betw/ bomb and cluster
|
||||
if (_ai->getBuildingArmor(getID()) < 1.5) {
|
||||
return ITEM_CLUSTER;
|
||||
}
|
||||
|
||||
if (energy > 2) {
|
||||
if (!_ai->_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) {
|
||||
debugC(DEBUG_MOONBASE_AI, "Offense weapon select");
|
||||
|
||||
int energy = _ai->getPlayerEnergy();
|
||||
|
||||
if (energy > 6) {
|
||||
//possibly choose crawler
|
||||
if (_ai->getBuildingWorth(getID()) > 21) {
|
||||
return ITEM_CRAWLER;
|
||||
}
|
||||
}
|
||||
|
||||
//choose betw/ bomb and cluster
|
||||
if (_ai->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) {
|
||||
debugC(DEBUG_MOONBASE_AI, "Crawler weapon select");
|
||||
int myUnit = _ai->getClosestUnit(getPosX(), getPosY(), _ai->getMaxX(), _ai->getCurrentPlayer(), 1, 0, 0, 0);
|
||||
int dist = _ai->getDistance(_ai->getHubX(myUnit), _ai->getHubY(myUnit), getPosX(), getPosY());
|
||||
|
||||
int x = getPosX();
|
||||
int y = getPosY();
|
||||
int energy = _ai->getPlayerEnergy();
|
||||
int terrain = _ai->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 (_ai->_vm->_rnd.getRandomNumber(1)) {
|
||||
return ITEM_MINE;
|
||||
} else {
|
||||
return ITEM_TIME_EXPIRED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SKIP_TURN;
|
||||
}
|
||||
|
||||
AntiAirUnit::AntiAirUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(190);
|
||||
setArmor(3);
|
||||
setCost(1);
|
||||
}
|
||||
|
||||
ShieldUnit::ShieldUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(170);
|
||||
setArmor(3);
|
||||
setCost(7);
|
||||
}
|
||||
|
||||
MineUnit::MineUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(80);
|
||||
setArmor(1);
|
||||
setCost(3);
|
||||
}
|
||||
|
||||
HubUnit::HubUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(1);
|
||||
setArmor(5);
|
||||
setCost(7);
|
||||
}
|
||||
|
||||
TowerUnit::TowerUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(1);
|
||||
setArmor(3);
|
||||
setCost(1);
|
||||
}
|
||||
|
||||
BridgeUnit::BridgeUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(1);
|
||||
setArmor(3);
|
||||
setCost(1);
|
||||
}
|
||||
|
||||
EnergyUnit::EnergyUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(1);
|
||||
setArmor(5);
|
||||
setCost(7);
|
||||
}
|
||||
|
||||
OffenseUnit::OffenseUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(1);
|
||||
setArmor(3);
|
||||
setCost(7);
|
||||
}
|
||||
|
||||
CrawlerUnit::CrawlerUnit(AI *ai) : DefenseUnit(ai) {
|
||||
setRadius(1);
|
||||
setArmor(3);
|
||||
setCost(7);
|
||||
}
|
||||
|
||||
AntiAirUnit::AntiAirUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
|
||||
}
|
||||
|
||||
ShieldUnit::ShieldUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
}
|
||||
|
||||
MineUnit::MineUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
}
|
||||
|
||||
HubUnit::HubUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
}
|
||||
|
||||
TowerUnit::TowerUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
}
|
||||
|
||||
BridgeUnit::BridgeUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
}
|
||||
|
||||
EnergyUnit::EnergyUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
}
|
||||
|
||||
OffenseUnit::OffenseUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
}
|
||||
|
||||
CrawlerUnit::CrawlerUnit(DefenseUnit *inUnit, AI *ai) : DefenseUnit(inUnit, ai) {
|
||||
setID(inUnit->getID());
|
||||
setPos(inUnit->getPosX(), inUnit->getPosY());
|
||||
setDistanceTo(inUnit->getDistanceTo());
|
||||
setState(inUnit->getState());
|
||||
setRadius(inUnit->getRadius());
|
||||
setArmor(inUnit->getArmor());
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
194
engines/scumm/he/moonbase/ai_defenseunit.h
Normal file
194
engines/scumm/he/moonbase/ai_defenseunit.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_DEFENCEUNIT_H
|
||||
#define SCUMM_HE_MOONBASE_AI_DEFENCEUNIT_H
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class AI;
|
||||
|
||||
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 _id;
|
||||
Common::Point _pos;
|
||||
int _distanceTo;
|
||||
int _state;
|
||||
int _radius;
|
||||
int _armor;
|
||||
int _cost;
|
||||
|
||||
protected:
|
||||
AI *_ai;
|
||||
|
||||
public:
|
||||
DefenseUnit(AI *ai);
|
||||
DefenseUnit(DefenseUnit *inUnit, AI *ai);
|
||||
|
||||
virtual ~DefenseUnit();
|
||||
|
||||
void setID(int id) { _id = id; }
|
||||
void setDistanceTo(int distanceTo) { _distanceTo = distanceTo; }
|
||||
void setState(int state) { _state = state; }
|
||||
void setRadius(int radius) { _radius = radius; }
|
||||
void setArmor(int armor) { _armor = armor; }
|
||||
void setDamage(int damage) { _armor -= damage; }
|
||||
void setPos(int x, int y) {
|
||||
_pos.x = x;
|
||||
_pos.y = y;
|
||||
}
|
||||
void setCost(int cost) { _cost = cost; }
|
||||
|
||||
int getID() const { return _id; }
|
||||
int getDistanceTo() const { return _distanceTo; }
|
||||
int getState() const { return _state; }
|
||||
int getRadius() const { return _radius; }
|
||||
int getArmor() const { return _armor; }
|
||||
int getPosX() const { return _pos.x; }
|
||||
int getPosY() const { return _pos.y; }
|
||||
int getCost() const { return _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(AI *ai);
|
||||
AntiAirUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_ANTI_AIR; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
class ShieldUnit : public DefenseUnit {
|
||||
private:
|
||||
|
||||
public:
|
||||
ShieldUnit(AI *ai);
|
||||
ShieldUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_SHIELD; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
class MineUnit : public DefenseUnit {
|
||||
private:
|
||||
|
||||
public:
|
||||
MineUnit(AI *ai);
|
||||
MineUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_MINE; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
class HubUnit : public DefenseUnit {
|
||||
private:
|
||||
|
||||
public:
|
||||
HubUnit(AI *ai);
|
||||
HubUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_HUB; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
class TowerUnit : public DefenseUnit {
|
||||
private:
|
||||
|
||||
public:
|
||||
TowerUnit(AI *ai);
|
||||
TowerUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_TOWER; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
class BridgeUnit : public DefenseUnit {
|
||||
private:
|
||||
|
||||
public:
|
||||
BridgeUnit(AI *ai);
|
||||
BridgeUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_BRIDGE; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
class EnergyUnit : public DefenseUnit {
|
||||
private:
|
||||
|
||||
public:
|
||||
EnergyUnit(AI *ai);
|
||||
EnergyUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_ENERGY; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
class OffenseUnit : public DefenseUnit {
|
||||
private:
|
||||
|
||||
public:
|
||||
OffenseUnit(AI *ai);
|
||||
OffenseUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_OFFENSE; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
class CrawlerUnit : public DefenseUnit {
|
||||
private:
|
||||
|
||||
public:
|
||||
CrawlerUnit(AI *ai);
|
||||
CrawlerUnit(DefenseUnit *inUnit, AI *ai);
|
||||
int getType() const override { return DUT_CRAWLER; }
|
||||
Common::Point *createTargetPos(int index, int distance, int weaponType, int sourceX, int sourceY) override;
|
||||
int selectWeapon(int index) override;
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
3070
engines/scumm/he/moonbase/ai_main.cpp
Normal file
3070
engines/scumm/he/moonbase/ai_main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
210
engines/scumm/he/moonbase/ai_main.h
Normal file
210
engines/scumm/he/moonbase/ai_main.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_MAIN_H
|
||||
#define SCUMM_HE_MOONBASE_AI_MAIN_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "scumm/he/moonbase/ai_tree.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class ScummEngine_v100he;
|
||||
class AIEntity;
|
||||
class patternList;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
class AI {
|
||||
public:
|
||||
AI(ScummEngine_v100he *vm);
|
||||
|
||||
void resetAI();
|
||||
void cleanUpAI();
|
||||
void setAIType(const int paramCount, const int32 *params);
|
||||
int masterControlProgram(const int paramCount, const int32 *params);
|
||||
|
||||
private:
|
||||
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);
|
||||
|
||||
public:
|
||||
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 calcAngle(int originX, int originY, int endX, int endY);
|
||||
int calcAngle(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 getBuildingMaxArmor(int building);
|
||||
int getBuildingWorth(int building);
|
||||
int getBuildingTeam(int building);
|
||||
|
||||
int getPlayerEnergy();
|
||||
int getPlayerMaxTime();
|
||||
int getTimerValue(int timerNum);
|
||||
int getPlayerTeam(int player);
|
||||
|
||||
int getAnimSpeed();
|
||||
|
||||
int simulateBuildingLaunch(int x, int y, int power, int angle, int numSteps, int isEnergy);
|
||||
|
||||
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 getUnitsWithinRadius(int x, int y, int radius);
|
||||
|
||||
float degToRad(float degrees);
|
||||
|
||||
int getEnergyHogType();
|
||||
|
||||
private:
|
||||
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 getWindXSpeed();
|
||||
int getWindYSpeed();
|
||||
int getTotalWindSpeed();
|
||||
int getWindXSpeedMax();
|
||||
int getWindYSpeedMax();
|
||||
int getBigXSize();
|
||||
int getBigYSize();
|
||||
int getEnergyPoolWidth(int pool);
|
||||
int getLastAttacked(int &x, int &y);
|
||||
int getFOW();
|
||||
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 simulateWeaponLaunch(int x, int y, int power, int angle, int numSteps);
|
||||
int fakeSimulateWeaponLaunch(int x, int y, int power, int angle);
|
||||
|
||||
int checkIfWaterSquare(int x, int y);
|
||||
|
||||
int getLandingPoint(int x, int y, int power, int angle);
|
||||
int getEnemyUnitsVisible(int playerNum);
|
||||
|
||||
void limitLocation(int &a, int &b, int c, int d);
|
||||
int energyPoolSize(int pool);
|
||||
int getMaxCollectors(int pool);
|
||||
|
||||
public:
|
||||
Common::Array<int> _lastXCoord[5];
|
||||
Common::Array<int> _lastYCoord[5];
|
||||
|
||||
ScummEngine_v100he *_vm;
|
||||
|
||||
AIEntity *_aiType[5];
|
||||
|
||||
int _aiState;
|
||||
int _behavior;
|
||||
int _energyHogType;
|
||||
|
||||
patternList *_moveList[5];
|
||||
|
||||
const int32 *_mcpParams;
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
152
engines/scumm/he/moonbase/ai_node.cpp
Normal file
152
engines/scumm/he/moonbase/ai_node.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scumm/he/moonbase/ai_node.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
IContainedObject::IContainedObject(IContainedObject &sourceContainedObject) {
|
||||
_objID = sourceContainedObject.getObjID();
|
||||
_valueG = sourceContainedObject.getG();
|
||||
}
|
||||
|
||||
int Node::_nodeCount = 0;
|
||||
|
||||
Node::Node() {
|
||||
_parent = nullptr;
|
||||
_depth = 0;
|
||||
_nodeCount++;
|
||||
_contents = nullptr;
|
||||
}
|
||||
|
||||
Node::Node(Node *sourceNode) {
|
||||
_parent = nullptr;
|
||||
_children = sourceNode->getChildren();
|
||||
|
||||
_depth = sourceNode->getDepth();
|
||||
|
||||
_contents = sourceNode->getContainedObject()->duplicate();
|
||||
}
|
||||
|
||||
Node::~Node() {
|
||||
if (_contents != nullptr) {
|
||||
delete _contents;
|
||||
_contents = nullptr;
|
||||
}
|
||||
|
||||
_nodeCount--;
|
||||
}
|
||||
|
||||
int Node::generateChildren() {
|
||||
int numChildren = _contents->numChildrenToGen();
|
||||
|
||||
int numChildrenGenerated = numChildren;
|
||||
int errorCode = -1;
|
||||
static int i = 0;
|
||||
|
||||
while (i < numChildren) {
|
||||
Node *tempNode = new Node;
|
||||
_children.push_back(tempNode);
|
||||
tempNode->setParent(this);
|
||||
tempNode->setDepth(_depth + 1);
|
||||
|
||||
int completionFlag;
|
||||
|
||||
IContainedObject *thisContObj = _contents->createChildObj(i, completionFlag);
|
||||
assert(!(thisContObj != nullptr && completionFlag == 0));
|
||||
|
||||
if (!completionFlag) {
|
||||
_children.pop_back();
|
||||
delete tempNode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (thisContObj != nullptr) {
|
||||
tempNode->setContainedObject(thisContObj);
|
||||
} else {
|
||||
_children.pop_back();
|
||||
delete tempNode;
|
||||
numChildrenGenerated--;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
if (numChildrenGenerated > 0)
|
||||
return numChildrenGenerated;
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
|
||||
int Node::generateNextChild() {
|
||||
int numChildren = _contents->numChildrenToGen();
|
||||
|
||||
static int i = 0;
|
||||
|
||||
Node *tempNode = new Node;
|
||||
_children.push_back(tempNode);
|
||||
tempNode->setParent(this);
|
||||
tempNode->setDepth(_depth + 1);
|
||||
|
||||
int compFlag;
|
||||
IContainedObject *thisContObj = _contents->createChildObj(i, compFlag);
|
||||
|
||||
if (thisContObj != nullptr) {
|
||||
tempNode->setContainedObject(thisContObj);
|
||||
} else {
|
||||
_children.pop_back();
|
||||
delete tempNode;
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
if (i > numChildren)
|
||||
i = 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
Node *Node::popChild() {
|
||||
Node *temp;
|
||||
|
||||
temp = _children.back();
|
||||
_children.pop_back();
|
||||
return temp;
|
||||
}
|
||||
|
||||
Node *Node::getFirstStep() {
|
||||
Node *currentNode = this;
|
||||
|
||||
if (currentNode->getParent() == nullptr)
|
||||
return currentNode;
|
||||
|
||||
while (currentNode->getParent()->getParent() != nullptr)
|
||||
currentNode = currentNode->getParent();
|
||||
|
||||
assert(currentNode->getDepth() == 1);
|
||||
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
102
engines/scumm/he/moonbase/ai_node.h
Normal file
102
engines/scumm/he/moonbase/ai_node.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_NODE_H
|
||||
#define SCUMM_HE_MOONBASE_AI_NODE_H
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
const float SUCCESS = -1;
|
||||
const float FAILURE = 1e20f;
|
||||
|
||||
class IContainedObject {
|
||||
private:
|
||||
int _objID;
|
||||
float _valueG;
|
||||
|
||||
protected:
|
||||
virtual float getG() const { return _valueG; }
|
||||
virtual float calcH() { return 0; }
|
||||
|
||||
public:
|
||||
IContainedObject() { _valueG = 0; _objID = -1; }
|
||||
IContainedObject(float inG) { _valueG = inG; _objID = -1; }
|
||||
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 *_parent;
|
||||
Common::Array<Node *> _children;
|
||||
|
||||
int _depth;
|
||||
static int _nodeCount;
|
||||
|
||||
IContainedObject *_contents;
|
||||
|
||||
public:
|
||||
Node();
|
||||
Node(Node *sourceNode);
|
||||
~Node();
|
||||
|
||||
void setParent(Node *parentPtr) { _parent = parentPtr; }
|
||||
Node *getParent() const { return _parent; }
|
||||
|
||||
void setDepth(int depth) { _depth = depth; }
|
||||
int getDepth() const { return _depth; }
|
||||
|
||||
static int getNodeCount() { return _nodeCount; }
|
||||
|
||||
void setContainedObject(IContainedObject *value) { _contents = value; }
|
||||
IContainedObject *getContainedObject() { return _contents; }
|
||||
|
||||
Common::Array<Node *> getChildren() const { return _children; }
|
||||
int generateChildren();
|
||||
int generateNextChild();
|
||||
Node *popChild();
|
||||
|
||||
float getObjectT() { return _contents->calcT(); }
|
||||
|
||||
Node *getFirstStep();
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
161
engines/scumm/he/moonbase/ai_pattern.h
Normal file
161
engines/scumm/he/moonbase/ai_pattern.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_PATTERN_H
|
||||
#define SCUMM_HE_MOONBASE_AI_PATTERN_H
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
const int NO_PATTERN = 0;
|
||||
const int PATTERN_FOUND = 1;
|
||||
|
||||
class patternInstance {
|
||||
private:
|
||||
int _sourceHub;
|
||||
int _unit;
|
||||
int _power;
|
||||
int _angle;
|
||||
|
||||
public:
|
||||
patternInstance() {
|
||||
_sourceHub = 0;
|
||||
_unit = 0;
|
||||
_power = 0;
|
||||
_angle = 0;
|
||||
}
|
||||
|
||||
patternInstance(int sh, int unit, int power, int angle) {
|
||||
setSourceHub(sh);
|
||||
setUnit(unit);
|
||||
setPower(power);
|
||||
setAngle(angle);
|
||||
}
|
||||
|
||||
void setSourceHub(int sh) { _sourceHub = sh; }
|
||||
void setUnit(int unit) { _unit = unit; }
|
||||
|
||||
void setPower(int power) {
|
||||
if (power < 300)
|
||||
_power = 1;
|
||||
else if (power < 480)
|
||||
_power = 2;
|
||||
else
|
||||
_power = 3;
|
||||
}
|
||||
|
||||
void setAngle(int angle) {
|
||||
int tempAngle = angle % 360;
|
||||
|
||||
if ((tempAngle >= 0) && (tempAngle < 90))
|
||||
_angle = 1;
|
||||
|
||||
if ((tempAngle >= 90) && (tempAngle < 180))
|
||||
_angle = 2;
|
||||
|
||||
if ((tempAngle >= 180) && (tempAngle < 270))
|
||||
_angle = 3;
|
||||
|
||||
if ((tempAngle >= 270))
|
||||
_angle = 4;
|
||||
}
|
||||
|
||||
int getSourceHub() const { return _sourceHub; }
|
||||
int getUnit() const { return _unit; }
|
||||
int getPowerIndex() const { return _power; }
|
||||
int getAngleIndex() const { return _angle; }
|
||||
|
||||
static int comparePatterns(patternInstance *p1, patternInstance *p2) {
|
||||
if (p1->getSourceHub() != p2->getSourceHub())
|
||||
return 0;
|
||||
|
||||
if (p1->getUnit() != p2->getUnit())
|
||||
return 0;
|
||||
|
||||
if (p1->getUnit() == -999)
|
||||
return 0;
|
||||
|
||||
int temp = abs(p1->getPowerIndex() - p2->getPowerIndex());
|
||||
|
||||
if (temp > 1)
|
||||
return 0;
|
||||
|
||||
temp = abs(p1->getAngleIndex() - p2->getAngleIndex());
|
||||
|
||||
if (temp > 1 && temp < 3)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
class patternList {
|
||||
private:
|
||||
patternInstance *theList[10];
|
||||
int listIndex;
|
||||
|
||||
public:
|
||||
patternList() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
theList[i] = new patternInstance();
|
||||
}
|
||||
|
||||
listIndex = 0;
|
||||
}
|
||||
~patternList() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
delete theList[i];
|
||||
}
|
||||
}
|
||||
|
||||
void addPattern(int sh, int unit, int power, int angle) {
|
||||
theList[listIndex]->setSourceHub(sh);
|
||||
theList[listIndex]->setUnit(unit);
|
||||
theList[listIndex]->setPower(power);
|
||||
theList[listIndex]->setAngle(angle);
|
||||
|
||||
listIndex++;
|
||||
|
||||
if (listIndex > 9)
|
||||
listIndex = 0;
|
||||
}
|
||||
|
||||
int evaluatePattern(int sh, int unit, int power, int angle) {
|
||||
patternInstance *patternToMatch = new patternInstance(sh, unit, power, angle);
|
||||
int matchCount = 0;
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (patternInstance::comparePatterns(theList[i], patternToMatch)) {
|
||||
matchCount++;
|
||||
}
|
||||
}
|
||||
|
||||
delete patternToMatch;
|
||||
|
||||
if (matchCount > 2)
|
||||
return PATTERN_FOUND;
|
||||
|
||||
return NO_PATTERN;
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
569
engines/scumm/he/moonbase/ai_targetacquisition.cpp
Normal file
569
engines/scumm/he/moonbase/ai_targetacquisition.cpp
Normal file
@@ -0,0 +1,569 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scumm/he/intern_he.h"
|
||||
#include "scumm/he/moonbase/moonbase.h"
|
||||
|
||||
#include "scumm/he/moonbase/ai_targetacquisition.h"
|
||||
#include "scumm/he/moonbase/ai_main.h"
|
||||
#include "scumm/he/moonbase/ai_weapon.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
int Sortie::_sSourceX = 0;
|
||||
int Sortie::_sSourceY = 0;
|
||||
|
||||
int Sortie::_sTargetX = 0;
|
||||
int Sortie::_sTargetY = 0;
|
||||
|
||||
Sortie::~Sortie() {
|
||||
for (Common::Array<DefenseUnit *>::iterator k = _enemyDefenses.begin(); k != _enemyDefenses.end(); k++) {
|
||||
delete *k;
|
||||
}
|
||||
}
|
||||
|
||||
void Sortie::setEnemyDefenses(int enemyDefensesScummArray, int defendX, int defendY) {
|
||||
DefenseUnit *thisUnit;
|
||||
int currentPlayer = _ai->getCurrentPlayer();
|
||||
|
||||
for (int i = 0; i < 200; i++) {
|
||||
int thisElement = _ai->_vm->_moonbase->readFromArray(enemyDefensesScummArray, 0, i);
|
||||
|
||||
if (thisElement) {
|
||||
if (_ai->getBuildingOwner(thisElement)) {
|
||||
if (_ai->getPlayerTeam(currentPlayer) != _ai->getBuildingTeam(thisElement)) {
|
||||
int type = _ai->getBuildingType(thisElement);
|
||||
|
||||
switch (type) {
|
||||
case BUILDING_ANTI_AIR:
|
||||
thisUnit = new AntiAirUnit(_ai);
|
||||
break;
|
||||
|
||||
case BUILDING_SHIELD:
|
||||
thisUnit = new ShieldUnit(_ai);
|
||||
break;
|
||||
|
||||
case BUILDING_EXPLOSIVE_MINE:
|
||||
if (_ai->getDistance(_ai->getHubX(thisElement), _ai->getHubY(thisElement), defendX, defendY) < 90)
|
||||
thisUnit = new MineUnit(_ai);
|
||||
else
|
||||
thisUnit = NULL;
|
||||
|
||||
break;
|
||||
|
||||
case BUILDING_CRAWLER:
|
||||
thisUnit = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
thisUnit = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (thisUnit != NULL) {
|
||||
thisUnit->setID(thisElement);
|
||||
thisUnit->setPos(_ai->getHubX(thisElement), _ai->getHubY(thisElement));
|
||||
|
||||
if (_ai->getBuildingState(thisElement)) thisUnit->setState(DUS_OFF);
|
||||
|
||||
_enemyDefenses.push_back(thisUnit);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i = 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int *Sortie::getShotPos() const {
|
||||
int *retVal = new int[2];
|
||||
|
||||
retVal[0] = _shotPosX;
|
||||
retVal[1] = _shotPosY;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int Sortie::numChildrenToGen() {
|
||||
int retVal = MAX<uint>(_enemyDefenses.size(), 1) * NUM_SHOT_POSITIONS * NUM_WEAPONS;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
IContainedObject *Sortie::createChildObj(int index, int &completionFlag) {
|
||||
float thisDamage;
|
||||
Sortie *retSortie = new Sortie(_ai);
|
||||
// int activeDefenses = 0;
|
||||
|
||||
Common::Array<DefenseUnit *> thisEnemyDefenses;
|
||||
|
||||
// Copy the defensive unit list from the parent
|
||||
for (Common::Array<DefenseUnit *>::iterator k = _enemyDefenses.begin(); k != _enemyDefenses.end(); k++) {
|
||||
DefenseUnit *temp;
|
||||
|
||||
switch ((*k)->getType()) {
|
||||
case DUT_ANTI_AIR:
|
||||
temp = new AntiAirUnit(*k, _ai);
|
||||
break;
|
||||
|
||||
case DUT_SHIELD:
|
||||
temp = new ShieldUnit(*k, _ai);
|
||||
break;
|
||||
|
||||
case DUT_MINE:
|
||||
temp = new MineUnit(*k, _ai);
|
||||
break;
|
||||
|
||||
case DUT_CRAWLER:
|
||||
temp = new CrawlerUnit(*k, _ai);
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = new ShieldUnit(*k, _ai);
|
||||
break;
|
||||
}
|
||||
|
||||
thisEnemyDefenses.push_back(temp);
|
||||
}
|
||||
|
||||
// Calculate the current target from the index
|
||||
DefenseUnit *currentTarget = *(thisEnemyDefenses.begin() + static_cast<int>(index / (NUM_WEAPONS * NUM_SHOT_POSITIONS)));
|
||||
|
||||
assert(currentTarget);
|
||||
|
||||
// Pick correct weapon according to index
|
||||
Weapon *currentWeapon = new Weapon(currentTarget->selectWeapon(index % NUM_WEAPONS));
|
||||
retSortie->setUnitType(currentWeapon->getTypeID());
|
||||
|
||||
// Calculate distance from target to source hub
|
||||
int distance = _ai->getDistance(currentTarget->getPosX(), currentTarget->getPosY(), getSourcePosX(), getSourcePosY());
|
||||
|
||||
// Pick correct shot position according to index
|
||||
Common::Point *targetCoords;
|
||||
targetCoords = currentTarget->createTargetPos((static_cast<int>(index / NUM_WEAPONS) % NUM_SHOT_POSITIONS), distance, currentWeapon->getTypeID(), getSourcePosX(), getSourcePosY());
|
||||
retSortie->setShotPos(targetCoords->x, targetCoords->y);
|
||||
|
||||
// Set the g value based on cost of the weapon
|
||||
retSortie->setValueG(getG() + currentWeapon->getCost());
|
||||
|
||||
int AAcounter = 3;
|
||||
|
||||
// Loop through defensive units, toggling anti-air units and deciding if this weapon will land safely
|
||||
for (Common::Array<DefenseUnit *>::iterator i = thisEnemyDefenses.begin(); i != thisEnemyDefenses.end(); i++) {
|
||||
distance = _ai->getDistance((*i)->getPosX(), (*i)->getPosY(), targetCoords->x, targetCoords->y);
|
||||
|
||||
// Check to see if we're within an active defense's radius
|
||||
if ((distance < (*i)->getRadius()) && ((*i)->getState() == DUS_ON)) {
|
||||
//activeDefenses++;
|
||||
|
||||
// Turn off this anti-air and drop the coverage count
|
||||
if (((*i)->getType() == DUT_ANTI_AIR)) {
|
||||
(*i)->setState(DUS_OFF);
|
||||
|
||||
if (currentWeapon->getTypeID() == ITEM_CLUSTER)
|
||||
AAcounter--;
|
||||
else
|
||||
AAcounter = 0;
|
||||
}
|
||||
|
||||
// Essentially disable this weapon choice, due to its impact with a shield, or untriggered anti-air
|
||||
if (((*i)->getType() == DUT_SHIELD) || !AAcounter) {
|
||||
retSortie->setValueG(1000);
|
||||
i = thisEnemyDefenses.end() - 1;
|
||||
}
|
||||
} else {
|
||||
// Turn on any anti-airs that were off the previous turn
|
||||
if (((*i)->getType() == DUT_ANTI_AIR) && ((*i)->getState() == DUS_OFF))
|
||||
(*i)->setState(DUS_ON);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn on all the non-anti-air units in preparation for emp's and the next turn
|
||||
for (Common::Array<DefenseUnit *>::iterator i = thisEnemyDefenses.begin(); i != thisEnemyDefenses.end(); i++) {
|
||||
if ((*i)->getType() != DUT_ANTI_AIR) {
|
||||
(*i)->setState(DUS_ON);
|
||||
}
|
||||
}
|
||||
|
||||
// If this weapon is still valid
|
||||
if (retSortie->getValueG() < 1000) {
|
||||
// Apply emp effects and damage to all units in range of weapon
|
||||
for (Common::Array<DefenseUnit *>::iterator i = thisEnemyDefenses.begin(); i != thisEnemyDefenses.end(); ) {
|
||||
// Special simulated crawler detonation location used, since it walks a bit
|
||||
if (currentWeapon->getTypeID() == ITEM_CRAWLER)
|
||||
distance = _ai->getDistance((*i)->getPosX(), (*i)->getPosY(), currentTarget->getPosX(), currentTarget->getPosY());
|
||||
// Normal detonation location used here
|
||||
else {
|
||||
distance = _ai->getDistance((*i)->getPosX(), (*i)->getPosY(), targetCoords->x, targetCoords->y);
|
||||
}
|
||||
|
||||
if (distance < currentWeapon->getRadius()) {
|
||||
// Apply damage
|
||||
thisDamage = currentWeapon->getDamage();
|
||||
|
||||
if ((AAcounter != 3) && (currentWeapon->getTypeID() == ITEM_CLUSTER))
|
||||
thisDamage = 0;
|
||||
|
||||
if (!_ai->_vm->_rnd.getRandomNumber(4))
|
||||
currentWeapon->setTypeID(ITEM_MINE);
|
||||
|
||||
(*i)->setDamage((int)thisDamage);
|
||||
|
||||
// Apply emp effect
|
||||
if (currentWeapon->getTypeID() == ITEM_EMP) {
|
||||
(*i)->setState(DUS_OFF);
|
||||
}
|
||||
|
||||
// Remove destroyed defenses
|
||||
if ((*i)->getArmor() <= 0) {
|
||||
delete *i;
|
||||
i = thisEnemyDefenses.erase(i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retSortie->setEnemyDefenses(thisEnemyDefenses);
|
||||
|
||||
delete targetCoords;
|
||||
delete currentWeapon;
|
||||
return retSortie;
|
||||
}
|
||||
|
||||
float Sortie::calcH() {
|
||||
float retValue = 0;
|
||||
Common::Array<DefenseUnit *> thisEnemyDefenses = getEnemyDefenses();
|
||||
|
||||
for (Common::Array<DefenseUnit *>::iterator i = thisEnemyDefenses.begin(); i != thisEnemyDefenses.end(); i++) {
|
||||
if ((*i)->getState() == DUS_ON) {
|
||||
switch ((*i)->getType()) {
|
||||
case DUT_ANTI_AIR:
|
||||
retValue += 1; // Is it bug in the original? Fixing it may break replay compatibility
|
||||
// fall through
|
||||
|
||||
case DUT_MINE:
|
||||
retValue += 1;
|
||||
break;
|
||||
|
||||
case DUT_SHIELD:
|
||||
retValue += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
int Sortie::checkSuccess() {
|
||||
if (!_enemyDefenses.size())
|
||||
return SUCCESS;
|
||||
|
||||
int targetX = getTargetPosX();
|
||||
int targetY = getTargetPosY();
|
||||
|
||||
int targetCheck = 0;
|
||||
|
||||
for (Common::Array<DefenseUnit *>::iterator i = _enemyDefenses.begin(); i != _enemyDefenses.end(); i++) {
|
||||
if (((*i)->getState() == DUS_ON) && ((*i)->getType() != DUT_HUB)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((*i)->getPosX() == targetX) && ((*i)->getPosY() == targetY)) targetCheck = 1;
|
||||
}
|
||||
|
||||
if (!targetCheck)
|
||||
return SUCCESS;
|
||||
|
||||
// If shot pos == target pos return SUCCESS;
|
||||
if ((targetX == getShotPosX()) && (getTargetPosY() == getShotPosY())) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Sortie::calcT() {
|
||||
return (checkSuccess() != SUCCESS) ? (getG() + calcH()) : SUCCESS;
|
||||
}
|
||||
|
||||
IContainedObject *Sortie::duplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
void Sortie::printEnemyDefenses() {
|
||||
for (Common::Array<DefenseUnit *>::iterator i = _enemyDefenses.begin(); i != _enemyDefenses.end(); i++) {
|
||||
debugC(DEBUG_MOONBASE_AI, "Unit %d - Type: %d, Armor: %d, Status: %d", (*i)->getID(), (*i)->getType(), static_cast<int>((*i)->getArmor()), (*i)->getState());
|
||||
}
|
||||
}
|
||||
|
||||
Defender::Defender(AI *ai) : _ai(ai) {
|
||||
_sourceX = _sourceY = 0;
|
||||
_targetX = _targetY = 0;
|
||||
_sourceUnit = 0;
|
||||
_power = 0;
|
||||
_angle = 0;
|
||||
_unit = 0;
|
||||
}
|
||||
|
||||
int Defender::calculateDefenseUnitPosition(int targetX, int targetY, int index) {
|
||||
int currentPlayer = _ai->getCurrentPlayer();
|
||||
|
||||
//get list of near hubs
|
||||
int unitsArray = _ai->getUnitsWithinRadius(targetX + 5, targetY, 480);
|
||||
|
||||
const int NUM_HUBS = 10;
|
||||
//Order on dist
|
||||
int hubArray[NUM_HUBS] = { 0 };
|
||||
int hubIndex = 0;
|
||||
|
||||
for (int i = 0; i < 200; i++) {
|
||||
int thisUnit = _ai->_vm->_moonbase->readFromArray(unitsArray, 0, i);
|
||||
|
||||
if (thisUnit) {
|
||||
if (((_ai->getBuildingType(thisUnit) == BUILDING_MAIN_BASE) || (_ai->getBuildingType(thisUnit) == BUILDING_OFFENSIVE_LAUNCHER)) && (_ai->getBuildingOwner(thisUnit) == currentPlayer)) {
|
||||
for (int j = 0; j < NUM_HUBS; j++) {
|
||||
if (hubArray[j]) {
|
||||
int distCurrent = _ai->getDistance(targetX, targetY, _ai->getHubX(thisUnit), _ai->getHubY(thisUnit));
|
||||
int distSaved = _ai->getDistance(targetX, targetY, _ai->getHubX(hubArray[j]), _ai->getHubY(hubArray[j]));
|
||||
|
||||
if (distCurrent < distSaved) {
|
||||
hubArray[hubIndex] = hubArray[j];
|
||||
hubArray[j] = thisUnit;
|
||||
hubIndex++;
|
||||
j = 100;
|
||||
}
|
||||
} else {
|
||||
hubArray[j] = thisUnit;
|
||||
hubIndex++;
|
||||
j = 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hubIndex >= NUM_HUBS) {
|
||||
hubIndex = NUM_HUBS;
|
||||
i = 200;
|
||||
}
|
||||
}
|
||||
|
||||
_ai->_vm->_moonbase->deallocateArray(unitsArray);
|
||||
|
||||
//Check if repair is needed
|
||||
int targetUnit = _ai->getClosestUnit(targetX + 5, targetY, 15, currentPlayer, 1, 0, 0, 0);
|
||||
|
||||
if (targetUnit && (targetUnit != BUILDING_CRAWLER) && (_ai->getBuildingTeam(targetUnit) == _ai->getPlayerTeam(currentPlayer))) {
|
||||
int armor = _ai->getBuildingArmor(targetUnit);
|
||||
|
||||
if (armor < _ai->getBuildingMaxArmor(targetUnit)) {
|
||||
unitsArray = _ai->getUnitsWithinRadius(targetX + 5, targetY, 170);
|
||||
int defCount = 0;
|
||||
|
||||
for (int i = 0; i < 200; i++) {
|
||||
int thisUnit = _ai->_vm->_moonbase->readFromArray(unitsArray, 0, i);
|
||||
|
||||
if (thisUnit) {
|
||||
if (((_ai->getBuildingType(thisUnit) == BUILDING_SHIELD) || (_ai->getBuildingType(thisUnit) == BUILDING_ANTI_AIR)) && (_ai->getBuildingOwner(thisUnit) == currentPlayer) && (_ai->getBuildingState(thisUnit) == 0)) {
|
||||
defCount++;
|
||||
i = 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ai->_vm->_moonbase->deallocateArray(unitsArray);
|
||||
|
||||
if (defCount) {
|
||||
//repair
|
||||
int hubUnit = _ai->getClosestUnit(targetX, targetY, 480, currentPlayer, 1, BUILDING_MAIN_BASE, 1, 110);
|
||||
|
||||
if (hubUnit && (hubUnit != targetUnit)) {
|
||||
int powAngle = abs(_ai->getPowerAngleFromPoint(_ai->getHubX(hubUnit), _ai->getHubY(hubUnit), targetX, targetY, 20));
|
||||
int power = powAngle / 360;
|
||||
int angle = powAngle - (power * 360);
|
||||
|
||||
setTargetX(targetX);
|
||||
setTargetY(targetY);
|
||||
|
||||
setSourceUnit(hubUnit);
|
||||
setUnit(ITEM_REPAIR);
|
||||
setPower(power);
|
||||
setAngle(angle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//For each hub
|
||||
for (int i = 0; i < MIN(NUM_HUBS, hubIndex); i++) {
|
||||
int hubX = _ai->getHubX(hubArray[i]);
|
||||
int hubY = _ai->getHubY(hubArray[i]);
|
||||
//get angle to hub
|
||||
int directAngleToHub = 0;
|
||||
|
||||
//If this hub is the target
|
||||
if ((hubX == targetX) && (hubY == targetY)) {
|
||||
//make the angle seed point at the closest enemy
|
||||
int enemyUnit = _ai->getClosestUnit(hubX, hubY, _ai->getMaxX(), currentPlayer, 0, 0, 0);
|
||||
directAngleToHub = _ai->calcAngle(targetX, targetY, _ai->getHubX(enemyUnit), _ai->getHubY(enemyUnit));
|
||||
} else {
|
||||
directAngleToHub = _ai->calcAngle(targetX, targetY, hubX, hubY);
|
||||
}
|
||||
|
||||
//Number of random chances to land
|
||||
for (int j = 0; j < 3; j++) {
|
||||
//Pick random angle and dist within semicircle (-90 to +90) and (40 to 150)
|
||||
int randAngle = directAngleToHub + _ai->_vm->_rnd.getRandomNumber(179) - 90;
|
||||
int randDist = _ai->_vm->_rnd.getRandomNumber(109) + 40;
|
||||
|
||||
int x = (int)(targetX + randDist * cos(_ai->degToRad(randAngle)));
|
||||
int y = (int)(targetY + randDist * sin(_ai->degToRad(randAngle)));
|
||||
|
||||
int powAngle = _ai->getPowerAngleFromPoint(hubX, hubY, x, y, 20);
|
||||
|
||||
if (powAngle < 0)
|
||||
continue;
|
||||
|
||||
int power = powAngle / 360;
|
||||
int angle = powAngle - (power * 360);
|
||||
|
||||
int coords = 0;
|
||||
coords = _ai->simulateBuildingLaunch(hubX, hubY, power, angle, 100, 0);
|
||||
|
||||
//if valid, return
|
||||
if (coords > 0) {
|
||||
//debugC(DEBUG_MOONBASE_AI, "The prospective launching hub for this defensive unit is: %d", hubArray[i]);
|
||||
|
||||
setSourceX(hubX);
|
||||
setSourceY(hubY);
|
||||
setTargetX((x + _ai->getMaxX()) % _ai->getMaxX());
|
||||
setTargetY((y + _ai->getMaxY()) % _ai->getMaxY());
|
||||
setSourceUnit(hubArray[i]);
|
||||
|
||||
int unitsArray2 = _ai->getUnitsWithinRadius(targetX + 5, targetY, 200);
|
||||
int shieldCount = 0;
|
||||
|
||||
for (int k = 0; k < 200; k++) {
|
||||
int thisUnit = _ai->_vm->_moonbase->readFromArray(unitsArray2, 0, k);
|
||||
|
||||
if (thisUnit) {
|
||||
if ((_ai->getBuildingType(thisUnit) == BUILDING_SHIELD) && (_ai->getBuildingOwner(thisUnit) == currentPlayer))
|
||||
shieldCount++;
|
||||
|
||||
if ((_ai->getBuildingType(thisUnit) == BUILDING_BRIDGE) && (_ai->getBuildingOwner(thisUnit) == currentPlayer)) {
|
||||
shieldCount--;
|
||||
shieldCount = MAX(-1, shieldCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((_ai->_vm->_rnd.getRandomNumber((int)pow(3.0f, shieldCount + 1) - 1) == 0) && (_ai->getPlayerEnergy() > 6))
|
||||
setUnit(ITEM_SHIELD);
|
||||
else
|
||||
setUnit(ITEM_ANTIAIR);
|
||||
|
||||
setPower(power);
|
||||
setAngle(angle);
|
||||
|
||||
_ai->_vm->_moonbase->deallocateArray(unitsArray2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (coords < 0) {
|
||||
//drop a bridge for the cord
|
||||
int yCoord = -coords / _ai->getMaxX();
|
||||
int xCoord = -coords - (yCoord * _ai->getMaxX());
|
||||
|
||||
if (_ai->checkIfWaterState(xCoord, yCoord)) {
|
||||
int terrainSquareSize = _ai->getTerrainSquareSize();
|
||||
xCoord = ((xCoord / terrainSquareSize * terrainSquareSize) + (terrainSquareSize / 2));
|
||||
yCoord = ((yCoord / terrainSquareSize * terrainSquareSize) + (terrainSquareSize / 2));
|
||||
|
||||
int xDist = xCoord - x;
|
||||
int yDist = yCoord - y;
|
||||
x = (int)(xCoord + (terrainSquareSize * 1.414 * (xDist / (abs(xDist) + 1))));
|
||||
y = (int)(yCoord + (terrainSquareSize * 1.414 * (yDist / (abs(yDist) + 1))));
|
||||
|
||||
setTargetX(x);
|
||||
setTargetY(y);
|
||||
|
||||
int nextUnit = _ai->getClosestUnit(x, y, 480, _ai->getCurrentPlayer(), 1, BUILDING_MAIN_BASE, 1, 120);
|
||||
powAngle = _ai->getPowerAngleFromPoint(_ai->getHubX(nextUnit), _ai->getHubY(nextUnit), x, y, 15);
|
||||
|
||||
powAngle = abs(powAngle);
|
||||
power = powAngle / 360;
|
||||
angle = powAngle - (power * 360);
|
||||
|
||||
setSourceUnit(nextUnit);
|
||||
setUnit(ITEM_BRIDGE);
|
||||
setPower(power);
|
||||
setAngle(angle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Else create new hub
|
||||
int count = 0;
|
||||
int coords = 0;
|
||||
|
||||
if (hubIndex == 0) return -3;
|
||||
|
||||
do {
|
||||
int sourceHub = hubArray[_ai->_vm->_rnd.getRandomNumber(hubIndex - 1)];
|
||||
|
||||
setSourceX(_ai->getHubX(sourceHub));
|
||||
setSourceY(_ai->getHubY(sourceHub));
|
||||
setSourceUnit(sourceHub);
|
||||
setUnit(ITEM_HUB);
|
||||
setPower(_ai->_vm->_rnd.getRandomNumber(299) + 200);
|
||||
setAngle(_ai->_vm->_rnd.getRandomNumber(359));
|
||||
count++;
|
||||
|
||||
if (count > (NUM_HUBS * 3)) break;
|
||||
|
||||
coords = _ai->simulateBuildingLaunch(getSourceX(), getSourceY(), getPower(), getAngle(), 100, 0);
|
||||
} while (coords <= 0);
|
||||
|
||||
if (coords > 0) {
|
||||
setTargetX(coords % _ai->getMaxX());
|
||||
setTargetY(coords / _ai->getMaxX());
|
||||
} else {
|
||||
setTargetX(0);
|
||||
setTargetY(0);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
151
engines/scumm/he/moonbase/ai_targetacquisition.h
Normal file
151
engines/scumm/he/moonbase/ai_targetacquisition.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_TARGETACQUISITION_H
|
||||
#define SCUMM_HE_MOONBASE_AI_TARGETACQUISITION_H
|
||||
|
||||
#include "scumm/he/moonbase/ai_defenseunit.h"
|
||||
#include "scumm/he/moonbase/ai_node.h"
|
||||
#include "scumm/he/moonbase/ai_tree.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
const int NUM_IMPT_UNITS = 3;
|
||||
const int NUM_SHOT_POSITIONS = 1;
|
||||
const int NUM_WEAPONS = 3;
|
||||
|
||||
class Sortie : public IContainedObject {
|
||||
private:
|
||||
static int _sSourceX;
|
||||
static int _sSourceY;
|
||||
|
||||
static int _sTargetX;
|
||||
static int _sTargetY;
|
||||
|
||||
int _unitType;
|
||||
int _shotPosX, _shotPosY;
|
||||
Common::Array<DefenseUnit *> _enemyDefenses;
|
||||
AI *_ai;
|
||||
|
||||
public:
|
||||
Sortie(AI *ai) { _ai = ai; _unitType = 0; _shotPosX = _shotPosY = 0; }
|
||||
~Sortie() override;
|
||||
|
||||
static void setSourcePos(int x, int y) {
|
||||
_sSourceX = x;
|
||||
_sSourceY = y;
|
||||
}
|
||||
static void setTargetPos(int x, int y) {
|
||||
_sTargetX = x;
|
||||
_sTargetY = y;
|
||||
}
|
||||
|
||||
void setUnitType(int unitType) { _unitType = unitType; }
|
||||
|
||||
void setShotPosX(int shotPosX) { _shotPosX = shotPosX; }
|
||||
void setShotPosY(int shotPosY) { _shotPosY = shotPosY; }
|
||||
void setShotPos(int shotPosX, int shotPosY) {
|
||||
_shotPosX = shotPosX;
|
||||
_shotPosY = shotPosY;
|
||||
}
|
||||
|
||||
void setEnemyDefenses(Common::Array<DefenseUnit *> enemyDefenses) {
|
||||
_enemyDefenses = enemyDefenses;
|
||||
}
|
||||
void setEnemyDefenses(int enemyDefensesScummArray, int defendX, int defendY);
|
||||
|
||||
void printEnemyDefenses();
|
||||
|
||||
static int getSourcePosX() { return _sSourceX; }
|
||||
static int getSourcePosY() { return _sSourceY; }
|
||||
static int getTargetPosX() { return _sTargetX; }
|
||||
static int getTargetPosY() { return _sTargetY; }
|
||||
|
||||
int getUnitType() const { return _unitType; }
|
||||
|
||||
int getShotPosX() const { return _shotPosX; }
|
||||
int getShotPosY() const { return _shotPosY; }
|
||||
int *getShotPos() const;
|
||||
|
||||
Common::Array<DefenseUnit *> getEnemyDefenses() const { return _enemyDefenses; }
|
||||
|
||||
IContainedObject *duplicate() override;
|
||||
|
||||
int numChildrenToGen() override;
|
||||
IContainedObject *createChildObj(int, int &completionFlag) override;
|
||||
|
||||
|
||||
float calcH() override;
|
||||
int checkSuccess() override;
|
||||
float calcT() override;
|
||||
};
|
||||
|
||||
class Defender {
|
||||
private:
|
||||
int _sourceX;
|
||||
int _sourceY;
|
||||
int _targetX;
|
||||
int _targetY;
|
||||
int _sourceUnit;
|
||||
int _power;
|
||||
int _angle;
|
||||
int _unit;
|
||||
AI *_ai;
|
||||
|
||||
public:
|
||||
Defender(AI *ai);
|
||||
void setSourceX(int sourceX) { _sourceX = sourceX; }
|
||||
void setSourceY(int sourceY) { _sourceY = sourceY; }
|
||||
void setTargetX(int targetX) { _targetX = targetX; }
|
||||
void setTargetY(int targetY) { _targetY = targetY; }
|
||||
void setSourceUnit(int sourceUnit) { _sourceUnit = sourceUnit; }
|
||||
void setPower(int power) { _power = power; }
|
||||
void setAngle(int angle) { _angle = angle; }
|
||||
void setUnit(int unit) { _unit = unit; }
|
||||
|
||||
int getSourceX() const { return _sourceX; }
|
||||
int getSourceY() const { return _sourceY; }
|
||||
int getTargetX() const { return _targetX; }
|
||||
int getTargetY() const { return _targetY; }
|
||||
int getSourceUnit() const { return _sourceUnit; }
|
||||
int getPower() const { return _power; }
|
||||
int getAngle() const { return _angle; }
|
||||
int getUnit() const { return _unit; }
|
||||
|
||||
int calculateDefenseUnitPosition(int targetX, int targetY, int index);
|
||||
};
|
||||
|
||||
class defenseUnitCompare {
|
||||
public:
|
||||
bool operator()(DefenseUnit *x, DefenseUnit *y) {
|
||||
//disabled units go at the end
|
||||
if (x->getState() == DUS_OFF) {
|
||||
debugC(DEBUG_MOONBASE_AI, "OFF");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return x->getDistanceTo() < y->getDistanceTo();
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
278
engines/scumm/he/moonbase/ai_traveller.cpp
Normal file
278
engines/scumm/he/moonbase/ai_traveller.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scumm/he/intern_he.h"
|
||||
#include "scumm/he/moonbase/moonbase.h"
|
||||
#include "scumm/he/moonbase/ai_traveller.h"
|
||||
#include "scumm/he/moonbase/ai_main.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
int Traveller::_targetPosX = 0;
|
||||
int Traveller::_targetPosY = 0;
|
||||
int Traveller::_maxDist = 0;
|
||||
|
||||
int Traveller::_numToGen = 0;
|
||||
int Traveller::_sizeAngleStep = 0;
|
||||
|
||||
Traveller::Traveller(AI *ai) : _ai(ai) {
|
||||
_waterFlag = 0;
|
||||
setValueG(0);
|
||||
unsetDisabled();
|
||||
|
||||
_sourceHub = 0;
|
||||
_angleTo = 0;
|
||||
_powerTo = 0;
|
||||
_waterSourceX = 0;
|
||||
_waterSourceY = 0;
|
||||
_waterDestX = 0;
|
||||
_waterDestY = 0;
|
||||
|
||||
_posX = _posY = 0;
|
||||
}
|
||||
|
||||
Traveller::Traveller(int originX, int originY, AI *ai) : _ai(ai) {
|
||||
_waterFlag = 0;
|
||||
setValueG(0);
|
||||
unsetDisabled();
|
||||
|
||||
_posX = originX;
|
||||
_posY = originY;
|
||||
|
||||
_sourceHub = 0;
|
||||
_angleTo = 0;
|
||||
_powerTo = 0;
|
||||
_waterSourceX = 0;
|
||||
_waterSourceY = 0;
|
||||
_waterDestX = 0;
|
||||
_waterDestY = 0;
|
||||
}
|
||||
|
||||
void Traveller::adjustPosX(int offsetX) {
|
||||
int maxX = _ai->getMaxX();
|
||||
int deltaX = _posX + offsetX;
|
||||
|
||||
if (deltaX < 0) _posX = maxX + deltaX;
|
||||
else if (deltaX > maxX) _posX = deltaX - maxX;
|
||||
else _posX = deltaX;
|
||||
}
|
||||
|
||||
void Traveller::adjustPosY(int offsetY) {
|
||||
int maxY = _ai->getMaxX();
|
||||
int deltaY = _posY + offsetY;
|
||||
|
||||
if (deltaY < 0) _posY = maxY + deltaY;
|
||||
else if (deltaY > maxY) _posY = deltaY - maxY;
|
||||
else _posY = deltaY;
|
||||
}
|
||||
|
||||
void Traveller::adjustXY(int offsetX, int offsetY) {
|
||||
adjustPosX(offsetX);
|
||||
adjustPosY(offsetY);
|
||||
}
|
||||
|
||||
float Traveller::calcH() {
|
||||
float retVal = 0;
|
||||
// Calc dist from here to target
|
||||
retVal = _ai->getDistance(_posX, _posY, _targetPosX, _targetPosY);
|
||||
// Divide by _maxDist to get minimum number of jumps to goal
|
||||
retVal /= static_cast<float>(_maxDist);
|
||||
|
||||
return retVal * 2.0;
|
||||
}
|
||||
|
||||
int Traveller::numChildrenToGen() {
|
||||
if (!_numToGen)
|
||||
_numToGen = _ai->getAnimSpeed() + 2;
|
||||
|
||||
return _numToGen;
|
||||
}
|
||||
|
||||
IContainedObject *Traveller::createChildObj(int index, int &completionFlag) {
|
||||
//static int nodeCount = 0;
|
||||
static int completionState = 1;
|
||||
|
||||
//if (!index) nodeCount = 0;
|
||||
|
||||
//nodeCount++;
|
||||
|
||||
Traveller *retTraveller = new Traveller(_ai);
|
||||
|
||||
static int dir, angle, power;
|
||||
|
||||
if (completionState) {
|
||||
// Calculate angle between here and target
|
||||
int directAngle = 0;
|
||||
|
||||
if (_ai->getEnergyHogType())
|
||||
directAngle = _ai->calcAngle(_posX, _posY, _targetPosX, _targetPosY, 1);
|
||||
else
|
||||
directAngle = _ai->calcAngle(_posX, _posY, _targetPosX, _targetPosY);
|
||||
|
||||
// Calculate the offset angle for this index
|
||||
if (!_sizeAngleStep)
|
||||
_sizeAngleStep = 52 - (_ai->getAnimSpeed() * 7);
|
||||
|
||||
dir = _sizeAngleStep * ((static_cast<int>(index / NUM_POWER_STEPS) + 1) >> 1);
|
||||
// Calculate the sign value for the offset for this index
|
||||
int orientation = dir * (((static_cast<int>(index / NUM_POWER_STEPS) % 2) << 1) - 1);
|
||||
// Add the offset angle to the direct angle to target
|
||||
angle = orientation + directAngle;
|
||||
|
||||
// Calculate power for this index
|
||||
int maxPower = 0;
|
||||
int directDist = _ai->getDistance(_posX, _posY, _targetPosX, _targetPosY);
|
||||
|
||||
if (directDist > _maxDist + 120)
|
||||
maxPower = _ai->getMaxPower();
|
||||
else
|
||||
maxPower = (int)((static_cast<float>(directDist) / static_cast<float>(_maxDist + 120)) * _ai->getMaxPower());
|
||||
|
||||
maxPower -= 70;
|
||||
power = (int)(maxPower * (1 - ((index % NUM_POWER_STEPS) * SIZE_POWER_STEP)));
|
||||
}
|
||||
|
||||
retTraveller->setAngleTo(angle);
|
||||
retTraveller->setPowerTo(power);
|
||||
|
||||
// Set this object's position to the new one determined by the power and angle from above
|
||||
static int lastSuccessful = 0;
|
||||
int coords = 0;
|
||||
|
||||
if (!(index % NUM_POWER_STEPS) || (!lastSuccessful)) {
|
||||
coords = _ai->simulateBuildingLaunch(_posX, _posY, power, angle, 10, 0);
|
||||
lastSuccessful = 0;
|
||||
} else {
|
||||
completionState = 1;
|
||||
lastSuccessful = 0;
|
||||
}
|
||||
|
||||
if (!coords) {
|
||||
completionFlag = 0;
|
||||
completionState = 0;
|
||||
delete retTraveller;
|
||||
return NULL;
|
||||
} else {
|
||||
completionFlag = 1;
|
||||
completionState = 1;
|
||||
}
|
||||
|
||||
int whoseTurn = _ai->getCurrentPlayer();
|
||||
int maxX = _ai->getMaxX();
|
||||
|
||||
// Check new position to see if landing is clear
|
||||
if (coords > 0) {
|
||||
int yCoord = coords / maxX;
|
||||
int xCoord = coords - (yCoord * maxX);
|
||||
|
||||
int terrain = _ai->getTerrain(xCoord, yCoord);
|
||||
assert(terrain == TERRAIN_TYPE_GOOD);
|
||||
|
||||
float pwr = _ai->getMinPower() * .3;
|
||||
float cosine = cos((static_cast<float>(angle) / 360) * (2 * M_PI));
|
||||
float sine = sin((static_cast<float>(angle) / 360) * (2 * M_PI));
|
||||
int xParam = (int)(xCoord + (pwr * cosine));
|
||||
int yParam = (int)(yCoord + (pwr * sine));
|
||||
|
||||
if (xParam < 0)
|
||||
xParam += _ai->getMaxX();
|
||||
else if (xParam > _ai->getMaxX())
|
||||
xParam -= _ai->getMaxX();
|
||||
|
||||
if (yParam < 0)
|
||||
yParam += _ai->getMaxY();
|
||||
else if (yParam > _ai->getMaxY())
|
||||
yParam -= _ai->getMaxY();
|
||||
|
||||
if (_ai->checkIfWaterState(xParam, yParam)) {
|
||||
delete retTraveller;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retTraveller->setPosY(yCoord);
|
||||
retTraveller->setPosX(xCoord);
|
||||
|
||||
// Iterate through the previous action list, making sure this one isn't on it
|
||||
for (Common::Array<int>::iterator i = (_ai->_lastXCoord[whoseTurn]).begin(), j = (_ai->_lastYCoord[whoseTurn]).begin(); i != (_ai->_lastXCoord[whoseTurn]).end(); i++, j++) {
|
||||
// Check if this shot is the same as the last time we tried
|
||||
if ((*i == retTraveller->getPosX()) && (*j == retTraveller->getPosY())) {
|
||||
retTraveller->setDisabled();
|
||||
delete retTraveller;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
retTraveller->setValueG(getG() + 7 + (dir * DIRECTION_WEIGHT));
|
||||
lastSuccessful = 1;
|
||||
} else {
|
||||
int yCoord = -coords / maxX;
|
||||
int xCoord = -coords - (yCoord * maxX);
|
||||
|
||||
// If landing fault is because of water, add 1 extra to g and turn on water flag. Also set coords, and adjust power to water fault location
|
||||
if (_ai->checkIfWaterState(xCoord, yCoord)) {
|
||||
int terrainSquareSize = _ai->getTerrainSquareSize();
|
||||
xCoord = ((xCoord / terrainSquareSize * terrainSquareSize) + (terrainSquareSize / 2));
|
||||
yCoord = ((yCoord / terrainSquareSize * terrainSquareSize) + (terrainSquareSize / 2));
|
||||
|
||||
int xDist = xCoord - _posX;
|
||||
int yDist = yCoord - _posY;
|
||||
retTraveller->setPosX((int)(xCoord + (terrainSquareSize * 1.414 * (xDist / (abs(xDist) + 1)))));
|
||||
retTraveller->setPosY((int)(yCoord + (terrainSquareSize * 1.414 * (yDist / (abs(yDist) + 1)))));
|
||||
|
||||
int closestHub = _ai->getClosestUnit(retTraveller->getPosX(), retTraveller->getPosY(), _ai->getMaxX(), _ai->getCurrentPlayer(), 1, BUILDING_MAIN_BASE, 1, 110);
|
||||
|
||||
retTraveller->setWaterSourceX(_ai->getHubX(closestHub));
|
||||
retTraveller->setWaterSourceY(_ai->getHubY(closestHub));
|
||||
retTraveller->setWaterDestX(retTraveller->getPosX());
|
||||
retTraveller->setWaterDestY(retTraveller->getPosY());
|
||||
|
||||
retTraveller->setPowerTo(power);
|
||||
retTraveller->setAngleTo(angle);
|
||||
|
||||
retTraveller->setValueG(getG() + 10 + (dir * DIRECTION_WEIGHT));
|
||||
retTraveller->enableWaterFlag();
|
||||
} else {
|
||||
// If not, set G to highest value
|
||||
retTraveller->setDisabled();
|
||||
delete retTraveller;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return retTraveller;
|
||||
}
|
||||
|
||||
int Traveller::checkSuccess() {
|
||||
if (_ai->getDistance(_posX + 1, _posY, _targetPosX, _targetPosY) < _maxDist)
|
||||
return SUCCESS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Traveller::calcT() {
|
||||
assert(!_disabled);
|
||||
|
||||
if (_disabled) return FAILURE;
|
||||
|
||||
return (checkSuccess() != SUCCESS) ? (getG() + calcH()) : SUCCESS;
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
122
engines/scumm/he/moonbase/ai_traveller.h
Normal file
122
engines/scumm/he/moonbase/ai_traveller.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_TRAVELER_H
|
||||
#define SCUMM_HE_MOONBASE_AI_TRAVELER_H
|
||||
|
||||
#include "scumm/he/moonbase/ai_node.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
const int NUM_TO_GEN = 9;
|
||||
|
||||
const int NUM_POWER_STEPS = 3;
|
||||
const double SIZE_POWER_STEP = .15;
|
||||
const int SIZE_ANGLE_STEP = 45;
|
||||
const int VARIATION_EXTENT = 3;
|
||||
const int DIRECTION_WEIGHT = 5;
|
||||
|
||||
class Traveller : public IContainedObject {
|
||||
private:
|
||||
static int _targetPosX;
|
||||
static int _targetPosY;
|
||||
static int _maxDist;
|
||||
|
||||
static int _numToGen;
|
||||
static int _sizeAngleStep;
|
||||
|
||||
int _sourceHub;
|
||||
|
||||
int _posX;
|
||||
int _posY;
|
||||
int _angleTo;
|
||||
int _powerTo;
|
||||
|
||||
int _disabled;
|
||||
int _waterFlag;
|
||||
int _waterSourceX;
|
||||
int _waterSourceY;
|
||||
int _waterDestX;
|
||||
int _waterDestY;
|
||||
|
||||
AI *_ai;
|
||||
|
||||
protected:
|
||||
float calcH() override;
|
||||
|
||||
public:
|
||||
Traveller(AI *ai);
|
||||
Traveller(int originX, int originY, AI *ai);
|
||||
~Traveller() override {}
|
||||
|
||||
IContainedObject *duplicate() override { return this; }
|
||||
|
||||
static void setTargetPosX(int posX) { _targetPosX = posX; }
|
||||
static void setTargetPosY(int posY) { _targetPosY = posY; }
|
||||
static void setMaxDist(int maxDist) { _maxDist = maxDist; }
|
||||
|
||||
void setSourceHub(int sourceHub) { _sourceHub = sourceHub; }
|
||||
|
||||
void setPosX(int posX) { _posX = posX; }
|
||||
void setPosY(int posY) { _posY = posY; }
|
||||
void setAngleTo(int angleTo) { _angleTo = angleTo; }
|
||||
void setPowerTo(int powerTo) { _powerTo = powerTo; }
|
||||
|
||||
void setWaterSourceX(int waterSourceX) { _waterSourceX = waterSourceX; }
|
||||
void setWaterSourceY(int waterSourceY) { _waterSourceY = waterSourceY; }
|
||||
|
||||
void setWaterDestX(int waterDestX) { _waterDestX = waterDestX; }
|
||||
void setWaterDestY(int waterDestY) { _waterDestY = waterDestY; }
|
||||
|
||||
int getSourceHub() const { return _sourceHub; }
|
||||
|
||||
int getPosX() const { return _posX; }
|
||||
int getPosY() const { return _posY; }
|
||||
int getAngleTo() const { return _angleTo; }
|
||||
int getPowerTo() const { return _powerTo; }
|
||||
|
||||
int getWaterSourceX() const { return _waterSourceX; }
|
||||
int getWaterSourceY() const { return _waterSourceY; }
|
||||
int getWaterDestX() const { return _waterDestX; }
|
||||
int getWaterDestY() const { return _waterDestY; }
|
||||
|
||||
void setDisabled() { _disabled = 1; }
|
||||
void unsetDisabled() { _disabled = 0; }
|
||||
int getDisabled() { return _disabled; }
|
||||
|
||||
void adjustPosX(int offsetX);
|
||||
void adjustPosY(int offsetY);
|
||||
void adjustXY(int offsetX, int offsetY);
|
||||
|
||||
void enableWaterFlag() { _waterFlag = 1; }
|
||||
void disableWaterFlag() { _waterFlag = 0; }
|
||||
int getWaterFlag() const { return _waterFlag; }
|
||||
|
||||
int numChildrenToGen() override;
|
||||
IContainedObject *createChildObj(int, int &) override;
|
||||
|
||||
int checkSuccess() override;
|
||||
float calcT() override;
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
244
engines/scumm/he/moonbase/ai_tree.cpp
Normal file
244
engines/scumm/he/moonbase/ai_tree.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scumm/he/intern_he.h"
|
||||
|
||||
#include "scumm/he/moonbase/moonbase.h"
|
||||
#include "scumm/he/moonbase/ai_tree.h"
|
||||
#include "scumm/he/moonbase/ai_main.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
static int compareTreeNodes(const void *a, const void *b) {
|
||||
if (((const TreeNode *)a)->value < ((const TreeNode *)b)->value)
|
||||
return -1;
|
||||
else if (((const TreeNode *)a)->value > ((const TreeNode *)b)->value)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Tree::Tree(AI *ai) : _ai(ai) {
|
||||
pBaseNode = new Node;
|
||||
_maxDepth = MAX_DEPTH;
|
||||
_maxNodes = MAX_NODES;
|
||||
_currentNode = nullptr;
|
||||
_currentChildIndex = 0;
|
||||
|
||||
_currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
|
||||
}
|
||||
|
||||
Tree::Tree(IContainedObject *contents, AI *ai) : _ai(ai) {
|
||||
pBaseNode = new Node;
|
||||
pBaseNode->setContainedObject(contents);
|
||||
_maxDepth = MAX_DEPTH;
|
||||
_maxNodes = MAX_NODES;
|
||||
_currentNode = nullptr;
|
||||
_currentChildIndex = 0;
|
||||
|
||||
_currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
|
||||
}
|
||||
|
||||
Tree::Tree(IContainedObject *contents, int maxDepth, AI *ai) : _ai(ai) {
|
||||
pBaseNode = new Node;
|
||||
pBaseNode->setContainedObject(contents);
|
||||
_maxDepth = maxDepth;
|
||||
_maxNodes = MAX_NODES;
|
||||
_currentNode = nullptr;
|
||||
_currentChildIndex = 0;
|
||||
|
||||
_currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
|
||||
}
|
||||
|
||||
Tree::Tree(IContainedObject *contents, int maxDepth, int maxNodes, AI *ai) : _ai(ai) {
|
||||
pBaseNode = new Node;
|
||||
pBaseNode->setContainedObject(contents);
|
||||
_maxDepth = maxDepth;
|
||||
_maxNodes = maxNodes;
|
||||
_currentNode = nullptr;
|
||||
_currentChildIndex = 0;
|
||||
|
||||
_currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
|
||||
}
|
||||
|
||||
void Tree::duplicateTree(Node *sourceNode, Node *destNode) {
|
||||
Common::Array<Node *> vUnvisited = sourceNode->getChildren();
|
||||
|
||||
while (vUnvisited.size()) {
|
||||
Node *newNode = new Node(*(vUnvisited.end()));
|
||||
newNode->setParent(destNode);
|
||||
(destNode->getChildren()).push_back(newNode);
|
||||
duplicateTree(*(vUnvisited.end()), newNode);
|
||||
vUnvisited.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
Tree::Tree(const Tree *sourceTree, AI *ai) : _ai(ai) {
|
||||
pBaseNode = new Node(sourceTree->getBaseNode());
|
||||
_maxDepth = sourceTree->getMaxDepth();
|
||||
_maxNodes = sourceTree->getMaxNodes();
|
||||
_currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
|
||||
_currentNode = nullptr;
|
||||
_currentChildIndex = 0;
|
||||
|
||||
duplicateTree(sourceTree->getBaseNode(), pBaseNode);
|
||||
}
|
||||
|
||||
Tree::~Tree() {
|
||||
// Delete all nodes
|
||||
Node *pNodeItr = pBaseNode;
|
||||
|
||||
// Depth first traversal of nodes to delete them
|
||||
while (pNodeItr != nullptr) {
|
||||
// If any children are left, move to one of them
|
||||
if (!(pNodeItr->getChildren().empty())) {
|
||||
pNodeItr = pNodeItr->popChild();
|
||||
} else {
|
||||
// Delete this node, and move up to the parent for further processing
|
||||
Node *pTemp = pNodeItr;
|
||||
pNodeItr = pNodeItr->getParent();
|
||||
delete pTemp;
|
||||
pTemp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
delete _currentMap;
|
||||
}
|
||||
|
||||
Node *Tree::aStarSearch() {
|
||||
Common::SortedArray<TreeNode *> mmfpOpen(compareTreeNodes);
|
||||
|
||||
Node *currentNode = nullptr;
|
||||
float currentT;
|
||||
|
||||
Node *retNode = nullptr;
|
||||
|
||||
float temp = pBaseNode->getContainedObject()->calcT();
|
||||
|
||||
if (static_cast<int>(temp) != SUCCESS) {
|
||||
mmfpOpen.insert(new TreeNode(pBaseNode->getObjectT(), pBaseNode));
|
||||
|
||||
while (mmfpOpen.size() && (retNode == nullptr)) {
|
||||
currentNode = mmfpOpen.front()->node;
|
||||
mmfpOpen.erase(mmfpOpen.begin());
|
||||
|
||||
if ((currentNode->getDepth() < _maxDepth) && (Node::getNodeCount() < _maxNodes)) {
|
||||
// Generate nodes
|
||||
Common::Array<Node *> vChildren = currentNode->getChildren();
|
||||
|
||||
for (Common::Array<Node *>::iterator i = vChildren.begin(); i != vChildren.end(); i++) {
|
||||
IContainedObject *pTemp = (*i)->getContainedObject();
|
||||
currentT = pTemp->calcT();
|
||||
|
||||
if (currentT == SUCCESS)
|
||||
retNode = *i;
|
||||
else
|
||||
mmfpOpen.insert(new TreeNode(currentT, (*i)));
|
||||
}
|
||||
} else {
|
||||
retNode = currentNode;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
retNode = pBaseNode;
|
||||
}
|
||||
|
||||
return retNode;
|
||||
}
|
||||
|
||||
|
||||
Node *Tree::aStarSearch_singlePassInit() {
|
||||
Node *retNode = nullptr;
|
||||
|
||||
_currentChildIndex = 1;
|
||||
|
||||
float temp = pBaseNode->getContainedObject()->calcT();
|
||||
|
||||
if (static_cast<int>(temp) != SUCCESS) {
|
||||
_currentMap->insert(new TreeNode(pBaseNode->getObjectT(), pBaseNode));
|
||||
} else {
|
||||
retNode = pBaseNode;
|
||||
}
|
||||
|
||||
return retNode;
|
||||
}
|
||||
|
||||
Node *Tree::aStarSearch_singlePass() {
|
||||
float currentT = 0.0;
|
||||
Node *retNode = nullptr;
|
||||
|
||||
static int maxTime = 0;
|
||||
|
||||
if (_currentChildIndex == 1) {
|
||||
maxTime = _ai->getPlayerMaxTime();
|
||||
}
|
||||
|
||||
if (_currentChildIndex) {
|
||||
if (!(_currentMap->size())) {
|
||||
retNode = _currentNode;
|
||||
return retNode;
|
||||
}
|
||||
|
||||
_currentNode = _currentMap->front()->node;
|
||||
_currentMap->erase(_currentMap->begin());
|
||||
}
|
||||
|
||||
if ((_currentNode->getDepth() < _maxDepth) && (Node::getNodeCount() < _maxNodes) && ((!maxTime) || (_ai->getTimerValue(3) < maxTime))) {
|
||||
// Generate nodes
|
||||
_currentChildIndex = _currentNode->generateChildren();
|
||||
|
||||
if (_currentChildIndex) {
|
||||
Common::Array<Node *> vChildren = _currentNode->getChildren();
|
||||
|
||||
if (!vChildren.size() && !_currentMap->size()) {
|
||||
_currentChildIndex = 0;
|
||||
retNode = _currentNode;
|
||||
}
|
||||
|
||||
for (Common::Array<Node *>::iterator i = vChildren.begin(); i != vChildren.end(); i++) {
|
||||
IContainedObject *pTemp = (*i)->getContainedObject();
|
||||
currentT = pTemp->calcT();
|
||||
|
||||
if (currentT == SUCCESS) {
|
||||
retNode = *i;
|
||||
i = vChildren.end() - 1;
|
||||
} else {
|
||||
_currentMap->insert(new TreeNode(currentT, (*i)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!(_currentMap->size()) && (currentT != SUCCESS)) {
|
||||
assert(_currentNode != nullptr);
|
||||
retNode = _currentNode;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
retNode = _currentNode;
|
||||
}
|
||||
|
||||
return retNode;
|
||||
}
|
||||
|
||||
int Tree::IsBaseNode(Node *thisNode) {
|
||||
return (thisNode == pBaseNode);
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
83
engines/scumm/he/moonbase/ai_tree.h
Normal file
83
engines/scumm/he/moonbase/ai_tree.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_TREE_H
|
||||
#define SCUMM_HE_MOONBASE_AI_TREE_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "scumm/he/moonbase/ai_node.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
const int MAX_DEPTH = 100;
|
||||
const int MAX_NODES = 1000000;
|
||||
|
||||
class AI;
|
||||
|
||||
struct TreeNode {
|
||||
float value;
|
||||
Node *node;
|
||||
|
||||
TreeNode(float v, Node *n) { value = v; node = n; }
|
||||
};
|
||||
|
||||
class Tree {
|
||||
private:
|
||||
Node *pBaseNode;
|
||||
|
||||
int _maxDepth;
|
||||
int _maxNodes;
|
||||
|
||||
int _currentChildIndex;
|
||||
|
||||
Common::SortedArray<TreeNode *> *_currentMap;
|
||||
Node *_currentNode;
|
||||
|
||||
AI *_ai;
|
||||
|
||||
public:
|
||||
Tree(AI *ai);
|
||||
Tree(IContainedObject *contents, AI *ai);
|
||||
Tree(IContainedObject *contents, int maxDepth, AI *ai);
|
||||
Tree(IContainedObject *contents, int maxDepth, int maxNodes, AI *ai);
|
||||
Tree(const Tree *sourceTree, AI *ai);
|
||||
~Tree();
|
||||
|
||||
void duplicateTree(Node *sourceNode, Node *destNode);
|
||||
|
||||
Node *getBaseNode() const { return pBaseNode; }
|
||||
void setMaxDepth(int maxDepth) { _maxDepth = maxDepth; }
|
||||
int getMaxDepth() const { return _maxDepth; }
|
||||
|
||||
void setMaxNodes(int maxNodes) { _maxNodes = maxNodes; }
|
||||
int getMaxNodes() const { return _maxNodes; }
|
||||
|
||||
Node *aStarSearch();
|
||||
|
||||
Node *aStarSearch_singlePassInit();
|
||||
Node *aStarSearch_singlePass();
|
||||
|
||||
int IsBaseNode(Node *thisNode);
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
176
engines/scumm/he/moonbase/ai_types.cpp
Normal file
176
engines/scumm/he/moonbase/ai_types.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/textconsole.h"
|
||||
#include "scumm/scumm.h"
|
||||
#include "scumm/he/moonbase/ai_types.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
AIEntity::AIEntity(int id) {
|
||||
switch (id) {
|
||||
default:
|
||||
case BRUTAKAS:
|
||||
debugC(DEBUG_MOONBASE_AI, "BRUTAKAS");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "BRUTAKAS", 64);
|
||||
_behaviorVariation = AI_VAR_SMALL;
|
||||
_targetVariation = AI_VAR_SMALL;
|
||||
_angleVariation = AI_VAR_SMALL;
|
||||
_powerVariation = AI_VAR_SMALL;
|
||||
break;
|
||||
|
||||
case AGI:
|
||||
debugC(DEBUG_MOONBASE_AI, "Agi");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "Agi", 64);
|
||||
_behaviorVariation = AI_VAR_SMALL;
|
||||
_targetVariation = AI_VAR_MEDIUM;
|
||||
_angleVariation = AI_VAR_MEDIUM;
|
||||
_powerVariation = AI_VAR_LARGE;
|
||||
break;
|
||||
|
||||
case EL_GATO:
|
||||
debugC(DEBUG_MOONBASE_AI, "El Gato de la Noche");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "El Gato de la Noche", 64);
|
||||
_behaviorVariation = AI_VAR_SMALL;
|
||||
_targetVariation = AI_VAR_SMALL;
|
||||
_angleVariation = AI_VAR_SMALL;
|
||||
_powerVariation = AI_VAR_MEDIUM;
|
||||
break;
|
||||
|
||||
case PIXELAHT:
|
||||
debugC(DEBUG_MOONBASE_AI, "Pixelaht");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "Pixelaht", 64);
|
||||
_behaviorVariation = AI_VAR_SMALL;
|
||||
_targetVariation = AI_VAR_LARGE;
|
||||
_angleVariation = AI_VAR_MEDIUM;
|
||||
_powerVariation = AI_VAR_SMALL;
|
||||
break;
|
||||
|
||||
case CYBALL:
|
||||
debugC(DEBUG_MOONBASE_AI, "cYbaLL");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "cYbaLL", 64);
|
||||
_behaviorVariation = AI_VAR_LARGE;
|
||||
_targetVariation = AI_VAR_LARGE;
|
||||
_angleVariation = AI_VAR_SMALL;
|
||||
_powerVariation = AI_VAR_SMALL;
|
||||
break;
|
||||
|
||||
case NEEP:
|
||||
debugC(DEBUG_MOONBASE_AI, "Neep! Neep!");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "Neep! Neep!", 64);
|
||||
_behaviorVariation = AI_VAR_MEDIUM;
|
||||
_targetVariation = AI_VAR_SMALL;
|
||||
_angleVariation = AI_VAR_SMALL;
|
||||
_powerVariation = AI_VAR_LARGE;
|
||||
break;
|
||||
|
||||
case WARCUPINE:
|
||||
debugC(DEBUG_MOONBASE_AI, "WARcupine");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "WARcupine", 64);
|
||||
_behaviorVariation = AI_VAR_SMALL;
|
||||
_targetVariation = AI_VAR_SMALL;
|
||||
_angleVariation = AI_VAR_LARGE;
|
||||
_powerVariation = AI_VAR_MEDIUM;
|
||||
break;
|
||||
|
||||
case AONE:
|
||||
debugC(DEBUG_MOONBASE_AI, "aone");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "aone", 64);
|
||||
_behaviorVariation = AI_VAR_MEDIUM;
|
||||
_targetVariation = AI_VAR_MEDIUM;
|
||||
_angleVariation = AI_VAR_MEDIUM;
|
||||
_powerVariation = AI_VAR_MEDIUM;
|
||||
break;
|
||||
|
||||
case SPANDO:
|
||||
debugC(DEBUG_MOONBASE_AI, "S p a n d o");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "S p a n d o", 64);
|
||||
_behaviorVariation = AI_VAR_LARGE;
|
||||
_targetVariation = AI_VAR_LARGE;
|
||||
_angleVariation = AI_VAR_SMALL;
|
||||
_powerVariation = AI_VAR_SMALL;
|
||||
break;
|
||||
|
||||
case ORBNU_LUNATEK:
|
||||
debugC(DEBUG_MOONBASE_AI, "Bonur J Lunatek");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "Bonur J Lunatek", 64);
|
||||
_behaviorVariation = AI_VAR_HUGE;
|
||||
_targetVariation = AI_VAR_HUGE;
|
||||
_angleVariation = AI_VAR_HUGE;
|
||||
_powerVariation = AI_VAR_HUGE;
|
||||
break;
|
||||
|
||||
case CRAWLER_CHUCKER:
|
||||
debugC(DEBUG_MOONBASE_AI, "Le Chuckre des Crawlres");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "Le Chuckre des Crawlres", 64);
|
||||
_behaviorVariation = AI_VAR_SMALL;
|
||||
_targetVariation = AI_VAR_MEDIUM;
|
||||
_angleVariation = AI_VAR_MEDIUM;
|
||||
_powerVariation = AI_VAR_LARGE;
|
||||
break;
|
||||
|
||||
case ENERGY_HOG:
|
||||
debugC(DEBUG_MOONBASE_AI, "Energy Hog");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "Energy Hog\n", 64);
|
||||
_behaviorVariation = AI_VAR_SMALL;
|
||||
_targetVariation = AI_VAR_SMALL;
|
||||
_angleVariation = AI_VAR_SMALL;
|
||||
_powerVariation = AI_VAR_SMALL;
|
||||
break;
|
||||
|
||||
case RANGER:
|
||||
debugC(DEBUG_MOONBASE_AI, "Ranger");
|
||||
_id = id;
|
||||
_nameString = new char[64];
|
||||
Common::strlcpy(_nameString, "Ranger\n", 64);
|
||||
_behaviorVariation = AI_VAR_SMALL;
|
||||
_targetVariation = AI_VAR_SMALL;
|
||||
_angleVariation = AI_VAR_SMALL;
|
||||
_powerVariation = AI_VAR_SMALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
96
engines/scumm/he/moonbase/ai_types.h
Normal file
96
engines/scumm/he/moonbase/ai_types.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_TYPES_H
|
||||
#define SCUMM_HE_MOONBASE_AI_TYPES_H
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
enum {
|
||||
AGI = 1,
|
||||
AONE = 2,
|
||||
BRUTAKAS = 3,
|
||||
CYBALL = 4,
|
||||
EL_GATO = 5,
|
||||
NEEP = 6,
|
||||
ORBNU_LUNATEK = 7,
|
||||
PIXELAHT = 8,
|
||||
SPANDO = 9,
|
||||
WARCUPINE = 10
|
||||
};
|
||||
|
||||
enum {
|
||||
CRAWLER_CHUCKER = 11,
|
||||
ENERGY_HOG = 12,
|
||||
RANGER = 13
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_VAR_NONE = -1,
|
||||
AI_VAR_SMALL = 0,
|
||||
AI_VAR_MEDIUM = 1,
|
||||
AI_VAR_LARGE = 2,
|
||||
AI_VAR_HUGE = 5
|
||||
};
|
||||
|
||||
enum {
|
||||
AI_VAR_BASE_BEHAVIOR = 10,
|
||||
AI_VAR_BASE_TARGET = 10,
|
||||
AI_VAR_BASE_ANGLE = 2,
|
||||
AI_VAR_BASE_POWER = 5
|
||||
};
|
||||
|
||||
class AIEntity {
|
||||
private:
|
||||
int _id;
|
||||
char *_nameString;
|
||||
int _behaviorVariation;
|
||||
int _targetVariation;
|
||||
int _angleVariation;
|
||||
int _powerVariation;
|
||||
|
||||
public:
|
||||
AIEntity(int id);
|
||||
~AIEntity() {
|
||||
if (_nameString) {
|
||||
delete[] _nameString;
|
||||
_nameString = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int getID() const { return _id; }
|
||||
char *getNameString() const { return _nameString; }
|
||||
int getBehaviorVariation() const { return _behaviorVariation; }
|
||||
int getTargetVariation() const { return _targetVariation; }
|
||||
int getAngleVariation() const { return _angleVariation; }
|
||||
int getPowerVariation() const { return _powerVariation; }
|
||||
|
||||
void setID(int id) { _id = id; }
|
||||
void setNameString(char *nameString) { _nameString = nameString; }
|
||||
void setBehaviorVariation(int behaviorVariation) { _behaviorVariation = behaviorVariation; }
|
||||
void setTargetVariation(int targetVariation) { _targetVariation = targetVariation; }
|
||||
void setAngleVariation(int angleVariation) { _angleVariation = angleVariation; }
|
||||
void setPowerVariation(int powerVariation) { _powerVariation = powerVariation; }
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
87
engines/scumm/he/moonbase/ai_weapon.cpp
Normal file
87
engines/scumm/he/moonbase/ai_weapon.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scumm/he/moonbase/ai_weapon.h"
|
||||
#include "scumm/he/moonbase/ai_main.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
Weapon::Weapon(int typeID) { //, float damage, int radius)
|
||||
switch (typeID) {
|
||||
default:
|
||||
case ITEM_BOMB:
|
||||
becomeBomb();
|
||||
break;
|
||||
|
||||
case ITEM_CLUSTER:
|
||||
becomeCluster();
|
||||
break;
|
||||
|
||||
case ITEM_CRAWLER:
|
||||
becomeCrawler();
|
||||
break;
|
||||
|
||||
case ITEM_EMP:
|
||||
becomeEMP();
|
||||
break;
|
||||
|
||||
case ITEM_SPIKE:
|
||||
becomeSpike();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Weapon::becomeBomb() {
|
||||
_typeID = ITEM_BOMB;
|
||||
_damage = 3;
|
||||
_radius = 30;
|
||||
_cost = 1;
|
||||
}
|
||||
|
||||
void Weapon::becomeCluster() {
|
||||
_typeID = ITEM_CLUSTER;
|
||||
_damage = 1.5;
|
||||
_radius = 20;
|
||||
_cost = 1;
|
||||
}
|
||||
|
||||
void Weapon::becomeCrawler() {
|
||||
_typeID = ITEM_CRAWLER;
|
||||
_damage = 4;
|
||||
_radius = 180;
|
||||
_cost = 7;
|
||||
}
|
||||
|
||||
void Weapon::becomeEMP() {
|
||||
_typeID = ITEM_EMP;
|
||||
_damage = .1f;
|
||||
_radius = 215;
|
||||
_cost = 3;
|
||||
}
|
||||
|
||||
void Weapon::becomeSpike() {
|
||||
_typeID = ITEM_SPIKE;
|
||||
_damage = 6;
|
||||
_radius = 180;
|
||||
_cost = 3;
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
57
engines/scumm/he/moonbase/ai_weapon.h
Normal file
57
engines/scumm/he/moonbase/ai_weapon.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_AI_WEAPON_H
|
||||
#define SCUMM_HE_MOONBASE_AI_WEAPON_H
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class Weapon {
|
||||
int _typeID = 0;
|
||||
float _damage = 0.0f;
|
||||
int _radius = 0;
|
||||
int _cost = 0;
|
||||
|
||||
public:
|
||||
Weapon() {}
|
||||
Weapon(int typeID);
|
||||
virtual ~Weapon() {}
|
||||
|
||||
void setTypeID(int typeID) { _typeID = typeID; }
|
||||
void setDamage(float damage) { _damage = damage; }
|
||||
void setRadius(int radius) { _radius = radius; }
|
||||
void setCost(int cost) { _cost = cost; }
|
||||
|
||||
int getTypeID() { return _typeID; }
|
||||
float getDamage() { return _damage; }
|
||||
int getRadius() { return _radius; }
|
||||
int getCost() { return _cost; }
|
||||
|
||||
void becomeBomb();
|
||||
void becomeCluster();
|
||||
void becomeCrawler();
|
||||
void becomeEMP();
|
||||
void becomeSpike();
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
377
engines/scumm/he/moonbase/dialog-mapgenerator.cpp
Normal file
377
engines/scumm/he/moonbase/dialog-mapgenerator.cpp
Normal file
@@ -0,0 +1,377 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "scumm/he/moonbase/map_main.h"
|
||||
#include "scumm/he/moonbase/dialog-mapgenerator.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
enum {
|
||||
kAlgorCmd = 'ALGR',
|
||||
kAlgorRandCmd = 'ALRM',
|
||||
|
||||
kSizeCmd = 'SIZE',
|
||||
kSizeRandCmd = 'SZRM',
|
||||
|
||||
kTileCmd = 'TILE',
|
||||
kTileRandCmd = 'TLRM',
|
||||
|
||||
kEnergyCmd = 'ENGY',
|
||||
kEnergyRandCmd = 'EGRM',
|
||||
|
||||
kTerrainCmd = 'TRIN',
|
||||
kTerrainRandCmd = 'TRRM',
|
||||
|
||||
kWaterCmd = 'WTER',
|
||||
kWaterRandCmd = 'WTRM',
|
||||
|
||||
kCancelCmd = 'CNCL',
|
||||
kGenerateCmd = 'GNRT'
|
||||
};
|
||||
|
||||
MapGeneratorDialog::MapGeneratorDialog(bool demo) : Dialog("MapGenerator"), _refreshing(false) {
|
||||
// I18N: Random map generator for Moonbase Commander
|
||||
_dialogTitle = new GUI::StaticTextWidget(this, "MapGenerator.Title", _("Random Map Options"));
|
||||
_dialogTitle->setAlign(Graphics::kTextAlignCenter);
|
||||
|
||||
// I18N: Map generator algorithms
|
||||
_algorDesc = new GUI::StaticTextWidget(this, "MapGenerator.Algorithm", _("Algorithm"));
|
||||
_algorDesc->setAlign(Graphics::kTextAlignLeft);
|
||||
_algorGroup = new GUI::RadiobuttonGroup(this, kAlgorCmd);
|
||||
// I18N: Spiff algorithm
|
||||
_algorSpiff = new GUI::RadiobuttonWidget(this, "MapGenerator.AlgorithmSpiff", _algorGroup, SPIFF_GEN, _("Spiff"));
|
||||
// I18N: Katton algorithm
|
||||
_algorSpiff = new GUI::RadiobuttonWidget(this, "MapGenerator.AlgorithmKatton", _algorGroup, KATTON_GEN, _("Katton"));
|
||||
// I18N: Random algorithm
|
||||
_algorRandom = new GUI::CheckboxWidget(this, "MapGenerator.AlgorithmRandom", _("Random"), _("Picks the map algorithm randomly."), kAlgorRandCmd);
|
||||
|
||||
// I18N: Map sizes
|
||||
_sizeDesc = new GUI::StaticTextWidget(this, "MapGenerator.Size", _("Size"));
|
||||
_sizeDesc->setAlign(Graphics::kTextAlignCenter);
|
||||
|
||||
_sizeGroup = new GUI::RadiobuttonGroup(this, kSizeCmd);
|
||||
_sizeSmall = new GUI::RadiobuttonWidget(this, "MapGenerator.SizeSmall", _sizeGroup, 4, _("Small"));
|
||||
_sizeMedium = new GUI::RadiobuttonWidget(this, "MapGenerator.SizeMedium", _sizeGroup, 5, _("Medium"));
|
||||
_sizeLarge = new GUI::RadiobuttonWidget(this, "MapGenerator.SizeLarge", _sizeGroup, 6, _("Large"));
|
||||
_sizeHuge = new GUI::RadiobuttonWidget(this, "MapGenerator.SizeHuge", _sizeGroup, 7, _("Huge"));
|
||||
_sizeSAI = new GUI::RadiobuttonWidget(this, "MapGenerator.SizeSAI", _sizeGroup, 8, _("SAI"));
|
||||
_sizeRidiculous = new GUI::RadiobuttonWidget(this, "MapGenerator.SizeRidiculous", _sizeGroup, 9, _("Ridiculous"));
|
||||
_sizeMax = new GUI::RadiobuttonWidget(this, "MapGenerator.SizeMax", _sizeGroup, 10, _("Max"));
|
||||
// I18N: Random map size
|
||||
_sizeRandom = new GUI::CheckboxWidget(this, "MapGenerator.SizeRandom", _("Random"), _("Picks the map size randomly."), kSizeRandCmd);
|
||||
|
||||
// I18N: Map tile sets
|
||||
_tileDesc = new GUI::StaticTextWidget(this, "MapGenerator.Tileset", _("Tileset"));
|
||||
_tileDesc->setAlign(Graphics::kTextAlignCenter);
|
||||
_tileGroup = new GUI::RadiobuttonGroup(this, kTileCmd);
|
||||
_tileTerrandra = new GUI::RadiobuttonWidget(this, "MapGenerator.TilesetTerrandra", _tileGroup, 1, Common::U32String("Terrandra"));
|
||||
_tileZanateros = new GUI::RadiobuttonWidget(this, "MapGenerator.TilesetZanateros", _tileGroup, 2, Common::U32String("Zanateros"));
|
||||
// Demo version of the game only has tilesets 1, 2, 4 and 6. Don't create buttons for
|
||||
// missing tiles.
|
||||
if (!demo)
|
||||
_tileDrijim = new GUI::RadiobuttonWidget(this, "MapGenerator.TilesetDaijim", _tileGroup, 3, Common::U32String("Daijim 3"));
|
||||
_tileKyanite = new GUI::RadiobuttonWidget(this, "MapGenerator.TilesetKyanite", _tileGroup, 4, Common::U32String("Kyanite"));
|
||||
if (!demo)
|
||||
_tileEmerau = new GUI::RadiobuttonWidget(this, "MapGenerator.TilesetEmerau", _tileGroup, 5, Common::U32String("Emerau Glyph"));
|
||||
_tileAblation = new GUI::RadiobuttonWidget(this, "MapGenerator.TilesetAblation", _tileGroup, 6, Common::U32String("Ablation Land"));
|
||||
// I18N: Random tileset
|
||||
_tileRandom = new GUI::CheckboxWidget(this, "MapGenerator.TilesetRandom", _("Random"), _("Picks the map tileset randomly."), kTileRandCmd);
|
||||
|
||||
// I18N: Percentage of energy pools
|
||||
_energyDesc = new GUI::StaticTextWidget(this, "MapGenerator.Energy", _("Energy"));
|
||||
_energyDesc->setAlign(Graphics::kTextAlignCenter);
|
||||
_energySlider = new GUI::SliderWidget(this, "MapGenerator.EnergySlider", Common::U32String(), kEnergyCmd);
|
||||
_energySlider->setMinValue(0); _energySlider->setMaxValue(6);
|
||||
// I18N: Energy slider label
|
||||
_energyLabel = new GUI::StaticTextWidget(this, "MapGenerator.EnergySliderLabel", _("Scarce - Lots"), Common::U32String());
|
||||
_energyLabel->setAlign(Graphics::kTextAlignCenter);
|
||||
|
||||
|
||||
// I18N: Random percentage of energy pools
|
||||
_energyRandom = new GUI::CheckboxWidget(this, "MapGenerator.EnergyRandom", _("Random"), _("Picks the random amount of energy pools."), kEnergyRandCmd);
|
||||
|
||||
// I18N: Percentage of terrain
|
||||
_terrainDesc = new GUI::StaticTextWidget(this, "MapGenerator.Terrain", _("Terrain"));
|
||||
_terrainDesc->setAlign(Graphics::kTextAlignCenter);
|
||||
_terrainSlider = new GUI::SliderWidget(this, "MapGenerator.TerrainSlider", Common::U32String(), kTerrainCmd);
|
||||
_terrainSlider->setMinValue(0); _terrainSlider->setMaxValue(6);
|
||||
// I18N: Terrain slider label
|
||||
_terrainLabel = new GUI::StaticTextWidget(this, "MapGenerator.TerrainSliderLabel", _("Barren - Rough"), Common::U32String());
|
||||
_terrainLabel->setAlign(Graphics::kTextAlignCenter);
|
||||
|
||||
// I18N: Random percentage of terrain
|
||||
_terrainRandom = new GUI::CheckboxWidget(this, "MapGenerator.TerrainRandom", _("Random"), _("Picks the random amount of terrain level."), kTerrainRandCmd);
|
||||
|
||||
// I18N: Percentage of water
|
||||
_waterDesc = new GUI::StaticTextWidget(this, "MapGenerator.Water", _("Water"));
|
||||
_waterDesc->setAlign(Graphics::kTextAlignCenter);
|
||||
_waterSlider = new GUI::SliderWidget(this, "MapGenerator.WaterSlider", Common::U32String(), kWaterCmd);
|
||||
_waterSlider->setMinValue(0); _waterSlider->setMaxValue(6);
|
||||
// I18N: Water slider label
|
||||
_waterLabel = new GUI::StaticTextWidget(this, "MapGenerator.WaterSliderLabel", _("Driest - Wettest"), Common::U32String());
|
||||
_waterLabel->setAlign(Graphics::kTextAlignCenter);
|
||||
|
||||
// I18N: Random percentage of water
|
||||
_waterRandom = new GUI::CheckboxWidget(this, "MapGenerator.WaterRandom", _("Random"), _("Picks the random amount of water."), kWaterRandCmd);
|
||||
|
||||
_cancelButton = new GUI::ButtonWidget(this, "MapGenerator.Cancel", _("Cancel"), Common::U32String(), kCancelCmd);
|
||||
// I18N: Generate new map
|
||||
_generateButton = new GUI::ButtonWidget(this, "MapGenerator.Generate", _("Generate"), Common::U32String(), kGenerateCmd);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void MapGeneratorDialog::refresh() {
|
||||
_refreshing = true;
|
||||
|
||||
// ALGORITHM
|
||||
bool randomAlgorithm = true;
|
||||
if (ConfMan.hasKey("map_algorithm"))
|
||||
randomAlgorithm = ConfMan.getInt("map_algorithm") == 0;
|
||||
|
||||
_algorGroup->setEnabled(!randomAlgorithm);
|
||||
_algorRandom->setState(randomAlgorithm);
|
||||
|
||||
if (!randomAlgorithm)
|
||||
_algorGroup->setValue(ConfMan.getInt("map_algorithm"));
|
||||
|
||||
// SIZE
|
||||
bool randomSize = true;
|
||||
if (ConfMan.hasKey("map_size"))
|
||||
randomSize = ConfMan.getInt("map_size") == 0;
|
||||
|
||||
_sizeGroup->setEnabled(!randomSize);
|
||||
_sizeRandom->setState(randomSize);
|
||||
|
||||
if (!randomSize)
|
||||
_sizeGroup->setValue(ConfMan.getInt("map_size"));
|
||||
|
||||
// TILESET
|
||||
bool randomTileset = true;
|
||||
if (ConfMan.hasKey("map_tileset"))
|
||||
randomTileset = ConfMan.getInt("map_tileset") == 0;
|
||||
|
||||
_tileGroup->setEnabled(!randomTileset);
|
||||
_tileRandom->setState(randomTileset);
|
||||
|
||||
if (!randomTileset)
|
||||
_tileGroup->setValue(ConfMan.getInt("map_tileset"));
|
||||
|
||||
// ENERGY
|
||||
bool randomEnergy = true;
|
||||
if (ConfMan.hasKey("map_energy"))
|
||||
randomEnergy = ConfMan.getInt("map_energy") == -1;
|
||||
|
||||
_energySlider->setEnabled(!randomEnergy);
|
||||
_energyRandom->setState(randomEnergy);
|
||||
|
||||
if (!randomEnergy)
|
||||
_energySlider->setValue(ConfMan.getInt("map_energy"));
|
||||
else if (ConfMan.hasKey("prev_map_energy"))
|
||||
_energySlider->setValue(ConfMan.getInt("prev_map_energy"));
|
||||
else
|
||||
_energySlider->setValue(3);
|
||||
|
||||
// TERRAIN
|
||||
bool randomTerrain = true;
|
||||
if (ConfMan.hasKey("map_terrain"))
|
||||
randomTerrain = ConfMan.getInt("map_terrain") == -1;
|
||||
|
||||
_terrainSlider->setEnabled(!randomTerrain);
|
||||
_terrainRandom->setState(randomTerrain);
|
||||
|
||||
if (!randomTerrain)
|
||||
_terrainSlider->setValue(ConfMan.getInt("map_terrain"));
|
||||
else if (ConfMan.hasKey("prev_map_terrain"))
|
||||
_terrainSlider->setValue(ConfMan.getInt("prev_map_terrain"));
|
||||
else
|
||||
_terrainSlider->setValue(3);
|
||||
|
||||
|
||||
// WATER
|
||||
bool randomWater = true;
|
||||
if (ConfMan.hasKey("map_water"))
|
||||
randomWater = ConfMan.getInt("map_water") == -1;
|
||||
|
||||
_waterSlider->setEnabled(!randomWater);
|
||||
_waterRandom->setState(randomWater);
|
||||
|
||||
if (!randomWater)
|
||||
_waterSlider->setValue(ConfMan.getInt("map_water"));
|
||||
else if (ConfMan.hasKey("prev_map_water"))
|
||||
_waterSlider->setValue(ConfMan.getInt("prev_map_water"));
|
||||
else
|
||||
_waterSlider->setValue(3);
|
||||
|
||||
drawDialog(GUI::kDrawLayerForeground);
|
||||
|
||||
_refreshing = false;
|
||||
}
|
||||
|
||||
void MapGeneratorDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
|
||||
if (_refreshing)
|
||||
return;
|
||||
|
||||
switch(cmd) {
|
||||
case kAlgorCmd:
|
||||
ConfMan.setInt("map_algorithm", data);
|
||||
break;
|
||||
case kAlgorRandCmd:
|
||||
if (data == 1) {
|
||||
if (ConfMan.hasKey("map_algorithm") && ConfMan.getInt("map_algorithm") != 0)
|
||||
// Store previous value
|
||||
ConfMan.setInt("prev_map_algorithm", ConfMan.getInt("map_algorithm"));
|
||||
ConfMan.setInt("map_algorithm", 0);
|
||||
} else {
|
||||
// Restore previous value
|
||||
int previousValue = SPIFF_GEN;
|
||||
if (ConfMan.hasKey("prev_map_algorithm"))
|
||||
previousValue = ConfMan.getInt("prev_map_algorithm");
|
||||
ConfMan.setInt("map_algorithm", previousValue);
|
||||
}
|
||||
|
||||
refresh();
|
||||
break;
|
||||
case kSizeCmd:
|
||||
ConfMan.setInt("map_size", data);
|
||||
break;
|
||||
case kSizeRandCmd:
|
||||
if (data == 1) {
|
||||
if (ConfMan.hasKey("map_size") && ConfMan.getInt("map_size") != 0)
|
||||
// Store previous value
|
||||
ConfMan.setInt("prev_map_size", ConfMan.getInt("map_size"));
|
||||
ConfMan.setInt("map_size", 0);
|
||||
} else {
|
||||
// Restore previous value
|
||||
int previousValue = 4;
|
||||
if (ConfMan.hasKey("prev_map_size"))
|
||||
previousValue = ConfMan.getInt("prev_map_size");
|
||||
ConfMan.setInt("map_size", previousValue);
|
||||
}
|
||||
|
||||
refresh();
|
||||
break;
|
||||
case kTileCmd:
|
||||
ConfMan.setInt("map_tileset", data);
|
||||
break;
|
||||
case kTileRandCmd:
|
||||
if (data == 1) {
|
||||
if (ConfMan.hasKey("map_tileset") && ConfMan.getInt("map_tileset") != 0)
|
||||
// Store previous value
|
||||
ConfMan.setInt("prev_map_tileset", ConfMan.getInt("map_tileset"));
|
||||
ConfMan.setInt("map_tileset", 0);
|
||||
} else {
|
||||
// Restore previous value
|
||||
int previousValue = 5;
|
||||
if (ConfMan.hasKey("prev_map_tileset"))
|
||||
previousValue = ConfMan.getInt("prev_map_tileset");
|
||||
ConfMan.setInt("map_tileset", previousValue);
|
||||
}
|
||||
|
||||
refresh();
|
||||
break;
|
||||
case kEnergyCmd:
|
||||
ConfMan.setInt("map_energy", data);
|
||||
break;
|
||||
case kEnergyRandCmd:
|
||||
if (data == 1) {
|
||||
if (ConfMan.hasKey("map_energy") && ConfMan.getInt("map_energy") != -1)
|
||||
// Store previous value
|
||||
ConfMan.setInt("prev_map_energy", ConfMan.getInt("map_energy"));
|
||||
ConfMan.setInt("map_energy", -1);
|
||||
} else {
|
||||
// Restore previous value
|
||||
int previousValue = 3;
|
||||
if (ConfMan.hasKey("prev_map_energy"))
|
||||
previousValue = ConfMan.getInt("prev_map_energy");
|
||||
ConfMan.setInt("map_energy", previousValue);
|
||||
}
|
||||
|
||||
refresh();
|
||||
break;
|
||||
case kTerrainCmd:
|
||||
ConfMan.setInt("map_terrain", data);
|
||||
break;
|
||||
case kTerrainRandCmd:
|
||||
if (data == 1) {
|
||||
if (ConfMan.hasKey("map_terrain") && ConfMan.getInt("map_terrain") != -1)
|
||||
// Store previous value
|
||||
ConfMan.setInt("prev_map_terrain", ConfMan.getInt("map_terrain"));
|
||||
ConfMan.setInt("map_terrain", -1);
|
||||
} else {
|
||||
// Restore previous value
|
||||
int previousValue = 3;
|
||||
if (ConfMan.hasKey("prev_map_terrain"))
|
||||
previousValue = ConfMan.getInt("prev_map_terrain");
|
||||
ConfMan.setInt("map_terrain", previousValue);
|
||||
}
|
||||
|
||||
refresh();
|
||||
break;
|
||||
case kWaterCmd:
|
||||
ConfMan.setInt("map_water", data);
|
||||
break;
|
||||
case kWaterRandCmd:
|
||||
if (data == 1) {
|
||||
if (ConfMan.hasKey("map_water") && ConfMan.getInt("map_water") != -1)
|
||||
// Store previous value
|
||||
ConfMan.setInt("prev_map_water", ConfMan.getInt("map_water"));
|
||||
ConfMan.setInt("map_water", -1);
|
||||
} else {
|
||||
// Restore previous value
|
||||
int previousValue = 3;
|
||||
if (ConfMan.hasKey("prev_map_water"))
|
||||
previousValue = ConfMan.getInt("prev_map_water");
|
||||
ConfMan.setInt("map_water", previousValue);
|
||||
}
|
||||
|
||||
refresh();
|
||||
break;
|
||||
case kCancelCmd:
|
||||
setResult(0);
|
||||
close();
|
||||
break;
|
||||
case kGenerateCmd:
|
||||
ConfMan.flushToDisk();
|
||||
setResult(1);
|
||||
close();
|
||||
break;
|
||||
default:
|
||||
Dialog::handleCommand(sender, cmd, data);
|
||||
}
|
||||
}
|
||||
|
||||
void MapGeneratorDialog::handleKeyDown(Common::KeyState state) {
|
||||
switch (state.keycode) {
|
||||
case Common::KEYCODE_RETURN:
|
||||
case Common::KEYCODE_KP_ENTER:
|
||||
ConfMan.flushToDisk();
|
||||
setResult(1);
|
||||
close();
|
||||
break;
|
||||
default:
|
||||
Dialog::handleKeyDown(state);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
90
engines/scumm/he/moonbase/dialog-mapgenerator.h
Normal file
90
engines/scumm/he/moonbase/dialog-mapgenerator.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_DIALOG_MAP_GENERATOR_H
|
||||
#define SCUMM_DIALOG_MAP_GENERATOR_H
|
||||
|
||||
#include "gui/dialog.h"
|
||||
#include "gui/widget.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class MapGeneratorDialog : public Dialog {
|
||||
public:
|
||||
MapGeneratorDialog(bool demo);
|
||||
|
||||
void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
|
||||
void handleKeyDown(Common::KeyState state) override;
|
||||
|
||||
private:
|
||||
void refresh();
|
||||
bool _refreshing;
|
||||
|
||||
GUI::StaticTextWidget *_dialogTitle;
|
||||
|
||||
GUI::StaticTextWidget *_algorDesc;
|
||||
GUI::RadiobuttonGroup *_algorGroup;
|
||||
GUI::RadiobuttonWidget *_algorSpiff;
|
||||
GUI::CheckboxWidget *_algorRandom;
|
||||
|
||||
GUI::StaticTextWidget *_sizeDesc;
|
||||
GUI::RadiobuttonGroup *_sizeGroup;
|
||||
GUI::RadiobuttonWidget *_sizeSmall;
|
||||
GUI::RadiobuttonWidget *_sizeMedium;
|
||||
GUI::RadiobuttonWidget *_sizeLarge;
|
||||
GUI::RadiobuttonWidget *_sizeHuge;
|
||||
GUI::RadiobuttonWidget *_sizeSAI;
|
||||
GUI::RadiobuttonWidget *_sizeRidiculous;
|
||||
GUI::RadiobuttonWidget *_sizeMax;
|
||||
GUI::CheckboxWidget *_sizeRandom;
|
||||
|
||||
GUI::StaticTextWidget *_tileDesc;
|
||||
GUI::RadiobuttonGroup *_tileGroup;
|
||||
GUI::RadiobuttonWidget *_tileAblation;
|
||||
GUI::RadiobuttonWidget *_tileEmerau;
|
||||
GUI::RadiobuttonWidget *_tileKyanite;
|
||||
GUI::RadiobuttonWidget *_tileDrijim;
|
||||
GUI::RadiobuttonWidget *_tileZanateros;
|
||||
GUI::RadiobuttonWidget *_tileTerrandra;
|
||||
GUI::CheckboxWidget *_tileRandom;
|
||||
|
||||
GUI::StaticTextWidget *_energyDesc;
|
||||
GUI::SliderWidget *_energySlider;
|
||||
GUI::StaticTextWidget *_energyLabel;
|
||||
GUI::CheckboxWidget *_energyRandom;
|
||||
|
||||
GUI::StaticTextWidget *_terrainDesc;
|
||||
GUI::SliderWidget *_terrainSlider;
|
||||
GUI::StaticTextWidget *_terrainLabel;
|
||||
GUI::CheckboxWidget *_terrainRandom;
|
||||
|
||||
GUI::StaticTextWidget *_waterDesc;
|
||||
GUI::SliderWidget *_waterSlider;
|
||||
GUI::StaticTextWidget *_waterLabel;
|
||||
GUI::CheckboxWidget *_waterRandom;
|
||||
|
||||
GUI::ButtonWidget *_cancelButton;
|
||||
GUI::ButtonWidget *_generateButton;
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
||||
393
engines/scumm/he/moonbase/map_data.h
Normal file
393
engines/scumm/he/moonbase/map_data.h
Normal file
@@ -0,0 +1,393 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_MAP_DATA_H
|
||||
#define SCUMM_HE_MOONBASE_MAP_DATA_H
|
||||
|
||||
// This header contains file data used by the map generator, mostly
|
||||
// the Template.thm and Template.wiz data taken from the Moonbase Console
|
||||
// source repository. Gzipped manually and then converted using
|
||||
// https://notisrac.github.io/FileToCArray/ (https://github.com/notisrac/FileToCArray)
|
||||
|
||||
// Template.thm.gz (Map Icon).
|
||||
// (https://github.com/michaelbarlow7/moonbase-console/blob/master/MoonbaseConsole/Template.thm)
|
||||
#define TEMPLATE_THM_SIZE 4296 // The actual non-compressed size of Template.thm.
|
||||
const byte Template_thm[] = {
|
||||
0x1f, 0x8b, 0x08, 0x08, 0x5f, 0x3e, 0x4b, 0x65, 0x00, 0x03, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61,
|
||||
0x74, 0x65, 0x2e, 0x74, 0x68, 0x6d, 0x00, 0xad, 0x97, 0x0f, 0x7c, 0x13, 0xd5, 0x1d, 0xc0, 0x7f,
|
||||
0x97, 0x5c, 0xe1, 0xaa, 0x87, 0x1c, 0x5b, 0x26, 0x99, 0x2b, 0xa3, 0x2d, 0x4d, 0xd7, 0xac, 0x89,
|
||||
0x23, 0xdb, 0x3a, 0x44, 0x40, 0xe8, 0x41, 0x5b, 0xe8, 0x54, 0x58, 0x90, 0x16, 0x3b, 0xd0, 0x6e,
|
||||
0xa9, 0xb6, 0x25, 0xb2, 0xb9, 0x76, 0x0e, 0x59, 0x27, 0x64, 0x72, 0x20, 0xd0, 0x14, 0x50, 0xa2,
|
||||
0x73, 0xac, 0x52, 0x98, 0x1e, 0xca, 0xd2, 0xb3, 0xab, 0x10, 0xb6, 0x39, 0x43, 0xbb, 0xd5, 0xa5,
|
||||
0xfc, 0x0d, 0x0a, 0x18, 0x14, 0x24, 0xa5, 0x73, 0x7a, 0x9b, 0x28, 0x61, 0x75, 0xa5, 0xb8, 0xcd,
|
||||
0x3d, 0xdf, 0xbb, 0x97, 0x4b, 0xd2, 0xd2, 0x7e, 0x3e, 0xeb, 0x3e, 0xbb, 0x5f, 0xaf, 0xef, 0xe5,
|
||||
0xcf, 0xfb, 0xde, 0xef, 0xef, 0x7b, 0xbf, 0x14, 0x96, 0x2f, 0xa8, 0x00, 0x10, 0x0e, 0xe1, 0x61,
|
||||
0x3e, 0x00, 0x98, 0x0c, 0xf8, 0x5f, 0x5e, 0xfc, 0x76, 0x96, 0x88, 0x8b, 0x01, 0x8c, 0x1c, 0x90,
|
||||
0xcb, 0x8f, 0x05, 0xfc, 0x7e, 0xbf, 0x36, 0xf3, 0x97, 0x93, 0x69, 0x39, 0xb9, 0x10, 0x96, 0x72,
|
||||
0x84, 0x90, 0x36, 0x43, 0xda, 0x0d, 0x30, 0x13, 0x60, 0x19, 0xc0, 0x23, 0x00, 0xcf, 0x00, 0x1c,
|
||||
0x04, 0x88, 0x02, 0x20, 0xfb, 0x54, 0x74, 0x7b, 0x35, 0x5a, 0xd5, 0x82, 0xf6, 0x9f, 0x41, 0xbd,
|
||||
0x7d, 0x48, 0xac, 0xf7, 0x8a, 0x0d, 0xb2, 0x28, 0xc9, 0xa2, 0x57, 0xc9, 0x19, 0x0b, 0x33, 0x4d,
|
||||
0xb0, 0x24, 0x0b, 0x56, 0xde, 0x0c, 0x1b, 0x66, 0x40, 0xcb, 0x02, 0x68, 0xab, 0x14, 0x3a, 0x56,
|
||||
0x65, 0x9e, 0xd8, 0x32, 0xb5, 0x47, 0x9e, 0x13, 0x7b, 0x65, 0x11, 0x3a, 0x5d, 0x89, 0x8e, 0x00,
|
||||
0x06, 0xbb, 0xdc, 0x52, 0x2f, 0x64, 0x89, 0x00, 0xd5, 0x00, 0x4d, 0x00, 0xfb, 0x00, 0xde, 0xc2,
|
||||
0x68, 0xfc, 0x97, 0x6f, 0x43, 0xe5, 0x4b, 0xd1, 0xba, 0xf5, 0xa8, 0xad, 0x1d, 0x9d, 0x8b, 0xe2,
|
||||
0x6f, 0xa2, 0x08, 0x20, 0x05, 0x90, 0x04, 0x08, 0x2b, 0x32, 0x1b, 0xe0, 0x3e, 0x80, 0x46, 0x80,
|
||||
0x97, 0x00, 0xde, 0x24, 0x0b, 0xec, 0x28, 0xbf, 0x02, 0x95, 0x3f, 0x86, 0xd6, 0xed, 0x47, 0x6d,
|
||||
0xbd, 0xe8, 0x9c, 0x0d, 0x2e, 0xdd, 0x0d, 0xaf, 0x6e, 0x80, 0x1d, 0xfb, 0xe0, 0xc1, 0x5e, 0x28,
|
||||
0x29, 0x86, 0x15, 0xcb, 0x60, 0x6d, 0x1d, 0xf8, 0x36, 0xc1, 0xde, 0x16, 0x38, 0x78, 0x00, 0x4e,
|
||||
0x77, 0xe5, 0xbf, 0xfd, 0x5a, 0xf9, 0xbb, 0xe7, 0xd7, 0x7d, 0xf8, 0x7e, 0xdb, 0x95, 0xab, 0xe7,
|
||||
0x10, 0xe4, 0x9d, 0x00, 0x67, 0x37, 0xd4, 0x3d, 0x0e, 0x4f, 0xb9, 0x61, 0xef, 0x2c, 0x66, 0x42,
|
||||
0x9e, 0x29, 0x77, 0x66, 0xde, 0xcc, 0x45, 0x33, 0x9c, 0x55, 0x0b, 0x6b, 0x1e, 0x76, 0xad, 0x69,
|
||||
0x5a, 0xf3, 0xe4, 0xee, 0x1d, 0xad, 0x81, 0x03, 0x5d, 0x87, 0x4f, 0x9e, 0x3d, 0x7f, 0xa9, 0xaf,
|
||||
0x6f, 0x76, 0x2f, 0xdc, 0xfb, 0x1e, 0xac, 0xbd, 0x08, 0x2d, 0x97, 0xa1, 0xa3, 0x1f, 0x22, 0xe1,
|
||||
0x70, 0x2c, 0xa6, 0x06, 0x02, 0xde, 0x50, 0x38, 0x5c, 0x2f, 0x2b, 0xc1, 0xa8, 0x2a, 0xfa, 0x94,
|
||||
0x50, 0x54, 0x55, 0x22, 0x6a, 0x7d, 0xb3, 0xe2, 0xf6, 0xc9, 0x4e, 0xaf, 0xec, 0x93, 0x15, 0x39,
|
||||
0x14, 0x11, 0x5d, 0xf5, 0xd8, 0x3f, 0xea, 0x00, 0xf2, 0x05, 0x42, 0xc4, 0x63, 0x92, 0xec, 0x6a,
|
||||
0x0e, 0xd6, 0xcb, 0x21, 0x67, 0x83, 0xcf, 0xea, 0xf6, 0x49, 0x72, 0xb0, 0xa2, 0x5e, 0x72, 0x7a,
|
||||
0x03, 0xc1, 0xe8, 0x80, 0x12, 0x56, 0xdd, 0x5e, 0x19, 0xbb, 0xd4, 0x17, 0x8c, 0x4a, 0x81, 0x68,
|
||||
0x54, 0x8d, 0x45, 0x63, 0x28, 0xa2, 0x0e, 0x78, 0xe5, 0xa0, 0x1a, 0x1b, 0x08, 0x47, 0xa2, 0xa2,
|
||||
0xdb, 0xe7, 0xf2, 0x06, 0x1d, 0x15, 0xf8, 0x8d, 0xa8, 0x12, 0x46, 0xe1, 0xe8, 0x80, 0x1c, 0x08,
|
||||
0x87, 0xa3, 0xc8, 0xdd, 0xd0, 0xec, 0x95, 0x23, 0x4e, 0x97, 0xd4, 0x1c, 0x44, 0x8e, 0xd2, 0x86,
|
||||
0x50, 0x58, 0x95, 0x9a, 0x07, 0x22, 0x51, 0x24, 0x2b, 0xe1, 0x50, 0x18, 0x49, 0xde, 0x60, 0x85,
|
||||
0xab, 0x19, 0xe3, 0xbc, 0x5e, 0x5f, 0x24, 0xa2, 0x2a, 0x4a, 0x24, 0x18, 0x8c, 0x29, 0x8a, 0x2a,
|
||||
0x35, 0xc8, 0xd1, 0xc8, 0x40, 0xbd, 0x4b, 0xae, 0x28, 0xf5, 0x4a, 0xee, 0xa0, 0xec, 0x0b, 0x05,
|
||||
0x65, 0x35, 0xd0, 0x1c, 0x6d, 0x70, 0xc9, 0xcd, 0x0d, 0x21, 0xc9, 0x25, 0xd7, 0x3b, 0x7d, 0x5e,
|
||||
0x97, 0x12, 0x0d, 0xc5, 0x22, 0x41, 0x55, 0x0d, 0xc7, 0x22, 0x81, 0x08, 0x8a, 0x0d, 0xe0, 0x64,
|
||||
0x02, 0x60, 0x01, 0xd2, 0x00, 0xc6, 0x00, 0x8c, 0x05, 0xc0, 0xa9, 0x95, 0x0e, 0x70, 0x1d, 0xc0,
|
||||
0xf5, 0x00, 0x3c, 0xc0, 0x38, 0x80, 0x1b, 0x00, 0xc6, 0x9f, 0xe8, 0x86, 0x3d, 0x3b, 0x61, 0xcd,
|
||||
0x43, 0x30, 0x77, 0x2e, 0xf4, 0xf4, 0xf4, 0xb4, 0xb7, 0xb7, 0x4b, 0x92, 0x84, 0x53, 0xed, 0xe5,
|
||||
0x73, 0x97, 0xd6, 0xc8, 0x47, 0xe7, 0xac, 0x6f, 0x9f, 0xb4, 0x7c, 0x03, 0xea, 0x7e, 0xfe, 0xea,
|
||||
0xfe, 0x47, 0xfb, 0x76, 0x2f, 0xbf, 0xb8, 0xe5, 0x16, 0x94, 0x03, 0xe8, 0x36, 0x40, 0x4b, 0x01,
|
||||
0xd5, 0x01, 0xf2, 0x02, 0xda, 0x03, 0xa8, 0x13, 0xd0, 0x59, 0xd8, 0x5d, 0x58, 0xb8, 0x7a, 0xf2,
|
||||
0xe4, 0x0f, 0x4e, 0xad, 0xe8, 0x6e, 0xc9, 0xdf, 0xe8, 0x4a, 0xbf, 0x1c, 0xea, 0x3b, 0xf3, 0xec,
|
||||
0x99, 0x17, 0x5c, 0x3b, 0x71, 0x36, 0x77, 0x75, 0x75, 0xed, 0x5b, 0x9c, 0xff, 0x8e, 0x7b, 0xda,
|
||||
0x99, 0xb6, 0x06, 0x74, 0x6a, 0x7b, 0x47, 0x47, 0xc7, 0xae, 0x5d, 0xcf, 0x79, 0x3c, 0x1e, 0x9c,
|
||||
0x4b, 0x38, 0x3d, 0x90, 0x36, 0x20, 0x6d, 0x86, 0xaf, 0xc5, 0x8b, 0x16, 0xde, 0x85, 0xdf, 0x10,
|
||||
0x20, 0x7e, 0x39, 0xef, 0x28, 0x5c, 0x04, 0xc0, 0xf0, 0xda, 0x0b, 0xc6, 0x60, 0x64, 0xd3, 0xc6,
|
||||
0x8c, 0xe5, 0xd2, 0xaf, 0xbb, 0x9e, 0x1f, 0x77, 0xc3, 0x78, 0x61, 0xc2, 0x67, 0x3e, 0x6b, 0xfa,
|
||||
0xdc, 0x8d, 0x13, 0xcd, 0x9f, 0xbf, 0xe9, 0x0b, 0x19, 0x93, 0xbe, 0x38, 0x39, 0x33, 0x2b, 0x7b,
|
||||
0x4a, 0x8e, 0x25, 0xf7, 0x4b, 0x79, 0xd6, 0x2f, 0xe7, 0xdb, 0xec, 0x37, 0x7f, 0x65, 0xaa, 0xe3,
|
||||
0xab, 0x5f, 0xfb, 0x7a, 0xc1, 0x37, 0xa6, 0xdd, 0x32, 0xfd, 0xd6, 0x19, 0x33, 0x67, 0xdd, 0x36,
|
||||
0x7b, 0x4e, 0xa1, 0x38, 0x77, 0x5e, 0x51, 0x71, 0xc9, 0xfc, 0x05, 0xa5, 0xdf, 0xbc, 0xfd, 0x8e,
|
||||
0x3b, 0x17, 0x2e, 0xfa, 0x96, 0x73, 0xf1, 0x5d, 0x4b, 0xca, 0xca, 0x97, 0xde, 0x5d, 0xf1, 0xed,
|
||||
0x65, 0xcb, 0xef, 0xb9, 0xb7, 0xf2, 0x3b, 0xdf, 0x75, 0x55, 0xdd, 0x77, 0x7f, 0x75, 0x4d, 0xed,
|
||||
0x0a, 0xf7, 0x03, 0x2b, 0xbf, 0xf7, 0xfd, 0x07, 0x7f, 0x50, 0x57, 0xff, 0xc3, 0x87, 0x7e, 0xb4,
|
||||
0xea, 0xe1, 0xd5, 0x3f, 0x6e, 0xf8, 0xc9, 0x23, 0x6b, 0xd6, 0x7a, 0x7e, 0xfa, 0xe8, 0x3a, 0x69,
|
||||
0xfd, 0x86, 0xc7, 0x36, 0x6e, 0xda, 0xdc, 0xe8, 0x6d, 0xda, 0xb2, 0x75, 0xdb, 0xe3, 0x4f, 0x6c,
|
||||
0xf7, 0x3d, 0xf9, 0xd4, 0xcf, 0x9e, 0xfe, 0xf9, 0x8e, 0x5f, 0x34, 0x3f, 0xb3, 0xb3, 0x65, 0xd7,
|
||||
0xee, 0x5f, 0x3e, 0xfb, 0x9c, 0xbc, 0xe7, 0xf9, 0x17, 0xf6, 0xfe, 0xca, 0xdf, 0xaa, 0xbc, 0xd8,
|
||||
0xf6, 0xeb, 0xf6, 0x97, 0xf6, 0xed, 0x0f, 0x1c, 0xf8, 0xcd, 0x6f, 0x7f, 0xf7, 0xf2, 0xef, 0x5f,
|
||||
0x09, 0x1e, 0xec, 0xe8, 0xfc, 0xc3, 0x1f, 0xbb, 0x5e, 0xfd, 0x53, 0xa8, 0xfb, 0xd0, 0xe1, 0x23,
|
||||
0x47, 0x8f, 0x1d, 0x0f, 0x9f, 0x78, 0xed, 0xf5, 0x93, 0xa7, 0x4e, 0xbf, 0x11, 0x39, 0xf3, 0xe6,
|
||||
0x5b, 0x67, 0xcf, 0xbd, 0x7d, 0x3e, 0xda, 0x73, 0xa1, 0xf7, 0xcf, 0xef, 0xfc, 0xe5, 0xdd, 0xf7,
|
||||
0xd4, 0xbf, 0xfe, 0xed, 0xfd, 0x8b, 0x1f, 0x7c, 0x78, 0x29, 0x76, 0xf9, 0xef, 0x7d, 0x1f, 0xfd,
|
||||
0xa3, 0xff, 0xca, 0xc0, 0xd5, 0x8f, 0xff, 0xf9, 0xaf, 0x7f, 0x7f, 0xf2, 0x1f, 0x84, 0xf7, 0x8d,
|
||||
0x79, 0x38, 0x76, 0x1b, 0x8f, 0x0b, 0xa3, 0x17, 0x45, 0x68, 0xe5, 0x1b, 0xf9, 0xcd, 0xdc, 0x26,
|
||||
0xae, 0x96, 0xab, 0xe1, 0xe6, 0xb3, 0xd5, 0x44, 0xb8, 0x12, 0xb6, 0x04, 0xbf, 0x1a, 0x3d, 0xad,
|
||||
0x15, 0x4b, 0x23, 0x4f, 0x48, 0x44, 0x4a, 0xd8, 0x62, 0x4d, 0x72, 0xa1, 0x08, 0xc8, 0x38, 0x6a,
|
||||
0xcd, 0x12, 0x34, 0x4d, 0x23, 0xcc, 0x29, 0x86, 0x22, 0xd6, 0x02, 0x39, 0x78, 0x8f, 0x24, 0xf2,
|
||||
0xbf, 0xe8, 0xb6, 0x49, 0xa3, 0x61, 0x6d, 0xc0, 0x12, 0x17, 0x30, 0x19, 0x71, 0x49, 0xe4, 0x80,
|
||||
0x65, 0x54, 0xfa, 0x11, 0x9a, 0x1f, 0xfb, 0x8d, 0xd8, 0x49, 0x6c, 0xa3, 0xac, 0x1c, 0x52, 0x59,
|
||||
0x1a, 0x8f, 0xc5, 0xaf, 0x46, 0x5e, 0x7d, 0x0c, 0xaf, 0x2e, 0x62, 0xb3, 0x81, 0x8a, 0x41, 0x13,
|
||||
0x06, 0xdf, 0x39, 0x40, 0x74, 0xcb, 0xc5, 0x6b, 0x59, 0x4d, 0x08, 0x89, 0xf2, 0x88, 0x86, 0x23,
|
||||
0xf3, 0xfc, 0xbc, 0x46, 0x62, 0xab, 0xf8, 0xc3, 0x66, 0x65, 0xba, 0x52, 0xe0, 0x75, 0x48, 0x82,
|
||||
0xc8, 0x31, 0x5a, 0x71, 0xe8, 0x7a, 0x11, 0x06, 0x79, 0x8e, 0xce, 0x63, 0x47, 0xe0, 0xf9, 0x85,
|
||||
0x1a, 0x8d, 0xe6, 0xb6, 0x07, 0xca, 0xde, 0xa8, 0xf0, 0x3a, 0x8e, 0x99, 0xfb, 0x4c, 0x47, 0xcd,
|
||||
0x5e, 0x87, 0xa3, 0x34, 0x3c, 0x2b, 0x53, 0x43, 0x1a, 0xe3, 0x2c, 0x1a, 0x85, 0xa4, 0x0c, 0x47,
|
||||
0xd3, 0xad, 0x94, 0x4d, 0x81, 0x32, 0x9f, 0xd3, 0x6d, 0x7f, 0x5a, 0xf8, 0x24, 0x63, 0x86, 0xf5,
|
||||
0xe3, 0xa2, 0xad, 0x7c, 0x08, 0x33, 0x33, 0x99, 0x4c, 0xe6, 0x02, 0xb3, 0x8b, 0xe9, 0xd4, 0xb8,
|
||||
0x8c, 0x26, 0x60, 0xa2, 0xa3, 0x61, 0x18, 0xfd, 0x88, 0x9d, 0x55, 0xbc, 0xa3, 0xd8, 0x59, 0x2a,
|
||||
0x9b, 0xc6, 0x8b, 0x81, 0xb2, 0x40, 0xd9, 0x92, 0xe2, 0xab, 0x85, 0xab, 0x2d, 0x75, 0xf6, 0xad,
|
||||
0x0e, 0xa5, 0x80, 0xd0, 0x3a, 0x19, 0x11, 0x87, 0xc0, 0x63, 0xf0, 0x18, 0x28, 0x91, 0x9c, 0xa7,
|
||||
0x74, 0x36, 0x94, 0x77, 0x4c, 0x98, 0xa7, 0xe9, 0xa6, 0x66, 0x6c, 0x73, 0xc8, 0xa6, 0x90, 0x29,
|
||||
0x64, 0x56, 0x33, 0x94, 0x02, 0x41, 0x9c, 0x5a, 0x1c, 0x2b, 0x0c, 0xcf, 0x72, 0xdb, 0x09, 0x2d,
|
||||
0x53, 0xd3, 0xad, 0x93, 0x21, 0x3c, 0x4a, 0xd4, 0x79, 0x84, 0x48, 0x39, 0x35, 0xfc, 0x94, 0x44,
|
||||
0x24, 0xe7, 0xb2, 0xc2, 0x84, 0x89, 0x69, 0x21, 0x33, 0xe5, 0x11, 0xa2, 0x8a, 0xe7, 0x92, 0x20,
|
||||
0x09, 0x2e, 0xde, 0xc5, 0x89, 0x5c, 0x16, 0xeb, 0x61, 0x2a, 0x19, 0x12, 0x59, 0x3c, 0xd3, 0x79,
|
||||
0x36, 0x3a, 0x50, 0xfd, 0x36, 0xf3, 0x34, 0x8e, 0xaa, 0xd9, 0x6d, 0x77, 0xdb, 0xb9, 0x2c, 0xab,
|
||||
0xc5, 0x6a, 0x71, 0xf1, 0x6e, 0x3b, 0x25, 0xca, 0xa6, 0xf5, 0x82, 0xc4, 0x8b, 0x1a, 0x29, 0x8b,
|
||||
0xcd, 0x64, 0x3c, 0x8c, 0x8b, 0xa7, 0x1c, 0x03, 0xb5, 0xd9, 0x96, 0x2a, 0x84, 0x47, 0xb4, 0x12,
|
||||
0xc4, 0xf0, 0xf4, 0x40, 0x99, 0xd7, 0x41, 0x68, 0xdc, 0x24, 0xa2, 0x4d, 0xa9, 0xd5, 0x6d, 0xb7,
|
||||
0x5a, 0x64, 0x53, 0x15, 0xef, 0xc2, 0x34, 0x6a, 0x29, 0x11, 0x17, 0x9f, 0xf4, 0x1d, 0xc0, 0x05,
|
||||
0x23, 0x15, 0x5d, 0x3f, 0xbf, 0x66, 0xa9, 0xdb, 0x2e, 0x09, 0xb2, 0x49, 0x29, 0x50, 0x33, 0x08,
|
||||
0x4f, 0x35, 0x13, 0x1e, 0xb6, 0x33, 0x83, 0xda, 0x1b, 0x4a, 0xd8, 0x2b, 0x72, 0x3a, 0x2d, 0xe9,
|
||||
0x3d, 0xc2, 0xd2, 0x99, 0x0c, 0x10, 0xff, 0xcb, 0xa6, 0xfd, 0x38, 0x8a, 0x91, 0x7b, 0xac, 0x96,
|
||||
0x7e, 0x76, 0x62, 0xda, 0xb4, 0x71, 0x47, 0xb4, 0xd5, 0x74, 0xbd, 0x24, 0x60, 0x9a, 0x36, 0x23,
|
||||
0xf6, 0x02, 0x54, 0x6a, 0x71, 0xc8, 0xc5, 0x47, 0x97, 0x11, 0x28, 0x43, 0xd7, 0x8e, 0x8e, 0x94,
|
||||
0x57, 0x6a, 0x25, 0x99, 0xc1, 0x65, 0xf5, 0xb3, 0xe6, 0x74, 0x73, 0xfa, 0xc4, 0xb4, 0x27, 0xf8,
|
||||
0x15, 0xdc, 0xfd, 0xd8, 0x4e, 0xca, 0xa1, 0x76, 0xe2, 0x88, 0x32, 0x84, 0x06, 0x40, 0x6b, 0xcd,
|
||||
0x98, 0x42, 0xd4, 0x6d, 0x07, 0xd0, 0x72, 0x97, 0xa5, 0x31, 0xe0, 0x26, 0x9d, 0xe4, 0x08, 0xef,
|
||||
0x56, 0x7c, 0xf7, 0xc3, 0x16, 0x68, 0x62, 0xa9, 0xbf, 0x08, 0x93, 0xb0, 0x01, 0x47, 0x94, 0xc4,
|
||||
0xc2, 0x63, 0x48, 0xd3, 0x78, 0xa4, 0x9e, 0x53, 0xbd, 0x87, 0x47, 0x5b, 0xab, 0x96, 0x71, 0x3a,
|
||||
0xcf, 0x6a, 0x21, 0xf6, 0xde, 0x94, 0x6e, 0x4e, 0xeb, 0x87, 0x53, 0xd0, 0x8e, 0x99, 0x84, 0xa8,
|
||||
0x65, 0x0a, 0x4f, 0xbd, 0x27, 0xf2, 0x94, 0xa8, 0xd7, 0x46, 0x32, 0x22, 0x94, 0x7b, 0x5c, 0xa8,
|
||||
0xe6, 0xb2, 0x21, 0x64, 0x26, 0x3c, 0x4c, 0xcc, 0xba, 0xc2, 0x4d, 0x1b, 0x77, 0x63, 0xfa, 0x15,
|
||||
0xf6, 0x14, 0xee, 0xb1, 0xb6, 0x11, 0x1d, 0x71, 0x07, 0x49, 0xb2, 0x97, 0xe8, 0x98, 0x14, 0xdd,
|
||||
0x46, 0x06, 0x92, 0xd6, 0xd2, 0x19, 0xa9, 0x09, 0x9c, 0xc3, 0x1c, 0xd1, 0x30, 0x3c, 0x9d, 0x64,
|
||||
0x9f, 0x30, 0xe1, 0x23, 0xee, 0x75, 0x96, 0xe8, 0xb6, 0x12, 0xcb, 0x03, 0xe0, 0xc6, 0xc4, 0x3c,
|
||||
0x2d, 0xa6, 0x24, 0xff, 0x00, 0x52, 0x57, 0x27, 0xa3, 0x91, 0xe4, 0x1d, 0x17, 0xa6, 0x68, 0x16,
|
||||
0x73, 0x59, 0xa4, 0x56, 0x95, 0x02, 0x49, 0x38, 0x64, 0x7a, 0x91, 0x6d, 0xd2, 0x48, 0xa5, 0xb0,
|
||||
0x00, 0xac, 0x1a, 0x2f, 0x2f, 0x25, 0xe7, 0x92, 0xeb, 0x87, 0xd2, 0x28, 0x8f, 0x58, 0x9c, 0xcd,
|
||||
0xd6, 0xdf, 0xe9, 0x73, 0x6e, 0x77, 0xe6, 0x65, 0xa9, 0x19, 0x92, 0x40, 0xbc, 0xb6, 0x91, 0x75,
|
||||
0x63, 0x5a, 0x1e, 0x6e, 0x67, 0xc6, 0x40, 0x9a, 0xb6, 0x73, 0x5e, 0x9b, 0xc7, 0x43, 0xac, 0x8d,
|
||||
0xd7, 0x07, 0xa9, 0x90, 0x2a, 0x3e, 0x3c, 0xdd, 0xe7, 0xc4, 0xf5, 0x80, 0x7d, 0x2f, 0x09, 0x56,
|
||||
0x8b, 0x07, 0x57, 0xfd, 0x2e, 0x9c, 0x21, 0x1e, 0x43, 0x76, 0x7c, 0x67, 0x1e, 0xea, 0xfd, 0x54,
|
||||
0xad, 0x74, 0xbb, 0xf5, 0xfd, 0x80, 0xac, 0xe1, 0xb0, 0x66, 0xa4, 0xde, 0x48, 0x8d, 0x90, 0xda,
|
||||
0xf0, 0x30, 0xc9, 0x3a, 0xa0, 0x32, 0xd8, 0xbe, 0xc1, 0xf5, 0xa6, 0xc7, 0x87, 0xf2, 0xaa, 0x39,
|
||||
0x03, 0x90, 0xda, 0x22, 0x75, 0x95, 0xc9, 0xe8, 0x34, 0x80, 0xe1, 0xd6, 0x0e, 0xfb, 0x4e, 0x7c,
|
||||
0x7f, 0xa1, 0x3c, 0x05, 0xef, 0xef, 0x0c, 0x88, 0x6c, 0xc8, 0x4c, 0x33, 0x8d, 0xec, 0x21, 0x43,
|
||||
0x59, 0xa9, 0x84, 0xc1, 0x5a, 0xa5, 0xf2, 0x0c, 0xa0, 0xc4, 0x4f, 0x41, 0xe2, 0x1d, 0xa2, 0x1d,
|
||||
0xdd, 0xe3, 0x46, 0xe6, 0x5d, 0xab, 0x25, 0x8d, 0x83, 0x2e, 0xf1, 0x33, 0x95, 0x2f, 0xc2, 0xe1,
|
||||
0xd3, 0x6b, 0x0b, 0xf3, 0xae, 0xb1, 0x75, 0xd0, 0xfa, 0x6b, 0xf4, 0xd5, 0xf5, 0xc3, 0x3f, 0x92,
|
||||
0x78, 0x3f, 0xe9, 0x6d, 0xf8, 0x12, 0xed, 0xd7, 0x13, 0xd9, 0xcb, 0x45, 0xae, 0x30, 0xb1, 0xef,
|
||||
0x0e, 0x17, 0x85, 0xa1, 0x3c, 0x6d, 0x48, 0xf0, 0x1a, 0xb5, 0x4e, 0xa9, 0x96, 0xf4, 0x35, 0xf4,
|
||||
0x64, 0x81, 0xc1, 0x31, 0x4d, 0xb5, 0x51, 0xaf, 0x88, 0x61, 0x2c, 0x4f, 0xf0, 0x36, 0x63, 0xdd,
|
||||
0x6a, 0x71, 0xcf, 0x45, 0xba, 0x07, 0x16, 0x0c, 0x29, 0xc4, 0x21, 0x66, 0xda, 0x92, 0xb1, 0x18,
|
||||
0xba, 0x2b, 0x0f, 0xe6, 0xd5, 0x6a, 0xdd, 0x88, 0x05, 0xf3, 0x8c, 0xd7, 0x9c, 0xce, 0x83, 0xcf,
|
||||
0x06, 0xb0, 0xa5, 0xc4, 0xd5, 0x36, 0xbc, 0x6c, 0x8a, 0xf7, 0x70, 0x74, 0x7f, 0x64, 0xb4, 0x4a,
|
||||
0xd0, 0x4f, 0xbf, 0xd4, 0xe7, 0xfe, 0x77, 0x33, 0x03, 0xd0, 0x5e, 0x89, 0x74, 0x23, 0xc6, 0x44,
|
||||
0xcf, 0x33, 0x3c, 0x8f, 0x19, 0x91, 0x02, 0x29, 0xf9, 0x4c, 0x78, 0xb9, 0x1a, 0x8d, 0xfc, 0x66,
|
||||
0x8e, 0x57, 0xe9, 0x28, 0xb5, 0x1a, 0xcc, 0x2b, 0x61, 0x8b, 0x12, 0x3c, 0xc3, 0xff, 0x81, 0x47,
|
||||
0xba, 0xb9, 0x91, 0x23, 0x30, 0x5a, 0xa9, 0x4d, 0xf4, 0x9a, 0x60, 0xcb, 0x89, 0x77, 0x61, 0x60,
|
||||
0x33, 0xc4, 0x7d, 0x49, 0x9e, 0xab, 0xfb, 0x80, 0x19, 0xd1, 0x1b, 0x4c, 0xe2, 0x7b, 0x46, 0xd0,
|
||||
0x7b, 0xe1, 0x5c, 0x96, 0xf0, 0x68, 0x8f, 0x08, 0x36, 0x63, 0x82, 0x0c, 0x09, 0x1f, 0xd0, 0x7e,
|
||||
0xcc, 0x30, 0x24, 0x32, 0xc9, 0xa7, 0x91, 0xcf, 0x8c, 0xf0, 0x29, 0xb1, 0xab, 0x44, 0x05, 0xc8,
|
||||
0x10, 0x00, 0x00
|
||||
};
|
||||
|
||||
// Template.wiz.gz (Map Thumbnail; modified in-code to display stats).
|
||||
// (https://github.com/michaelbarlow7/moonbase-console/blob/master/MoonbaseConsole/Template.wiz)
|
||||
#define TEMPLATE_WIZ_SIZE 39738 // The actual non-compressed size of Template.wiz.
|
||||
const byte Template_wiz[] = {
|
||||
0x1f, 0x8b, 0x08, 0x08, 0xf4, 0x21, 0x4c, 0x65, 0x00, 0x03, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61,
|
||||
0x74, 0x65, 0x2e, 0x77, 0x69, 0x7a, 0x00, 0xed, 0x5d, 0x0d, 0x9c, 0x1b, 0x45, 0x15, 0x7f, 0x48,
|
||||
0x80, 0x05, 0x0e, 0x08, 0x7a, 0x6a, 0xda, 0x5e, 0x81, 0x53, 0xee, 0x2e, 0x69, 0x0b, 0xb4, 0x16,
|
||||
0x84, 0x42, 0xf9, 0xe8, 0x81, 0x05, 0x22, 0x1c, 0xed, 0x1e, 0xf4, 0x20, 0x82, 0x20, 0x9b, 0x0a,
|
||||
0x12, 0x51, 0xb8, 0x88, 0x80, 0x91, 0xb6, 0x72, 0x4b, 0x01, 0x09, 0x28, 0x12, 0x50, 0xe1, 0xa0,
|
||||
0x54, 0x08, 0x1f, 0x96, 0x58, 0x4b, 0x2f, 0xa8, 0x48, 0x28, 0x5a, 0x4c, 0x05, 0x34, 0x45, 0xc0,
|
||||
0x14, 0x28, 0xa4, 0x56, 0xa4, 0x8b, 0x7c, 0xf4, 0xb0, 0x4a, 0x83, 0xf8, 0x31, 0xee, 0x64, 0x32,
|
||||
0xd9, 0xd9, 0xdd, 0xd9, 0x7c, 0xb4, 0xb9, 0x66, 0xfd, 0xed, 0xe6, 0xdf, 0x6b, 0x76, 0xdf, 0xbe,
|
||||
0x9d, 0xbc, 0xfd, 0xef, 0xdb, 0x99, 0x79, 0x33, 0xbb, 0x6f, 0x67, 0x0d, 0x9c, 0x1c, 0x02, 0xb8,
|
||||
0xe3, 0x48, 0xf5, 0xeb, 0x24, 0x00, 0x68, 0xff, 0x90, 0xfa, 0xdf, 0x0d, 0xe5, 0x3f, 0xf1, 0xc4,
|
||||
0xde, 0x7e, 0x80, 0x9d, 0x05, 0xc0, 0x9f, 0x65, 0x2a, 0x60, 0xd9, 0xb2, 0x65, 0xa5, 0xa5, 0x65,
|
||||
0x03, 0x78, 0x71, 0x00, 0x7f, 0x90, 0x8a, 0x01, 0x84, 0x50, 0x69, 0x09, 0x95, 0xfe, 0x00, 0x66,
|
||||
0x02, 0x9c, 0x0d, 0x70, 0x15, 0xc0, 0x9d, 0x00, 0x8f, 0x03, 0x14, 0x00, 0xd0, 0x41, 0x53, 0xd1,
|
||||
0x29, 0x17, 0xa0, 0xcb, 0x97, 0xa0, 0x91, 0x75, 0x68, 0xe3, 0x16, 0xd4, 0x1b, 0x8d, 0xf7, 0xc6,
|
||||
0x92, 0xbd, 0x72, 0xb2, 0x37, 0x9e, 0x3a, 0x70, 0x37, 0x98, 0xd9, 0x0e, 0x67, 0x74, 0xc2, 0xc5,
|
||||
0x07, 0xc3, 0xe2, 0xa3, 0x60, 0xc9, 0xc9, 0xb0, 0xfc, 0x3c, 0xef, 0xaa, 0xcb, 0x0f, 0x58, 0x7b,
|
||||
0xd3, 0xd4, 0x0d, 0xc9, 0xe3, 0x46, 0x1f, 0x9b, 0x83, 0x5e, 0x38, 0x0f, 0x3d, 0x0d, 0x6a, 0xc1,
|
||||
0x52, 0x44, 0xde, 0x08, 0x9d, 0xbd, 0x00, 0x17, 0x00, 0xdc, 0x08, 0xb0, 0x12, 0xe0, 0x25, 0xb5,
|
||||
0x68, 0xf5, 0xdf, 0xe4, 0x29, 0x68, 0xe0, 0x4c, 0x34, 0x74, 0x0d, 0x5a, 0xbe, 0x02, 0xad, 0x2f,
|
||||
0xa8, 0x9a, 0x28, 0x0f, 0x28, 0x05, 0x48, 0x06, 0xa4, 0x1a, 0x72, 0x2c, 0xc0, 0xfc, 0xd2, 0x21,
|
||||
0x3d, 0x0c, 0xf0, 0x22, 0xde, 0xe1, 0x20, 0x34, 0x39, 0x84, 0x06, 0xae, 0x45, 0x43, 0x23, 0x68,
|
||||
0xf9, 0x46, 0xb4, 0x7e, 0x0a, 0x6c, 0x3e, 0x0b, 0x9e, 0x5c, 0x0c, 0xb7, 0xaf, 0x84, 0x4b, 0x36,
|
||||
0xc2, 0x89, 0xb3, 0xe1, 0xa2, 0xb3, 0x61, 0xe1, 0x20, 0x24, 0xae, 0x87, 0x07, 0x97, 0xc0, 0xe3,
|
||||
0x8f, 0xc0, 0x0b, 0xab, 0x27, 0xbf, 0xf2, 0xec, 0xc0, 0xeb, 0xaf, 0x0e, 0xbd, 0xf3, 0xe6, 0xf2,
|
||||
0xad, 0xef, 0xaf, 0x47, 0xe0, 0x5f, 0x0b, 0xe2, 0x1a, 0x18, 0xbc, 0x19, 0x6e, 0x8b, 0xc0, 0x83,
|
||||
0x47, 0xef, 0xb4, 0xaf, 0xbf, 0xbd, 0x7b, 0xa6, 0x7f, 0xe6, 0x9c, 0xa3, 0xc4, 0xf0, 0x69, 0x17,
|
||||
0x5e, 0x21, 0x2d, 0xb8, 0x71, 0xc1, 0xad, 0x4b, 0x6f, 0x7f, 0x28, 0xfd, 0xc8, 0xea, 0xa7, 0x9e,
|
||||
0x7b, 0xf9, 0xd5, 0xcd, 0x5b, 0xb6, 0x1c, 0xbb, 0x11, 0xce, 0xdd, 0x04, 0x0b, 0xdf, 0x82, 0x25,
|
||||
0xef, 0xc2, 0xaa, 0xf7, 0x20, 0x9f, 0xcb, 0x8d, 0x8e, 0x2a, 0xe9, 0x74, 0x3c, 0x9b, 0xcb, 0x45,
|
||||
0x93, 0xa9, 0x4c, 0x41, 0xe9, 0x4d, 0xa4, 0xb2, 0x05, 0x25, 0x95, 0x57, 0xa2, 0xc3, 0xa9, 0x48,
|
||||
0x22, 0x29, 0xc6, 0x93, 0x89, 0x64, 0x2a, 0x99, 0xcd, 0xf7, 0x4a, 0x51, 0x95, 0x1f, 0xa5, 0x88,
|
||||
0x12, 0xe9, 0x2c, 0x66, 0x4c, 0x4e, 0x4a, 0xc3, 0x99, 0x68, 0x32, 0x2b, 0xc6, 0x12, 0x81, 0x48,
|
||||
0x42, 0x4e, 0x66, 0x42, 0x51, 0x59, 0x8c, 0xa7, 0x33, 0x85, 0x62, 0x2a, 0xa7, 0x44, 0xe2, 0x49,
|
||||
0x95, 0xd2, 0x44, 0xa6, 0x20, 0xa7, 0x0b, 0x05, 0x65, 0xb4, 0x30, 0x8a, 0xf2, 0x4a, 0x31, 0x9e,
|
||||
0xcc, 0x28, 0xa3, 0xc5, 0x5c, 0xbe, 0xd0, 0x1b, 0x49, 0x48, 0xf1, 0xcc, 0xb4, 0x90, 0x2a, 0x28,
|
||||
0xa4, 0x72, 0x28, 0x57, 0x28, 0x26, 0xd3, 0xb9, 0x5c, 0x01, 0x45, 0x62, 0xc3, 0xf1, 0x64, 0x5e,
|
||||
0x94, 0xe4, 0xe1, 0x0c, 0x9a, 0x16, 0x8c, 0x65, 0x73, 0x8a, 0x3c, 0x5c, 0xcc, 0x17, 0x50, 0x32,
|
||||
0x95, 0xcb, 0xe6, 0x90, 0x1c, 0xcf, 0x84, 0xa4, 0x61, 0xb5, 0xb8, 0x78, 0x3c, 0x91, 0xcf, 0x2b,
|
||||
0xa9, 0x54, 0x3e, 0x93, 0x19, 0x4d, 0xa5, 0x14, 0x39, 0x96, 0x2c, 0xe4, 0x8b, 0x51, 0x29, 0x19,
|
||||
0x0a, 0xc6, 0xe5, 0x48, 0x26, 0x99, 0xc8, 0x66, 0x92, 0x4a, 0x7a, 0xb8, 0x10, 0x93, 0x92, 0xc3,
|
||||
0xb1, 0xac, 0x2c, 0x25, 0xa3, 0x62, 0x22, 0x2e, 0xa5, 0x0a, 0xd9, 0xd1, 0x7c, 0x46, 0x51, 0x72,
|
||||
0xa3, 0xf9, 0x74, 0x1e, 0x8d, 0x16, 0x55, 0x67, 0x02, 0xf0, 0x00, 0xec, 0x02, 0xb0, 0x2b, 0xc0,
|
||||
0x6e, 0x00, 0xaa, 0x6b, 0xed, 0x0e, 0xb0, 0x07, 0xc0, 0x9e, 0x00, 0x6d, 0x00, 0x7b, 0x01, 0xec,
|
||||
0x0d, 0xb0, 0xcf, 0xda, 0x35, 0x70, 0xdf, 0x5d, 0xb0, 0xe0, 0x32, 0x38, 0xfe, 0x78, 0xd8, 0xb0,
|
||||
0x61, 0xc3, 0x8a, 0x15, 0x2b, 0x64, 0x59, 0x56, 0x5d, 0xed, 0xd1, 0xf5, 0x9b, 0x17, 0x24, 0x9f,
|
||||
0x39, 0xee, 0x9a, 0x15, 0x13, 0xcf, 0x59, 0x8c, 0xd6, 0xdc, 0xff, 0xfe, 0xc8, 0xd5, 0x5b, 0x96,
|
||||
0x9e, 0xf3, 0xd6, 0x4d, 0x47, 0xa0, 0x03, 0x01, 0x1d, 0x03, 0xe8, 0x4c, 0x40, 0x83, 0x80, 0xe2,
|
||||
0x80, 0xee, 0x03, 0xf4, 0x04, 0xa0, 0x97, 0x61, 0xe9, 0xac, 0x59, 0x57, 0xee, 0xbf, 0xff, 0xdb,
|
||||
0xcf, 0x5f, 0xb4, 0x66, 0xc9, 0xe4, 0xeb, 0xa4, 0xdd, 0xdf, 0xcd, 0x6e, 0x59, 0x77, 0xcf, 0xba,
|
||||
0x07, 0xa4, 0xbb, 0x54, 0x6f, 0x5e, 0xbd, 0x7a, 0xf5, 0xca, 0xfe, 0xc9, 0xaf, 0x45, 0x0e, 0x5f,
|
||||
0xb7, 0x3c, 0x86, 0x9e, 0xbf, 0x65, 0xd5, 0xaa, 0x55, 0x77, 0xdf, 0x7d, 0xef, 0xa2, 0x45, 0x8b,
|
||||
0x54, 0x5f, 0x52, 0xdd, 0x03, 0x95, 0xbe, 0x50, 0x69, 0x49, 0xfd, 0xf4, 0xcf, 0x39, 0xed, 0x74,
|
||||
0x55, 0xe0, 0x85, 0xf2, 0x47, 0x3c, 0x75, 0xd6, 0x1c, 0x80, 0x9d, 0xda, 0x4a, 0x2b, 0x3b, 0x7d,
|
||||
0x68, 0x67, 0xcf, 0x2e, 0xbb, 0xee, 0x26, 0xec, 0xbe, 0xc7, 0x9e, 0x6d, 0x7b, 0xed, 0xbd, 0x8f,
|
||||
0x77, 0xdf, 0x0f, 0x7f, 0xa4, 0xfd, 0xa3, 0x1f, 0xfb, 0xb8, 0x6f, 0xdc, 0xf8, 0x09, 0x1d, 0x13,
|
||||
0xf7, 0xdb, 0xff, 0x80, 0xce, 0x4f, 0x7c, 0xf2, 0xc0, 0xae, 0xee, 0x1e, 0x7f, 0x60, 0xd2, 0xe4,
|
||||
0x29, 0x07, 0x1d, 0x7c, 0xc8, 0xd4, 0x69, 0x9f, 0x9a, 0x7e, 0xe8, 0x61, 0x9f, 0x3e, 0xfc, 0x88,
|
||||
0x19, 0x47, 0x1e, 0x35, 0xf3, 0xe8, 0x63, 0x8e, 0x3d, 0x6e, 0x56, 0xef, 0xf1, 0x27, 0x7c, 0x66,
|
||||
0xf6, 0x89, 0x27, 0x9d, 0x1c, 0xfc, 0xec, 0x29, 0xa7, 0xf6, 0x9d, 0x36, 0x67, 0xae, 0xd8, 0x7f,
|
||||
0xfa, 0x19, 0xf3, 0x06, 0xce, 0x3c, 0x2b, 0xf4, 0xb9, 0xb3, 0xcf, 0xf9, 0xfc, 0xb9, 0xe7, 0x7d,
|
||||
0xe1, 0x7c, 0x29, 0x3c, 0xff, 0x8b, 0x17, 0x5c, 0xf8, 0xa5, 0x8b, 0x22, 0x5f, 0xbe, 0xf8, 0x2b,
|
||||
0x5f, 0xbd, 0xe4, 0xd2, 0xc1, 0xe8, 0xd7, 0x2e, 0xfb, 0xfa, 0xe5, 0x57, 0x5c, 0xf9, 0x8d, 0xd8,
|
||||
0x37, 0xaf, 0x5a, 0xb0, 0x70, 0xd1, 0xb7, 0xae, 0x1e, 0x92, 0xaf, 0x59, 0x7c, 0xed, 0x75, 0xd7,
|
||||
0x7f, 0xfb, 0x86, 0xf8, 0x8d, 0x37, 0x7d, 0xe7, 0xbb, 0x37, 0x7f, 0xef, 0x96, 0xc4, 0xad, 0xb7,
|
||||
0x7d, 0xff, 0x07, 0x3f, 0xbc, 0xfd, 0x8e, 0xe1, 0x3b, 0xef, 0x5a, 0x72, 0xf7, 0xd2, 0x1f, 0xdd,
|
||||
0x73, 0x6f, 0xf2, 0xbe, 0xfb, 0x1f, 0x78, 0xf0, 0xc7, 0xcb, 0x1e, 0x4a, 0xfd, 0x64, 0xf9, 0x4f,
|
||||
0x57, 0x3c, 0xbc, 0x72, 0x24, 0xfd, 0xc8, 0xcf, 0x7e, 0xfe, 0x8b, 0x47, 0x7f, 0xf9, 0x58, 0xe6,
|
||||
0xf1, 0x55, 0x4f, 0xfc, 0xea, 0xd7, 0xab, 0x9f, 0xfc, 0x4d, 0x76, 0xcd, 0x6f, 0x9f, 0x7a, 0xfa,
|
||||
0x99, 0xdf, 0xfd, 0x3e, 0xb7, 0xf6, 0xd9, 0x3f, 0x3c, 0xf7, 0xfc, 0x0b, 0x7f, 0xcc, 0xaf, 0x7b,
|
||||
0xf1, 0xa5, 0x97, 0xd7, 0xbf, 0xf2, 0x6a, 0x61, 0xc3, 0x9f, 0x36, 0xfe, 0xf9, 0xb5, 0xbf, 0xbc,
|
||||
0xbe, 0x49, 0x79, 0xe3, 0xaf, 0x6f, 0xbe, 0xf5, 0xf6, 0x3b, 0x9b, 0x47, 0xdf, 0xfd, 0xdb, 0x96,
|
||||
0xbf, 0xff, 0xe3, 0xbd, 0xad, 0xc5, 0xf7, 0xff, 0xf9, 0xc1, 0xbf, 0xfe, 0xfd, 0x9f, 0xff, 0x22,
|
||||
0xb5, 0xde, 0x38, 0x01, 0xe0, 0xb6, 0x0f, 0xe6, 0xb6, 0xb9, 0x70, 0x36, 0x06, 0xbd, 0x97, 0x7a,
|
||||
0xe7, 0x7a, 0xcb, 0x6b, 0x5e, 0xfd, 0x5a, 0xab, 0x6d, 0x6b, 0x1d, 0x06, 0xbd, 0x18, 0x25, 0x06,
|
||||
0xbc, 0x83, 0x5e, 0xfd, 0x5a, 0xab, 0x6d, 0x6b, 0x35, 0x2b, 0x98, 0x81, 0x4b, 0x2b, 0xac, 0xd0,
|
||||
0xb5, 0x56, 0xdb, 0x66, 0x07, 0x56, 0x06, 0x75, 0xac, 0x0c, 0xba, 0xac, 0xb8, 0xac, 0x70, 0x59,
|
||||
0x71, 0xeb, 0x15, 0x33, 0x2b, 0x73, 0xcb, 0x3c, 0xcc, 0xf5, 0xea, 0xd7, 0x5a, 0x6d, 0x9b, 0x0b,
|
||||
0x7b, 0xa1, 0xe2, 0x1d, 0x95, 0x6b, 0x48, 0x5b, 0x6b, 0xb5, 0x6d, 0xad, 0x65, 0xc5, 0xad, 0x57,
|
||||
0xf8, 0xac, 0x0c, 0x7a, 0xe7, 0x7a, 0x75, 0x6d, 0x90, 0xd7, 0x6d, 0x83, 0x5c, 0x56, 0xb6, 0x9d,
|
||||
0x95, 0xe9, 0x5e, 0xe7, 0x20, 0x5a, 0x42, 0xbf, 0xba, 0xd4, 0x5f, 0x5e, 0xa6, 0x6b, 0xfd, 0x06,
|
||||
0xcd, 0x0e, 0xf7, 0xc3, 0xf9, 0x4c, 0x70, 0xe1, 0xa2, 0x4e, 0x4c, 0x11, 0x5c, 0x98, 0x11, 0x10,
|
||||
0x26, 0x8d, 0x01, 0x02, 0xdb, 0x8c, 0xb1, 0xb0, 0xa6, 0x31, 0x04, 0x4b, 0xf6, 0xd7, 0x3c, 0x42,
|
||||
0x8f, 0x9f, 0x81, 0x26, 0xd5, 0xe4, 0x01, 0x0f, 0xd5, 0xeb, 0xa9, 0x40, 0x95, 0xaa, 0x65, 0xb3,
|
||||
0x12, 0x2a, 0xd3, 0x4b, 0xcb, 0xb2, 0x52, 0x39, 0x64, 0x9d, 0x2d, 0xb3, 0x96, 0x35, 0xac, 0x66,
|
||||
0xc0, 0x24, 0x0b, 0x70, 0xf5, 0xf8, 0x3c, 0x18, 0xcf, 0x6a, 0x75, 0x4e, 0xfc, 0x9e, 0xb0, 0x20,
|
||||
0x33, 0x08, 0x0b, 0x98, 0x19, 0xbd, 0x34, 0x2c, 0xe0, 0xe3, 0x31, 0xea, 0xf1, 0x65, 0x01, 0xa1,
|
||||
0xa7, 0xe6, 0xbe, 0x54, 0x6e, 0xb6, 0xc6, 0x5a, 0xb3, 0x76, 0xa9, 0xfc, 0x12, 0x2d, 0xb8, 0xaf,
|
||||
0xca, 0x4b, 0x40, 0x2d, 0x39, 0x2f, 0x86, 0x24, 0x0d, 0xc5, 0xd0, 0x1b, 0xbe, 0x6e, 0xcf, 0x1b,
|
||||
0xbe, 0x62, 0x48, 0x2f, 0x93, 0x3c, 0x46, 0x3d, 0xa5, 0x5d, 0xe2, 0xec, 0xdb, 0x65, 0xda, 0xd7,
|
||||
0xac, 0x47, 0x75, 0x8d, 0x47, 0x61, 0xb6, 0xc6, 0xba, 0x54, 0x9e, 0x45, 0xe6, 0x12, 0xb7, 0x95,
|
||||
0x15, 0x59, 0x08, 0x49, 0x68, 0x21, 0x5a, 0x18, 0x8b, 0x84, 0xa4, 0x58, 0x04, 0x2f, 0x8d, 0xf4,
|
||||
0x49, 0x42, 0x31, 0x44, 0x65, 0x58, 0x9a, 0x89, 0x16, 0x43, 0xaa, 0x6c, 0x9e, 0x5e, 0x86, 0xf5,
|
||||
0x58, 0xbb, 0xa8, 0xcc, 0xb8, 0xef, 0x48, 0xdf, 0x50, 0xe9, 0x37, 0x62, 0x11, 0x52, 0x3e, 0x59,
|
||||
0xc2, 0x65, 0x86, 0x05, 0xbd, 0xd7, 0xfb, 0xcb, 0xd6, 0x98, 0x35, 0x25, 0x61, 0xa4, 0xaf, 0xb6,
|
||||
0x45, 0xe6, 0x12, 0xad, 0xae, 0xa8, 0xfa, 0x58, 0x89, 0x45, 0x84, 0x4e, 0xc5, 0x17, 0x09, 0x60,
|
||||
0x6b, 0xb4, 0xa3, 0x88, 0x04, 0x84, 0x4e, 0xa1, 0x13, 0x4b, 0x43, 0xd2, 0x90, 0xb0, 0x75, 0x1e,
|
||||
0x96, 0x29, 0x3e, 0xec, 0xad, 0x8a, 0x2f, 0x16, 0x99, 0x71, 0xee, 0xf9, 0xb0, 0xc9, 0x87, 0xf7,
|
||||
0x93, 0xbd, 0x54, 0xb6, 0x75, 0x1e, 0xdd, 0x57, 0xd3, 0x23, 0x32, 0x2c, 0xc1, 0x6b, 0x64, 0x1b,
|
||||
0x5e, 0x0a, 0x49, 0xb2, 0xe0, 0xe7, 0xb0, 0xc2, 0xd3, 0xa4, 0xbf, 0xce, 0xb3, 0x08, 0x5b, 0x40,
|
||||
0x65, 0xc6, 0x12, 0x29, 0x0b, 0x41, 0xdd, 0xda, 0xa4, 0x1a, 0x35, 0x3f, 0x65, 0x25, 0x24, 0x29,
|
||||
0xbe, 0xbc, 0x48, 0x2c, 0xd9, 0xd4, 0x4e, 0x64, 0x98, 0xfb, 0xb4, 0x98, 0x16, 0x8b, 0xa1, 0x4c,
|
||||
0x94, 0xda, 0x80, 0x7f, 0xb7, 0xdb, 0xd3, 0x5d, 0xda, 0xab, 0x38, 0x8f, 0xf8, 0x4a, 0x5e, 0x94,
|
||||
0x84, 0x2e, 0x4f, 0x57, 0x49, 0x46, 0x59, 0x61, 0xf5, 0x88, 0x2c, 0x24, 0x49, 0x82, 0x54, 0xde,
|
||||
0x46, 0x96, 0xac, 0x58, 0xe1, 0x69, 0x92, 0x5f, 0xe7, 0x5b, 0x94, 0xf5, 0x89, 0xbd, 0x69, 0x31,
|
||||
0x2f, 0xce, 0x50, 0x2d, 0xb1, 0xf2, 0x15, 0x8d, 0x97, 0x60, 0x09, 0xd5, 0x59, 0xf1, 0x57, 0x58,
|
||||
0x11, 0x3a, 0xe9, 0x95, 0x44, 0x59, 0x61, 0xcf, 0x37, 0xcb, 0x0a, 0xae, 0xe7, 0x58, 0x06, 0x58,
|
||||
0x3d, 0xcc, 0x14, 0xbe, 0x82, 0xcc, 0xbe, 0xd2, 0x0c, 0x56, 0x2c, 0x2c, 0xf2, 0x4a, 0x35, 0xea,
|
||||
0xdb, 0xa0, 0x05, 0x2b, 0x56, 0xbc, 0xd0, 0xfa, 0x2d, 0x2f, 0x62, 0x5f, 0xc1, 0xbf, 0x3f, 0x43,
|
||||
0x9a, 0x36, 0x9b, 0xfa, 0x00, 0xad, 0xe9, 0xf3, 0x22, 0xf6, 0x87, 0x68, 0x1f, 0x91, 0xe1, 0x56,
|
||||
0x10, 0xcb, 0xa2, 0xe5, 0x7a, 0x05, 0x9f, 0x23, 0x7c, 0x06, 0xc9, 0xd9, 0x92, 0x4a, 0xf5, 0x22,
|
||||
0x2b, 0x23, 0x7a, 0xb8, 0x04, 0xcd, 0xb7, 0x88, 0xc4, 0x78, 0x66, 0x03, 0x95, 0xdf, 0x32, 0x6a,
|
||||
0x6a, 0xbf, 0xce, 0xb3, 0xa8, 0xa7, 0xd2, 0x36, 0x07, 0x2d, 0x8e, 0xb3, 0x31, 0x56, 0x68, 0x8b,
|
||||
0x17, 0x16, 0xba, 0x21, 0x5c, 0x61, 0xbc, 0xab, 0x2c, 0x23, 0xcc, 0x63, 0x0d, 0x56, 0x86, 0x4b,
|
||||
0x63, 0x65, 0xb5, 0xdb, 0xeb, 0xae, 0x92, 0x36, 0xdd, 0x42, 0x97, 0x78, 0x67, 0xb6, 0xc7, 0x42,
|
||||
0xb3, 0xba, 0x45, 0x6c, 0x8d, 0xc1, 0xe7, 0x23, 0xa8, 0x5b, 0xd7, 0x58, 0xa9, 0x56, 0xb7, 0x60,
|
||||
0x96, 0xb5, 0x5e, 0x1b, 0x3e, 0x7f, 0x01, 0x5d, 0xaf, 0xa8, 0xb4, 0xb5, 0xd4, 0x37, 0xa3, 0xfd,
|
||||
0xb4, 0x40, 0xc9, 0x63, 0xb4, 0xfe, 0x9a, 0x9f, 0xe9, 0xb3, 0xf1, 0x7a, 0x57, 0x01, 0xa6, 0xdf,
|
||||
0x45, 0x97, 0xf8, 0x35, 0x80, 0x95, 0xa6, 0xd9, 0x22, 0xa3, 0xcc, 0x1a, 0x46, 0xb6, 0x58, 0x56,
|
||||
0x9a, 0xd3, 0xdb, 0xb6, 0x4f, 0xcf, 0x7d, 0x7b, 0xd0, 0xea, 0x38, 0xcc, 0x9e, 0x68, 0x75, 0xcc,
|
||||
0x6e, 0x4f, 0xb8, 0x1f, 0xde, 0xa7, 0xd5, 0x63, 0xa9, 0xf6, 0xc4, 0xb6, 0x8e, 0x97, 0x8b, 0x0d,
|
||||
0xfe, 0x8e, 0xe8, 0xb5, 0xcb, 0xde, 0x63, 0x89, 0xe9, 0xde, 0xf1, 0xbe, 0xfa, 0x3d, 0x72, 0xbc,
|
||||
0x4f, 0xcf, 0x7f, 0x2b, 0xf7, 0x1e, 0x5b, 0x56, 0xea, 0xb7, 0x0b, 0x7f, 0x8c, 0xc7, 0xd5, 0xba,
|
||||
0xbd, 0xc7, 0x96, 0x95, 0x71, 0xbe, 0x43, 0xeb, 0xf4, 0xe0, 0x43, 0x55, 0x5d, 0xe3, 0x71, 0xb5,
|
||||
0x6e, 0xef, 0xb1, 0x84, 0xd8, 0xc0, 0xf5, 0x6a, 0xd6, 0x6d, 0xe5, 0xde, 0x2e, 0x76, 0x0c, 0x5c,
|
||||
0xe6, 0x79, 0x98, 0xbe, 0x43, 0xaf, 0x52, 0xfb, 0xc0, 0x38, 0xb3, 0x10, 0xf0, 0xe8, 0x59, 0xd9,
|
||||
0x91, 0xed, 0x9c, 0x5d, 0x60, 0x9e, 0x59, 0xc0, 0xe3, 0x13, 0x4e, 0x67, 0xc5, 0x3c, 0xb3, 0x40,
|
||||
0x46, 0xc4, 0x9c, 0xcd, 0x0a, 0x3b, 0xcf, 0x61, 0x66, 0x45, 0x54, 0x5b, 0xff, 0x09, 0xbe, 0xc3,
|
||||
0xda, 0x1b, 0xeb, 0x6f, 0xdb, 0x07, 0xdb, 0xda, 0x4e, 0x84, 0xcb, 0x63, 0xcd, 0x64, 0x06, 0x01,
|
||||
0x43, 0xf1, 0x75, 0x03, 0x65, 0x05, 0xd7, 0xb5, 0x13, 0x3b, 0x26, 0xf8, 0xc6, 0xff, 0x5f, 0x62,
|
||||
0xdb, 0xdb, 0x89, 0x1e, 0x8f, 0x52, 0x19, 0x6b, 0xc6, 0x23, 0xcd, 0xae, 0xaf, 0x10, 0x56, 0xf0,
|
||||
0xbc, 0x01, 0xf1, 0x12, 0x32, 0x27, 0x46, 0xe6, 0xdb, 0xe8, 0x76, 0x67, 0xd6, 0x2b, 0xf3, 0x05,
|
||||
0x3c, 0xa3, 0x94, 0xae, 0xcc, 0x4a, 0x90, 0xb9, 0x59, 0x6d, 0xbb, 0x33, 0x59, 0xe1, 0xcd, 0xe3,
|
||||
0xb3, 0xdb, 0x9d, 0xc9, 0x8a, 0xb1, 0x17, 0x17, 0x70, 0x7b, 0x71, 0x6d, 0xd4, 0x57, 0xa8, 0x87,
|
||||
0xd0, 0x39, 0x29, 0xa7, 0xb3, 0x12, 0xae, 0xcc, 0x95, 0x62, 0x2f, 0x09, 0x57, 0xe6, 0x35, 0x9d,
|
||||
0xcd, 0x8a, 0x5c, 0xb9, 0x63, 0x80, 0xce, 0xa1, 0x93, 0x39, 0x70, 0xb2, 0xd5, 0xa9, 0x2d, 0x33,
|
||||
0xef, 0x6e, 0x03, 0x8d, 0x15, 0xa7, 0xf6, 0xe2, 0xc2, 0xba, 0xbb, 0x08, 0xc8, 0x7d, 0x20, 0xae,
|
||||
0xaf, 0xe8, 0x5b, 0x66, 0xa3, 0xaf, 0x38, 0xb5, 0x5e, 0x61, 0x5b, 0xe6, 0x1e, 0xb7, 0xb6, 0xe5,
|
||||
0xc2, 0x6d, 0x99, 0x35, 0xb0, 0x77, 0x03, 0xbb, 0xbd, 0x38, 0x82, 0xea, 0x7d, 0x7e, 0x67, 0xb2,
|
||||
0xe2, 0xe7, 0xde, 0x75, 0xdc, 0xe3, 0xf0, 0x7a, 0x05, 0xb3, 0x42, 0xee, 0x12, 0xd6, 0xa0, 0x8d,
|
||||
0x25, 0x38, 0xb5, 0x65, 0xe6, 0x8d, 0xb0, 0x68, 0x6d, 0xb3, 0x53, 0x7b, 0x71, 0x98, 0x15, 0xed,
|
||||
0x3e, 0x73, 0x72, 0x5f, 0xb8, 0xc6, 0x8a, 0xeb, 0x2b, 0xfc, 0xd1, 0x38, 0x67, 0xd6, 0x2b, 0x01,
|
||||
0x4f, 0xf5, 0xd1, 0x38, 0x67, 0xb2, 0xe2, 0xb6, 0xcc, 0x56, 0x30, 0x8e, 0xc6, 0xb1, 0xdb, 0x9c,
|
||||
0xca, 0x8a, 0xeb, 0x2b, 0x66, 0xb8, 0xbd, 0x38, 0x2b, 0x56, 0x78, 0xbd, 0x38, 0x67, 0xb7, 0xcc,
|
||||
0x7e, 0x4f, 0x37, 0x04, 0x3b, 0x69, 0xbb, 0x6c, 0x64, 0xc5, 0xa9, 0xbd, 0x38, 0xcd, 0x57, 0xe8,
|
||||
0xfc, 0x7b, 0x31, 0xa4, 0x54, 0xae, 0x20, 0xa7, 0xfa, 0x4a, 0x4f, 0xe5, 0x39, 0x43, 0x3a, 0xff,
|
||||
0x8e, 0x47, 0x70, 0xdd, 0x7a, 0x45, 0x3f, 0x72, 0x8b, 0x21, 0xf6, 0xce, 0x67, 0xc6, 0xb3, 0x9d,
|
||||
0xc8, 0x4a, 0xad, 0xbb, 0x9d, 0x9c, 0xca, 0x0a, 0x1d, 0x8b, 0xd3, 0x9e, 0x01, 0xf3, 0x3b, 0xbe,
|
||||
0xbf, 0x42, 0xa0, 0x9f, 0x57, 0x65, 0xe1, 0x5c, 0x56, 0xe8, 0x73, 0xa9, 0xc6, 0xbb, 0x34, 0x5c,
|
||||
0x56, 0x48, 0xeb, 0xac, 0xbf, 0xa3, 0xc7, 0xb9, 0x2d, 0x33, 0x01, 0xbe, 0x0f, 0x4c, 0x3f, 0x0a,
|
||||
0x47, 0xe0, 0xd4, 0x5e, 0x1c, 0x81, 0xf6, 0xc4, 0xbb, 0x9e, 0x15, 0x67, 0xfb, 0x8a, 0x15, 0x2b,
|
||||
0x4e, 0xae, 0x57, 0xb4, 0xfa, 0x56, 0x3f, 0x9b, 0xea, 0x74, 0x56, 0xd8, 0xb6, 0x79, 0x92, 0xe0,
|
||||
0xb2, 0xa2, 0x81, 0x3e, 0x4d, 0xaf, 0x97, 0x3a, 0xf5, 0x99, 0x8f, 0xea, 0x70, 0x9f, 0x0f, 0xaa,
|
||||
0x0e, 0xf7, 0x09, 0x3b, 0x1e, 0xdc, 0xa7, 0x31, 0xf9, 0xac, 0xb4, 0xee, 0xd9, 0x5b, 0x3b, 0x3f,
|
||||
0xb9, 0xcb, 0x7b, 0xd2, 0x7a, 0x62, 0xc7, 0x7e, 0xea, 0x9f, 0xf9, 0x53, 0xdf, 0x73, 0xda, 0x3b,
|
||||
0x66, 0xef, 0xb1, 0x04, 0xef, 0xa9, 0xfc, 0xc3, 0xda, 0x3b, 0x54, 0xcb, 0x3a, 0x3a, 0x78, 0xbd,
|
||||
0xdf, 0xda, 0xcf, 0xf4, 0xef, 0xa8, 0xbd, 0xeb, 0x3b, 0xe7, 0xcd, 0x43, 0x35, 0xcb, 0xaa, 0x03,
|
||||
0xdb, 0x8d, 0xaf, 0x8b, 0xfd, 0xca, 0xfe, 0xde, 0x68, 0x26, 0x84, 0xed, 0xf9, 0x6d, 0x1e, 0xc6,
|
||||
0xf9, 0x9a, 0x89, 0xf1, 0x1d, 0x13, 0x3a, 0xc6, 0x77, 0x34, 0xbc, 0x57, 0xc9, 0xc7, 0x59, 0x56,
|
||||
0xf0, 0x35, 0xd2, 0x68, 0x29, 0x24, 0x73, 0x4a, 0x73, 0x8e, 0xa3, 0xd5, 0x59, 0x71, 0xa6, 0x08,
|
||||
0x87, 0xb4, 0x8d, 0xe3, 0xb0, 0x32, 0xce, 0x77, 0x48, 0x5b, 0xeb, 0x6c, 0xaa, 0xe4, 0x63, 0x62,
|
||||
0xee, 0x0f, 0xd4, 0x4b, 0x8c, 0x99, 0x41, 0x8d, 0xb9, 0x41, 0x79, 0xb9, 0x4a, 0x79, 0xd9, 0x4a,
|
||||
0x79, 0xd9, 0xb0, 0x48, 0x0e, 0x25, 0x3e, 0x2b, 0x53, 0x98, 0x3c, 0x4b, 0xe6, 0x2c, 0x58, 0x6c,
|
||||
0xd6, 0xab, 0xda, 0x99, 0x4a, 0x79, 0xf9, 0xb5, 0xf4, 0x92, 0x20, 0x27, 0xbb, 0x93, 0x79, 0x76,
|
||||
0xb9, 0xbb, 0x8e, 0x5c, 0xa5, 0x32, 0x27, 0xfb, 0x19, 0x2f, 0x2f, 0xa9, 0x6c, 0x91, 0x39, 0x0d,
|
||||
0x47, 0x59, 0x81, 0x3a, 0x58, 0x31, 0x67, 0x4c, 0xd3, 0x67, 0x48, 0xab, 0x95, 0xa9, 0xd4, 0xca,
|
||||
0x1a, 0xbd, 0x96, 0x99, 0x13, 0x7d, 0xc6, 0x4f, 0x92, 0x9f, 0x0e, 0xe7, 0xa0, 0xab, 0x9e, 0xab,
|
||||
0x34, 0x24, 0x45, 0xfb, 0xea, 0xc9, 0x4b, 0xaa, 0xe9, 0xb1, 0x59, 0xf6, 0xc8, 0x72, 0x6d, 0x56,
|
||||
0xb4, 0x08, 0x5e, 0xcb, 0x99, 0x47, 0xbf, 0x95, 0xf6, 0x5a, 0x99, 0x4a, 0xcd, 0x5a, 0x56, 0x56,
|
||||
0xf7, 0x98, 0x32, 0xf6, 0xd1, 0xf9, 0x42, 0x6d, 0x6e, 0x99, 0x9f, 0x83, 0xd4, 0xa8, 0x47, 0x33,
|
||||
0x75, 0x56, 0xcb, 0x69, 0x5a, 0xb2, 0x63, 0xb6, 0x39, 0xff, 0x24, 0xcd, 0xa8, 0x58, 0x8b, 0x15,
|
||||
0x6d, 0xb4, 0x87, 0xe6, 0x57, 0xd4, 0xf2, 0x2c, 0xf2, 0x32, 0x95, 0x46, 0xfb, 0xb4, 0x8c, 0xa6,
|
||||
0x84, 0x15, 0xaa, 0x55, 0xcd, 0x6a, 0x63, 0x3e, 0x53, 0x3f, 0x33, 0x5f, 0x48, 0xee, 0xfd, 0xc2,
|
||||
0x99, 0x40, 0x25, 0x0f, 0x3f, 0xb7, 0xa8, 0x5e, 0x4f, 0xcb, 0x49, 0xc9, 0xcb, 0x69, 0x4a, 0xf6,
|
||||
0x95, 0xbd, 0x58, 0xcf, 0x98, 0x7f, 0x12, 0x9f, 0x1f, 0x62, 0xc7, 0xf6, 0xb0, 0x62, 0xce, 0x54,
|
||||
0x2a, 0x0b, 0x92, 0x47, 0xcb, 0x68, 0x8a, 0xaf, 0x0d, 0x7a, 0x24, 0xd5, 0xad, 0xb6, 0x62, 0x85,
|
||||
0xe4, 0x25, 0xa5, 0x5e, 0x47, 0xca, 0x22, 0xe7, 0xd3, 0x6f, 0xc8, 0x37, 0xaa, 0xe9, 0x9d, 0x5f,
|
||||
0x25, 0xa7, 0x29, 0xde, 0x17, 0xe7, 0x2a, 0x2d, 0x7b, 0x7b, 0x39, 0xff, 0x24, 0xfe, 0xc3, 0xff,
|
||||
0xe7, 0x45, 0xea, 0xb3, 0xdb, 0xcb, 0x8a, 0x3e, 0x53, 0x29, 0xf6, 0x45, 0xf3, 0x53, 0x4e, 0xb5,
|
||||
0xad, 0xc6, 0xb3, 0xe9, 0x41, 0xce, 0x15, 0x44, 0x33, 0xc1, 0x92, 0xb9, 0x65, 0x8d, 0x15, 0x5c,
|
||||
0xdb, 0xd3, 0xcc, 0xac, 0x46, 0x3d, 0x89, 0x9b, 0xd3, 0x94, 0xef, 0x17, 0xa4, 0xce, 0xc3, 0xe7,
|
||||
0x11, 0x6f, 0xd1, 0xea, 0xb7, 0x7a, 0x59, 0xa1, 0xd9, 0x6c, 0xcd, 0x59, 0x6d, 0xf5, 0x4f, 0x33,
|
||||
0xf5, 0xe8, 0xc6, 0x57, 0x79, 0x47, 0xc7, 0xb3, 0x5a, 0xcf, 0x4a, 0xa0, 0x52, 0xdb, 0xea, 0xe7,
|
||||
0x96, 0xb5, 0x8c, 0x9f, 0xda, 0xb3, 0x76, 0x92, 0x49, 0x6f, 0xea, 0x31, 0x92, 0x29, 0xa7, 0x69,
|
||||
0x34, 0x68, 0xcc, 0x4b, 0x4a, 0xfd, 0x22, 0xc0, 0x3c, 0x47, 0xa2, 0xd5, 0x6d, 0xd6, 0xac, 0x04,
|
||||
0x74, 0xb5, 0x2d, 0x2e, 0x0f, 0xdf, 0xbf, 0x48, 0xbf, 0xf9, 0x99, 0x4a, 0xc3, 0x82, 0xdf, 0xc3,
|
||||
0x8e, 0xaf, 0xf2, 0x8e, 0x8e, 0x6f, 0xf5, 0x7c, 0xe6, 0x0a, 0x0a, 0x58, 0xb4, 0xcc, 0xbc, 0x2c,
|
||||
0xa0, 0xd6, 0x6d, 0x9c, 0xfa, 0xcd, 0xe4, 0x34, 0xe5, 0xb5, 0x98, 0x34, 0x33, 0xa5, 0x39, 0x1b,
|
||||
0x69, 0x2d, 0x56, 0xf8, 0x39, 0xc4, 0xad, 0x6d, 0x64, 0x5b, 0x72, 0xab, 0x7e, 0x07, 0xdd, 0xb3,
|
||||
0x5b, 0x67, 0x35, 0x73, 0xfd, 0x54, 0xce, 0x08, 0xaf, 0x9f, 0x63, 0xcc, 0x02, 0x6a, 0xd6, 0xa3,
|
||||
0xbd, 0x33, 0x9a, 0x39, 0x5e, 0x9f, 0x73, 0xde, 0xcf, 0x48, 0x8c, 0x25, 0xd5, 0xcf, 0x0a, 0x2f,
|
||||
0xdf, 0x7c, 0x35, 0x1b, 0xcd, 0xd9, 0x4a, 0xad, 0x8e, 0x4e, 0x9f, 0x89, 0xd5, 0x4e, 0xd9, 0x39,
|
||||
0xed, 0xd8, 0xe3, 0x6f, 0x52, 0x54, 0xd8, 0x9c, 0x52, 0x9a, 0x10, 0xdf, 0x35, 0xc7, 0x92, 0xe6,
|
||||
0x8c, 0x21, 0xb4, 0xf6, 0xcc, 0x1a, 0xfd, 0x6e, 0xfb, 0xd1, 0x9c, 0x71, 0x39, 0xda, 0x8e, 0xb2,
|
||||
0x31, 0x66, 0xf5, 0x9a, 0xa8, 0xf1, 0x77, 0x5f, 0x90, 0xd2, 0xfc, 0xe5, 0x25, 0x7e, 0xec, 0x4a,
|
||||
0xeb, 0x28, 0x3b, 0x80, 0xb2, 0x62, 0xae, 0xeb, 0xfd, 0x75, 0x46, 0x66, 0x8d, 0xbd, 0xfb, 0xc2,
|
||||
0x3a, 0xba, 0xb3, 0x1f, 0x2b, 0xe6, 0xf7, 0x4d, 0xd0, 0x1e, 0x4e, 0xad, 0xb8, 0xb3, 0xd1, 0x77,
|
||||
0x5f, 0x58, 0x47, 0x77, 0xf6, 0x63, 0x65, 0x92, 0x80, 0x59, 0x61, 0x23, 0xb3, 0x28, 0x27, 0x9e,
|
||||
0xd4, 0xc7, 0x9d, 0x34, 0x9e, 0xe4, 0x45, 0x6b, 0xe6, 0xb7, 0x54, 0x50, 0x3d, 0x1a, 0x7b, 0x98,
|
||||
0xdf, 0x56, 0x61, 0x47, 0x56, 0x70, 0xaf, 0x92, 0x8d, 0xcc, 0x24, 0x4e, 0xdc, 0xb9, 0xa9, 0x12,
|
||||
0x77, 0xf2, 0xe2, 0x49, 0x36, 0x5a, 0x23, 0xec, 0xb1, 0xb1, 0x1f, 0x65, 0x83, 0xf7, 0xfe, 0x03,
|
||||
0xd2, 0xbf, 0xb7, 0x23, 0x2b, 0x6c, 0x24, 0x27, 0x97, 0xea, 0x94, 0x6a, 0x71, 0x27, 0x2f, 0x9e,
|
||||
0x64, 0xa3, 0x35, 0xa2, 0xc7, 0xc6, 0x7e, 0x46, 0x56, 0xcc, 0x59, 0x2e, 0xec, 0xc9, 0x4a, 0xa0,
|
||||
0x66, 0x64, 0x36, 0x54, 0x61, 0xc5, 0xfc, 0x8e, 0x0c, 0x7d, 0xb4, 0x66, 0x3d, 0x96, 0xc1, 0xb2,
|
||||
0x42, 0x23, 0x7a, 0x7b, 0xb3, 0x52, 0x2b, 0x32, 0xd3, 0xe2, 0x4e, 0xde, 0x3b, 0x32, 0x74, 0x31,
|
||||
0xa6, 0x29, 0xf6, 0xa3, 0xb5, 0x2c, 0x3b, 0xb2, 0xa7, 0xcf, 0x13, 0x63, 0x4f, 0x56, 0x1a, 0x89,
|
||||
0xcc, 0xba, 0x38, 0xef, 0xc8, 0xa8, 0xf7, 0xbd, 0x19, 0x56, 0x71, 0xa1, 0x5d, 0x59, 0xa9, 0x16,
|
||||
0x99, 0xe9, 0x47, 0xfb, 0xf5, 0xf1, 0xa4, 0xdf, 0xa8, 0x55, 0xe3, 0x2d, 0x15, 0xfc, 0xb8, 0xd0,
|
||||
0x6e, 0xac, 0xd8, 0xa9, 0xc7, 0xdf, 0x6a, 0x3e, 0x28, 0x2b, 0xcd, 0x89, 0xc9, 0x9a, 0x01, 0xfb,
|
||||
0xdc, 0xa1, 0xd6, 0xf8, 0xac, 0xf0, 0x58, 0xc2, 0xbd, 0x17, 0xcb, 0x85, 0x0b, 0x17, 0x2e, 0x5c,
|
||||
0xb8, 0x70, 0xe1, 0xc2, 0x85, 0x0b, 0x17, 0x2e, 0x5c, 0xb8, 0x70, 0xb1, 0x63, 0xf1, 0x3f, 0x53,
|
||||
0xd1, 0xe8, 0xeb, 0x3a, 0x9b, 0x00, 0x00
|
||||
};
|
||||
|
||||
#endif // SCUMM_HE_MOONBASE_MAP_DATA_H
|
||||
797
engines/scumm/he/moonbase/map_katton.cpp
Normal file
797
engines/scumm/he/moonbase/map_katton.cpp
Normal file
@@ -0,0 +1,797 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scumm/he/moonbase/map_katton.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
KattonGenerator::KattonGenerator(int seed) {
|
||||
_seed = seed;
|
||||
}
|
||||
|
||||
int KattonGenerator::getRandomNumber() {
|
||||
// This is the exact linear congruential generator
|
||||
// algorithm used on MSVCRT (Windows Visual C++ Runtime), with
|
||||
// RAND_MAX being 0x7fff (32767). This is implemented here
|
||||
// to match the RNG between the original Moonbase Console
|
||||
// program and ScummVM.
|
||||
//
|
||||
// (Common::RandomSource uses Xorshift and uses unsigned
|
||||
// integers compared to MSVCRT's rand)
|
||||
_seed = _seed * 214013 + 2531011;
|
||||
return (_seed >> 16) & 0x7fff;
|
||||
}
|
||||
|
||||
MapFile *KattonGenerator::generateMap(int water, int tileSet, int mapSize, int energy, int terrain) {
|
||||
_size = mapSize;
|
||||
_tileset = tileSet;
|
||||
int inEnergy = energy;
|
||||
int inTerrain = terrain;
|
||||
int inWater = water;
|
||||
|
||||
if (!(inEnergy == 0)) {
|
||||
inEnergy = inEnergy * 14 + plusminus(14);
|
||||
}
|
||||
|
||||
if (!(inTerrain == 0)) {
|
||||
inTerrain = inTerrain * 14 + plusminus(14);
|
||||
}
|
||||
|
||||
if (!(inWater == 0)) {
|
||||
inWater = inWater * 14 + plusminus(14);
|
||||
}
|
||||
|
||||
float terrainpercent = ((float)inTerrain) / 100;
|
||||
float waterpercent = ((float)inWater) / 100;
|
||||
|
||||
//****************************************Let the generation BEGIN!
|
||||
|
||||
fillboards(0);
|
||||
|
||||
// used everywhere
|
||||
int i, j, k, l, x, y, z;
|
||||
// used in making the basic landmass shapes
|
||||
int numsplotches, length;
|
||||
// used in making water
|
||||
int numwaterplaces = 0, numwatersplotches, multiplier;
|
||||
short int goodwater[1600][2];
|
||||
// used in making energy
|
||||
int maxnumclose = 0, maxnumfar = 0, maxnumrand = 0, smallmed = 0, goodplaceClose[300][2], goodplaceFar[300][2], numplaceClose, numplaceFar, placeFar[3], placeClose[2], counter, counterpools;
|
||||
int stringiness, randomx, randomy;
|
||||
|
||||
//****************************************Make the basic landmass shapes.
|
||||
|
||||
numsplotches = (int)(_size / 4) + (int)((terrainpercent - 0.5) * _size / 2);
|
||||
|
||||
for (i = 0; i < numsplotches; i++) {
|
||||
length = (int)(((1 - waterpercent) / 6 * _size * _size) / numsplotches);
|
||||
length = length + plusminus((int)(length / 2));
|
||||
stringiness = 1 + plusminus(1);
|
||||
randomx = getRandomNumber() % _size;
|
||||
randomy = getRandomNumber() % _size;
|
||||
randomsplotch(length, 1 + stringiness, 2, randomx, randomy);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)numsplotches / 4; i++) {
|
||||
length = (int)(((1 - waterpercent) / 3 * _size * _size) / numsplotches);
|
||||
length = length + plusminus((int)(length / 4));
|
||||
stringiness = 1 + plusminus(1);
|
||||
randomx = getRandomNumber() % _size;
|
||||
randomy = getRandomNumber() % _size;
|
||||
randomsplotch(length, stringiness, 1, randomx, randomy);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)numsplotches / 2; i++) {
|
||||
length = (int)(_size + plusminus((int)(_size / 2)));
|
||||
stringiness = 1 + plusminus(1);
|
||||
randomx = getRandomNumber() % _size;
|
||||
randomy = getRandomNumber() % _size;
|
||||
randomsplotch(length, stringiness, 0, randomx, randomy);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)waterpercent * _size; i++) {
|
||||
length = (int)(_size + plusminus((int)(_size / 2)));
|
||||
stringiness = 1 + plusminus(1);
|
||||
randomx = getRandomNumber() % _size;
|
||||
randomy = getRandomNumber() % _size;
|
||||
randomsplotch(length, stringiness, 0, randomx, randomy);
|
||||
}
|
||||
|
||||
//****************************************Fatten up the landmasses
|
||||
|
||||
// make the highhills bigger
|
||||
fattenall(-3, 2, NEVER_USED_NUM, TEMP_REPLACEMENT_NUMA);
|
||||
replacenum(TEMP_REPLACEMENT_NUMA, 2);
|
||||
|
||||
// make the lowlands bigger, depending on wateriness
|
||||
fattenall(-((int)(waterpercent * 3)), 0, NEVER_USED_NUM, TEMP_REPLACEMENT_NUMA);
|
||||
replacenum(TEMP_REPLACEMENT_NUMA, 2);
|
||||
|
||||
// surround the high hills with at least one med
|
||||
fattenall(2, 2, NEVER_USED_NUM, 1);
|
||||
|
||||
// fatten the medium hills
|
||||
fattenall(-3, 1, 2, TEMP_REPLACEMENT_NUMA);
|
||||
replacenum(TEMP_REPLACEMENT_NUMA, 1);
|
||||
|
||||
//****************************************Smooth out/rough up the landmasses
|
||||
|
||||
randomflip((int)(terrainpercent * terrainpercent * _size * _size / 4 + _size / 4), inWater);
|
||||
|
||||
//****************************************Make the start locations
|
||||
|
||||
findstartloc();
|
||||
|
||||
//****************************************Put down some water
|
||||
|
||||
for (i = 0; i < _size; i += 2) {
|
||||
for (j = 0; j < _size; j += 2) {
|
||||
if (goodforwater(i, j)) {
|
||||
goodwater[numwaterplaces][0] = i;
|
||||
goodwater[numwaterplaces][1] = j;
|
||||
numwaterplaces++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
numwatersplotches = (int)(_size * waterpercent * waterpercent * 5);
|
||||
|
||||
if (numwaterplaces <= numwatersplotches) {
|
||||
numwatersplotches = numwaterplaces;
|
||||
}
|
||||
if (numwatersplotches >= 1) {
|
||||
multiplier = (int)((float)numwaterplaces / (float)numwatersplotches);
|
||||
|
||||
for (i = 0; i < numwatersplotches; i++) {
|
||||
z = getRandomNumber() % multiplier + i * multiplier;
|
||||
x = goodwater[z][0];
|
||||
y = goodwater[z][1];
|
||||
length = _size + plusminus(_size / 2);
|
||||
stringiness = getRandomNumber() % 3;
|
||||
randomwater(length, stringiness, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//****************************************Put down the energy
|
||||
if (inEnergy >= 90) {
|
||||
maxnumclose = 2;
|
||||
maxnumfar = 3;
|
||||
maxnumrand = (int)(_size * _size / 150);
|
||||
smallmed = 2;
|
||||
} else if (inEnergy >= 75) {
|
||||
maxnumclose = 2;
|
||||
maxnumfar = 1;
|
||||
maxnumrand = (int)(_size * _size / 250) + 4;
|
||||
smallmed = 3;
|
||||
} else if (inEnergy >= 60) {
|
||||
maxnumclose = 1;
|
||||
maxnumfar = 2;
|
||||
maxnumrand = (int)(_size * _size / 250);
|
||||
smallmed = 4;
|
||||
} else if (inEnergy >= 45) {
|
||||
maxnumclose = 1;
|
||||
maxnumfar = 1;
|
||||
maxnumrand = (int)(_size * _size / 250);
|
||||
smallmed = 6;
|
||||
} else if (inEnergy >= 30) {
|
||||
maxnumclose = 1;
|
||||
maxnumfar = 0;
|
||||
maxnumrand = (int)(_size * _size / 350) + 2;
|
||||
smallmed = 8;
|
||||
} else if (inEnergy >= 15) {
|
||||
maxnumclose = 0;
|
||||
maxnumfar = 1;
|
||||
maxnumrand = (int)(_size * _size / 450);
|
||||
smallmed = 10;
|
||||
} else if (inEnergy >= 0) {
|
||||
maxnumclose = 0;
|
||||
maxnumfar = 0;
|
||||
maxnumrand = 0;
|
||||
smallmed = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
numplaceClose = 0;
|
||||
numplaceFar = 0;
|
||||
for (j = 0; j < _size; j++) {
|
||||
for (k = 0; k < _size; k++) {
|
||||
if ((goodforenergy(j, k, 0)) && (distance(_startloc[i][0], _startloc[i][1], j, k) >= (int)(_size / 10)) && (distance(_startloc[i][0], _startloc[i][1], j, k) <= (int)(_size / 8))) {
|
||||
goodplaceClose[numplaceClose][0] = j;
|
||||
goodplaceClose[numplaceClose][1] = k;
|
||||
numplaceClose++;
|
||||
} else if ((goodforenergy(j, k, 0)) && (distance(_startloc[i][0], _startloc[i][1], j, k) >= (int)(_size / 7)) && (distance(_startloc[i][0], _startloc[i][1], j, k) <= (int)(_size / 5))) {
|
||||
goodplaceFar[numplaceFar][0] = j;
|
||||
goodplaceFar[numplaceFar][1] = k;
|
||||
numplaceFar++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numplaceClose >= 1) {
|
||||
placeClose[0] = getRandomNumber() % (int)(numplaceClose / 2) + 1;
|
||||
}
|
||||
if (numplaceClose >= 2) {
|
||||
placeClose[1] = getRandomNumber() % (int)(numplaceClose / 2) + (int)(numplaceClose / 2) - 1;
|
||||
}
|
||||
|
||||
if (numplaceClose >= maxnumclose) {
|
||||
for (l = 0; l < maxnumclose; l++) {
|
||||
_special[goodplaceClose[placeClose[l]][0]][goodplaceClose[placeClose[l]][1]] = 100;
|
||||
}
|
||||
} else {
|
||||
for (l = 0; l < numplaceClose; l++) {
|
||||
_special[goodplaceClose[placeClose[l]][0]][goodplaceClose[placeClose[l]][1]] = 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (numplaceFar >= 1) {
|
||||
placeFar[0] = getRandomNumber() % (int)(numplaceFar / 3) + 1;
|
||||
}
|
||||
if (numplaceFar >= 2) {
|
||||
placeFar[1] = getRandomNumber() % (int)(numplaceFar / 3) + (int)(numplaceClose / 3);
|
||||
}
|
||||
if (numplaceFar >= 3) {
|
||||
placeFar[2] = getRandomNumber() % (int)(numplaceFar / 3) + (int)(2 * numplaceClose / 3) - 1;
|
||||
}
|
||||
|
||||
if (numplaceFar >= maxnumfar) {
|
||||
for (l = 0; l < maxnumfar; l++) {
|
||||
_special[goodplaceFar[placeFar[l]][0]][goodplaceFar[placeFar[l]][1]] = 100;
|
||||
}
|
||||
} else {
|
||||
for (l = 0; l < numplaceFar; l++) {
|
||||
_special[goodplaceFar[placeFar[l]][0]][goodplaceFar[placeFar[l]][1]] = 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
counter = 0;
|
||||
counterpools = 4 * (maxnumfar + maxnumclose);
|
||||
for (k = 0; k < maxnumrand && counterpools < 50; k++) {
|
||||
do {
|
||||
i = getRandomNumber() % _size;
|
||||
j = getRandomNumber() % _size;
|
||||
counter++;
|
||||
} while (!((distance(i, j, _startloc[0][0], _startloc[0][1]) >= 10) && (distance(i, j, _startloc[1][0], _startloc[1][1]) >= 10) && (distance(i, j, _startloc[2][0], _startloc[2][1]) >= 10) && (distance(i, j, _startloc[3][0], _startloc[3][1]) >= 10) && (goodforenergy(i, j, 1)) && (counter < 5000)));
|
||||
if (getRandomNumber() % smallmed == 0) {
|
||||
_special[i][j] = 200;
|
||||
counterpools++;
|
||||
} else {
|
||||
_special[i][j] = 100;
|
||||
counterpools++;
|
||||
}
|
||||
}
|
||||
|
||||
//****************************************Do that saving thing that you do, BABY!
|
||||
MIF mif = MIF();
|
||||
Common::sprintf_s(mif._name, "Katton %04X", (uint16)_seed);
|
||||
mif._dimension = _size;
|
||||
mif._mapType = _tileset;
|
||||
for (j = 0; j < _size; j++) {
|
||||
for (i = 0; i < _size; i++)
|
||||
mif._cornerMap[i][j] = _board[i][j];
|
||||
for (i = 0; i < _size; i++)
|
||||
if (_special[i][j] == 0)
|
||||
mif._centerMap[i][j] = '.';
|
||||
else if (_special[i][j] == -1)
|
||||
mif._centerMap[i][j] = 'W';
|
||||
else if (_special[i][j] == 100)
|
||||
mif._centerMap[i][j] = 'S';
|
||||
else if (_special[i][j] == 200)
|
||||
mif._centerMap[i][j] = 'M';
|
||||
else if (_special[i][j] == 300)
|
||||
mif._centerMap[i][j] = 'L';
|
||||
else
|
||||
mif._centerMap[i][j] = -_special[i][j];
|
||||
}
|
||||
|
||||
// Generate new map:
|
||||
MapFile *map = new MapFile();
|
||||
mif.generateMap(map);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
int KattonGenerator::distance(int x1, int y1, int x2, int y2) {
|
||||
int dx, dy, disp;
|
||||
dx = min((abs(x1 - x2)), (abs(x1 + _size - x2)), (abs(x2 + _size - x1)));
|
||||
dy = min((abs(y1 - y2)), (abs(y1 + _size - y2)), (abs(y2 + _size - y1)));
|
||||
disp = (int)sqrt((double)(dx * dx + dy * dy));
|
||||
return disp;
|
||||
}
|
||||
|
||||
int KattonGenerator::min(int a, int b, int c) {
|
||||
if ((a <= b) && (a <= c)) {
|
||||
return a;
|
||||
} else if ((b < a) && (b <= c)) {
|
||||
return b;
|
||||
} else if ((c < a) && (c < b)) {
|
||||
return c;
|
||||
} else {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
int KattonGenerator::goodforenergy(int x, int y, int poolsize) {
|
||||
switch (poolsize) {
|
||||
case 0:
|
||||
if ((_board[x][y] == _board[findcoord(x, +1)][y]) && (_board[findcoord(x, +1)][y] == _board[x][findcoord(y, +1)]) && (_board[x][findcoord(y, +1)] == _board[findcoord(x, +1)][findcoord(y, +1)])) {
|
||||
//check main map
|
||||
if (_special[x][y] == 0) { //specials are clear
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case 1:
|
||||
if ((_board[x][y] == _board[findcoord(x, +1)][y]) && (_board[findcoord(x, +1)][y] == _board[x][findcoord(y, +1)]) && (_board[x][findcoord(y, +1)] == _board[findcoord(x, +1)][findcoord(y, +1)])) { //check main map
|
||||
if ((_special[x][y] == 0) && (_special[findcoord(x, +1)][y] == 0) && (_special[x][findcoord(y, +1)] == 0) && (_special[findcoord(x, +1)][findcoord(y, +1)] == 0)) { //specials are clear
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int KattonGenerator::plusminus(int max) {
|
||||
int result = getRandomNumber() % (max + 1);
|
||||
if (getRandomNumber() % 2 == 0) {
|
||||
result *= (-1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int KattonGenerator::fillboards(int num) {
|
||||
int i, j;
|
||||
for (i = 0; i < _size; i++) {
|
||||
for (j = 0; j < _size; j++) {
|
||||
_board[i][j] = num;
|
||||
_special[i][j] = num;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KattonGenerator::randomplace(int numberofplaces, int placer) {
|
||||
int i, randx, randy;
|
||||
for (i = 0; i < numberofplaces; i++) {
|
||||
randx = (getRandomNumber() % _size);
|
||||
randy = (getRandomNumber() % _size);
|
||||
_board[randx][randy] = placer;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KattonGenerator::randomsplotch(int length, int stringiness, int placer, int x, int y) {
|
||||
int currx, curry, direction = 10, prevdirection, movex = 0, movey = 0, i = 0;
|
||||
currx = x;
|
||||
curry = y;
|
||||
while (i <= length) {
|
||||
_board[currx][curry] = placer;
|
||||
prevdirection = direction;
|
||||
direction = (getRandomNumber() % 4);
|
||||
if ((((direction + 2) == prevdirection) || ((direction - 2) == prevdirection)) && (stringiness == 2)) {
|
||||
direction = prevdirection;
|
||||
}
|
||||
if (!((((direction + 2) == prevdirection) || ((direction - 2) == prevdirection)) && (stringiness == 1))) {
|
||||
switch (direction) {
|
||||
case 0:
|
||||
movex = 0;
|
||||
movey = 1;
|
||||
break;
|
||||
case 1:
|
||||
movex = 1;
|
||||
movey = 0;
|
||||
break;
|
||||
case 2:
|
||||
movex = 0;
|
||||
movey = -1;
|
||||
break;
|
||||
case 3:
|
||||
movex = -1;
|
||||
movey = 0;
|
||||
break;
|
||||
}
|
||||
currx = findcoord(currx, movex);
|
||||
curry = findcoord(curry, movey);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KattonGenerator::findcoord(int value, int move) {
|
||||
move = move % _size;
|
||||
int final = value + move;
|
||||
if (final < 0) {
|
||||
final = _size + final;
|
||||
}
|
||||
if (final >= _size) {
|
||||
final = final % _size;
|
||||
}
|
||||
return final;
|
||||
}
|
||||
|
||||
int KattonGenerator::replacenum(int replacee, int replacer) {
|
||||
int i, j;
|
||||
for (j = 0; j < _size; j++) {
|
||||
for (i = 0; i < _size; i++) {
|
||||
if (_board[i][j] == replacee) {
|
||||
_board[i][j] = replacer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KattonGenerator::fattenall(int howfat, int middle, int ignorer, int replacer) {
|
||||
int i, j, temp;
|
||||
for (j = 0; j < _size; j++) {
|
||||
for (i = 0; i < _size; i++) {
|
||||
if (_board[i][j] == middle) {
|
||||
if (howfat <= 0) {
|
||||
temp = (int)(abs(howfat) + plusminus(2));
|
||||
if (temp <= 1) {
|
||||
temp = 2;
|
||||
} else if (temp >= 6) {
|
||||
temp = 5;
|
||||
}
|
||||
fattenone(i, j, temp, middle, ignorer, replacer);
|
||||
} else {
|
||||
fattenone(i, j, howfat, middle, ignorer, replacer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int KattonGenerator::fattenone(int x, int y, int howfat, int middle, int ignorer, int replacer) {
|
||||
if (howfat == -100) {
|
||||
_board[x][y] = replacer;
|
||||
_board[findcoord(x, +1)][y] = replacer;
|
||||
_board[x][findcoord(y, +1)] = replacer;
|
||||
_board[findcoord(x, +1)][findcoord(y, +1)] = replacer;
|
||||
}
|
||||
if (howfat >= 1) {
|
||||
_board[x][findcoord(y, -1)] = ((_board[x][findcoord(y, -1)] == middle) || (_board[x][findcoord(y, -1)] == ignorer)) ? _board[x][findcoord(y, -1)] : replacer;
|
||||
_board[x][findcoord(y, +1)] = ((_board[x][findcoord(y, +1)] == middle) || (_board[x][findcoord(y, +1)] == ignorer)) ? _board[x][findcoord(y, +1)] : replacer;
|
||||
_board[findcoord(x, -1)][y] = ((_board[findcoord(x, -1)][y] == middle) || (_board[findcoord(x, -1)][y] == ignorer)) ? _board[findcoord(x, -1)][y] : replacer;
|
||||
_board[findcoord(x, +1)][y] = ((_board[findcoord(x, +1)][y] == middle) || (_board[findcoord(x, +1)][y] == ignorer)) ? _board[findcoord(x, +1)][y] : replacer;
|
||||
}
|
||||
if (howfat >= 2) {
|
||||
_board[findcoord(x, -1)][findcoord(y, -1)] = ((_board[findcoord(x, -1)][findcoord(y, -1)] == middle) || (_board[findcoord(x, -1)][findcoord(y, -1)] == ignorer)) ? _board[findcoord(x, -1)][findcoord(y, -1)] : replacer;
|
||||
_board[findcoord(x, -1)][findcoord(y, +1)] = ((_board[findcoord(x, -1)][findcoord(y, +1)] == middle) || (_board[findcoord(x, -1)][findcoord(y, +1)] == ignorer)) ? _board[findcoord(x, -1)][findcoord(y, +1)] : replacer;
|
||||
_board[findcoord(x, +1)][findcoord(y, -1)] = ((_board[findcoord(x, +1)][findcoord(y, -1)] == middle) || (_board[findcoord(x, +1)][findcoord(y, -1)] == ignorer)) ? _board[findcoord(x, +1)][findcoord(y, -1)] : replacer;
|
||||
_board[findcoord(x, +1)][findcoord(y, +1)] = ((_board[findcoord(x, +1)][findcoord(y, +1)] == middle) || (_board[findcoord(x, +1)][findcoord(y, +1)] == ignorer)) ? _board[findcoord(x, +1)][findcoord(y, +1)] : replacer;
|
||||
}
|
||||
if (howfat >= 3) {
|
||||
_board[x][findcoord(y, -2)] = ((_board[x][findcoord(y, -2)] == middle) || (_board[x][findcoord(y, -2)] == ignorer)) ? _board[x][findcoord(y, -2)] : replacer;
|
||||
_board[x][findcoord(y, +2)] = ((_board[x][findcoord(y, +2)] == middle) || (_board[x][findcoord(y, +2)] == ignorer)) ? _board[x][findcoord(y, +2)] : replacer;
|
||||
_board[findcoord(x, -2)][y] = ((_board[findcoord(x, -2)][y] == middle) || (_board[findcoord(x, -2)][y] == ignorer)) ? _board[findcoord(x, -2)][y] : replacer;
|
||||
_board[findcoord(x, +2)][y] = ((_board[findcoord(x, +2)][y] == middle) || (_board[findcoord(x, +2)][y] == ignorer)) ? _board[findcoord(x, +2)][y] : replacer;
|
||||
}
|
||||
if (howfat >= 4) {
|
||||
_board[findcoord(x, -1)][findcoord(y, -2)] = ((_board[findcoord(x, -1)][findcoord(y, -2)] == middle) || (_board[findcoord(x, -1)][findcoord(y, -2)] == ignorer)) ? _board[findcoord(x, -1)][findcoord(y, -2)] : replacer;
|
||||
_board[findcoord(x, -1)][findcoord(y, +2)] = ((_board[findcoord(x, -1)][findcoord(y, +2)] == middle) || (_board[findcoord(x, -1)][findcoord(y, +2)] == ignorer)) ? _board[findcoord(x, -1)][findcoord(y, +2)] : replacer;
|
||||
_board[findcoord(x, +1)][findcoord(y, -2)] = ((_board[findcoord(x, +1)][findcoord(y, -2)] == middle) || (_board[findcoord(x, +1)][findcoord(y, -2)] == ignorer)) ? _board[findcoord(x, +1)][findcoord(y, -2)] : replacer;
|
||||
_board[findcoord(x, +1)][findcoord(y, +2)] = ((_board[findcoord(x, +1)][findcoord(y, +2)] == middle) || (_board[findcoord(x, +1)][findcoord(y, +2)] == ignorer)) ? _board[findcoord(x, +1)][findcoord(y, +2)] : replacer;
|
||||
|
||||
_board[findcoord(x, -2)][findcoord(y, -1)] = ((_board[findcoord(x, -2)][findcoord(y, -1)] == middle) || (_board[findcoord(x, -2)][findcoord(y, -1)] == ignorer)) ? _board[findcoord(x, -2)][findcoord(y, -1)] : replacer;
|
||||
_board[findcoord(x, -2)][findcoord(y, +1)] = ((_board[findcoord(x, -2)][findcoord(y, +1)] == middle) || (_board[findcoord(x, -2)][findcoord(y, +1)] == ignorer)) ? _board[findcoord(x, -2)][findcoord(y, +1)] : replacer;
|
||||
_board[findcoord(x, +2)][findcoord(y, -1)] = ((_board[findcoord(x, +2)][findcoord(y, -1)] == middle) || (_board[findcoord(x, +2)][findcoord(y, -1)] == ignorer)) ? _board[findcoord(x, +2)][findcoord(y, -1)] : replacer;
|
||||
_board[findcoord(x, +2)][findcoord(y, +1)] = ((_board[findcoord(x, +2)][findcoord(y, +1)] == middle) || (_board[findcoord(x, +2)][findcoord(y, +1)] == ignorer)) ? _board[findcoord(x, +2)][findcoord(y, +1)] : replacer;
|
||||
}
|
||||
if (howfat >= 5) {
|
||||
_board[findcoord(x, -2)][findcoord(y, -2)] = ((_board[findcoord(x, -2)][findcoord(y, -2)] == middle) || (_board[findcoord(x, -2)][findcoord(y, -2)] == ignorer)) ? _board[findcoord(x, -2)][findcoord(y, -2)] : replacer;
|
||||
_board[findcoord(x, -2)][findcoord(y, +2)] = ((_board[findcoord(x, -2)][findcoord(y, +2)] == middle) || (_board[findcoord(x, -2)][findcoord(y, +2)] == ignorer)) ? _board[findcoord(x, -2)][findcoord(y, +2)] : replacer;
|
||||
_board[findcoord(x, +2)][findcoord(y, -2)] = ((_board[findcoord(x, +2)][findcoord(y, -2)] == middle) || (_board[findcoord(x, +2)][findcoord(y, -2)] == ignorer)) ? _board[findcoord(x, +2)][findcoord(y, -2)] : replacer;
|
||||
_board[findcoord(x, +2)][findcoord(y, +2)] = ((_board[findcoord(x, +2)][findcoord(y, +2)] == middle) || (_board[findcoord(x, +2)][findcoord(y, +2)] == ignorer)) ? _board[findcoord(x, +2)][findcoord(y, +2)] : replacer;
|
||||
|
||||
_board[x][findcoord(y, -3)] = ((_board[x][findcoord(y, -3)] == middle) || (_board[x][findcoord(y, -3)] == ignorer)) ? _board[x][findcoord(y, -3)] : replacer;
|
||||
_board[x][findcoord(y, +3)] = ((_board[x][findcoord(y, +3)] == middle) || (_board[x][findcoord(y, +3)] == ignorer)) ? _board[x][findcoord(y, +3)] : replacer;
|
||||
_board[findcoord(x, -3)][y] = ((_board[findcoord(x, -3)][y] == middle) || (_board[findcoord(x, -3)][y] == ignorer)) ? _board[findcoord(x, -3)][y] : replacer;
|
||||
_board[findcoord(x, +3)][y] = ((_board[findcoord(x, +3)][y] == middle) || (_board[findcoord(x, +3)][y] == ignorer)) ? _board[findcoord(x, +3)][y] : replacer;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KattonGenerator::findstartloc() {
|
||||
int temp, i, j, shiftx, shifty, secondshift;
|
||||
int start[4][2];
|
||||
shiftx = getRandomNumber() % _size;
|
||||
shifty = getRandomNumber() % _size;
|
||||
start[0][0] = findcoord((int)_size / 4, (plusminus(3) + shiftx));
|
||||
start[0][1] = findcoord((int)_size / 4, (plusminus(3) + shifty));
|
||||
start[1][0] = findcoord((int)3 * _size / 4, (plusminus(3) + shiftx));
|
||||
start[1][1] = findcoord((int)_size / 4, (plusminus(3) + shifty));
|
||||
start[2][0] = findcoord((int)_size / 4, (plusminus(3) + shiftx));
|
||||
start[2][1] = findcoord((int)3 * _size / 4, (plusminus(3) + shifty));
|
||||
start[3][0] = findcoord((int)3 * _size / 4, (plusminus(3) + shiftx));
|
||||
start[3][1] = findcoord((int)3 * _size / 4, (plusminus(3) + shifty));
|
||||
|
||||
temp = getRandomNumber() % 2;
|
||||
secondshift = getRandomNumber() % _size;
|
||||
|
||||
if (temp == 0) {
|
||||
start[0][0] = findcoord(start[0][0], secondshift);
|
||||
start[1][0] = findcoord(start[1][0], secondshift);
|
||||
}
|
||||
|
||||
else {
|
||||
start[1][1] = findcoord(start[1][1], secondshift);
|
||||
start[3][1] = findcoord(start[3][1], secondshift);
|
||||
}
|
||||
|
||||
temp = whatheightstartloc(start[0][0], start[0][1]);
|
||||
fattenone(start[0][0], start[0][1], -100, temp, NEVER_USED_NUM, temp);
|
||||
|
||||
temp = whatheightstartloc(start[1][0], start[1][1]);
|
||||
fattenone(start[1][0], start[1][1], -100, temp, NEVER_USED_NUM, temp);
|
||||
|
||||
temp = whatheightstartloc(start[2][0], start[2][1]);
|
||||
fattenone(start[2][0], start[2][1], -100, temp, NEVER_USED_NUM, temp);
|
||||
|
||||
temp = whatheightstartloc(start[3][0], start[3][1]);
|
||||
fattenone(start[3][0], start[3][1], -100, temp, NEVER_USED_NUM, temp);
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
_startloc[j][i] = start[j][i];
|
||||
}
|
||||
}
|
||||
|
||||
temp = getRandomNumber() % 4;
|
||||
j = 4;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (temp == i) {
|
||||
} else {
|
||||
_startloc[j][0] = start[i][0];
|
||||
_startloc[j][1] = start[i][1];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
_startloc[7][0] = _startloc[4][0];
|
||||
_startloc[7][1] = _startloc[4][1];
|
||||
_startloc[8][0] = _startloc[6][0];
|
||||
_startloc[8][1] = _startloc[6][1];
|
||||
|
||||
for (j = 9; j < 13; j++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
_startloc[j][i] = start[j - 9][i];
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 13; j < 17; j++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
_startloc[j][i] = start[j - 13][i];
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 17; j < 20; j++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
_startloc[j][i] = _startloc[j - 13][i];
|
||||
}
|
||||
}
|
||||
|
||||
// place on special map
|
||||
for (i = 0; i < 4; i++) {
|
||||
_special[_startloc[i][0]][_startloc[i][1]] += 1;
|
||||
}
|
||||
for (i = 4; i < 7; i++) {
|
||||
_special[_startloc[i][0]][_startloc[i][1]] += 2;
|
||||
}
|
||||
for (i = 7; i < 9; i++) {
|
||||
_special[_startloc[i][0]][_startloc[i][1]] += 4;
|
||||
}
|
||||
for (i = 9; i < 13; i++) {
|
||||
_special[_startloc[i][0]][_startloc[i][1]] += 8;
|
||||
}
|
||||
for (i = 13; i < 17; i++) {
|
||||
_special[_startloc[i][0]][_startloc[i][1]] += 16;
|
||||
}
|
||||
for (i = 17; i < 20; i++) {
|
||||
_special[_startloc[i][0]][_startloc[i][1]] += 32;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KattonGenerator::whatheightstartloc(int x, int y) {
|
||||
int heightfield[3] = {0, 0, 0};
|
||||
|
||||
heightfield[_board[findcoord(x, +2)][findcoord(y, -1)]]++;
|
||||
heightfield[_board[findcoord(x, +2)][y]]++;
|
||||
heightfield[_board[findcoord(x, +2)][findcoord(y, +1)]]++;
|
||||
heightfield[_board[findcoord(x, +2)][findcoord(y, +2)]]++;
|
||||
|
||||
heightfield[_board[findcoord(x, -1)][findcoord(y, -1)]]++;
|
||||
heightfield[_board[findcoord(x, -1)][y]]++;
|
||||
heightfield[_board[findcoord(x, -1)][findcoord(y, +1)]]++;
|
||||
heightfield[_board[findcoord(x, -1)][findcoord(y, +2)]]++;
|
||||
|
||||
heightfield[_board[x][findcoord(y, -1)]]++;
|
||||
heightfield[_board[x][y]]++;
|
||||
heightfield[_board[x][findcoord(y, +1)]]++;
|
||||
heightfield[_board[x][findcoord(y, +2)]]++;
|
||||
|
||||
heightfield[_board[findcoord(x, +1)][findcoord(y, -1)]]++;
|
||||
heightfield[_board[findcoord(x, +1)][y]]++;
|
||||
heightfield[_board[findcoord(x, +1)][findcoord(y, +1)]]++;
|
||||
heightfield[_board[findcoord(x, +1)][findcoord(y, +2)]]++;
|
||||
|
||||
if (heightfield[0] == 0) {
|
||||
if (heightfield[1] >= heightfield[2]) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
} else if (heightfield[1] == 0) {
|
||||
if (heightfield[0] >= heightfield[2]) {
|
||||
return 0;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
} else if (heightfield[2] == 0) {
|
||||
if (heightfield[1] >= heightfield[0]) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int KattonGenerator::goodforwater(int x, int y) {
|
||||
if ((_board[x][y] == 0) && (_board[findcoord(x, +1)][y] == 0) && (_board[x][findcoord(y, +1)] == 0) && (_board[findcoord(x, +1)][findcoord(y, +1)] == 0)) { //check main map
|
||||
if ((_special[x][y] <= 0) && (_special[x][findcoord(y, 1)] <= 0) && (_special[findcoord(x, 1)][findcoord(y, 1)] <= 0) && (_special[findcoord(x, 1)][y] <= 0) && (_special[findcoord(x, 1)][findcoord(y, -1)] <= 0) && (_special[x][findcoord(y, -1)] <= 0) && (_special[findcoord(x, -1)][findcoord(y, -1)] <= 0) && (_special[findcoord(x, -1)][y] <= 0) && (_special[findcoord(x, -1)][findcoord(y, 1)] <= 0)) { //specials are clear
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int KattonGenerator::randomwater(int length, int stringiness, int x, int y) {
|
||||
int currx, curry, direction = 10, prevdirection, i = 0;
|
||||
currx = x;
|
||||
curry = y;
|
||||
while (i <= length) {
|
||||
_special[currx][curry] = -1;
|
||||
prevdirection = direction;
|
||||
direction = (getRandomNumber() % 4);
|
||||
if ((((direction + 2) == prevdirection) || ((direction - 2) == prevdirection)) && (stringiness == 2)) {
|
||||
direction = prevdirection;
|
||||
}
|
||||
if (!((((direction + 2) == prevdirection) || ((direction - 2) == prevdirection)) && (stringiness == 1))) {
|
||||
switch (direction) {
|
||||
|
||||
case 0: //north
|
||||
if (goodforwater(currx, findcoord(curry, 1))) {
|
||||
curry = findcoord(curry, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: //east
|
||||
if (goodforwater(findcoord(currx, 1), curry)) {
|
||||
currx = findcoord(currx, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: //south
|
||||
if (goodforwater(currx, findcoord(curry, -1))) {
|
||||
curry = findcoord(curry, -1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: //west
|
||||
if (goodforwater(findcoord(currx, -1), curry)) {
|
||||
currx = findcoord(currx, -1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KattonGenerator::tileaverage(int x, int y, int threshold) {
|
||||
int heightfield[3] = {0, 0, 0};
|
||||
|
||||
heightfield[_board[findcoord(x, -1)][findcoord(y, -1)]]++;
|
||||
heightfield[_board[findcoord(x, -1)][y]]++;
|
||||
heightfield[_board[findcoord(x, -1)][findcoord(y, +1)]]++;
|
||||
|
||||
heightfield[_board[x][findcoord(y, -1)]]++;
|
||||
heightfield[_board[x][y]]++;
|
||||
heightfield[_board[x][findcoord(y, +1)]]++;
|
||||
|
||||
heightfield[_board[findcoord(x, +1)][findcoord(y, -1)]]++;
|
||||
heightfield[_board[findcoord(x, +1)][y]]++;
|
||||
heightfield[_board[findcoord(x, +1)][findcoord(y, +1)]]++;
|
||||
|
||||
if ((heightfield[2] == 0) && (heightfield[1] < heightfield[0]) && (heightfield[0] >= threshold)) {
|
||||
_board[x][y] = 0;
|
||||
return 0;
|
||||
} else if ((heightfield[0] == 0) && (heightfield[1] < heightfield[2]) && (heightfield[2] >= threshold)) {
|
||||
_board[x][y] = 2;
|
||||
return 2;
|
||||
} else if (heightfield[1] >= threshold) {
|
||||
_board[x][y] = 1;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int KattonGenerator::randomflip(int numberofplaces, int inWater) {
|
||||
int i, x, y, temp;
|
||||
for (i = 0; i < numberofplaces; i++) {
|
||||
x = getRandomNumber() % _size;
|
||||
y = getRandomNumber() % _size;
|
||||
if (_board[x][y] == 0) {
|
||||
if (inWater == 0) {
|
||||
temp = 0;
|
||||
} else {
|
||||
temp = getRandomNumber() % inWater;
|
||||
}
|
||||
|
||||
if (temp <= 50) {
|
||||
_board[x][y] = 1;
|
||||
}
|
||||
} else if (_board[x][y] == 2) {
|
||||
_board[x][y] = 1;
|
||||
} else if (_board[x][y] == 1) {
|
||||
|
||||
temp = getRandomNumber() % 2;
|
||||
int heightfield[3] = {0, 0, 0};
|
||||
|
||||
heightfield[_board[findcoord(x, -1)][findcoord(y, -1)]]++;
|
||||
heightfield[_board[findcoord(x, -1)][y]]++;
|
||||
heightfield[_board[findcoord(x, -1)][findcoord(y, +1)]]++;
|
||||
|
||||
heightfield[_board[x][findcoord(y, -1)]]++;
|
||||
heightfield[_board[x][findcoord(y, +1)]]++;
|
||||
|
||||
heightfield[_board[findcoord(x, +1)][findcoord(y, -1)]]++;
|
||||
heightfield[_board[findcoord(x, +1)][y]]++;
|
||||
heightfield[_board[findcoord(x, +1)][findcoord(y, +1)]]++;
|
||||
temp = getRandomNumber() % 2;
|
||||
if (heightfield[0] == 0) {
|
||||
_board[x][y] = 2;
|
||||
} else if (heightfield[2] == 0) {
|
||||
_board[x][y] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
77
engines/scumm/he/moonbase/map_katton.h
Normal file
77
engines/scumm/he/moonbase/map_katton.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_MAP_KATTON_H
|
||||
#define SCUMM_HE_MOONBASE_MAP_KATTON_H
|
||||
|
||||
#ifdef ENABLE_HE
|
||||
|
||||
#include "engines/scumm/he/moonbase/map_mif.h"
|
||||
|
||||
#define TEMP_REPLACEMENT_NUMA 5
|
||||
#define NEVER_USED_NUM 99
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class KattonGenerator {
|
||||
public:
|
||||
KattonGenerator(int seed);
|
||||
~KattonGenerator() = default;
|
||||
|
||||
MapFile *generateMap(int water, int tileSet, int mapSize, int energy, int terrain);
|
||||
|
||||
private:
|
||||
int _seed = 0;
|
||||
|
||||
int _size = 0; // 32, 40, 48, or 56
|
||||
int _tileset = 0;
|
||||
int _startloc[20][2] = { {}, {} };
|
||||
int _board[MAX_TILE_COUNT][MAX_TILE_COUNT] = { {}, {} };
|
||||
int _special[MAX_TILE_COUNT][MAX_TILE_COUNT] = { {}, {} };
|
||||
|
||||
int getRandomNumber();
|
||||
|
||||
int min(int a, int b, int c);
|
||||
int distance(int x1, int y1, int x2, int y2);
|
||||
int plusminus(int max);
|
||||
int fillboards(int num);
|
||||
int randomplace(int numberofplaces, int placer);
|
||||
int randomflip(int numberofplaces, int inWater);
|
||||
// stringiness: 0 = no change/random, 1 = no back, 2 = back goes forwards
|
||||
int randomsplotch(int length, int stringiness, int placer, int x, int y);
|
||||
int goodforwater(int x, int y);
|
||||
int randomwater(int length, int stringiness, int x, int y);
|
||||
int goodforenergy(int x, int y, int poolsize);
|
||||
int findcoord(int value, int move);
|
||||
int replacenum(int replacee, int replacer);
|
||||
int fattenone(int x, int y, int howfat, int middle, int ignorer, int replacer);
|
||||
// howfat: positive 1-5 for distance, -100 to 0 for random 3 spread from 2 to 5.
|
||||
int fattenall(int howfat, int middle, int ignorer, int replacer);
|
||||
int findstartloc();
|
||||
int whatheightstartloc(int x, int y);
|
||||
int tileaverage(int x, int y, int threshold);
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif // ENABLE_HE
|
||||
|
||||
#endif // SCUMM_HE_MOONBASE_MAP_KATTON_H
|
||||
293
engines/scumm/he/moonbase/map_main.cpp
Normal file
293
engines/scumm/he/moonbase/map_main.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/compression/deflate.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "common/base64.h"
|
||||
|
||||
#include "common/memstream.h"
|
||||
#include "common/bufferedstream.h"
|
||||
|
||||
#include "scumm/he/intern_he.h"
|
||||
|
||||
#include "scumm/he/moonbase/map_data.h"
|
||||
#include "scumm/he/moonbase/map_main.h"
|
||||
|
||||
#include "scumm/he/moonbase/map_spiff.h"
|
||||
#include "scumm/he/moonbase/map_katton.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
Map::Map(ScummEngine_v100he *vm) : _vm(vm), _rnd("moonbase") {
|
||||
_mapGenerated = false;
|
||||
_generatedMap = nullptr;
|
||||
|
||||
_generator = 0;
|
||||
_size = 0;
|
||||
_seed = 0;
|
||||
_tileset = 0;
|
||||
_energy = -1;
|
||||
_terrain = -1;
|
||||
_water = -1;
|
||||
|
||||
_encodedMap = Common::String();
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
deleteMap();
|
||||
}
|
||||
|
||||
bool Map::generateNewMap() {
|
||||
deleteMap();
|
||||
|
||||
if (!ConfMan.getBool("generate_random_maps"))
|
||||
return false;
|
||||
|
||||
// Show a dialog allowing the user to customize options.
|
||||
if (!_vm->mapGeneratorDialog(!strcmp(_vm->_game.variant, "Demo")))
|
||||
// They have clicked cancel, abort.
|
||||
return false;
|
||||
|
||||
// Create a new seed just for the below values. This is to
|
||||
// ensure these are truly random after generating a previous
|
||||
// map (or to debug with a prefixed seed).
|
||||
_rnd.generateNewSeed();
|
||||
|
||||
if (ConfMan.hasKey("map_size"))
|
||||
_size = ConfMan.getInt("map_size");
|
||||
if (_size < 4 || _size > 10)
|
||||
// Don't randomly pick nonstandard map sizes.
|
||||
_size = _rnd.getRandomNumberRngSigned(4, 8);
|
||||
|
||||
_size *= 8;
|
||||
|
||||
if (ConfMan.hasKey("map_algorithm"))
|
||||
_generator = ConfMan.getInt("map_algorithm");
|
||||
if (_generator < SPIFF_GEN || _generator > KATTON_GEN)
|
||||
_generator = _rnd.getRandomNumberRng(1, 2);
|
||||
|
||||
if (ConfMan.hasKey("map_tileset"))
|
||||
_tileset = ConfMan.getInt("map_tileset");
|
||||
if (_tileset < 1 || _tileset > 6)
|
||||
_tileset = _rnd.getRandomNumberRngSigned(1, 6);
|
||||
|
||||
if (!strcmp(_vm->_game.variant, "Demo") && (_tileset == 1 ||
|
||||
_tileset == 3 || _tileset == 5)) {
|
||||
// Demo version only has tilesets 1, 2, 4 and 6.
|
||||
switch (_rnd.getRandomNumber(3)) {
|
||||
case 0:
|
||||
_tileset = 1;
|
||||
break;
|
||||
case 1:
|
||||
_tileset = 2;
|
||||
break;
|
||||
case 2:
|
||||
_tileset = 4;
|
||||
break;
|
||||
default:
|
||||
_tileset = 6;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfMan.hasKey("map_energy"))
|
||||
_energy = ConfMan.getInt("map_energy");
|
||||
if (_energy < 0 || _energy > 6)
|
||||
// Only use [2, 3, 4] of the legal [0, 1, 2, 3, 4, 5, 6]
|
||||
_energy = _rnd.getRandomNumberRngSigned(2, 4);
|
||||
|
||||
if (ConfMan.hasKey("map_terrain"))
|
||||
_terrain = ConfMan.getInt("map_terrain");
|
||||
if (_terrain < 0 || _terrain > 6)
|
||||
// Only use [2, 3, 4] of the legal [0, 1, 2, 3, 4, 5, 6]
|
||||
_terrain = _rnd.getRandomNumberRngSigned(2, 4);
|
||||
|
||||
if (ConfMan.hasKey("map_water"))
|
||||
_water = ConfMan.getInt("map_water");
|
||||
if (_water < 0 || _water > 6)
|
||||
// Only use [2, 3, 4] of the legal [0, 1, 2, 3, 4, 5, 6]
|
||||
_water = _rnd.getRandomNumberRngSigned(2, 4);
|
||||
|
||||
// 32767 is RAND_MAX on Windows
|
||||
int seed = _rnd.getRandomNumber(32767);
|
||||
|
||||
debug(1, "Map: Generating new map with info: generator = %d, seed = %d, size = %d, tileset = %d , energy = %d, terrain = %d, water = %d.", _generator, getSeed(), _size, _tileset, _energy, _terrain, _water);
|
||||
switch (_generator) {
|
||||
case SPIFF_GEN:
|
||||
{
|
||||
SpiffGenerator spiff = SpiffGenerator(seed);
|
||||
_generatedMap = spiff.generateMap(_water, _tileset, _size, _energy, _terrain);
|
||||
break;
|
||||
}
|
||||
case KATTON_GEN:
|
||||
{
|
||||
KattonGenerator katton = KattonGenerator(seed);
|
||||
_generatedMap = katton.generateMap(_water, _tileset, _size, _energy, _terrain);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error("Map: Got unknown generator: %d", _generator);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Encode the newly generated map file into base64 to transmit over the wire:
|
||||
_encodedMap = Common::b64EncodeData(_generatedMap, sizeof(MapFile));
|
||||
debug(2, "Map: Base64: %s", _encodedMap.c_str());
|
||||
|
||||
_mapGenerated = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Map::generateMapWithInfo(Common::String encodedMap, uint8 generator, int seed, int mapSize, int tileset, int energy, int terrain, int water) {
|
||||
deleteMap();
|
||||
|
||||
_generator = generator;
|
||||
_seed = seed;
|
||||
_size = mapSize;
|
||||
_tileset = tileset;
|
||||
_energy = energy;
|
||||
_terrain = terrain;
|
||||
_water = water;
|
||||
_encodedMap = encodedMap;
|
||||
|
||||
// Decode base64 encoded map file
|
||||
debug(2, "Map: Generating map with base64: encodedMap: %s, generator = %d, seed = %d, mapSize = %d, tileset = %d , energy = %d, terrain = %d, water = %d.", encodedMap.c_str(), generator, getSeed(), mapSize, tileset, energy, terrain, water);
|
||||
_generatedMap = new MapFile();
|
||||
bool success = Common::b64DecodeData(encodedMap, _generatedMap);
|
||||
if (!success) {
|
||||
warning("Map: Error has occurred while decoding map data from base64");
|
||||
return false;
|
||||
}
|
||||
_mapGenerated = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Map::deleteMap() {
|
||||
if (_mapGenerated) {
|
||||
// Delete old map.
|
||||
delete _generatedMap;
|
||||
_generatedMap = nullptr;
|
||||
|
||||
_mapGenerated = false;
|
||||
_generator = 0;
|
||||
_size = 0;
|
||||
_seed = 0;
|
||||
_tileset = 0;
|
||||
_energy = -1;
|
||||
_terrain = -1;
|
||||
_water = -1;
|
||||
_encodedMap = "";
|
||||
debug(1, "Map: Deleted.");
|
||||
}
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *Map::makeWiz() {
|
||||
unsigned short wiz [139][139];
|
||||
int i, j;
|
||||
|
||||
Common::MemoryReadStream *wizTemplate = new Common::MemoryReadStream(Template_wiz, ARRAYSIZE(Template_wiz));
|
||||
Common::SeekableReadStream *stream = Common::wrapCompressedReadStream(wizTemplate);
|
||||
|
||||
stream->seek(0x0448);
|
||||
for (j = 0; j < 139; ++j) {
|
||||
for (i = 0; i < 139; ++i) {
|
||||
uint16 data = stream->readUint16LE();
|
||||
wiz[i][j] = data;
|
||||
}
|
||||
}
|
||||
delete stream;
|
||||
|
||||
for (j = 0; j < _energy * 9; j++) {
|
||||
for (i = 30; i < 51; i++) {
|
||||
wiz[i][91 - j] = ((255) / 8 ) + ((int) (130 - (j * 100 / (_energy * 9)))) / 8 * 32 + ((int) (80 + j * 80 / (_energy * 9)) / 8 * 1024);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < _terrain * 9; j++) {
|
||||
for (i = 61; i < 82; i++) {
|
||||
wiz[i][91 - j] = ((255) / 8 ) + ((int) (130 - (j * 100 / (_terrain*9))))/8 * 32 + ((int) (80 + j * 80 / (_terrain * 9)) / 8 * 1024);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < _water * 9; j++) {
|
||||
for (i = 92; i < 113; i++) {
|
||||
wiz[i][91 - j] = ((255) / 8 ) + ((int) (130 - (j * 100 / (_water * 9)))) / 8 * 32 + ((int) (80 + j * 80 / (_water*9)) / 8 * 1024);
|
||||
}
|
||||
}
|
||||
|
||||
// Re-read the template (to avoid compressed stream seeking):
|
||||
wizTemplate = new Common::MemoryReadStream(Template_wiz, ARRAYSIZE(Template_wiz));
|
||||
stream = Common::wrapCompressedReadStream(wizTemplate);
|
||||
byte *pwiz = (byte *)malloc(TEMPLATE_WIZ_SIZE);
|
||||
stream->read(pwiz, TEMPLATE_WIZ_SIZE);
|
||||
delete stream;
|
||||
|
||||
Common::SeekableMemoryWriteStream ws = Common::SeekableMemoryWriteStream(pwiz, TEMPLATE_WIZ_SIZE);
|
||||
ws.seek(0x0448);
|
||||
for (j = 0; j < 139; j++) {
|
||||
for (i = 0; i < 139; i++) {
|
||||
ws.writeUint16LE(wiz[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
return new Common::MemoryReadStream(pwiz, TEMPLATE_WIZ_SIZE, DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *Map::substituteFile(const byte *fileName) {
|
||||
if (_mapGenerated) {
|
||||
// Worth noting here that the game opens these files more than once.
|
||||
// The exact scenario for the .thm and .wiz files is that the game
|
||||
// opens it first to make sure that it exists and readable, closes it,
|
||||
// and calls processWizImage to open the file again to actually read
|
||||
// the data inside.
|
||||
if (!strcmp((const char *)fileName, "map\\moon001.thm")) {
|
||||
// Load compressed thumbnail data from header.
|
||||
Common::MemoryReadStream *templateThm = new Common::MemoryReadStream(Template_thm, ARRAYSIZE(Template_thm));
|
||||
Common::SeekableReadStream *stream = Common::wrapCompressedReadStream(templateThm);
|
||||
|
||||
// Read the uncompressed data into memory
|
||||
// (This is done to avoid compressed stream seeking)
|
||||
byte *thumbnail = (byte *)malloc(TEMPLATE_THM_SIZE);
|
||||
stream->read(thumbnail, TEMPLATE_THM_SIZE);
|
||||
delete stream;
|
||||
|
||||
// And return a new ReadStream for it.
|
||||
return new Common::MemoryReadStream(thumbnail, TEMPLATE_THM_SIZE, DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
if (!strcmp((const char *)fileName, "map\\moon001.wiz")) {
|
||||
return makeWiz();
|
||||
}
|
||||
|
||||
if (!strcmp((const char *)fileName, "map\\moon001.map") ||
|
||||
!strcmp((const char *)fileName, "user\\Temp.map")) {
|
||||
// (The Temp.map name is used when the game saves the map alongside
|
||||
// replay data)
|
||||
// Return new ReadStream but do not dispose it. We'll handle
|
||||
// that ourselves.
|
||||
return new Common::MemoryReadStream((byte *)_generatedMap, sizeof(MapFile));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
112
engines/scumm/he/moonbase/map_main.h
Normal file
112
engines/scumm/he/moonbase/map_main.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_MAP_MAIN_H
|
||||
#define SCUMM_HE_MOONBASE_MAP_MAIN_H
|
||||
|
||||
#ifdef ENABLE_HE
|
||||
|
||||
#include "common/random.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "engines/scumm/he/moonbase/map_mif.h"
|
||||
|
||||
#define SPIFF_GEN 1
|
||||
#define KATTON_GEN 2
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class Map {
|
||||
public:
|
||||
Map(ScummEngine_v100he *vm);
|
||||
~Map();
|
||||
|
||||
bool generateNewMap();
|
||||
bool generateMapWithInfo(Common::String encodedMap, uint8 generator, int seed, int mapSize, int tileset, int energy, int terrain, int water);
|
||||
Common::SeekableReadStream *substituteFile(const byte *fileName);
|
||||
|
||||
void deleteMap();
|
||||
|
||||
uint8 getGenerator() const {
|
||||
return _generator;
|
||||
}
|
||||
|
||||
int getSize() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
int getSeed() const {
|
||||
return _seed;
|
||||
}
|
||||
|
||||
int getTileset() const {
|
||||
return _tileset;
|
||||
}
|
||||
|
||||
int getEnergy() const {
|
||||
return _energy;
|
||||
}
|
||||
|
||||
int getTerrain() const {
|
||||
return _terrain;
|
||||
}
|
||||
|
||||
int getWater() const {
|
||||
return _water;
|
||||
}
|
||||
|
||||
bool mapGenerated() const {
|
||||
return _mapGenerated;
|
||||
}
|
||||
|
||||
Common::String getEncodedMap() const {
|
||||
return _encodedMap;
|
||||
}
|
||||
|
||||
private:
|
||||
ScummEngine_v100he *_vm;
|
||||
|
||||
// We require our own random number generator
|
||||
// so we can send and set seeds from online players to ensure
|
||||
// they're playing on the same generated map.
|
||||
Common::RandomSource _rnd;
|
||||
|
||||
uint8 _generator;
|
||||
int _size;
|
||||
int _seed;
|
||||
int _tileset;
|
||||
int _energy;
|
||||
int _terrain;
|
||||
int _water;
|
||||
|
||||
bool _mapGenerated;
|
||||
MapFile *_generatedMap;
|
||||
Common::String _encodedMap;
|
||||
|
||||
Common::SeekableReadStream *makeWiz();
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
|
||||
#endif // ENABLE_HE
|
||||
|
||||
#endif // SCUMM_HE_MOONBASE_MAP_MAIN_H
|
||||
825
engines/scumm/he/moonbase/map_mif.cpp
Normal file
825
engines/scumm/he/moonbase/map_mif.cpp
Normal file
@@ -0,0 +1,825 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/str.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "scumm/he/moonbase/map_mif.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
static const byte waterTileMap[] = {
|
||||
0x44, 0x40, 0x32, 0x32, 0x3C, 0x38, 0x32, 0x32, // 0x00
|
||||
0x2C, 0x2C, 0x26, 0x26, 0x2A, 0x2A, 0x26, 0x26,
|
||||
0x2F, 0x2D, 0x27, 0x27, 0x2F, 0x2D, 0x27, 0x27, // 0x10
|
||||
0x1B, 0x1B, 0x49, 0x49, 0x1B, 0x1B, 0x49, 0x49,
|
||||
0x42, 0x3E, 0x30, 0x30, 0x3A, 0x36, 0x30, 0x30, // 0x20
|
||||
0x2C, 0x2C, 0x26, 0x26, 0x2A, 0x2A, 0x26, 0x26,
|
||||
0x2E, 0x22, 0x1E, 0x1E, 0x2E, 0x22, 0x1E, 0x1E, // 0x30
|
||||
0x1B, 0x1B, 0x49, 0x49, 0x1B, 0x1B, 0x49, 0x49,
|
||||
0x35, 0x33, 0x1C, 0x1C, 0x34, 0x24, 0x1C, 0x1C, // 0x40
|
||||
0x28, 0x28, 0x4B, 0x4B, 0x1F, 0x1F, 0x4B, 0x4B,
|
||||
0x29, 0x20, 0x4C, 0x4C, 0x29, 0x20, 0x4C, 0x4C, // 0x50
|
||||
0x48, 0x48, 0x4A, 0x4A, 0x48, 0x48, 0x4A, 0x4A,
|
||||
0x35, 0x33, 0x1C, 0x1C, 0x34, 0x24, 0x1C, 0x1C, // 0x60
|
||||
0x28, 0x28, 0x4B, 0x4B, 0x1F, 0x1F, 0x4B, 0x4B,
|
||||
0x29, 0x20, 0x4C, 0x4C, 0x29, 0x20, 0x4C, 0x4C, // 0x70
|
||||
0x48, 0x48, 0x4A, 0x4A, 0x48, 0x48, 0x4A, 0x4A,
|
||||
0x43, 0x3F, 0x31, 0x31, 0x3B, 0x37, 0x31, 0x31, // 0x80
|
||||
0x2B, 0x2B, 0x1D, 0x1D, 0x21, 0x21, 0x1D, 0x1D,
|
||||
0x2F, 0x2D, 0x27, 0x27, 0x2F, 0x2D, 0x27, 0x27, // 0x90
|
||||
0x1B, 0x1B, 0x49, 0x49, 0x1B, 0x1B, 0x49, 0x49,
|
||||
0x41, 0x3D, 0x23, 0x23, 0x39, 0x25, 0x23, 0x23, // 0xA0
|
||||
0x2B, 0x2B, 0x1D, 0x1D, 0x21, 0x21, 0x1D, 0x1D,
|
||||
0x2E, 0x22, 0x1E, 0x1E, 0x2E, 0x22, 0x1E, 0x1E, // 0xB0
|
||||
0x1B, 0x1B, 0x49, 0x49, 0x1B, 0x1B, 0x49, 0x49,
|
||||
0x35, 0x33, 0x1C, 0x1C, 0x34, 0x24, 0x1C, 0x1C, // 0xC0
|
||||
0x28, 0x28, 0x4B, 0x4B, 0x1F, 0x1F, 0x4B, 0x4B,
|
||||
0x29, 0x20, 0x4C, 0x4C, 0x29, 0x20, 0x4C, 0x4C, // 0xD0
|
||||
0x48, 0x48, 0x4A, 0x4A, 0x48, 0x48, 0x4A, 0x4A,
|
||||
0x35, 0x33, 0x1C, 0x1C, 0x34, 0x24, 0x1C, 0x1C, // 0xE0
|
||||
0x28, 0x28, 0x4B, 0x4B, 0x1F, 0x1F, 0x4B, 0x4B,
|
||||
0x29, 0x20, 0x4C, 0x4C, 0x29, 0x20, 0x4C, 0x4C, // 0xF0
|
||||
0x48, 0x48, 0x4A, 0x4A, 0x48, 0x48, 0x4A, 0x4A
|
||||
};
|
||||
|
||||
static int magic(int x, int y) {
|
||||
static const byte matrix[8][8] = {
|
||||
{ 2, 0, 2, 1, 3, 0, 3, 1 } ,
|
||||
{ 3, 1, 0, 3, 2, 1, 0, 2 } ,
|
||||
{ 0, 2, 1, 2, 0, 3, 1, 3 } ,
|
||||
{ 1, 3, 0, 3, 1, 2, 0, 2 } ,
|
||||
{ 2, 0, 1, 2, 3, 0, 1, 3 } ,
|
||||
{ 3, 1, 3, 0, 2, 1, 2, 0 } ,
|
||||
{ 0, 2, 0, 1, 3, 0, 3, 2 } ,
|
||||
{ 1, 3, 0, 3, 2, 1, 2, 0 }
|
||||
};
|
||||
return matrix[y % 8][x % 8];
|
||||
}
|
||||
|
||||
MIF::MIF() {
|
||||
}
|
||||
|
||||
void MIF::generateMap(MapFile *map) {
|
||||
map->terrainDimX = _dimension;
|
||||
map->terrainDimY = _dimension;
|
||||
map->mapType = _mapType;
|
||||
Common::strlcpy(map->name, _name, 17);
|
||||
|
||||
int x, y;
|
||||
for (y = 0; y < _dimension; ++y) {
|
||||
for (x = 0; x < _dimension; ++x) {
|
||||
map->terrainStates[x][y] = findTileFor(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
defineEnergyPools(map);
|
||||
defineStartLocations(map);
|
||||
makeCraters(map);
|
||||
}
|
||||
|
||||
void MIF::defineStartLocations(MapFile *map) {
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < _dimension; ++y) {
|
||||
for (x = 0; x < _dimension; ++x) {
|
||||
int8 ch = _centerMap[x][y];
|
||||
|
||||
if (ch < 0) {
|
||||
int i;
|
||||
ch = -ch;
|
||||
|
||||
if (ch & 1) {
|
||||
// 4 player start
|
||||
i = 0;
|
||||
while (i < 4) {
|
||||
if (map->fourPlayerPoints[i].x == 0xFFFF) {
|
||||
map->fourPlayerPoints[i].x = x * 60;
|
||||
map->fourPlayerPoints[i].y = y * 60;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ch = ch >> 1;
|
||||
if (ch & 1) {
|
||||
// 3 player start
|
||||
i = 0;
|
||||
while (i < 3) {
|
||||
if (map->threePlayerPoints[i].x == 0xFFFF) {
|
||||
map->threePlayerPoints[i].x = x * 60;
|
||||
map->threePlayerPoints[i].y = y * 60;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ch = ch >> 1;
|
||||
if (ch & 1) {
|
||||
// 2 player start
|
||||
i = 0;
|
||||
while (i < 2) {
|
||||
if (map->twoPlayerPoints[i].x == 0xFFFF) {
|
||||
map->twoPlayerPoints[i].x = x * 60;
|
||||
map->twoPlayerPoints[i].y = y * 60;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ch = ch >> 1;
|
||||
if (ch & 1) {
|
||||
// 2v2 player start
|
||||
i = 0;
|
||||
while (i < 4) {
|
||||
if (map->twoVTwoPoints[i].x == 0xFFFF) {
|
||||
map->twoVTwoPoints[i].x = x * 60;
|
||||
map->twoVTwoPoints[i].y = y * 60;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ch = ch >> 1;
|
||||
if (ch & 1) {
|
||||
// 1v3 player start
|
||||
i = 0;
|
||||
while (i < 4) {
|
||||
if (map->oneVThreePoints[i].x == 0xFFFF) {
|
||||
map->oneVThreePoints[i].x = x * 60;
|
||||
map->oneVThreePoints[i].y = y * 60;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ch = ch >> 1;
|
||||
if (ch & 1) {
|
||||
// 1v2 player start
|
||||
i = 0;
|
||||
while (i < 3) {
|
||||
if (map->oneVTwoPoints[i].x == 0xFFFF) {
|
||||
map->oneVTwoPoints[i].x = x * 60;
|
||||
map->oneVTwoPoints[i].y = y * 60;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MIF::defineEnergyPools(MapFile *map) {
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < _dimension; ++y) {
|
||||
for (x = 0; x < _dimension; ++x) {
|
||||
char ch = _centerMap[x][y];
|
||||
|
||||
if ('S' == ch || 'M' == ch || 'L' == ch) {
|
||||
// Verify legal position
|
||||
if (!((tlCorner(x, y) == trCorner(x, y)) && (blCorner(x, y) == brCorner(x, y)) &&
|
||||
(tlCorner(x, y) == blCorner(x, y)) && (trCorner(x, y) == brCorner(x, y)))) {
|
||||
error("small and medium energy pools must be on a flat tile (%d, %d)", x, y);
|
||||
}
|
||||
|
||||
if ('L' == ch) {
|
||||
byte nHeight;
|
||||
nHeight = blCorner(x, y);
|
||||
if (!(tlCorner(x, y) == nHeight && ttlCorner(x, y) == nHeight && ttrCorner(x, y) == nHeight && trCorner(x, y) == nHeight && brCorner(x, y) == nHeight)) {
|
||||
error("large energy pools must be on the lower of two flat tiles (%d, %d)", x, y);
|
||||
}
|
||||
}
|
||||
|
||||
int xLoc;
|
||||
int yLoc;
|
||||
|
||||
if ('S' == ch) {
|
||||
xLoc = 60 * x + 30 + 20000;
|
||||
yLoc = 60 * y + 30;
|
||||
} else if ('M' == ch) {
|
||||
xLoc = 60 * x + 30 + 10000;
|
||||
yLoc = 60 * y + 30;
|
||||
} else {
|
||||
xLoc = 60 * x + 30;
|
||||
yLoc = 60 * y;
|
||||
}
|
||||
|
||||
if (map->numEnergyPools < 49) {
|
||||
map->poolLocs[map->numEnergyPools].location.x = xLoc;
|
||||
map->poolLocs[map->numEnergyPools].location.y = yLoc;
|
||||
|
||||
++map->numEnergyPools;
|
||||
} else if (map->numEnergyPools == 49) {
|
||||
map->lastPool.x = xLoc;
|
||||
map->lastPool.y = yLoc;
|
||||
|
||||
++map->numEnergyPools;
|
||||
} else {
|
||||
error("only 50 energy pools are allowed, this is the 51st (%d, %d)", x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MIF::makeCraters(MapFile *map) {
|
||||
// squarenumber, type, x, y (offset from top left (abs y)). x/y = 9 if none of that type
|
||||
static const byte locations[8][3][2] = {
|
||||
{ {1, 1}, {5, 2}, {3, 5} },
|
||||
{ {6, 1}, {1, 6}, {2, 0} },
|
||||
{ {0, 4}, {3, 2}, {6, 5} },
|
||||
{ {4, 4}, {5, 0}, {9, 9} },
|
||||
{ {3, 6}, {9, 9}, {2, 1} },
|
||||
{ {9, 9}, {3, 3}, {0, 2} },
|
||||
{ {2, 4}, {0, 0}, {5, 3} },
|
||||
{ {4, 1}, {0, 3}, {5, 6} }
|
||||
};
|
||||
|
||||
// I made up the crater patterns for sizes larger than SAI
|
||||
// This will work for maps up to 80x80
|
||||
static byte const largegrid[10][10] = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 0, 1},
|
||||
{2, 3, 4, 5, 6, 7, 0, 1, 2, 3},
|
||||
{4, 5, 6, 7, 0, 1, 2, 3, 4, 5},
|
||||
{3, 0, 1, 2, 6, 4, 5, 7, 3, 0},
|
||||
{1, 2, 3, 4, 5, 6, 7, 0, 1, 2},
|
||||
{3, 4, 5, 6, 7, 0, 1, 2, 3, 4},
|
||||
{6, 3, 0, 1, 2, 7, 4, 5, 6, 3},
|
||||
{5, 6, 7, 0, 1, 2, 3, 4, 5, 6},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 0, 1},
|
||||
{2, 3, 4, 5, 6, 7, 0, 1, 2, 3}
|
||||
};
|
||||
|
||||
for (int i = 0; i < _dimension / 8; i++) {
|
||||
for (int j = 0; j < _dimension / 8; j++) {
|
||||
for (int nCrater = 0; nCrater < 3; nCrater++) {
|
||||
if (9 == locations[largegrid[j][i]][nCrater][0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int x = locations[largegrid[j][i]][nCrater][0] + i * 8;
|
||||
int y = locations[largegrid[j][i]][nCrater][1] + j * 8;
|
||||
|
||||
byte nLevel = tlCorner(x, y);
|
||||
if ((tlCorner(x, y) == nLevel) && (trCorner(x, y) == nLevel) && (trrCorner(x, y) == nLevel) &&
|
||||
(_centerMap[x][y] != 'W') && (_centerMap[x + 1][y] != 'W') &&
|
||||
(blCorner(x, y) == nLevel) && (brCorner(x, y) == nLevel) && (brrCorner(x, y) == nLevel) &&
|
||||
(_centerMap[x][y + 1] != 'W') && (_centerMap[x + 1][y + 1] != 'W') &&
|
||||
(bblCorner(x, y) == nLevel) && (bbrCorner(x, y) == nLevel) && (bbrrCorner(x, y) == nLevel)) {
|
||||
// The tile values follow a predictable pattern, level one craters in order, etc.
|
||||
int16 nBase = 0xA6 + (tlCorner(x, y) * 12) + (nCrater * 4);
|
||||
|
||||
map->terrainStates[x][y] = nBase;
|
||||
map->terrainStates[x + 1][y] = nBase + 1;
|
||||
map->terrainStates[x][y + 1] = nBase + 2;
|
||||
map->terrainStates[x + 1][y + 1] = nBase + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16 MIF::findTileFor(int x, int y) {
|
||||
int index;
|
||||
int8 ch;
|
||||
|
||||
byte aLowBlanks[] = {0x93, 0x94, 0x00, 0x96};
|
||||
byte aMedBlanks[] = {0x97, 0x99, 0x0D, 0x9A};
|
||||
byte aHiBlanks[] = {0x9B, 0x9C, 0x1A, 0x9D};
|
||||
ch = _centerMap[x][y];
|
||||
|
||||
debug(5, "MIF: Tile for %d, %d is %c", x, y, ch);
|
||||
|
||||
if ('S' == ch || 'M' == ch || 'L' == ch || '.' == ch || ch < 0) {
|
||||
// Do the easy cases, things with no transitions.
|
||||
if (0 == tlCorner(x, y) && 0 == trCorner(x, y) && 0 == blCorner(x, y) && 0 == brCorner(x, y))
|
||||
return aLowBlanks[magic(x, y)];
|
||||
if (1 == tlCorner(x, y) && 1 == trCorner(x, y) && 1 == blCorner(x, y) && 1 == brCorner(x, y))
|
||||
return aMedBlanks[magic(x, y)];
|
||||
if (2 == tlCorner(x, y) && 2 == trCorner(x, y) && 2 == blCorner(x, y) && 2 == brCorner(x, y))
|
||||
return aHiBlanks[magic(x, y)];
|
||||
|
||||
//
|
||||
// Low to med transitions
|
||||
//
|
||||
if (0 == tlCorner(x, y) || 0 == trCorner(x, y) || 0 == blCorner(x, y) || 0 == brCorner(x, y)) {
|
||||
// Corner cases
|
||||
|
||||
int cornerSum = tlCorner(x, y) + trCorner(x, y) + blCorner(x, y) + brCorner(x, y);
|
||||
|
||||
if (1 == cornerSum) {
|
||||
if (tlCorner(x, y)) {
|
||||
if (tllCorner(x, y) > 0 && ttlCorner(x, y) > 0)
|
||||
return 0x03;
|
||||
else
|
||||
return 0x89;
|
||||
} else if (trCorner(x, y)) {
|
||||
if (trrCorner(x, y) > 0 && ttrCorner(x, y) > 0)
|
||||
return 0x04;
|
||||
else
|
||||
return 0x8C;
|
||||
} else if (blCorner(x, y)) {
|
||||
if (bllCorner(x, y) > 0 && bblCorner(x, y) > 0)
|
||||
return 0x02;
|
||||
else
|
||||
return 0x86;
|
||||
} else // brCorner
|
||||
{
|
||||
if (brrCorner(x, y) > 0 && bbrCorner(x, y) > 0)
|
||||
return 0x01;
|
||||
else
|
||||
return 0x83;
|
||||
}
|
||||
}
|
||||
|
||||
// Straight edges
|
||||
|
||||
// edge on bottom
|
||||
if (tlCorner(x, y) == 0 && trCorner(x, y) == 0 && blCorner(x, y) == 1 && brCorner(x, y) == 1) {
|
||||
bool bLeftEased = (bllCorner(x, y) == 0 && bblCorner(x, y) == 1);
|
||||
bool bRightEased = (brrCorner(x, y) == 0 && bbrCorner(x, y) == 1);
|
||||
|
||||
if (bLeftEased && bRightEased)
|
||||
return 0x0A;
|
||||
if (!bLeftEased && bRightEased)
|
||||
return 0x54;
|
||||
if (bLeftEased && !bRightEased)
|
||||
return 0x55;
|
||||
if (!bLeftEased && !bRightEased)
|
||||
return (magic(x, y) & 0x01) ? 0x9F : 0x56;
|
||||
}
|
||||
// edge on top
|
||||
else if (tlCorner(x, y) == 1 && trCorner(x, y) == 1 && blCorner(x, y) == 0 && brCorner(x, y) == 0) {
|
||||
bool bLeftEased = (tllCorner(x, y) == 0 && ttlCorner(x, y) == 1);
|
||||
bool bRightEased = (trrCorner(x, y) == 0 && ttrCorner(x, y) == 1);
|
||||
|
||||
if (bLeftEased && bRightEased)
|
||||
return 0x0C;
|
||||
if (!bLeftEased && bRightEased)
|
||||
return 0x52;
|
||||
if (bLeftEased && !bRightEased)
|
||||
return 0x51;
|
||||
if (!bLeftEased && !bRightEased)
|
||||
return (magic(x, y) & 0x01) ? 0xA1 : 0x53;
|
||||
}
|
||||
// edge on right
|
||||
if (tlCorner(x, y) == 0 && blCorner(x, y) == 0 && trCorner(x, y) == 1 && brCorner(x, y) == 1) {
|
||||
bool bTopEased = (ttrCorner(x, y) == 0 && trrCorner(x, y) == 1);
|
||||
bool bBotEased = (bbrCorner(x, y) == 0 && brrCorner(x, y) == 1);
|
||||
|
||||
if (bTopEased && bBotEased)
|
||||
return 0x09;
|
||||
if (!bTopEased && bBotEased)
|
||||
return 0x5B;
|
||||
if (bTopEased && !bBotEased)
|
||||
return 0x5A;
|
||||
if (!bTopEased && !bBotEased)
|
||||
return (magic(x, y) & 0x01) ? 0x9E : 0x5C;
|
||||
}
|
||||
// edge on left
|
||||
if (tlCorner(x, y) == 1 && blCorner(x, y) == 1 && trCorner(x, y) == 0 && brCorner(x, y) == 0) {
|
||||
bool bTopEased = (ttlCorner(x, y) == 0 && tllCorner(x, y) == 1);
|
||||
bool bBotEased = (bblCorner(x, y) == 0 && bllCorner(x, y) == 1);
|
||||
|
||||
if (bTopEased && bBotEased)
|
||||
return 0x0B;
|
||||
if (!bTopEased && bBotEased)
|
||||
return 0x57;
|
||||
if (bTopEased && !bBotEased)
|
||||
return 0x58;
|
||||
if (!bTopEased && !bBotEased)
|
||||
return (magic(x, y) & 0x01) ? 0xA0 : 0x59;
|
||||
}
|
||||
|
||||
// Three corner cases
|
||||
|
||||
// 0 1 1 1 0 0 0 0 0 0
|
||||
// 0 1 1 0x5F 0 1 1 0x5E 0 1 1 0x62 0 1 1 0x60
|
||||
// 0 0 0 0 0 0 0 1 1 1
|
||||
//
|
||||
// 0 1 1 1 0 0 1 0 0 1
|
||||
// 0 1 1 0x5D 0 1 1 0x06 0 1 1 0x61 0 1 1 0x07
|
||||
// 0 0 1 0 0 1 0 1 1 1
|
||||
//
|
||||
//
|
||||
// 0 0 0 1 0 0 1 0 1 1
|
||||
// 1 1 0 0x65 1 1 0 0x63 1 1 0 0x68 1 1 0 0x66
|
||||
// 1 0 1 0 0 0 0 0 0 0
|
||||
//
|
||||
// 0 0 0 1 0 0 1 0 1 1
|
||||
// 1 1 0 0x64 1 1 0 0x08 1 1 0 0x67 1 1 0 0x05
|
||||
// 1 1 1 1 1 0 0 1 0 0
|
||||
|
||||
// corner in upper left
|
||||
if (blCorner(x, y) == 1 && tlCorner(x, y) == 1 && trCorner(x, y) == 1) {
|
||||
bool BLDiag = (bllCorner(x, y) > 0 && bblCorner(x, y) == 0);
|
||||
bool TRDiag = (ttrCorner(x, y) > 0 && trrCorner(x, y) == 0);
|
||||
|
||||
if (!BLDiag && !TRDiag)
|
||||
return 0x62;
|
||||
else if (!BLDiag && TRDiag)
|
||||
return 0x61;
|
||||
else if (BLDiag && !TRDiag)
|
||||
return 0x60;
|
||||
else
|
||||
return 0x07;
|
||||
}
|
||||
|
||||
// corner in upper right
|
||||
if (tlCorner(x, y) == 1 && trCorner(x, y) == 1 && brCorner(x, y) == 1) {
|
||||
bool TLDiag = (ttlCorner(x, y) > 0 && tllCorner(x, y) == 0);
|
||||
bool BRDiag = (brrCorner(x, y) > 0 && bbrCorner(x, y) == 0);
|
||||
|
||||
if (!TLDiag && !BRDiag)
|
||||
return 0x65;
|
||||
else if (!TLDiag && BRDiag)
|
||||
return 0x64;
|
||||
else if (TLDiag && !BRDiag)
|
||||
return 0x63;
|
||||
else
|
||||
return 0x08;
|
||||
}
|
||||
|
||||
// corner in bottom right
|
||||
if (trCorner(x, y) == 1 && brCorner(x, y) == 1 && blCorner(x, y) == 1) {
|
||||
bool TRDiag = (trrCorner(x, y) > 0 && ttrCorner(x, y) == 0);
|
||||
bool BLDiag = (bblCorner(x, y) > 0 && bllCorner(x, y) == 0);
|
||||
|
||||
if (!TRDiag && !BLDiag)
|
||||
return 0x68;
|
||||
else if (!TRDiag && BLDiag)
|
||||
return 0x67;
|
||||
else if (TRDiag && !BLDiag)
|
||||
return 0x66;
|
||||
else
|
||||
return 0x05;
|
||||
}
|
||||
|
||||
// corner in bottom left
|
||||
if (brCorner(x, y) == 1 && blCorner(x, y) == 1 && tlCorner(x, y) == 1) {
|
||||
bool TLDiag = (tllCorner(x, y) > 0 && ttlCorner(x, y) == 0);
|
||||
bool BRDiag = (bbrCorner(x, y) > 0 && brrCorner(x, y) == 0);
|
||||
|
||||
if (!TLDiag && !BRDiag)
|
||||
return 0x5F;
|
||||
else if (!TLDiag && BRDiag)
|
||||
return 0x5D;
|
||||
else if (TLDiag && !BRDiag)
|
||||
return 0x5E;
|
||||
else
|
||||
return 0x06;
|
||||
}
|
||||
|
||||
// Opposing corner cases
|
||||
if (tlCorner(x, y) == 1 && brCorner(x, y) == 1) {
|
||||
// There are four cases, big big, big small, small big, small small
|
||||
|
||||
// big big
|
||||
if (tllCorner(x, y) > 0 && ttlCorner(x, y) > 0 && brrCorner(x, y) > 0 && bbrCorner(x, y) > 0)
|
||||
return 0x4D;
|
||||
// big small
|
||||
if (tllCorner(x, y) > 0 && ttlCorner(x, y) > 0)
|
||||
return 0x81;
|
||||
// small big
|
||||
if (brrCorner(x, y) > 0 && bbrCorner(x, y) > 0)
|
||||
return 0x82;
|
||||
// small small
|
||||
return 0x84;
|
||||
}
|
||||
if (trCorner(x, y) == 1 && blCorner(x, y) == 1) {
|
||||
// There are four cases, big big, big small, small big, small small
|
||||
|
||||
// big big
|
||||
if (trrCorner(x, y) > 0 && ttrCorner(x, y) > 0 && bllCorner(x, y) > 0 && bblCorner(x, y) > 0)
|
||||
return 0x4E;
|
||||
// big small
|
||||
if (trrCorner(x, y) > 0 && ttrCorner(x, y) > 0)
|
||||
return 0x85;
|
||||
// small big
|
||||
if (bllCorner(x, y) > 0 && bblCorner(x, y) > 0)
|
||||
return 0x87;
|
||||
// small small
|
||||
return 0x88;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Med to high transitions
|
||||
//
|
||||
if (1 == tlCorner(x, y) || 1 == trCorner(x, y) || 1 == blCorner(x, y) || 1 == brCorner(x, y)) {
|
||||
// Corner cases
|
||||
|
||||
int cornerSum = (tlCorner(x, y) == 2) + (trCorner(x, y) == 2) + (blCorner(x, y) == 2) + (brCorner(x, y) == 2);
|
||||
|
||||
if (1 == cornerSum) {
|
||||
if (tlCorner(x, y) == 2) {
|
||||
if (tllCorner(x, y) == 2 && ttlCorner(x, y) == 2)
|
||||
return 0x10;
|
||||
else
|
||||
return 0x95;
|
||||
} else if (trCorner(x, y) == 2) {
|
||||
if (trrCorner(x, y) == 2 && ttrCorner(x, y) == 2)
|
||||
return 0x11;
|
||||
else
|
||||
return 0x98;
|
||||
} else if (blCorner(x, y) == 2) {
|
||||
if (bllCorner(x, y) == 2 && bblCorner(x, y) == 2)
|
||||
return 0x0F;
|
||||
else
|
||||
return 0x92;
|
||||
} else // brCorner
|
||||
{
|
||||
if (brrCorner(x, y) == 2 && bbrCorner(x, y) == 2)
|
||||
return 0x0E;
|
||||
else
|
||||
return 0x8F;
|
||||
}
|
||||
}
|
||||
|
||||
// Straight edges
|
||||
|
||||
// edge on bottom
|
||||
if (tlCorner(x, y) < 2 && trCorner(x, y) < 2 && blCorner(x, y) == 2 && brCorner(x, y) == 2) {
|
||||
bool bLeftEased = (bllCorner(x, y) < 2 && bblCorner(x, y) == 2);
|
||||
bool bRightEased = (brrCorner(x, y) < 2 && bbrCorner(x, y) == 2);
|
||||
|
||||
if (bLeftEased && bRightEased)
|
||||
return 0x17;
|
||||
if (!bLeftEased && bRightEased)
|
||||
return 0x6C;
|
||||
if (bLeftEased && !bRightEased)
|
||||
return 0x6D;
|
||||
if (!bLeftEased && !bRightEased)
|
||||
return (magic(x, y) & 0x01) ? 0xA3 : 0x6E;
|
||||
}
|
||||
// edge on top
|
||||
else if (tlCorner(x, y) == 2 && trCorner(x, y) == 2 && blCorner(x, y) < 2 && brCorner(x, y) < 2) {
|
||||
bool bLeftEased = (tllCorner(x, y) < 2 && ttlCorner(x, y) == 2);
|
||||
bool bRightEased = (trrCorner(x, y) < 2 && ttrCorner(x, y) == 2);
|
||||
|
||||
if (bLeftEased && bRightEased)
|
||||
return 0x19;
|
||||
if (!bLeftEased && bRightEased)
|
||||
return 0x6A;
|
||||
if (bLeftEased && !bRightEased)
|
||||
return 0x69;
|
||||
if (!bLeftEased && !bRightEased)
|
||||
return (magic(x, y) & 0x01) ? 0xA5 : 0x6B;
|
||||
}
|
||||
// edge on right
|
||||
if (tlCorner(x, y) < 2 && blCorner(x, y) < 2 && trCorner(x, y) == 2 && brCorner(x, y) == 2) {
|
||||
bool bTopEased = (ttrCorner(x, y) < 2 && trrCorner(x, y) == 2);
|
||||
bool bBotEased = (bbrCorner(x, y) < 2 && brrCorner(x, y) == 2);
|
||||
|
||||
if (bTopEased && bBotEased)
|
||||
return 0x16;
|
||||
if (!bTopEased && bBotEased)
|
||||
return 0x73;
|
||||
if (bTopEased && !bBotEased)
|
||||
return 0x72;
|
||||
if (!bTopEased && !bBotEased)
|
||||
return (magic(x, y) & 0x01) ? 0xA2 : 0x74;
|
||||
}
|
||||
// edge on left
|
||||
if (tlCorner(x, y) == 2 && blCorner(x, y) == 2 && trCorner(x, y) < 2 && brCorner(x, y) < 2) {
|
||||
bool bTopEased = (ttlCorner(x, y) < 2 && tllCorner(x, y) == 2);
|
||||
bool bBotEased = (bblCorner(x, y) < 2 && bllCorner(x, y) == 2);
|
||||
|
||||
if (bTopEased && bBotEased)
|
||||
return 0x18;
|
||||
if (!bTopEased && bBotEased)
|
||||
return 0x6F;
|
||||
if (bTopEased && !bBotEased)
|
||||
return 0x70;
|
||||
if (!bTopEased && !bBotEased)
|
||||
return (magic(x, y) & 0x01) ? 0xA4 : 0x71;
|
||||
}
|
||||
|
||||
// edge on bottom
|
||||
if (tlCorner(x, y) == 1 && trCorner(x, y) == 1 && blCorner(x, y) == 2 && brCorner(x, y) == 2) {
|
||||
// no other high corners
|
||||
if (bllCorner(x, y) < 2 && brrCorner(x, y) < 2)
|
||||
return 0x17;
|
||||
// high corner on left
|
||||
if (bllCorner(x, y) == 2 && brrCorner(x, y) < 2)
|
||||
return 0x6C;
|
||||
// high corner on right
|
||||
if (bllCorner(x, y) < 2 && brrCorner(x, y) == 2)
|
||||
return 0x6D;
|
||||
// both neighbor corners high
|
||||
if (bllCorner(x, y) == 2 && brrCorner(x, y) == 2)
|
||||
return (magic(x, y) & 0x01) ? 0xA3 : 0x6E;
|
||||
}
|
||||
// edge on top
|
||||
else if (tlCorner(x, y) == 2 && trCorner(x, y) == 2 && blCorner(x, y) == 1 && brCorner(x, y) == 1) {
|
||||
// no other high corners
|
||||
if (tllCorner(x, y) < 2 && trrCorner(x, y) < 2)
|
||||
return 0x19;
|
||||
// high corner on left
|
||||
if (tllCorner(x, y) == 2 && trrCorner(x, y) < 2)
|
||||
return 0x6A;
|
||||
// high corner on right
|
||||
if (tllCorner(x, y) < 2 && trrCorner(x, y) == 2)
|
||||
return 0x69;
|
||||
// both neighbor corners high
|
||||
if (tllCorner(x, y) == 2 && trrCorner(x, y) == 2)
|
||||
return (magic(x, y) & 0x01) ? 0xA5 : 0x6B;
|
||||
}
|
||||
// edge on right
|
||||
if (tlCorner(x, y) == 1 && blCorner(x, y) == 1 && trCorner(x, y) == 2 && brCorner(x, y) == 2) {
|
||||
// no high neighbor corners
|
||||
if (ttrCorner(x, y) < 2 && bbrCorner(x, y) < 2)
|
||||
return 0x16;
|
||||
// high neighbor corner on top
|
||||
if (ttrCorner(x, y) == 2 && bbrCorner(x, y) < 2)
|
||||
return 0x73;
|
||||
// high neighbor corner on bottom
|
||||
if (ttrCorner(x, y) < 2 && bbrCorner(x, y) == 2)
|
||||
return 0x72;
|
||||
// both neighbor corners high
|
||||
if (ttrCorner(x, y) == 2 && bbrCorner(x, y) == 2)
|
||||
return (magic(x, y) & 0x01) ? 0xA2 : 0x74;
|
||||
}
|
||||
// edge on left
|
||||
if (tlCorner(x, y) == 2 && blCorner(x, y) == 2 && trCorner(x, y) == 1 && brCorner(x, y) == 1) {
|
||||
// no high neighbor corners
|
||||
if (ttlCorner(x, y) < 2 && bblCorner(x, y) < 2)
|
||||
return 0x18;
|
||||
// high neighbor corner on top
|
||||
if (ttlCorner(x, y) == 2 && bblCorner(x, y) < 2)
|
||||
return 0x6F;
|
||||
// high neighbor corner on bottom
|
||||
if (ttlCorner(x, y) < 2 && bblCorner(x, y) == 2)
|
||||
return 0x70;
|
||||
// both neighbor corners high
|
||||
if (ttlCorner(x, y) == 2 && bblCorner(x, y) == 2)
|
||||
return (magic(x, y) & 0x01) ? 0xA4 : 0x71;
|
||||
}
|
||||
|
||||
// Three corner cases
|
||||
|
||||
// Three corner cases
|
||||
|
||||
// 0 1 1 1 0 0 0 0 0 0
|
||||
// 0 1 1 0x77 0 1 1 0x76 0 1 1 0x7A 0 1 1 0x78
|
||||
// 0 0 0 0 0 0 0 1 1 1
|
||||
//
|
||||
// 0 1 1 1 0 0 1 0 0 1
|
||||
// 0 1 1 0x75 0 1 1 0x13 0 1 1 0x79 0 1 1 0x14
|
||||
// 0 0 1 0 0 1 0 1 1 1
|
||||
//
|
||||
//
|
||||
// 0 0 0 1 0 0 1 0 1 1
|
||||
// 1 1 0 0x7D 1 1 0 0x7B 1 1 0 0x80 1 1 0 0x7E
|
||||
// 1 0 1 0 0 0 0 0 0 0
|
||||
//
|
||||
// 0 0 0 1 0 0 1 0 1 1
|
||||
// 1 1 0 0x7C 1 1 0 0x15 1 1 0 0x7F 1 1 0 0x12
|
||||
// 1 1 1 1 1 0 0 1 0 0
|
||||
|
||||
// corner in upper left
|
||||
if (blCorner(x, y) == 2 && tlCorner(x, y) == 2 && trCorner(x, y) == 2) {
|
||||
bool BLDiag = (bllCorner(x, y) > 1 && bblCorner(x, y) < 2);
|
||||
bool TRDiag = (ttrCorner(x, y) > 1 && trrCorner(x, y) < 2);
|
||||
|
||||
if (!BLDiag && !TRDiag)
|
||||
return 0x7A;
|
||||
else if (!BLDiag && TRDiag)
|
||||
return 0x79;
|
||||
else if (BLDiag && !TRDiag)
|
||||
return 0x78;
|
||||
else
|
||||
return 0x14;
|
||||
}
|
||||
|
||||
// corner in upper right
|
||||
if (tlCorner(x, y) == 2 && trCorner(x, y) == 2 && brCorner(x, y) == 2) {
|
||||
bool TLDiag = ((ttlCorner(x, y) > 1) && (tllCorner(x, y) < 2));
|
||||
bool BRDiag = ((brrCorner(x, y) > 1) && (bbrCorner(x, y) < 2));
|
||||
|
||||
if (!TLDiag && !BRDiag)
|
||||
return 0x7D;
|
||||
else if (!TLDiag && BRDiag)
|
||||
return 0x7C;
|
||||
else if (TLDiag && !BRDiag)
|
||||
return 0x7B;
|
||||
else
|
||||
return 0x15;
|
||||
}
|
||||
|
||||
// corner in bottom right
|
||||
if (trCorner(x, y) == 2 && brCorner(x, y) == 2 && blCorner(x, y) == 2) {
|
||||
bool TRDiag = (trrCorner(x, y) > 1 && ttrCorner(x, y) < 2);
|
||||
bool BLDiag = (bblCorner(x, y) > 1 && bllCorner(x, y) < 2);
|
||||
|
||||
if (!TRDiag && !BLDiag)
|
||||
return 0x80;
|
||||
else if (!TRDiag && BLDiag)
|
||||
return 0x7F;
|
||||
else if (TRDiag && !BLDiag)
|
||||
return 0x7E;
|
||||
else
|
||||
return 0x12;
|
||||
}
|
||||
|
||||
// corner in bottom left
|
||||
if (brCorner(x, y) == 2 && blCorner(x, y) == 2 && tlCorner(x, y) == 2) {
|
||||
bool TLDiag = (tllCorner(x, y) > 1 && ttlCorner(x, y) < 2);
|
||||
bool BRDiag = (bbrCorner(x, y) > 1 && brrCorner(x, y) < 2);
|
||||
|
||||
if (!TLDiag && !BRDiag)
|
||||
return 0x77;
|
||||
else if (!TLDiag && BRDiag)
|
||||
return 0x75;
|
||||
else if (TLDiag && !BRDiag)
|
||||
return 0x76;
|
||||
else
|
||||
return 0x13;
|
||||
}
|
||||
|
||||
// Opposing corner cases
|
||||
if (tlCorner(x, y) == 2 && brCorner(x, y) == 2) {
|
||||
// There are four cases, big big, big small, small big, small small
|
||||
|
||||
// big big
|
||||
if (tllCorner(x, y) == 2 && ttlCorner(x, y) == 2 && brrCorner(x, y) == 2 && bbrCorner(x, y) == 2)
|
||||
return 0x4F;
|
||||
// big small
|
||||
if (tllCorner(x, y) == 2 && ttlCorner(x, y) == 2)
|
||||
return 0x8A;
|
||||
// small big
|
||||
if (brrCorner(x, y) == 2 && bbrCorner(x, y) == 2)
|
||||
return 0x8B;
|
||||
// small small
|
||||
return 0x8D;
|
||||
}
|
||||
if (trCorner(x, y) == 2 && blCorner(x, y) == 2) {
|
||||
// There are four cases, big big, big small, small big, small small
|
||||
|
||||
// big big
|
||||
if (trrCorner(x, y) == 2 && ttrCorner(x, y) == 2 && bllCorner(x, y) == 2 && bblCorner(x, y) == 2)
|
||||
return 0x50;
|
||||
// big small
|
||||
if (trrCorner(x, y) == 2 && ttrCorner(x, y) == 2)
|
||||
return 0x8E;
|
||||
// small big
|
||||
if (bllCorner(x, y) == 2 && bblCorner(x, y) == 2)
|
||||
return 0x90;
|
||||
// small small
|
||||
return 0x91;
|
||||
}
|
||||
}
|
||||
|
||||
error("illegal corner height arrangement (%d, %d)", x, y);
|
||||
} else if ('W' == ch) {
|
||||
// Check to make sure that we're on ground level
|
||||
if (tlCorner(x, y) > 0 || trCorner(x, y) > 0 || blCorner(x, y) > 0 || brCorner(x, y) > 0)
|
||||
error("water must be on a flat tile (%d, %d)", x, y);
|
||||
|
||||
index = (('W' != tlCenter(x, y)) << 7) |
|
||||
(('W' != tCenter(x, y)) << 6) |
|
||||
(('W' != trCenter(x, y)) << 5) |
|
||||
(('W' != lCenter(x, y)) << 4) |
|
||||
(('W' != rCenter(x, y)) << 3) |
|
||||
(('W' != blCenter(x, y)) << 2) |
|
||||
(('W' != bCenter(x, y)) << 1) |
|
||||
('W' != brCenter(x, y));
|
||||
|
||||
uint16 nWaterTile = waterTileMap[index];
|
||||
|
||||
if (0x44 == nWaterTile) {
|
||||
uint16 aWaterBlanks[] = {0x45, 0x46, 0x44, 0x47};
|
||||
|
||||
nWaterTile = aWaterBlanks[magic(x, y)];
|
||||
}
|
||||
|
||||
return nWaterTile;
|
||||
} else
|
||||
error("illegal tile character (%d, %d)", x, y);
|
||||
|
||||
error("unknown tile find error (%d, %d)", x, y);
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
203
engines/scumm/he/moonbase/map_mif.h
Normal file
203
engines/scumm/he/moonbase/map_mif.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_MAP_MIF_H
|
||||
#define SCUMM_HE_MOONBASE_MAP_MIF_H
|
||||
|
||||
#ifdef ENABLE_HE
|
||||
|
||||
#include "scumm/he/intern_he.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
#define MAX_TILE_COUNT 80
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
struct PixelLoc {
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
};
|
||||
|
||||
struct EnergyPoolLoc {
|
||||
PixelLoc location;
|
||||
PixelLoc dummy;
|
||||
};
|
||||
|
||||
|
||||
struct MapFile {
|
||||
// Header:
|
||||
uint16 headerDummy;
|
||||
uint16 terrainDimX;
|
||||
uint16 terrainDimY;
|
||||
uint16 mapType;
|
||||
uint16 numEnergyPools;
|
||||
|
||||
uint16 terrainStates[80][161];
|
||||
uint8 space1[230];
|
||||
char name[17];
|
||||
uint8 space2[25837];
|
||||
EnergyPoolLoc poolLocs[49];
|
||||
PixelLoc lastPool;
|
||||
uint16 dummy;
|
||||
PixelLoc fourPlayerPoints[4]; // 2^0
|
||||
PixelLoc threePlayerPoints[3]; // 2^1
|
||||
PixelLoc twoPlayerPoints[2]; // 2^2
|
||||
PixelLoc twoVTwoPoints[4]; // 2^3
|
||||
PixelLoc oneVThreePoints[4]; // 2^4
|
||||
PixelLoc oneVTwoPoints[3]; // 2^5
|
||||
|
||||
MapFile() {
|
||||
memset(this, 0, sizeof(MapFile));
|
||||
|
||||
mapType = 1;
|
||||
memset(fourPlayerPoints, 0xFF, sizeof(fourPlayerPoints));
|
||||
memset(threePlayerPoints, 0xFF, sizeof(threePlayerPoints));
|
||||
memset(twoPlayerPoints, 0xFF, sizeof(twoPlayerPoints));
|
||||
memset(twoVTwoPoints, 0xFF, sizeof(twoVTwoPoints));
|
||||
memset(oneVThreePoints, 0xFF, sizeof(oneVThreePoints));
|
||||
memset(oneVTwoPoints, 0xFF, sizeof(oneVTwoPoints));
|
||||
}
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
class MIF {
|
||||
public:
|
||||
MIF();
|
||||
|
||||
void generateMap(MapFile *map);
|
||||
|
||||
int _dimension = 0; // 32 (small), 40 (medium), 48 (large), 56 (huge), 64 (SAI)
|
||||
int _mapType = 0;
|
||||
char _name[17] = {};
|
||||
byte _cornerMap[MAX_TILE_COUNT][MAX_TILE_COUNT] = { {}, {} };
|
||||
int8 _centerMap[MAX_TILE_COUNT][MAX_TILE_COUNT] = { {}, {} };
|
||||
private:
|
||||
|
||||
void defineStartLocations(MapFile *map);
|
||||
void defineEnergyPools(MapFile *map);
|
||||
void makeCraters(MapFile *map);
|
||||
uint16 findTileFor(int x, int y);
|
||||
|
||||
inline char tlCenter(int x, int y) const {
|
||||
return _centerMap[(0 == x) ? _dimension - 1 : x - 1][(0 == y) ? _dimension - 1 : y - 1];
|
||||
}
|
||||
|
||||
inline char tCenter(int x, int y) const {
|
||||
return _centerMap[x][(0 == y) ? _dimension - 1 : y - 1];
|
||||
}
|
||||
|
||||
inline char trCenter(int x, int y) const {
|
||||
return _centerMap[(x + 1) % _dimension][(0 == y) ? _dimension - 1 : y - 1];
|
||||
}
|
||||
|
||||
inline char lCenter(int x, int y) const {
|
||||
return _centerMap[(0 == x) ? _dimension - 1 : x - 1][y];
|
||||
}
|
||||
|
||||
inline char rCenter(int x, int y) const {
|
||||
return _centerMap[(x + 1) % _dimension][y];
|
||||
}
|
||||
|
||||
inline char blCenter(int x, int y) const {
|
||||
return _centerMap[(0 == x) ? _dimension - 1 : x - 1][(y + 1) % _dimension];
|
||||
}
|
||||
|
||||
inline char bCenter(int x, int y) const {
|
||||
return _centerMap[x][(y + 1) % _dimension];
|
||||
}
|
||||
|
||||
inline char brCenter(int x, int y) const {
|
||||
return _centerMap[(x + 1) % _dimension][(y + 1) % _dimension];
|
||||
}
|
||||
|
||||
inline byte tlCorner(int x, int y) const {
|
||||
return _cornerMap[x][y];
|
||||
}
|
||||
|
||||
inline byte trCorner(int x, int y) const {
|
||||
return _cornerMap[(x + 1) % _dimension][y];
|
||||
}
|
||||
|
||||
inline byte blCorner(int x, int y) const {
|
||||
return _cornerMap[x][(y + 1) % _dimension];
|
||||
}
|
||||
|
||||
inline byte brCorner(int x, int y) const {
|
||||
return _cornerMap[(x + 1) % _dimension][(y + 1) % _dimension];
|
||||
}
|
||||
|
||||
inline byte ttllCorner(int x, int y) const {
|
||||
return tlCorner((x == 0) ? _dimension - 1 : x - 1, (y == 0) ? _dimension - 1: y - 1);
|
||||
}
|
||||
|
||||
inline byte ttlCorner(int x, int y) const {
|
||||
return trCorner((x == 0) ? _dimension - 1 : x - 1, (y == 0) ? _dimension - 1: y - 1);
|
||||
}
|
||||
|
||||
inline byte ttrCorner(int x, int y) const {
|
||||
return tlCorner((x + 1) % _dimension, (y == 0) ? _dimension - 1: y - 1);
|
||||
}
|
||||
|
||||
inline byte ttrrCorner(int x, int y) const {
|
||||
return trCorner((x + 1) % _dimension, (y == 0) ? _dimension - 1: y - 1);
|
||||
}
|
||||
|
||||
inline byte tllCorner(int x, int y) const {
|
||||
return tlCorner((x == 0) ? _dimension - 1 : x - 1, y);
|
||||
}
|
||||
|
||||
inline byte trrCorner(int x, int y) const {
|
||||
return trCorner((x + 1) % _dimension, y);
|
||||
}
|
||||
|
||||
inline byte bllCorner(int x, int y) const {
|
||||
return blCorner((x == 0) ? _dimension - 1 : x - 1, y);
|
||||
}
|
||||
|
||||
inline byte brrCorner(int x, int y) const {
|
||||
return brCorner((x + 1) % _dimension, y);
|
||||
}
|
||||
|
||||
inline byte bbllCorner(int x, int y) const {
|
||||
return blCorner((x == 0) ? _dimension - 1 : x - 1, (y + 1) % _dimension);
|
||||
}
|
||||
|
||||
inline byte bblCorner(int x, int y) const {
|
||||
return brCorner((x == 0) ? _dimension - 1 : x - 1, (y + 1) % _dimension);
|
||||
}
|
||||
|
||||
inline byte bbrCorner(int x, int y) const {
|
||||
return blCorner((x + 1) % _dimension, (y + 1) % _dimension);
|
||||
}
|
||||
|
||||
inline byte bbrrCorner(int x, int y) const {
|
||||
return brCorner((x + 1) % _dimension, (y + 1) % _dimension);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif // ENABLE_HE
|
||||
|
||||
#endif // SCUMM_HE_MOONBASE_MAP_MIF_H
|
||||
620
engines/scumm/he/moonbase/map_spiff.cpp
Normal file
620
engines/scumm/he/moonbase/map_spiff.cpp
Normal file
@@ -0,0 +1,620 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include "scumm/he/moonbase/map_spiff.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
SpiffGenerator::SpiffGenerator(int seed) {
|
||||
_seed = seed;
|
||||
}
|
||||
|
||||
MapFile *SpiffGenerator::generateMap(int water, int tileset, int mapSize, int energy, int terrain) {
|
||||
_totalMapSizeG = mapSize;
|
||||
_energyAmountG = (2 + energy) * _totalMapSizeG * _totalMapSizeG;
|
||||
|
||||
_islandsFlagG = pickFrom2(0, 1, water - 4, (water >= 5)); // 1 is large islands, 2 is small
|
||||
if (_islandsFlagG) {
|
||||
water -= 3;
|
||||
_energyAmountG = (int)(_energyAmountG * (5 - _islandsFlagG) / 6); // *2/3 or *1/2
|
||||
}
|
||||
|
||||
_waterAmountG = 4 * water;
|
||||
_cliffAmountG = 1 << terrain;
|
||||
_advancedMirrorOK_G = ((terrain > 1) && (water < 6)) || _islandsFlagG;
|
||||
_terrainSeedFlagG = 2 * water - terrain;
|
||||
|
||||
int n = (int)(_energyAmountG / 2700);
|
||||
if (n > 12) {
|
||||
n = 12;
|
||||
}
|
||||
if (n < 1) {
|
||||
n = 1;
|
||||
}
|
||||
_numPoolsG = spiffRand((int)(_energyAmountG / 4000) + 1, n);
|
||||
if (_numPoolsG > 12) {
|
||||
_numPoolsG = 12;
|
||||
}
|
||||
|
||||
generate();
|
||||
|
||||
// Populate MIF for map data generation:
|
||||
MIF mif = MIF();
|
||||
|
||||
int levelMap[MAXELEVVAL];
|
||||
levelMap[kElevHigh] = 2;
|
||||
levelMap[kElevMedium] = 1;
|
||||
levelMap[kElevLow] = 0;
|
||||
|
||||
mif._mapType = tileset;
|
||||
Common::sprintf_s(mif._name, "Spiff %04X", (uint16)_seed);
|
||||
|
||||
mif._dimension = _totalMapSizeG;
|
||||
|
||||
int y;
|
||||
int x;
|
||||
byte t;
|
||||
int XOffset = spiffRand(0, _totalMapSizeG-1);
|
||||
int YOffset = spiffRand(0, _totalMapSizeG-1);
|
||||
int newX;
|
||||
int newY;
|
||||
|
||||
for (y = 0, newY = YOffset; y < _totalMapSizeG; ++y, ++newY) {
|
||||
for (x = 0, newX = XOffset; x < _totalMapSizeG; ++x, ++newX) {
|
||||
if (newX == _totalMapSizeG)
|
||||
newX = 0;
|
||||
if (newY == _totalMapSizeG)
|
||||
newY = 0;
|
||||
mif._cornerMap[newX][newY] = levelMap[_mapCorner[x][y]];
|
||||
switch (_mapMiddle[x][y]) {
|
||||
case HUB:
|
||||
t = 0xff;
|
||||
break;
|
||||
case SMALLPOOL:
|
||||
t = 'S';
|
||||
break;
|
||||
case MEDIUMPOOL:
|
||||
t = 'M';
|
||||
break;
|
||||
case LARGEPOOLBOTTOM:
|
||||
t = 'L';
|
||||
break;
|
||||
case WATER:
|
||||
t = 'W';
|
||||
break;
|
||||
case UNASSIGNED:
|
||||
case LARGEPOOLTOP:
|
||||
t = '.';
|
||||
break;
|
||||
default:
|
||||
t = '?';
|
||||
}
|
||||
mif._centerMap[newX][newY] = t;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate new map:
|
||||
MapFile *map = new MapFile();
|
||||
mif.generateMap(map);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
float SpiffGenerator::getRandomFloat() {
|
||||
// This is the exact linear congruential generator
|
||||
// algorithm used on MSVCRT (Windows Visual C++ Runtime), with
|
||||
// RAND_MAX being 0x7fff (32767). This is implemented here
|
||||
// to match the RNG between the original Moonbase Console
|
||||
// program and ScummVM.
|
||||
//
|
||||
// (Common::RandomSource uses Xorshift and uses unsigned
|
||||
// integers compared to MSVCRT's rand)
|
||||
_seed = _seed * 214013 + 2531011;
|
||||
return (float)((_seed >> 16) & 0x7fff) / 32767;
|
||||
}
|
||||
|
||||
int SpiffGenerator::spiffRand(int min, int max) {
|
||||
// returns a random integer min to max inclusive
|
||||
return ((int)(getRandomFloat() * (max + 1 - min))) + min;
|
||||
}
|
||||
|
||||
int SpiffGenerator::pickFrom2(int a, int probA, int b, int probB) {
|
||||
debug(3, "SpiffGenerator::pickFrom2(%d, %d, %d, %d)", a, probA, b, probB);
|
||||
float r = getRandomFloat() * (probA + probB);
|
||||
debug(3, " r = %f", r);
|
||||
if (r < probA)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
int SpiffGenerator::pickFrom3(int a, int probA, int b, int probB, int c, int probC) {
|
||||
debug(3, "SpiffGenerator::pickFrom3(%d, %d, %d, %d, %d, %d)", a, probA, b, probB, c, probC);
|
||||
float r = getRandomFloat() * (probA + probB + probC);
|
||||
debug(3, " r = %f", r);
|
||||
if (r < probA)
|
||||
return a;
|
||||
else if (r < probA + probB)
|
||||
return b;
|
||||
else
|
||||
return c;
|
||||
}
|
||||
|
||||
int SpiffGenerator::pickFrom4(int a, int probA, int b, int probB, int c, int probC, int d, int probD) {
|
||||
debug(3, "SpiffGenerator::pickFrom4(%d, %d, %d, %d, %d, %d, %d, %d)", a, probA, b, probB, c, probC, d, probD);
|
||||
float r = getRandomFloat() * (probA + probB + probC + probD);
|
||||
debug(3, " r = %f", r);
|
||||
if (r < probA)
|
||||
return a;
|
||||
else if (r < probA + probB)
|
||||
return b;
|
||||
else if (r < probA + probB + probC)
|
||||
return c;
|
||||
else
|
||||
return d;
|
||||
}
|
||||
|
||||
void SpiffGenerator::getSpecials() {
|
||||
// choose where the starting points and pools are
|
||||
int x, y, p, t;
|
||||
int edgeWaterA = (int)(_islandsFlagG * _totalMapSizeG / 16 + 0.5);
|
||||
int edgeWaterB = (int)(_islandsFlagG * _totalMapSizeG / 16); // don't put pools between islands
|
||||
|
||||
// No matter what, they get a start hub spot.
|
||||
if (_mirrorTypeG == MAXDISTMIRROR)
|
||||
x = (int)((_totalMapSizeG * 3 + 8) / 16);
|
||||
else
|
||||
x = (int)(_mapMiddleMaxG / 2);
|
||||
y = x;
|
||||
|
||||
_mapMiddle[x][y] = HUB; // hub start position
|
||||
|
||||
for (p = 1; p <= _numPoolsG; ++p) {
|
||||
x = spiffRand(edgeWaterA, _mapMiddleMaxG - edgeWaterB);
|
||||
y = spiffRand(edgeWaterA, _mapMiddleMaxG - edgeWaterB);
|
||||
if (_mapMiddle[x][y] != UNASSIGNED)
|
||||
--p; // repick this pool
|
||||
else {
|
||||
t = pickFrom3(SMALLPOOL, 40000 * _numPoolsG, MEDIUMPOOL, 20000 * _numPoolsG + _energyAmountG, LARGEPOOLTOP, 2 * _energyAmountG);
|
||||
if (t == LARGEPOOLTOP) {
|
||||
if ((y == _mapMiddleMaxG - edgeWaterB) || (_mapMiddle[x][y + 1] != UNASSIGNED))
|
||||
t = SMALLPOOL; // keep large pool from being too high or overlapping another pool or start
|
||||
else
|
||||
_mapMiddle[x][y + 1] = LARGEPOOLBOTTOM;
|
||||
}
|
||||
_mapMiddle[x][y] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpiffGenerator::copyMap(int XOffset, int YOffset, int XDirection, int YDirection) {
|
||||
// copies the first quadrant of the map
|
||||
// XOffset and YOffset are the distances moved
|
||||
// XDirection and/or YDirection are/is -1 for mirrored, 1 for not mirrored
|
||||
int x, y, tempMiddle, newCX;
|
||||
int newCY = YOffset;
|
||||
int newMX, newMY;
|
||||
|
||||
if (YDirection < 0)
|
||||
newCY += _mapCornerMaxG;
|
||||
|
||||
for (y = 0; y <= _mapCornerMaxG; ++y) {
|
||||
if (newCY < 0)
|
||||
newCY += _totalMapSizeG;
|
||||
else if (newCY >= _totalMapSizeG)
|
||||
newCY -= _totalMapSizeG;
|
||||
|
||||
newCX = XOffset;
|
||||
if (XDirection < 0)
|
||||
newCX += _mapCornerMaxG;
|
||||
|
||||
for (x = 0; x <= _mapCornerMaxG; ++x) {
|
||||
if (newCX < 0)
|
||||
newCX += _totalMapSizeG;
|
||||
else if (newCX >= _totalMapSizeG)
|
||||
newCX -= _totalMapSizeG;
|
||||
|
||||
_mapCorner[newCX][newCY] = _mapCorner[x][y];
|
||||
if ((x != _mapCornerMaxG) && (y != _mapCornerMaxG)) {
|
||||
tempMiddle = _mapMiddle[x][y];
|
||||
newMX = newCX;
|
||||
newMY = newCY;
|
||||
if (YDirection < 0) {
|
||||
newMY--;
|
||||
if (newMY == -1)
|
||||
newMY = _totalMapSizeG - 1;
|
||||
if (tempMiddle == LARGEPOOLTOP)
|
||||
tempMiddle = LARGEPOOLBOTTOM;
|
||||
else if (tempMiddle == LARGEPOOLBOTTOM)
|
||||
tempMiddle = LARGEPOOLTOP;
|
||||
}
|
||||
if (XDirection < 0) {
|
||||
newMX--;
|
||||
if (newMX == -1)
|
||||
newMX = _totalMapSizeG - 1;
|
||||
}
|
||||
_mapMiddle[newMX][newMY] = tempMiddle;
|
||||
}
|
||||
|
||||
newCX += XDirection;
|
||||
}
|
||||
|
||||
newCY += YDirection;
|
||||
}
|
||||
}
|
||||
|
||||
void SpiffGenerator::mirrorMap() {
|
||||
// --------------------------------------------------------------
|
||||
// mirror map
|
||||
// --------------------------------------------------------------
|
||||
|
||||
int swapXa = pickFrom2(-1, 1, 1, _advancedMirrorOK_G);
|
||||
int swapYa = pickFrom2(-1, _advancedMirrorOK_G, 1, 1);
|
||||
int swapXb = pickFrom2(-1, _advancedMirrorOK_G, 1, 1);
|
||||
int swapYb = pickFrom2(-1, 1, 1, _advancedMirrorOK_G);
|
||||
|
||||
switch (_mirrorTypeG) {
|
||||
case NORMALMIRROR: // four quadrants
|
||||
// ABCBA
|
||||
// DEFED
|
||||
// GHIHG
|
||||
// DEFED
|
||||
// ABCBA
|
||||
copyMap(_mapCornerMaxG, 0, swapXa, swapYa);
|
||||
copyMap(0, _mapCornerMaxG, swapXb, swapYb);
|
||||
copyMap(_mapCornerMaxG, _mapCornerMaxG, swapXa * swapXb, swapYa * swapYb);
|
||||
break;
|
||||
case XOFFSETMIRROR: // Like normal, but one half is moved horizontally by 1/4 totalmapsize
|
||||
// ABABABABA
|
||||
// DEFGHGFED
|
||||
// CDCDCDCDC
|
||||
// FGHGFEDEF
|
||||
// ABABABABA
|
||||
if (swapYa == -1) // ensures fairness
|
||||
swapXb = -1;
|
||||
copyMap(_mapCornerMaxG, 0, 1, swapYa);
|
||||
copyMap(_mapCornerMaxG / 2, _mapCornerMaxG, swapXb, swapYb);
|
||||
copyMap(_mapCornerMaxG * 3 / 2, _mapCornerMaxG, swapXb, swapYa * swapYb);
|
||||
break;
|
||||
case YOFFSETMIRROR: // Like normal, but one half is moved vertically by 1/4 totalmapsize
|
||||
if (swapXb == -1) // ensures fairness
|
||||
swapYa = -1;
|
||||
copyMap(_mapCornerMaxG, _mapCornerMaxG / 2, swapXa, swapYa);
|
||||
copyMap(0, _mapCornerMaxG, swapXb, 1);
|
||||
copyMap(_mapCornerMaxG, _mapCornerMaxG * 3 / 2, swapXa * swapXb, swapYa);
|
||||
break;
|
||||
case MAXDISTMIRROR: // Allows maximum distance between starting points
|
||||
default:
|
||||
// ABCDCBA
|
||||
// E*GHIJE
|
||||
// HIJE*GH
|
||||
// DCBABCD
|
||||
// HG*EJIH
|
||||
// EJIHG*E
|
||||
// ABCDCBA
|
||||
|
||||
copyMap(_mapCornerMaxG, 0, 1, -1);
|
||||
copyMap(0, _mapCornerMaxG, -1, 1);
|
||||
copyMap(_mapCornerMaxG, _mapCornerMaxG, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void SpiffGenerator::errorCorrection() {
|
||||
// corrects errors caused by pool placement and mirroring
|
||||
// doesn't correct _mapCorner[x][_totalMapSizeG+1] or _mapCorner[_totalMapSizeG+1][y], since it isn't used
|
||||
|
||||
// for any kElevHigh to kElevLow transitions, makes the kElevHigh kElevMedium
|
||||
// for pools on nonflat terrain, makes the terrain kElevMedium
|
||||
// removes invalid water
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int tempX;
|
||||
int tempY;
|
||||
int dx;
|
||||
int dy;
|
||||
int redo;
|
||||
int elev;
|
||||
|
||||
for (y = 0; y < _totalMapSizeG; ++y) {
|
||||
for (x = 0; x < _totalMapSizeG; ++x) {
|
||||
if (_mapCorner[x][y] == kElevHigh) {
|
||||
for (dy = -1; dy <= 1; ++dy) {
|
||||
tempY = y + dy;
|
||||
if (tempY == _totalMapSizeG) {
|
||||
tempY = 0;
|
||||
} else if (tempY == -1) {
|
||||
tempY = _totalMapSizeG - 1;
|
||||
}
|
||||
|
||||
for (dx = -1; dx <= 1; ++dx) {
|
||||
tempX = x + dx;
|
||||
if (tempX == _totalMapSizeG) {
|
||||
tempX = 0;
|
||||
} else if (tempX == -1) {
|
||||
tempX = _totalMapSizeG - 1;
|
||||
}
|
||||
|
||||
if (_mapCorner[tempX][tempY] == kElevLow) {
|
||||
_mapCorner[x][y] = kElevMedium;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((_mapCorner[x][y] != kElevLow) && (_mapCorner[x][y] != kElevMedium)) {
|
||||
_mapCorner[x][y] = kElevMedium; // should not happen anymore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
redo = 0;
|
||||
for (y = 0; y < _totalMapSizeG; ++y) {
|
||||
for (x = 0; x < _totalMapSizeG; ++x) {
|
||||
if (_mapMiddle[x][y] != UNASSIGNED) {
|
||||
tempY = y + 1;
|
||||
if (tempY == _totalMapSizeG)
|
||||
tempY = 0;
|
||||
|
||||
tempX = x + 1;
|
||||
if (tempX == _totalMapSizeG)
|
||||
tempX = 0;
|
||||
|
||||
elev = _mapCorner[x][y];
|
||||
if ((_mapMiddle[x][y] == WATER) && (elev != kElevLow))
|
||||
_mapMiddle[x][y] = UNASSIGNED;
|
||||
else if ((elev != _mapCorner[x][tempY]) || (elev != _mapCorner[tempX][y]) || (elev != _mapCorner[tempX][tempY])) {
|
||||
if (_mapMiddle[x][y] == WATER)
|
||||
_mapMiddle[x][y] = UNASSIGNED;
|
||||
else {
|
||||
_mapCorner[x][y] = kElevMedium;
|
||||
_mapCorner[x][tempY] = kElevMedium;
|
||||
_mapCorner[tempX][y] = kElevMedium;
|
||||
_mapCorner[tempX][tempY] = kElevMedium;
|
||||
redo = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (redo);
|
||||
}
|
||||
|
||||
void SpiffGenerator::generate() {
|
||||
// --------------------------------------------------------------
|
||||
// initialize
|
||||
// --------------------------------------------------------------
|
||||
int x;
|
||||
int y;
|
||||
int neighbors[MAXELEVVAL];
|
||||
int a;
|
||||
int b;
|
||||
int tempElevation;
|
||||
int nextElevation;
|
||||
int special;
|
||||
|
||||
_mapCornerMaxG = _totalMapSizeG / 2;
|
||||
_mapMiddleMaxG = _mapCornerMaxG - 1;
|
||||
|
||||
for (y = 0; y <= _mapCornerMaxG; ++y) {
|
||||
// initialise map to UNASSIGNED tiles
|
||||
for (x = 0; x <= _mapCornerMaxG; ++x) {
|
||||
_mapCorner[x][y] = UNASSIGNED;
|
||||
_mapMiddle[x][y] = UNASSIGNED;
|
||||
}
|
||||
}
|
||||
if (_advancedMirrorOK_G)
|
||||
_mirrorTypeG = pickFrom4(NORMALMIRROR, 1, XOFFSETMIRROR, 2, YOFFSETMIRROR, 2, MAXDISTMIRROR, 4);
|
||||
else
|
||||
_mirrorTypeG = NORMALMIRROR;
|
||||
getSpecials(); // get start and pools
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// loop through each square
|
||||
// --------------------------------------------------------------
|
||||
_mapCorner[0][0] = pickFrom3(kElevLow, 1, kElevMedium, (_terrainSeedFlagG < 9), kElevHigh, (_terrainSeedFlagG < 8)); // seed
|
||||
// fill in the rest of the random map
|
||||
for (y = 0; y <= _mapCornerMaxG; ++y) {
|
||||
for (x = 0; x <= _mapCornerMaxG; ++x) {
|
||||
special = _mapMiddle[x][y]; // water wouldn't have been assigned yet, so must be pool, start, or UNASSIGNED
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// check neighbors
|
||||
// --------------------------------------------------------------
|
||||
if ((_mapCorner[x][y] != UNASSIGNED) && (_mapCorner[x][y] != LOW_OR_WATER))
|
||||
nextElevation = _mapCorner[x][y]; // already defined because of a special or (0,0), so no change
|
||||
else {
|
||||
neighbors[kElevHigh] = 0;
|
||||
neighbors[kElevMedium] = 0;
|
||||
neighbors[kElevLow] = 0;
|
||||
neighbors[WATER] = 0;
|
||||
|
||||
if (x > 0) {
|
||||
a = _mapCorner[x - 1][y];
|
||||
if ((y > 1) && (_mapMiddle[x - 1][y - 2] == WATER))
|
||||
++neighbors[WATER];
|
||||
if (y > 0)
|
||||
neighbors[_mapCorner[x - 1][y - 1]] += 3;
|
||||
} else {
|
||||
a = _mapCorner[x][y - 1];
|
||||
}
|
||||
|
||||
neighbors[a] += 3;
|
||||
if (y > 0) {
|
||||
b = _mapCorner[x][y - 1];
|
||||
neighbors[b] += 3;
|
||||
if (x < _mapCornerMaxG) {
|
||||
++neighbors[_mapCorner[x + 1][y - 1]]; // so this value can be ignored when choosing water
|
||||
if ((special != UNASSIGNED) && (x < _mapCornerMaxG - 1))
|
||||
++neighbors[_mapCorner[x + 2][y - 1]];
|
||||
}
|
||||
if ((x > 1) && (_mapMiddle[x - 2][y - 1] == WATER))
|
||||
++neighbors[WATER];
|
||||
} else {
|
||||
b = _mapCorner[x - 1][y]; // for probability equations for edges
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// pick new elevation
|
||||
// --------------------------------------------------------------
|
||||
// neighbors possible new elevation
|
||||
// kElevHigh or kElevHigh with kElevMedium kElevHigh or kElevMedium
|
||||
// kElevMedium only kElevHigh, kElevMedium or kElevLow
|
||||
// kElevLow or WATER only kElevMedium, kElevLow or WATER
|
||||
// kElevMedium with kElevLow or WATER kElevMedium or kElevLow, possible WATER if no kElevMedium left, down, or down-left
|
||||
// kElevHigh with kElevLow or WATER kElevMedium
|
||||
|
||||
const int highAmt = 105;
|
||||
const int mediumAmt = 100 + _waterAmountG;
|
||||
const int lowAmt = 105 + 3 * _waterAmountG;
|
||||
const int waterAmt = 15 * _waterAmountG;
|
||||
|
||||
|
||||
|
||||
if (neighbors[kElevLow]) {
|
||||
if (neighbors[kElevHigh]) { // kElevHigh with kElevLow or WATER
|
||||
nextElevation = kElevMedium;
|
||||
} else if (neighbors[kElevMedium] >= 3) { // kElevMedium with kElevLow or WATER
|
||||
if (a != b) {
|
||||
nextElevation = pickFrom2(kElevLow, lowAmt, kElevMedium, mediumAmt);
|
||||
} else if (a == kElevLow) {
|
||||
nextElevation = pickFrom2(kElevLow, 100 * lowAmt, kElevMedium, mediumAmt * _cliffAmountG);
|
||||
} else {
|
||||
nextElevation = pickFrom2(kElevLow, lowAmt * _cliffAmountG, kElevMedium, 100 * mediumAmt);
|
||||
}
|
||||
} else { // kElevLow or WATER only, possibly kElevMedium down-right
|
||||
if (neighbors[WATER] == 1) {
|
||||
nextElevation = pickFrom3(WATER, 100 * waterAmt, kElevLow, 100 * lowAmt, kElevMedium, mediumAmt * _cliffAmountG);
|
||||
} else if (neighbors[WATER] == 0) {
|
||||
nextElevation = pickFrom3(WATER, waterAmt * _cliffAmountG, kElevLow, 100 * lowAmt, kElevMedium, mediumAmt * _cliffAmountG);
|
||||
} else {
|
||||
nextElevation = pickFrom3(WATER, 10000 * waterAmt, kElevLow, lowAmt * 100 * _cliffAmountG, kElevMedium, mediumAmt * _cliffAmountG * _cliffAmountG);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (neighbors[kElevHigh]) { // kElevHigh or kElevHigh with kElevMedium
|
||||
if (a != b) {
|
||||
nextElevation = pickFrom2(kElevMedium, mediumAmt, kElevHigh, highAmt);
|
||||
} else if (a == kElevHigh) {
|
||||
nextElevation = pickFrom2(kElevMedium, mediumAmt * _cliffAmountG, kElevHigh, 100 * highAmt);
|
||||
} else {
|
||||
nextElevation = pickFrom2(kElevMedium, 100 * mediumAmt, kElevHigh, highAmt * _cliffAmountG);
|
||||
}
|
||||
} else {
|
||||
nextElevation = pickFrom3(kElevLow, lowAmt * _cliffAmountG, kElevMedium, 200 * mediumAmt, kElevHigh, highAmt * _cliffAmountG);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// set elevation
|
||||
// --------------------------------------------------------------
|
||||
if ((_mapCorner[x][y] == LOW_OR_WATER) && (nextElevation != WATER)) {
|
||||
// bottom and left edges of a special on kElevLow ground there may only be kElevLow or WATER
|
||||
nextElevation = kElevLow;
|
||||
}
|
||||
|
||||
if (nextElevation == WATER) {
|
||||
if ((x != 0) && (y != 0) && (_mapMiddle[x - 1][y - 1] == UNASSIGNED)) {
|
||||
_mapMiddle[x - 1][y - 1] = WATER; // set WATER
|
||||
}
|
||||
nextElevation = kElevLow;
|
||||
}
|
||||
|
||||
_mapCorner[x][y] = nextElevation; // set elevation
|
||||
|
||||
if (special != UNASSIGNED) { // if special, make flat spot (don't worry about going over map edge, will go into mirrored part)
|
||||
tempElevation = nextElevation;
|
||||
if (tempElevation == kElevLow)
|
||||
tempElevation = LOW_OR_WATER; // allow for water on left and bottom edges
|
||||
_mapCorner[x + 1][y + 1] = nextElevation;
|
||||
_mapCorner[x + 1][y] = tempElevation;
|
||||
_mapCorner[x][y + 1] = tempElevation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_islandsFlagG) { // replace borders with water, errorCorrection() finishes it.
|
||||
int edgeWaterA = (int)(_islandsFlagG * _totalMapSizeG / 16 + 0.5);
|
||||
int edgeWaterB = _mapMiddleMaxG - (int)(_islandsFlagG * _totalMapSizeG / 16);
|
||||
for (y = 0; y <= _mapCornerMaxG; ++y) {
|
||||
for (x = 0; x < edgeWaterA; ++x) {
|
||||
_mapCorner[x][y] = kElevLow;
|
||||
_mapMiddle[x][y] = WATER;
|
||||
}
|
||||
if (_mapCorner[edgeWaterA + 1][y] == kElevHigh)
|
||||
_mapCorner[edgeWaterA][y] = kElevMedium;
|
||||
|
||||
for (x = _mapMiddleMaxG; x > edgeWaterB; --x) {
|
||||
_mapCorner[x + 1][y] = kElevLow;
|
||||
_mapMiddle[x][y] = WATER;
|
||||
}
|
||||
if (_mapCorner[edgeWaterB][y] == kElevHigh) {
|
||||
_mapCorner[edgeWaterB + 1][y] = kElevMedium;
|
||||
}
|
||||
}
|
||||
|
||||
for (x = edgeWaterA; x <= edgeWaterB + 1; ++x) {
|
||||
for (y = 0; y < edgeWaterA; ++y) {
|
||||
_mapCorner[x][y] = kElevLow;
|
||||
_mapMiddle[x][y] = WATER;
|
||||
}
|
||||
if (_mapCorner[x][edgeWaterA + 1] == kElevHigh)
|
||||
_mapCorner[x][edgeWaterA] = kElevMedium;
|
||||
|
||||
for (y = _mapMiddleMaxG; y > edgeWaterB; --y) {
|
||||
_mapCorner[x][y + 1] = kElevLow;
|
||||
_mapMiddle[x][y] = WATER;
|
||||
}
|
||||
if (_mapCorner[x][edgeWaterB] == kElevHigh) {
|
||||
_mapCorner[x][edgeWaterB + 1] = kElevMedium;
|
||||
}
|
||||
}
|
||||
|
||||
if (_islandsFlagG == 2) { // add tiny islands to help bridge wide channels
|
||||
int j;
|
||||
for (int i = 0; i < _totalMapSizeG / 16; ++i) {
|
||||
x = (int)(_totalMapSizeG / 16 - .5);
|
||||
y = spiffRand(x, _totalMapSizeG / 2 - 1 - x);
|
||||
if (spiffRand(0, 1)) {
|
||||
x = _totalMapSizeG / 2 - 1 - x;
|
||||
}
|
||||
if (spiffRand(0, 1)) {
|
||||
_mapMiddle[x][y] = UNASSIGNED;
|
||||
for (j = 0; j < 4; ++j) {
|
||||
_mapMiddle[x + spiffRand(-1, 1)][y + spiffRand(-1, 1)] = UNASSIGNED;
|
||||
}
|
||||
} else {
|
||||
_mapMiddle[y][x] = UNASSIGNED;
|
||||
for (j = 0; j < 4; ++j) {
|
||||
_mapMiddle[y + spiffRand(-1, 1)][x + spiffRand(-1, 1)] = UNASSIGNED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mirrorMap();
|
||||
errorCorrection();
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
100
engines/scumm/he/moonbase/map_spiff.h
Normal file
100
engines/scumm/he/moonbase/map_spiff.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_MAP_SPIFF_H
|
||||
#define SCUMM_HE_MOONBASE_MAP_SPIFF_H
|
||||
|
||||
#ifdef ENABLE_HE
|
||||
|
||||
#include "engines/scumm/he/moonbase/map_mif.h"
|
||||
|
||||
#define MAXELEVVAL 4 // for array size
|
||||
|
||||
// These were "HIGH", "MEDIUM", and "LOW", but
|
||||
// was renamed to prevent potential clashing
|
||||
// with different platforms.
|
||||
#define kElevHigh 3 // elevations
|
||||
#define kElevMedium 2
|
||||
#define kElevLow 1
|
||||
|
||||
#define WATER 0 // special types
|
||||
#define HUB 1
|
||||
#define SMALLPOOL 2
|
||||
#define MEDIUMPOOL 3
|
||||
#define LARGEPOOLTOP 4
|
||||
#define LARGEPOOLBOTTOM 5 // placeholder for top half of a large pool
|
||||
|
||||
#define UNASSIGNED -1
|
||||
#define LOW_OR_WATER -2
|
||||
|
||||
#define MAXSIZE 80
|
||||
|
||||
#define NORMALMIRROR 0
|
||||
#define XOFFSETMIRROR 1
|
||||
#define YOFFSETMIRROR 2
|
||||
#define MAXDISTMIRROR 3
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class SpiffGenerator {
|
||||
public:
|
||||
SpiffGenerator(int seed);
|
||||
~SpiffGenerator() = default;
|
||||
|
||||
MapFile *generateMap(int water, int tileset, int mapSize, int energy, int terrain);
|
||||
|
||||
private:
|
||||
int _seed = 0;
|
||||
|
||||
int _numPoolsG = 0; // per quadrant
|
||||
int _energyAmountG = 0; // 2048 = min energy on small map, 51200 = max energy on max map, etc.
|
||||
int _cliffAmountG = 0; // amount of cliffs, 10 is min, 70 is max
|
||||
int _waterAmountG = 0; // 0 is min, 30 is max
|
||||
int _totalMapSizeG = 0;
|
||||
|
||||
int _terrainSeedFlagG = 0; // disables kElevHigh or kElevLow terrain for the initial elevation when appropriate
|
||||
int _islandsFlagG = 0; // enables islands
|
||||
int _advancedMirrorOK_G = 0; // low terrain roughness can leave too abrupt changes at the edge, so set false to disable some mirroring types
|
||||
int _mirrorTypeG = 0; // what mirroring is used
|
||||
|
||||
int _mapCornerMaxG = 0; // size of random section
|
||||
int _mapMiddleMaxG = 0;
|
||||
int _mapCorner[MAXSIZE+1][MAXSIZE+1] = { {}, {} };
|
||||
int _mapMiddle[MAXSIZE][MAXSIZE] = { {}, {} };
|
||||
|
||||
float getRandomFloat();
|
||||
int spiffRand(int min, int max);
|
||||
int pickFrom2(int a, int probA, int b, int probB);
|
||||
int pickFrom3(int a, int probA, int b, int probB, int c, int probC);
|
||||
int pickFrom4(int a, int probA, int b, int probB, int c, int probC, int d, int probD);
|
||||
|
||||
void getSpecials();
|
||||
void copyMap(int XOffset, int YOffset, int XDirection, int YDirection);
|
||||
void mirrorMap();
|
||||
void errorCorrection();
|
||||
void generate();
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif // ENABLE_HE
|
||||
|
||||
#endif // SCUMM_HE_MOONBASE_MAP_SPIFF_H
|
||||
85
engines/scumm/he/moonbase/moonbase.cpp
Normal file
85
engines/scumm/he/moonbase/moonbase.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/formats/winexe_pe.h"
|
||||
|
||||
#include "scumm/he/intern_he.h"
|
||||
#include "scumm/he/moonbase/moonbase.h"
|
||||
#include "scumm/he/moonbase/ai_main.h"
|
||||
#include "scumm/he/moonbase/map_main.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
Moonbase::Moonbase(ScummEngine_v100he *vm) : _vm(vm) {
|
||||
_exe = new Common::PEResources();
|
||||
|
||||
initFOW();
|
||||
|
||||
_ai = new AI(_vm);
|
||||
_map = new Map(_vm);
|
||||
}
|
||||
|
||||
Moonbase::~Moonbase() {
|
||||
delete _exe;
|
||||
delete _ai;
|
||||
delete _map;
|
||||
}
|
||||
|
||||
int Moonbase::readFromArray(int array, int y, int x) {
|
||||
_vm->VAR(_vm->VAR_U32_RESERVED) = array;
|
||||
|
||||
return _vm->readArray(_vm->VAR_U32_RESERVED, y, x);
|
||||
}
|
||||
|
||||
void Moonbase::deallocateArray(int array) {
|
||||
_vm->VAR(_vm->VAR_U32_RESERVED) = array;
|
||||
|
||||
return _vm->nukeArray(_vm->VAR_U32_RESERVED);
|
||||
}
|
||||
|
||||
int Moonbase::callScummFunction(int scriptNumber, int paramCount,...) {
|
||||
va_list va_params;
|
||||
va_start(va_params, paramCount);
|
||||
int args[25];
|
||||
|
||||
memset(args, 0, sizeof(args));
|
||||
|
||||
Common::String str;
|
||||
str = Common::String::format("Moonbase::callScummFunction(%d, [", scriptNumber);
|
||||
|
||||
for (int i = 0; i < paramCount; i++) {
|
||||
args[i] = va_arg(va_params, int);
|
||||
|
||||
str += Common::String::format("%d ", args[i]);
|
||||
}
|
||||
str += "])";
|
||||
|
||||
debug(3, "%s", str.c_str());
|
||||
|
||||
|
||||
va_end(va_params);
|
||||
|
||||
_vm->runScript(scriptNumber, 0, 1, args);
|
||||
|
||||
return _vm->pop();
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
111
engines/scumm/he/moonbase/moonbase.h
Normal file
111
engines/scumm/he/moonbase/moonbase.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCUMM_HE_MOONBASE_MOONBASE_H
|
||||
#define SCUMM_HE_MOONBASE_MOONBASE_H
|
||||
|
||||
#ifdef ENABLE_HE
|
||||
|
||||
namespace Common {
|
||||
class PEResources;
|
||||
}
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class AI;
|
||||
class Map;
|
||||
|
||||
class Moonbase {
|
||||
public:
|
||||
Moonbase(ScummEngine_v100he *vm);
|
||||
~Moonbase();
|
||||
|
||||
int readFromArray(int array, int y, int x);
|
||||
void deallocateArray(int array);
|
||||
int callScummFunction(int scriptNumber, int paramCount,...);
|
||||
|
||||
// FOW Stuff
|
||||
bool isFOW(int resNum, int state, uint32 conditionBits) {
|
||||
return resNum == _fowSentinelImage && state == _fowSentinelState && conditionBits == _fowSentinelConditionBits;
|
||||
}
|
||||
|
||||
void initFOW();
|
||||
void releaseFOWResources();
|
||||
|
||||
bool setFOWImage(int id);
|
||||
|
||||
void setFOWInfo(int fowInfoArray, int downDim, int acrossDim, int viewX, int viewY, int clipX1,
|
||||
int clipY1, int clipX2, int clipY2, int technique, int nFrame);
|
||||
|
||||
|
||||
void renderFOW(WizMultiTypeBitmap *destSurface);
|
||||
|
||||
private:
|
||||
int readFOWVisibilityArray(int array, int y, int x);
|
||||
void renderFOWState(WizMultiTypeBitmap *destSurface, int x, int y, int state);
|
||||
|
||||
public:
|
||||
int _fowSentinelImage;
|
||||
int _fowSentinelState;
|
||||
uint32 _fowSentinelConditionBits;
|
||||
|
||||
AI *_ai;
|
||||
Map *_map;
|
||||
|
||||
private:
|
||||
ScummEngine_v100he *_vm;
|
||||
|
||||
int _fowFrameBaseNumber;
|
||||
int _fowAnimationFrames;
|
||||
int _fowCurrentFOWFrame;
|
||||
|
||||
int32 _fowTileW;
|
||||
int32 _fowTileH;
|
||||
|
||||
uint8 *_fowImage;
|
||||
int _fowClipX1;
|
||||
int _fowClipY1;
|
||||
int _fowClipX2;
|
||||
int _fowClipY2;
|
||||
|
||||
int _fowDrawX;
|
||||
int _fowDrawY;
|
||||
|
||||
int _fowVtx1;
|
||||
int _fowVty1;
|
||||
int _fowMvx;
|
||||
int _fowMvy;
|
||||
int _fowVw;
|
||||
int _fowVh;
|
||||
|
||||
bool _fowBlackMode;
|
||||
|
||||
int32 _fowRenderTable[32768];
|
||||
|
||||
Common::PEResources *_exe;
|
||||
Common::Path _fileName;
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif // ENABLE_HE
|
||||
|
||||
#endif // SCUMM_HE_MOONBASE_H
|
||||
440
engines/scumm/he/moonbase/moonbase_fow.cpp
Normal file
440
engines/scumm/he/moonbase/moonbase_fow.cpp
Normal file
@@ -0,0 +1,440 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/formats/winexe_pe.h"
|
||||
|
||||
#include "scumm/he/intern_he.h"
|
||||
#include "scumm/he/moonbase/moonbase.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
#define FOW_ANIM_FRAME_COUNT 38
|
||||
|
||||
void Moonbase::initFOW() {
|
||||
_fowSentinelImage = -1;
|
||||
_fowSentinelState = -1;
|
||||
_fowSentinelConditionBits = 0;
|
||||
|
||||
_fowFrameBaseNumber = 0;
|
||||
_fowAnimationFrames = 1;
|
||||
_fowCurrentFOWFrame = 0;
|
||||
|
||||
_fowTileW = 0;
|
||||
_fowTileH = 0;
|
||||
|
||||
_fowImage = nullptr;
|
||||
_fowClipX1 = 0;
|
||||
_fowClipY1 = 0;
|
||||
_fowClipX2 = 0;
|
||||
_fowClipY2 = 0;
|
||||
|
||||
_fowDrawX = 0;
|
||||
_fowDrawY = 0;
|
||||
|
||||
_fowVtx1 = 0;
|
||||
_fowVty1 = 0;
|
||||
_fowMvx = 0;
|
||||
_fowMvy = 0;
|
||||
_fowVw = 0;
|
||||
_fowVh = 0;
|
||||
|
||||
_fowBlackMode = true;
|
||||
|
||||
memset(_fowRenderTable, 0, sizeof(_fowRenderTable));
|
||||
}
|
||||
|
||||
void Moonbase::releaseFOWResources() {
|
||||
if (_fowImage) {
|
||||
free(_fowImage);
|
||||
_fowImage = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Moonbase::setFOWImage(int image) {
|
||||
releaseFOWResources();
|
||||
|
||||
if (!_fowImage) {
|
||||
Common::String fowImageFilename(ConfMan.get("MOONX_FOWImageFilename").c_str());
|
||||
|
||||
#if 0 // TODO
|
||||
if (!fowImageFilename.empty()) {
|
||||
void *wiz = loadWizFromFilename(fowImageFilename);
|
||||
|
||||
if (wiz) {
|
||||
captureFOWImageFromLocation(wiz, file.size());
|
||||
free(wiz);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!_fowImage && image < 0) {
|
||||
int resId;
|
||||
|
||||
// PIECES BUBBLES CIRCLES SIMPLE* WEDGEY BUBBLE2
|
||||
// WEDGE2 SPIKEY ANGLES SMOOTHED WUZZY SYS7-BEVELED
|
||||
if (image >= -12 && image <= -1)
|
||||
resId = 210 - image; // 211-222 range
|
||||
else
|
||||
resId = 214; // default, SIMPLE
|
||||
|
||||
if (_fileName.empty()) { // We are running for the first time
|
||||
_fileName = _vm->generateFilename(-3);
|
||||
|
||||
if (!_exe->loadFromEXE(_fileName))
|
||||
error("Cannot open file %s", _fileName.toString(Common::Path::kNativeSeparator).c_str());
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *stream = _exe->getResource(Common::kWinRCData, resId);
|
||||
|
||||
if (stream->size()) {
|
||||
_fowImage = (uint8 *)malloc(stream->size());
|
||||
|
||||
stream->read(_fowImage, stream->size());
|
||||
}
|
||||
|
||||
delete stream;
|
||||
}
|
||||
|
||||
if (!_fowImage && image > 0) {
|
||||
int sz = _vm->getResourceSize(rtImage, image);
|
||||
_fowImage = (uint8 *)malloc(sz);
|
||||
|
||||
// We have to copy it, otherwise the resource manager
|
||||
// will kill it earlier or later. Matches original.
|
||||
memcpy(_fowImage, _vm->getResourceAddress(rtImage, image), sz);
|
||||
}
|
||||
|
||||
if (!_fowImage)
|
||||
return false;
|
||||
}
|
||||
|
||||
int nStates = _vm->_wiz->getWizImageStates(_fowImage);
|
||||
|
||||
if (nStates > FOW_ANIM_FRAME_COUNT) {
|
||||
releaseFOWResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
_fowAnimationFrames = (nStates + FOW_ANIM_FRAME_COUNT - 1) / FOW_ANIM_FRAME_COUNT;
|
||||
|
||||
_vm->_wiz->getWizImageDim(_fowImage, (nStates - 1), _fowTileW, _fowTileH);
|
||||
|
||||
bool sizeIndicatorWasBlack = true;
|
||||
int32 hitTestValue = 0;
|
||||
int32 pixelValue = 0;
|
||||
|
||||
_vm->_wiz->moonbaseLayeredWizHitTest(
|
||||
&hitTestValue, &pixelValue, _fowImage, (nStates - 1), 0, 0, 0, 0);
|
||||
|
||||
sizeIndicatorWasBlack = (pixelValue == 0);
|
||||
|
||||
if (ConfMan.hasKey("EnableFOWRects"))
|
||||
_fowBlackMode = (ConfMan.getInt("EnableFOWRects") == 1);
|
||||
else
|
||||
_fowBlackMode = sizeIndicatorWasBlack;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum FOWElement {
|
||||
FOW_EMPTY = 0,
|
||||
FOW_SOLID = 1,
|
||||
|
||||
FF_L = 0x01,
|
||||
FF_R = 0x02,
|
||||
FF_T = 0x04,
|
||||
FF_B = 0x08,
|
||||
FF_T_L = 0x10,
|
||||
FF_T_R = 0x20,
|
||||
FF_B_L = 0x40,
|
||||
FF_B_R = 0x80,
|
||||
FF_Q_A = (FF_L | FF_T | FF_T_L),
|
||||
FF_Q_B = (FF_R | FF_T | FF_T_R),
|
||||
FF_Q_C = (FF_L | FF_B | FF_B_L),
|
||||
FF_Q_D = (FF_R | FF_B | FF_B_R)
|
||||
};
|
||||
|
||||
int Moonbase::readFOWVisibilityArray(int array, int y, int x) {
|
||||
if (readFromArray(array, x, y) > 0)
|
||||
return FOW_EMPTY;
|
||||
|
||||
return FOW_SOLID;
|
||||
}
|
||||
|
||||
void Moonbase::setFOWInfo(int fowInfoArray, int downDim, int acrossDim, int viewX, int viewY, int clipX1,
|
||||
int clipY1, int clipX2, int clipY2, int technique, int nFrame) {
|
||||
if (!_fowImage)
|
||||
return;
|
||||
|
||||
memset(_fowRenderTable, 0, sizeof(_fowRenderTable));
|
||||
|
||||
_fowDrawX = clipX1;
|
||||
_fowDrawY = clipY1;
|
||||
|
||||
_fowClipX1 = clipX1;
|
||||
_fowClipY1 = clipY1;
|
||||
_fowClipX2 = clipX2;
|
||||
_fowClipY2 = clipY2;
|
||||
|
||||
// Figure out the number of tiles are involved
|
||||
int view_W = (clipX2 - clipX1) + 1;
|
||||
int view_H = (clipY2 - clipY1) + 1;
|
||||
|
||||
int tw = _fowTileW;
|
||||
int th = _fowTileH;
|
||||
|
||||
int dw = acrossDim;
|
||||
int dh = downDim;
|
||||
|
||||
int dlw = dw * tw;
|
||||
int dlh = dh * th;
|
||||
|
||||
_fowMvx = (0 <= viewX) ? (viewX % dlw) : (dlw - (-viewX % dlw));
|
||||
_fowMvy = (0 <= viewY) ? (viewY % dlh) : (dlh - (-viewY % dlh));
|
||||
|
||||
_fowVtx1 = _fowMvx / tw;
|
||||
_fowVty1 = _fowMvy / th;
|
||||
|
||||
_fowVw = (((_fowMvx + view_W + tw - 1) / tw) - _fowVtx1) + 1;
|
||||
_fowVh = (((_fowMvy + view_H + th - 1) / th) - _fowVty1) + 1;
|
||||
|
||||
// Build the connectivity table
|
||||
int t = (_fowVty1 - 1); if (t >= dh) { t = 0; } else if (t < 0) { t = (dh - 1); }
|
||||
int m = (_fowVty1 + 0); if (m >= dh) { m = 0; } else if (m < 0) { m = (dh - 1); }
|
||||
int b = (_fowVty1 + 1); if (b >= dh) { b = 0; } else if (b < 0) { b = (dh - 1); }
|
||||
|
||||
int il = (_fowVtx1 - 1); if (il >= dh) { il = 0; } else if (il < 0) { il = (dw - 1); }
|
||||
int ic = (_fowVtx1 + 0); if (ic >= dh) { ic = 0; } else if (ic < 0) { ic = (dw - 1); }
|
||||
int ir = (_fowVtx1 + 1); if (ir >= dh) { ir = 0; } else if (ir < 0) { ir = (dw - 1); }
|
||||
|
||||
int dataOffset = (_fowVw * 3);
|
||||
int dataOffset2 = (dataOffset * 2);
|
||||
int32 *pOutterRenderTableA = _fowRenderTable;
|
||||
int32 *pOutterRenderTableB = pOutterRenderTableA + dataOffset;
|
||||
|
||||
for (int ay = 0; ay < _fowVh; ay++) {
|
||||
int l = il;
|
||||
int c = ic;
|
||||
int r = ir;
|
||||
|
||||
int32 *pRenderTableA = pOutterRenderTableA;
|
||||
int32 *pRenderTableB = pOutterRenderTableB;
|
||||
|
||||
pOutterRenderTableA += dataOffset2;
|
||||
pOutterRenderTableB += dataOffset2;
|
||||
|
||||
for (int ax = 0; ax < _fowVw; ax++) {
|
||||
int visibility = readFOWVisibilityArray(fowInfoArray, m, c);
|
||||
|
||||
if (visibility == FOW_EMPTY) {
|
||||
uint32 bits = 0;
|
||||
|
||||
if (readFOWVisibilityArray(fowInfoArray, t, l) != 0) bits |= FF_T_L;
|
||||
if (readFOWVisibilityArray(fowInfoArray, t, c) != 0) bits |= FF_T;
|
||||
if (readFOWVisibilityArray(fowInfoArray, t, r) != 0) bits |= FF_T_R;
|
||||
if (readFOWVisibilityArray(fowInfoArray, m, l) != 0) bits |= FF_L;
|
||||
if (readFOWVisibilityArray(fowInfoArray, m, r) != 0) bits |= FF_R;
|
||||
if (readFOWVisibilityArray(fowInfoArray, b, l) != 0) bits |= FF_B_L;
|
||||
if (readFOWVisibilityArray(fowInfoArray, b, c) != 0) bits |= FF_B;
|
||||
if (readFOWVisibilityArray(fowInfoArray, b, r) != 0) bits |= FF_B_R;
|
||||
|
||||
if (bits) {
|
||||
*pRenderTableA++ = 1;
|
||||
*pRenderTableB++ = 1;
|
||||
|
||||
// Quadrant (A)
|
||||
if (bits & FF_Q_A) {
|
||||
*pRenderTableA++ = (
|
||||
((FF_L & bits) ? 1 : 0) |
|
||||
((FF_T & bits) ? 2 : 0) |
|
||||
((FF_T_L & bits) ? 4 : 0)
|
||||
) + 0;
|
||||
} else {
|
||||
*pRenderTableA++ = 0;
|
||||
}
|
||||
|
||||
// Quadrant (B)
|
||||
if (bits & FF_Q_B) {
|
||||
*pRenderTableA++ = (
|
||||
((FF_R & bits) ? 1 : 0) |
|
||||
((FF_T & bits) ? 2 : 0) |
|
||||
((FF_T_R & bits) ? 4 : 0)
|
||||
) + 8;
|
||||
} else {
|
||||
*pRenderTableA++ = 0;
|
||||
}
|
||||
|
||||
// Quadrant (C)
|
||||
if (bits & FF_Q_C) {
|
||||
*pRenderTableB++ = (
|
||||
((FF_L & bits) ? 1 : 0) |
|
||||
((FF_B & bits) ? 2 : 0) |
|
||||
((FF_B_L & bits) ? 4 : 0)
|
||||
) + 16;
|
||||
} else {
|
||||
*pRenderTableB++ = 0;
|
||||
}
|
||||
|
||||
// Quadrant (D)
|
||||
if (bits & FF_Q_D) {
|
||||
*pRenderTableB++ = (
|
||||
((FF_R & bits) ? 1 : 0) |
|
||||
((FF_B & bits) ? 2 : 0) |
|
||||
((FF_B_R & bits) ? 4 : 0)
|
||||
) + 24;
|
||||
} else {
|
||||
*pRenderTableB++ = 0;
|
||||
}
|
||||
} else {
|
||||
*pRenderTableA++ = 0;
|
||||
*pRenderTableB++ = 0;
|
||||
}
|
||||
} else {
|
||||
if (_fowBlackMode) {
|
||||
*pRenderTableA++ = 2;
|
||||
*pRenderTableB++ = 2;
|
||||
} else {
|
||||
*pRenderTableA++ = 1;
|
||||
*pRenderTableA++ = 33;
|
||||
*pRenderTableA++ = 34;
|
||||
|
||||
*pRenderTableB++ = 1;
|
||||
*pRenderTableB++ = 35;
|
||||
*pRenderTableB++ = 36;
|
||||
}
|
||||
}
|
||||
|
||||
if (++l >= dw) { l = 0; }
|
||||
if (++c >= dw) { c = 0; }
|
||||
if (++r >= dw) { r = 0; }
|
||||
}
|
||||
|
||||
if (++t >= dh) { t = 0; }
|
||||
if (++m >= dh) { m = 0; }
|
||||
if (++b >= dh) { b = 0; }
|
||||
}
|
||||
|
||||
_fowCurrentFOWFrame = (nFrame >= 0) ? (nFrame % _fowAnimationFrames) : ((-nFrame) % _fowAnimationFrames);
|
||||
_fowFrameBaseNumber = (_fowCurrentFOWFrame * FOW_ANIM_FRAME_COUNT);
|
||||
}
|
||||
|
||||
void Moonbase::renderFOWState(WizMultiTypeBitmap *destSurface,int x, int y, int state) {
|
||||
int32 spotx, spoty;
|
||||
|
||||
_vm->_wiz->getWizImageSpot(_fowImage, state, spotx, spoty);
|
||||
|
||||
_vm->_wiz->drawMoonbaseLayeredWiz(
|
||||
destSurface->data,
|
||||
destSurface->width, destSurface->height,
|
||||
destSurface->stride, destSurface->format, destSurface->bpp,
|
||||
_fowImage, x - spotx, y - spoty, state,
|
||||
_fowClipX1, _fowClipY1, _fowClipX2, _fowClipY2,
|
||||
0, 0, nullptr, nullptr);
|
||||
}
|
||||
|
||||
static void blackRect_16bpp(WizMultiTypeBitmap *destSurface, int x1, int y1, int x2, int y2) {
|
||||
byte *dst = destSurface->data + (destSurface->stride * y1) + (x1 * sizeof(WizRawPixel16));
|
||||
int h = (y2 - y1) + 1;
|
||||
int writeBytes = ((x2 - x1) + 1) * sizeof(WizRawPixel16);
|
||||
|
||||
while (--h >= 0) {
|
||||
memset(dst, 0, writeBytes);
|
||||
dst += destSurface->stride;
|
||||
}
|
||||
}
|
||||
|
||||
void Moonbase::renderFOW(WizMultiTypeBitmap *destSurface) {
|
||||
if (!_fowImage)
|
||||
return;
|
||||
|
||||
const int32 *outerRenderTable = _fowRenderTable;
|
||||
int ixPos = ((_fowVtx1 * _fowTileW) - _fowMvx) + _fowDrawX;
|
||||
int yPos = ((_fowVty1 * _fowTileH) - _fowMvy) + _fowDrawY;
|
||||
int dataOffset = _fowVw * 3;
|
||||
int halfTileHeight = _fowTileH / 2;
|
||||
int cx2 = MIN<int>(_fowClipX2, (int)(destSurface->width - 1));
|
||||
int cy2 = MIN<int>(_fowClipY2, (int)(destSurface->height - 1));
|
||||
|
||||
for (int ry = 0; ry < _fowVh; ry++) {
|
||||
int realYPos = yPos;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
const int32 *renderTable = outerRenderTable;
|
||||
outerRenderTable += dataOffset;
|
||||
|
||||
int xPos = ixPos;
|
||||
|
||||
for (int rx = 0; rx < _fowVw; rx++) {
|
||||
int state = *renderTable++;
|
||||
|
||||
if (state != 0) {
|
||||
if (state == 2) {
|
||||
int countLeft = (_fowVw - rx);
|
||||
int count = 0;
|
||||
|
||||
for (; count < countLeft; count++) {
|
||||
if (*(renderTable + count) != 2)
|
||||
break;
|
||||
|
||||
renderTable++;
|
||||
rx++;
|
||||
}
|
||||
count++;
|
||||
|
||||
int x1 = xPos;
|
||||
int y1 = realYPos;
|
||||
|
||||
xPos += _fowTileW * count;
|
||||
int x2 = (xPos - 1);
|
||||
int y2 = ((y1 + halfTileHeight) - 1);
|
||||
|
||||
x1 = MAX(0, x1);
|
||||
y1 = MAX(0, y1);
|
||||
x2 = MIN(x2, cx2);
|
||||
y2 = MIN(y2, cy2);
|
||||
|
||||
if ((x2 >= x1) && (y2 >= y1) && (x1 <= _fowClipX2) && (y1 <= _fowClipY2))
|
||||
blackRect_16bpp(destSurface, x1, y1, x2, y2);
|
||||
} else {
|
||||
int subState;
|
||||
|
||||
if ((subState = *renderTable++) != 0)
|
||||
renderFOWState(destSurface, xPos, yPos, (subState + _fowFrameBaseNumber));
|
||||
|
||||
if ((subState = *renderTable++) != 0)
|
||||
renderFOWState(destSurface, xPos, yPos, (subState + _fowFrameBaseNumber));
|
||||
|
||||
xPos += _fowTileW;
|
||||
}
|
||||
} else {
|
||||
xPos += _fowTileW;
|
||||
}
|
||||
}
|
||||
|
||||
realYPos += halfTileHeight;
|
||||
}
|
||||
|
||||
yPos += _fowTileH;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
1285
engines/scumm/he/moonbase/moonbase_gfx.cpp
Normal file
1285
engines/scumm/he/moonbase/moonbase_gfx.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user