bool AbstractParser::parsePrint(StringView &input)
{
    const auto syntax = [this]() { sendToUser("Print what? [dynamic | static | note]\r\n"); };

    if (input.isEmpty()) {
        syntax();
        return true;
    }

    const auto next = input.takeFirstWord();
    if (Abbrev{"dynamic", 1}.matches(next)) {
        printRoomInfo(dynamicRoomFields);
        return true;
    } else if (Abbrev{"static", 1}.matches(next)) {
        printRoomInfo(staticRoomFields);
        return true;
    } else if (Abbrev{"note", 1}.matches(next)) {
        showNote();
        return true;
    } else {
        syntax();
        return true;
    }
}
void AbstractParser::initSpecialCommandMap()
{
    auto &map = m_specialCommandMap;
    map.clear();

    auto add = [this](Abbrev abb, const ParserCallback &callback, const HelpCallback &help) {
        addSpecialCommand(abb.getCommand(), abb.getMinAbbrev(), callback, help);
    };

    const auto makeSimpleHelp = [this](const std::string &help) {
        return [this, help](const std::string &name) {
            sendToUser(QString("Help for %1%2:\r\n  %3\r\n\r\n")
                           .arg(prefixChar)
                           .arg(QString::fromStdString(name))
                           .arg(QString::fromStdString(help)));
        };
    };

    qInfo() << "Adding special commands to the map...";

    // help is important, so it comes first

    add(cmdHelp,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            this->parseHelp(rest);
            return true;
        },
        // TODO: create a parse tree, and show all of the help topics.
        makeSimpleHelp("Provides help."));
    add(cmdMapHelp,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->showMapHelp();
            return true;
        },
        makeSimpleHelp("Help for mapping console commands."));
    add(cmdDoorHelp,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->showDoorCommandHelp();
            return true;
        },
        makeSimpleHelp("Help for door console commands."));
    add(cmdGroupHelp,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->showGroupHelp();
            return true;
        },
        makeSimpleHelp("Help for group manager console commands."));

    // door actions
    for (const DoorActionType x : ALL_DOOR_ACTION_TYPES) {
        if (auto cmd = getParserCommandName(x))
            add(cmd,
                [this, x](const std::vector<StringView> & /*s*/, StringView rest) {
                    return parseDoorAction(x, rest);
                },
                makeSimpleHelp("Sets door action: " + std::string{cmd.getCommand()}));
    }

    for (const DoorFlag x : ALL_DOOR_FLAGS) {
        if (auto cmd = getParserCommandName(x))
            add(getParserCommandName(x),
                [this, x](const std::vector<StringView> & /*s*/, StringView rest) {
                    return parseDoorFlag(x, rest);
                },
                makeSimpleHelp("Sets door flag: " + std::string{cmd.getCommand()}));
    }

    for (const ExitFlag x : ALL_EXIT_FLAGS) {
        if (auto cmd = getParserCommandName(x))
            add(cmd,
                [this, x](const std::vector<StringView> & /*s*/, StringView rest) {
                    return parseExitFlag(x, rest);
                },
                makeSimpleHelp("Sets exit flag: " + std::string{cmd.getCommand()}));
    }

