Skip to content
Snippets Groups Projects
Strategy.cpp 3.43 KiB
Newer Older
  • Learn to ignore specific revisions
  • Franck Dary's avatar
    Franck Dary committed
    #include "Strategy.hpp"
    
    Franck Dary's avatar
    Franck Dary committed
    Strategy::Strategy(std::vector<std::string> definition)
    
    Franck Dary's avatar
    Franck Dary committed
      std::regex blockRegex("(?:(?:\\s|\\t)*)Block(?:(?:\\s|\\t)*):(?:(?:\\s|\\t)*)End\\{(.*)\\}(?:(?:\\s|\\t)*)");
    
    Franck Dary's avatar
    Franck Dary committed
      for (auto & line : definition)
        if (!util::doIfNameMatch(blockRegex, line, [this](auto sm)
          {
            blocks.emplace_back(util::split(sm.str(1), ' '));
          }))
    
    Franck Dary's avatar
    Franck Dary committed
        {
    
    Franck Dary's avatar
    Franck Dary committed
          if (blocks.empty())
            util::myThrow(fmt::format("invalid line '{}', expeced 'Block : End{}'",line,"{...}"));
          blocks.back().addMovement(line);
    
    Franck Dary's avatar
    Franck Dary committed
        }
    
    
    Franck Dary's avatar
    Franck Dary committed
      if (blocks.empty())
        util::myThrow("empty strategy");
      for (auto & block : blocks)
        if (block.empty())
          util::myThrow("there is an empty block");
    
    Franck Dary's avatar
    Franck Dary committed
    Strategy::Movement Strategy::getMovement(const Config & c, const std::string & transition)
    
    Franck Dary's avatar
    Franck Dary committed
    {
    
    Franck Dary's avatar
    Franck Dary committed
      auto movement = blocks[currentBlock].getMovement(c, transition);
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
      if (blocks[currentBlock].isFinished(c, movement))
    
    Franck Dary's avatar
    Franck Dary committed
      {
    
    Franck Dary's avatar
    Franck Dary committed
        currentBlock++;
        if (currentBlock >= blocks.size())
          return endMovement;
        movement.first = blocks[currentBlock].getInitialState();
        movement.second = -c.getWordIndex();
    
    Franck Dary's avatar
    Franck Dary committed
      return movement;
    
    Franck Dary's avatar
    Franck Dary committed
    }
    
    
    Franck Dary's avatar
    Franck Dary committed
    Strategy::Movement Strategy::Block::getMovement(const Config & c, const std::string & transition)
    
    Franck Dary's avatar
    Franck Dary committed
    {
    
    Franck Dary's avatar
    Franck Dary committed
      std::string transitionPrefix(util::split(transition, ' ')[0]);
      auto currentState = c.getState();
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
      for (auto & movement : movements)
    
    Franck Dary's avatar
    Franck Dary committed
        auto fromState = std::get<0>(movement);
        auto toState = std::get<1>(movement);
        auto trans = std::get<2>(movement);
        auto mov = std::get<3>(movement);
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
        if (fromState == currentState and (trans == transitionPrefix or trans == "*"))
          return std::make_pair(toState, mov);
      }
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
      util::myThrow(fmt::format("no movement found for state '{}' and transitionPrefix '{}'", currentState, transitionPrefix));
    
    Franck Dary's avatar
    Franck Dary committed
      return endMovement;
    }
    
    
    Franck Dary's avatar
    Franck Dary committed
    const std::string Strategy::getInitialState() const
    
    Franck Dary's avatar
    Franck Dary committed
      return blocks.at(0).getInitialState();
    }
    
    Franck Dary's avatar
    Franck Dary committed
    void Strategy::reset()
    {
      currentBlock = 0;
    }
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
    Strategy::Block::Block(std::vector<std::string> endConditionsStr)
    {
      for (auto & cond : endConditionsStr)
        endConditions.emplace_back(str2condition(cond));
    }
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
    void Strategy::Block::addMovement(std::string definition)
    {
      std::regex regex("(?:(?:\\s|\\t)*)(\\S+)(?:(?:\\s|\\t)+)(\\S+)(?:(?:\\s|\\t)+)(\\S+)(?:(?:\\s|\\t)+)(\\S+)(?:(?:\\s|\\t)*)");
      auto errorMessage = fmt::format("invalid definition '{}' expected fromState toState transitionNamePrefix wordIndexMovement", definition);
    
    Franck Dary's avatar
    Franck Dary committed
      if (!util::doIfNameMatch(regex, definition, [this, &errorMessage](auto sm)
        {
          try
          {
            movements.emplace_back(std::make_tuple(sm.str(1), sm.str(2), sm.str(3), std::stoi(sm.str(4))));
          } catch (std::exception & e) {util::myThrow(fmt::format("caught '{}' in {}", e.what(), errorMessage));}
        }))
        util::myThrow(errorMessage);
    }
    
    Franck Dary's avatar
    Franck Dary committed
    Strategy::Block::EndCondition Strategy::Block::str2condition(const std::string & s)
    {
      if (s == "cannotMove")
        return EndCondition::CannotMove;
      else
        util::myThrow(fmt::format("invalid EndCondition '{}'", s));
    
    Franck Dary's avatar
    Franck Dary committed
      return EndCondition::CannotMove;
    }
    
    Franck Dary's avatar
    Franck Dary committed
    const std::string Strategy::Block::getInitialState() const
    {
      return std::get<0>(movements.at(0));
    
    Franck Dary's avatar
    Franck Dary committed
    bool Strategy::Block::empty()
    
    Franck Dary's avatar
    Franck Dary committed
      return movements.empty();
    
    Franck Dary's avatar
    Franck Dary committed
    bool Strategy::Block::isFinished(const Config & c, const Movement & movement)
    
    Franck Dary's avatar
    Franck Dary committed
      for (auto & condition : endConditions)
        if (condition == EndCondition::CannotMove)
        {
          if (c.canMoveWordIndex(movement.second))
            return false;
        }
    
      return true;