/// <summary>
        ///     Initializes a new instance of the <see cref="GameController" /> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="maze">The maze.</param>
        /// <param name="model">The model.</param>
        public GameController(string name, Maze maze, MazeModel model)
        {
            _directions = new Dictionary <string, Direction>
            {
                { Direction.Up.ToString(), Direction.Up },
                { Direction.Down.ToString(), Direction.Down },
                { Direction.Right.ToString(), Direction.Right },
                { Direction.Left.ToString(), Direction.Left }
            };

            _players   = new List <TcpClient>();
            _positions = new List <Position>();
            _moves     = new ConcurrentQueue <Move>();
            _changes   = new ConcurrentQueue <Move>();

            _name  = name;
            _model = model;

            Maze     = maze;
            Commands = new Dictionary <string, ICommand>
            {
                { "play", new Play(this) },
                { "close", new Close(model) }
            };
            _isPlayer2Connected = false;
            _gameFinished       = false;
            _lastReaderIndex    = -1;
        }
Exemplo n.º 2
0
        public void Given_MazeCoordinatorExecutor_When_Executing_Then_Maze_Is_Solved()
        {
            var mazeInput = "path/to/maze";
            var mazeStr   = @"____G__X
                            ___XXX__
                            X______X
                            __XXXX__
                            ___X____
                            __S__X__";

            var maze = new MazeModel();

            _mazeSourceMock.Setup(x => x.GetMaze(mazeInput))
            .Returns(mazeStr);

            _mazeTransformerMock.Setup(x => x.Execute(mazeStr))
            .Returns(maze);

            var expectedSolution = new Solution();

            _mazePathfinderAlgorithmExecutorMock.Setup(x => x.Execute(maze))
            .Returns(expectedSolution);

            var actualSolution = _executor.Execute(mazeInput);

            Assert.That(actualSolution, Is.EqualTo(expectedSolution));
        }
Exemplo n.º 3
0
        public static void Apply(MazeModel mazeData)
        {
            foreach (NodeVO deadEnd in mazeData.deadEnds)
            {
                NodeVO node         = deadEnd;
                int    currentScore = DifficultyModel.Instance().minScore;
                int    ds           = 1;

                while (node != null && node.score == 0)
                {
                    currentScore += ds;
                    node.score    = currentScore;
                    //define score delta
                    if (node.score <= DifficultyModel.Instance().minScore)
                    {
                        ds = 1;
                    }

                    if (node.score >= DifficultyModel.Instance().maxScore)
                    {
                        ds = -1;
                    }

                    node = node.previousNode;
                }
            }
        }
        public IActionResult Index()
        {
            var model = new MazeModel()
            {
                Size = 75
            };

            return(View(model));
        }
Exemplo n.º 5
0
        /// <summary>
        ///     Main.
        /// </summary>
        /// <param name="args">The arguments for the main.</param>
        private static void Main(string[] args)
        {
            IModel         model      = new MazeModel();
            IController    controller = new ServerController(model);
            IClientHandler ch         = new ClientHandler(controller);
            Server         server     = new Server(ch);

            server.Start();
            server.Stop();
        }
Exemplo n.º 6
0
        private void OnNodeReached()
        {
            var cellPosition = PlayerModel.Instance().cellPosition;
            int index        = cellPosition.x * MazeModel.Instance().size + cellPosition.y;

            if (index < _nodeInstances.Count)
            {
                _nodeInstances [index].GetComponent <NodeMediator> ().onReached();
            }
        }
Exemplo n.º 7
0
        public void CreateMazeCharactersTest()
        {
            var controller = new MazeController();

            foreach (var mazeId in mazeIds)
            {
                MazeModel model = controller.CreateMazeCharacters(mazeId);
                Assert.True(model.GameState.StateResult == StateResult.SuccesfullyCreated);
            }
        }
