Files
aliendefender/map.cpp
2011-08-20 07:34:19 +04:00

383 lines
8.4 KiB
C++

#include "map.h"
Map::Map(QByteArray data, QSize size, QString name, int maxPlayers, int image, QObject *parent) :
QObject(parent)
{
QByteArray ba = QByteArray::fromBase64(data);
ba = qUncompress(ba);
QDataStream s(ba);
mapName = name;
s >> Cells;
int chei;
if (Cells.size() <= 0)
qFatal("Map has invalid width");
if (Cells.size() != size.width())
qCritical("Map has wrong width");
mapSize.setWidth(Cells.size());
chei = Cells.at(0).size();
for (int i=0; i<Cells.size(); i++)
{
if (Cells[i].size() <= 0)
qFatal("Map has invalid height");
if (Cells[i].size() != size.height())
{
qCritical("Map has wrong height");
if (Cells[i].size() != chei)
qFatal("Corrupted map data");
}
for (int j=0; j<Cells[i].size(); j++)
{
if (Cells[i][j]==Start) Starts.push_back(QPoint(i,j));
if (Cells[i][j]==Finish) Finishs.push_back(QPoint(i,j));
}
}
mapSize.setHeight(chei);
if (Starts.isEmpty() || Finishs.isEmpty()) qFatal("invalid map, not found start/finish");
// TODO: check for maxPlayers
players = maxPlayers;
imageType = image;
}
void Map::printMap()
{
for (int i=0; i<Cells.size(); i++) qDebug()<<Cells.at(i);
}
void Map::removeAliensPath()
{
for (int i=0; i<Cells.size(); i++)
{
for (int j=0; j<Cells[i].size(); j++)
{
if (Cells[i][j] > 1000 && Cells[i][j] < 2000) Cells[i][j]=Cells[i][j]-1000;
}
}
}
void Map::delTowerOnMap(int playerId, QPoint pos)
{
Cells[pos.x()][pos.y()]=Player+playerId;
Cells[pos.x()-1][pos.y()]=Player+playerId;
Cells[pos.x()][pos.y()-1]=Player+playerId;
Cells[pos.x()-1][pos.y()-1]=Player+playerId;
emit recreateAlienPath(new bool());
}
bool Map::isReachable(int playerId, QPoint pos)
{
Cells[pos.x()][pos.y()]=PlayerTower-Player-playerId;
Cells[pos.x()-1][pos.y()]=PlayerTower-Player-playerId;
Cells[pos.x()][pos.y()-1]=PlayerTower-Player-playerId;
Cells[pos.x()-1][pos.y()-1]=PlayerTower-Player-playerId;
for (int i=0; i<Starts.size(); i++) {
for (int j=0; j<Finishs.size(); j++) {
if (waveTrace(Starts.at(i),Finishs.at(j))<0) {
Cells[pos.x()][pos.y()]=Player+playerId;
Cells[pos.x()-1][pos.y()]=Player+playerId;
Cells[pos.x()][pos.y()-1]=Player+playerId;
Cells[pos.x()-1][pos.y()-1]=Player+playerId;
return false;
}
}
}
return true;
}
bool Map::addTowerOnMap(int playerId, QPoint pos)
{
if (playerId < 0 || playerId > players) return false;
QRect r(QPoint(),mapSize);
if (!r.contains(pos) ||
!r.contains(pos-QPoint(1,0)) ||
!r.contains(pos-QPoint(0,1)) ||
!r.contains(pos-QPoint(1,1))) return false;
if (Cells[pos.x()][pos.y()]==Player+playerId &&
Cells[pos.x()-1][pos.y()]==Player+playerId &&
Cells[pos.x()][pos.y()-1]==Player+playerId &&
Cells[pos.x()-1][pos.y()-1]==Player+playerId)
return isReachable(playerId,pos);
if ((Cells[pos.x()][pos.y()]==AlienPath+Player+playerId || Cells[pos.x()][pos.y()]==Player+playerId) &&
(Cells[pos.x()-1][pos.y()]==AlienPath+Player+playerId || Cells[pos.x()-1][pos.y()]==Player+playerId) &&
(Cells[pos.x()][pos.y()-1]==AlienPath+Player+playerId || Cells[pos.x()][pos.y()-1]==Player+playerId) &&
(Cells[pos.x()-1][pos.y()-1]==AlienPath+Player+playerId || Cells[pos.x()-1][pos.y()-1]==Player+playerId))
{
if (!isReachable(playerId,pos)) return false;
bool * pathOK;
pathOK = new bool(true);
emit recreateAlienPath(pathOK);
qDebug() << *pathOK;
if (*pathOK)
return true;
else
delTowerOnMap(playerId,pos);
}
qDebug()<<"Dont buid here" << pos;
return false;
}
QVector<QPointF> Map::createPath(QPoint start, QPoint finish)
{
QPointF tp;
QVector<QPoint> srcPath;
QVector<QPointF> tmpPath;
QVector<QPointF> path;
if (Cells[start.x()][start.y()] < 0)
{
qDebug("ERROR invalid start");
return path;
}
if (Cells[finish.x()][finish.y()] < 0)
{
qDebug("ERROR invalid finish");
return path;
}
srcPath = invWaveTrace(finish,waveTrace(start,finish));
for (int i=0; i<srcPath.size();i++)
{
int x = Cells.at(srcPath.at(i).x()).at(srcPath.at(i).y());
if (x > 0 && x < 1000) x = x+1000;
Cells[srcPath.at(i).x()][srcPath.at(i).y()] = x;
tmpPath.push_back(QPointF(srcPath.at(i)));
}
srcPath.clear();
if (!tmpPath.isEmpty())
{
for (int j=0; j<4; j++)
{
path.clear();
tp = tmpPath.at(0);
path.push_back(tp);
for (int i = 0; i < tmpPath.size() - 1; i++)
{
tp.setX((tmpPath.at(i).x() + tmpPath.at(i + 1).x()) / 2.0);
tp.setY((tmpPath.at(i).y() + tmpPath.at(i + 1).y()) / 2.0);
path.push_back(tp);
}
tp = tmpPath.at(tmpPath.size() - 1);
path.push_back(tp);
tmpPath = path;
}
tmpPath.clear();
if (path.size() >= 6)
{
path.remove(1);
path.remove(1);
path.remove(path.size()-2);
path.remove(path.size()-2);
}
return path;
}
path.clear();
return path;
}
int Map::waveTrace(QPoint start, QPoint finish)
{
bool stop = false;
int step = 2;
QPoint cp, tp;
QRect fr(QPoint(), mapSize);
QVector<QPoint> tmpp, curp;
TmpCells << Cells;
for (int i = 0; i < Cells.size(); i++)
{
for (int j = 0; j < Cells.at(i).size(); j++)
{
if (Cells[i][j] < 0 ) TmpCells[i][j] = -1;
else TmpCells[i][j] = 0;
}
}
cp = start;
curp.push_back(cp);
TmpCells[cp.x()][cp.y()] = 1;
//qDebug() << "trace";
while (!stop) {
tmpp = curp;
curp.clear();
stop = true;
for (int i = 0; i < tmpp.size(); i++) {
cp = tmpp.at(i);
if (cp == finish) {
TmpCells[cp.x()][cp.y()] = step;
//qDebug() << "trace done!";
return step;
}
tp.setX(cp.x() - 1);
tp.setY(cp.y());
if (fr.contains(tp)) {
if (TmpCells[tp.x()][tp.y()] == 0) {
TmpCells[tp.x()][tp.y()] = step;
curp.push_back(tp);
stop = false;
}
}
tp.setX(cp.x() + 1);
if (fr.contains(tp)) {
if (TmpCells[tp.x()][tp.y()] == 0) {
TmpCells[tp.x()][tp.y()] = step;
curp.push_back(tp);
stop = false;
}
}
tp.setX(cp.x());
tp.setY(cp.y() - 1);
if (fr.contains(tp)) {
if (TmpCells[tp.x()][tp.y()] == 0) {
TmpCells[tp.x()][tp.y()] = step;
curp.push_back(tp);
stop = false;
}
}
tp.setY(cp.y() + 1);
if (fr.contains(tp)) {
if (TmpCells[tp.x()][tp.y()] == 0) {
TmpCells[tp.x()][tp.y()] = step;
curp.push_back(tp);
stop = false;
}
}
}
step++;
}
qDebug() << "trace false";
return -1;
}
QVector<QPoint> Map::invWaveTrace(QPoint finish, int cnt)
{
QPoint wp, Ppnt;
QVector<QPoint> alpath;
if (cnt < 2) return alpath;
int Ind, c, xpp, ypp, xnn, ynn;
unsigned char chk;
Ppnt = wp = finish;
xnn=0;
xpp=0;
ynn=0;
ypp=0;
cnt--;
alpath.push_front(Ppnt);
while (cnt > 1)
{
cnt--;
chk = 0;
Ind = 0;
c = 0;
if (wp.x() - 1 >= 0 && TmpCells[wp.x()-1][wp.y()] == cnt)
{
chk = chk | 0x01;
c++;
}
if (wp.x() + 1 < mapSize.width() && TmpCells[wp.x()+1][wp.y()] == cnt)
{
chk = chk | 0x02;
c++;
}
if (wp.y() - 1 >= 0 && TmpCells[wp.x()][wp.y()-1] == cnt)
{
chk = chk | 0x04;
c++;
}
if (wp.y() + 1 < mapSize.height() && TmpCells[wp.x()][wp.y()+1] == cnt)
{
chk = chk | 0x08;
c++;
}
if (c == 0 || chk == 0) qDebug("ERROR in InvWaveTrace"),exit(-1);
if (c > 1)
{
if ((chk & 0x01)==0x01 && (chk & 0x04)==0x04)
{
if (xnn <= ynn && Ind == 0){
wp.rx()--;
xnn++;
if (xnn == ynn) xnn++;
Ind = 1;
} else if (Ind == 0) {
wp.ry()--;
ynn++;
ynn++;
Ind = 1;
}
}
if ((chk & 0x02)==0x02 && (chk & 0x04)==0x04)
{
if (xpp <= ynn && Ind == 0){
wp.rx()++;
xpp++;
if (xpp == ynn) xpp++;
Ind = 1;
} else if (Ind == 0) {
wp.ry()--;
ynn++;
ynn++;
Ind = 1;
}
}
if ((chk & 0x01)==0x01 && (chk & 0x08)==0x08)
{
if (xnn <= ypp && Ind == 0){
wp.rx()--;
xnn++;
if (xnn == ypp) xnn++;
Ind = 1;
} else if (Ind == 0) {
wp.ry()++;
ypp++;
ypp++;
Ind = 1;
}
}
if ((chk & 0x02)==0x02 && (chk & 0x08)==0x08)
{
if (xpp <= ypp && Ind == 0){
wp.rx()++;
xpp++;
if (xpp == ypp) xpp++;
Ind = 1;
} else if (Ind == 0) {
wp.ry()++;
ypp++;
ypp++;
Ind = 1;
}
}
}
if (c == 1 || Ind == 0)
{
xnn=0;
xpp=0;
ynn=0;
ypp=0;
if ((chk & 0x01)==0x01) {
wp.rx()--;
xnn++;
}
else if ((chk & 0x02)==0x02) {
wp.rx()++;
xpp++;
}
else if ((chk & 0x04)==0x04) {
wp.ry()--;
ynn++;
}
else if ((chk & 0x08)==0x08) {
wp.ry()++;
ypp++;
}
}
Ppnt = wp;
alpath.push_front(Ppnt);
}
return alpath;
}