public IEnumerator MoveAndConvertTo()
        {
            const int playerId   = 2;
            const int unitNumber = 0;

            Coordinate[] waypoints    = null;
            Coordinate   initialCoord = new Coordinate();
            VoxelData    voxel        = null;
            MapRoot      mapRoot      = null;

            yield return(TaskDefaultTest(playerId, (unitIndexInput, playerIndexInput) => TaskInfo.MoveAndConvertTo(unitIndexInput, playerIndexInput, waypoints[1], (int)KnownVoxelTypes.Ground), false,
                                         map =>
            {
                mapRoot = map;

                Coordinate[] coords = map.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);

                Debug.LogFormat("Unit {0} starting at {1}", unitNumber, coords[unitNumber]);

                initialCoord = coords[unitNumber];
                voxel = map.Get(initialCoord);
                waypoints = new[] { initialCoord, map.FindDataOfType((int)KnownVoxelTypes.Ground, playerId)[0] };
            },
                                         rootTaskInfo =>
            {
                Assert.IsFalse(voxel.IsAlive);

                Coordinate[] coords = mapRoot.FindDataOfType((int)KnownVoxelTypes.Ground, playerId);

                Assert.AreEqual(2, coords.Length);

                VoxelData zero = mapRoot.Get(coords[0]);
                VoxelData one = mapRoot.Get(coords[1]);

                Assert.IsTrue(one.Prev == zero || zero.Prev == one);
                if (one.Prev == zero)
                {
                    Assert.AreEqual(4, one.Height);
                    Assert.AreEqual(zero.Altitude + zero.Height, one.Altitude);
                }
                else
                {
                    Assert.AreEqual(4, zero.Height);
                    Assert.AreEqual(one.Altitude + one.Height, zero.Altitude);
                }
            },
                                         childTaskCompleted => { },
                                         unitNumber,
                                         TestEnv5));
        }
        public IEnumerator FindPathClientSidePreprocessingTest()
        {
            BeginTest(TestEnv0, 4, 0, () => {
                MapRoot map = Dependencies.Map.Map;
                IMatchEngineCli matchEngineCli = Dependencies.MatchEngine;

                const int playerId          = 3;
                Coordinate[] coords         = map.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);
                VoxelData data              = map.Get(coords[0]);
                Coordinate targetCoordinate = coords[0].Add(-1, -1);
                MovementCmd moveCmd         = new MovementCmd(CmdCode.Move, data.UnitOrAssetIndex, 0);
                moveCmd.Coordinates         = new[] { coords[0], targetCoordinate };

                MatchEngineCliEvent <long, CommandsBundle> eventHandler = null;
                eventHandler = (e, tick, commandsBundle) =>
                {
                    if (commandsBundle.TasksStateInfo != null)
                    {
                        TaskStateInfo taskStateInfo = commandsBundle.TasksStateInfo[0];
                        Assert.AreEqual(taskStateInfo.PlayerId, playerId);

                        if (taskStateInfo.State == TaskState.Completed)
                        {
                            matchEngineCli.ExecuteCommands -= eventHandler;

                            Coordinate[] newCoords = map.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);
                            Assert.AreEqual(targetCoordinate, newCoords[0]);

                            EndTest();
                        }
                        else
                        {
                            Assert.AreEqual(TaskState.Active, taskStateInfo.State);
                        }
                    }
                };
                matchEngineCli.ExecuteCommands += eventHandler;

                TaskInfo taskInfo = new TaskInfo(moveCmd);
                taskInfo.RequiresClientSidePreprocessing = true;
                matchEngineCli.GetClientTaskEngine(playerId).GenerateIdentitifers(taskInfo);
                matchEngineCli.Submit(playerId, new TaskCmd(SerializedTask.FromTaskInfo(taskInfo)));
            });

            yield return(Run());
        }
        public IEnumerator FindPathClientSideTaskTest()
        {
            BeginTest(TestEnv1, 2, 0, () =>
            {
                MapRoot map = Dependencies.Map.Map;
                IMatchEngineCli matchEngineCli = Dependencies.MatchEngine;

                const int playerId          = 1;
                Coordinate[] coords         = map.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);
                VoxelData data              = map.Get(coords[0]);
                Coordinate targetCoordinate = coords[0].Add(1, -1);
                MovementCmd moveCmd         = new MovementCmd(CmdCode.Move, data.UnitOrAssetIndex, 0);
                moveCmd.Coordinates         = new[] { coords[0], targetCoordinate };

                ITaskEngine taskEngine = matchEngineCli.GetClientTaskEngine(playerId);
                TaskEngineEvent <TaskInfo> taskStateChanged = null;
                taskStateChanged = taskStateInfo =>
                {
                    if (taskStateInfo.State == TaskState.Completed)
                    {
                        taskEngine.TaskStateChanged -= taskStateChanged;

                        Coordinate[] newCoords = map.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);
                        Assert.AreEqual(targetCoordinate, newCoords[0]);

                        EndTest();
                    }
                    else
                    {
                        Assert.AreEqual(TaskState.Active, taskStateInfo.State);
                    }
                };
                taskEngine.TaskStateChanged += taskStateChanged;

                TaskInfo taskInfo = new TaskInfo(moveCmd, playerId);
                taskInfo.RequiresClientSidePreprocessing = true;

                taskEngine.SubmitTask(taskInfo);
            });
            yield return(Run());
        }
        public IEnumerator GrowTest()
        {
            const int playerId   = 1;
            const int unitNumber = 0;

            Coordinate[] coordinates = new[]
            {
                new Coordinate(27, 32, 1, 2),
                new Coordinate(27, 33, 1, 2),
            };
            MapCell   cell    = null;
            VoxelData voxel   = null;
            MapRoot   mapRoot = null;

            yield return(TaskTest(playerId, (unitIndexInput, playerIndexInput) => HealMoveToCoordGrow(coordinates, unitIndexInput, playerIndexInput), false,
                                  map =>
            {
                mapRoot = map;
                Coordinate[] coords = map.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);
                Debug.LogFormat("Unit {0} starting at {1}", unitNumber, coords[unitNumber]);

                Coordinate coord = coords[unitNumber];
                voxel = map.Get(coord);
            },
                                  rootTaskInfo =>
            {
                VoxelData prev = voxel.Prev;

                Coordinate[] coords = mapRoot.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);
                Coordinate coord = coords[unitNumber];
                cell = mapRoot.Get(coord.Row, coord.Col, coord.Weight);
                Assert.IsNull(cell.GetDescendantsWithVoxelData(data => data != null));
                Assert.IsNotNull(prev);
                Assert.AreEqual((int)KnownVoxelTypes.Ground, prev.Type);
            },
                                  childTaskCompleted => { },
                                  unitNumber,
                                  Bug3Repro));
        }
        public IEnumerator TaskTest(
            int playerId,
            Func <TaskInputInfo, TaskInputInfo, TaskInfo> GetTestTaskInfo,
            bool shouldTaskBeFailed,
            Action <MapRoot> testStarted,
            Action <TaskInfo> rootTaskCompleted,
            Action <TaskInfo> childTaskCompleted = null,
            int unitNumber = 0,
            string testEnv = TestEnv2)
        {
            BeginTest(testEnv, 2, 0, () =>
            {
                MapRoot map = Dependencies.Map.Map;
                testStarted(map);

                IMatchEngineCli matchEngineCli = Dependencies.MatchEngine;
                Coordinate[] coords            = map.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);
                VoxelData voxel              = map.Get(coords[unitNumber]);
                TaskInfo unitIndexTask       = TaskInfo.UnitOrAssetIndex(voxel.UnitOrAssetIndex);
                TaskInfo playerIndexTask     = TaskInfo.EvalExpression(ExpressionInfo.PrimitiveVal(playerId));
                TaskInputInfo unitIndexInput = new TaskInputInfo
                {
                    OutputIndex = 0,
                    OutputTask  = unitIndexTask
                };
                TaskInputInfo playerIndexInput = new TaskInputInfo
                {
                    OutputIndex = 0,
                    OutputTask  = playerIndexTask
                };

                TaskInfo testTaskInfo = GetTestTaskInfo(unitIndexInput, playerIndexInput);
                TaskInfo rootTask     = TaskInfo.Procedure(
                    playerIndexTask,
                    unitIndexTask,
                    testTaskInfo,
                    TaskInfo.Return(ExpressionInfo.TaskStatus(testTaskInfo)));
                rootTask.SetParents();
                rootTask.Initialize(playerId);

                ITaskEngine taskEngine = matchEngineCli.GetClientTaskEngine(playerId);
                TaskEngineEvent <TaskInfo> taskStateChanged = null;
                taskStateChanged = taskInfo =>
                {
                    if (taskInfo.State == TaskState.Completed)
                    {
                        if (taskInfo.TaskId == rootTask.TaskId)
                        {
                            Assert.AreEqual(shouldTaskBeFailed, taskInfo.IsFailed, taskInfo.ToString());
                            taskEngine.TaskStateChanged -= taskStateChanged;
                            rootTaskCompleted(taskInfo);
                            EndTest();
                        }
                        else
                        {
                            if (childTaskCompleted != null)
                            {
                                childTaskCompleted(taskInfo);
                            }
                        }
                    }
                    else if (taskInfo.State != TaskState.Idle)
                    {
                        Assert.AreEqual(TaskState.Active, taskInfo.State, taskInfo.ToString());
                    }
                };
                taskEngine.TaskStateChanged += taskStateChanged;
                taskEngine.SubmitTask(rootTask);
            });


            yield return(Run());
        }
        private void CalculateBounds()
        {
            int weight = GameConstants.MinVoxelActorWeight;
            int size   = m_map.GetMapSizeWith(weight);

            Debug.Assert(size >= m_minMapBoundsSize, "map size < m_minMapBoundsSize");

            MapPos min = new MapPos(0, 0);
            MapPos max = new MapPos(size - 1, size - 1);

            MapCell col0 = m_map.Get(0, 0, weight);

            for (int row = 0; row < size; ++row)
            {
                MapCell cell     = col0;
                bool    nonEmpty = false;
                for (int col = 0; col < size; ++col)
                {
                    nonEmpty = IsNonEmpty(cell);
                    if (nonEmpty)
                    {
                        break;
                    }
                    cell = cell.SiblingPCol;
                }

                if (nonEmpty)
                {
                    min.Row = row;
                    break;
                }
                else
                {
                    min.Row = row;
                }

                col0 = col0.SiblingPRow;
            }

            col0 = m_map.Get(size - 1, 0, weight);
            for (int row = size - 1; row >= 0; --row)
            {
                MapCell cell     = col0;
                bool    nonEmpty = false;
                for (int col = 0; col < size; ++col)
                {
                    nonEmpty = IsNonEmpty(cell);
                    if (nonEmpty)
                    {
                        break;
                    }
                    cell = cell.SiblingPCol;
                }

                if (nonEmpty)
                {
                    max.Row = row;
                    break;
                }
                else
                {
                    max.Row = row;
                }

                col0 = col0.SiblingMRow;
            }

            MapCell row0 = m_map.Get(0, 0, weight);

            for (int col = 0; col < size; ++col)
            {
                MapCell cell     = row0;
                bool    nonEmpty = false;
                for (int row = 0; row < size; ++row)
                {
                    nonEmpty = IsNonEmpty(cell);
                    if (nonEmpty)
                    {
                        break;
                    }
                    cell = cell.SiblingPRow;
                }

                if (nonEmpty)
                {
                    min.Col = col;
                    break;
                }
                else
                {
                    min.Col = col;
                }

                row0 = row0.SiblingPCol;
            }

            row0 = m_map.Get(0, size - 1, weight);
            for (int col = size - 1; col >= 0; --col)
            {
                MapCell cell     = row0;
                bool    nonEmpty = false;
                for (int row = 0; row < size; ++row)
                {
                    nonEmpty = IsNonEmpty(cell);
                    if (nonEmpty)
                    {
                        break;
                    }
                    cell = cell.SiblingPRow;
                }

                if (nonEmpty)
                {
                    max.Col = col;
                    break;
                }
                else
                {
                    max.Col = col;
                }

                row0 = row0.SiblingMCol;
            }

            if (min.Col > max.Col)
            {
                min.Col = max.Col;
            }

            if (min.Row > max.Row)
            {
                min.Row = max.Row;
            }

            int centerCol = min.Col + (max.Col - min.Col) / 2;
            int centerRow = min.Row + (max.Row - min.Row) / 2;

            int minCol = Mathf.Max(0, centerCol - m_minMapBoundsSize / 2);
            int minRow = Mathf.Max(0, centerRow - m_minMapBoundsSize / 2);

            int maxCol = minCol + m_minMapBoundsSize;
            int maxRow = minRow + m_minMapBoundsSize;

            if (maxCol >= size)
            {
                maxCol = size - 1;
                minCol = maxCol - m_minMapBoundsSize;
            }

            if (maxRow >= size)
            {
                maxRow = size - 1;
                minRow = maxRow - m_minMapBoundsSize;
            }

            if (minCol < min.Col)
            {
                min.Col = minCol;
            }
            if (minRow < min.Row)
            {
                min.Row = minRow;
            }
            if (maxCol > max.Col)
            {
                max.Col = maxCol;
            }
            if (maxRow > max.Row)
            {
                max.Row = maxRow;
            }


            m_mapBounds = new MapRect(min, max);
        }
        public IEnumerator SearchForFoodTaskTest(int playerId, Action <ITaskEngine, TaskInfo, TaskInfo, Coordinate[]> callback)
        {
            BeginTest(TestEnv1, 2, 0, () =>
            {
                MapRoot map = Dependencies.Map.Map;
                IMatchEngineCli matchEngineCli = Dependencies.MatchEngine;

                Coordinate[] coords = map.FindDataOfType((int)KnownVoxelTypes.Eater, playerId);
                VoxelData voxel     = map.Get(coords[0]);

                TaskInfo searchForFoodTask = new TaskInfo(TaskType.SearchForFood)
                {
                    OutputsCount = 2
                };
                TaskInputInfo searchForFoodContext = new TaskInputInfo
                {
                    OutputIndex = 0,
                    OutputTask  = searchForFoodTask,
                };

                TaskInfo getUnitIndexTask = new TaskInfo(TaskType.EvalExpression)
                {
                    Expression   = ExpressionInfo.PrimitiveVal(voxel.UnitOrAssetIndex),
                    OutputsCount = 1
                };
                TaskInputInfo unitIndex = new TaskInputInfo
                {
                    OutputIndex = 0,
                    OutputTask  = getUnitIndexTask
                };

                searchForFoodTask.Inputs = new[] { searchForFoodContext, unitIndex };
                TaskInfo rootTask        = new TaskInfo(TaskType.Sequence)
                {
                    Children = new[] { getUnitIndexTask, searchForFoodTask }
                };

                rootTask.SetParents();
                rootTask.Initialize(playerId);

                ITaskEngine taskEngine = matchEngineCli.GetClientTaskEngine(playerId);
                TaskEngineEvent <TaskInfo> taskStateChanged = null;
                taskStateChanged = taskInfo =>
                {
                    if (taskInfo.State == TaskState.Completed)
                    {
                        if (taskInfo.TaskId == searchForFoodTask.TaskId)
                        {
                            callback(taskEngine, taskInfo, searchForFoodTask, coords);
                        }
                        else if (taskInfo.TaskId == rootTask.TaskId)
                        {
                            taskEngine.TaskStateChanged -= taskStateChanged;

                            EndTest();
                        }
                    }
                    else
                    {
                        Assert.AreEqual(TaskState.Active, taskInfo.State);
                    }
                };
                taskEngine.TaskStateChanged += taskStateChanged;
                taskEngine.SubmitTask(rootTask);
            });

            yield return(Run());
        }