scummvm/engines/pegasus/ai/ai_condition.cpp
2022-09-28 11:30:00 +02:00

289 lines
7.8 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.
*
* Additional copyright for this file:
* Copyright (C) 1995-1997 Presto Studios, Inc.
*
* 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/stream.h"
#include "pegasus/energymonitor.h"
#include "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_condition.h"
#include "pegasus/items/itemlist.h"
#include "pegasus/items/biochips/biochipitem.h"
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
AIOneChildCondition::AIOneChildCondition(AICondition *child) {
_child = child;
}
AIOneChildCondition::~AIOneChildCondition() {
delete _child;
}
void AIOneChildCondition::writeAICondition(Common::WriteStream *stream) {
if (_child)
_child->writeAICondition(stream);
}
void AIOneChildCondition::readAICondition(Common::ReadStream *stream) {
if (_child)
_child->readAICondition(stream);
}
AITwoChildrenCondition::AITwoChildrenCondition(AICondition *leftChild, AICondition *rightChild) {
_leftChild = leftChild;
_rightChild = rightChild;
}
AITwoChildrenCondition::~AITwoChildrenCondition() {
delete _leftChild;
delete _rightChild;
}
void AITwoChildrenCondition::writeAICondition(Common::WriteStream *stream) {
if (_leftChild)
_leftChild->writeAICondition(stream);
if (_rightChild)
_rightChild->writeAICondition(stream);
}
void AITwoChildrenCondition::readAICondition(Common::ReadStream *stream) {
if (_leftChild)
_leftChild->readAICondition(stream);
if (_rightChild)
_rightChild->readAICondition(stream);
}
AINotCondition::AINotCondition(AICondition* child) : AIOneChildCondition(child) {
}
bool AINotCondition::fireCondition() {
return _child && !_child->fireCondition();
}
AIAndCondition::AIAndCondition(AICondition *leftChild, AICondition *rightChild) : AITwoChildrenCondition(leftChild, rightChild) {
}
bool AIAndCondition::fireCondition() {
return _leftChild && _leftChild->fireCondition() && _rightChild && _rightChild->fireCondition();
}
AIOrCondition::AIOrCondition(AICondition *leftChild, AICondition *rightChild) : AITwoChildrenCondition(leftChild, rightChild) {
}
bool AIOrCondition::fireCondition() {
return (_leftChild && _leftChild->fireCondition()) || (_rightChild && _rightChild->fireCondition());
}
AITimerCondition::AITimerCondition(const TimeValue time, const TimeScale scale, const bool shouldStartTimer) {
_timerFuse.primeFuse(time, scale);
_timerFuse.setFunctor(new Common::Functor0Mem<void, AITimerCondition>(this, &AITimerCondition::fire));
_fired = false;
if (shouldStartTimer)
startTimer();
}
void AITimerCondition::startTimer() {
_fired = false;
_timerFuse.lightFuse();
}
void AITimerCondition::stopTimer() {
_timerFuse.stopFuse();
}
void AITimerCondition::writeAICondition(Common::WriteStream *stream) {
stream->writeByte(_timerFuse.isFuseLit());
stream->writeByte(_fired);
stream->writeUint32BE(_timerFuse.getTimeRemaining());
stream->writeUint32BE(_timerFuse.getFuseScale());
}
void AITimerCondition::readAICondition(Common::ReadStream *stream) {
bool running = stream->readByte();
_fired = stream->readByte();
TimeValue time = stream->readUint32BE();
TimeScale scale = stream->readUint32BE();
_timerFuse.stopFuse();
_timerFuse.primeFuse(time, scale);
if (running)
_timerFuse.lightFuse();
}
bool AITimerCondition::fireCondition() {
return _fired;
}
void AITimerCondition::fire() {
_fired = true;
}
AILocationCondition::AILocationCondition(uint32 maxLocations) {
_numLocations = 0;
_maxLocations = maxLocations;
_locations = new RoomViewID[maxLocations];
}
AILocationCondition::~AILocationCondition() {
delete[] _locations;
}
void AILocationCondition::addLocation(const RoomViewID location) {
if (_numLocations < _maxLocations)
_locations[_numLocations++] = location;
}
bool AILocationCondition::fireCondition() {
RoomViewID test = GameState.getCurrentRoomAndView(), *p;
uint32 i;
for (i = 0, p = _locations; i < _numLocations; i++, p++) {
if (test == *p) {
*p = MakeRoomView(kNoRoomID, kNoDirection);
return true;
}
}
return false;
}
void AILocationCondition::writeAICondition(Common::WriteStream *stream) {
stream->writeUint32BE(_maxLocations);
stream->writeUint32BE(_numLocations);
uint32 i;
RoomViewID *p;
for (i = 0, p = _locations; i < _numLocations; i++, p++)
stream->writeUint32BE(*p);
}
void AILocationCondition::readAICondition(Common::ReadStream *stream) {
uint32 maxLocations = stream->readUint32BE();
if (_maxLocations != maxLocations) {
delete[] _locations;
_locations = new RoomViewID[maxLocations];
_maxLocations = maxLocations;
}
_numLocations = stream->readUint32BE();
uint32 i;
RoomViewID *p;
for (i = 0, p = _locations; i < _numLocations; i++, p++)
*p = stream->readUint32BE();
}
AIDoorOpenedCondition::AIDoorOpenedCondition(RoomViewID doorLocation) {
_doorLocation = doorLocation;
}
bool AIDoorOpenedCondition::fireCondition() {
return GameState.getCurrentRoomAndView() == _doorLocation && GameState.isCurrentDoorOpen();
}
AIHasItemCondition::AIHasItemCondition(const ItemID item) {
_item = item;
}
bool AIHasItemCondition::fireCondition() {
return _item == kNoItemID || GameState.isTakenItemID(_item);
}
AIDoesntHaveItemCondition::AIDoesntHaveItemCondition(const ItemID item) {
_item = item;
}
bool AIDoesntHaveItemCondition::fireCondition() {
return _item == kNoItemID || !GameState.isTakenItemID(_item);
}
AICurrentItemCondition::AICurrentItemCondition(const ItemID item) {
_item = item;
}
bool AICurrentItemCondition::fireCondition() {
InventoryItem *item = g_vm->getCurrentInventoryItem();
if (_item == kNoItemID)
return item == nullptr;
return item != nullptr && item->getObjectID() == _item;
}
AICurrentBiochipCondition::AICurrentBiochipCondition(const ItemID biochip) {
_biochip = biochip;
}
bool AICurrentBiochipCondition::fireCondition() {
BiochipItem *biochip = g_vm->getCurrentBiochip();
if (_biochip == kNoItemID)
return biochip == nullptr;
return biochip != nullptr && biochip->getObjectID() == _biochip;
}
AIItemStateCondition::AIItemStateCondition(const ItemID item, const ItemState state) {
_item = item;
_state = state;
}
bool AIItemStateCondition::fireCondition() {
Item *item = g_allItems.findItemByID(_item);
return item != nullptr && item->getItemState() == _state;
}
AIEnergyMonitorCondition::AIEnergyMonitorCondition(const int32 energyThreshold) {
_energyThreshold = energyThreshold;
}
bool AIEnergyMonitorCondition::fireCondition() {
return g_energyMonitor != nullptr && g_energyMonitor->getCurrentEnergy() < _energyThreshold;
}
AILastExtraCondition::AILastExtraCondition(const ExtraID lastExtra) {
_lastExtra = lastExtra;
}
bool AILastExtraCondition::fireCondition() {
return g_neighborhood && (ExtraID)g_neighborhood->getLastExtra() == _lastExtra;
}
AICondition *makeLocationAndDoesntHaveItemCondition(const RoomID room, const DirectionConstant direction, const ItemID item) {
AILocationCondition *location = new AILocationCondition(1);
location->addLocation(MakeRoomView(room, direction));
AIDoesntHaveItemCondition *doesntHaveItem = new AIDoesntHaveItemCondition(item);
return new AIAndCondition(location, doesntHaveItem);
}
} // End of namespace Pegasus