scummvm/engines/asylum/puzzles/pipes.h
2021-05-17 15:37:54 +02:00

208 lines
5.7 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ASYLUM_PUZZLES_PIPES_H
#define ASYLUM_PUZZLES_PIPES_H
#include "common/list.h"
#include "common/hashmap.h"
#include "common/array.h"
#include "common/random.h"
#include "common/str.h"
#include "asylum/puzzles/puzzle.h"
namespace Asylum {
class AsylumEngine;
class Connector;
static const uint32 connectorsCount = 21, peepholesCount = 37;
enum BinNum {
kBinNum0000,
kBinNum0001,
kBinNum0010,
kBinNum0011,
kBinNum0100,
kBinNum0101,
kBinNum0110,
kBinNum0111,
kBinNum1000,
kBinNum1001,
kBinNum1010,
kBinNum1011,
kBinNum1100,
kBinNum1101,
kBinNum1110,
kBinNum1111
};
enum ConnectorType {
kConnectorTypeI = kBinNum0101,
kConnectorTypeL = kBinNum0110,
kConnectorTypeT = kBinNum0111
};
enum Direction {
kDirectionNowhere = kBinNum0000,
kDirectionNh = kBinNum0001,
kDirectionEt = kBinNum0010,
kDirectionSh = kBinNum0100,
kDirectionWt = kBinNum1000
};
class Peephole {
public:
Peephole() {}
~Peephole() {}
static bool marks[peepholesCount];
uint32 _flowValues[4];
uint32 getId() { return _id; }
void setId(uint32 id) { _id = id; }
uint32 getLevel() { return (_flowValues[0] > 0) + (_flowValues[1] > 0) + (_flowValues[2] > 0) + (_flowValues[3] > 0); }
uint32 getLevel1() { return _flowValues[0] + _flowValues[1] + _flowValues[2] + _flowValues[3]; }
bool isConnected() { return isConnected(0) || isConnected(1) || isConnected(2) || isConnected(3); }
void connect(Connector *connector) { _connectors.push_back(connector); }
void disconnect(Connector *connector) { _connectors.remove(connector); }
void startUpWater(bool flag = false);
private:
uint32 _id;
Common::List<Connector *> _connectors;
bool isConnected(uint32 val) { return _flowValues[val]; }
};
class Connector {
public:
Connector() {}
~Connector() {}
uint32 getId() { return _id; }
void setId(uint32 id) { _id = id; }
void setPos(uint32 *pos) { _position = pos; }
BinNum getState() { return _state; }
ConnectorType getType() { return _type; }
void init(Peephole *n, Peephole *e, Peephole *s, Peephole *w, uint32 pos, ConnectorType type, Connector *nextConnector = NULL, Direction nextConnectorPosition = kDirectionNowhere);
void initGroup();
void turn(bool updpos = true);
private:
uint32 _id;
BinNum _state;
ConnectorType _type;
uint32 *_position;
Peephole *_nodes[4];
Common::List<Peephole *> _connectedNodes;
Connector *_nextConnector;
Direction _nextConnectorPosition;
bool _isConnected;
void connect(Connector *connector);
void disconnect(Connector *connector);
bool isReadyForConnection() { return _state & _nextConnectorPosition; }
friend void Peephole::startUpWater(bool);
};
class Spider {
public:
Spider(const Common::Rect &rect, Common::String id);
~Spider() { delete _rnd; }
bool isAlive() const { return _isAlive; }
bool isActive() const { return _delta != Common::Point(0, 0); }
bool isVisible(Common::Rect rect) const { return rect.contains(_location); }
Direction getDirection() const { return _direction; }
Common::Rect getPolygon(Common::Rect frame) const { return Common::Rect(_location.x - frame.left, _location.y - frame.top, _location.x + frame.right, _location.y + frame.bottom); }
Common::Point move();
void smash() { _isAlive = false; }
private:
static const uint32 minStepsNumber = 20, maxStepsNumber = 200;
Common::RandomSource *_rnd;
bool _isAlive;
Common::Point _location;
Common::Point _delta;
Common::Rect _boundingBox;
Direction _direction;
uint32 _stepsNumber;
uint32 _steps;
void randomize(Direction excluded = kDirectionNowhere);
};
class PuzzlePipes : public Puzzle {
public:
PuzzlePipes(AsylumEngine *engine);
~PuzzlePipes();
// Serializable
virtual void saveLoadWithSerializer(Common::Serializer &s);
private:
int32 _previousMusicVolume;
int32 _rectIndex;
uint32 _frameIndex, _frameIndexLever;
bool _levelFlags[5];
float _levelValues[4], _previousLevels[4];
bool _isLeverReady;
Common::HashMap<uint32, uint32> _connectorResources;
Connector _connectors[connectorsCount];
uint32 _positions[connectorsCount];
Peephole _peepholes[peepholesCount];
Peephole *_sinks[4], *_sources[4];
Common::Array<Spider *> _spiders;
uint32 *_frameIndexSpider;
//////////////////////////////////////////////////////////////////////////
// Event Handling
//////////////////////////////////////////////////////////////////////////
bool init(const AsylumEvent &evt);
bool update(const AsylumEvent &evt);
bool mouseLeftDown(const AsylumEvent &evt);
bool mouseRightDown(const AsylumEvent &evt);
//////////////////////////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////////////////////////
void initResources();
void setup();
void updateCursor();
int32 findRect();
uint32 checkFlags();
void startUpWater();
void checkConnections();
};
} // End of namespace Asylum
#endif // ASYLUM_PUZZLES_PIPES_H