Exemplo n.º 8
0
        override public PrefromResult Perform(float delta)
        {
            var game = GameModel.Instance();

            game.state = GameModel.STATE_INITED;
            game.timeBonus.SetValue(DifficultyModel.Instance().maxTimeBonus, DifficultyModel.Instance().minTimeBonus, DifficultyModel.Instance().bonusTime);
            game.movesLeft.SetValue(MazeModel.Instance().deadEnds [0].GetDistance() * 2);

            MazePaceNotifications.GAME_UPDATED.Dispatch();

            return(PrefromResult.COMPLETED);
        }
Exemplo n.º 9
0
        public async Task <HttpResponseMessage> Post([FromBody] MazePostModel mazeModel)
        {
            if (string.IsNullOrWhiteSpace(mazeModel.mazeString))
            {
                return(Request.CreateResponse(HttpStatusCode.BadRequest));
            }

            var theseus = new MazeModel(mazeModel.mazeString);

            var solutionModel = theseus.SolveMaze();

            return(Request.CreateResponse(HttpStatusCode.OK, solutionModel));
        }
Exemplo n.º 10
0
 public IActionResult GetMaze(int size)
 {
     try
     {
         var maze = new MazeModel(size);
         maze.GenerateMaze();
         var model = _mapper.Map <MazeViewModel>(maze);
         return(Ok(model));
     }
     catch (Exception ex)
     {
         return(BadRequest(ex.Message));
     }
 }
Exemplo n.º 11
0
    void Start()
    {
        float       wallLenght    = cell.GetComponent <CellConstruct>().wallLenght;
        BoxCollider finishTrigger = this.GetComponent <BoxCollider>();

        finishTrigger.enabled   = true;
        finishTrigger.isTrigger = true;
        finishTrigger.size      = new Vector3(wallLenght, wallLenght, wallLenght);


        MazeModel mazeComponent = maze.GetComponent <MazeModel>();

        this.transform.position = new Vector3((mazeComponent.row - 1) * wallLenght, 0f, (mazeComponent.column - 1) * wallLenght);
    }
Exemplo n.º 12
0
        static void PrintMaze(MazeModel maze)
        {
            var size = maze.Size;

            // print the north border first
            for (int i = 0; i < size; i++)
            {
                if (maze.GetCellAtIndex(i).North.IsClosed)
                {
                    Console.Write("+----");
                }
                else
                {
                    Console.Write("+    ");
                }
            }
            Console.WriteLine("+");

            // print the interior walls
            for (int i = 0; i < size * size; i += size) // rows
            {
                for (int j = i; j < i + size; ++j)      // Prints the west wall
                {
                    if (maze.GetCellAtIndex(j).West.IsClosed)
                    {
                        Console.Write("|    ");
                    }
                    else
                    {
                        Console.Write("     ");
                    }
                }
                Console.WriteLine("|");            // Right most border

                for (int j = i; j < i + size; ++j) // Prints the south wall
                {
                    if (maze.GetCellAtIndex(j).South.IsClosed)
                    {
                        Console.Write("+----");
                    }
                    else
                    {
                        Console.Write("+    ");
                    }
                }
                Console.WriteLine("+"); // Right most border
            }
        }
