diff --git a/reading_machine/include/Config.hpp b/reading_machine/include/Config.hpp
index 464286f2ca3370381bc068fee911a889e038959a..697418c0f75a671b99f6123dfe4540f8a3ed0775 100644
--- a/reading_machine/include/Config.hpp
+++ b/reading_machine/include/Config.hpp
@@ -93,6 +93,7 @@ class Config
   bool hasStack(int relativeIndex) const;
   String getState() const;
   void setState(const std::string state);
+  bool stateIsDone() const;
 
 };
 
diff --git a/reading_machine/include/Strategy.hpp b/reading_machine/include/Strategy.hpp
index 60dbfa90d424d42dd866c33f02a7a40435826d75..e1bc580c2dadc42d896c2c4156c6c7a8248cb274 100644
--- a/reading_machine/include/Strategy.hpp
+++ b/reading_machine/include/Strategy.hpp
@@ -5,6 +5,10 @@
 
 class Strategy
 {
+  public :
+
+  static inline std::pair<std::string, int> endMovement{"", 0};
+
   private :
 
   enum Type
@@ -15,6 +19,13 @@ class Strategy
 
   Type type;
   std::map<std::pair<std::string, std::string>, std::string> edges;
+  std::map<std::string, bool> isDone;
+  std::vector<std::string> defaultCycle;
+
+  private :
+
+  std::pair<std::string, int> getMovementSequential(const Config & c, const std::string & transition);
+  std::pair<std::string, int> getMovementIncremental(const Config & c, const std::string & transition);
 
   public :
 
diff --git a/reading_machine/src/Config.cpp b/reading_machine/src/Config.cpp
index 919ab2517da772a56539b3a3d8a22cae802f62ef..a8d8134ac62d4a0b75a159b6df9094941311c6fe 100644
--- a/reading_machine/src/Config.cpp
+++ b/reading_machine/src/Config.cpp
@@ -340,3 +340,11 @@ void Config::setState(const std::string state)
   this->state = state;
 }
 
+bool Config::stateIsDone() const
+{
+  if (!rawInput.empty())
+    return rawInputOnlySeparatorsLeft();
+
+  return !has(0, wordIndex+1, 0);
+}
+
diff --git a/reading_machine/src/Strategy.cpp b/reading_machine/src/Strategy.cpp
index 2d5e9ae9af696cfc936dbcb5c19d46ed5961c213..afb1e3fc97408280589871f8d7dae6dbdc4b343b 100644
--- a/reading_machine/src/Strategy.cpp
+++ b/reading_machine/src/Strategy.cpp
@@ -9,28 +9,97 @@ Strategy::Strategy(const std::vector<std::string_view> & lines)
   for (unsigned int i = 1; i < lines.size(); i++)
   {
     auto splited = util::split(lines[i], ' ');
+    std::pair<std::string, std::string> key;
+    std::string value;
+
     if (splited.size() == 2)
-      edges[std::pair<std::string,std::string>(splited[0], "")] = splited[1];
+    {
+      key = std::pair<std::string,std::string>(splited[0], "");
+      value = splited[1];
+      defaultCycle.emplace_back(value);
+    }
     else if (splited.size() == 3)
-      edges[std::pair<std::string,std::string>(splited[0], splited[1])] = splited[2];
+    {
+      key = std::pair<std::string,std::string>(splited[0], splited[1]);
+      value = splited[1];
+    }
     else
       util::myThrow(fmt::format("Invalid strategy line '{}'", lines[i]));
+
+    if (edges.count(key))
+      util::myThrow(fmt::format("Edge {} {} defined twice", key.first, key.second));
+    edges[key] = value;
+    isDone[key.first] = false;
   }
+
+  if (edges.empty())
+    util::myThrow("Strategy is empty");
+  defaultCycle.pop_back();
+  std::reverse(defaultCycle.begin(), defaultCycle.end());
+
+  for (auto & s : defaultCycle)
+    fmt::print("{}\n", s);
 }
 
 std::pair<std::string, int> Strategy::getMovement(const Config & c, const std::string & transition)
+{
+  if (c.stateIsDone())
+    isDone[c.getState()] = true;
+
+  while (defaultCycle.size() && isDone[defaultCycle.back()])
+    defaultCycle.pop_back();
+
+  if (type == Type::Sequential)
+    return getMovementSequential(c, transition);
+
+  return getMovementIncremental(c, transition);
+}
+
+std::pair<std::string, int> Strategy::getMovementSequential(const Config & c, const std::string & transition)
+{
+  auto foundSpecific = edges.find(std::make_pair(c.getState(), transition));
+  auto foundGeneric = edges.find(std::make_pair(c.getState(), ""));
+
+  std::string target;
+
+  if (foundSpecific != edges.end())
+    target = foundSpecific->second;
+  else if (foundGeneric != edges.end())
+    target = foundGeneric->second;
+
+  if (target.empty())
+    util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition));
+
+  if (!c.stateIsDone())
+    return {c.getState(), (c.getState() == target) && edges.size() > 1 ? 0 : 1};
+
+  if (!isDone[target])
+    return {target, -c.getWordIndex()};
+
+  return endMovement;
+}
+
+std::pair<std::string, int> Strategy::getMovementIncremental(const Config & c, const std::string & transition)
 {
   auto foundSpecific = edges.find(std::make_pair(c.getState(), transition));
   auto foundGeneric = edges.find(std::make_pair(c.getState(), ""));
 
+  std::string target;
+
   if (foundSpecific != edges.end())
-    return {foundSpecific->second, 1};
+    target = foundSpecific->second;
+  else if (foundGeneric != edges.end())
+    target = foundGeneric->second;
+
+  if (target.empty())
+    util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition));
 
-  if (foundGeneric != edges.end())
-    return {foundGeneric->second, 1};
+  if (!isDone[target])
+    return {target, target == defaultCycle.back() ? 1 : 0};
 
-  util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition));
+  if (defaultCycle.empty())
+    return endMovement;
 
-  return {"", 0};
+  return {defaultCycle.back(), 1};
 }