Ejemplo n.º 1
0
    Figure* Board::swap(const Coords &pos, const Figure * const fig) {
        Figure * const result = board[coordsToIndex(pos)];
        // TODO: Figure parametrisieren
        board[coordsToIndex(pos)] = (fig == NULL) ? NULL : fig->clone();

        return result;
    }
Ejemplo n.º 2
0
    bool Board::move(const Coords &from, const Coords &to) {
        if (board[coordsToIndex(from)] == NULL || board[coordsToIndex(to)] == NULL) {
            return false;
        }
        // TODO: Figure parametrisieren
        board[coordsToIndex(to)] = board[coordsToIndex(from)];
        board[coordsToIndex(from)] = NULL;

        return true;
    }
Ejemplo n.º 3
0
toweringinferno::World::ActionSuccess toweringinferno::World::updateHoseRelease(
	const TCOD_key_t& command
	)
{
	if (isActionKey(command) == false)
	{
		return eAction_InvalidInput;
	}

	const Point playerPos = m_player.getPos();
	for(int col = playerPos.col - 1; col < playerPos.col + 2; ++col)
	{
		for(int row = playerPos.row - 1; row < playerPos.row + 2; ++row)
		{
			if (getType(col, row) != eHose)
			{
				continue;
			}

			Cell& hose = m_floorData.map[coordsToIndex(col, row)];
			if (hose.hp == 0.0f)
			{
				continue;
			}

			hose.water = 3.5f;
			hose.hp = 0.0f;
			return eAction_Succeeded;
		}
	}

	return eAction_Failed;
}
Ejemplo n.º 4
0
toweringinferno::World::ActionSuccess toweringinferno::World::updateAxe(
	const TCOD_key_t& command
	)
{
	if (isAxeKey(command) == false)
	{
		return eAction_InvalidInput;
	}

	if (m_player.getAxesRemaining() == 0)
	{
		return eAction_Failed;
	}

	Cell* wallToAxe = NULL;

	const Point playerPos = m_player.getPos();
	for(int col = playerPos.col - 1; col < playerPos.col + 2; ++col)
	{
		for(int row = playerPos.row - 1; row < playerPos.row + 2; ++row)
		{
			if ((col == playerPos.col && row == playerPos.row) || isValidCoords(col, row) == false)
			{
				continue;
			}

			Cell& axisNeighbourCell = m_floorData.map[coordsToIndex(col, row)];

			if (axisNeighbourCell.type == eWall 
				&& (wallToAxe == NULL 
					|| isDeltaWithDirection(col - playerPos.col, row - playerPos.row, m_floorData.lastMovementDir)))
			{
				wallToAxe = &axisNeighbourCell;
			}
		}
	}

	if (wallToAxe != NULL)
	{
		wallToAxe->hp -= 0.34f;
		if (wallToAxe->hp <= 0.0f)
		{
			wallToAxe->type = eFloor;
			m_player.useAxe();
		}

		return eAction_Succeeded;
	}
	else
	{
		return eAction_Failed;
	}
}
Ejemplo n.º 5
0
toweringinferno::World::ActionSuccess toweringinferno::World::updateSprinklerControl(
	const TCOD_key_t& command
	)
{
	if (isActionKey(command) == false)
	{
		return eAction_InvalidInput;
	}

	if (m_floorData.isSprinklerAvailable == false)
	{
		return eAction_Failed;
	}

	const Point playerPos = m_player.getPos();
	for(int col = playerPos.col - 1; col < playerPos.col + 2; ++col)
	{
		for(int row = playerPos.row - 1; row < playerPos.row + 2; ++row)
		{
			if (getType(col, row) != eSprinklerControl)
			{
				continue;
			}

			// GO GO SPRINKLERS
			const int sprinklerSpacing = 9;
			for (int sprinklerCol = sprinklerSpacing; sprinklerCol < m_width; sprinklerCol += sprinklerSpacing)
			{
				for(int sprinklerRow = sprinklerSpacing; sprinklerRow < m_height; sprinklerRow += sprinklerSpacing)
				{
					Cell& cell = m_floorData.map[coordsToIndex(sprinklerCol, sprinklerRow)];

					if (cell.type == eFloor)
					{
						cell.water = 1.5f;
						cell.fire = 0.0f;
						cell.heat = 0.0f;
					}
				}
			}

			m_floorData.isSprinklerAvailable = false;
			return eAction_Succeeded;
		}
	}

	return eAction_Failed;
}
Ejemplo n.º 6
0
toweringinferno::World::ActionSuccess toweringinferno::World::updateDoors(
	const TCOD_key_t& command
	)
{
	if (isDoorToggleKey(command) == false)
	{
		return eAction_InvalidInput;
	}

	bool didAnyDoorFlip = false;
	const Point playerPos = m_player.getPos();
	for(int col = playerPos.col - 1; col < playerPos.col + 2; ++col)
	{
		for(int row = playerPos.row - 1; row < playerPos.row + 2; ++row)
		{
			if (isValidCoords(col, row) == false)
			{
				continue;
			}

			Cell& axisNeighbourCell = m_floorData.map[coordsToIndex(col, row)];
			if (axisNeighbourCell.type == eOpenDoor)
			{
				axisNeighbourCell.type = eClosedDoor;
				didAnyDoorFlip = true;
			}
			else if (axisNeighbourCell.type == eClosedDoor)
			{
				axisNeighbourCell.type = eOpenDoor;
				didAnyDoorFlip = true;
			}
		}
	}

	return didAnyDoorFlip ? eAction_Succeeded : eAction_Failed;
}
Ejemplo n.º 7
0
void toweringinferno::World::updateDynamics()
{
	for(int col = 0; col < getWidth(); ++col)
	{
		for(int row = 0; row < getHeight(); ++row)
		{
			Cell& cell = m_floorData.map[coordsToIndex(col, row)];
			cell.typeFlip = cell.type;
		}
	}

	for(int col = 0; col < getWidth(); ++col)
	{
		for(int row = 0; row < getHeight(); ++row)
		{
			Cell& cell = m_floorData.map[coordsToIndex(col, row)];

			if (cell.type == eSky)
			{
				continue;
			}

			// calculate heat
			float heat = 0.0f;
				
			const float minEvaporation = utils::mapValue(cell.water, 0.1f, 0.15f, 0.0f, 0.1f);
			const float evaporation = utils::mapValue(cell.heat, 0.0f, 1.0f, minEvaporation, 0.6f);
			float waterTotal = cell.water - evaporation;
			int waterContributors = 1;

			float condensationScore = cell.water;
			int condensationContributors = 1;
			
 			for(int neighbourCol = utils::max(col - 1, 0); 
				neighbourCol < utils::min(getWidth(), col + 2);
				++neighbourCol)
			{
				for (int neighbourRow = utils::max(row - 1, 0);
					neighbourRow < utils::min(getHeight(), row + 2);
					++neighbourRow)
				{
					if (neighbourCol == col && neighbourRow == row)
					{
						continue;
					}

					Cell& neighbour = m_floorData.map[coordsToIndex(neighbourCol,neighbourRow)];

					const bool isDiagonalNeighbour = row != neighbourRow && col != neighbourCol;

					const bool wallCanContributeHeat 
						= (row == neighbourRow 
							&& getType(col + 1, row) != eClosedDoor && getType(col - 1, row) != eClosedDoor 
							&& ((getType(col, row - 1) == eFloor && getType(col + (neighbourCol < col ? -1 : 1), row - 1) != eClosedDoor) 
								|| (getType(col, row + 1) == eFloor && getType(col + (neighbourCol < col ? -1 : 1), row + 1) != eClosedDoor)))
						|| (col == neighbourCol 
							&& getType(col, row - 1) != eClosedDoor && getType(col, row + 1) != eClosedDoor
							&& ((getType(col - 1, row) == eFloor && getType(col - 1, row + (neighbourRow < row ? -1 : 1)) != eClosedDoor)
								|| (getType(col + 1, row) == eFloor && getType(col + 1, row + (neighbourRow < row ? -1 : 1)) != eClosedDoor)));

					const float heatContribution 
						= isDiagonalNeighbour ? 0.0f
						: neighbour.type == eWall && cell.type == eWall && wallCanContributeHeat == false ? 0.0f
						: neighbour.type == eWall ? (3.5f/6.0f)
						: (1.5f/6.0f);
					
					heat += neighbour.heat * heatContribution;

					if (isDiagonalNeighbour == false)
					{
						condensationScore += neighbour.water;
						condensationContributors += neighbour.water > 0.0f ? 1 : 0;
					}

					const bool isNeighbourContributingWater = isWaterBlocker(neighbour) == false
						&& cell.water < neighbour.water;
					waterTotal += (isNeighbourContributingWater ? neighbour.water : 0.0f);
					waterContributors += isNeighbourContributingWater ? 1 : 0;
				}
			}

			cell.waterFlip = isWaterBlocker(cell) ? 0.0f
				: utils::max(waterTotal / static_cast<float>(waterContributors), 0.0f);
			
			const float heatBuildRate 
				= cell.type == eWall ? 0.65f 
				: isHeatProof(cell.type) ? 0.0f
				: 0.25f;

			const float condensation = utils::mapValue(condensationScore / static_cast<float>(condensationContributors), 
				0.0f, 1.0f, 0.01f, 0.6f);
			cell.heatFlip = utils::clamp( cell.heat + heat * heatBuildRate - condensation, 0.0f, 1.0f);

			if (cell.type == eWall)
			{
				cell.hp = utils::max(0.0f, cell.hp - utils::mapValue(cell.fire, 0.9f, 1.0f, 0.0f, 0.02f));

				if (cell.hp == 0.0f)
				{
					cell.typeFlip = eFloor;
					cell.fire = 0.75f;
				}
			}
		}
	}

	for(int col = 0; col < getWidth(); ++col)
	{
		for(int row = 0; row < getHeight(); ++row)
		{
			Cell& cell = m_floorData.map[coordsToIndex(col, row)];
			cell.type = cell.typeFlip;

			cell.water = cell.waterFlip;

			cell.heat = cell.heatFlip;

			const float fireThreshold = 0.5f;

			if (cell.heat > fireThreshold)
			{
				cell.fire = utils::clamp(cell.fire + utils::mapValue(cell.heat, fireThreshold, 1.0f, 0.0f, 0.05f), 0.0f, 1.0f);
			}
			else
			{
				cell.fire = 0.0f;
			}
		}
	}
}
Ejemplo n.º 8
0
    bool Board::apply(BoardTransaction &tr) {
        MutableBoardTransaction mtr(tr);

        if (mtr.isAccepted()) {
            return false; // transaction has already been accepted/applied
        }

        mtr.setTransactionNumber(nextTransaction); // assign preliminary transaction number

        if (mtr.getBoardOps().size() == 0) { // empty transaction, apply rules
            if (!inRange(mtr.getFrom()) || !inRange(mtr.getTo())) {
                throw std::out_of_range("Source or target coordinates are outside of board range");
            }

            if (mtr.getFrom() == mtr.getTo()) {
                mtr.setStateCode(bsc_SourceAndDestinationAreEqual);

                return false;
            }

            Figure *fig = board[coordsToIndex(mtr.getFrom())];
            if (fig == NULL) {
                return false; // no figure which could do something is there
            }

            if (!fig->apply(mtr)) {
                mtr.setAccepted(false);
                mtr.getBoardOps().clear();

                return false; // failed to prepare transaction
            }
        }

        std::vector<BoardOp::Operation*> &ops = mtr.getBoardOps();

        bool result = true;
        size_t i = 0;

        for (; result && i < ops.size(); i++) {
            result &= ops[i]->apply(*this);
        }

        if (result) {
            mtr.setAccepted(true);
            nextTransaction++; // Increment for next transaction

            return true; // transaction has been applied successfully
        } // else: transaction failed, rollback

        result = true;

        do {
            i--;
            result &= ops[i]->undo(*this);
        } while (result && i != 0);

        if (!result) { // rollback has failed, too ... something is broken utterly
            // we don't bother about invalidating the transaction, this is a major
            // problem which can not be resolved
            throw std::logic_error("Undo operation failed to recover from failure");
        }

        mtr.setAccepted(false);

        return false;
    }
Ejemplo n.º 9
0
 const Figure* Board::get(const Coords &pos) const {
     return board[coordsToIndex(pos)];
 }