Exemplo n.º 13
0
		override public PrefromResult Perform (float delta)
		{
			var player = PlayerModel.Instance ();
			IntPointVO pos = player.cellPosition;
			int directionIdx = player.directionIdx;
			NodeVO node = MazeModel.Instance ().GetNode (pos.x, pos.y);
			GameModel game = GameModel.Instance ();

			game.AddScore ((int)((float)node.score * game.timeBonus));
			node.score = 0;

			game.movesLeft.Dec (1);

			if (game.state == GameModel.STATE_INITED || game.state == GameModel.STATE_STUCK) {
				game.state = GameModel.STATE_MOVING;	
				game.score.Freeze();
				game.timeBonus.Freeze();
			}

			if (node.HasFlag (NodeVO.SPECIALS_EXIT)) {
				game.state = GameModel.STATE_ENDED;
				MazePaceNotifications.EXIT_REACHED.Dispatch ();
			} else {
				if (node.HasFlag (NodeVO.SPECIALS_HIDE_WALLS)) {
					MazePaceNotifications.TOGGLE_WALLS_VISIBILITY.Dispatch (false);
				}
				if (node.HasFlag (NodeVO.SPECIALS_SHOW_WALLS)) {
					MazePaceNotifications.TOGGLE_WALLS_VISIBILITY.Dispatch (true);
				}
				bool shouldRotate = node.HasWall (directionIdx) || player.moved;
				if (node.HasFlag (NodeVO.SPECIALS_ROTATOR_CW | NodeVO.SPECIALS_ROTATOR_CCW) && shouldRotate) {
					MazePaceNotifications.ROTATE_AT_NODE.Dispatch (node);
					player.moved = false;
				} else if (!node.HasWall (directionIdx)) {
					player.cellPosition.x += NodeVO.DIRECTIONS [player.directionIdx, 0];
					player.cellPosition.y += NodeVO.DIRECTIONS [player.directionIdx, 1];
					player.moved = true;
					MazePaceNotifications.PROCEED_FROM_NODE.Dispatch (node);
				} else {
					game.state = GameModel.STATE_STUCK;
					game.score.SetValue (game.score, 0, DifficultyModel.Instance ().scoreDrainTime);
					MazePaceNotifications.PLAYER_STUCK.Dispatch ();
				}
			}

			MazePaceNotifications.GAME_UPDATED.Dispatch ();
			return PrefromResult.COMPLETED;
		}
Exemplo n.º 14
0
        public override PrefromResult Perform(float delta)
        {
            var difficultyModel = DifficultyModel.Instance();
            var cellPosition    = PlayerModel.Instance().cellPosition;

            MazeModel.Instance().Recreate(difficultyModel.size, cellPosition.x, cellPosition.y);
            ExitDecorator.Apply(MazeModel.Instance());
            ScoreDecorator.Apply(MazeModel.Instance());
            HiderDecorator.Apply(MazeModel.Instance());
            SpeedUpDecorator.Apply(MazeModel.Instance());
            RotatorDecorator.Apply(MazeModel.Instance());

            MazePaceNotifications.MAZE_RECREATED.Dispatch();

            return(PrefromResult.COMPLETED);
        }
Exemplo n.º 15
0
        static void Main(string[] args)
        {
            // TODO: Read N x N size in as an input
            var size = 15;
            var maze = new MazeModel(size);

            Console.WriteLine();
            Console.WriteLine();
            maze.GenerateMaze();
            PrintMaze(maze);

            var solver = MazeSolverFactory.CreateMazeSolver(MazeSolverType.BFS);

            var solution = solver.SolveMaze(maze);

            PrintSolution(maze, solution);
        }
Exemplo n.º 16
0
    public void SetMazeActive()
    {
        int row    = Int32.Parse(rowNum.text);
        int column = Int32.Parse(columnNum.text);

        MazeModel maze = Maze.GetComponent <MazeModel>();

        maze.row    = row;
        maze.column = column;

        Vector3 cameraPosition = new Vector3(row / 2, (row + column) * 3 / 4, column / 2);

        Camera.transform.position = cameraPosition;

        StartMenu.SetActive(false);
        Maze.SetActive(true);
    }
Exemplo n.º 17
0
 public static void Apply(MazeModel mazeData)
 {
     for (int i = 0; i < mazeData.deadEnds.Count; i++)
     {
         var deadEnd = mazeData.deadEnds [i];
         var isExit  = i == 0;
         if (isExit)
         {
             deadEnd.AddFlag(NodeVO.SPECIALS_EXIT);
             SetDirectionsTowards(deadEnd);
         }
         else
         {
             SetDirectionsFrom(deadEnd);
         }
     }
 }
