//------------------------------------------------------------------------------
        //
        //------------------------------------------------------------------------------
        public Errno findPath(int roleTypeId, 
                              Vec2<sbyte> roleSizeInGrids,
                              Vec2<short> startPos, 
                              Vec2<short> endPos, 
                              IList<AStarNode> path)
        {
            Errno err = Errno.OK;

            if (roleSizeInGrids.x <= 0 || roleSizeInGrids.y <= 0
                    || startPos.x < 0 || startPos.x >= _mapSize.x || startPos.y < 0 || startPos.y >= _mapSize.y
                    || endPos.x < 0 || endPos.x >= _mapSize.x || endPos.y < 0 || endPos.y >= _mapSize.y
                    || path == null)
                err = Errno.InvalidArg;

            AStarNode node = null;
            if (err == Errno.OK)
            {
                _roleTypeId = roleTypeId;
                _roleSize.assign(roleSizeInGrids);
                _endPos.assign(endPos);

                path.Clear();

                //node = new AStarNode(new Vec2<short>(startPos), _map[startPos.y, startPos.x]);
                node = new AStarNode(new Vec2<short>(startPos));
                node.tileId = _map[startPos.y, startPos.x];
                node.speed = _speedConfig.onGetMoveSpeed(this, _roleTypeId, node.tileId);

                if (Utils.floatCompare(node.speed, 0) <= 0)
                    err = Errno.General;

                Debug.Assert(err == Errno.OK);
            }

            if (err == Errno.OK)
            {
                _openList.Add(getKey(node), node);
                err = doFindPath();
            }

            _closeList.Clear();

            if (err == Errno.OK)
                node = getNodeFromList(getKey(_endPos), _openList);

            _openList.Clear();

            if (err == Errno.OK)
                generatePath(node, path);

            return err;
        }
        void moveToNextGrid()
        {
            //if (soldier.index < soldier.paths.Count)
            if (soldier.paths.Count > 0)
            {
                _nextNode = soldier.paths[0];
                soldier.paths.RemoveAt(0);

                soldier.x = _nextNode.pos.x;
                soldier.y = _nextNode.pos.y;

                if (soldier.paths.Count > 0)
                {
                    _nextPos.x = _nextNode.pos.x * map.nodeW + map.nodeW / 2.0F;
                    _nextPos.z = _nextNode.pos.y * map.nodeH + map.nodeH / 2.0F;
                    //transform.FindChild("Player").LookAt(_nextGridPos);

                    _direct = _nextPos - transform.position;
                    _direct = _direct * 10000.0F + _nextPos;
                }
                else
                {
                    _nextPos.x = soldier._target.x;
                    _nextPos.z = soldier._target.y;
                }
            }
            else
            {
                _nextNode = null;

                //Debug.Log("soldier.paths.Count == 0");
                canRotate = false;
                _isMoving = false;
                animator.SetBool(runningHash, false);
                soldier.paths = null;
                _nextPos = Vector3.zero;
                playAttackSound();
            }
        }
        //------------------------------------------------------------------------------
        //
        //------------------------------------------------------------------------------
        private void generatePath(AStarNode node, IList<AStarNode> path)
        {
            int n = 0;

            path.Clear();

            AStarNode node1 = node;
            while (node1 != null)
            {
                path.Add(node);
                node1 = node1.previousNode;
                ++n;
            }

            //--n;
            node1 = node;
            while (node1 != null /*&& n > 0*/)
            {
                path[--n] = node1;
                node1 = node1.previousNode;
            }
        }
        private void fillBorderSpeeds(AStarNode curNode, int rowNum, int colNum, float[,] speeds)
        {
            Vec2<short> curPos = curNode.pos;
            int row, col;

            for (row = 0; row < rowNum; ++row)
                for (col = 0; col < colNum; ++col)
                {
                    if (row != 0 && row != (rowNum - 1) && col != 0 && col != (colNum - 1))
                        speeds[row, col] = -1;
                    else
                        speeds[row, col] = 0;
                }

            bool isSkip = false;
            Vec2<short> pos = new Vec2<short>();
            int i, j;

            for (row = 0; row < rowNum; ++row)
                for (col = 0; col < colNum; ++col)
                {
                    isSkip = Utils.floatCompare(speeds[row, col], 0) < 0;

                    if (!isSkip)
                    {
                        pos.x = (short)(curPos.x + col - 1);
                        pos.y = (short)(curPos.y + row - 1);

                        if (pos.x < 0 || pos.x >= _mapSize.x)
                        {
                            for (i = 0; i < rowNum; ++i)
                                speeds[i, col] = -1;

                            isSkip = true;
                        }
                    }

                    if (!isSkip && (pos.y < 0 || pos.y >= _mapSize.y))
                    {
                        for (j = 0; j < colNum; ++j)
                            speeds[row, j] = -1;

                        isSkip = true;
                    }

                    if (!isSkip)
                    {
                        speeds[row, col] = _speedConfig.onGetMoveSpeed(
                                this,
                                _roleTypeId,
                                (short)_map[pos.y, pos.x]);

                        if (Utils.floatCompare(speeds[row, col], 0) <= 0)
                        {
                            isSkip = true;

                            if (row != 0 && row != (rowNum - 1))
                            {
                                for (i = 0; i < rowNum; ++i)
                                    speeds[i, col] = -1;
                            }
                            else if (col != 0 && col != (colNum - 1))
                            {
                                for (j = 0; j < colNum; ++j)
                                    speeds[row, j] = -1;
                            }
                        }
                    }
                }  // for
        }
        private void convertBorderSpeedsToNeighbor(
                float[,] borderSpeeds, int rowNum, int colNum, AStarNode curNode, 
                float[,] neighborSpeeds)
        {
            Vec2<short> curPos = curNode.pos;
            int row, col;

            for (row = 0; row < 3; ++row)
                for (col = 0; col < 3; ++col)
                    neighborSpeeds[row, col] = 0;

            neighborSpeeds[1, 1] = -1;

            bool isSkip = false;
            Vec2<short> pos = new Vec2<short>();
            int key;
            float speed;
            int i, j;

            for (row = 0; row < 3; ++row)
                for (col = 0; col < 3; ++col)
                {
                    isSkip = Utils.floatCompare(neighborSpeeds[row, col], 0) < 0;

                    if (!isSkip)
                    {
                        pos.x = (short)(curPos.x + col - 1);
                        pos.y = (short)(curPos.y + row - 1);

                        key = getKey(pos);
                        if (getNodeFromList(key, _closeList) != null)
                        {
                            neighborSpeeds[row, col] = -1;
                            isSkip = true;

                            if (row == 1)
                            {
                                neighborSpeeds[0, col] = -1;
                                neighborSpeeds[2, col] = -1;
                            }
                            else if (col == 1)
                            {
                                neighborSpeeds[row, 0] = -1;
                                neighborSpeeds[row, 2] = -1;
                            }
                        }
                    }

                    if (!isSkip)
                    {
                        speed = 0;

                        if ((row == 0 || row == 2) && (col == 0 || col == 2))
                        {
                            i = (row == 0 ? 0 : rowNum - 1);
                            j = (col == 0 ? 0 : colNum - 1);
                            speed = borderSpeeds[i, j];
                        }
                        else if (row == 0 || row == 2)
                        {
                            i = (row == 0 ? 0 : rowNum - 1);
                            for (j = 1; j < colNum - 1; ++j)
                                speed += borderSpeeds[i, j];

                            speed /= (float)(colNum - 2);
                        }
                        else //if (col == 0 || col == 2)
                        {
                            j = (col == 0 ? 0 : colNum - 1);
                            for (i = 1; i < rowNum - 1; ++i)
                                speed += borderSpeeds[i, j];

                            speed /= (float)(rowNum - 2);
                        }

                        neighborSpeeds[row, col] = speed;
                    }
                }
        }
        private void addNeighborsToOpenList(float[,] neighborSpeeds, AStarNode curNode)
        {
            int row, col;
            float speed, costG;
            Vec2<short> curPos = curNode.pos;
            Vec2<short> pos = new Vec2<short>();
            int key;
            AStarNode node = null;

            for (row = 0; row < 3; ++row)
                for (col = 0; col < 3; ++col)
                {
                    speed = neighborSpeeds[row, col];

                    if (Utils.floatCompare(speed, 0) <= 0)
                        continue;

                    if (row == 1 || col == 1)
                        costG = 10000.0F / speed;
                    else
                        costG = 14142.135623730950488016887242097F / speed;

                    costG += curNode.costG;

                    pos.x = (short)(curPos.x + col - 1);
                    pos.y = (short)(curPos.y + row - 1);

                    key = getKey(pos);
                    node = getNodeFromList(key, _openList);

                    if (node == null)
                    {
                        node = new AStarNode(new Vec2<short>(pos));
                        node.tileId = _map[pos.y, pos.x];
                        node.speed = speed;
                        node.costH = _hCostEstimator.onEvaluateHCost(this, pos, _endPos);
                        node.costG = costG;
                        node.previousNode = curNode;

                        _openList.Add(key, node);
                    }
                    else if (costG < node.costG)
                    {
                        node.costG = costG;
                        node.previousNode = curNode;
                    }
                }  // for
        }
 //------------------------------------------------------------------------------
 //
 //------------------------------------------------------------------------------
 private static int getKey(AStarNode node)
 {
     return getKey(node.pos);
 }