diff --git a/README.md b/README.md
index 8133a429575c5d52c9e3b8c9d6adf30997b9a400..c69ff3fe1c9ddeb8c432241bf66b718affda1faf 100644
--- a/README.md
+++ b/README.md
@@ -190,9 +190,9 @@ The code for the Boost board game application is organized as follows:
 
 # Footrace Puzzle Generator Design
 
-Within the project `@unlsoft/boost-puzzles` is a generator for footrace puzzles, `generateFootracePuzzles.js`. This is used to generate puzzle in which the user is racing the AI to the opposite side of the board and is based on dynamic programming through it's main function, `findStartingSituationAndFastestMoveSequence`. In this case dynamic is programming is necessary because the solution follows a directed acyclic graph (DAG). Greedy algorithm design would not work with this particular generator because if we take the best (in this case farthest move) we may miss a move sequence that will take us farther in fewer moves and lose the race.
+Within the project `@unlsoft/boost-puzzles` is a generator for footrace puzzles, `generateFootracePuzzles.js`. This is used to generate puzzle in which the user is racing the AI to the opposite side of the board and is based on dynamic programming through it's main function, `findStartingSituationAndFastestMoveSequence`. In this case dynamic is programming is necessary because the solution follows a directed acyclic graph (DAG). Greedy algorithm design would not work with this particular generator because if we take the best move (in this case farthest move) we may miss a move sequence that will take us farther in fewer moves and lose the race.
 
-The generator uses two games. One is used in the dynamic programming algorithm and the other is the lane that the player will use in their race. This is done to reduce our search space since the algorithm needs to only worry about the lane that the AI will be racing on. The vertices for the DAG represent how many steps are needed to reach the goal. Steps are equivalient to board points. For example, an unboosted piece can only move one step and a singly boosted piece can move two steps. The generator determines these vertices by taking into account all possible situations and the amount of steps needed to achieve those situations. The edges for the DAG represent the moves taken to get to those situations. The generator determines these edges by taking the fewest moves possible to reach a vertex.
+The generator uses two games. One is used in the dynamic programming algorithm and the other is the lane that the player will use in their race. This is done to reduce our search space and speed up the generation of the puzzles since the algorithm needs to only worry about the lane that the AI will be racing on. The vertices for the DAG are all the various situations that the board could be in. The generator determines these vertices through its `Situation` class. These vertices are then sorted into topological order through the `topologically` function. The topological order of these vertices are from first left to right then bottom to top (Example: `[(0, 1), (1, 1), (0, 2)]`). The edges for the DAG represent the moves taken to get to those situations. The generator determines these edges by taking the fewest moves possible to reach a vertex.
 
 # Generating `Game` Objects with `boost-game`
 
diff --git a/boost-app/src/tutorials/footrace.js b/boost-app/src/tutorials/footrace.js
index c66c5ded3672d4eadc0c9abaa5db16c49241fb9e..0a259e757b69d43f831089516eb613ad3a9b3d2c 100644
--- a/boost-app/src/tutorials/footrace.js
+++ b/boost-app/src/tutorials/footrace.js
@@ -1,4 +1,4 @@
-/* eslint-disable max-len */
+/* eslint-disable no-magic-numbers */
 
 import React from 'react';
 