Exemplo n.º 18
0
        public static void Apply(MazeModel mazeData)
        {
            if (DifficultyModel.Instance().hidersCount == 0)
            {
                return;
            }

            for (int i = 0; i < mazeData.deadEnds.Count; i++)
            {
                if (i >= DifficultyModel.Instance().hidersCount)
                {
                    break;
                }

                int distance = (int)mazeData.deadEnds [i].GetDistance();

                if (distance < 4)
                {
                    return;
                }

                int showIndex = _rnd.Next((int)distance / 4, (int)distance / 2);
                int hideIndex = _rnd.Next(showIndex + 2, showIndex + (int)Math.Min((int)(distance / 2), 8));

                NodeVO node  = mazeData.deadEnds [i].previousNode;
                int    index = 0;
                while (node != null)
                {
                    index++;

                    if (index == showIndex)
                    {
                        node.AddFlag(NodeVO.SPECIALS_SHOW_WALLS);
                    }


                    if (index == hideIndex)
                    {
                        node.AddFlag(NodeVO.SPECIALS_HIDE_WALLS);
                    }

                    node = node.previousNode;
                }
            }
        }
Exemplo n.º 19
0
        private void PopulateIndexModelFromMaze(IndexModel model, MazeModel maze)
        {
            model.Difficulty = maze.Difficulty;
            model.Height     = maze.Size[0];
            model.Width      = maze.Size[1];
            model.Walls      = maze.Data;
            model.Pony       = maze.Pony[0];
            model.Domokun    = maze.Domokun[0];
            model.EndPoint   = maze.EndPoint[0];

            model.Messages = new List <string>();
            model.Messages.Add(maze.GameState.StateResult);

            if (!string.IsNullOrEmpty(maze.GameState.HiddenUrl))
            {
                model.Prize = $"{BaseWebsite}/{maze.GameState.HiddenUrl}";
            }
        }
Exemplo n.º 20
0
        private static void PrintSolution(MazeModel maze, SortedDictionary <int, int> solution)
        {
            int start = 0;
            var hash  = new HashSet <int>();

            hash.Add(start);

            int cell = maze.MaxIndex;

            while (cell != start)
            {
                hash.Add(cell);
                cell = solution[cell];
            }

            // Display the ascii repesentation of the maze
            PrintMaze(maze, hash);
        }
Exemplo n.º 21
0
        private void OnExitReached()
        {
            var maze = MazeModel.Instance();

            for (int i = 0; i < _nodeInstances.Count; i++)
            {
                int        value    = Random.Range(0, 3);
                GameObject node     = _nodeInstances [i];
                var        position = node.transform.position;
                if (Random.Range(0, 2) == 1)
                {
                    node.transform.DOLocalMoveX((Random.Range(0, 2) == 1 ? value + maze.size : -(value + 1)) * DifficultyModel.NODE_SIZE, TRANSITION_TIME);
                }
                else
                {
                    node.transform.DOLocalMoveY((Random.Range(0, 2) == 1 ? value + maze.size : -(value + 1)) * DifficultyModel.NODE_SIZE, TRANSITION_TIME);
                }
            }
        }
Exemplo n.º 22
0
 /// <summary>
 /// generating maze
 /// </summary>
 /// <param name="name"></param>
 /// <param name="cols"></param>
 /// <param name="rows"></param>
 /// <returns></returns>
 public IHttpActionResult GetMaze(string name, int cols, int rows)
 {
     try
     {
         Maze      maze      = model.GenerateMaze(name, rows, cols);
         JObject   jmaze     = JObject.Parse(maze.ToJSON());
         MazeModel mazeModel = new MazeModel();
         mazeModel.Name       = name;
         mazeModel.Cols       = cols;
         mazeModel.Rows       = rows;
         mazeModel.StartCol   = maze.InitialPos.Col;
         mazeModel.StartRow   = maze.InitialPos.Row;
         mazeModel.ExitCol    = maze.GoalPos.Col;
         mazeModel.ExitRow    = maze.GoalPos.Row;
         mazeModel.MazeString = jmaze.GetValue("Maze").ToString();
         return(Ok(mazeModel));
     } catch
     {
         return(InternalServerError());
     }
 }
