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"); } } }
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(); }
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)); } } }
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; } }
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(); }
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); } } } }
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); } }
void PathMachine::tryExit(const Exit &possible, RoomRecipient &recipient, const bool out) { for (auto idx : possible.getRange(out)) { emit lookingForRooms(recipient, idx); } }