#define ADD_FIELD_CMDS(X) \
    do { \
        for (const auto x : DEFINED_ROOM_##X##_TYPES) { \
            if (auto cmd = getParserCommandName(x)) { \
                auto type = RoomField::X##_TYPE; \
                add(cmd, \
                    [this, x, type](const std::vector<StringView> & /*s*/, StringView rest) { \
                        if (!rest.isEmpty()) \
                            return false; \
                        setRoomFieldCommand(x, type); \
                        return true; \
                    }, \
                    makeSimpleHelp("Sets " #X " flag: " + std::string{cmd.getCommand()})); \
            } \
        } \
    } while (false)
    ADD_FIELD_CMDS(LIGHT);
    ADD_FIELD_CMDS(SUNDEATH);
    ADD_FIELD_CMDS(PORTABLE);
    ADD_FIELD_CMDS(RIDABLE);
    ADD_FIELD_CMDS(ALIGN);
#undef ADD_FIELD_CMDS

    for (const RoomMobFlag x : ALL_MOB_FLAGS) {
        if (auto cmd = getParserCommandName(x)) {
            add(cmd,
                [this, x](const std::vector<StringView> & /*s*/, StringView rest) {
                    if (!rest.isEmpty())
                        return false;
                    toggleRoomFlagCommand(x, RoomField::MOB_FLAGS);
                    return true;
                },
                makeSimpleHelp("Sets room mob flag: " + std::string{cmd.getCommand()}));
        }
    }

    for (const RoomLoadFlag x : ALL_LOAD_FLAGS) {
        if (auto cmd = getParserCommandName(x))
            add(cmd,
                [this, x](const std::vector<StringView> & /*s*/, StringView rest) {
                    if (!rest.isEmpty())
                        return false;
                    toggleRoomFlagCommand(x, RoomField::LOAD_FLAGS);
                    return true;
                },
                makeSimpleHelp("Sets room load flag: " + std::string{cmd.getCommand()}));
    }

    // misc commands

    add(cmdBack,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->doBackCommand();
            return true;
        },
        makeSimpleHelp("Delete prespammed commands from queue."));
    add(cmdDirections,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            this->parseDirections(rest);
            return true;
        },
        makeSimpleHelp("Prints directions to matching rooms."));
    add(cmdGroupKick,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            this->parseGroupKick(rest);
            return true;
        },
        makeSimpleHelp("Kick [player] from the group."));
    add(cmdGroupLock,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->doGroupLockCommand();
            return true;
        },
        makeSimpleHelp("Toggle the lock on the group."));
    add(cmdGroupTell,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            this->parseGroupTell(rest);
            return true;
        },
        makeSimpleHelp("Send a grouptell with the [message]."));
    add(cmdMarkCurrent,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->doMarkCurrentCommand();
            return true;
        },
        makeSimpleHelp("Highlight the room you are currently in."));
    add(cmdName,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            this->parseName(rest);
            return true;
        },
        makeSimpleHelp(
            "Arguments: <dir> <name>;  Sets the name of door in direction <dir> with <name>."));
    add(cmdNote,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            this->parseNoteCmd(rest);
            return true;
        },
        makeSimpleHelp("Sets the note for the current room."));
    add(cmdRemoveDoorNames,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->doRemoveDoorNamesCommand();
            return true;
        },
        makeSimpleHelp(
            "Removes all secret door names from the current map (WARNING: destructive)!"));
    add(cmdSearch,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            this->parseSearch(rest);
            return true;
        },
        makeSimpleHelp("Highlight matching rooms on the map."));
    add(cmdSet,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            this->parseSetCommand(rest);
            return true;
        },
        [this](const std::string &name) {
            const char help[]
                = "Subcommands:\r\n"
                  "\tprefix              # Displays the current prefix.\r\n"
                  "\tprefix <punct-char> # Changes the current prefix.\r\n"
                  "\r\n"
                  // REVISIT: Does it actually support LATIN-1 punctuation like the degree symbol?
                  "Note: <punct-char> may be any ASCII punctuation character,\r\n"
                  "      which can be optionally single- or double-quoted.\r\n"
                  "\r\n"
                  "Examples to set prefix:\r\n"
                  "\tprefix /   # slash character\r\n"
                  "\tprefix '/' # single-quoted slash character\r\n"
                  "\tprefix \"/\" # double-quoted slash character\r\n"
                  "\tprefix '   # bare single-quote character\r\n"
                  "\tprefix \"'\" # double-quoted single-quote character\r\n"
                  "\tprefix \"   # bare double-quote character\r\n"
                  "\tprefix '\"' # single-quoted double-quote character\r\n"
                  "\r\n"
                  "Note: Quoted versions do not allow escape codes,\r\n"
                  "so you cannot do ''', '\\'', \"\"\", or \"\\\"\".";
            sendToUser(QString("Help for %1%2:\r\n%3\r\n\r\n")
                           .arg(prefixChar)
                           .arg(QString::fromStdString(name))
                           .arg(QString::fromStdString(help)));
        });
    add(cmdTime,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->showMumeTime();
            return true;
        },
        makeSimpleHelp("Displays the current MUME time."));
    add(cmdTrollExit,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->toggleTrollMapping();
            return true;
        },
        makeSimpleHelp("Toggles troll-only exit mapping for direct sunlight."));
    add(cmdVote,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            this->openVoteURL();
            return true;
        },
        makeSimpleHelp("Launches a web browser so you can vote for MUME on TMC!"));

    /* print commands */
    add(cmdPrint,
        [this](const std::vector<StringView> & /*s*/, StringView rest) { return parsePrint(rest); },
        makeSimpleHelp("There is no help for this command yet."));

    add(cmdPDynamic,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            printRoomInfo(dynamicRoomFields);
            return true;
        },
        makeSimpleHelp("Prints current room description."));
    add(cmdPStatic,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            printRoomInfo(staticRoomFields);
            return true;
        },
        makeSimpleHelp("Prints current room description without movable items."));

    add(cmdPNote,
        [this](const std::vector<StringView> & /*s*/, StringView rest) {
            if (!rest.isEmpty())
                return false;
            showNote();
            return true;
        },
        makeSimpleHelp("Print the note in the current room."));

    qInfo() << "Total commands + abbreviations: " << map.size();
}
void interpretGame(){
  if(strcasecmp(input,"Help\n") == 0){
    system("clear");
    DisplayHelp();
  }
  else if(strcasecmp(input,"Stats\n") == 0){
    system("clear");
    printStats();
  }
  else if(strcasecmp(input,"Room\n") == 0){
    system("clear");
    printRoomInfo();
  }
  else if(strcasecmp(input,"Attack\n") == 0){
    battle();
  }
  else if(strcasecmp(input,"down forward low punch\n") == 0){
    printf("Hadoken \n");
    sleep(1);
    if(DRoom->roomClear)
      printf("A blue orb comes out of your hands and hits the wall\n");
    else
      printf("%s: ... \n", Enemy->name);
    sleep(1);
  }
  else if(strcasecmp(input,"Advance\n") == 0){
    if(!DRoom -> roomClear){
      printf("The room isn't clear yet!\n");
      sleep(1);
    }
    else{
      printf("You move into the next room\n");
      generateRoom();
    }
  }
  else if(!strcasecmp(input,"Save\n")){
    dump();
    printf("Game saved\n");
  }
    else if(!strcasecmp(input,"OSave\n")){
    dump();
    char buff[256];
    printf("Enter the ip adress of the save server\n");
    fgets(buff, sizeof(buff), stdin);
    OSave(2, buff);
  }
  else if(strcasecmp(input,"Inventory\n") == 0){
    if(Player->weaponNum == 0){
	printf("You have no weapons!\n");
	getchar();
    }
    else if(Player->weaponNum == 1){
	printf("Your weapons give you a +%d bonus to attack.\n",Player->slot1.attk);
	getchar();
    }
    else if(Player->weaponNum == 2){
      printf("Your weapons give you a +%d bonus to attack.\n",Player->slot1.attk + Player->slot2.attk);
      getchar();
    }
  }
  else if(strcasecmp(input,"Quit\n") == 0 || strcasecmp(input,"Exit\n") == 0){
    quit = 0;
  }
  else{
    printf("Sorry, I don't understand that\n");
    sleep(1);
    system("clear");
  }
}