Exemplo n.º 23
0
 public QuitCommand(IModel model)
 {
     this.model = model as MazeModel;
 }
Exemplo n.º 24
0
        void UpdateCorrectDirection()
        {
            IntPointVO cell         = PlayerModel.Instance().cellPosition;
            var        currentNode  = MazeModel.Instance().GetNode(cell.x, cell.y);
            int        newDirection = currentNode.directionToExit;

            if (currentNode.HasFlag(NodeVO.SPECIALS_ROTATOR_CW))
            {
                newDirection--;
                if (newDirection < 0)
                {
                    newDirection = 3;
                }
            }

            if (currentNode.HasFlag(NodeVO.SPECIALS_ROTATOR_CCW))
            {
                newDirection++;
                if (newDirection > 3)
                {
                    newDirection = 0;
                }
            }

            if (_correctDirection == newDirection)
            {
                return;
            }

            _correctDirection = newDirection;
            UpdateVisibility();

            DOTween.Kill(_handTransform);

            Vector2 start = new Vector2(0, -Camera.main.orthographicSize * 0.5f);
            Vector2 stop  = new Vector2(0, -Camera.main.orthographicSize * 0.5f);

            switch (_correctDirection)
            {
            case (NodeVO.DIRECTION_UP_IDX):
                start.y -= 25.0f;
                stop.y  += 25.0f;
                break;

            case (NodeVO.DIRECTION_RIGHT_IDX):
                start.x -= 25.0f;
                stop.x  += 25.0f;
                break;

            case (NodeVO.DIRECTION_DOWN_IDX):
                start.y += 25.0f;
                stop.y  -= 25.0f;
                break;

            case (NodeVO.DIRECTION_LEFT_IDX):
                start.x += 25.0f;
                stop.x  -= 25.0f;
                break;
            }

            _handTransform.position = start;
            _handTransform.DOMove(stop, 0.5f).SetLoops(-1).SetEase(Ease.InOutCubic);
        }
Exemplo n.º 25
0
 private void Awake()
 {
     GameData  = new GameData();
     MazeModel = new MazeModel(new MazeData());
 }
Exemplo n.º 26
0
        public static void Apply(MazeModel mazeData)
        {
            if (DifficultyModel.Instance().rotatorsCount == 0)
            {
                return;
            }

            List <NodeVO> candidates = new List <NodeVO> ();

            foreach (NodeVO node in mazeData.crossRoads)
            {
                //make sure there are no special flags yet
                if (node.HasFlag(
                        NodeVO.SPECIALS_SPEEDUP_UP |
                        NodeVO.SPECIALS_SPEEDUP_RIGHT |
                        NodeVO.SPECIALS_SPEEDUP_DOWN |
                        NodeVO.SPECIALS_SPEEDUP_LEFT |
                        NodeVO.SPECIALS_HIDE_WALLS |
                        NodeVO.SPECIALS_SHOW_WALLS))
                {
                    continue;
                }

                //make sure its not the start node
                if (node.previousNode == null)
                {
                    continue;
                }

                candidates.Add(node);
            }

            Shuffle(candidates);
            for (int i = 0; i < candidates.Count; i++)
            {
                if (i >= DifficultyModel.Instance().rotatorsCount)
                {
                    break;
                }

                uint type = 0;

                //entering direction to this node
                int prevDirection = candidates [i].previousNode.GetDirectionTowards(candidates [i]);

                //calculate the delta direction towards exit
                int delta = candidates [i].directionToExit - prevDirection;
                if (delta > 2)
                {
                    delta -= 4;
                }
                if (delta < -2)
                {
                    delta += 4;
                }

                if (delta == -1)
                {
                    type = NodeVO.SPECIALS_ROTATOR_CCW;
                }
                else if (delta == 1)
                {
                    type = NodeVO.SPECIALS_ROTATOR_CW;
                }

                candidates [i].AddFlag(type);
            }
        }