@@ -21,17 +21,15 @@ function isSuccessful(game, encoding) {
 export const FOOTRACE_TUTORIAL = {
   title: 'Tutorial: Footrace',
   gameIdentifier: 'boost-12-14-2-8-2-demo',
-  successMessage: (
+  successMessage:
     <p>
       You win! Tap the "next" button to continue or the "previous" button to
       review previous moves.
-    </p>
-  ),
-  failureMessage: (
+    </p>,
+  failureMessage:
     <p>
       You lose! Tap the "previous" button to rewind your moves and try again.
-    </p>
-  ),
+    </p>,
   pages: [
     {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
@@ -45,11 +43,11 @@ export const FOOTRACE_TUTORIAL = {
           'l2l3',
           'l3k4',
           'k4j6',
-          'j6j9',
-          'j9j10',
-          'j10j11',
-          'j11i12',
-          'i12i14',
+          'j6k8',
+          'k8k9',
+          'k9k11',
+          'k11k12',
+          'k12k14',
         ],
       ],
       done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * 9,
@@ -68,9 +66,9 @@ export const FOOTRACE_TUTORIAL = {
           'k4k6',
           'k6k7',
           'k7k9',
-          'k9j10',
-          'j10i11',
-          'i11i12',
+          'k9l10',
+          'l10k11',
+          'k11i12',
           'i12i14',
         ],
       ],
@@ -80,20 +78,21 @@ export const FOOTRACE_TUTORIAL = {
     {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
       treeName: 'puzzle 2',
-      rootPosition: '0;1/0/0,2048/0/2050170099319551267225582119965919576064',
+      rootPosition:
+        '0;1/0/0,2048/0/11507187246694903440616897131005246879723188224',
       moves: [
         undefined,
         [
-          'l1l2',
-          'l2l3',
-          'l3l4',
-          'l4l5',
-          'l5k6',
-          'k6k8',
-          'k8i9',
-          'i9i11',
-          'i11i13',
-          'i13i14',
+          'l1j1',
+          'j1i2',
+          'i2i4',
+          'i4j5',
+          'j5j7',
+          'j7j8',
+          'j8k9',
+          'k9k11',
+          'k11k13',
+          'k13l14',
         ],
       ],
       done: (game, encoding) =>
@@ -104,43 +103,65 @@ export const FOOTRACE_TUTORIAL = {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
       treeName: 'puzzle 3',
       rootPosition:
-        '0;1/0/0,2048/0/51581627732242356946020196381670558673591644160',
+        '0;1/0/0,2048/0/57201413483900801113121729762249414128492904448',
       moves: [
         undefined,
-        ['l1j1', 'j1j2', 'j2j5', 'j5j7', 'j7j8', 'j8j11', 'j11j13', 'j13i14'],
+        [
+          'l1l2',
+          'l2k3',
+          'k3k5',
+          'k5i6',
+          'i6i8',
+          'i8j9',
+          'j9k10',
+          'k10l11',
+          'l11k12',
+          'k12k14',
+        ],
       ],
-      done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * 8,
+      done: (game, encoding) =>
+        encoding !== undefined && encoding.ply >= 2 * 10,
       successful: isSuccessful,
     },
     {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
       treeName: 'puzzle 4',
       rootPosition:
-        '0;1/0/0,2048/0/28786140552272944960061483921793904047562973184',
+        '0;1/0/0,2048/0/18179245835384575624873324492777302119178240',
       moves: [
         undefined,
-        ['l1l2', 'l2l4', 'l4k5', 'k5k7', 'k7k9', 'k9j11', 'j11j12', 'j12i14'],
+        [
+          'l1l2',
+          'l2k3',
+          'k3k5',
+          'k5l6',
+          'l6k7',
+          'k7k9',
+          'k9k11',
+          'k11j12',
+          'j12k14',
+        ],
       ],
-      done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * 8,
+      done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * 9,
       successful: isSuccessful,
     },
     {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
       treeName: 'puzzle 5',
       rootPosition:
-        '0;1/0/0,2048/0/34387749447136084679612586608550874213127307264',
+        '0;1/0/0,2048/0/5887400820453110114042174348582801936132087808',
       moves: [
         undefined,
         [
-          'l1l2',
-          'l2k3',
-          'k3k5',
-          'k5k7',
-          'k7k8',
-          'k8j9',
-          'j9j11',
-          'j11i12',
-          'i12i14',
+          'l1k1',
+          'k1j2',
+          'j2j4',
+          'j4j7',
+          'j7k8',
+          'k8j10',
+          'j10j11',
+          'j11j13',
+          'j13k14',
         ],
       ],
       done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * 9,
@@ -150,32 +171,42 @@ export const FOOTRACE_TUTORIAL = {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
       treeName: 'puzzle 6',
       rootPosition:
-        '0;1/0/0,2048/0/13965188838842973896148906485912890813464576',
+        '0;1/0/0,2048/0/5586076085985609888201517988148032929050624',
       moves: [
         undefined,
-        ['l1l2', 'l2k3', 'k3k6', 'k6k8', 'k8i9', 'i9i10', 'i10i12', 'i12i14'],
+        [
+          'l1j1',
+          'j1j2',
+          'j2j5',
+          'j5j6',
+          'j6i8',
+          'i8j9',
+          'j9j11',
+          'j11j12',
+          'j12j14',
+        ],
       ],
-      done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * 8,
+      done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * 9,
       successful: isSuccessful,
     },
     {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
       treeName: 'puzzle 7',
       rootPosition:
-        '0;1/0/0,2048/0/22891723114397983295943612568662210956502269952',
+        '0;1/0/0,2048/0/18179246335730357748118938819075017950629888',
       moves: [
         undefined,
         [
-          'l1l2',
-          'l2l3',
-          'l3l4',
-          'l4k5',
-          'k5j6',
-          'j6j7',
-          'j7j9',
-          'j9j12',
-          'j12j13',
-          'j13i14',
+          'l1k2',
+          'k2i3',
+          'i3i5',
+          'i5j6',
+          'j6k7',
+          'k7k8',
+          'k8j9',
+          'j9i11',
+          'i11j12',
+          'j12k14',
         ],
       ],
       done: (game, encoding) =>
@@ -186,43 +217,45 @@ export const FOOTRACE_TUTORIAL = {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
       treeName: 'puzzle 8',
       rootPosition:
-        '0;1/0/0,2048/0/5586075335658634150240222331234293606551552',
+        '0;1/0/0,2048/0/5887401505670000632844727971923076094949896192',
       moves: [
         undefined,
         [
-          'l1k2',
-          'k2k4',
-          'k4i5',
-          'i5i7',
-          'i7i9',
-          'i9i11',
-          'i11i12',
-          'i12i13',
-          'i13i14',
+          'l1j1',
+          'j1j2',
+          'j2j5',
+          'j5k6',
+          'k6j7',
+          'j7j9',
+          'j9i10',
+          'i10i12',
+          'i12j13',
+          'j13k14',
         ],
       ],
-      done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * 9,
+      done: (game, encoding) =>
+        encoding !== undefined && encoding.ply >= 2 * 10,
       successful: isSuccessful,
     },
     {
       caption: <p>Beat your opponent to the north edge of the board.</p>,
       treeName: 'puzzle 9',
       rootPosition:
-        '0;1/0/0,2048/0/5586075835944113695925751026669024079519744',
+        '0;1/0/0,2048/0/34387753869392015550955487667270925732013948928',
       moves: [
         undefined,
         [
           'l1l2',
-          'l2k3',
-          'k3i4',
-          'i4i6',
-          'i6i7',
-          'i7i8',
-          'i8i9',
-          'i9i10',
-          'i10i12',
+          'l2l3',
+          'l3j3',
+          'j3j5',
+          'j5j7',
+          'j7k8',
+          'k8k9',
+          'k9j10',
+          'j10i12',
           'i12i13',
-          'i13i14',
+          'i13j14',
         ],
       ],
       done: (game, encoding) =>
@@ -231,12 +264,11 @@ export const FOOTRACE_TUTORIAL = {
     },
 
     {
-      caption: (
+      caption:
         <p>
           Congratulations! You have completed all of the footrace puzzles! Tap
           the "menu" button to return to the main menu.
-        </p>
-      ),
+        </p>,
       rootPosition: '0;0/0/0,0/0/0',
       treeName: 'congratuations',
     },
diff --git a/boost-puzzles/src/generateFootracePuzzles.js b/boost-puzzles/src/generateFootracePuzzles.js
index 2e825952120ee5646d2b9cc64b96d4345e06c36a..2fdb23f866b9ac4edc32a270f2e9835590cb1e18 100755
--- a/boost-puzzles/src/generateFootracePuzzles.js
+++ b/boost-puzzles/src/generateFootracePuzzles.js
@@ -3,7 +3,7 @@
 import ONE_LANE_GAME from './games/oneLaneFootrace.js';
 import TWO_LANE_GAME from './games/twoLaneFootrace.js';
 
-function* getPoints() {
+function*getPoints() {
   for (let x = 0; x < ONE_LANE_GAME.boardWidth; ++x) {
     for (let y = 0; y < ONE_LANE_GAME.boardHeight; ++y) {
       yield [x, y];
@@ -58,7 +58,7 @@ class Situation {
   }
 }
 
-function* getSituations(position) {
+function*getSituations(position) {
   for (const point of getPoints(position)) {
     if (isEmptyAt(position, ...point)) {
       yield new Situation(position, ...point);
@@ -96,7 +96,6 @@ class BackpointersTable {
         return element[1];
       }
     }
-    console.log('no vertex found');
     return undefined;
   }
 
@@ -106,16 +105,25 @@ class BackpointersTable {
 }
 
 function topologically(firstSituation, secondSituation) {
-  // TODO: design a proper topological order
-  if (firstSituation.x !== secondSituation.x) {
-    return firstSituation.x - secondSituation.x;
+  if (
+    (firstSituation.x < secondSituation.x &&
+      firstSituation.y === secondSituation.y) ||
+    firstSituation.y < secondSituation.y
+  ) {
+    return -1;
+  }
+  if (
+    firstSituation.y === secondSituation.y &&
+    firstSituation.x === secondSituation.x
+  ) {
+    return 0;
   }
-  return firstSituation.y - secondSituation.y;
+  return 1;
 }
 
 const MAXIMUM_POSSIBLE_STEPS_PER_MOVE = 3;
 
-function* getPredecessorsAndMoves(position, situation) {
+function*getPredecessorsAndMoves(position, situation) {
   const lowestPossibleY = Math.max(
     situation.y - MAXIMUM_POSSIBLE_STEPS_PER_MOVE,
     0,
@@ -152,29 +160,18 @@ function selectBetterBackpointer(first, second) {
 }
 
 function chooseBackpointer(position, situation, backpointersTable) {
-  // TODO: clean up debugging code
-  console.debug(`Choosing a backpointer for ${situation}:`);
   let best = new Backpointer(undefined, undefined, Infinity);
   for (const [predecessor, move] of getPredecessorsAndMoves(
     position,
     situation,
   )) {
-    console.debug(
-      `  Considering a backpointer to ${predecessor} via the move ${move}.`,
-    );
     const candidate = new Backpointer(
       predecessor,
       move,
       backpointersTable.get(predecessor).totalMoves + 1,
     );
-    console.debug(`  Candidate backpointer: ${candidate}.`);
     best = selectBetterBackpointer(best, candidate);
-    if (candidate === best) {
-      console.debug('    This candidate is the best so far.');
-    }
   }
-  console.debug(`Best backpointer: ${best}.`);
-  console.debug();
   return best;
 }
 
@@ -190,17 +187,16 @@ function findStartingSituationAndFastestMoveSequence(position) {
     );
   }
   let best = undefined;
-  let results = [];
+  const results = [];
   for (let x = 0; x < ONE_LANE_GAME.boardWidth; ++x) {
-    results = [];
     const candidate = backpointersTable.get(
       new Situation(position, x, ONE_LANE_GAME.boardHeight - 1),
     );
     best = selectBetterBackpointer(best, candidate);
-    while (best !== undefined && best.move !== undefined) {
-      results.push(best.move);
-      best = backpointersTable.get(best.predecessor);
-    }
+  }
+  while (best !== undefined && best.move !== undefined) {
+    results.push(best.move);
+    best = backpointersTable.get(best.predecessor);
   }
   return [startingSituation, results.reverse()];
 }
@@ -215,8 +211,6 @@ function maybeModifiedWithTowerAt(position, x, y) {
     (isOpenFromTheSouthAt(position, x - 1, y) ||
       isOpenFromTheSouthAt(position, x + 1, y))
   ) {
-    // TODO: clean up debugging code
-    console.debug(`Placing tower at (${x}, ${y}).`);
     return position.modified(x, y, 1, ONE_LANE_GAME.tower);
   }
   return position;
@@ -226,7 +220,7 @@ const SEED_COEFFICIENT = 15;
 const BROWNIAN_PARAMETER = 0x100;
 
 // Generate a predictable pattern of points that still makes the puzzles look haphazard.
-function* brownian(seed) {
+function*brownian(seed) {
   let i = SEED_COEFFICIENT * seed;
   let x = Math.floor(((Math.sin(i) + 1) / 2) * ONE_LANE_GAME.boardWidth);
   let y = 1;
@@ -250,13 +244,9 @@ function getCandidatePosition(seed) {
   const edgeX = ONE_LANE_GAME.boardWidth - 1;
   for (let y = 0; y < ONE_LANE_GAME.boardHeight; ++y) {
     if (!isEmptyAt(result, edgeX, y - 1) && !isEmptyAt(result, edgeX - 1, y)) {
-      // TODO: clean up debugging code
-      console.debug(`Placing tower at (${edgeX}, ${y}).`);
       result = result.modified(edgeX, y, 1, ONE_LANE_GAME.tower);
     }
   }
-  // TODO: clean up debugging code
-  console.debug();
   return result;
 }
 
@@ -298,7 +288,7 @@ function convertToTwoLanes(position, start, moves) {
   return [doubledPosition, moves.map(mirrorMove)];
 }
 
-function* composePuzzles() {
+function*composePuzzles() {
   for (let seed = 0; ; ++seed) {
     const position = getCandidatePosition(seed);
     const [start, moves] = findStartingSituationAndFastestMoveSequence(
@@ -310,7 +300,7 @@ function* composePuzzles() {
   }
 }
 
-function* take(generator, count) {
+function*take(generator, count) {
   if (count > 0) {
     let remaining = count;
     for (const element of generator) {
@@ -338,8 +328,8 @@ function formatAsPage([position, moves], index) {
         [${moves.map(quote).join(', ')}],
       ],
       done: (game, encoding) => encoding !== undefined && encoding.ply >= 2 * ${
-        moves.length
-      },
+  moves.length
+},
       successful: isSuccessful,
     },
 `.substring(1);
@@ -348,7 +338,7 @@ function formatAsPage([position, moves], index) {
 function formatAsTutorial(puzzles) {
   /* eslint-disable max-len */
   return `
-/* eslint-disable max-len */
+/* eslint-disable no-magic-numbers */
 
 import React from 'react';