Esempio n. 1
0
void RoomPropertySetter::parseProperty(const QByteArray &command, const Coordinate &roomPos)
{
    QList<QByteArray> words = command.simplified().split(' ');
    AbstractAction *action = 0;
    QByteArray property = words[1];
    uint pos = propPositions[property];
    if (words.size() == 4) {
        //change exit property
        ExitDirection dir = Mmapper2Exit::dirForChar(words[2][0]);
        switch (pos) {
        case E_FLAGS:
        case E_DOORFLAGS:
            action = new ModifyExitFlags(fieldValues[property], dir, pos, FMM_TOGGLE);
            break;
        case E_DOORNAME:
            action = new UpdateExitField(property, dir, pos);
            break;
        default:
            emit sendToUser("unknown property: " + property + "\r\n");
            return;
        }
    } else if (words.size() == 3) {
        //change room property
        switch (pos) {
        case R_TERRAINTYPE:
            action = new UpdatePartial(fieldValues[property], pos);
            break;
        case R_NAME:
        case R_DESC:
            action = new UpdatePartial(property, pos);
            break;
        case R_MOBFLAGS:
        case R_LOADFLAGS:
            action = new ModifyRoomFlags(fieldValues[property], pos, FMM_TOGGLE);
            break;
        case R_DYNAMICDESC:
        case R_NOTE:
            action = new UpdateRoomField(property, pos);
            break;
        case R_PORTABLETYPE:
        case R_LIGHTTYPE:
        case R_ALIGNTYPE:
        case R_RIDABLETYPE:
            action = new UpdateRoomField(fieldValues[property], pos);
            break;
        default:
            emit sendToUser("unknown property: " + property + "\r\n");
            return;
        }

        RoomPropertySetterSlave slave(action);
        emit lookingForRooms(&slave, roomPos);

        if (slave.getResult()) {
            emit sendToUser("OK\r\n");
        } else {
            emit sendToUser("setting " + property + " failed!\r\n");
        }
    }
}
Esempio n. 2
0
void PathMachine::syncing(const SigParseEvent &sigParseEvent)
{
    ParseEvent &event = sigParseEvent.deref();
    {
        Syncing sync(params, paths, &signaler);
        if (event.getNumSkipped() <= params.maxSkipped) {
            emit lookingForRooms(sync, sigParseEvent);
        }
        paths = sync.evaluate();
    }
    evaluatePaths();
}
Esempio n. 3
0
void PathMachine::tryCoordinate(const Room *const room, RoomRecipient &recipient, ParseEvent &event)
{
    const CommandIdType moveCode = event.getMoveType();
    if (moveCode < CommandIdType::FLEE) {
        // LOOK, UNKNOWN will have an empty offset
        auto offset = RoomFactory::exitDir(getDirection(moveCode));
        const Coordinate c = room->getPosition() + offset;
        emit lookingForRooms(recipient, c);

    } else {
        const Coordinate roomPos = room->getPosition();
        // REVISIT: Should this enumerate 6 or 7 values?
        // NOTE: This previously enumerated 8 values instead of 7,
        // which meant it was asking for exitDir(ExitDirection::NONE),
        // even though both ExitDirection::UNKNOWN and ExitDirection::NONE
        // both have Coordinate(0, 0, 0).
        for (const auto dir : ALL_EXITS7) {
            emit lookingForRooms(recipient, roomPos + RoomFactory::exitDir(dir));
        }
    }
}
Esempio n. 4
0
void PathMachine::setCurrentRoom(const RoomId id, bool update)
{
    Forced forced(lastEvent, update);
    emit lookingForRooms(forced, id);
    releaseAllPaths();
    if (const Room *perhaps = forced.oneMatch()) {
        // WARNING: This copies the current values of the room.
        mostLikelyRoom = *perhaps;
        emit playerMoved(mostLikelyRoom.getPosition());
        emit setCharPosition(mostLikelyRoom.getId());
        state = PathState::APPROVED;
    }
}
Esempio n. 5
0
void PathMachine::experimenting(const SigParseEvent &sigParseEvent)
{
    ParseEvent &event = sigParseEvent.deref();

    std::unique_ptr<Experimenting> exp = nullptr;
    const CommandIdType moveCode = event.getMoveType();

    const auto dir = getDirection(moveCode);
    const Coordinate &move = RoomFactory::exitDir(dir);

    // only create rooms if no properties are skipped and
    // the move coordinate is not 0,0,0

    if (event.getNumSkipped() == 0 && moveCode < CommandIdType::FLEE && !mostLikelyRoom.isFake()
        && !move.isNull()) {
        exp = std::make_unique<Crossover>(paths, dir, params, factory);
        std::set<const Room *> pathEnds{};
        for (auto &path : *paths) {
            const Room *const working = path->getRoom();
            if (pathEnds.find(working) == pathEnds.end()) {
                emit createRoom(sigParseEvent, working->getPosition() + move);
                pathEnds.insert(working);
            }
        }
        emit lookingForRooms(*exp, sigParseEvent);
    } else {
        auto pOneByOne = std::make_unique<OneByOne>(factory, sigParseEvent, params, &signaler);
        {
            auto &tmp = *pOneByOne;
            for (auto &path : *paths) {
                const Room *const working = path->getRoom();
                tmp.addPath(path);
                tryExits(working, tmp, event, true);
                tryExits(working, tmp, event, false);
                tryCoordinate(working, tmp, event);
            }
        }
        exp = static_upcast<Experimenting>(std::exchange(pOneByOne, nullptr));
    }

    paths = exp->evaluate();
    evaluatePaths();
}
Esempio n. 6
0
void PathMachine::tryExits(const Room *const room,
                           RoomRecipient &recipient,
                           ParseEvent &event,
                           const bool out)
{
    const CommandIdType move = event.getMoveType();
    if (isDirection7(move)) {
        const Exit &possible = room->exit(getDirection(move));
        tryExit(possible, recipient, out);
    } else {
        // Only check the current room for LOOK
        emit lookingForRooms(recipient, room->getId());
        if (move >= CommandIdType::FLEE) {
            // Only try all possible exits for commands FLEE, SCOUT, and NONE
            for (const auto &possible : room->getExitsList()) {
                tryExit(possible, recipient, out);
            }
        }
    }
}
Esempio n. 7
0
void PathMachine::approved(const SigParseEvent &sigParseEvent)
{
    ParseEvent &event = sigParseEvent.deref();

    Approved appr(factory, sigParseEvent, params.matchingTolerance);
    const Room *perhaps = nullptr;

    if (event.getMoveType() == CommandIdType::LOOK) {
        emit lookingForRooms(appr, mostLikelyRoom.getId());

    } else {
        tryExits(&mostLikelyRoom, appr, event, true);
    }

    perhaps = appr.oneMatch();

    if (perhaps == nullptr) {
        // try to match by reverse exit
        appr.reset();
        tryExits(&mostLikelyRoom, appr, event, false);
        perhaps = appr.oneMatch();
        if (perhaps == nullptr) {
            // try to match by coordinate
            appr.reset();
            tryCoordinate(&mostLikelyRoom, appr, event);
            perhaps = appr.oneMatch();
            if (perhaps == nullptr) {
                // try to match by coordinate one step below expected
                // FIXME: need stronger type checking here.

                const auto cmd = event.getMoveType();
                // NOTE: This allows ExitDirection::UNKNOWN,
                // which means the coordinate can be Coordinate(0,0,0).
                const Coordinate &eDir = RoomFactory::exitDir(getDirection(cmd));

                // CAUTION: This test seems to mean it wants only NESW,
                // but it would also accept ExitDirection::UNKNOWN,
                // which in the context of this function would mean "no move."
                if (eDir.z == 0) {
                    appr.reset();
                    Coordinate c = mostLikelyRoom.getPosition() + eDir;
                    c.z--;
                    emit lookingForRooms(appr, c);
                    perhaps = appr.oneMatch();

                    if (perhaps == nullptr) {
                        // try to match by coordinate one step above expected
                        appr.reset();
                        c.z += 2;
                        emit lookingForRooms(appr, c);
                        perhaps = appr.oneMatch();
                    }
                }
            }
        }
    }
    if (perhaps != nullptr) {
        // Update the exit from the previous room to the current room
        const CommandIdType move = event.getMoveType();
        if (static_cast<uint32_t>(move) < NUM_EXITS) {
            emit scheduleAction(new AddExit(mostLikelyRoom.getId(),
                                            perhaps->getId(),
                                            static_cast<ExitDirection>(move)));
        }

        // Update most likely room with player's current location
        mostLikelyRoom = *perhaps;

        // Update rooms behind exits now that we are certain about our current location
        const ConnectedRoomFlagsType bFlags = event.getConnectedRoomFlags();
        if (bFlags.isValid()) {
            for (const auto dir : ALL_DIRECTIONS6) {
                const Exit &e = mostLikelyRoom.exit(dir);
                if (!e.outIsUnique()) {
                    continue;
                }
                RoomId connectedRoomId = e.outFirst();
                auto bThisRoom = bFlags.getDirectionalLight(dir);
                if (IS_SET(bThisRoom, DirectionalLightType::DIRECT_SUN_ROOM)) {
                    emit scheduleAction(
                        new SingleRoomAction(new UpdateRoomField(RoomSundeathType::SUNDEATH),
                                             connectedRoomId));
                } else if (IS_SET(bThisRoom, DirectionalLightType::INDIRECT_SUN_ROOM)) {
                    emit scheduleAction(
                        new SingleRoomAction(new UpdateRoomField(RoomSundeathType::NO_SUNDEATH),
                                             connectedRoomId));
                }
            }
        }

        // Update the room if we had a tolerant match rather than an exact match
        if (appr.needsUpdate()) {
            emit scheduleAction(
                new SingleRoomAction(new Update(sigParseEvent), mostLikelyRoom.getId()));
        }

        // Send updates
        emit playerMoved(mostLikelyRoom.getPosition());
        // GroupManager
        emit setCharPosition(mostLikelyRoom.getId());
    } else {
        // couldn't match, give up
        state = PathState::EXPERIMENTING;
        pathRoot = mostLikelyRoom;
        auto *const root = new Path(&pathRoot, nullptr, nullptr, &signaler);
        paths->push_front(root);
        experimenting(sigParseEvent);
    }
}
Esempio n. 8
0
void PathMachine::tryExit(const Exit &possible, RoomRecipient &recipient, const bool out)
{
    for (auto idx : possible.getRange(out)) {
        emit lookingForRooms(recipient, idx);
    }
}