Exemplo n.º 27
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="maze"></param>
        /// <returns></returns>
        public SortedDictionary <int, int> SolveMaze(MazeModel maze)
        {
            var queue       = new Queue <int>();
            var vistedRooms = new HashSet <int>();
            var solution    = new SortedDictionary <int, int>();

            var goalIndex = maze.MaxIndex;
            var startIndex = 0;
            int row, col, nextRow, nextCol, nextCell;

            queue.Enqueue(startIndex);
            vistedRooms.Add(startIndex);

            while (queue.Count >= 0)
            {
                var cell = queue.Dequeue();
                if (cell == goalIndex)
                {
                    break;
                }

                row = cell / maze.Size;
                col = cell % maze.Size;

                // Check North
                nextRow = row - 1;
                nextCol = col;
                if (nextRow >= 0)
                {
                    if (maze.GetCellAtIndex(cell).North.IsOpen)
                    {
                        nextCell = nextRow * maze.Size + nextCol;
                        if (!vistedRooms.Contains(nextCell))
                        {
                            queue.Enqueue(nextCell);
                            vistedRooms.Add(nextCell);
                            solution.Add(nextCell, cell);
                        }
                    }
                }

                // Check South
                nextRow = row + 1;
                nextCol = col;
                if (nextRow < maze.Size)
                {
                    if (maze.GetCellAtIndex(cell).South.IsOpen)
                    {
                        nextCell = nextRow * maze.Size + nextCol;
                        if (!vistedRooms.Contains(nextCell))
                        {
                            queue.Enqueue(nextCell);
                            vistedRooms.Add(nextCell);
                            solution.Add(nextCell, cell);
                        }
                    }
                }

                //check east
                nextRow = row;
                nextCol = col + 1;
                if (nextCol < maze.Size)
                {
                    if (maze.GetCellAtIndex(cell).East.IsOpen)
                    {
                        nextCell = nextRow * maze.Size + nextCol;
                        if (!vistedRooms.Contains(nextCell))
                        {
                            queue.Enqueue(nextCell);
                            vistedRooms.Add(nextCell);
                            solution.Add(nextCell, cell);
                        }
                    }
                }

                // check west
                nextRow = row;
                nextCol = col - 1;
                if (nextCol >= 0)
                {
                    if (maze.GetCellAtIndex(cell).West.IsOpen)
                    {
                        nextCell = nextRow * maze.Size + nextCol;
                        if (!vistedRooms.Contains(nextCell))
                        {
                            queue.Enqueue(nextCell);
                            vistedRooms.Add(nextCell);
                            solution.Add(nextCell, cell);
                        }
                    }
                }
            }

            return(solution);
        }
Exemplo n.º 28
0
 public MazeController(MazeModel model)
 {
     Model = model;
 }
Exemplo n.º 29
0
        static void PrintMaze(MazeModel maze, HashSet <int> hash)
        {
            var size = maze.Size;

            // print the north border first
            Console.WriteLine("\n\n");

            for (int i = 0; i < size; i++)
            {
                if (maze.GetCellAtIndex(i).North.IsClosed)
                {
                    Console.Write("+----");
                }
                else
                {
                    Console.Write("+    ");
                }
            }
            Console.WriteLine("+");

            var actualIndex = 0;

            // print the interior walls
            for (int i = 0; i < size * size; i += size) // rows
            {
                for (int j = i; j < i + size; ++j)      // Prints the west wall
                {
                    Console.ResetColor();
                    var index = i + j;
                    if (maze.GetCellAtIndex(j).West.IsClosed&& hash.Contains(actualIndex))
                    {
                        Console.Write("| ");
                        Console.ForegroundColor = System.ConsoleColor.Red;
                        Console.Write("X  ");
                    }
                    else if (maze.GetCellAtIndex(j).West.IsClosed&& !hash.Contains(actualIndex))
                    {
                        Console.Write("|    ");
                    }
                    else
                    {
                        if (hash.Contains(actualIndex))
                        {
                            Console.Write("  ");
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.Write("X  ");
                        }
                        else
                        {
                            Console.Write("     ");
                        }
                    }

                    actualIndex++;
                }
                Console.ResetColor();
                Console.WriteLine("|");            // Right most border

                for (int j = i; j < i + size; ++j) // Prints the south wall
                {
                    if (maze.GetCellAtIndex(j).South.IsClosed)
                    {
                        Console.Write("+----");
                    }
                    else
                    {
                        Console.Write("+    ");
                    }
                }
                Console.WriteLine("+"); // Right most border
            }
        }
Exemplo n.º 30
0
        public static void Apply(MazeModel mazeData)
        {
            if (DifficultyModel.Instance().speedUpsCount == 0)
            {
                return;
            }

            List <SpeedUpChain> chains = new List <SpeedUpChain> ();

            foreach (NodeVO deadEnd in mazeData.deadEnds)
            {
                NodeVO       node             = deadEnd;
                int          currentDirection = -1;
                SpeedUpChain currentChain     = new SpeedUpChain();

                do
                {
                    NodeVO previousNode = node.previousNode;

                    bool nodeHasSpeedUp = false;
                    foreach (SpeedUpChain chain in chains)
                    {
                        if (chain.nodes.Contains(node))
                        {
                            nodeHasSpeedUp = true;
                            break;
                        }
                    }

                    if (nodeHasSpeedUp)                     //branch reached a point of another branch that has already been processed
                    {
                        break;
                    }

                    if (previousNode != null)
                    {
                        currentChain.nodes.Add(node);

                        bool hasSpecial = previousNode.HasFlag(
                            NodeVO.SPECIALS_ROTATOR_CW |
                            NodeVO.SPECIALS_ROTATOR_CCW |
                            NodeVO.SPECIALS_HIDE_WALLS |
                            NodeVO.SPECIALS_SHOW_WALLS);

                        int direction = previousNode.GetDirectionTowards(node);

                        if ((currentDirection != direction) || hasSpecial)
                        {
                            if (currentChain != null && currentChain.nodes.Count > 1)
                            {
                                chains.Add(currentChain);
                            }

                            currentChain           = new SpeedUpChain();
                            currentChain.direction = direction;
                        }

                        currentDirection = hasSpecial ? -1 : direction;
                    }
                    node = previousNode;
                } while (node != null);
            }

            chains.Sort();

            for (int i = 0; i < chains.Count; i++)
            {
                if (i >= DifficultyModel.Instance().speedUpsCount)
                {
                    break;
                }

                //mark nodes to contain according speedup flags
                foreach (NodeVO nodeData in chains[i].nodes)
                {
                    switch (chains [i].direction)
                    {
                    case (NodeVO.DIRECTION_UP_IDX):
                        nodeData.AddFlag(NodeVO.SPECIALS_SPEEDUP_UP);
                        break;

                    case (NodeVO.DIRECTION_RIGHT_IDX):
                        nodeData.AddFlag(NodeVO.SPECIALS_SPEEDUP_RIGHT);
                        break;

                    case (NodeVO.DIRECTION_DOWN_IDX):
                        nodeData.AddFlag(NodeVO.SPECIALS_SPEEDUP_DOWN);
                        break;

                    case (NodeVO.DIRECTION_LEFT_IDX):
                        nodeData.AddFlag(NodeVO.SPECIALS_SPEEDUP_LEFT);
                        break;
                    }
                }
            }
        }